diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..adbbad58152b50165f2ea70ad2d62d9dbb7281a2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,133 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +.idea/ + +*.ipynb_checkpoints/ \ No newline at end of file diff --git a/app/Disc Golf Simulator.py b/app/Disc Golf Simulator.py new file mode 100644 index 0000000000000000000000000000000000000000..0bb06a0efa79c64421854f2a00ef7016336f58a2 --- /dev/null +++ b/app/Disc Golf Simulator.py @@ -0,0 +1,117 @@ +from logging import getLogger +from pathlib import Path +proj_dir = Path(__file__).parents[1] +import sys +sys.path.append(str(proj_dir)) + +import numpy as np +import streamlit as st + +from shotshaper.projectile import DiscGolfDisc +from visualize import get_plot, get_stl, get_subplots, visualize_disc + + +# Define the default values +default_U = 24.2 +default_omega = 116.8 +default_z0 = 1.3 +default_pitch = 15.5 +default_nose = 0.0 +default_roll = 14.7 + + +def main(): + tab1, tab2 = st.tabs(['Simulator', 'FAQ']) + with tab1: + disc_names = { + 'Innova Wraith': 'dd2', + 'Innova Firebird': 'cd1', + 'Innova Roadrunner': 'cd5', + 'Innova Fairway Driver': 'fd2', + } + disc_selected = st.sidebar.selectbox("Disc Selection", disc_names.keys()) + disc_name = disc_names[disc_selected] + + # Create the sliders with the default values + U = st.sidebar.slider("Throwing Velocity (m/s)", min_value=0.0, max_value=40.0, value=default_U, step=0.1, + help='Fastest Throw on record is ~40m/s by Simon Lizotte') + omega = st.sidebar.slider("Omega", min_value=0.0, max_value=200.0, value=default_omega, step=0.1) + z0 = st.sidebar.slider("Release Height (m)", min_value=0.0, max_value=2.0, value=default_z0, step=0.1) + pitch = st.sidebar.slider("Pitch Angle (deg) | Release angle", min_value=0.0, max_value=90.0, value=default_pitch, + step=0.1) + nose = st.sidebar.slider("Nose Angle (deg) | Up/Down", min_value=0.0, max_value=90.0, value=default_nose, + step=0.1) + roll = st.sidebar.slider("Roll Angle (deg) | Tilt Left/Right", min_value=-90.0, max_value=90.0, value=default_roll, + step=0.1) + + pos = np.array((0, 0, default_z0)) + disc_dict = DiscGolfDisc(disc_name) + + stl_mesh = get_stl(proj_dir / 'shotshaper' / 'discs' / (disc_name + '.stl')) + fig = visualize_disc(stl_mesh, nose=nose, roll=roll) + + st.markdown("""## Disc orientation""") + st.plotly_chart(fig) + st.markdown("""## Flight Path""") + shot = disc_dict.shoot(speed=U, omega=omega, pitch=pitch, + position=pos, nose_angle=nose, roll_angle=roll) + + # Plot trajectory + x, y, z = shot.position + x_new, y_new = -1 * y, x + + # Reversed x and y to mimic a throw + fig = get_plot(x_new, y_new, z) + st.plotly_chart(fig, True) + + st.markdown( + f""" + **Arrows in Blue** show you where your *s-turn* is. + + **Arrows in Red** show you your *max height* and *lateral deviance*. + + Hit Play to watch your animated throw. + + | Metric | Value | + |--------------|--------| + | Drift Left | {round(min(x_new), 2)} | + | Drift Right | {round(max(x_new), 2)} | + | Max Height | {round(max(z), 2)} | + | Distance | {round(max(y_new), 2)} | + + """ + ) + + arc, alphas, betas, lifts, drags, moms, rolls = disc_dict.post_process(shot, omega) + fig = get_subplots(arc, alphas, lifts, drags, moms, rolls, shot.velocity) + st.plotly_chart(fig, True) + + with tab2: + st.markdown(""" + # Motivation + I saw some great work by [kegiljarhus](https://github.com/kegiljarhus) [repo](https://github.com/kegiljarhus/shotshaper) + and wanted to make this available as an app so people could learn more about disc golf. I really want to commend + the amazing idea of writing a [scientific article](https://link.springer.com/article/10.1007/s12283-022-00390-5) + AND releasing code, and actually executing it well. This is what gets people excited about STEM. + + I originally saw this + [reddit post](https://www.reddit.com/r/discgolf/comments/yyhbcj/wrote_a_scientific_article_on_disc_golf_flight/) + which really piqued my interest. + + # Questions + - I imagine some of you will want to add your disc here, if you can convert your disc into an `.stl` then I will + add it to the database. If this gets common enough I will add an option to upload your own. + - I imagine there will be a barrier to entry to do this. + - If you have any ideas, just let me know in a discussion or in a pull request + """) + + +if __name__ == "__main__": + # Setting up Logger and proj_dir + logger = getLogger(__name__) + proj_dir = Path(__file__).parents[1] + + st.title("Disc Golf Simulator") + + # initialize_state() + main() diff --git a/app/extrema.py b/app/extrema.py new file mode 100644 index 0000000000000000000000000000000000000000..54cc7f67a8c2a8bcd8ac43c5b75eb7c5150c81a3 --- /dev/null +++ b/app/extrema.py @@ -0,0 +1,32 @@ +import numpy as np +from scipy.signal import argrelextrema + +def find_extrema(x, y): + # Find the indices of the local maxima and minima + maxima_idx = argrelextrema(x, np.greater)[0] + minima_idx = argrelextrema(x, np.less)[0] + + # Get the x and y values at the extrema + maxima_x = x[maxima_idx] + maxima_y = y[maxima_idx] + minima_x = x[minima_idx] + minima_y = y[minima_idx] + + # Combine the maxima and minima into a single array + extrema_x = np.concatenate((maxima_x, minima_x)) + extrema_y = np.concatenate((maxima_y, minima_y)) + + # Determine whether each extrema is a maximum or minimum + is_maxima = np.zeros(len(extrema_x), dtype=bool) + is_maxima[:len(maxima_x)] = True + + # Sort the extrema by x-value + idx = np.argsort(extrema_x) + extrema_x = extrema_x[idx] + extrema_y = extrema_y[idx] + is_maxima = is_maxima[idx] + + # Convert the boolean array to a list of strings + extrema_type = ["arrow-left" if is_max else "arrow-right" for is_max in is_maxima] + + return extrema_x, extrema_y, extrema_type diff --git a/app/get_disc.py b/app/get_disc.py new file mode 100644 index 0000000000000000000000000000000000000000..4eea761a6a90e4da8f8dfed2ae1e621e5cec5b1d --- /dev/null +++ b/app/get_disc.py @@ -0,0 +1,101 @@ +import requests + +headers = { + 'authority': 'alldiscs.com', + 'accept': 'application/json, text/javascript, */*; q=0.01', + 'accept-language': 'en-US,en;q=0.6', + 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8', + 'origin': 'https://alldiscs.com', + 'referer': 'https://alldiscs.com/', + 'sec-fetch-dest': 'empty', + 'sec-fetch-mode': 'cors', + 'sec-fetch-site': 'same-origin', + 'sec-gpc': '1', + 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36', + 'x-requested-with': 'XMLHttpRequest', +} + +params = { + 'action': 'get_wdtable', + 'table_id': '5', +} + +data = { + 'draw': '4', + 'columns[0][data]': '0', + 'columns[0][name]': 'wdt_ID', + 'columns[0][searchable]': 'true', + 'columns[0][orderable]': 'true', + 'columns[0][search][value]': '', + 'columns[0][search][regex]': 'false', + 'columns[1][data]': '1', + 'columns[1][name]': 'brand', + 'columns[1][searchable]': 'true', + 'columns[1][orderable]': 'true', + 'columns[1][search][value]': '', + 'columns[1][search][regex]': 'false', + 'columns[2][data]': '2', + 'columns[2][name]': 'mold', + 'columns[2][searchable]': 'true', + 'columns[2][orderable]': 'true', + 'columns[2][search][value]': '', + 'columns[2][search][regex]': 'false', + 'columns[3][data]': '3', + 'columns[3][name]': 'type', + 'columns[3][searchable]': 'true', + 'columns[3][orderable]': 'true', + 'columns[3][search][value]': 'Distance|Fairway|Midrange|Putter', + 'columns[3][search][regex]': 'false', + 'columns[4][data]': '4', + 'columns[4][name]': 'speed', + 'columns[4][searchable]': 'true', + 'columns[4][orderable]': 'true', + 'columns[4][search][value]': '1|15', + 'columns[4][search][regex]': 'false', + 'columns[5][data]': '5', + 'columns[5][name]': 'glide', + 'columns[5][searchable]': 'true', + 'columns[5][orderable]': 'true', + 'columns[5][search][value]': '1|7', + 'columns[5][search][regex]': 'false', + 'columns[6][data]': '6', + 'columns[6][name]': 'turn', + 'columns[6][searchable]': 'true', + 'columns[6][orderable]': 'true', + 'columns[6][search][value]': '-5|1', + 'columns[6][search][regex]': 'false', + 'columns[7][data]': '7', + 'columns[7][name]': 'fade', + 'columns[7][searchable]': 'true', + 'columns[7][orderable]': 'true', + 'columns[7][search][value]': '0|5', + 'columns[7][search][regex]': 'false', + 'columns[8][data]': '8', + 'columns[8][name]': 'inproduction', + 'columns[8][searchable]': 'true', + 'columns[8][orderable]': 'true', + 'columns[8][search][value]': 'Coming Soon|Yes', + 'columns[8][search][regex]': 'false', + 'columns[9][data]': '9', + 'columns[9][name]': 'dateapproved', + 'columns[9][searchable]': 'true', + 'columns[9][orderable]': 'true', + 'columns[9][search][value]': '|', + 'columns[9][search][regex]': 'false', + 'columns[10][data]': '10', + 'columns[10][name]': 'link', + 'columns[10][searchable]': 'true', + 'columns[10][orderable]': 'true', + 'columns[10][search][value]': '', + 'columns[10][search][regex]': 'false', + 'order[0][column]': '0', + 'order[0][dir]': 'asc', + 'start': '0', + 'length': '10', + 'search[value]': 'wraith', + 'search[regex]': 'false', + 'wdtNonce': '511bd3400c', + 'sRangeSeparator': '|', +} + +response = requests.post('https://alldiscs.com/wp-admin/admin-ajax.php', params=params, headers=headers, data=data) \ No newline at end of file diff --git a/app/visualize.py b/app/visualize.py new file mode 100644 index 0000000000000000000000000000000000000000..0770eb24320b953d10f206b2cf46a0a00d3b6f29 --- /dev/null +++ b/app/visualize.py @@ -0,0 +1,272 @@ +import math + +import numpy as np +import plotly.graph_objects as go +from plotly.colors import sequential +from stl.mesh import Mesh + +from extrema import find_extrema + + +def get_stl(stl_file): + """ + Taken from https://community.plotly.com/t/view-3d-cad-data/16920/9 + """ + stl_mesh = Mesh.from_file(stl_file) + return stl_mesh + + +def visualize_disc(stl_mesh, nose, roll): + """ + Taken from https://community.plotly.com/t/view-3d-cad-data/16920/9 + """ + stl_mesh.rotate([1, 0, 0], math.radians(-1*nose)) + stl_mesh.rotate([0, 1, 0], math.radians(roll)) + # stl_mesh.rotate([0, 0, 1], math.radians(z_angle)) + + p, q, r = stl_mesh.vectors.shape # (p, 3, 3) + # the array stl_mesh.vectors.reshape(p*q, r) can contain multiple copies of the same vertex; + # extract unique vertices from all mesh triangles + vertices, ixr = np.unique(stl_mesh.vectors.reshape(p * q, r), return_inverse=True, axis=0) + I = np.take(ixr, [3 * k for k in range(p)]) + J = np.take(ixr, [3 * k + 1 for k in range(p)]) + K = np.take(ixr, [3 * k + 2 for k in range(p)]) + + x, y, z = vertices.T + trace = go.Mesh3d(x=x, y=y, z=z, i=I, j=J, k=K) + # optional parameters to make it look nicer + trace.update(flatshading=True, lighting_facenormalsepsilon=0, lighting_ambient=0.7) + + fig = go.Figure(trace) + + # Add camera controls to the plot + camera = dict( + eye=dict(x=0, y=-3, z=0) + ) + fig.update_layout(scene_camera=camera) + + fig.update_layout( + scene=dict( + xaxis=dict(nticks=4, range=[-0.11, 0.11], ), + yaxis=dict(nticks=4, range=[-0.11, 0.11], ), + zaxis=dict(nticks=4, range=[-0.11, 0.11], ), ) + ) + return fig + + +import plotly.subplots as sp + + +def get_plot(x, y, z): + xm = np.min(x) - 1.5 + xM = np.max(x) + 1.5 + ym = -5 + yM = np.max(y) + 1.5 + zm = np.min(z) + zM = np.max(z) + N = len(x) + category = 'Height' + x_extrema, y_extrema, extrema_type = find_extrema(x, y) + + xM_abs = max(abs(xm), abs(xM)) + xm_abs = -1 * xM_abs + + carats_v = go.Scatter( + x=[category, category], + y=[min(z), max(z)], + mode='markers', + showlegend=False, + marker=dict(symbol=['arrow-up', 'arrow-down'], size=20, color=['red', 'red']), + name='Carets', + ) + carats_h = go.Scatter( + x=[min(x), max(x)], + y=['', ''], + mode='markers', + showlegend=False, + marker=dict(symbol=['arrow-right', 'arrow-left'], size=20, color=['red', 'red']), + name='Carets', + ) + + extrema = go.Scatter( + x=x_extrema, + y=y_extrema, + mode='markers', + showlegend=False, + marker=dict(symbol=extrema_type, size=20, color='blue'), + name='Extrema', + ) + + # Create figure with subplots + fig = sp.make_subplots(rows=2, cols=2, subplot_titles=("Flight Path", "Height", "Lateral Deviance"), + specs=[[{"rowspan": 2}, {}], [None, {}]], row_heights=[0.5, 0.5]) + + # Add traces to the main plot + fig.add_trace( + go.Scatter(x=x, y=y, + mode="lines", + showlegend=False, + line=dict(width=1, color='black')), + row=1, col=1 + ) + + fig.add_trace( + go.Scatter(x=x, y=y, + showlegend=False, + mode="markers", marker_colorscale=sequential.Peach, + marker=dict(color=z, size=3, showscale=True)), + row=1, col=1 + ) + + fig.add_trace( + extrema, + row=1, col=1 + ) + + # Add trace for the subplot + fig.add_trace(carats_v, + row=1, col=2 + ) + fig.add_trace( + go.Bar( + x=[], + y=[], + showlegend=False, + ), + row=1, col=2 + ) + # Add trace for the subplot + fig.add_trace(carats_h, + row=2, col=2 + ) + fig.add_trace( + go.Bar( + x=[], + y=[], + showlegend=False, + orientation='h', + ), + row=2, col=2 + ) + + # Update layout + fig.update_layout( + xaxis=dict(range=[xm, xM], autorange=False, zeroline=False), + yaxis=dict(range=[ym, yM], autorange=False, zeroline=False), + title_text="Flight Path", + hovermode="closest", + updatemenus=[ + dict( + type="buttons", + buttons=[ + dict( + label="Play", + method="animate", + args=[None, {"frame": {"duration": 30, "redraw": True}, "fromcurrent": True}] + ), + dict( + label="Pause", + method="animate", + args=[[None], {"frame": {"duration": 0, "redraw": False}, "mode": "immediate", + "transition": {"duration": 0}}] + ) + ], + showactive=False, + x=0.05, + y=0.05 + ) + ], + ) + + # Create frames for the main plot and subplot + all_frames = [ + go.Frame(data=[ + go.Scatter( + x=[x[k]], + y=[y[k]], + mode="markers", + showlegend=False, + marker=dict(color="red", size=10)), + go.Scatter(x=x, y=y, + mode="markers", marker_colorscale=sequential.Peach, + marker=dict(color=z, size=3, showscale=True)), + extrema, + carats_v, + go.Bar( + x=['Height'], + y=[z[k]], + showlegend=False, + name='Value', + marker=dict(color='orange', line=dict(width=1)) + # Set color of value bar to orange and line width to 1 + ), + carats_h, + go.Bar( + x=[x[k]], + y=[''], + showlegend=False, + name='Value', + orientation='h', + marker=dict(color='orange', line=dict(width=1)) + # Set color of value bar to orange and line width to 1 + ) + ]) + for k in range(N) + ] + + # Combine frames for the main plot and subplot + fig.frames = all_frames + fig.update_yaxes(scaleanchor="x", scaleratio=1, row=1, col=1) + fig.update_yaxes(range=[zm - 2, zM + 2], fixedrange=True, row=1, col=2) + fig.update_xaxes(range=[xm_abs, xM_abs], fixedrange=True, row=2, col=2) + + # # Add green rectangle at the bottom of the plot + fig.update_layout( + shapes=[dict(type="rect", xref="x", yref="y", + x0=-1, y0=0, x1=1, y1=-4, fillcolor="gray", + opacity=1, layer="below")], + plot_bgcolor="green", + ) + + return fig + + +import plotly.graph_objs as go +from plotly.subplots import make_subplots + + +def get_subplots(arc, alphas, lifts, drags, moms, rolls, velocity): + fig = make_subplots(rows=2, cols=3, specs=[[{}, {}, {}], [{}, {}, {}]], + subplot_titles=("Lift force (N)", "Drag force (N)", "Moment (Nm)", + "Angle of attack (deg)", "Velocities (m/s)", "Roll rate (rad/s)"), + shared_xaxes=True) + + fig.add_trace(go.Scatter(x=arc, y=lifts, name="Lift force (N)"), row=1, col=1) + fig.update_xaxes(title_text="Distance (m)", row=1, col=1) + fig.update_yaxes(title_text="Lift force (N)", row=1, col=1) + + fig.add_trace(go.Scatter(x=arc, y=drags, name="Drag force (N)"), row=1, col=2) + fig.update_xaxes(title_text="Distance (m)", row=1, col=2) + fig.update_yaxes(title_text="Drag force (N)", row=1, col=2) + + fig.add_trace(go.Scatter(x=arc, y=moms, name="Moment (Nm)"), row=1, col=3) + fig.update_xaxes(title_text="Distance (m)", row=1, col=3) + fig.update_yaxes(title_text="Moment (Nm)", row=1, col=3) + + fig.add_trace(go.Scatter(x=arc, y=alphas, name="Angle of attack (deg)"), row=2, col=1) + fig.update_xaxes(title_text="Distance (m)", row=2, col=1) + fig.update_yaxes(title_text="Angle of attack (deg)", row=2, col=1) + + fig.add_trace(go.Scatter(x=arc, y=velocity[0, :], name="u"), row=2, col=2) + fig.add_trace(go.Scatter(x=arc, y=velocity[1, :], name="v"), row=2, col=2) + fig.add_trace(go.Scatter(x=arc, y=velocity[2, :], name="w"), row=2, col=2) + fig.update_xaxes(title_text="Distance (m)", row=2, col=2) + fig.update_yaxes(title_text="Velocities (m/s)", row=2, col=2) + fig.update_traces(mode='lines', row=2, col=2) + + fig.add_trace(go.Scatter(x=arc, y=rolls, name="Roll rate (rad/s)"), row=2, col=3) + fig.update_xaxes(title_text="Distance (m)", row=2, col=3) + fig.update_yaxes(title_text="Roll rate (rad/s)", row=2, col=3) + + fig.update_layout(height=600, width=1000, title_text="Plotly Subplots", hovermode='x') + return fig diff --git a/bootstrap.py b/bootstrap.py new file mode 100644 index 0000000000000000000000000000000000000000..d9ccf5d9d819d74ce37568c512fd4a47b4dfa27d --- /dev/null +++ b/bootstrap.py @@ -0,0 +1,12 @@ +from pathlib import Path +import streamlit.web.bootstrap +from streamlit import config as _config + +proj_dir = Path(__file__).parent +filename = proj_dir / "app" / "app.py" + +_config.set_option("server.headless", True) +args = [] + +# streamlit.cli.main_run(filename, args) +streamlit.web.bootstrap.run(str(filename), "", args, "") diff --git a/examples/disc_experimental_trajectory_comparison.py b/examples/disc_experimental_trajectory_comparison.py new file mode 100644 index 0000000000000000000000000000000000000000..463ec858561421e781308ebf06a954822cba3618 --- /dev/null +++ b/examples/disc_experimental_trajectory_comparison.py @@ -0,0 +1,106 @@ +# -*- coding: utf-8 -*- + +import sys +from shotshaper.projectile import DiscGolfDisc +import matplotlib.pyplot as pl +import numpy as np +import shotshaper.environment as env +from shotshaper.transforms import T_12 +from random import uniform + + +def rotz(pos,betad): + beta = np.radians(betad) + TZ = np.array([[np.cos(beta), -np.sin(beta), 0], + [np.sin(beta), np.cos(beta), 0], + [0, 0, 1]]) + + return np.matmul(TZ,pos) + +throws=[1,6,15] + +nthrow = len(throws) + # pitch, roll, nose,speed,spin, yaw, wind, length +params = [[15.5, 21.8, 0.0, 24.7, 138, -31.6, 4.8, 89.7], + [12.3, 14.7, 0.8, 24.2, 128.5, -9.60, 4.8, 87.0], + [5.20,-0.70, 0.0, 24.5, 147.7, 8.00, 4.8, 106.6]] + + +d = DiscGolfDisc('dd2') +fig1, ax1 = pl.subplots( ) + +fig1.set_figheight(4) +fig1.set_figwidth(6) + +for i in range(nthrow): + p = params[i] + t = throws[i] + U = p[3] + omega = p[4] + z0 = 1.5 + pos = np.array((0,0,z0)) + pitch = p[0] + yaw = p[5] + nose = p[2] + roll = p[1] + + env.Uref = p[6] + env.winddir = np.array((1,0,0)) + + # Currently handle yaw by rotating the position after the throw, hence + # also need to rotate the wind vector accordingly + env.winddir = rotz(env.winddir, -yaw) + + s = d.shoot(speed=U, omega=omega, pitch=pitch, position=pos, nose_angle=nose, roll_angle=roll) + + pos = s.position + for j in range(len(pos[0,:])): + pos[:,j] = rotz(pos[:,j], yaw) + x,y,z = pos + arc,alphas,betas,lifts,drags,moms,rolls = d.post_process(s, omega) + + # Plot trajectory + ax1.plot(x,y,f'C{i}-') + + # Experiment + te,xe,ye,ve = np.loadtxt(f'data/throw{t}',skiprows=2,unpack=True) + ax1.plot(xe,ye,f'C{i}--') + + ax1.set_xlabel('Distance (m)') + ax1.set_ylabel('Drift (m)') + ax1.axis('equal') + + # Plot other parameters + + # axes[0,0].plot(arc, lifts) + # axes[0,0].set_xlabel('Distance (m)') + # axes[0,0].set_ylabel('Lift force (N)') + + # axes[0,1].plot(arc, drags) + # axes[0,1].set_xlabel('Distance (m)') + # axes[0,1].set_ylabel('Drag force (N)') + + # axes[0,2].plot(arc, moms) + # axes[0,2].set_xlabel('Distance (m)') + # axes[0,2].set_ylabel('Moment (Nm)') + + # axes[1,0].plot(arc, alphas) + # axes[1,0].set_xlabel('Distance (m)') + # axes[1,0].set_ylabel('Angle of attack (deg)') + + # axes[1,1].plot(arc, s.velocity[0,:]) + # axes[1,1].plot(arc, s.velocity[1,:]) + # axes[1,1].plot(arc, s.velocity[2,:]) + # axes[1,1].set_xlabel('Distance (m)') + # axes[1,1].set_ylabel('Velocities (m/s)') + + # axes[1,2].plot(arc, rolls) + # axes[1,2].set_xlabel('Distance (m)') + # axes[1,2].set_ylabel('Roll rate (rad/s)') + +pl.tight_layout() +pl.show() + + + + diff --git a/examples/disc_golf_throw.py b/examples/disc_golf_throw.py new file mode 100644 index 0000000000000000000000000000000000000000..ebb9fbc42b21e3a2f46c3b46fdf6d82f89f990b4 --- /dev/null +++ b/examples/disc_golf_throw.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +""" +Example showing a single disc throw. +""" + +from shotshaper.projectile import DiscGolfDisc +import matplotlib.pyplot as pl +import numpy as np +import plotly.express as px + +d = DiscGolfDisc('dd2') +U = 24.2 +omega = 116.8 +z0 = 1.3 +pos = np.array((0,0,z0)) +pitch = 15.5 +nose = 0.0 +roll = 14.7 + +shot = d.shoot(speed=U, omega=omega, pitch=pitch, + position=pos, nose_angle=nose, roll_angle=roll) + +# Plot trajectory +pl.figure(1) +x,y,z = shot.position +pl.plot(x,y) +fig = px.scatter(x,y) +fig.show() + +pl.xlabel('Distance (m)') +pl.ylabel('Drift (m)') +pl.axis('equal') + +# Plot other parameters +arc,alphas,betas,lifts,drags,moms,rolls = d.post_process(shot, omega) +fig, axes = pl.subplots(nrows=2, ncols=3, dpi=80,figsize=(13,5)) + +axes[0,0].plot(arc, lifts) +axes[0,0].set_xlabel('Distance (m)') +axes[0,0].set_ylabel('Lift force (N)') + +axes[0,1].plot(arc, drags) +axes[0,1].set_xlabel('Distance (m)') +axes[0,1].set_ylabel('Drag force (N)') + +axes[0,2].plot(arc, moms) +axes[0,2].set_xlabel('Distance (m)') +axes[0,2].set_ylabel('Moment (Nm)') + +axes[1,0].plot(arc, alphas) +axes[1,0].set_xlabel('Distance (m)') +axes[1,0].set_ylabel('Angle of attack (deg)') + +axes[1,1].plot(arc, shot.velocity[0,:]) +axes[1,1].plot(arc, shot.velocity[1,:]) +axes[1,1].plot(arc, shot.velocity[2,:]) +axes[1,1].set_xlabel('Distance (m)') +axes[1,1].set_ylabel('Velocities (m/s)') +axes[1,1].legend(('u','v','w')) + +axes[1,2].plot(arc, rolls) +axes[1,2].set_xlabel('Distance (m)') +axes[1,2].set_ylabel('Roll rate (rad/s)') +pl.tight_layout() + +pl.show() diff --git a/examples/disc_gui2d.py b/examples/disc_gui2d.py new file mode 100644 index 0000000000000000000000000000000000000000..549bb52edaeb47edbfc34828bf65f33543b1d58c --- /dev/null +++ b/examples/disc_gui2d.py @@ -0,0 +1,105 @@ +# -*- coding: utf-8 -*- +""" +Graphical user interface to explore the influence +of disc throw parameters on the trajectory +""" + +import numpy as np +import matplotlib.pyplot as pl +from matplotlib.widgets import Slider, TextBox +from shotshaper.projectile import DiscGolfDisc + +name = 'dd2' +mass = 0.175 + +d = DiscGolfDisc(name, mass=mass) +speed = 24 +omega = d.empirical_spin(speed) +z0 = 1.3 +pos = np.array((0,0,z0)) +pitch = 10 +nose = 0.0 +roll = 15.0 +yaw = 0 +adjust_axes = False + +s = d.shoot(speed=speed, omega=omega, pitch=pitch, position=pos, nose_angle=nose, roll_angle=roll,yaw=yaw) + +x,y,z = s.position + +# Creating figure +fig = pl.figure(1,figsize=(13, 6), dpi=80) +ax1 = pl.subplot(2,3,2) +ax2 = pl.subplot(2,3,5) +ax3 = pl.subplot(1,3,3) +fac = 1.6 +ylim = fac*max(abs(min(y)),abs(max(y))) +ax1.axis((min(x),fac*max(x),-ylim,ylim)) +ax2.axis((min(x),fac*max(x),min(z),fac*max(z))) +ax3.axis((-ylim,ylim,min(z),fac*max(z))) + +ax3.invert_xaxis() + +l1, = ax1.plot(x,y,lw=2) +ax1.set_xlabel('Distance (m)') +ax1.set_ylabel('Drift (m)') +l2, = ax2.plot(x,z,lw=2) +ax2.set_xlabel('Distance (m)') +ax2.set_ylabel('Height (m)') + +l3, = ax3.plot(y,z,lw=2) +ax3.set_xlabel('Drift (m)') +ax3.set_ylabel('Height (m)') + +xax = 0.07 +ax4 = pl.axes([xax, 0.80, 0.25, 0.03], facecolor='lightgrey') +ax5 = pl.axes([xax, 0.75, 0.25, 0.03], facecolor='lightgrey') +ax6 = pl.axes([xax, 0.70, 0.25, 0.03], facecolor='lightgrey') +#ax7 = pl.axes([xax, 0.65, 0.25, 0.03], facecolor='lightgrey') +ax8 = pl.axes([xax, 0.65, 0.25, 0.03], facecolor='lightgrey') +ax9 = pl.axes([xax, 0.60, 0.25, 0.03], facecolor='lightgrey') +ax11 = pl.axes([xax, 0.55, 0.25, 0.03], facecolor='lightgrey') + +s1 = Slider(ax=ax4, label='Speed (m/s)', valmin=15, valmax=35, valinit=speed) +s2 = Slider(ax=ax5, label='Roll (deg)', valmin=-110, valmax=110, valinit=roll) +s3 = Slider(ax=ax6, label='Pitch (deg)', valmin=-10, valmax=50, valinit=pitch) +s5 = Slider(ax=ax8, label='Nose (deg)', valmin=-5, valmax=5, valinit=nose) +s7 = Slider(ax=ax9, label='Mass (kg)', valmin=0.140, valmax=0.200, valinit=mass) +s6 = Slider(ax=ax11, label='Spin (-)', valmin=0, valmax=2, valinit=1.0) + +def update(x): + speed = s1.val + roll = s2.val + pitch = s3.val + nose = s5.val + spin = s6.val + mass = s7.val + d = DiscGolfDisc(name,mass=mass) + + omega = spin*d.empirical_spin(speed) + s = d.shoot(speed=speed, omega=omega, pitch=pitch, position=pos, nose_angle=nose, roll_angle=roll) + x,y,z = s.position + + l1.set_xdata(x) + l1.set_ydata(y) + l2.set_xdata(x) + l2.set_ydata(z) + l3.set_xdata(y) + l3.set_ydata(z) + + if adjust_axes: + ax1.axis((min(x),max(x),min(y),max(y))) + ax2.axis((min(x),max(x),min(z),max(z))) + ax3.axis((min(y),max(y),min(z),max(z))) + + fig.canvas.draw_idle() + +s1.on_changed(update) +s2.on_changed(update) +s3.on_changed(update) +s5.on_changed(update) +s6.on_changed(update) +s7.on_changed(update) + +pl.show() + diff --git a/examples/driver.py b/examples/driver.py new file mode 100644 index 0000000000000000000000000000000000000000..13b1a3748c0ea2fc8ae6da0b01770324ebf801f5 --- /dev/null +++ b/examples/driver.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +""" +Simple example comparing different projectiles. +""" + +from shotshaper.projectile import _Particle, ShotPutBall, SoccerBall +import matplotlib.pyplot as pl +import numpy as np + +U = 10.0 +angle = 20.0 + +p = _Particle() +shot = p.shoot(speed=U, pitch=angle) +pl.plot(shot.position[0,:],shot.position[2,:]) + +p = ShotPutBall('M') +shot = p.shoot(speed=U, pitch=angle) +pl.plot(shot.position[0,:],shot.position[2,:]) + +p = SoccerBall() + +spin = np.array((0,0,0)) +shot = p.shoot(speed=U, pitch=angle, spin=spin) +pl.plot(shot.position[0,:],shot.position[2,:]) + +spin = np.array((0,-10,0)) +shot = p.shoot(speed=U, pitch=angle, spin=spin) +pl.plot(shot.position[0,:],shot.position[2,:]) + +pl.legend(('vacuum','air', 'no spin','spin')) + +pl.show() + + diff --git a/examples/validation_balls.py b/examples/validation_balls.py new file mode 100644 index 0000000000000000000000000000000000000000..bc04826cc417a89c686992b5419b5ef64b11149e --- /dev/null +++ b/examples/validation_balls.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +""" +This program calculates trajectories that were experimentally conducted in + +Mencke, J. E., Salewski, M., Trinhammer, O. L., & Adler, A. T. (2020). +Flight and bounce of spinning sports balls. American Journal of Physics, +88(11), 934-947. + +Specifically, this includes data for: + - a shot put throw, representing a heavy projectile where the + gravitational forces dominate over the aerodynamic forces + - a soccer ball, with slightly more influence of air drag + - a table tennis ball, significantly impacted by air drag due + to low weight +""" + +from shotshaper.projectile import SoccerBall, ShotPutBall, TableTennisBall +import matplotlib.pyplot as pl +import numpy as np + +cases = ('Shot','Soccer ball','Table tennis ball') +projectiles = (ShotPutBall('M'), SoccerBall(), TableTennisBall()) +ux = (9.0, 11.0, 11.8) +uy = (7.1, 10.2, 12.0) +z0 = (2.4, 0.0, 1.0) +spin = (0,0,0) + +f, ax = pl.subplots(1, 1, figsize=(6,4)) +for i,c in enumerate(cases): + speed = np.sqrt(ux[i]**2 + uy[i]**2) + pitch = np.degrees(np.arctan2(uy[i],ux[i])) + position = (0, 0, z0[i]) + + s = projectiles[i].shoot(speed=speed,pitch=pitch,position=position,spin=spin) + + x,y,z = s.position + + ax.plot(x,z,'C0-') + ax.text(x[0]-0.5, z[0], c, fontsize=9, ha='right') + + x,z = np.loadtxt(f'data/{c}_trajectory.dat', unpack=True, delimiter=';') + ax.plot(x,z,'C1--') + +ax.legend(('Simulation','Experiment')) +ax.axis((-10,25,-1,6)) + +pl.xlabel('Length (m)') +pl.ylabel('Height (m)') + +pl.show() diff --git a/examples/validation_spinning_ball.py b/examples/validation_spinning_ball.py new file mode 100644 index 0000000000000000000000000000000000000000..52e06af01e78a374fcc0fd282666617048ddb69d --- /dev/null +++ b/examples/validation_spinning_ball.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +""" +This program calculates the trajectory of a spinning soccer ball +that was experimentally investigated in + +Mencke, J. E., Salewski, M., Trinhammer, O. L., & Adler, A. T. (2020). +Flight and bounce of spinning sports balls. American Journal of Physics, +88(11), 934-947. + +""" + +from shotshaper.projectile import SoccerBall +import matplotlib.pyplot as pl +import numpy as np +from scipy.linalg import norm + +ball = SoccerBall() +u = np.array([20.0, 2.5, 4.9]) +# Note that spin is here negative along the z-axis, as opposed +# to positive around the y-axis, since we define z as upwards, +# while Mencke et al. define y as upwards +spin = (0,0,-46) +speed = norm(u) +pitch = np.degrees(np.arctan2(u[2],u[0])) +yaw = -np.degrees(np.arctan2(u[1],u[0])) + +s = ball.shoot(speed=speed,pitch=pitch,yaw=yaw,spin=spin) + +x,y,z = s.position + +f, (ax1, ax2) = pl.subplots(2, 1, figsize=(5,7)) + +ax1.plot(x,z,'C0-') +ax2.plot(x,y,'C0-') +x,z = np.loadtxt('data/Spin_z_trajectory.dat', unpack=True, delimiter=';') +ax1.plot(x,z,'C1--') +x,y = np.loadtxt('data/Spin_y_trajectory.dat', unpack=True, delimiter=';') +ax2.plot(x,y,'C1--') + +ax1.legend(('Simulation','Experiment')) +ax2.legend(('Simulation','Experiment')) + +ax1.set_xlabel('Length (m)') +ax1.set_ylabel('Height (m)') +ax2.set_xlabel('Length (m)') +ax2.set_ylabel('Drift (m)') + +pl.show() diff --git a/notebooks/animation.ipynb b/notebooks/animation.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..574ca73e7e3e5960953f405de98ee9fc96371930 --- /dev/null +++ b/notebooks/animation.ipynb @@ -0,0 +1,11341 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "602d79a8", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "077b6d03", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "PosixPath('/Users/derekthomas/projects/shotshaper_app')" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from pathlib import Path\n", + "\n", + "import matplotlib.pyplot as plt\n", + "from matplotlib.animation import FuncAnimation\n", + "\n", + "import numpy as np\n", + "\n", + "proj_dir = Path.cwd().parent\n", + "proj_dir" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "fbec8bf2", + "metadata": {}, + "outputs": [], + "source": [ + "import sys\n", + "sys.path.append(str(proj_dir))\n", + "\n", + "from shotshaper.projectile import DiscGolfDisc\n", + "from app.visualize_disc import get_stl, get_plot" + ] + }, + { + "cell_type": "code", + "execution_count": 61, + "id": "3fae5e12", + "metadata": {}, + "outputs": [], + "source": [ + "disc_names = {\n", + " 'Innova Wraith': 'dd2',\n", + " 'Innova Firebird': 'cd1',\n", + " 'Innova Roadrunner': 'cd5',\n", + " 'Innova Fairway Driver': 'fd2',\n", + " }\n", + "disc_name = 'dd2'\n", + "\n", + "U = 24.2\n", + "omega = 116.8\n", + "z0 = 1.3\n", + "pos = np.array((0, 0, z0))\n", + "pitch = 15.5\n", + "nose = 0.0\n", + "roll = 14.7\n", + "\n", + "disc_dict = DiscGolfDisc(disc_name)\n", + "\n", + "shot = disc_dict.shoot(speed=U, omega=omega, pitch=pitch,\n", + " position=pos, nose_angle=nose, roll_angle=roll)\n", + "\n", + "# Plot trajectory\n", + "x, y, z = shot.position" + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "id": "3197d909", + "metadata": {}, + "outputs": [], + "source": [ + "reverse=True" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "id": "cb495cca", + "metadata": {}, + "outputs": [], + "source": [ + "if reverse:\n", + " x,y = y,x" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "id": "ddd260f0", + "metadata": {}, + "outputs": [], + "source": [ + "import plotly.io as pio\n", + "\n", + "pio.templates.default = \"seaborn\"" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "id": "5d8db99e", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "line": { + "color": "black", + "width": 1 + }, + "mode": "lines", + "type": "scatter", + "x": [ + 0, + 0.0010983589941245442, + 0.00427619745063529, + 0.009365653406349208, + 0.016205620162965298, + 0.02463844175531675, + 0.034508742586064935, + 0.04566244978621435, + 0.057946701262729224, + 0.0712098456985336, + 0.08530144255251122, + 0.1000706867945729, + 0.11536754138326388, + 0.13105196805892474, + 0.14698472581081257, + 0.16302667989274092, + 0.17903880182307982, + 0.19488216938475592, + 0.21042010093238206, + 0.2255303918040158, + 0.2400941529618775, + 0.2539941125955256, + 0.26711510792876336, + 0.27934408521963855, + 0.29057009976044373, + 0.300685743957656, + 0.309593655450644, + 0.31719802747772946, + 0.3234076468096852, + 0.32813661323363996, + 0.3313043395530784, + 0.33283555158784134, + 0.3326602881741255, + 0.33071390116448374, + 0.3269370554278247, + 0.3212757288494131, + 0.3136930280801147, + 0.3041588254540771, + 0.29262071076803087, + 0.27903290120181323, + 0.26335685051262864, + 0.2455612490350489, + 0.22562202368101322, + 0.20352233793982843, + 0.1792525918781689, + 0.1528104221400761, + 0.12420070194695887, + 0.09343554109759394, + 0.060534285968125434, + 0.025520046231359828, + -0.011616497219535962, + -0.050888014639398266, + -0.092298715172146, + -0.1358469561082469, + -0.18152524288471686, + -0.22932022908511934, + -0.27921271643956597, + -0.3311776548247172, + -0.38518414226378156, + -0.44119542492651537, + -0.49916889712922247, + -0.5590561013347564, + -0.6208029971066803, + -0.6844038687076884, + -0.7498500581699944, + -0.8170979263286259, + -0.8861037874492588, + -0.9568239092282187, + -1.0292145127924766, + -1.1032317726996548, + -1.1788318169380245, + -1.2559707269265017, + -1.3346045375146547, + -1.4146892369826987, + -1.4961807670414977, + -1.5790349940802104, + -1.663201610016293, + -1.7486203851470916, + -1.8352310774273644, + -1.9229738365440703, + -2.0117892039163756, + -2.1016181126956495, + -2.1924018877654654, + -2.284082245741601, + -2.3766012949720365, + -2.469901535536957, + -2.5639258592487546, + -2.6586175496520195, + -2.7539172698514673, + -2.849738649150951, + -2.9460074195778514, + -3.0426525381277245, + -3.139600594522026, + -3.2367758112081173, + -3.334100043359261, + -3.4314927788746195, + -3.5288711383792597, + -3.6261498752241508, + -3.7232413754861624, + -3.82005565796807, + -3.9165003741985442, + -4.012479933302324, + -4.107895462246632, + -4.202649239569367, + -4.296642196632203, + -4.38977375741116, + -4.481941838496603, + -4.573042849093244, + -4.662971691020136, + -4.751621758710683, + -4.838884939212635, + -4.924651612188081, + -5.008812097338238, + -5.091257117468792, + -5.171874219913148, + -5.250550441340474, + -5.3271723824195005, + -5.401626207818531, + -5.473797646205435, + -5.543571990247649, + -5.610834096612183, + -5.675468385965606, + -5.737369241314975, + -5.796446642679979, + -5.85256219189122, + -5.9055778527653295, + -5.955360459130243, + -6.001781714825189, + -6.044718193700705, + -6.0840513396186235, + -6.1196674664520785, + -6.151457758085507, + -6.179318268414645, + -6.2031499213465295, + -6.222858510799498, + -6.238354700703189, + -6.24955437206703, + -6.256366374568064, + -6.258646894373072, + -6.256251275277718, + -6.249047374496844, + -6.236915562664473, + -6.219748723833799, + -6.197452255477199, + -6.169944068486224, + -6.137154587171603, + -6.099026749263243, + -6.055516005910229, + -6.006590321680821, + -5.952229825670214, + -5.892380072941787, + -5.826923824892067, + -5.755756224847247, + -5.678789891904708, + -5.595954920933018, + -5.50719888257192, + -5.412486823232352, + -5.311801265096435, + -5.205142206117466, + -5.092527120019939, + -4.973990956299522, + -4.849586140223074, + -4.719354475843899, + -4.583208148390372, + -4.441112388067696, + -4.29305394005681, + -4.13903018566233, + -3.979049142312538, + -3.813129463559366, + -3.6413004390784236, + -3.463601994668987, + -3.2800846922539804, + -3.090809729880008, + -2.8958489417173405, + -2.695284798059895, + -2.4891579829150476, + -2.277343750099553, + -2.0598344687027206, + -1.8366472712998312, + -1.6078115870720198, + -1.3733691418063179, + -1.133373957895606, + -0.8878923543386541, + -0.6370029467401079, + -0.3807966473104645, + -0.11937639690606999, + 0.14717296430808147, + 0.41881412230523896, + 0.6955117076484528, + 0.9772268376846887, + 1.2639171165448508, + 1.5555366351437314, + 1.8520359711800665, + 2.1533621891364882, + 2.4594592205203734, + 2.770297047266685, + 3.0858540420102143, + 3.4060987168050487, + 3.731000097941278, + 4.060527725945029 + ], + "y": [ + 0, + 0.8009254237823245, + 1.5960792856623531, + 2.385475597072574, + 3.169107926495013, + 3.9469627091118635, + 4.719064738594156, + 5.485428489174774, + 6.246054659859775, + 7.000930174428392, + 7.750028181433031, + 8.493321800844054, + 9.230848303648116, + 9.962640419188402, + 10.688721135726254, + 11.409106100281491, + 12.12380361863239, + 12.832814655315694, + 13.536141526069686, + 14.233827708840856, + 14.92590791962178, + 15.612412172842994, + 16.29336837171016, + 16.968802308204065, + 17.638737663080626, + 18.303197772284673, + 18.96221687393142, + 19.615831094811565, + 20.264078251103, + 20.906998493476177, + 21.54463430709409, + 22.177030511612276, + 22.804234261178824, + 23.42629504443437, + 24.043264684512103, + 24.65519733903775, + 25.262152267131423, + 25.864181722662728, + 26.461325266599058, + 27.05362363907989, + 27.641118986264335, + 28.223854860331127, + 28.801876219478636, + 29.375229427924843, + 29.943962255907365, + 30.508123879683442, + 31.067764881529943, + 31.622937249743355, + 32.173694378639794, + 32.72009218738413, + 33.26218010702771, + 33.799977667389044, + 34.3335034093641, + 34.8627786915446, + 35.387827690218025, + 35.90867739936762, + 36.42535763067235, + 36.93790101350698, + 37.446342994942015, + 37.95072183974371, + 38.45107863037406, + 38.94745726699086, + 39.43990427792595, + 39.928431407790036, + 40.41305297902097, + 40.893806661689624, + 41.37072840442675, + 41.84385243442295, + 42.31321125742866, + 42.7788356577542, + 43.24075469826971, + 43.6989957204052, + 44.15358434415054, + 44.60454446805543, + 45.05189826922945, + 45.49566630651224, + 45.93588056745503, + 46.3725796919581, + 46.80579821530137, + 47.235570987770096, + 47.661933174654884, + 48.08492025625169, + 48.50456802786183, + 48.92091259979195, + 49.33399039735404, + 49.74383816086546, + 50.15049294564891, + 50.553992122032405, + 50.954374617417564, + 51.35169287353763, + 51.74599726604182, + 52.13733557974711, + 52.525754923163895, + 52.91130172849604, + 53.294021751640855, + 53.67396007218908, + 54.051161093424916, + 54.425668542325994, + 54.79752546956339, + 55.16677424950164, + 55.53345658019872, + 55.89760865798415, + 56.25925895103407, + 56.6184500510062, + 56.97522530669493, + 57.32962796938487, + 57.681701192850845, + 58.03148803335787, + 58.37903144966116, + 58.724374303006165, + 59.06755935712853, + 59.40862927825411, + 59.74762542292647, + 60.084589296713986, + 60.41956528121868, + 60.75259695310655, + 61.083727002184034, + 61.412997231398116, + 61.74044855683622, + 62.06612100772625, + 62.390053726436626, + 62.712284968476226, + 63.03284998497459, + 63.351776987950316, + 63.66909935696007, + 63.984848949806604, + 64.29905533513912, + 64.61174579245314, + 64.92294531209069, + 65.23267659524016, + 65.54096005393635, + 65.84781381106046, + 66.15325370034014, + 66.45729326634941, + 66.7599437645087, + 67.06121416108488, + 67.36111123046317, + 67.6596393484896, + 67.95679201680211, + 68.25255805236169, + 68.54692390182664, + 68.83987364155264, + 69.1313889775927, + 69.4214492456972, + 69.71003141131382, + 69.99711006958765, + 70.28265744536107, + 70.56664339317383, + 70.84903539726304, + 71.12979877804013, + 71.4089013037207, + 71.68628709809721, + 71.9618920961067, + 72.23565387870656, + 72.50751167287468, + 72.77740635160949, + 73.0452804339298, + 73.31107808487492, + 73.57474511550464, + 73.8362289828992, + 74.09547879015935, + 74.35244528640624, + 74.60707597251024, + 74.85929376642193, + 75.10903033701548, + 75.35622269709795, + 75.60081139525005, + 75.84274051582622, + 76.08195767895464, + 76.31841404053715, + 76.55206429224933, + 76.78286666154047, + 77.01078291163358, + 77.23577834152536, + 77.45782178598624, + 77.67686626514661, + 77.89279917306106, + 78.10554900769742, + 78.31505799671363, + 78.52127773038842, + 78.72416916162125, + 78.9237026059323, + 79.11985774146251, + 79.31262360897355, + 79.50199861184787, + 79.68799051389001, + 79.87060499112509, + 80.04982419888624, + 80.22562876649116, + 80.39800223908368, + 80.56693107763384, + 80.73240465893781, + 80.89441527561794, + 81.05295813612273, + 81.2080312693581, + 81.35962836017158, + 81.50774318088123, + 81.65237333039319, + 81.79351749445702, + 81.9311754456657 + ] + }, + { + "marker": { + "color": [ + 1.3, + 1.5209323692530852, + 1.7379504943362472, + 1.9511645303797363, + 2.1607246729084886, + 2.36679884101108, + 2.569448068987617, + 2.768759133677192, + 2.9648542438730994, + 3.1578910403228377, + 3.3480625957281083, + 3.535562447776559, + 3.720413701461157, + 3.902642533735428, + 4.08230024360506, + 4.259457522419323, + 4.434204453871075, + 4.606650513996753, + 4.7769005425345075, + 4.944942634483472, + 5.110785388374909, + 5.274449055858441, + 5.435958505567465, + 5.595343223119146, + 5.752637311114429, + 5.907872785410262, + 6.061041957137692, + 6.212138359914943, + 6.361154727136652, + 6.50808028388185, + 6.652900746913956, + 6.795598324680785, + 6.936151717314541, + 7.07453611663182, + 7.210723206133611, + 7.344681161005296, + 7.476350724079777, + 7.6056840196598845, + 7.732699751596999, + 7.857410805635951, + 7.9798228549524435, + 8.099934360153055, + 8.217736569275237, + 8.333213517787309, + 8.446342028588468, + 8.55709171200878, + 8.665424965809189, + 8.771296975181507, + 8.874655712748417, + 8.975443593158214, + 9.073661898850656, + 9.169387060799691, + 9.262688525057053, + 9.353623128922314, + 9.442235100942883, + 9.52855606091401, + 9.612605019878778, + 9.694388380128117, + 9.773899935200793, + 9.851120869883406, + 9.9260197602104, + 9.998552573464055, + 10.068663641574643, + 10.136479415998386, + 10.202119293215837, + 10.265582739596592, + 10.32687664299534, + 10.386015312751848, + 10.443020479690974, + 10.49792129612266, + 10.550754335841937, + 10.601563594128917, + 10.650400487748803, + 10.697323854951879, + 10.74239995547352, + 10.785702071972553, + 10.827258548203995, + 10.867068837028187, + 10.905150659630374, + 10.941524110862662, + 10.976211659244019, + 11.009238146960268, + 11.040630789864103, + 11.070419177475072, + 11.098635272979589, + 11.125313413230925, + 11.150490308749216, + 11.174205043721459, + 11.19648876304176, + 11.217279914415831, + 11.23656242412488, + 11.254342447726987, + 11.270629736804947, + 11.28543763896628, + 11.298783097843222, + 11.310686653092723, + 11.32117244039646, + 11.330268191460817, + 11.338005234016904, + 11.34441849182055, + 11.349546484652297, + 11.353441754996625, + 11.35616148865276, + 11.357719068368699, + 11.358126536736089, + 11.357396843168235, + 11.355543843900099, + 11.352582301988297, + 11.348527887311107, + 11.343397176568462, + 11.337207653281952, + 11.329977707794827, + 11.321704660920405, + 11.312354314344036, + 11.301922965750713, + 11.290403311836899, + 11.277783382434315, + 11.26404654050992, + 11.249171482165936, + 11.233132236639825, + 11.215898166304305, + 11.19743396666734, + 11.177678861559363, + 11.156540067957518, + 11.134023021813956, + 11.11012918189388, + 11.084846780990143, + 11.05815082592324, + 11.03000309754131, + 11.00035215072014, + 10.969133314363155, + 10.936268691401429, + 10.901667158793678, + 10.865224367526263, + 10.826822742613192, + 10.786331483096115, + 10.74360895875499, + 10.698601492235799, + 10.651303047964893, + 10.601678243046502, + 10.549677020828101, + 10.495234650900425, + 10.438271729097455, + 10.378694177496422, + 10.31639324441781, + 10.251245504425356, + 10.183112858326046, + 10.111842533170115, + 10.037267082251057, + 9.959205894705523, + 9.877581137899316, + 9.79237896544146, + 9.703547674922588, + 9.611023665983495, + 9.514731440315144, + 9.414583601658641, + 9.310480855805265, + 9.202312010596453, + 9.08995397592379, + 8.973271763729034, + 8.852118488004091, + 8.726335364791039, + 8.595787291013197, + 8.460502957393023, + 8.320439389581793, + 8.175534605633603, + 8.025722108093406, + 7.870930883996998, + 7.711085404871009, + 7.546105626732926, + 7.375906990091082, + 7.200400419944639, + 7.019492325783618, + 6.8330846015888875, + 6.641074625832142, + 6.443410629542258, + 6.240225395969214, + 6.03153690892241, + 5.8173414981922855, + 5.597626847082848, + 5.3723719924117175, + 5.141547324510075, + 4.905114587222707, + 4.663026877907989, + 4.415228647437864, + 4.161655696607112, + 3.9022546228863275, + 3.6370188467518987, + 3.365949402304829, + 3.08904707405606, + 2.806312396926447, + 2.5177456562468095, + 2.2233468877578764, + 1.923115877610332, + 1.6170524149095176, + 1.3051749454539563, + 0.9875079465076095, + 0.6640724603393158, + 0.3348934901354721, + -2.220446049250313E-16 + ], + "showscale": true, + "size": 3 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0, + 0.0010983589941245442, + 0.00427619745063529, + 0.009365653406349208, + 0.016205620162965298, + 0.02463844175531675, + 0.034508742586064935, + 0.04566244978621435, + 0.057946701262729224, + 0.0712098456985336, + 0.08530144255251122, + 0.1000706867945729, + 0.11536754138326388, + 0.13105196805892474, + 0.14698472581081257, + 0.16302667989274092, + 0.17903880182307982, + 0.19488216938475592, + 0.21042010093238206, + 0.2255303918040158, + 0.2400941529618775, + 0.2539941125955256, + 0.26711510792876336, + 0.27934408521963855, + 0.29057009976044373, + 0.300685743957656, + 0.309593655450644, + 0.31719802747772946, + 0.3234076468096852, + 0.32813661323363996, + 0.3313043395530784, + 0.33283555158784134, + 0.3326602881741255, + 0.33071390116448374, + 0.3269370554278247, + 0.3212757288494131, + 0.3136930280801147, + 0.3041588254540771, + 0.29262071076803087, + 0.27903290120181323, + 0.26335685051262864, + 0.2455612490350489, + 0.22562202368101322, + 0.20352233793982843, + 0.1792525918781689, + 0.1528104221400761, + 0.12420070194695887, + 0.09343554109759394, + 0.060534285968125434, + 0.025520046231359828, + -0.011616497219535962, + -0.050888014639398266, + -0.092298715172146, + -0.1358469561082469, + -0.18152524288471686, + -0.22932022908511934, + -0.27921271643956597, + -0.3311776548247172, + -0.38518414226378156, + -0.44119542492651537, + -0.49916889712922247, + -0.5590561013347564, + -0.6208029971066803, + -0.6844038687076884, + -0.7498500581699944, + -0.8170979263286259, + -0.8861037874492588, + -0.9568239092282187, + -1.0292145127924766, + -1.1032317726996548, + -1.1788318169380245, + -1.2559707269265017, + -1.3346045375146547, + -1.4146892369826987, + -1.4961807670414977, + -1.5790349940802104, + -1.663201610016293, + -1.7486203851470916, + -1.8352310774273644, + -1.9229738365440703, + -2.0117892039163756, + -2.1016181126956495, + -2.1924018877654654, + -2.284082245741601, + -2.3766012949720365, + -2.469901535536957, + -2.5639258592487546, + -2.6586175496520195, + -2.7539172698514673, + -2.849738649150951, + -2.9460074195778514, + -3.0426525381277245, + -3.139600594522026, + -3.2367758112081173, + -3.334100043359261, + -3.4314927788746195, + -3.5288711383792597, + -3.6261498752241508, + -3.7232413754861624, + -3.82005565796807, + -3.9165003741985442, + -4.012479933302324, + -4.107895462246632, + -4.202649239569367, + -4.296642196632203, + -4.38977375741116, + -4.481941838496603, + -4.573042849093244, + -4.662971691020136, + -4.751621758710683, + -4.838884939212635, + -4.924651612188081, + -5.008812097338238, + -5.091257117468792, + -5.171874219913148, + -5.250550441340474, + -5.3271723824195005, + -5.401626207818531, + -5.473797646205435, + -5.543571990247649, + -5.610834096612183, + -5.675468385965606, + -5.737369241314975, + -5.796446642679979, + -5.85256219189122, + -5.9055778527653295, + -5.955360459130243, + -6.001781714825189, + -6.044718193700705, + -6.0840513396186235, + -6.1196674664520785, + -6.151457758085507, + -6.179318268414645, + -6.2031499213465295, + -6.222858510799498, + -6.238354700703189, + -6.24955437206703, + -6.256366374568064, + -6.258646894373072, + -6.256251275277718, + -6.249047374496844, + -6.236915562664473, + -6.219748723833799, + -6.197452255477199, + -6.169944068486224, + -6.137154587171603, + -6.099026749263243, + -6.055516005910229, + -6.006590321680821, + -5.952229825670214, + -5.892380072941787, + -5.826923824892067, + -5.755756224847247, + -5.678789891904708, + -5.595954920933018, + -5.50719888257192, + -5.412486823232352, + -5.311801265096435, + -5.205142206117466, + -5.092527120019939, + -4.973990956299522, + -4.849586140223074, + -4.719354475843899, + -4.583208148390372, + -4.441112388067696, + -4.29305394005681, + -4.13903018566233, + -3.979049142312538, + -3.813129463559366, + -3.6413004390784236, + -3.463601994668987, + -3.2800846922539804, + -3.090809729880008, + -2.8958489417173405, + -2.695284798059895, + -2.4891579829150476, + -2.277343750099553, + -2.0598344687027206, + -1.8366472712998312, + -1.6078115870720198, + -1.3733691418063179, + -1.133373957895606, + -0.8878923543386541, + -0.6370029467401079, + -0.3807966473104645, + -0.11937639690606999, + 0.14717296430808147, + 0.41881412230523896, + 0.6955117076484528, + 0.9772268376846887, + 1.2639171165448508, + 1.5555366351437314, + 1.8520359711800665, + 2.1533621891364882, + 2.4594592205203734, + 2.770297047266685, + 3.0858540420102143, + 3.4060987168050487, + 3.731000097941278, + 4.060527725945029 + ], + "y": [ + 0, + 0.8009254237823245, + 1.5960792856623531, + 2.385475597072574, + 3.169107926495013, + 3.9469627091118635, + 4.719064738594156, + 5.485428489174774, + 6.246054659859775, + 7.000930174428392, + 7.750028181433031, + 8.493321800844054, + 9.230848303648116, + 9.962640419188402, + 10.688721135726254, + 11.409106100281491, + 12.12380361863239, + 12.832814655315694, + 13.536141526069686, + 14.233827708840856, + 14.92590791962178, + 15.612412172842994, + 16.29336837171016, + 16.968802308204065, + 17.638737663080626, + 18.303197772284673, + 18.96221687393142, + 19.615831094811565, + 20.264078251103, + 20.906998493476177, + 21.54463430709409, + 22.177030511612276, + 22.804234261178824, + 23.42629504443437, + 24.043264684512103, + 24.65519733903775, + 25.262152267131423, + 25.864181722662728, + 26.461325266599058, + 27.05362363907989, + 27.641118986264335, + 28.223854860331127, + 28.801876219478636, + 29.375229427924843, + 29.943962255907365, + 30.508123879683442, + 31.067764881529943, + 31.622937249743355, + 32.173694378639794, + 32.72009218738413, + 33.26218010702771, + 33.799977667389044, + 34.3335034093641, + 34.8627786915446, + 35.387827690218025, + 35.90867739936762, + 36.42535763067235, + 36.93790101350698, + 37.446342994942015, + 37.95072183974371, + 38.45107863037406, + 38.94745726699086, + 39.43990427792595, + 39.928431407790036, + 40.41305297902097, + 40.893806661689624, + 41.37072840442675, + 41.84385243442295, + 42.31321125742866, + 42.7788356577542, + 43.24075469826971, + 43.6989957204052, + 44.15358434415054, + 44.60454446805543, + 45.05189826922945, + 45.49566630651224, + 45.93588056745503, + 46.3725796919581, + 46.80579821530137, + 47.235570987770096, + 47.661933174654884, + 48.08492025625169, + 48.50456802786183, + 48.92091259979195, + 49.33399039735404, + 49.74383816086546, + 50.15049294564891, + 50.553992122032405, + 50.954374617417564, + 51.35169287353763, + 51.74599726604182, + 52.13733557974711, + 52.525754923163895, + 52.91130172849604, + 53.294021751640855, + 53.67396007218908, + 54.051161093424916, + 54.425668542325994, + 54.79752546956339, + 55.16677424950164, + 55.53345658019872, + 55.89760865798415, + 56.25925895103407, + 56.6184500510062, + 56.97522530669493, + 57.32962796938487, + 57.681701192850845, + 58.03148803335787, + 58.37903144966116, + 58.724374303006165, + 59.06755935712853, + 59.40862927825411, + 59.74762542292647, + 60.084589296713986, + 60.41956528121868, + 60.75259695310655, + 61.083727002184034, + 61.412997231398116, + 61.74044855683622, + 62.06612100772625, + 62.390053726436626, + 62.712284968476226, + 63.03284998497459, + 63.351776987950316, + 63.66909935696007, + 63.984848949806604, + 64.29905533513912, + 64.61174579245314, + 64.92294531209069, + 65.23267659524016, + 65.54096005393635, + 65.84781381106046, + 66.15325370034014, + 66.45729326634941, + 66.7599437645087, + 67.06121416108488, + 67.36111123046317, + 67.6596393484896, + 67.95679201680211, + 68.25255805236169, + 68.54692390182664, + 68.83987364155264, + 69.1313889775927, + 69.4214492456972, + 69.71003141131382, + 69.99711006958765, + 70.28265744536107, + 70.56664339317383, + 70.84903539726304, + 71.12979877804013, + 71.4089013037207, + 71.68628709809721, + 71.9618920961067, + 72.23565387870656, + 72.50751167287468, + 72.77740635160949, + 73.0452804339298, + 73.31107808487492, + 73.57474511550464, + 73.8362289828992, + 74.09547879015935, + 74.35244528640624, + 74.60707597251024, + 74.85929376642193, + 75.10903033701548, + 75.35622269709795, + 75.60081139525005, + 75.84274051582622, + 76.08195767895464, + 76.31841404053715, + 76.55206429224933, + 76.78286666154047, + 77.01078291163358, + 77.23577834152536, + 77.45782178598624, + 77.67686626514661, + 77.89279917306106, + 78.10554900769742, + 78.31505799671363, + 78.52127773038842, + 78.72416916162125, + 78.9237026059323, + 79.11985774146251, + 79.31262360897355, + 79.50199861184787, + 79.68799051389001, + 79.87060499112509, + 80.04982419888624, + 80.22562876649116, + 80.39800223908368, + 80.56693107763384, + 80.73240465893781, + 80.89441527561794, + 81.05295813612273, + 81.2080312693581, + 81.35962836017158, + 81.50774318088123, + 81.65237333039319, + 81.79351749445702, + 81.9311754456657 + ] + } + ], + "frames": [ + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0 + ], + "y": [ + 0 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.0010983589941245442 + ], + "y": [ + 0.8009254237823245 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.00427619745063529 + ], + "y": [ + 1.5960792856623531 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.009365653406349208 + ], + "y": [ + 2.385475597072574 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.016205620162965298 + ], + "y": [ + 3.169107926495013 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.02463844175531675 + ], + "y": [ + 3.9469627091118635 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.034508742586064935 + ], + "y": [ + 4.719064738594156 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.04566244978621435 + ], + "y": [ + 5.485428489174774 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.057946701262729224 + ], + "y": [ + 6.246054659859775 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.0712098456985336 + ], + "y": [ + 7.000930174428392 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.08530144255251122 + ], + "y": [ + 7.750028181433031 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.1000706867945729 + ], + "y": [ + 8.493321800844054 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.11536754138326388 + ], + "y": [ + 9.230848303648116 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.13105196805892474 + ], + "y": [ + 9.962640419188402 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.14698472581081257 + ], + "y": [ + 10.688721135726254 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.16302667989274092 + ], + "y": [ + 11.409106100281491 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.17903880182307982 + ], + "y": [ + 12.12380361863239 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.19488216938475592 + ], + "y": [ + 12.832814655315694 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.21042010093238206 + ], + "y": [ + 13.536141526069686 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.2255303918040158 + ], + "y": [ + 14.233827708840856 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.2400941529618775 + ], + "y": [ + 14.92590791962178 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.2539941125955256 + ], + "y": [ + 15.612412172842994 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.26711510792876336 + ], + "y": [ + 16.29336837171016 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.27934408521963855 + ], + "y": [ + 16.968802308204065 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.29057009976044373 + ], + "y": [ + 17.638737663080626 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.300685743957656 + ], + "y": [ + 18.303197772284673 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.309593655450644 + ], + "y": [ + 18.96221687393142 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.31719802747772946 + ], + "y": [ + 19.615831094811565 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.3234076468096852 + ], + "y": [ + 20.264078251103 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.32813661323363996 + ], + "y": [ + 20.906998493476177 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.3313043395530784 + ], + "y": [ + 21.54463430709409 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.33283555158784134 + ], + "y": [ + 22.177030511612276 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.3326602881741255 + ], + "y": [ + 22.804234261178824 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.33071390116448374 + ], + "y": [ + 23.42629504443437 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.3269370554278247 + ], + "y": [ + 24.043264684512103 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.3212757288494131 + ], + "y": [ + 24.65519733903775 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.3136930280801147 + ], + "y": [ + 25.262152267131423 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.3041588254540771 + ], + "y": [ + 25.864181722662728 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.29262071076803087 + ], + "y": [ + 26.461325266599058 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.27903290120181323 + ], + "y": [ + 27.05362363907989 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.26335685051262864 + ], + "y": [ + 27.641118986264335 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.2455612490350489 + ], + "y": [ + 28.223854860331127 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.22562202368101322 + ], + "y": [ + 28.801876219478636 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.20352233793982843 + ], + "y": [ + 29.375229427924843 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.1792525918781689 + ], + "y": [ + 29.943962255907365 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.1528104221400761 + ], + "y": [ + 30.508123879683442 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.12420070194695887 + ], + "y": [ + 31.067764881529943 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.09343554109759394 + ], + "y": [ + 31.622937249743355 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.060534285968125434 + ], + "y": [ + 32.173694378639794 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.025520046231359828 + ], + "y": [ + 32.72009218738413 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.011616497219535962 + ], + "y": [ + 33.26218010702771 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.050888014639398266 + ], + "y": [ + 33.799977667389044 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.092298715172146 + ], + "y": [ + 34.3335034093641 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.1358469561082469 + ], + "y": [ + 34.8627786915446 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.18152524288471686 + ], + "y": [ + 35.387827690218025 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.22932022908511934 + ], + "y": [ + 35.90867739936762 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.27921271643956597 + ], + "y": [ + 36.42535763067235 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.3311776548247172 + ], + "y": [ + 36.93790101350698 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.38518414226378156 + ], + "y": [ + 37.446342994942015 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.44119542492651537 + ], + "y": [ + 37.95072183974371 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.49916889712922247 + ], + "y": [ + 38.45107863037406 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.5590561013347564 + ], + "y": [ + 38.94745726699086 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.6208029971066803 + ], + "y": [ + 39.43990427792595 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.6844038687076884 + ], + "y": [ + 39.928431407790036 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.7498500581699944 + ], + "y": [ + 40.41305297902097 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.8170979263286259 + ], + "y": [ + 40.893806661689624 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.8861037874492588 + ], + "y": [ + 41.37072840442675 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.9568239092282187 + ], + "y": [ + 41.84385243442295 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -1.0292145127924766 + ], + "y": [ + 42.31321125742866 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -1.1032317726996548 + ], + "y": [ + 42.7788356577542 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -1.1788318169380245 + ], + "y": [ + 43.24075469826971 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -1.2559707269265017 + ], + "y": [ + 43.6989957204052 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -1.3346045375146547 + ], + "y": [ + 44.15358434415054 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -1.4146892369826987 + ], + "y": [ + 44.60454446805543 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -1.4961807670414977 + ], + "y": [ + 45.05189826922945 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -1.5790349940802104 + ], + "y": [ + 45.49566630651224 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -1.663201610016293 + ], + "y": [ + 45.93588056745503 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -1.7486203851470916 + ], + "y": [ + 46.3725796919581 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -1.8352310774273644 + ], + "y": [ + 46.80579821530137 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -1.9229738365440703 + ], + "y": [ + 47.235570987770096 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -2.0117892039163756 + ], + "y": [ + 47.661933174654884 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -2.1016181126956495 + ], + "y": [ + 48.08492025625169 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -2.1924018877654654 + ], + "y": [ + 48.50456802786183 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -2.284082245741601 + ], + "y": [ + 48.92091259979195 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -2.3766012949720365 + ], + "y": [ + 49.33399039735404 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -2.469901535536957 + ], + "y": [ + 49.74383816086546 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -2.5639258592487546 + ], + "y": [ + 50.15049294564891 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -2.6586175496520195 + ], + "y": [ + 50.553992122032405 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -2.7539172698514673 + ], + "y": [ + 50.954374617417564 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -2.849738649150951 + ], + "y": [ + 51.35169287353763 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -2.9460074195778514 + ], + "y": [ + 51.74599726604182 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -3.0426525381277245 + ], + "y": [ + 52.13733557974711 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -3.139600594522026 + ], + "y": [ + 52.525754923163895 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -3.2367758112081173 + ], + "y": [ + 52.91130172849604 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -3.334100043359261 + ], + "y": [ + 53.294021751640855 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -3.4314927788746195 + ], + "y": [ + 53.67396007218908 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -3.5288711383792597 + ], + "y": [ + 54.051161093424916 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -3.6261498752241508 + ], + "y": [ + 54.425668542325994 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -3.7232413754861624 + ], + "y": [ + 54.79752546956339 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -3.82005565796807 + ], + "y": [ + 55.16677424950164 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -3.9165003741985442 + ], + "y": [ + 55.53345658019872 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -4.012479933302324 + ], + "y": [ + 55.89760865798415 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -4.107895462246632 + ], + "y": [ + 56.25925895103407 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -4.202649239569367 + ], + "y": [ + 56.6184500510062 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -4.296642196632203 + ], + "y": [ + 56.97522530669493 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -4.38977375741116 + ], + "y": [ + 57.32962796938487 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -4.481941838496603 + ], + "y": [ + 57.681701192850845 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -4.573042849093244 + ], + "y": [ + 58.03148803335787 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -4.662971691020136 + ], + "y": [ + 58.37903144966116 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -4.751621758710683 + ], + "y": [ + 58.724374303006165 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -4.838884939212635 + ], + "y": [ + 59.06755935712853 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -4.924651612188081 + ], + "y": [ + 59.40862927825411 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -5.008812097338238 + ], + "y": [ + 59.74762542292647 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -5.091257117468792 + ], + "y": [ + 60.084589296713986 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -5.171874219913148 + ], + "y": [ + 60.41956528121868 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -5.250550441340474 + ], + "y": [ + 60.75259695310655 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -5.3271723824195005 + ], + "y": [ + 61.083727002184034 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -5.401626207818531 + ], + "y": [ + 61.412997231398116 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -5.473797646205435 + ], + "y": [ + 61.74044855683622 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -5.543571990247649 + ], + "y": [ + 62.06612100772625 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -5.610834096612183 + ], + "y": [ + 62.390053726436626 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -5.675468385965606 + ], + "y": [ + 62.712284968476226 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -5.737369241314975 + ], + "y": [ + 63.03284998497459 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -5.796446642679979 + ], + "y": [ + 63.351776987950316 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -5.85256219189122 + ], + "y": [ + 63.66909935696007 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -5.9055778527653295 + ], + "y": [ + 63.984848949806604 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -5.955360459130243 + ], + "y": [ + 64.29905533513912 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -6.001781714825189 + ], + "y": [ + 64.61174579245314 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -6.044718193700705 + ], + "y": [ + 64.92294531209069 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -6.0840513396186235 + ], + "y": [ + 65.23267659524016 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -6.1196674664520785 + ], + "y": [ + 65.54096005393635 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -6.151457758085507 + ], + "y": [ + 65.84781381106046 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -6.179318268414645 + ], + "y": [ + 66.15325370034014 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -6.2031499213465295 + ], + "y": [ + 66.45729326634941 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -6.222858510799498 + ], + "y": [ + 66.7599437645087 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -6.238354700703189 + ], + "y": [ + 67.06121416108488 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -6.24955437206703 + ], + "y": [ + 67.36111123046317 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -6.256366374568064 + ], + "y": [ + 67.6596393484896 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -6.258646894373072 + ], + "y": [ + 67.95679201680211 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -6.256251275277718 + ], + "y": [ + 68.25255805236169 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -6.249047374496844 + ], + "y": [ + 68.54692390182664 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -6.236915562664473 + ], + "y": [ + 68.83987364155264 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -6.219748723833799 + ], + "y": [ + 69.1313889775927 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -6.197452255477199 + ], + "y": [ + 69.4214492456972 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -6.169944068486224 + ], + "y": [ + 69.71003141131382 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -6.137154587171603 + ], + "y": [ + 69.99711006958765 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -6.099026749263243 + ], + "y": [ + 70.28265744536107 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -6.055516005910229 + ], + "y": [ + 70.56664339317383 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -6.006590321680821 + ], + "y": [ + 70.84903539726304 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -5.952229825670214 + ], + "y": [ + 71.12979877804013 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -5.892380072941787 + ], + "y": [ + 71.4089013037207 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -5.826923824892067 + ], + "y": [ + 71.68628709809721 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -5.755756224847247 + ], + "y": [ + 71.9618920961067 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -5.678789891904708 + ], + "y": [ + 72.23565387870656 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -5.595954920933018 + ], + "y": [ + 72.50751167287468 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -5.50719888257192 + ], + "y": [ + 72.77740635160949 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -5.412486823232352 + ], + "y": [ + 73.0452804339298 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -5.311801265096435 + ], + "y": [ + 73.31107808487492 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -5.205142206117466 + ], + "y": [ + 73.57474511550464 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -5.092527120019939 + ], + "y": [ + 73.8362289828992 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -4.973990956299522 + ], + "y": [ + 74.09547879015935 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -4.849586140223074 + ], + "y": [ + 74.35244528640624 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -4.719354475843899 + ], + "y": [ + 74.60707597251024 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -4.583208148390372 + ], + "y": [ + 74.85929376642193 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -4.441112388067696 + ], + "y": [ + 75.10903033701548 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -4.29305394005681 + ], + "y": [ + 75.35622269709795 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -4.13903018566233 + ], + "y": [ + 75.60081139525005 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -3.979049142312538 + ], + "y": [ + 75.84274051582622 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -3.813129463559366 + ], + "y": [ + 76.08195767895464 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -3.6413004390784236 + ], + "y": [ + 76.31841404053715 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -3.463601994668987 + ], + "y": [ + 76.55206429224933 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -3.2800846922539804 + ], + "y": [ + 76.78286666154047 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -3.090809729880008 + ], + "y": [ + 77.01078291163358 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -2.8958489417173405 + ], + "y": [ + 77.23577834152536 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -2.695284798059895 + ], + "y": [ + 77.45782178598624 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -2.4891579829150476 + ], + "y": [ + 77.67686626514661 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -2.277343750099553 + ], + "y": [ + 77.89279917306106 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -2.0598344687027206 + ], + "y": [ + 78.10554900769742 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -1.8366472712998312 + ], + "y": [ + 78.31505799671363 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -1.6078115870720198 + ], + "y": [ + 78.52127773038842 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -1.3733691418063179 + ], + "y": [ + 78.72416916162125 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -1.133373957895606 + ], + "y": [ + 78.9237026059323 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.8878923543386541 + ], + "y": [ + 79.11985774146251 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.6370029467401079 + ], + "y": [ + 79.31262360897355 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.3807966473104645 + ], + "y": [ + 79.50199861184787 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.11937639690606999 + ], + "y": [ + 79.68799051389001 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.14717296430808147 + ], + "y": [ + 79.87060499112509 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.41881412230523896 + ], + "y": [ + 80.04982419888624 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.6955117076484528 + ], + "y": [ + 80.22562876649116 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.9772268376846887 + ], + "y": [ + 80.39800223908368 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 1.2639171165448508 + ], + "y": [ + 80.56693107763384 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 1.5555366351437314 + ], + "y": [ + 80.73240465893781 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 1.8520359711800665 + ], + "y": [ + 80.89441527561794 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 2.1533621891364882 + ], + "y": [ + 81.05295813612273 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 2.4594592205203734 + ], + "y": [ + 81.2080312693581 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 2.770297047266685 + ], + "y": [ + 81.35962836017158 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 3.0858540420102143 + ], + "y": [ + 81.50774318088123 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 3.4060987168050487 + ], + "y": [ + 81.65237333039319 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 3.731000097941278 + ], + "y": [ + 81.79351749445702 + ] + } + ] + }, + { + "data": [ + { + "marker": { + "color": "red", + "size": 10 + }, + "mode": "markers", + "type": "scatter", + "x": [ + 4.060527725945029 + ], + "y": [ + 81.9311754456657 + ] + } + ] + } + ], + "layout": { + "hovermode": "closest", + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "rgb(36,36,36)" + }, + "error_y": { + "color": "rgb(36,36,36)" + }, + "marker": { + "line": { + "color": "rgb(234,234,242)", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "rgb(234,234,242)", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "rgb(36,36,36)", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "rgb(36,36,36)" + }, + "baxis": { + "endlinecolor": "rgb(36,36,36)", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "rgb(36,36,36)" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "colorscale": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "colorscale": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ], + "type": "heatmap" + } + ], + "heatmapgl": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "colorscale": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ], + "type": "heatmapgl" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "colorscale": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "colorscale": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scattergl" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "colorscale": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "rgb(231,231,240)" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "rgb(183,183,191)" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "rgb(67,103,167)" + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "colorscale": { + "sequential": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ], + "sequentialminus": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ] + }, + "colorway": [ + "rgb(76,114,176)", + "rgb(221,132,82)", + "rgb(85,168,104)", + "rgb(196,78,82)", + "rgb(129,114,179)", + "rgb(147,120,96)", + "rgb(218,139,195)", + "rgb(140,140,140)", + "rgb(204,185,116)", + "rgb(100,181,205)" + ], + "font": { + "color": "rgb(36,36,36)" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "rgb(234,234,242)", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "paper_bgcolor": "white", + "plot_bgcolor": "rgb(234,234,242)", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "showgrid": true, + "ticks": "" + }, + "bgcolor": "rgb(234,234,242)", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "showgrid": true, + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "rgb(234,234,242)", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "showgrid": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "rgb(234,234,242)", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "showgrid": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "rgb(234,234,242)", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "showgrid": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "fillcolor": "rgb(67,103,167)", + "line": { + "width": 0 + }, + "opacity": 0.5 + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "showgrid": true, + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "showgrid": true, + "ticks": "" + }, + "bgcolor": "rgb(234,234,242)", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "showgrid": true, + "ticks": "" + } + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "showgrid": true, + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white" + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "showgrid": true, + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white" + } + } + }, + "title": { + "text": "Flight Path" + }, + "updatemenus": [ + { + "buttons": [ + { + "args": [ + null, + { + "frame": { + "duration": 30, + "redraw": true + }, + "fromcurrent": true + } + ], + "label": "Play", + "method": "animate" + }, + { + "args": [ + [ + null + ], + { + "frame": { + "duration": 0, + "redraw": false + }, + "mode": "immediate", + "transition": { + "duration": 0 + } + } + ], + "label": "Pause", + "method": "animate" + } + ], + "showactive": false, + "type": "buttons", + "x": 0.05, + "y": 0.05 + } + ], + "xaxis": { + "autorange": "reversed", + "range": [ + -7.758646894373072, + 5.560527725945029 + ], + "zeroline": false + }, + "yaxis": { + "autorange": false, + "range": [ + -1.5, + 83.4311754456657 + ], + "scaleanchor": "x", + "scaleratio": 1, + "zeroline": false + } + } + }, + "text/html": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import plotly.graph_objects as go\n", + "\n", + "import numpy as np\n", + "\n", + "xm = np.min(x) - 1.5\n", + "xM = np.max(x) + 1.5\n", + "ym = np.min(y) - 1.5\n", + "yM = np.max(y) + 1.5\n", + "N = len(x)\n", + "s = np.arange(1,N)\n", + "\n", + "\n", + "# Create figure\n", + "fig = go.Figure(\n", + " data=[go.Scatter(x=x, y=y,\n", + " mode=\"lines\",\n", + " line=dict(width=1, color='black')),\n", + " \n", + " go.Scatter(x=x, y=y,\n", + " mode=\"markers\",\n", + " marker=dict(color=z, size=3, showscale=True),),\n", + " ],\n", + " layout=go.Layout(\n", + " xaxis=dict(range=[xm, xM], autorange=False, zeroline=False),\n", + " yaxis=dict(range=[ym, yM], autorange=False, zeroline=False),\n", + " title_text=\"Flight Path\", hovermode=\"closest\",\n", + " updatemenus=[dict(\n", + " type=\"buttons\",\n", + " buttons=[\n", + " dict(\n", + " label=\"Play\",\n", + " method=\"animate\",\n", + " args=[None, {\"frame\": {\"duration\": 30, \"redraw\": True}, \"fromcurrent\": True}]\n", + " ),\n", + " dict(\n", + " label=\"Pause\",\n", + " method=\"animate\",\n", + " args=[[None], {\"frame\": {\"duration\": 0, \"redraw\": False}, \"mode\": \"immediate\", \"transition\": {\"duration\": 0}}]\n", + " )\n", + " ],\n", + " showactive=False,\n", + " x=0.05,\n", + " y=0.05\n", + " )]),\n", + " frames=[go.Frame(\n", + " data=[go.Scatter(\n", + " x=[x[k]],\n", + " y=[y[k]],\n", + " mode=\"markers\",\n", + " marker=dict(color=\"red\", size=10))])\n", + "\n", + " for k in range(N)]\n", + ")\n", + "if reverse:\n", + " fig.update_xaxes(autorange=\"reversed\") \n", + "fig.update_yaxes(\n", + " scaleanchor=\"x\",\n", + " scaleratio=1,\n", + " )\n", + "\n", + "fig.show()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6fabcd97", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e072cd1b", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "81eef49e", + "metadata": {}, + "outputs": [], + "source": [ + "import plotly.io as pio\n", + "pio.renderers.default = 'plotly'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8c91b75f", + "metadata": {}, + "outputs": [], + "source": [ + "True" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "dfb292c7", + "metadata": {}, + "outputs": [], + "source": [ + "pio.renderers.default = 'browser'" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "b36b9877", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "marker": { + "color": "orange", + "line": { + "width": 1 + } + }, + "name": "Value", + "type": "bar", + "x": [ + "Category A" + ], + "y": [ + 18 + ] + }, + { + "marker": { + "color": "blue", + "size": 8, + "symbol": "triangle-up" + }, + "mode": "markers", + "name": "Minimum", + "type": "scatter", + "x": [ + "Category A" + ], + "y": [ + 10 + ] + }, + { + "marker": { + "color": "red", + "size": 8, + "symbol": "triangle-down" + }, + "mode": "markers", + "name": "Maximum", + "type": "scatter", + "x": [ + "Category A" + ], + "y": [ + 25 + ] + } + ], + "layout": { + "barmode": "group", + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "rgb(36,36,36)" + }, + "error_y": { + "color": "rgb(36,36,36)" + }, + "marker": { + "line": { + "color": "rgb(234,234,242)", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "rgb(234,234,242)", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "rgb(36,36,36)", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "rgb(36,36,36)" + }, + "baxis": { + "endlinecolor": "rgb(36,36,36)", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "rgb(36,36,36)" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "colorscale": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "colorscale": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ], + "type": "heatmap" + } + ], + "heatmapgl": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "colorscale": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ], + "type": "heatmapgl" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "colorscale": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "colorscale": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scattergl" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "colorscale": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "rgb(231,231,240)" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "rgb(183,183,191)" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "rgb(67,103,167)" + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "colorscale": { + "sequential": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ], + "sequentialminus": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ] + }, + "colorway": [ + "rgb(76,114,176)", + "rgb(221,132,82)", + "rgb(85,168,104)", + "rgb(196,78,82)", + "rgb(129,114,179)", + "rgb(147,120,96)", + "rgb(218,139,195)", + "rgb(140,140,140)", + "rgb(204,185,116)", + "rgb(100,181,205)" + ], + "font": { + "color": "rgb(36,36,36)" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "rgb(234,234,242)", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "paper_bgcolor": "white", + "plot_bgcolor": "rgb(234,234,242)", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "showgrid": true, + "ticks": "" + }, + "bgcolor": "rgb(234,234,242)", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "showgrid": true, + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "rgb(234,234,242)", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "showgrid": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "rgb(234,234,242)", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "showgrid": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "rgb(234,234,242)", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "showgrid": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "fillcolor": "rgb(67,103,167)", + "line": { + "width": 0 + }, + "opacity": 0.5 + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "showgrid": true, + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "showgrid": true, + "ticks": "" + }, + "bgcolor": "rgb(234,234,242)", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "showgrid": true, + "ticks": "" + } + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "showgrid": true, + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white" + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "showgrid": true, + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white" + } + } + }, + "title": { + "text": "Value Between Minimum and Maximum" + }, + "width": 400, + "yaxis": { + "title": { + "text": "Lateral Deviance" + } + } + } + }, + "text/html": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import plotly.graph_objs as go\n", + "\n", + "# Sample data for Category A\n", + "y_min = 10 # Minimum value\n", + "y_max = 25 # Maximum value\n", + "y_value = 18 # Actual value\n", + "\n", + "# Create a bar chart trace for actual value\n", + "trace_value = go.Bar(\n", + " x=['Category A'],\n", + " y=[y_value],\n", + " name='Value',\n", + " marker=dict(color='orange', line=dict(width=1)) # Set color of value bar to orange and line width to 1\n", + ")\n", + "\n", + "# Create a scatter trace for the minimum caret (triangle-up)\n", + "trace_min_caret = go.Scatter(\n", + " x=['Category A'],\n", + " y=[y_min],\n", + " mode='markers',\n", + " marker=dict(symbol='triangle-up', size=8, color='blue'),\n", + " name='Minimum'\n", + ")\n", + "\n", + "# Create a scatter trace for the maximum caret (triangle-down)\n", + "trace_max_caret = go.Scatter(\n", + " x=['Category A'],\n", + " y=[y_max],\n", + " mode='markers',\n", + " marker=dict(symbol='triangle-down', size=8, color='red'),\n", + " name='Maximum'\n", + ")\n", + "\n", + "# Create a layout\n", + "layout = go.Layout(\n", + " title='Value Between Minimum and Maximum',\n", + " yaxis=dict(title='Lateral Deviance'),\n", + " barmode='group', # Set the bars to group mode\n", + " width=400 # Set the width of the plot to 400 pixels\n", + ")\n", + "\n", + "# Create a figure object\n", + "fig = go.Figure(data=[trace_value, trace_min_caret, trace_max_caret], layout=layout)\n", + "\n", + "# Show the figure\n", + "fig.show()\n" + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "id": "1dfc862e", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "marker": { + "color": "green", + "line": { + "width": 1 + } + }, + "name": "Value", + "type": "bar", + "x": [ + "Lateral Deviance" + ], + "y": [ + 18 + ] + }, + { + "marker": { + "color": [ + "red", + "red" + ], + "size": 20, + "symbol": [ + "triangle-up", + "triangle-down" + ] + }, + "mode": "markers", + "name": "Carets", + "type": "scatter", + "x": [ + "Lateral Deviance", + "Lateral Deviance" + ], + "y": [ + 10, + 25 + ] + } + ], + "layout": { + "barmode": "group", + "showlegend": false, + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "rgb(36,36,36)" + }, + "error_y": { + "color": "rgb(36,36,36)" + }, + "marker": { + "line": { + "color": "rgb(234,234,242)", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "rgb(234,234,242)", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "rgb(36,36,36)", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "rgb(36,36,36)" + }, + "baxis": { + "endlinecolor": "rgb(36,36,36)", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "rgb(36,36,36)" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "colorscale": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "colorscale": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ], + "type": "heatmap" + } + ], + "heatmapgl": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "colorscale": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ], + "type": "heatmapgl" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "colorscale": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "colorscale": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scattergl" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "colorscale": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "rgb(231,231,240)" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "rgb(183,183,191)" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "rgb(67,103,167)" + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "colorscale": { + "sequential": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ], + "sequentialminus": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ] + }, + "colorway": [ + "rgb(76,114,176)", + "rgb(221,132,82)", + "rgb(85,168,104)", + "rgb(196,78,82)", + "rgb(129,114,179)", + "rgb(147,120,96)", + "rgb(218,139,195)", + "rgb(140,140,140)", + "rgb(204,185,116)", + "rgb(100,181,205)" + ], + "font": { + "color": "rgb(36,36,36)" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "rgb(234,234,242)", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "paper_bgcolor": "white", + "plot_bgcolor": "rgb(234,234,242)", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "showgrid": true, + "ticks": "" + }, + "bgcolor": "rgb(234,234,242)", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "showgrid": true, + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "rgb(234,234,242)", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "showgrid": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "rgb(234,234,242)", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "showgrid": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "rgb(234,234,242)", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "showgrid": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "fillcolor": "rgb(67,103,167)", + "line": { + "width": 0 + }, + "opacity": 0.5 + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "showgrid": true, + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "showgrid": true, + "ticks": "" + }, + "bgcolor": "rgb(234,234,242)", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "showgrid": true, + "ticks": "" + } + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "showgrid": true, + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white" + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "showgrid": true, + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white" + } + } + }, + "title": { + "text": "Value Between Minimum and Maximum" + }, + "width": 200, + "yaxis": { + "title": { + "text": "Value" + } + } + } + }, + "text/html": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import plotly.graph_objs as go\n", + "\n", + "# Sample data for Category A\n", + "y_min = 10 # Minimum value\n", + "y_max = 25 # Maximum value\n", + "y_value = 18 # Actual value\n", + "category = 'Lateral Deviance'\n", + "\n", + "# Create a bar chart trace for actual value\n", + "trace_value = go.Bar(\n", + " x=[category],\n", + " y=[y_value],\n", + " name='Value',\n", + " marker=dict(color='green', line=dict(width=1)) # Set color of value bar to orange and line width to 1\n", + ")\n", + "\n", + "# Create a scatter trace for the minimum and maximum carets\n", + "trace_carets = go.Scatter(\n", + " x=[category, category],\n", + " y=[y_min, y_max],\n", + " mode='markers',\n", + " marker=dict(symbol=['triangle-up', 'triangle-down'], size=20, color=['red', 'red']),\n", + " name='Carets'\n", + ")\n", + "\n", + "# Create a layout\n", + "layout = go.Layout(\n", + " title='Value Between Minimum and Maximum',\n", + " yaxis=dict(title='Value'),\n", + " barmode='group', # Set the bars to group mode\n", + " width=200, # Set the width of the plot to 400 pixels\n", + " showlegend=False\n", + ")\n", + "\n", + "# Create a figure object\n", + "fig = go.Figure(data=[trace_value, trace_carets], layout=layout)\n", + "\n", + "# Show the figure\n", + "fig.show()\n" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "e8de4810", + "metadata": {}, + "outputs": [], + "source": [ + "import plotly.graph_objs as go\n", + "\n", + "def plot_value_between_min_max_trace(category_name, y_min, y_max, y_value, horizontal=False):\n", + " # Create a bar chart trace for actual value\n", + " trace_value = go.Bar(\n", + " x=[category_name] if not horizontal else [y_value],\n", + " y=[y_value] if not horizontal else [category_name],\n", + " orientation='h' if horizontal else 'v',\n", + " name='Value',\n", + " marker=dict(color='orange', line=dict(width=1)) # Set color of value bar to orange and line width to 1\n", + " )\n", + "\n", + " # Create a scatter trace for the minimum and maximum carets\n", + " trace_carets = go.Scatter(\n", + " x=[category_name, category_name] if not horizontal else [y_min, y_max],\n", + " y=[y_min, y_max] if not horizontal else [category_name, category_name],\n", + " mode='markers',\n", + " marker=dict(symbol=['triangle-up', 'triangle-down'], size=20, color=['blue', 'red']),\n", + " name='Carets'\n", + " )\n", + "\n", + " # Combine the traces into a single list\n", + " trace = [trace_value, trace_carets]\n", + "\n", + " return trace\n" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "id": "16032b57", + "metadata": {}, + "outputs": [], + "source": [ + "fig = sp.make_subplots(rows=1, cols=2, subplot_titles=(\"Main plot\", \"Most Recent Value\"))\n", + "# Create the trace for the value between minimum and maximum\n", + "category_name = 'Category A'\n", + "y_min = 10\n", + "y_max = 25\n", + "y_value = 18\n", + "horizontal = False\n", + "trace = plot_value_between_min_max_trace(category_name, y_min, y_max, y_value, horizontal)\n", + "\n", + "# Add the trace to the second column (most recent value)\n", + "for t in trace:\n", + " fig.add_trace(t, row=1, col=1)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "id": "eb0ee2f0", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "marker": { + "color": "orange", + "line": { + "width": 1 + } + }, + "name": "Value", + "orientation": "v", + "type": "bar", + "x": [ + "Category A" + ], + "xaxis": "x", + "y": [ + 18 + ], + "yaxis": "y" + }, + { + "marker": { + "color": [ + "blue", + "red" + ], + "size": 20, + "symbol": [ + "triangle-up", + "triangle-down" + ] + }, + "mode": "markers", + "name": "Carets", + "type": "scatter", + "x": [ + "Category A", + "Category A" + ], + "xaxis": "x", + "y": [ + 10, + 25 + ], + "yaxis": "y" + } + ], + "layout": { + "annotations": [ + { + "font": { + "size": 16 + }, + "showarrow": false, + "text": "Main plot", + "x": 0.225, + "xanchor": "center", + "xref": "paper", + "y": 1, + "yanchor": "bottom", + "yref": "paper" + }, + { + "font": { + "size": 16 + }, + "showarrow": false, + "text": "Most Recent Value", + "x": 0.775, + "xanchor": "center", + "xref": "paper", + "y": 1, + "yanchor": "bottom", + "yref": "paper" + } + ], + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "rgb(36,36,36)" + }, + "error_y": { + "color": "rgb(36,36,36)" + }, + "marker": { + "line": { + "color": "rgb(234,234,242)", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "rgb(234,234,242)", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "rgb(36,36,36)", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "rgb(36,36,36)" + }, + "baxis": { + "endlinecolor": "rgb(36,36,36)", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "rgb(36,36,36)" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "colorscale": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "colorscale": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ], + "type": "heatmap" + } + ], + "heatmapgl": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "colorscale": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ], + "type": "heatmapgl" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "colorscale": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "colorscale": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scattergl" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "colorscale": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "rgb(231,231,240)" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "rgb(183,183,191)" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "rgb(67,103,167)" + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "colorscale": { + "sequential": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ], + "sequentialminus": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ] + }, + "colorway": [ + "rgb(76,114,176)", + "rgb(221,132,82)", + "rgb(85,168,104)", + "rgb(196,78,82)", + "rgb(129,114,179)", + "rgb(147,120,96)", + "rgb(218,139,195)", + "rgb(140,140,140)", + "rgb(204,185,116)", + "rgb(100,181,205)" + ], + "font": { + "color": "rgb(36,36,36)" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "rgb(234,234,242)", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "paper_bgcolor": "white", + "plot_bgcolor": "rgb(234,234,242)", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "showgrid": true, + "ticks": "" + }, + "bgcolor": "rgb(234,234,242)", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "showgrid": true, + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "rgb(234,234,242)", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "showgrid": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "rgb(234,234,242)", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "showgrid": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "rgb(234,234,242)", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "showgrid": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "fillcolor": "rgb(67,103,167)", + "line": { + "width": 0 + }, + "opacity": 0.5 + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "showgrid": true, + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "showgrid": true, + "ticks": "" + }, + "bgcolor": "rgb(234,234,242)", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "showgrid": true, + "ticks": "" + } + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "showgrid": true, + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white" + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "showgrid": true, + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white" + } + } + }, + "xaxis": { + "anchor": "y", + "domain": [ + 0, + 0.45 + ] + }, + "xaxis2": { + "anchor": "y2", + "domain": [ + 0.55, + 1 + ] + }, + "yaxis": { + "anchor": "x", + "domain": [ + 0, + 1 + ] + }, + "yaxis2": { + "anchor": "x2", + "domain": [ + 0, + 1 + ] + } + } + }, + "text/html": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 75, + "id": "52ffb04d", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "mode": "markers+lines", + "name": "Sample Data 1", + "type": "scatter", + "x": [], + "xaxis": "x", + "y": [], + "yaxis": "y" + }, + { + "mode": "markers+lines", + "name": "Sample Data 2", + "type": "scatter", + "x": [], + "xaxis": "x", + "y": [], + "yaxis": "y" + }, + { + "marker": { + "size": 10 + }, + "mode": "markers", + "showlegend": false, + "type": "scatter", + "x": [ + 1 + ], + "xaxis": "x2", + "y": [ + 0 + ], + "yaxis": "y2" + }, + { + "marker": { + "size": 10 + }, + "mode": "markers", + "showlegend": false, + "type": "scatter", + "x": [ + 1 + ], + "xaxis": "x2", + "y": [ + 0 + ], + "yaxis": "y2" + } + ], + "frames": [ + { + "data": [ + { + "mode": "markers+lines", + "name": "Sample Data 1", + "type": "scatter", + "x": [ + 1 + ], + "y": [ + 10 + ] + }, + { + "mode": "markers+lines", + "name": "Sample Data 2", + "type": "scatter", + "x": [ + 1 + ], + "y": [ + 5 + ] + }, + { + "marker": { + "size": 10 + }, + "mode": "markers", + "showlegend": false, + "type": "scatter", + "x": [ + 1 + ], + "y": [ + 10 + ] + }, + { + "marker": { + "size": 10 + }, + "mode": "markers", + "showlegend": false, + "type": "scatter", + "x": [ + 1 + ], + "y": [ + 5 + ] + } + ] + }, + { + "data": [ + { + "mode": "markers+lines", + "name": "Sample Data 1", + "type": "scatter", + "x": [ + 1, + 2 + ], + "y": [ + 10, + 15 + ] + }, + { + "mode": "markers+lines", + "name": "Sample Data 2", + "type": "scatter", + "x": [ + 1, + 2 + ], + "y": [ + 5, + 9 + ] + }, + { + "marker": { + "size": 10 + }, + "mode": "markers", + "showlegend": false, + "type": "scatter", + "x": [ + 1 + ], + "y": [ + 15 + ] + }, + { + "marker": { + "size": 10 + }, + "mode": "markers", + "showlegend": false, + "type": "scatter", + "x": [ + 1 + ], + "y": [ + 9 + ] + } + ] + }, + { + "data": [ + { + "mode": "markers+lines", + "name": "Sample Data 1", + "type": "scatter", + "x": [ + 1, + 2, + 3 + ], + "y": [ + 10, + 15, + 13 + ] + }, + { + "mode": "markers+lines", + "name": "Sample Data 2", + "type": "scatter", + "x": [ + 1, + 2, + 3 + ], + "y": [ + 5, + 9, + 11 + ] + }, + { + "marker": { + "size": 10 + }, + "mode": "markers", + "showlegend": false, + "type": "scatter", + "x": [ + 1 + ], + "y": [ + 13 + ] + }, + { + "marker": { + "size": 10 + }, + "mode": "markers", + "showlegend": false, + "type": "scatter", + "x": [ + 1 + ], + "y": [ + 11 + ] + } + ] + }, + { + "data": [ + { + "mode": "markers+lines", + "name": "Sample Data 1", + "type": "scatter", + "x": [ + 1, + 2, + 3, + 4 + ], + "y": [ + 10, + 15, + 13, + 17 + ] + }, + { + "mode": "markers+lines", + "name": "Sample Data 2", + "type": "scatter", + "x": [ + 1, + 2, + 3, + 4 + ], + "y": [ + 5, + 9, + 11, + 13 + ] + }, + { + "marker": { + "size": 10 + }, + "mode": "markers", + "showlegend": false, + "type": "scatter", + "x": [ + 1 + ], + "y": [ + 17 + ] + }, + { + "marker": { + "size": 10 + }, + "mode": "markers", + "showlegend": false, + "type": "scatter", + "x": [ + 1 + ], + "y": [ + 13 + ] + } + ] + }, + { + "data": [ + { + "mode": "markers+lines", + "name": "Sample Data 1", + "type": "scatter", + "x": [ + 1, + 2, + 3, + 4, + 5 + ], + "y": [ + 10, + 15, + 13, + 17, + 12 + ] + }, + { + "mode": "markers+lines", + "name": "Sample Data 2", + "type": "scatter", + "x": [ + 1, + 2, + 3, + 4, + 5 + ], + "y": [ + 5, + 9, + 11, + 13, + 8 + ] + }, + { + "marker": { + "size": 10 + }, + "mode": "markers", + "showlegend": false, + "type": "scatter", + "x": [ + 1 + ], + "y": [ + 12 + ] + }, + { + "marker": { + "size": 10 + }, + "mode": "markers", + "showlegend": false, + "type": "scatter", + "x": [ + 1 + ], + "y": [ + 8 + ] + } + ] + } + ], + "layout": { + "annotations": [ + { + "font": { + "size": 16 + }, + "showarrow": false, + "text": "Main plot", + "x": 0.225, + "xanchor": "center", + "xref": "paper", + "y": 1, + "yanchor": "bottom", + "yref": "paper" + }, + { + "font": { + "size": 16 + }, + "showarrow": false, + "text": "Most Recent Values", + "x": 0.775, + "xanchor": "center", + "xref": "paper", + "y": 1, + "yanchor": "bottom", + "yref": "paper" + } + ], + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "rgb(36,36,36)" + }, + "error_y": { + "color": "rgb(36,36,36)" + }, + "marker": { + "line": { + "color": "rgb(234,234,242)", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "rgb(234,234,242)", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "rgb(36,36,36)", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "rgb(36,36,36)" + }, + "baxis": { + "endlinecolor": "rgb(36,36,36)", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "rgb(36,36,36)" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "colorscale": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "colorscale": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ], + "type": "heatmap" + } + ], + "heatmapgl": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "colorscale": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ], + "type": "heatmapgl" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "colorscale": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "colorscale": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scattergl" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + }, + "colorscale": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "rgb(231,231,240)" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "rgb(183,183,191)" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "rgb(67,103,167)" + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "tickcolor": "rgb(36,36,36)", + "ticklen": 8, + "ticks": "outside", + "tickwidth": 2 + } + }, + "colorscale": { + "sequential": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ], + "sequentialminus": [ + [ + 0, + "rgb(2,4,25)" + ], + [ + 0.06274509803921569, + "rgb(24,15,41)" + ], + [ + 0.12549019607843137, + "rgb(47,23,57)" + ], + [ + 0.18823529411764706, + "rgb(71,28,72)" + ], + [ + 0.25098039215686274, + "rgb(97,30,82)" + ], + [ + 0.3137254901960784, + "rgb(123,30,89)" + ], + [ + 0.3764705882352941, + "rgb(150,27,91)" + ], + [ + 0.4392156862745098, + "rgb(177,22,88)" + ], + [ + 0.5019607843137255, + "rgb(203,26,79)" + ], + [ + 0.5647058823529412, + "rgb(223,47,67)" + ], + [ + 0.6274509803921569, + "rgb(236,76,61)" + ], + [ + 0.6901960784313725, + "rgb(242,107,73)" + ], + [ + 0.7529411764705882, + "rgb(244,135,95)" + ], + [ + 0.8156862745098039, + "rgb(245,162,122)" + ], + [ + 0.8784313725490196, + "rgb(246,188,153)" + ], + [ + 0.9411764705882353, + "rgb(247,212,187)" + ], + [ + 1, + "rgb(250,234,220)" + ] + ] + }, + "colorway": [ + "rgb(76,114,176)", + "rgb(221,132,82)", + "rgb(85,168,104)", + "rgb(196,78,82)", + "rgb(129,114,179)", + "rgb(147,120,96)", + "rgb(218,139,195)", + "rgb(140,140,140)", + "rgb(204,185,116)", + "rgb(100,181,205)" + ], + "font": { + "color": "rgb(36,36,36)" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "rgb(234,234,242)", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "paper_bgcolor": "white", + "plot_bgcolor": "rgb(234,234,242)", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "showgrid": true, + "ticks": "" + }, + "bgcolor": "rgb(234,234,242)", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "showgrid": true, + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "rgb(234,234,242)", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "showgrid": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "rgb(234,234,242)", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "showgrid": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "rgb(234,234,242)", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "showgrid": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "fillcolor": "rgb(67,103,167)", + "line": { + "width": 0 + }, + "opacity": 0.5 + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "showgrid": true, + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "showgrid": true, + "ticks": "" + }, + "bgcolor": "rgb(234,234,242)", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "showgrid": true, + "ticks": "" + } + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "showgrid": true, + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white" + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "showgrid": true, + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white" + } + } + }, + "title": { + "text": "Plotly Animation with Multiple Traces", + "x": 0.5 + }, + "updatemenus": [ + { + "buttons": [ + { + "args": [ + null, + { + "frame": { + "duration": 1000, + "redraw": true + }, + "fromcurrent": true + } + ], + "label": "Play", + "method": "animate" + } + ], + "showactive": false, + "type": "buttons" + } + ], + "xaxis": { + "anchor": "y", + "domain": [ + 0, + 0.45 + ] + }, + "xaxis2": { + "anchor": "y2", + "domain": [ + 0.55, + 1 + ] + }, + "yaxis": { + "anchor": "x", + "domain": [ + 0, + 1 + ] + }, + "yaxis2": { + "anchor": "x2", + "domain": [ + 0, + 1 + ] + } + } + }, + "text/html": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import plotly.subplots as sp\n", + "import plotly.graph_objects as go\n", + "\n", + "# Sample data\n", + "x = [1, 2, 3, 4, 5]\n", + "y1 = [10, 15, 13, 17, 12]\n", + "y2 = [5, 9, 11, 13, 8]\n", + "\n", + "# Create a subplot with 1 row and 2 columns\n", + "fig = sp.make_subplots(rows=1, cols=2, subplot_titles=(\"Main plot\", \"Most Recent Values\"))\n", + "\n", + "# Add initial traces to the main plot\n", + "fig.add_trace(go.Scatter(x=[], y=[], mode=\"markers+lines\", name=\"Sample Data 1\"), row=1, col=1)\n", + "fig.add_trace(go.Scatter(x=[], y=[], mode=\"markers+lines\", name=\"Sample Data 2\"), row=1, col=1)\n", + "\n", + "# Add initial scatter traces to the second subplot\n", + "fig.add_trace(go.Scatter(x=[1], y=[0], mode=\"markers\", marker=dict(size=10), showlegend=False), row=1, col=2)\n", + "fig.add_trace(go.Scatter(x=[1], y=[0], mode=\"markers\", marker=dict(size=10), showlegend=False), row=1, col=2)\n", + "\n", + "# Update layout\n", + "fig.update_layout(\n", + " title_text=\"Plotly Animation with Multiple Traces\",\n", + " title_x=0.5,\n", + " updatemenus=[dict(\n", + " type=\"buttons\",\n", + " showactive=False,\n", + " buttons=[dict(\n", + " label=\"Play\",\n", + " method=\"animate\",\n", + " args=[None, {\"frame\": {\"duration\": 1000, \"redraw\": True}, \"fromcurrent\": True}]\n", + " )]\n", + " )]\n", + ")\n", + "\n", + "# Create animation frames\n", + "frames = []\n", + "for i in range(len(x)):\n", + " frame = go.Frame(\n", + " data=[\n", + " go.Scatter(x=x[:i+1], y=y1[:i+1], mode=\"markers+lines\", name=\"Sample Data 1\"),\n", + " go.Scatter(x=x[:i+1], y=y2[:i+1], mode=\"markers+lines\", name=\"Sample Data 2\"),\n", + " go.Scatter(x=[1], y=[y1[i]], mode=\"markers\", marker=dict(size=10), showlegend=False),\n", + " go.Scatter(x=[1], y=[y2[i]], mode=\"markers\", marker=dict(size=10), showlegend=False)\n", + " ]\n", + " )\n", + " frames.append(frame)\n", + "\n", + "# Add frames to the figure\n", + "fig.frames = frames\n", + "\n", + "# Show the plot\n", + "fig.show()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bcd4980d", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.6" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/disc_plot.ipynb b/notebooks/disc_plot.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..8950dd3c4dc30a643234373210db12487901fac2 --- /dev/null +++ b/notebooks/disc_plot.ipynb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1006c45576f250234568583529a2f594a1d6fd5400aeb877b2dbee7dd770cde9 +size 11383386 diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8963019f5f56bbff59040a36ab8cf491d52a6d46 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +numpy>=1.18.1 +scipy>=1.4.1 +PyYAML==6.0 +numpy_stl==3.0.1 +plotly==5.13.1 \ No newline at end of file diff --git a/setup.py b/setup.py new file mode 100644 index 0000000000000000000000000000000000000000..9abb7dcfdf5965b442b3429561dce3b90f52940b --- /dev/null +++ b/setup.py @@ -0,0 +1,7 @@ +from setuptools import setup, find_packages +setup( + name="shotshaper", + version="0.1.0", + packages=find_packages(), + include_package_data=True +) diff --git a/shotshaper/__init__.py b/shotshaper/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..faaaf799c7de53e7e92a4fc474a6e6204f31fe3a --- /dev/null +++ b/shotshaper/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + + diff --git a/shotshaper/discs/.gitattributes b/shotshaper/discs/.gitattributes new file mode 100644 index 0000000000000000000000000000000000000000..26a791c6b599e89310b7daf02216d1b208b5f7e0 --- /dev/null +++ b/shotshaper/discs/.gitattributes @@ -0,0 +1,4 @@ +cd1.stl filter=lfs diff=lfs merge=lfs -text +cd5.stl filter=lfs diff=lfs merge=lfs -text +dd2.stl filter=lfs diff=lfs merge=lfs -text +fd2.stl filter=lfs diff=lfs merge=lfs -text diff --git a/shotshaper/discs/cd1.stl b/shotshaper/discs/cd1.stl new file mode 100644 index 0000000000000000000000000000000000000000..004f94e0c29d34726522ab03a5e31a0945f6aa7c --- /dev/null +++ b/shotshaper/discs/cd1.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:750a9ec26e520f1d662453952e44a20c2b02eeb4d7f52a1d702c7a5dff335ad0 +size 3869884 diff --git a/shotshaper/discs/cd1.yaml b/shotshaper/discs/cd1.yaml new file mode 100644 index 0000000000000000000000000000000000000000..dfa90b7c0069971e18089ba4182d4136bd3ae91f --- /dev/null +++ b/shotshaper/discs/cd1.yaml @@ -0,0 +1,24 @@ +# Overstable control driver, modelled after an Innova Firebird +# Data taken from CFD simulations + +diameter: 0.211 +J_xy: 3.759e-03 +J_z: 7.485e-03 +alpha: [-90,-80,-70,-60,-50,-40,-30,-20,-15, + -10,-8,-6,-4,-2,0,2,4,6,8,10,12,14,16,18,20, + 25,30,40,50,60,70,80,90] +Cd: [ 0.9641927, 1.040903, 1.014881, 0.8892227, 0.79079, 0.674083, 0.5343097, 0.272792, 0.1632757, + + 0.0813, 0.0663, 0.0554, 0.0474, 0.0474, 0.0458, 0.057, 0.0668, 0.0846, 0.109, 0.137, 0.1729, 0.2182, 0.2672, 0.3268, 0.3924, + +.5411498, 0.7411681, 1.111394, 1.115411, 1.080624, 1.186235, 1.023045, 1.029478 ] + +Cl: [ 0.0001273178, -0.1869159, -0.3665411, -0.5029187, -0.6435312, -0.7736677, -0.8636631, -0.6659618, -0.4805856, + +-0.29, -0.219, -0.1522, -0.0802, -0.0026, 0.0674, 0.1646, 0.2486, 0.3467, 0.4523, 0.5633, 0.6728, 0.7904, 0.8948, 1.0084, 1.0936, +1.199855, 1.309407, 1.322162, 0.9143433, 0.6057466, 0.4181427, 0.1679042, -0.001581172 ] + +Cm: [ 0.0003381886, -0.03136248, -0.04697123, -0.06378013, -0.07869955, -0.08915614, -0.100739, -0.07532892, -0.08049738, + -0.075, -0.0617, -0.0484, -0.0346, -0.0238, -0.0099, 0.002, 0.0112, 0.0211, 0.0323, 0.0461, 0.0601, 0.0749, 0.0929, 0.1087, 0.1159, + +0.1514894, 0.1528616, 0.135503, 0.09038871, 0.06759896, 0.07489785, 0.04788332, -0.002841088 ] diff --git a/shotshaper/discs/cd5.stl b/shotshaper/discs/cd5.stl new file mode 100644 index 0000000000000000000000000000000000000000..eb8a23d70cd4ba5310180d88638ef20cdcb5d029 --- /dev/null +++ b/shotshaper/discs/cd5.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ffdbc36b511ef0a98ab99ab247c32353f0e15475d2ca2ef8fbf87f5d6e3c188d +size 6317884 diff --git a/shotshaper/discs/cd5.yaml b/shotshaper/discs/cd5.yaml new file mode 100644 index 0000000000000000000000000000000000000000..6c75c24012d64954b136afba55a095204bf62b19 --- /dev/null +++ b/shotshaper/discs/cd5.yaml @@ -0,0 +1,23 @@ +# Understable control driver, modelled after an Innova Roadrunner +# Data taken from CFD simulations + +diameter: 0.211 +J_xy: 3.829e-03 +J_z: 7.616e-03 +alpha: [-90,-80,-70,-60,-50,-40,-30,-20,-15, + -10,-8,-6,-4,-2,0,2,4,6,8,10,12,14,16,18,20, + 25,30,40,50,60,70,80,90] +Cd: [ 0.9179461, 0.9709634, 0.9750627, 0.8941224, 0.7740944, 0.611287, 0.4877146, 0.2566395, 0.1423688, + + 0.0773, 0.0606, 0.0514, 0.0468, 0.0439, 0.0528, 0.0631, 0.0763, 0.0968, 0.1171, 0.1417, 0.1776, 0.2136, 0.2587, 0.2986, 0.3612, +0.5332736, 0.7454067, 1.100109, 1.231819, 1.080511, 1.06314, 1.025655, 1.000069 ] + +Cl: [ -0.003535795, -0.1650353, -0.3380664, -0.4879364, -0.6047266, -0.6677451, -0.7633718, -0.6095486, -0.4310734, + # + -0.2642, -0.1891, -0.1239, -0.0469, 0.0208, 0.1081, 0.1917, 0.2859, 0.4015, 0.4846, 0.5882, 0.6957, 0.7988, 0.9093, 1.0012, 1.1181, +1.246332, 1.367988, 1.333375, 1.038364, 0.6176756, 0.4386948, 0.1819935, 0.0001378738 ] + +Cm: [ -0.004521051, -0.03329007, -0.05428122, -0.072994, -0.09090575, -0.09778813, -0.1002716, -0.08264331, -0.09134467, + -0.0783, -0.0634, -0.0539, -0.0436, -0.0304, -0.0229, -0.012, -0.0013, 0.005, 0.019, 0.0302, 0.042, 0.0559, 0.0692, 0.0901, 0.1032, + +0.1538899, 0.1695394, 0.1369221, 0.1079746, 0.06659547, 0.07765108, 0.04283614, -2.493789e-05 ] \ No newline at end of file diff --git a/shotshaper/discs/dd2.stl b/shotshaper/discs/dd2.stl new file mode 100644 index 0000000000000000000000000000000000000000..b1a7efcfc1284c56ffc0a992afd6a0be68cd88dd --- /dev/null +++ b/shotshaper/discs/dd2.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0d9226b43dba147376cb204532fa9547c6729d61d086a51803a5769e56016d67 +size 3673484 diff --git a/shotshaper/discs/dd2.yaml b/shotshaper/discs/dd2.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9e3a3f5424b60b2a31e306f1fab8fa668e1d3b46 --- /dev/null +++ b/shotshaper/discs/dd2.yaml @@ -0,0 +1,21 @@ +diameter: 0.211 +J_xy: 3.755e-03 +J_z: 7.465e-03 + +alpha: [-90,-80,-70,-60,-50,-40,-30,-20,-15,-10,-8,-6,-4,-2,0,2,4,6,8,10,12,14, + 16,18,20,25,30,40,50,60,70,80,90] + +Cd: [1.0156, 1.0413, 0.995, 0.8904, 0.7415, 0.6219, 0.4648, 0.2499, 0.1556, + 0.0769, 0.0617, 0.0509, 0.0432, 0.0429, 0.0417, 0.0578, 0.0664, 0.0825, + 0.1058, 0.1281, 0.1624, 0.2015, 0.2462, 0.2962, 0.3591, 0.561, 0.8141, + 1.2255, 1.2382, 1.0793, 1.1797, 1.199, 1.1867] + +Cl: [0.0001, -0.2141, -0.4086, -0.5726, -0.6814, -0.7987, -0.8534, -0.694, + -0.4917, -0.2137, -0.1607, -0.0952, -0.0401, 0.0347, 0.1091, 0.2013, + 0.2761, 0.3666, 0.477, 0.5604, 0.6684, 0.7773, 0.888, 1.0013, 1.1157, + 1.67, 1.8447, 1.8161, 1.2563, 0.7495, 0.5236, 0.2646, 0.0033] + +Cm: [-0.0007, -0.0326, -0.0544, -0.0712, -0.085, -0.0985, -0.0953, -0.0728, + -0.0742, -0.0966, -0.076, -0.0621, -0.0455, -0.0342, -0.0175, -0.0122, + 0.0013, 0.0128, 0.0217, 0.0364, 0.0486, 0.0618, 0.0758, 0.0925, 0.1081, + 0.1568, 0.1712, 0.1419, 0.0995, 0.0731, 0.0692, 0.0421, 0.0016] \ No newline at end of file diff --git a/shotshaper/discs/fd2.stl b/shotshaper/discs/fd2.stl new file mode 100644 index 0000000000000000000000000000000000000000..b898d2d2a1b5de27aabf6c0b09e7a3c5012e8d12 --- /dev/null +++ b/shotshaper/discs/fd2.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3f4a12f3fc29c8ddf1661c92ddd750e49ce2fb5f056fe3508b919fb39f9172cc +size 4492684 diff --git a/shotshaper/discs/fd2.yaml b/shotshaper/discs/fd2.yaml new file mode 100644 index 0000000000000000000000000000000000000000..2d3ce95d49acacbb53406a402b650a0eeafc3dcc --- /dev/null +++ b/shotshaper/discs/fd2.yaml @@ -0,0 +1,27 @@ +# Stable fairway driver, modelled after an Innova Teebird +# Data taken from CFD simulations (-90 to -15, and 25 to 90 copied from cd1) + +diameter: 0.211 +J_xy: 3.809e-03 +J_z: 7.577e-03 +alpha: [-90,-80,-70,-60,-50,-40,-30,-20,-15, + -10,-8,-6,-4,-2,0,2,4,6,8,10,12,14,16,18,20, + 25,30,40,50,60,70,80,90] +Cd: [ 0.9641927, 1.040903, 1.014881, 0.8892227, 0.79079, 0.674083, 0.5343097, 0.272792, 0.1632757, + +#0.0913, 0.0644, 0.0543, 0.0502, 0.0458, 0.0436, 0.0594, 0.0671, 0.0875, 0.1111, 0.1415, 0.1749, 0.2152, 0.2613, 0.3132, 0.3829, + 0.08, 0.0674, 0.0555, 0.0496, 0.046, 0.0454, 0.0488, 0.0701, 0.0872, 0.1096, 0.1336, 0.1688, 0.212, 0.2604, 0.3172, 0.387, +.5411498, 0.7411681, 1.111394, 1.115411, 1.080624, 1.186235, 1.023045, 1.029478 ] + +Cl: [ 0.0001273178, -0.1869159, -0.3665411, -0.5029187, -0.6435312, -0.7736677, -0.8636631, -0.6659618, -0.4805856, + +#-0.2833, -0.1839, -0.1311, -0.0441, 0.0169, 0.0734, 0.1942, 0.2687, 0.3722, 0.478, 0.5899, 0.6983, 0.8132, 0.9264, 1.0354, 1.1698, +-0.2624, -0.1941, -0.1464, -0.0673, -0.0005, 0.0672, 0.1408, 0.2622, 0.3575, 0.4587, 0.5593, 0.673, 0.7957, 0.9149, 1.0373, 1.148, + +1.199855, 1.309407, 1.322162, 0.9143433, 0.6057466, 0.4181427, 0.1679042, -0.001581172 ] + +Cm: [ 0.0003381886, -0.03136248, -0.04697123, -0.06378013, -0.07869955, -0.08915614, -0.100739, -0.07532892, -0.08049738, + +# -0.0763, -0.0653, -0.0475, -0.0432, -0.027, -0.0128, -0.0112, 0.0016, 0.0095, 0.019, 0.0292, 0.042, 0.055, 0.0701, 0.0888, 0.1095, + -0.0694, -0.0567, -0.0429, -0.0361, -0.0233, -0.0112, 0.0006, 0.0026, 0.0125, 0.0224, 0.0344, 0.0452, 0.0566, 0.0703, 0.0886, 0.1093, +0.1514894, 0.1528616, 0.135503, 0.09038871, 0.06759896, 0.07489785, 0.04788332, -0.002841088 ] diff --git a/shotshaper/environment.py b/shotshaper/environment.py new file mode 100644 index 0000000000000000000000000000000000000000..4b6087bd026af49bdc0b6e8281be3ab9645453a8 --- /dev/null +++ b/shotshaper/environment.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +""" +""" +import numpy as np + +g = -9.81 +# Air +rho = 1.225 +mu = 1.81e-5 + +winddir = np.array((1,0,0)) +z0 = 0.1 +Uref = 0.0 +zref = 1.5 +kappa = 0.41 + +def wind_abl(z): + # For a constant wind: + # return Uref*winddir + + if z < 0.0: + z = 0.0 + + ustar = Uref*kappa/(np.log((zref+z0)/z0)) + u = ustar/kappa*np.log((z+z0)/z0) + + return u*winddir diff --git a/shotshaper/projectile.py b/shotshaper/projectile.py new file mode 100644 index 0000000000000000000000000000000000000000..9ddb4b2dc0ee1d517c472e3ac00f523f8c9ed584 --- /dev/null +++ b/shotshaper/projectile.py @@ -0,0 +1,607 @@ +# -*- coding: utf-8 -*- +""" +Created on Tue Oct 19 18:29:10 2021 + +@author: 2913452 + +TODO: + - height of athlete, optimal angle shot put + - note that biomech can influence + how much force an athlete can emit for each angle + - +""" + +from abc import ABC, abstractmethod +from scipy.integrate import solve_ivp +from scipy.interpolate import interp1d +from .transforms import T_12, T_23, T_34, T_14, T_41, T_31 +import matplotlib.pyplot as pl +from numpy import exp,matmul,pi,sqrt,arctan2,radians,degrees,sin,cos,array,concatenate,linspace,zeros_like,cross,zeros,argmin +from numpy.linalg import norm +from . import environment +import os +import yaml + +T_END = 60 +N_STEP = 200 + +def hit_ground(t, y, *args): + return y[2] + +def stopped(t, y, *args): + U = norm(y[3:6]) + return U - 1e-4 + +class Shot: + def __init__(self,t,x,v,att=None): + self.time = t + self.position = x + self.velocity = v + if att is not None: + self.attitude = att + + +class _Projectile(ABC): + def __init__(self): + pass + + def _shoot(self, advance_function, y0, *args): + hit_ground.terminal = True + hit_ground.direction = -1 + stopped.terminal = True + stopped.direction = -1 + + sol = solve_ivp(advance_function,[0,T_END],y0, + dense_output=True,args=args, + method='RK45', + events=(hit_ground,stopped)) + + t = linspace(0,sol.t[-1],N_STEP) + + f = sol.sol(t) + pos = array([f[0],f[1],f[2]]) + vel = array([f[3],f[4],f[5]]) + + if len(f) <= 6: + shot = Shot(t, pos, vel) + else: + att = array([f[6],f[7],f[8]]) + shot = Shot(t, pos, vel, att) + + return shot + + @abstractmethod + def advance(self,t,vec,*args): + """ + :param float T: Thrust + :param float Q: Torque + :param float P: Power + :return: Right hand side of kinematic equations for a projectile + :rtype: array + """ + +class _Particle(_Projectile): + def __init__(self): + super().__init__() + + self.g = environment.g + + def initialize_shot(self, **kwargs): + kwargs.setdefault('yaw', 0.0) + + pitch = radians(kwargs["pitch"]) + yaw = radians(kwargs["yaw"]) + U = kwargs["speed"] + xy = cos(pitch) + u = U*xy*cos(yaw) + w = U*sin(pitch) + v = U*xy*sin(-yaw) + if "position" in kwargs: + x,y,z = kwargs["position"] + else: + x = 0. + y = 0. + z = 0. + + y0 = array((x,y,z,u,v,w)) + return y0 + + def shoot(self, **kwargs): + + y0 = self.initialize_shot(**kwargs) + shot = self._shoot(self.advance, y0) + + return shot + + def gravity_force(self, x=None): + if x is None: + return array((0,0,environment.g)) + else: + # Messy way to return g array... + f = zeros_like(x) + f[0,:] = 0 + f[1,:] = 0 + f[2,:] = environment.g + return f + + def advance(self, t, vec, *args): + # x, y, z, u, v, w = vec + x = vec[0:3] + u = vec[3:6] + + f = self.gravity_force() + + return concatenate((u,f)) + + +class _SphericalParticleAirResistance(_Particle): + def __init__(self, mass, diameter): + super().__init__() + + self.mass = mass + self.diameter = diameter + self.radius = 0.5*diameter + self.area = 0.25*pi*diameter**2 + self.volume = 4./3.*pi*self.radius**3 + + + def air_resistance_force(self, U, Cd): + + f = -0.5*environment.rho*self.area*Cd*norm(U)*U/self.mass + #f = -0.5*environment.rho*self.area*Cd*Umag*U/self.mass + + return f + + def advance(self, t, vec, *args): + x = vec[0:3] + u = vec[3:6] + + Cd = self.drag_coefficient(norm(u)) + + f = self.air_resistance_force(u, Cd) \ + + self.gravity_force() + + return concatenate((u,f)) + + + def reynolds_number(self, velocity): + """ + Reynolds number, non-dimensional number giving the + ratio of inertial forces to viscous forces. Used + for calculating the drag coefficient. + + :param float velocity: Velocity seen by particle + :return: Reynolds number + :rtype: float + + """ + return environment.rho*velocity*self.diameter/environment.mu + + def drag_coefficient(self, velocity): + """ + Drag coefficient for sphere, empirical curve fit + taken from: + + F. A. Morrison, An Introduction to Fluid Mechanics, (Cambridge + University Press, New York, 2013). This correlation appears in + Figure 8.13 on page 625. + + The full formula is: + + .. math:: + F = \\frac{2}{\\pi}\\cos^{-1}e^{-f} \\\\ + f = \\frac{B}{2}\\frac{R-r}{r\\sin\\phi} + + + :param float velocity: Velocity seen by particle + :return: Drag coefficient + :rtype: float + """ + + Re = self.reynolds_number(velocity) + + if Re <= 0: + return 1e30 + + tmp1 = Re/5.0 + tmp2 = Re/2.63e5 + tmp3 = Re/1e6 + + Cd = 24.0/Re \ + + 2.6*tmp1/(1 + tmp1**1.52) \ + + 0.411*tmp2**-7.94/(1 + tmp2**-8) \ + + 0.25*tmp3/(1 + tmp3) + + return Cd + + +class _SphericalParticleAirResistanceSpin(_SphericalParticleAirResistance): + def __init__(self, mass, diameter): + super().__init__(mass, diameter) + + + def lift_coefficient(self, Umag, omega): + # TODO - complex dependency on Re. For now, + # assume constant + return 0.9 + + def shoot(self, **kwargs): + y0 = self.initialize_shot(**kwargs) + spin = array((kwargs["spin"])) + + shot = self._shoot(self.advance, y0, spin) + + return shot + + def spin_force(self,U,spin): + + Umag = norm(U) + omega = norm(spin) + + Cl = self.lift_coefficient(Umag, omega) + + if U.ndim == 1: + f = Cl*pi*self.radius**3*environment.rho*cross(spin, U)/self.mass + else: + # Messy way to return spin array for post-processing + f = zeros_like(U) + for i in range(U.shape[1]): + f[:,i] = Cl*pi*self.radius**3*environment.rho*cross(spin, U[:,i])/self.mass + + return f + + def advance(self, t, vec, spin): + x = vec[0:3] + u = vec[3:6] + + Cd = self.drag_coefficient(norm(u), norm(spin)) + + f = self.air_resistance_force(u, Cd) \ + + self.gravity_force() \ + + self.spin_force(u,spin) + + return concatenate((u,f)) + + +class ShotPutBall(_SphericalParticleAirResistance): + """ + Note that diameter can vary 110 mm to 130mm + and 95 mm to 110 mm + """ + def __init__(self, weight_class): + + if weight_class == 'M': + mass = 7.26 + diameter = 0.11 + elif weight_class == 'F': + mass = 4.0 + diameter = 0.095 + + super().__init__(mass, diameter) + + +class SoccerBall(_SphericalParticleAirResistanceSpin): + """ + Note that diameter can vary 110 mm to 130mm + and 95 mm to 110 mm + """ + def __init__(self, mass=0.430, diameter=0.22): + + super(SoccerBall, self).__init__(mass, diameter) + + def drag_coefficient(self, velocity, omega): + # Texture, sewing pattern and spin will alter + # the drag coefficient. + # Here, use correlation from + + # Goff, J. E., & Carré, M. J. (2010). Soccer ball lift + # coefficients via trajectory analysis. + # European Journal of Physics, 31(4), 775. + + + vc = 12.19 + vs = 1.309 + + S = omega*self.radius/velocity; + if S > 0.05 and velocity > vc: + Cd = 0.4127*S**0.3056; + else: + Cd = 0.155 + 0.346 / (1 + exp((velocity - vc)/vs)) + + return Cd + + def lift_coefficient(self, Umag, omega): + # TODO - complex dependency on Re and spin, skin texture etc + return 0.9 + +class TableTennisBall(SoccerBall): + """ + + """ + def __init__(self): + + mass = 2.7e-3 + diameter = 40e-3 + + super(TableTennisBall, self).__init__(mass, diameter) + + +class DiscGolfDisc(_Projectile): + def __init__(self, name, mass=0.175): + this_dir = os.path.dirname(os.path.abspath(__file__)) + path = os.path.join(this_dir, 'discs', name + '.yaml') + + self.name = name + + with open(path, 'r') as f: + data = yaml.load(f, Loader=yaml.FullLoader) + + self.diameter = data['diameter'] + self.mass = mass + self.weight = environment.g*mass + self.area = pi*self.diameter**2/4.0 + self.I_xy = mass*data['J_xy'] + self.I_z = mass*data['J_z'] + + a = array(data['alpha']) + cl = array(data['Cl']) + cd = array(data['Cd']) + cm = array(data['Cm']) + + + self._alpha,self._Cl,self._Cd,self._Cm = self._flip(a,cl,cd,cm) + kind = 'linear' + self.Cl_func = interp1d(self._alpha, self._Cl, kind=kind) + self.Cd_func = interp1d(self._alpha, self._Cd, kind=kind) + self.Cm_func = interp1d(self._alpha, self._Cm, kind=kind) + + def _flip(self,a,cl,cd,cm): + """ + Data given from -90 deg to 90 deg. + Expand to -180 to 180 using symmetry considerations. + """ + n = len(a) + + idx = argmin(abs(a)) + a2 = zeros(2*n) + cl2 = zeros(2*n) + cd2 = zeros(2*n) + cm2 = zeros(2*n) + + a2[idx:idx+n] = a[:] + cl2[idx:idx+n] = cl[:] + cd2[idx:idx+n] = cd[:] + cm2[idx:idx+n] = cm[:] + for i in range(idx): + a2[i] = -(180 + a[idx-i]) + cl2[i] = -cl[idx-i] + cd2[i] = cd[idx-i] + cm2[i] = -cm[idx-i] + + for i in range(idx+n,2*n): + a2[i] = 180 - a[idx+n-i-2] + cl2[i] = -cl[idx+n-i-2] + cd2[i] = cd[idx+n-i-2] + cm2[i] = -cm[idx+n-i-2] + + return a2,cl2,cd2,cm2 + + def _normalize_angle(self, alpha): + """ + Ensure that the angle fulfils :math:`-\\pi < \\alpha < \\pi` + + :param float alpha: Angle in radians + :return: Normalized angle + :rtype: float + """ + + return arctan2(sin(alpha), cos(alpha)) + + def Cd(self, alpha): + """ + Provide drag coefficent for a given angle of attack. + + :param float alpha: Angle in radians + :return: Drag coefficient + :rtype: float + """ + + # NB! The stored data uses degrees for the angle + return self.Cd_func(degrees(self._normalize_angle(alpha))) + + def Cl(self, alpha): + """ + Provide drag coefficent for a given angle of attack. + + :param float alpha: Angle in radians + :return: Drag coefficient + :rtype: float + """ + + # NB! The stored data uses degrees for the angle + return self.Cl_func(degrees(self._normalize_angle(alpha))) + + def Cm(self, alpha): + """ + Provide coefficent of moment for a given angle of attack. + + :param float alpha: Angle in radians + :return: Coefficient of moment + :rtype: float + """ + + # NB! The stored data uses degrees for the angle + return self.Cm_func(degrees(self._normalize_angle(alpha))) + + + def plot_coeffs(self, color='k'): + """ + Utility function to quickly explore disc coefficients. + + :param string color: Matplotlib color key. Default value is k, i.e. black. + """ + pl.plot(self._alpha, self._Cl, 'C0-o',label='$C_L$') + pl.plot(self._alpha, self._Cd, 'C1-o',label='$C_D$') + pl.plot(self._alpha, 3*self._Cm, 'C2-o',label='$C_M$') + + a = linspace(-pi,pi,200) + #pl.plot(degrees(a), self.Cl(a), 'C0-',label='$C_L$') + #pl.plot(degrees(a), self.Cd(a), 'C1-',label='$C_D$') + #pl.plot(degrees(a), 3*self.Cm(a), 'C2-',label='$C_M$') + + pl.xlabel('Angle of attack ($^\circ$)') + pl.ylabel('Aerodynamic coefficients (-)') + pl.legend(loc='upper left') + ax = pl.gca() + ax2 = pl.gca().twinx() + ax2.set_ylabel("Aerodynamic efficiency, $C_L/C_D$") + pl.plot(self._alpha, self._Cl/self._Cd, 'C3-.',label='$C_L/C_D$') + ax2.legend(loc='upper right') + + return ax,ax2 + + + def empirical_spin(self, speed): + # Simple empirical formula for spin rate, based on curve-fitting + # data from: + # https://www.dgcoursereview.com/dgr/forums/viewtopic.php?f=2&t=7097 + #omega = -0.257*speed**2 + 15.338*speed + + # Alternatively, experiments indicate a linear relationship, + omega = 5.2*speed + + return omega + + + + def initialize_shot(self, **kwargs): + U = kwargs["speed"] + + kwargs.setdefault('yaw', 0.0) + #kwargs.setdefault('omega', self.empirical_spin(U)) + + pitch = radians(kwargs["pitch"]) + yaw = radians(kwargs["yaw"]) + omega = kwargs["omega"] + + # phi, theta + roll_angle = radians(kwargs["roll_angle"]) # phi + nose_angle = radians(kwargs["nose_angle"]) # theta + # psi, rotation around z irrelevant for starting position + # since the disc is symmetric + + # Initialize position + if "position" in kwargs: + x,y,z = kwargs["position"] + else: + x = 0. + y = 0. + z = 0. + + # Initialize velocity + xy = cos(pitch) + u = U*xy*cos(yaw) + v = U*xy*sin(-yaw) + w = U*sin(pitch) + + # Initialize angles + attitude = array([roll_angle, nose_angle, 0]) + # The initial orientation of the disc must also account for the + # angle of the throw itself, i.e. the launch angle. + attitude += matmul(T_12(attitude), array((0, pitch, 0))) + + #attitude = matmul(T_23(yaw),attitude) + #attitude += matmul(T_12(attitude), array((0, pitch, 0))) + phi, theta, psi = attitude + y0 = array((x,y,z,u,v,w,phi,theta,psi)) + return y0, omega + + def shoot(self, **kwargs): + + y0, omega = self.initialize_shot(**kwargs) + + shot = self._shoot(self.advance, y0, omega) + + return shot + + def post_process(self, s, omega): + n = len(s.time) + alphas = zeros(n) + betas = zeros(n) + lifts = zeros(n) + drags = zeros(n) + moms = zeros(n) + rolls = zeros(n) + for i in range(n): + x = s.position[:,i] + u = s.velocity[:,i] + a = s.attitude[:,i] + + alpha, beta, Fd, Fl, M, g4 = self.forces(x, u, a, omega) + + alphas[i] = alpha + betas[i] = beta + lifts[i] = Fl + drags[i] = Fd + moms[i] = M + rolls[i] = -M/(omega*(self.I_xy - self.I_z)) + + arc_length = norm(s.position, axis=0) + return arc_length,degrees(alphas),degrees(betas),lifts,drags,moms,degrees(rolls) + + def forces(self, x, u, a, omega): + # Velocity in body axes + urel = u - environment.wind_abl(x[2]) + u2 = matmul(T_12(a), urel) + # Side slip angle is the angle between the x and y velocity + beta = -arctan2(u2[1], u2[0]) + # Velocity in zero side slip axes + u3 = matmul(T_23(beta), u2) + # Angle of attack is the angle between + # vertical and horizontal velocity + alpha = -arctan2(u3[2], u3[0]) + # Velocity in wind system, where forces are to be calculated + u4 = matmul(T_34(alpha), u3) + + # Convert gravitational force from Earth to Wind axes + g = array((0, 0, self.mass*environment.g)) + g4 = T_14(g, a, beta, alpha) + + # Aerodynamic forces + q = 0.5*environment.rho*u4[0]**2 + S = self.area + D = self.diameter + + Fd = q*S*self.Cd(alpha) + Fl = q*S*self.Cl(alpha) + M = q*S*D*self.Cm(alpha) + + return alpha, beta, Fd, Fl, M, g4 + + def advance(self, t, vec, omega): + x = vec[0:3] + u = vec[3:6] + a = vec[6:9] + + alpha, beta, Fd, Fl, M, g4 = self.forces(x, u, a, omega) + + m = self.mass + # Calculate accelerations + dudt = (-Fd + g4[0])/m + dvdt = g4[1]/m + dwdt = ( Fl + g4[2])/m + acc4 = array((dudt,dvdt,dwdt)) + # Roll rate acts around x-axis (in axes 3: zero side slip axes) + dphidt = -M/(omega*(self.I_xy - self.I_z)) + # Other angular rotations are ignored, assume zero wobble + angvel3 = array((dphidt, 0, 0)) + + acc1 = T_41(acc4, a, beta, alpha) + angvel1 = T_31(angvel3, a, beta) + + return concatenate((u,acc1,angvel1)) + + + + + diff --git a/shotshaper/transforms.py b/shotshaper/transforms.py new file mode 100644 index 0000000000000000000000000000000000000000..8597a83f646b0bf18e7e1f98402d7ee1869fa318 --- /dev/null +++ b/shotshaper/transforms.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +""" + +The axes are denoted: +1: Earth +2: Body +3: Zero side slip - rotation around z, to apply roll +4: Wind axes - to replicate the CFD condition with wind coming straight onto the body + +In Crowther & Potts, z-axis is defined pointing downwards. Here, it points upwards +leading to some different signs. +""" +import numpy as np +from numpy import cos,sin,matmul + +def T_12(attitude): + """ + Transform from Earth axes to Body axes + """ + phi, theta, psi = attitude + + return np.array([[cos(theta)*cos(psi), sin(phi)*sin(theta)*cos(psi) - cos(phi)*sin(psi), cos(phi)*sin(theta)*cos(psi) + sin(phi)*sin(psi)], + [cos(theta)*sin(psi), sin(phi)*sin(theta)*sin(psi) + cos(phi)*cos(psi), cos(phi)*sin(theta)*sin(psi) - sin(phi)*cos(psi)], + [-sin(theta), sin(phi)*cos(theta), cos(phi)*cos(theta) ]]) + +def T_23(beta): + """ + Transform from Body axes to Zero side slip axes, + Rotation around z-axis by the side-slip angle + """ + return np.array([[cos(beta), -sin(beta), 0], + [sin(beta), cos(beta), 0], + [0, 0, 1]]) + + +def T_34(alpha): + """ + Transform from Zero side slip axes to Wind axes + Rotation around y-axis by the angle of attack. + """ + return np.array([[cos(alpha), 0, -sin(alpha)], + [0, 1, 0 ], + [sin(alpha), 0, cos(alpha)]]) + +def T_14(vec, attitude, beta, alpha): + return matmul(T_34(alpha), matmul(T_23(beta), matmul(T_12(attitude), vec))) + +def T_21(attitude): + """ + Transform from Body axes to Earth axes. + Done by transposing the opposite + """ + return np.transpose(T_12(attitude)) + +def T_32(beta): + return np.transpose(T_23(beta)) + +def T_43(alpha): + return np.transpose(T_34(alpha)) + +def T_41(vec, attitude, beta, alpha): + return matmul(T_21(attitude), matmul(T_32(beta), matmul(T_43(alpha), vec))) + +def T_31(vec, attitude, beta): + return matmul(T_21(attitude), matmul(T_32(beta), vec)) + + + diff --git a/utils/disc_geometric_properties.py b/utils/disc_geometric_properties.py new file mode 100644 index 0000000000000000000000000000000000000000..8494c43c87b273b702b2320eca89074969e22d6f --- /dev/null +++ b/utils/disc_geometric_properties.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +""" +Calculate moments of inertia for a disc from STL file. +""" + +import numpy as np +import trimesh +import sys +import os + +path = os.path.dirname(os.path.realpath(__file__)) +# attach to logger so trimesh messages will be printed to console +#trimesh.util.attach_to_log() + +name = sys.argv[-1] + +m = trimesh.load(os.path.join(path, 'discs', name + '.stl')) +trimesh.repair.fix_inversion(m) +trimesh.repair.fix_normals(m) +trimesh.repair.fix_winding(m) + +if m.is_watertight and m.is_winding_consistent and m.is_volume: + V = m.volume + J = m.principal_inertia_components/V + print('Volume: ', V) + print('J_xy: %4.3e' % J[0]) + print('J_z: %4.3e' % J[2]) +