{ "cells": [ { "cell_type": "markdown", "id": "cell-0", "metadata": {}, "source": [ "# Coordinate Systems: Transformations and Projections\n", "\n", "This notebook covers coordinate system conversions and map projections commonly used in tracking and navigation. We explore:\n", "\n", "1. **Geodetic Coordinates** - Latitude, longitude, altitude (WGS84)\n", "2. **ECEF Coordinates** - Earth-Centered Earth-Fixed Cartesian system\n", "3. **Local Frames** - ENU (East-North-Up) and NED (North-East-Down)\n", "4. **Rotation Representations** - Euler angles, quaternions, rotation matrices\n", "5. **Map Projections** - UTM, Mercator, stereographic\n", "\n", "## Prerequisites\n", "\n", "```bash\n", "pip install nrl-tracker plotly numpy\n", "```" ] }, { "cell_type": "code", "execution_count": 1, "id": "cell-1", "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import plotly.graph_objects as go\n", "from plotly.subplots import make_subplots\n", "from pytcl.coordinate_systems import (\n", " # Geodetic conversions\n", " geodetic2ecef, ecef2geodetic,\n", " ecef2enu, enu2ecef, ecef2ned, ned2ecef,\n", " enu2ned, ned2enu,\n", " # Rotation operations\n", " rotx, roty, rotz,\n", " euler2rotmat, rotmat2euler,\n", " euler2quat, quat2euler,\n", " quat_multiply, quat_rotate, slerp,\n", " axisangle2rotmat, rotmat2axisangle,\n", " # Projections\n", " geodetic2utm, utm2geodetic,\n", " mercator, mercator_inverse,\n", " stereographic, polar_stereographic,\n", " lambert_conformal_conic,\n", ")\n", "from pytcl.core.constants import WGS84\n", "\n", "np.random.seed(42)\n", "\n", "# Plotly dark theme template\n", "dark_template = go.layout.Template()\n", "dark_template.layout = go.Layout(\n", " paper_bgcolor='#0d1117',\n", " plot_bgcolor='#0d1117',\n", " font=dict(color='#e6edf3'),\n", " xaxis=dict(gridcolor='#30363d', zerolinecolor='#30363d'),\n", " yaxis=dict(gridcolor='#30363d', zerolinecolor='#30363d'),\n", ")" ] }, { "cell_type": "markdown", "id": "cell-2", "metadata": {}, "source": [ "## 1. Geodetic and ECEF Coordinates\n", "\n", "### Geodetic Coordinates (LLA)\n", "\n", "Geodetic coordinates describe position using:\n", "- **Latitude (φ)**: Angle from equatorial plane (-90° to +90°)\n", "- **Longitude (λ)**: Angle from prime meridian (-180° to +180°)\n", "- **Altitude (h)**: Height above reference ellipsoid\n", "\n", "### ECEF Coordinates\n", "\n", "Earth-Centered Earth-Fixed (ECEF) is a Cartesian coordinate system:\n", "- **Origin**: Earth's center of mass\n", "- **X-axis**: Points to (0°N, 0°E) - equator/prime meridian intersection\n", "- **Y-axis**: Points to (0°N, 90°E) - equator/90° east\n", "- **Z-axis**: Points to North Pole (90°N)\n", "\n", "### Conversion Formulas\n", "\n", "The WGS84 ellipsoid is defined by:\n", "- Semi-major axis: a = 6,378,137 m\n", "- Flattening: f = 1/298.257223563" ] }, { "cell_type": "code", "execution_count": 2, "id": "cell-3", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Location Coordinates\n", "================================================================================\n", "Location | Lat (°) | Lon (°) | X (km) | Y (km) | Z (km)\n", "--------------------------------------------------------------------------------\n", "Washington DC | 38.9072 | -77.0369 | 1114.8 | -4843.1 | 3984.3\n", "London | 51.5074 | -0.1278 | 3978.0 | -8.9 | 4968.9\n", "Tokyo | 35.6762 | 139.6503 | -3953.1 | 3358.4 | 3699.1\n", "Sydney | -33.8688 | 151.2093 | -4646.1 | 2553.2 | -3534.4\n", "North Pole | 90.0000 | 0.0000 | 0.0 | 0.0 | 6356.8\n", "Equator/Prime | 0.0000 | 0.0000 | 6378.1 | 0.0 | 0.0\n" ] } ], "source": [ "# Define some example locations\n", "locations = {\n", " 'Washington DC': (38.9072, -77.0369, 0), # lat, lon (deg), alt (m)\n", " 'London': (51.5074, -0.1278, 0),\n", " 'Tokyo': (35.6762, 139.6503, 0),\n", " 'Sydney': (-33.8688, 151.2093, 0),\n", " 'North Pole': (90.0, 0.0, 0),\n", " 'Equator/Prime': (0.0, 0.0, 0),\n", "}\n", "\n", "print(\"Location Coordinates\")\n", "print(\"=\" * 80)\n", "print(f\"{'Location':15s} | {'Lat (°)':>10s} | {'Lon (°)':>10s} | \"\n", " f\"{'X (km)':>10s} | {'Y (km)':>10s} | {'Z (km)':>10s}\")\n", "print(\"-\" * 80)\n", "\n", "ecef_coords = {}\n", "for name, (lat_deg, lon_deg, alt) in locations.items():\n", " lat = np.radians(lat_deg)\n", " lon = np.radians(lon_deg)\n", " \n", " ecef = geodetic2ecef(lat, lon, alt)\n", " ecef_coords[name] = ecef\n", " \n", " print(f\"{name:15s} | {lat_deg:10.4f} | {lon_deg:10.4f} | \"\n", " f\"{ecef[0]/1e3:10.1f} | {ecef[1]/1e3:10.1f} | {ecef[2]/1e3:10.1f}\")" ] }, { "cell_type": "code", "execution_count": 3, "id": "cell-4", "metadata": {}, "outputs": [ { "data": { "application/vnd.plotly.v1+json": { "config": { "plotlyServerURL": "https://plot.ly" }, "data": [ { "colorscale": [ [ 0, "lightblue" ], [ 1, "lightblue" ] ], "name": "Earth", "opacity": 0.3, "showscale": false, "type": "surface", "x": { "bdata": "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", "dtype": "f8", "shape": "50, 30" }, "y": { "bdata": "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", "dtype": "f8", "shape": "50, 30" }, "z": { "bdata": "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", "dtype": "f8", "shape": "50, 30" } }, { "marker": { "color": "#00d4ff", "size": 8 }, "mode": "markers+text", "name": "Washington DC", "text": [ "Washington DC" ], "textposition": "top center", "type": "scatter3d", "x": [ 1.1148438126095623 ], "y": [ -4.843147441358448 ], "z": [ 3.9843054980691055 ] }, { "marker": { "color": "#ff4757", "size": 8 }, "mode": "markers+text", "name": "London", "text": [ "London" ], "textposition": "top center", "type": "scatter3d", "x": [ 3.9779942738150056 ], "y": [ -0.008873053401790553 ], "z": [ 4.968874937267014 ] }, { "marker": { "color": "#00ff88", "size": 8 }, "mode": "markers+text", "name": "Tokyo", "text": [ "Tokyo" ], "textposition": "top center", "type": "scatter3d", "x": [ -3.9530750830819685 ], "y": [ 3.358350993627036 ], "z": [ 3.699066157620805 ] }, { "marker": { "color": "#ffb800", "size": 8 }, "mode": "markers+text", "name": "Sydney", "text": [ "Sydney" ], "textposition": "top center", "type": "scatter3d", "x": [ -4.646051272064736 ], "y": [ 2.5532063422192874 ], "z": [ -3.534372387913518 ] }, { "marker": { "color": "#a855f7", "size": 8 }, "mode": "markers+text", "name": "North Pole", "text": [ "North Pole" ], "textposition": "top center", "type": "scatter3d", "x": [ 3.9186209248144716e-16 ], "y": [ 0 ], "z": [ 6.356752314245179 ] }, { "marker": { "color": "#ec4899", "size": 8 }, "mode": "markers+text", "name": "Equator/Prime", "text": [ "Equator/Prime" ], "textposition": "top center", "type": "scatter3d", "x": [ 6.378137 ], "y": [ 0 ], "z": [ 0 ] }, { "line": { "color": "red", "width": 4 }, "mode": "lines+text", "showlegend": false, "text": [ "", "X" ], "textposition": "top center", "type": "scatter3d", "x": [ 0, 8 ], "y": [ 0, 0 ], "z": [ 0, 0 ] }, { "line": { "color": "green", "width": 4 }, "mode": "lines+text", "showlegend": false, "text": [ "", "Y" ], "textposition": "top center", "type": "scatter3d", "x": [ 0, 0 ], "y": [ 0, 8 ], "z": [ 0, 0 ] }, { "line": { "color": "blue", "width": 4 }, "mode": "lines+text", "showlegend": false, "text": [ "", "Z (North)" ], "textposition": "top center", "type": "scatter3d", "x": [ 0, 0 ], "y": [ 0, 0 ], "z": [ 0, 8 ] } ], "layout": { "height": 600, "scene": { "aspectmode": "data", "xaxis": { "gridcolor": "#30363d", "title": { "text": "X (million m)" } }, "yaxis": { "gridcolor": "#30363d", "title": { "text": "Y (million m)" } }, "zaxis": { "gridcolor": "#30363d", "title": { "text": "Z (million m)" } } }, "template": { "layout": { "font": { "color": "#e6edf3" }, "paper_bgcolor": "#0d1117", "plot_bgcolor": "#0d1117", "xaxis": { "gridcolor": "#30363d", "zerolinecolor": "#30363d" }, "yaxis": { "gridcolor": "#30363d", "zerolinecolor": "#30363d" } } }, "title": { "text": "ECEF Coordinate System" } } } }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Visualize locations in 3D ECEF\n", "# Draw Earth ellipsoid (simplified as sphere)\n", "u = np.linspace(0, 2 * np.pi, 50)\n", "v = np.linspace(0, np.pi, 30)\n", "R = WGS84.a / 1e6 # Scale to millions of meters\n", "\n", "x_sphere = R * np.outer(np.cos(u), np.sin(v))\n", "y_sphere = R * np.outer(np.sin(u), np.sin(v))\n", "z_sphere = R * np.outer(np.ones(np.size(u)), np.cos(v)) * (1 - WGS84.f)\n", "\n", "fig = go.Figure()\n", "\n", "# Earth surface\n", "fig.add_trace(\n", " go.Surface(x=x_sphere, y=y_sphere, z=z_sphere,\n", " colorscale=[[0, 'lightblue'], [1, 'lightblue']],\n", " opacity=0.3, showscale=False, name='Earth')\n", ")\n", "\n", "# Plot locations\n", "colors = ['#00d4ff', '#ff4757', '#00ff88', '#ffb800', '#a855f7', '#ec4899']\n", "for (name, ecef), color in zip(ecef_coords.items(), colors):\n", " fig.add_trace(\n", " go.Scatter3d(x=[ecef[0]/1e6], y=[ecef[1]/1e6], z=[ecef[2]/1e6],\n", " mode='markers+text', marker=dict(size=8, color=color),\n", " text=[name], textposition='top center',\n", " name=name)\n", " )\n", "\n", "# Draw axes\n", "axis_length = 8\n", "fig.add_trace(\n", " go.Scatter3d(x=[0, axis_length], y=[0, 0], z=[0, 0],\n", " mode='lines+text', line=dict(color='red', width=4),\n", " text=['', 'X'], textposition='top center',\n", " showlegend=False)\n", ")\n", "fig.add_trace(\n", " go.Scatter3d(x=[0, 0], y=[0, axis_length], z=[0, 0],\n", " mode='lines+text', line=dict(color='green', width=4),\n", " text=['', 'Y'], textposition='top center',\n", " showlegend=False)\n", ")\n", "fig.add_trace(\n", " go.Scatter3d(x=[0, 0], y=[0, 0], z=[0, axis_length],\n", " mode='lines+text', line=dict(color='blue', width=4),\n", " text=['', 'Z (North)'], textposition='top center',\n", " showlegend=False)\n", ")\n", "\n", "fig.update_layout(\n", " template=dark_template,\n", " title='ECEF Coordinate System',\n", " height=600,\n", " scene=dict(\n", " xaxis_title='X (million m)',\n", " yaxis_title='Y (million m)',\n", " zaxis_title='Z (million m)',\n", " aspectmode='data',\n", " xaxis=dict(gridcolor='#30363d'),\n", " yaxis=dict(gridcolor='#30363d'),\n", " zaxis=dict(gridcolor='#30363d'),\n", " )\n", ")\n", "fig.show()" ] }, { "cell_type": "code", "execution_count": 4, "id": "cell-5", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Round-trip Conversion Accuracy (ECEF → Geodetic → ECEF)\n", "============================================================\n", "Washington DC : Round-trip error = 4.656613e-10 m\n", "London : Round-trip error = 1.818989e-12 m\n", "Tokyo : Round-trip error = 4.656613e-10 m\n", "Sydney : Round-trip error = 9.313226e-10 m\n", "North Pole : Round-trip error = 0.000000e+00 m\n", "Equator/Prime : Round-trip error = 0.000000e+00 m\n" ] } ], "source": [ "# Verify round-trip conversion accuracy\n", "print(\"Round-trip Conversion Accuracy (ECEF → Geodetic → ECEF)\")\n", "print(\"=\" * 60)\n", "\n", "for name, ecef_orig in ecef_coords.items():\n", " # ECEF to geodetic\n", " lat, lon, alt = ecef2geodetic(ecef_orig)\n", " \n", " # Back to ECEF\n", " ecef_back = geodetic2ecef(lat, lon, alt)\n", " \n", " # Compute error\n", " error = np.linalg.norm(ecef_orig - ecef_back)\n", " \n", " print(f\"{name:15s}: Round-trip error = {error:.6e} m\")" ] }, { "cell_type": "markdown", "id": "cell-6", "metadata": {}, "source": [ "## 2. Local Tangent Plane Frames: ENU and NED\n", "\n", "For local operations near a reference point, we use tangent plane coordinate systems:\n", "\n", "### ENU (East-North-Up)\n", "- **East**: Points east (increasing longitude)\n", "- **North**: Points north (increasing latitude) \n", "- **Up**: Points away from Earth center (opposite gravity)\n", "\n", "### NED (North-East-Down)\n", "- **North**: Points north\n", "- **East**: Points east\n", "- **Down**: Points toward Earth center (with gravity)\n", "\n", "NED is common in aerospace (aircraft body frame), while ENU is common in robotics." ] }, { "cell_type": "code", "execution_count": 5, "id": "cell-7", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Reference Point: 38.90°N, -77.00°W\n", "\n", "Simulated aircraft positions relative to reference:\n", "Aircraft | East (m) | North (m) | Up (m)\n", "-------------------------------------------------------\n", "Aircraft 1 | 1000 | 2000 | 500\n", "Aircraft 2 | -500 | 3000 | 1000\n", "Aircraft 3 | 2000 | -1000 | 2000\n" ] } ], "source": [ "# Reference point: Washington DC airport\n", "ref_lat = np.radians(38.9)\n", "ref_lon = np.radians(-77.0)\n", "ref_alt = 0.0\n", "\n", "print(f\"Reference Point: {np.degrees(ref_lat):.2f}°N, {np.degrees(ref_lon):.2f}°W\")\n", "print(\"\\nSimulated aircraft positions relative to reference:\")\n", "\n", "# Simulate aircraft at various positions\n", "aircraft_offsets = [\n", " ('Aircraft 1', 1000, 2000, 500), # 1km E, 2km N, 500m Up\n", " ('Aircraft 2', -500, 3000, 1000), # 500m W, 3km N, 1km Up\n", " ('Aircraft 3', 2000, -1000, 2000), # 2km E, 1km S, 2km Up\n", "]\n", "\n", "print(f\"{'Aircraft':12s} | {'East (m)':>10s} | {'North (m)':>10s} | {'Up (m)':>10s}\")\n", "print(\"-\" * 55)\n", "\n", "ecef_aircraft = []\n", "enu_aircraft = []\n", "\n", "for name, east, north, up in aircraft_offsets:\n", " print(f\"{name:12s} | {east:10.0f} | {north:10.0f} | {up:10.0f}\")\n", " \n", " # Convert ENU offset to ECEF\n", " enu = np.array([east, north, up])\n", " ecef = enu2ecef(enu, ref_lat, ref_lon)\n", " \n", " enu_aircraft.append(enu)\n", " ecef_aircraft.append(ecef)" ] }, { "cell_type": "code", "execution_count": 6, "id": "cell-8", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Comparison: ENU vs NED frames\n", "================================================================================\n", "Aircraft | E (m) N (m) U (m) | N (m) E (m) D (m)\n", " | --- ENU --- | --- NED --- \n", "--------------------------------------------------------------------------------\n", "Aircraft 1 | 1000 2000 500 | 2000 1000 -500\n", "Aircraft 2 | -500 3000 1000 | 3000 -500 -1000\n", "Aircraft 3 | 2000 -1000 2000 | -1000 2000 -2000\n", "\n", "Note: NED swaps E↔N and negates Up to get Down\n" ] } ], "source": [ "# Convert same positions to NED\n", "print(\"\\nComparison: ENU vs NED frames\")\n", "print(\"=\" * 80)\n", "print(f\"{'Aircraft':12s} | {'E (m)':>8s} {'N (m)':>8s} {'U (m)':>8s} | \"\n", " f\"{'N (m)':>8s} {'E (m)':>8s} {'D (m)':>8s}\")\n", "print(f\"{'':12s} | {'--- ENU ---':^26s} | {'--- NED ---':^26s}\")\n", "print(\"-\" * 80)\n", "\n", "for i, (name, _, _, _) in enumerate(aircraft_offsets):\n", " enu = enu_aircraft[i]\n", " ned = enu2ned(enu)\n", " \n", " print(f\"{name:12s} | {enu[0]:8.0f} {enu[1]:8.0f} {enu[2]:8.0f} | \"\n", " f\"{ned[0]:8.0f} {ned[1]:8.0f} {ned[2]:8.0f}\")\n", "\n", "print(\"\\nNote: NED swaps E↔N and negates Up to get Down\")" ] }, { "cell_type": "code", "execution_count": 7, "id": "cell-9", "metadata": {}, "outputs": [ { "data": { "application/vnd.plotly.v1+json": { "config": { "plotlyServerURL": "https://plot.ly" }, "data": [ { "marker": { "color": "#00d4ff", "size": 12 }, "mode": "markers+text", "name": "Aircraft 1", "showlegend": true, "text": [ "Aircraft 1
Up=500m" ], "textposition": "top right", "type": "scatter", "x": [ 1000 ], "xaxis": "x", "y": [ 2000 ], "yaxis": "y" }, { "marker": { "color": "#ff4757", "size": 12 }, "mode": "markers+text", "name": "Aircraft 2", "showlegend": true, "text": [ "Aircraft 2
Up=1000m" ], "textposition": "top right", "type": "scatter", "x": [ -500 ], "xaxis": "x", "y": [ 3000 ], "yaxis": "y" }, { "marker": { "color": "#00ff88", "size": 12 }, "mode": "markers+text", "name": "Aircraft 3", "showlegend": true, "text": [ "Aircraft 3
Up=2000m" ], "textposition": "top right", "type": "scatter", "x": [ 2000 ], "xaxis": "x", "y": [ -1000 ], "yaxis": "y" }, { "marker": { "color": "white", "size": 15, "symbol": "star" }, "mode": "markers", "name": "Reference", "showlegend": true, "type": "scatter", "x": [ 0 ], "xaxis": "x", "y": [ 0 ], "yaxis": "y" }, { "marker": { "color": "#00d4ff", "size": 12 }, "mode": "markers+text", "showlegend": false, "text": [ "Down=-500m" ], "textposition": "top right", "type": "scatter", "x": [ 1000 ], "xaxis": "x2", "y": [ 2000 ], "yaxis": "y2" }, { "marker": { "color": "#ff4757", "size": 12 }, "mode": "markers+text", "showlegend": false, "text": [ "Down=-1000m" ], "textposition": "top right", "type": "scatter", "x": [ -500 ], "xaxis": "x2", "y": [ 3000 ], "yaxis": "y2" }, { "marker": { "color": "#00ff88", "size": 12 }, "mode": "markers+text", "showlegend": false, "text": [ "Down=-2000m" ], "textposition": "top right", "type": "scatter", "x": [ 2000 ], "xaxis": "x2", "y": [ -1000 ], "yaxis": "y2" }, { "marker": { "color": "white", "size": 15, "symbol": "star" }, "mode": "markers", "showlegend": false, "type": "scatter", "x": [ 0 ], "xaxis": "x2", "y": [ 0 ], "yaxis": "y2" } ], "layout": { "annotations": [ { "font": { "size": 16 }, "showarrow": false, "text": "ENU Frame (looking down)", "x": 0.225, "xanchor": "center", "xref": "paper", "y": 1, "yanchor": "bottom", "yref": "paper" }, { "font": { "size": 16 }, "showarrow": false, "text": "NED Frame (X=North, Y=East)", "x": 0.775, "xanchor": "center", "xref": "paper", "y": 1, "yanchor": "bottom", "yref": "paper" } ], "height": 450, "template": { "layout": { "font": { "color": "#e6edf3" }, "paper_bgcolor": "#0d1117", "plot_bgcolor": "#0d1117", "xaxis": { "gridcolor": "#30363d", "zerolinecolor": "#30363d" }, "yaxis": { "gridcolor": "#30363d", "zerolinecolor": "#30363d" } } }, "xaxis": { "anchor": "y", "domain": [ 0, 0.45 ], "scaleanchor": "y", "scaleratio": 1, "title": { "text": "East (m)" } }, "xaxis2": { "anchor": "y2", "domain": [ 0.55, 1 ], "title": { "text": "East (m)" } }, "yaxis": { "anchor": "x", "domain": [ 0, 1 ], "title": { "text": "North (m)" } }, "yaxis2": { "anchor": "x2", "domain": [ 0, 1 ], "scaleanchor": "x2", "scaleratio": 1, "title": { "text": "North (m)" } } } } }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Visualize ENU and NED frames\n", "fig = make_subplots(rows=1, cols=2, subplot_titles=('ENU Frame (looking down)', 'NED Frame (X=North, Y=East)'),\n", " horizontal_spacing=0.1)\n", "\n", "colors = ['#00d4ff', '#ff4757', '#00ff88']\n", "\n", "# ENU plot\n", "for i, (name, _, _, _) in enumerate(aircraft_offsets):\n", " enu = enu_aircraft[i]\n", " fig.add_trace(\n", " go.Scatter(x=[enu[0]], y=[enu[1]], mode='markers+text',\n", " marker=dict(size=12, color=colors[i]),\n", " text=[f\"{name}
Up={enu[2]:.0f}m\"], textposition='top right',\n", " name=name, showlegend=True),\n", " row=1, col=1\n", " )\n", "\n", "# Reference point for ENU\n", "fig.add_trace(\n", " go.Scatter(x=[0], y=[0], mode='markers',\n", " marker=dict(size=15, color='white', symbol='star'),\n", " name='Reference', showlegend=True),\n", " row=1, col=1\n", ")\n", "\n", "# NED plot \n", "for i, (name, _, _, _) in enumerate(aircraft_offsets):\n", " enu = enu_aircraft[i]\n", " ned = enu2ned(enu)\n", " fig.add_trace(\n", " go.Scatter(x=[ned[1]], y=[ned[0]], mode='markers+text',\n", " marker=dict(size=12, color=colors[i]),\n", " text=[f\"Down={ned[2]:.0f}m\"], textposition='top right',\n", " showlegend=False),\n", " row=1, col=2\n", " )\n", "\n", "# Reference point for NED\n", "fig.add_trace(\n", " go.Scatter(x=[0], y=[0], mode='markers',\n", " marker=dict(size=15, color='white', symbol='star'),\n", " showlegend=False),\n", " row=1, col=2\n", ")\n", "\n", "fig.update_layout(\n", " template=dark_template,\n", " height=450,\n", ")\n", "fig.update_xaxes(title_text='East (m)', row=1, col=1, scaleanchor='y', scaleratio=1)\n", "fig.update_xaxes(title_text='East (m)', row=1, col=2)\n", "fig.update_yaxes(title_text='North (m)', row=1, col=1)\n", "fig.update_yaxes(title_text='North (m)', row=1, col=2, scaleanchor='x2', scaleratio=1)\n", "\n", "fig.show()" ] }, { "cell_type": "markdown", "id": "cell-10", "metadata": {}, "source": [ "## 3. Rotation Representations\n", "\n", "Rotations in 3D can be represented several ways:\n", "\n", "| Representation | Parameters | Singularities | Use Case |\n", "|----------------|-----------|---------------|----------|\n", "| Euler Angles | 3 | Gimbal lock | Human intuition |\n", "| Rotation Matrix | 9 (6 DOF) | None | Direct application |\n", "| Quaternion | 4 (3 DOF) | None | Interpolation, composition |\n", "| Axis-Angle | 3 | Small angles | Visualization |\n", "\n", "### Euler Angles (ZYX Convention)\n", "\n", "The aerospace convention uses:\n", "- **Yaw (ψ)**: Rotation about Z-axis (heading)\n", "- **Pitch (θ)**: Rotation about Y-axis (nose up/down)\n", "- **Roll (φ)**: Rotation about X-axis (bank)" ] }, { "cell_type": "code", "execution_count": 8, "id": "cell-11", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Input Euler angles (ZYX convention):\n", " Yaw: 45.0°\n", " Pitch: 15.0°\n", " Roll: 10.0°\n", "\n", "Rotation Matrix:\n", "[[ 0.6830127 -0.66458442 0.30302013]\n", " [ 0.6830127 0.72814406 0.05744452]\n", " [-0.25881905 0.16773126 0.95125124]]\n", "\n", "Quaternion [w, x, y, z]: [0.9168435 0.0300724 0.15319931 0.3674556 ]\n", "\n", "Recovered Euler angles:\n", " Yaw: 45.0°\n", " Pitch: 15.0°\n", " Roll: 10.0°\n" ] } ], "source": [ "# Demonstrate rotation representations\n", "yaw = np.radians(45) # 45° heading\n", "pitch = np.radians(15) # 15° nose up\n", "roll = np.radians(10) # 10° bank right\n", "\n", "angles = np.array([yaw, pitch, roll])\n", "\n", "print(\"Input Euler angles (ZYX convention):\")\n", "print(f\" Yaw: {np.degrees(yaw):6.1f}°\")\n", "print(f\" Pitch: {np.degrees(pitch):6.1f}°\")\n", "print(f\" Roll: {np.degrees(roll):6.1f}°\")\n", "\n", "# Convert to rotation matrix\n", "R = euler2rotmat(angles, 'ZYX')\n", "print(f\"\\nRotation Matrix:\\n{R}\")\n", "\n", "# Convert to quaternion\n", "q = euler2quat(angles, 'ZYX')\n", "print(f\"\\nQuaternion [w, x, y, z]: {q}\")\n", "\n", "# Convert back to verify\n", "angles_back = rotmat2euler(R, 'ZYX')\n", "print(f\"\\nRecovered Euler angles:\")\n", "print(f\" Yaw: {np.degrees(angles_back[0]):6.1f}°\")\n", "print(f\" Pitch: {np.degrees(angles_back[1]):6.1f}°\")\n", "print(f\" Roll: {np.degrees(angles_back[2]):6.1f}°\")" ] }, { "cell_type": "code", "execution_count": 9, "id": "cell-12", "metadata": {}, "outputs": [ { "data": { "application/vnd.plotly.v1+json": { "config": { "plotlyServerURL": "https://plot.ly" }, "data": [ { "line": { "color": "red", "width": 6 }, "mode": "lines", "name": "Forward (X)", "scene": "scene", "type": "scatter3d", "x": [ 0, 1 ], "y": [ 0, 0 ], "z": [ 0, 0 ] }, { "line": { "color": "green", "width": 6 }, "mode": "lines", "name": "Right (Y)", "scene": "scene", "type": "scatter3d", "x": [ 0, 0 ], "y": [ 0, 1 ], "z": [ 0, 0 ] }, { "line": { "color": "blue", "width": 6 }, "mode": "lines", "name": "Down (Z)", "scene": "scene", "type": "scatter3d", "x": [ 0, 0 ], "y": [ 0, 0 ], "z": [ 0, 1 ] }, { "line": { "color": "red", "width": 6 }, "mode": "lines", "scene": "scene2", "showlegend": false, "type": "scatter3d", "x": [ 0, 0.6830127018922194 ], "y": [ 0, 0.6830127018922193 ], "z": [ 0, -0.25881904510252074 ] }, { "line": { "color": "green", "width": 6 }, "mode": "lines", "scene": "scene2", "showlegend": false, "type": "scatter3d", "x": [ 0, -0.6645844181465338 ], "y": [ 0, 0.728144062493504 ], "z": [ 0, 0.16773125949652062 ] }, { "line": { "color": "blue", "width": 6 }, "mode": "lines", "scene": "scene2", "showlegend": false, "type": "scatter3d", "x": [ 0, 0.3030201316921424 ], "y": [ 0, 0.05744452375419671 ], "z": [ 0, 0.9512512425641977 ] } ], "layout": { "annotations": [ { "font": { "size": 16 }, "showarrow": false, "text": "Body Axes (No Rotation)", "x": 0.225, "xanchor": "center", "xref": "paper", "y": 1, "yanchor": "bottom", "yref": "paper" }, { "font": { "size": 16 }, "showarrow": false, "text": "Rotated (Yaw=45°, Pitch=15°, Roll=10°)", "x": 0.775, "xanchor": "center", "xref": "paper", "y": 1, "yanchor": "bottom", "yref": "paper" } ], "height": 450, "scene": { "aspectmode": "cube", "domain": { "x": [ 0, 0.45 ], "y": [ 0, 1 ] }, "xaxis": { "gridcolor": "#30363d", "range": [ -1, 1 ] }, "yaxis": { "gridcolor": "#30363d", "range": [ -1, 1 ] }, "zaxis": { "gridcolor": "#30363d", "range": [ -1, 1 ] } }, "scene2": { "aspectmode": "cube", "domain": { "x": [ 0.55, 1 ], "y": [ 0, 1 ] }, "xaxis": { "gridcolor": "#30363d", "range": [ -1, 1 ] }, "yaxis": { "gridcolor": "#30363d", "range": [ -1, 1 ] }, "zaxis": { "gridcolor": "#30363d", "range": [ -1, 1 ] } }, "template": { "layout": { "font": { "color": "#e6edf3" }, "paper_bgcolor": "#0d1117", "plot_bgcolor": "#0d1117", "xaxis": { "gridcolor": "#30363d", "zerolinecolor": "#30363d" }, "yaxis": { "gridcolor": "#30363d", "zerolinecolor": "#30363d" } } } } } }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Visualize rotation effect on aircraft axes\n", "# Define aircraft body axes (before rotation)\n", "body_axes = np.array([\n", " [1, 0, 0], # Forward (nose)\n", " [0, 1, 0], # Right wing\n", " [0, 0, 1], # Down\n", "]).T\n", "\n", "# Apply rotation\n", "rotated_axes = R @ body_axes\n", "\n", "fig = make_subplots(rows=1, cols=2, specs=[[{'type': 'scene'}, {'type': 'scene'}]],\n", " subplot_titles=['Body Axes (No Rotation)', \n", " f'Rotated (Yaw={np.degrees(yaw):.0f}°, Pitch={np.degrees(pitch):.0f}°, Roll={np.degrees(roll):.0f}°)'])\n", "\n", "colors = ['red', 'green', 'blue']\n", "labels = ['Forward (X)', 'Right (Y)', 'Down (Z)']\n", "\n", "# Plot before rotation (left)\n", "for i, (color, label) in enumerate(zip(colors, labels)):\n", " fig.add_trace(\n", " go.Scatter3d(x=[0, body_axes[0, i]], y=[0, body_axes[1, i]], z=[0, body_axes[2, i]],\n", " mode='lines', line=dict(color=color, width=6),\n", " name=label),\n", " row=1, col=1\n", " )\n", "\n", "# Plot after rotation (right)\n", "for i, (color, label) in enumerate(zip(colors, labels)):\n", " fig.add_trace(\n", " go.Scatter3d(x=[0, rotated_axes[0, i]], y=[0, rotated_axes[1, i]], z=[0, rotated_axes[2, i]],\n", " mode='lines', line=dict(color=color, width=6),\n", " showlegend=False),\n", " row=1, col=2\n", " )\n", "\n", "scene_layout = dict(\n", " xaxis=dict(range=[-1, 1], gridcolor='#30363d'),\n", " yaxis=dict(range=[-1, 1], gridcolor='#30363d'),\n", " zaxis=dict(range=[-1, 1], gridcolor='#30363d'),\n", " aspectmode='cube'\n", ")\n", "\n", "fig.update_layout(\n", " template=dark_template,\n", " height=450,\n", " scene=scene_layout,\n", " scene2=scene_layout,\n", ")\n", "fig.show()" ] }, { "cell_type": "markdown", "id": "cell-13", "metadata": {}, "source": [ "## 4. Quaternion Operations\n", "\n", "Quaternions are excellent for:\n", "- **Composition**: Multiplying quaternions combines rotations\n", "- **Interpolation**: SLERP provides smooth rotation interpolation\n", "- **Numerical stability**: No gimbal lock issues" ] }, { "cell_type": "code", "execution_count": 10, "id": "cell-14", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Composing rotations:\n", " q1 (30° yaw): [0.96592583 0. 0. 0.25881905]\n", " q2 (20° pitch): [0.98480775 0. 0.17364818 0. ]\n", " q1 * q2: [ 0.95125124 -0.04494346 0.16773126 0.254887 ]\n", "\n", "Composed rotation (Euler):\n", " Yaw: 30.0°, Pitch: 20.0°, Roll: 0.0°\n" ] } ], "source": [ "# Demonstrate quaternion operations\n", "\n", "# Two rotations to compose\n", "q1 = euler2quat(np.radians([30, 0, 0]), 'ZYX') # 30° yaw\n", "q2 = euler2quat(np.radians([0, 20, 0]), 'ZYX') # 20° pitch\n", "\n", "print(\"Composing rotations:\")\n", "print(f\" q1 (30° yaw): {q1}\")\n", "print(f\" q2 (20° pitch): {q2}\")\n", "\n", "# Multiply quaternions (composition)\n", "q_composed = quat_multiply(q1, q2)\n", "print(f\" q1 * q2: {q_composed}\")\n", "\n", "# Convert result back to Euler\n", "euler_composed = quat2euler(q_composed, 'ZYX')\n", "print(f\"\\nComposed rotation (Euler):\")\n", "print(f\" Yaw: {np.degrees(euler_composed[0]):.1f}°, \"\n", " f\"Pitch: {np.degrees(euler_composed[1]):.1f}°, \"\n", " f\"Roll: {np.degrees(euler_composed[2]):.1f}°\")" ] }, { "cell_type": "code", "execution_count": 11, "id": "cell-15", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "SLERP Interpolation:\n", " t | Yaw (°) | Pitch (°) | Roll (°)\n", "---------------------------------------------\n", " 0.00 | 0.00 | -0.00 | 0.00\n", " 0.10 | 14.91 | 4.82 | -5.67\n", " 0.20 | 29.46 | 10.92 | -9.97\n", " 0.30 | 43.94 | 17.90 | -12.65\n", " 0.40 | 58.79 | 25.30 | -13.44\n", " 0.50 | 74.62 | 32.63 | -12.03\n", " 0.60 | 92.16 | 39.31 | -7.96\n", " 0.70 | 112.04 | 44.57 | -0.89\n", " 0.80 | 134.26 | 47.60 | 8.92\n", " 0.90 | 157.59 | 47.76 | 19.98\n", " 1.00 | 180.00 | 45.00 | 30.00\n" ] } ], "source": [ "# SLERP interpolation demonstration\n", "q_start = euler2quat(np.radians([0, 0, 0]), 'ZYX') # No rotation\n", "q_end = euler2quat(np.radians([180, 45, 30]), 'ZYX') # Complex rotation\n", "\n", "# Interpolate\n", "t_values = np.linspace(0, 1, 11)\n", "interpolated = []\n", "\n", "print(\"SLERP Interpolation:\")\n", "print(f\"{'t':>5s} | {'Yaw (°)':>10s} | {'Pitch (°)':>10s} | {'Roll (°)':>10s}\")\n", "print(\"-\" * 45)\n", "\n", "for t in t_values:\n", " q_interp = slerp(q_start, q_end, t)\n", " euler = quat2euler(q_interp, 'ZYX')\n", " interpolated.append(np.degrees(euler))\n", " print(f\"{t:5.2f} | {np.degrees(euler[0]):10.2f} | \"\n", " f\"{np.degrees(euler[1]):10.2f} | {np.degrees(euler[2]):10.2f}\")\n", "\n", "interpolated = np.array(interpolated)" ] }, { "cell_type": "code", "execution_count": 12, "id": "cell-16", "metadata": {}, "outputs": [ { "data": { "application/vnd.plotly.v1+json": { "config": { "plotlyServerURL": "https://plot.ly" }, "data": [ { "line": { "color": "#00d4ff", "width": 2 }, "marker": { "size": 8 }, "mode": "lines+markers", "name": "Yaw", "type": "scatter", "x": { "bdata": "AAAAAAAAAACamZmZmZm5P5qZmZmZmck/NDMzMzMz0z+amZmZmZnZPwAAAAAAAOA/NDMzMzMz4z9nZmZmZmbmP5qZmZmZmek/zczMzMzM7D8AAAAAAADwPw==", "dtype": "f8" }, "y": { "bdata": "AAAAAAAAAAAicbXlkM8tQFCTkzXQdT1ApJRXXPn3RUC1+7Fps2RNQJqYcLSap1JAWwHfhBUKV0BK1IUpSwJcQFWGelQ0yGBAsJ4qGcyyY0AAAAAAAIBmQA==", "dtype": "f8" } }, { "line": { "color": "#ff4757", "width": 2 }, "marker": { "size": 8, "symbol": "square" }, "mode": "lines+markers", "name": "Pitch", "type": "scatter", "x": { "bdata": "AAAAAAAAAACamZmZmZm5P5qZmZmZmck/NDMzMzMz0z+amZmZmZnZPwAAAAAAAOA/NDMzMzMz4z9nZmZmZmbmP5qZmZmZmek/zczMzMzM7D8AAAAAAADwPw==", "dtype": "f8" }, "y": { "bdata": "AAAAAAAAAIDWr548FEgTQBGef8OF2CVA/VYFJnvlMUD/OaHAUkw5QFysbG0OUUBAE1xyLDGnQ0AJFxcnl0lGQE0G7SJlzUdA0CWDDxThR0D//////39GQA==", "dtype": "f8" } }, { "line": { "color": "#00ff88", "width": 2 }, "marker": { "size": 8, "symbol": "triangle-up" }, "mode": "lines+markers", "name": "Roll", "type": "scatter", "x": { "bdata": "AAAAAAAAAACamZmZmZm5P5qZmZmZmck/NDMzMzMz0z+amZmZmZnZPwAAAAAAAOA/NDMzMzMz4z9nZmZmZmbmP5qZmZmZmek/zczMzMzM7D8AAAAAAADwPw==", "dtype": "f8" }, "y": { "bdata": "AAAAAAAAAAD7RmajnbAWwAcPN84v8CPAyeHyj0VKKcBKa5Ozp+MqwNthsy0UDijAFVMhtP7VH8CtklcU0m7sv2NzkQ1l1iFAbljMwJn5M0D///////89QA==", "dtype": "f8" } } ], "layout": { "height": 400, "template": { "layout": { "font": { "color": "#e6edf3" }, "paper_bgcolor": "#0d1117", "plot_bgcolor": "#0d1117", "xaxis": { "gridcolor": "#30363d", "zerolinecolor": "#30363d" }, "yaxis": { "gridcolor": "#30363d", "zerolinecolor": "#30363d" } } }, "title": { "text": "SLERP Quaternion Interpolation" }, "xaxis": { "title": { "text": "Interpolation Parameter t" } }, "yaxis": { "title": { "text": "Angle (degrees)" } } } } }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Visualize SLERP interpolation\n", "fig = go.Figure()\n", "\n", "fig.add_trace(\n", " go.Scatter(x=t_values, y=interpolated[:, 0], mode='lines+markers',\n", " name='Yaw', line=dict(color='#00d4ff', width=2),\n", " marker=dict(size=8))\n", ")\n", "fig.add_trace(\n", " go.Scatter(x=t_values, y=interpolated[:, 1], mode='lines+markers',\n", " name='Pitch', line=dict(color='#ff4757', width=2),\n", " marker=dict(size=8, symbol='square'))\n", ")\n", "fig.add_trace(\n", " go.Scatter(x=t_values, y=interpolated[:, 2], mode='lines+markers',\n", " name='Roll', line=dict(color='#00ff88', width=2),\n", " marker=dict(size=8, symbol='triangle-up'))\n", ")\n", "\n", "fig.update_layout(\n", " template=dark_template,\n", " title='SLERP Quaternion Interpolation',\n", " xaxis_title='Interpolation Parameter t',\n", " yaxis_title='Angle (degrees)',\n", " height=400,\n", ")\n", "fig.show()" ] }, { "cell_type": "markdown", "id": "cell-17", "metadata": {}, "source": [ "## 5. Map Projections\n", "\n", "Map projections convert 3D geodetic coordinates to 2D plane coordinates. Different projections preserve different properties:\n", "\n", "| Projection | Preserves | Distorts | Use Case |\n", "|------------|-----------|----------|----------|\n", "| Mercator | Angles (conformal) | Area | Navigation, web maps |\n", "| UTM | Local distances | At zone edges | Military, surveying |\n", "| Lambert | Angles (conformal) | Poles | Mid-latitude regions |\n", "| Stereographic | Angles (conformal) | Edges | Polar regions |" ] }, { "cell_type": "code", "execution_count": 13, "id": "cell-18", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "UTM Projection Examples\n", "======================================================================\n", "Washington DC : Zone 18N, E= 323383.2m, N= 4318900.7m, Scale=0.999984\n", "London : Zone 30N, E= 699316.2m, N= 5720598.4m, Scale=1.000088\n", "Tokyo : Zone 54N, E= 377855.8m, N= 3958999.5m, Scale=0.999784\n", "Sydney : Zone 56S, E= 334368.6m, N= 6241061.1m, Scale=0.999938\n", "North Pole : UTM not defined (use UPS for polar regions)\n", "Equator/Prime : Zone 31N, E= 166021.4m, N= 0.0m, Scale=1.000981\n" ] } ], "source": [ "# UTM projection example\n", "print(\"UTM Projection Examples\")\n", "print(\"=\" * 70)\n", "\n", "for name, (lat_deg, lon_deg, _) in locations.items():\n", " lat = np.radians(lat_deg)\n", " lon = np.radians(lon_deg)\n", " \n", " # Skip poles (UTM not defined there)\n", " if abs(lat_deg) > 84:\n", " print(f\"{name:15s}: UTM not defined (use UPS for polar regions)\")\n", " continue\n", " \n", " utm = geodetic2utm(lat, lon)\n", " \n", " print(f\"{name:15s}: Zone {utm.zone:2d}{utm.hemisphere}, \"\n", " f\"E={utm.easting:10.1f}m, N={utm.northing:11.1f}m, \"\n", " f\"Scale={utm.scale:.6f}\")" ] }, { "cell_type": "code", "execution_count": 14, "id": "cell-19", "metadata": {}, "outputs": [], "source": [ "# Compare projections for a region\n", "# Generate a grid of points around Washington DC\n", "center_lat = np.radians(38.9)\n", "center_lon = np.radians(-77.0)\n", "\n", "# Create a 10° x 10° grid\n", "lat_range = np.linspace(center_lat - np.radians(5), center_lat + np.radians(5), 20)\n", "lon_range = np.linspace(center_lon - np.radians(5), center_lon + np.radians(5), 20)\n", "\n", "LAT, LON = np.meshgrid(lat_range, lon_range)\n", "\n", "# Project using different methods\n", "mercator_x = np.zeros_like(LAT)\n", "mercator_y = np.zeros_like(LAT)\n", "stereo_x = np.zeros_like(LAT)\n", "stereo_y = np.zeros_like(LAT)\n", "\n", "for i in range(LAT.shape[0]):\n", " for j in range(LAT.shape[1]):\n", " # Mercator\n", " merc = mercator(LAT[i, j], LON[i, j], center_lon)\n", " mercator_x[i, j] = merc.x / 1e6\n", " mercator_y[i, j] = merc.y / 1e6\n", " \n", " # Stereographic\n", " ster = stereographic(LAT[i, j], LON[i, j], center_lat, center_lon)\n", " stereo_x[i, j] = ster.x / 1e6\n", " stereo_y[i, j] = ster.y / 1e6" ] }, { "cell_type": "code", "execution_count": 15, "id": "cell-20", "metadata": {}, "outputs": [ { "data": { "application/vnd.plotly.v1+json": { "config": { "plotlyServerURL": "https://plot.ly" }, "data": [ { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "AAAAAACAVMAAAAAAAIBUwAAAAAAAgFTAAAAAAACAVMAAAAAAAIBUwAAAAAAAgFTAAAAAAACAVMAAAAAAAIBUwAAAAAAAgFTAAAAAAACAVMAAAAAAAIBUwAAAAAAAgFTAAAAAAACAVMAAAAAAAIBUwAAAAAAAgFTAAAAAAACAVMAAAAAAAIBUwAAAAAAAgFTAAAAAAACAVMAAAAAAAIBUwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "MzMzMzPzQEBpxwqEkTZBQJ9b4tTveUFA1O+5JU69QUAKhJF2rABCQEAYaccKREJAdqxAGGmHQkCsQBhpx8pCQOLU77klDkNAGGnHCoRRQ0BO/Z5b4pRDQISRdqxA2ENAuiVO/Z4bREDwuSVO/V5EQCVO/Z5bokRAW+LU77nlRECRdqxAGClFQMcKhJF2bEVA/Z5b4tSvRUAzMzMzM/NFQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "5TWU11BeVMDlNZTXUF5UwOU1lNdQXlTA5TWU11BeVMDlNZTXUF5UwOU1lNdQXlTA5TWU11BeVMDlNZTXUF5UwOU1lNdQXlTA5TWU11BeVMDlNZTXUF5UwOU1lNdQXlTA5TWU11BeVMDlNZTXUF5UwOU1lNdQXlTA5TWU11BeVMDlNZTXUF5UwOU1lNdQXlTA5TWU11BeVMDlNZTXUF5UwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "MzMzMzPzQEBpxwqEkTZBQJ9b4tTveUFA1O+5JU69QUAKhJF2rABCQEAYaccKREJAdqxAGGmHQkCsQBhpx8pCQOLU77klDkNAGGnHCoRRQ0BO/Z5b4pRDQISRdqxA2ENAuiVO/Z4bREDwuSVO/V5EQCVO/Z5bokRAW+LU77nlRECRdqxAGClFQMcKhJF2bEVA/Z5b4tSvRUAzMzMzM/NFQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "ymsor6E8VMDKayivoTxUwMprKK+hPFTAymsor6E8VMDKayivoTxUwMprKK+hPFTAymsor6E8VMDKayivoTxUwMprKK+hPFTAymsor6E8VMDKayivoTxUwMprKK+hPFTAymsor6E8VMDKayivoTxUwMprKK+hPFTAymsor6E8VMDKayivoTxUwMprKK+hPFTAymsor6E8VMDKayivoTxUwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "MzMzMzPzQEBpxwqEkTZBQJ9b4tTveUFA1O+5JU69QUAKhJF2rABCQEAYaccKREJAdqxAGGmHQkCsQBhpx8pCQOLU77klDkNAGGnHCoRRQ0BO/Z5b4pRDQISRdqxA2ENAuiVO/Z4bREDwuSVO/V5EQCVO/Z5bokRAW+LU77nlRECRdqxAGClFQMcKhJF2bEVA/Z5b4tSvRUAzMzMzM/NFQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "r6G8hvIaVMCvobyG8hpUwK+hvIbyGlTAr6G8hvIaVMCvobyG8hpUwK+hvIbyGlTAr6G8hvIaVMCvobyG8hpUwK+hvIbyGlTAr6G8hvIaVMCvobyG8hpUwK+hvIbyGlTAr6G8hvIaVMCvobyG8hpUwK+hvIbyGlTAr6G8hvIaVMCvobyG8hpUwK+hvIbyGlTAr6G8hvIaVMCvobyG8hpUwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "MzMzMzPzQEBpxwqEkTZBQJ9b4tTveUFA1O+5JU69QUAKhJF2rABCQEAYaccKREJAdqxAGGmHQkCsQBhpx8pCQOLU77klDkNAGGnHCoRRQ0BO/Z5b4pRDQISRdqxA2ENAuiVO/Z4bREDwuSVO/V5EQCVO/Z5bokRAW+LU77nlRECRdqxAGClFQMcKhJF2bEVA/Z5b4tSvRUAzMzMzM/NFQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "lNdQXkP5U8CU11BeQ/lTwJTXUF5D+VPAlNdQXkP5U8CU11BeQ/lTwJTXUF5D+VPAlNdQXkP5U8CU11BeQ/lTwJTXUF5D+VPAlNdQXkP5U8CU11BeQ/lTwJTXUF5D+VPAlNdQXkP5U8CU11BeQ/lTwJTXUF5D+VPAlNdQXkP5U8CU11BeQ/lTwJTXUF5D+VPAlNdQXkP5U8CU11BeQ/lTwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "MzMzMzPzQEBpxwqEkTZBQJ9b4tTveUFA1O+5JU69QUAKhJF2rABCQEAYaccKREJAdqxAGGmHQkCsQBhpx8pCQOLU77klDkNAGGnHCoRRQ0BO/Z5b4pRDQISRdqxA2ENAuiVO/Z4bREDwuSVO/V5EQCVO/Z5bokRAW+LU77nlRECRdqxAGClFQMcKhJF2bEVA/Z5b4tSvRUAzMzMzM/NFQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "eQ3lNZTXU8B5DeU1lNdTwHkN5TWU11PAeQ3lNZTXU8B5DeU1lNdTwHkN5TWU11PAeQ3lNZTXU8B5DeU1lNdTwHkN5TWU11PAeQ3lNZTXU8B5DeU1lNdTwHkN5TWU11PAeQ3lNZTXU8B5DeU1lNdTwHkN5TWU11PAeQ3lNZTXU8B5DeU1lNdTwHkN5TWU11PAeQ3lNZTXU8B5DeU1lNdTwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "MzMzMzPzQEBpxwqEkTZBQJ9b4tTveUFA1O+5JU69QUAKhJF2rABCQEAYaccKREJAdqxAGGmHQkCsQBhpx8pCQOLU77klDkNAGGnHCoRRQ0BO/Z5b4pRDQISRdqxA2ENAuiVO/Z4bREDwuSVO/V5EQCVO/Z5bokRAW+LU77nlRECRdqxAGClFQMcKhJF2bEVA/Z5b4tSvRUAzMzMzM/NFQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "XkN5DeW1U8BeQ3kN5bVTwF5DeQ3ltVPAXkN5DeW1U8BeQ3kN5bVTwF5DeQ3ltVPAXkN5DeW1U8BeQ3kN5bVTwF5DeQ3ltVPAXkN5DeW1U8BeQ3kN5bVTwF5DeQ3ltVPAXkN5DeW1U8BeQ3kN5bVTwF5DeQ3ltVPAXkN5DeW1U8BeQ3kN5bVTwF5DeQ3ltVPAXkN5DeW1U8BeQ3kN5bVTwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "MzMzMzPzQEBpxwqEkTZBQJ9b4tTveUFA1O+5JU69QUAKhJF2rABCQEAYaccKREJAdqxAGGmHQkCsQBhpx8pCQOLU77klDkNAGGnHCoRRQ0BO/Z5b4pRDQISRdqxA2ENAuiVO/Z4bREDwuSVO/V5EQCVO/Z5bokRAW+LU77nlRECRdqxAGClFQMcKhJF2bEVA/Z5b4tSvRUAzMzMzM/NFQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "Q3kN5TWUU8BDeQ3lNZRTwEN5DeU1lFPAQ3kN5TWUU8BDeQ3lNZRTwEN5DeU1lFPAQ3kN5TWUU8BDeQ3lNZRTwEN5DeU1lFPAQ3kN5TWUU8BDeQ3lNZRTwEN5DeU1lFPAQ3kN5TWUU8BDeQ3lNZRTwEN5DeU1lFPAQ3kN5TWUU8BDeQ3lNZRTwEN5DeU1lFPAQ3kN5TWUU8BDeQ3lNZRTwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "MzMzMzPzQEBpxwqEkTZBQJ9b4tTveUFA1O+5JU69QUAKhJF2rABCQEAYaccKREJAdqxAGGmHQkCsQBhpx8pCQOLU77klDkNAGGnHCoRRQ0BO/Z5b4pRDQISRdqxA2ENAuiVO/Z4bREDwuSVO/V5EQCVO/Z5bokRAW+LU77nlRECRdqxAGClFQMcKhJF2bEVA/Z5b4tSvRUAzMzMzM/NFQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "KK+hvIZyU8Aor6G8hnJTwCivobyGclPAKK+hvIZyU8Aor6G8hnJTwCivobyGclPAKK+hvIZyU8Aor6G8hnJTwCivobyGclPAKK+hvIZyU8Aor6G8hnJTwCivobyGclPAKK+hvIZyU8Aor6G8hnJTwCivobyGclPAKK+hvIZyU8Aor6G8hnJTwCivobyGclPAKK+hvIZyU8Aor6G8hnJTwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "MzMzMzPzQEBpxwqEkTZBQJ9b4tTveUFA1O+5JU69QUAKhJF2rABCQEAYaccKREJAdqxAGGmHQkCsQBhpx8pCQOLU77klDkNAGGnHCoRRQ0BO/Z5b4pRDQISRdqxA2ENAuiVO/Z4bREDwuSVO/V5EQCVO/Z5bokRAW+LU77nlRECRdqxAGClFQMcKhJF2bEVA/Z5b4tSvRUAzMzMzM/NFQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "DuU1lNdQU8AO5TWU11BTwA7lNZTXUFPADuU1lNdQU8AO5TWU11BTwA7lNZTXUFPADuU1lNdQU8AO5TWU11BTwA7lNZTXUFPADuU1lNdQU8AO5TWU11BTwA7lNZTXUFPADuU1lNdQU8AO5TWU11BTwA7lNZTXUFPADuU1lNdQU8AO5TWU11BTwA7lNZTXUFPADuU1lNdQU8AO5TWU11BTwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "MzMzMzPzQEBpxwqEkTZBQJ9b4tTveUFA1O+5JU69QUAKhJF2rABCQEAYaccKREJAdqxAGGmHQkCsQBhpx8pCQOLU77klDkNAGGnHCoRRQ0BO/Z5b4pRDQISRdqxA2ENAuiVO/Z4bREDwuSVO/V5EQCVO/Z5bokRAW+LU77nlRECRdqxAGClFQMcKhJF2bEVA/Z5b4tSvRUAzMzMzM/NFQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "8xrKaygvU8DzGsprKC9TwPMaymsoL1PA8xrKaygvU8DzGsprKC9TwPMaymsoL1PA8xrKaygvU8DzGsprKC9TwPMaymsoL1PA8xrKaygvU8DzGsprKC9TwPMaymsoL1PA8xrKaygvU8DzGsprKC9TwPMaymsoL1PA8xrKaygvU8DzGsprKC9TwPMaymsoL1PA8xrKaygvU8DzGsprKC9TwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "MzMzMzPzQEBpxwqEkTZBQJ9b4tTveUFA1O+5JU69QUAKhJF2rABCQEAYaccKREJAdqxAGGmHQkCsQBhpx8pCQOLU77klDkNAGGnHCoRRQ0BO/Z5b4pRDQISRdqxA2ENAuiVO/Z4bREDwuSVO/V5EQCVO/Z5bokRAW+LU77nlRECRdqxAGClFQMcKhJF2bEVA/Z5b4tSvRUAzMzMzM/NFQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "2FBeQ3kNU8DYUF5DeQ1TwNhQXkN5DVPA2FBeQ3kNU8DYUF5DeQ1TwNhQXkN5DVPA2FBeQ3kNU8DYUF5DeQ1TwNhQXkN5DVPA2FBeQ3kNU8DYUF5DeQ1TwNhQXkN5DVPA2FBeQ3kNU8DYUF5DeQ1TwNhQXkN5DVPA2FBeQ3kNU8DYUF5DeQ1TwNhQXkN5DVPA2FBeQ3kNU8DYUF5DeQ1TwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "MzMzMzPzQEBpxwqEkTZBQJ9b4tTveUFA1O+5JU69QUAKhJF2rABCQEAYaccKREJAdqxAGGmHQkCsQBhpx8pCQOLU77klDkNAGGnHCoRRQ0BO/Z5b4pRDQISRdqxA2ENAuiVO/Z4bREDwuSVO/V5EQCVO/Z5bokRAW+LU77nlRECRdqxAGClFQMcKhJF2bEVA/Z5b4tSvRUAzMzMzM/NFQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "vobyGsrrUsC+hvIayutSwL6G8hrK61LAvobyGsrrUsC+hvIayutSwL6G8hrK61LAvobyGsrrUsC+hvIayutSwL6G8hrK61LAvobyGsrrUsC+hvIayutSwL6G8hrK61LAvobyGsrrUsC+hvIayutSwL6G8hrK61LAvobyGsrrUsC+hvIayutSwL6G8hrK61LAvobyGsrrUsC+hvIayutSwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "MzMzMzPzQEBpxwqEkTZBQJ9b4tTveUFA1O+5JU69QUAKhJF2rABCQEAYaccKREJAdqxAGGmHQkCsQBhpx8pCQOLU77klDkNAGGnHCoRRQ0BO/Z5b4pRDQISRdqxA2ENAuiVO/Z4bREDwuSVO/V5EQCVO/Z5bokRAW+LU77nlRECRdqxAGClFQMcKhJF2bEVA/Z5b4tSvRUAzMzMzM/NFQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "o7yG8hrKUsCjvIbyGspSwKO8hvIaylLAo7yG8hrKUsCjvIbyGspSwKO8hvIaylLAo7yG8hrKUsCjvIbyGspSwKO8hvIaylLAo7yG8hrKUsCjvIbyGspSwKO8hvIaylLAo7yG8hrKUsCjvIbyGspSwKO8hvIaylLAo7yG8hrKUsCjvIbyGspSwKO8hvIaylLAo7yG8hrKUsCjvIbyGspSwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "MzMzMzPzQEBpxwqEkTZBQJ9b4tTveUFA1O+5JU69QUAKhJF2rABCQEAYaccKREJAdqxAGGmHQkCsQBhpx8pCQOLU77klDkNAGGnHCoRRQ0BO/Z5b4pRDQISRdqxA2ENAuiVO/Z4bREDwuSVO/V5EQCVO/Z5bokRAW+LU77nlRECRdqxAGClFQMcKhJF2bEVA/Z5b4tSvRUAzMzMzM/NFQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "iPIaymuoUsCI8hrKa6hSwIjyGsprqFLAiPIaymuoUsCI8hrKa6hSwIjyGsprqFLAiPIaymuoUsCI8hrKa6hSwIjyGsprqFLAiPIaymuoUsCI8hrKa6hSwIjyGsprqFLAiPIaymuoUsCI8hrKa6hSwIjyGsprqFLAiPIaymuoUsCI8hrKa6hSwIjyGsprqFLAiPIaymuoUsCI8hrKa6hSwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "MzMzMzPzQEBpxwqEkTZBQJ9b4tTveUFA1O+5JU69QUAKhJF2rABCQEAYaccKREJAdqxAGGmHQkCsQBhpx8pCQOLU77klDkNAGGnHCoRRQ0BO/Z5b4pRDQISRdqxA2ENAuiVO/Z4bREDwuSVO/V5EQCVO/Z5bokRAW+LU77nlRECRdqxAGClFQMcKhJF2bEVA/Z5b4tSvRUAzMzMzM/NFQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "bSivobyGUsBtKK+hvIZSwG0or6G8hlLAbSivobyGUsBtKK+hvIZSwG0or6G8hlLAbSivobyGUsBtKK+hvIZSwG0or6G8hlLAbSivobyGUsBtKK+hvIZSwG0or6G8hlLAbSivobyGUsBtKK+hvIZSwG0or6G8hlLAbSivobyGUsBtKK+hvIZSwG0or6G8hlLAbSivobyGUsBtKK+hvIZSwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "MzMzMzPzQEBpxwqEkTZBQJ9b4tTveUFA1O+5JU69QUAKhJF2rABCQEAYaccKREJAdqxAGGmHQkCsQBhpx8pCQOLU77klDkNAGGnHCoRRQ0BO/Z5b4pRDQISRdqxA2ENAuiVO/Z4bREDwuSVO/V5EQCVO/Z5bokRAW+LU77nlRECRdqxAGClFQMcKhJF2bEVA/Z5b4tSvRUAzMzMzM/NFQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "Ul5DeQ1lUsBSXkN5DWVSwFJeQ3kNZVLAUl5DeQ1lUsBSXkN5DWVSwFJeQ3kNZVLAUl5DeQ1lUsBSXkN5DWVSwFJeQ3kNZVLAUl5DeQ1lUsBSXkN5DWVSwFJeQ3kNZVLAUl5DeQ1lUsBSXkN5DWVSwFJeQ3kNZVLAUl5DeQ1lUsBSXkN5DWVSwFJeQ3kNZVLAUl5DeQ1lUsBSXkN5DWVSwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "MzMzMzPzQEBpxwqEkTZBQJ9b4tTveUFA1O+5JU69QUAKhJF2rABCQEAYaccKREJAdqxAGGmHQkCsQBhpx8pCQOLU77klDkNAGGnHCoRRQ0BO/Z5b4pRDQISRdqxA2ENAuiVO/Z4bREDwuSVO/V5EQCVO/Z5bokRAW+LU77nlRECRdqxAGClFQMcKhJF2bEVA/Z5b4tSvRUAzMzMzM/NFQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "N5TXUF5DUsA3lNdQXkNSwDeU11BeQ1LAN5TXUF5DUsA3lNdQXkNSwDeU11BeQ1LAN5TXUF5DUsA3lNdQXkNSwDeU11BeQ1LAN5TXUF5DUsA3lNdQXkNSwDeU11BeQ1LAN5TXUF5DUsA3lNdQXkNSwDeU11BeQ1LAN5TXUF5DUsA3lNdQXkNSwDeU11BeQ1LAN5TXUF5DUsA3lNdQXkNSwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "MzMzMzPzQEBpxwqEkTZBQJ9b4tTveUFA1O+5JU69QUAKhJF2rABCQEAYaccKREJAdqxAGGmHQkCsQBhpx8pCQOLU77klDkNAGGnHCoRRQ0BO/Z5b4pRDQISRdqxA2ENAuiVO/Z4bREDwuSVO/V5EQCVO/Z5bokRAW+LU77nlRECRdqxAGClFQMcKhJF2bEVA/Z5b4tSvRUAzMzMzM/NFQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "HMprKK8hUsAcymsoryFSwBzKayivIVLAHMprKK8hUsAcymsoryFSwBzKayivIVLAHMprKK8hUsAcymsoryFSwBzKayivIVLAHMprKK8hUsAcymsoryFSwBzKayivIVLAHMprKK8hUsAcymsoryFSwBzKayivIVLAHMprKK8hUsAcymsoryFSwBzKayivIVLAHMprKK8hUsAcymsoryFSwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "MzMzMzPzQEBpxwqEkTZBQJ9b4tTveUFA1O+5JU69QUAKhJF2rABCQEAYaccKREJAdqxAGGmHQkCsQBhpx8pCQOLU77klDkNAGGnHCoRRQ0BO/Z5b4pRDQISRdqxA2ENAuiVO/Z4bREDwuSVO/V5EQCVO/Z5bokRAW+LU77nlRECRdqxAGClFQMcKhJF2bEVA/Z5b4tSvRUAzMzMzM/NFQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "AQAAAAAAUsABAAAAAABSwAEAAAAAAFLAAQAAAAAAUsABAAAAAABSwAEAAAAAAFLAAQAAAAAAUsABAAAAAABSwAEAAAAAAFLAAQAAAAAAUsABAAAAAABSwAEAAAAAAFLAAQAAAAAAUsABAAAAAABSwAEAAAAAAFLAAQAAAAAAUsABAAAAAABSwAEAAAAAAFLAAQAAAAAAUsABAAAAAABSwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "MzMzMzPzQEBpxwqEkTZBQJ9b4tTveUFA1O+5JU69QUAKhJF2rABCQEAYaccKREJAdqxAGGmHQkCsQBhpx8pCQOLU77klDkNAGGnHCoRRQ0BO/Z5b4pRDQISRdqxA2ENAuiVO/Z4bREDwuSVO/V5EQCVO/Z5bokRAW+LU77nlRECRdqxAGClFQMcKhJF2bEVA/Z5b4tSvRUAzMzMzM/NFQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "AAAAAACAVMDlNZTXUF5UwMprKK+hPFTAr6G8hvIaVMCU11BeQ/lTwHkN5TWU11PAXkN5DeW1U8BDeQ3lNZRTwCivobyGclPADuU1lNdQU8DzGsprKC9TwNhQXkN5DVPAvobyGsrrUsCjvIbyGspSwIjyGsprqFLAbSivobyGUsBSXkN5DWVSwDeU11BeQ1LAHMprKK8hUsABAAAAAABSwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "MzMzMzPzQEAzMzMzM/NAQDMzMzMz80BAMzMzMzPzQEAzMzMzM/NAQDMzMzMz80BAMzMzMzPzQEAzMzMzM/NAQDMzMzMz80BAMzMzMzPzQEAzMzMzM/NAQDMzMzMz80BAMzMzMzPzQEAzMzMzM/NAQDMzMzMz80BAMzMzMzPzQEAzMzMzM/NAQDMzMzMz80BAMzMzMzPzQEAzMzMzM/NAQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "AAAAAACAVMDlNZTXUF5UwMprKK+hPFTAr6G8hvIaVMCU11BeQ/lTwHkN5TWU11PAXkN5DeW1U8BDeQ3lNZRTwCivobyGclPADuU1lNdQU8DzGsprKC9TwNhQXkN5DVPAvobyGsrrUsCjvIbyGspSwIjyGsprqFLAbSivobyGUsBSXkN5DWVSwDeU11BeQ1LAHMprKK8hUsABAAAAAABSwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "accKhJE2QUBpxwqEkTZBQGnHCoSRNkFAaccKhJE2QUBpxwqEkTZBQGnHCoSRNkFAaccKhJE2QUBpxwqEkTZBQGnHCoSRNkFAaccKhJE2QUBpxwqEkTZBQGnHCoSRNkFAaccKhJE2QUBpxwqEkTZBQGnHCoSRNkFAaccKhJE2QUBpxwqEkTZBQGnHCoSRNkFAaccKhJE2QUBpxwqEkTZBQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "AAAAAACAVMDlNZTXUF5UwMprKK+hPFTAr6G8hvIaVMCU11BeQ/lTwHkN5TWU11PAXkN5DeW1U8BDeQ3lNZRTwCivobyGclPADuU1lNdQU8DzGsprKC9TwNhQXkN5DVPAvobyGsrrUsCjvIbyGspSwIjyGsprqFLAbSivobyGUsBSXkN5DWVSwDeU11BeQ1LAHMprKK8hUsABAAAAAABSwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "n1vi1O95QUCfW+LU73lBQJ9b4tTveUFAn1vi1O95QUCfW+LU73lBQJ9b4tTveUFAn1vi1O95QUCfW+LU73lBQJ9b4tTveUFAn1vi1O95QUCfW+LU73lBQJ9b4tTveUFAn1vi1O95QUCfW+LU73lBQJ9b4tTveUFAn1vi1O95QUCfW+LU73lBQJ9b4tTveUFAn1vi1O95QUCfW+LU73lBQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "AAAAAACAVMDlNZTXUF5UwMprKK+hPFTAr6G8hvIaVMCU11BeQ/lTwHkN5TWU11PAXkN5DeW1U8BDeQ3lNZRTwCivobyGclPADuU1lNdQU8DzGsprKC9TwNhQXkN5DVPAvobyGsrrUsCjvIbyGspSwIjyGsprqFLAbSivobyGUsBSXkN5DWVSwDeU11BeQ1LAHMprKK8hUsABAAAAAABSwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "1O+5JU69QUDU77klTr1BQNTvuSVOvUFA1O+5JU69QUDU77klTr1BQNTvuSVOvUFA1O+5JU69QUDU77klTr1BQNTvuSVOvUFA1O+5JU69QUDU77klTr1BQNTvuSVOvUFA1O+5JU69QUDU77klTr1BQNTvuSVOvUFA1O+5JU69QUDU77klTr1BQNTvuSVOvUFA1O+5JU69QUDU77klTr1BQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "AAAAAACAVMDlNZTXUF5UwMprKK+hPFTAr6G8hvIaVMCU11BeQ/lTwHkN5TWU11PAXkN5DeW1U8BDeQ3lNZRTwCivobyGclPADuU1lNdQU8DzGsprKC9TwNhQXkN5DVPAvobyGsrrUsCjvIbyGspSwIjyGsprqFLAbSivobyGUsBSXkN5DWVSwDeU11BeQ1LAHMprKK8hUsABAAAAAABSwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "CoSRdqwAQkAKhJF2rABCQAqEkXasAEJACoSRdqwAQkAKhJF2rABCQAqEkXasAEJACoSRdqwAQkAKhJF2rABCQAqEkXasAEJACoSRdqwAQkAKhJF2rABCQAqEkXasAEJACoSRdqwAQkAKhJF2rABCQAqEkXasAEJACoSRdqwAQkAKhJF2rABCQAqEkXasAEJACoSRdqwAQkAKhJF2rABCQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "AAAAAACAVMDlNZTXUF5UwMprKK+hPFTAr6G8hvIaVMCU11BeQ/lTwHkN5TWU11PAXkN5DeW1U8BDeQ3lNZRTwCivobyGclPADuU1lNdQU8DzGsprKC9TwNhQXkN5DVPAvobyGsrrUsCjvIbyGspSwIjyGsprqFLAbSivobyGUsBSXkN5DWVSwDeU11BeQ1LAHMprKK8hUsABAAAAAABSwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "QBhpxwpEQkBAGGnHCkRCQEAYaccKREJAQBhpxwpEQkBAGGnHCkRCQEAYaccKREJAQBhpxwpEQkBAGGnHCkRCQEAYaccKREJAQBhpxwpEQkBAGGnHCkRCQEAYaccKREJAQBhpxwpEQkBAGGnHCkRCQEAYaccKREJAQBhpxwpEQkBAGGnHCkRCQEAYaccKREJAQBhpxwpEQkBAGGnHCkRCQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "AAAAAACAVMDlNZTXUF5UwMprKK+hPFTAr6G8hvIaVMCU11BeQ/lTwHkN5TWU11PAXkN5DeW1U8BDeQ3lNZRTwCivobyGclPADuU1lNdQU8DzGsprKC9TwNhQXkN5DVPAvobyGsrrUsCjvIbyGspSwIjyGsprqFLAbSivobyGUsBSXkN5DWVSwDeU11BeQ1LAHMprKK8hUsABAAAAAABSwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "dqxAGGmHQkB2rEAYaYdCQHasQBhph0JAdqxAGGmHQkB2rEAYaYdCQHasQBhph0JAdqxAGGmHQkB2rEAYaYdCQHasQBhph0JAdqxAGGmHQkB2rEAYaYdCQHasQBhph0JAdqxAGGmHQkB2rEAYaYdCQHasQBhph0JAdqxAGGmHQkB2rEAYaYdCQHasQBhph0JAdqxAGGmHQkB2rEAYaYdCQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "AAAAAACAVMDlNZTXUF5UwMprKK+hPFTAr6G8hvIaVMCU11BeQ/lTwHkN5TWU11PAXkN5DeW1U8BDeQ3lNZRTwCivobyGclPADuU1lNdQU8DzGsprKC9TwNhQXkN5DVPAvobyGsrrUsCjvIbyGspSwIjyGsprqFLAbSivobyGUsBSXkN5DWVSwDeU11BeQ1LAHMprKK8hUsABAAAAAABSwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "rEAYacfKQkCsQBhpx8pCQKxAGGnHykJArEAYacfKQkCsQBhpx8pCQKxAGGnHykJArEAYacfKQkCsQBhpx8pCQKxAGGnHykJArEAYacfKQkCsQBhpx8pCQKxAGGnHykJArEAYacfKQkCsQBhpx8pCQKxAGGnHykJArEAYacfKQkCsQBhpx8pCQKxAGGnHykJArEAYacfKQkCsQBhpx8pCQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "AAAAAACAVMDlNZTXUF5UwMprKK+hPFTAr6G8hvIaVMCU11BeQ/lTwHkN5TWU11PAXkN5DeW1U8BDeQ3lNZRTwCivobyGclPADuU1lNdQU8DzGsprKC9TwNhQXkN5DVPAvobyGsrrUsCjvIbyGspSwIjyGsprqFLAbSivobyGUsBSXkN5DWVSwDeU11BeQ1LAHMprKK8hUsABAAAAAABSwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "4tTvuSUOQ0Di1O+5JQ5DQOLU77klDkNA4tTvuSUOQ0Di1O+5JQ5DQOLU77klDkNA4tTvuSUOQ0Di1O+5JQ5DQOLU77klDkNA4tTvuSUOQ0Di1O+5JQ5DQOLU77klDkNA4tTvuSUOQ0Di1O+5JQ5DQOLU77klDkNA4tTvuSUOQ0Di1O+5JQ5DQOLU77klDkNA4tTvuSUOQ0Di1O+5JQ5DQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "AAAAAACAVMDlNZTXUF5UwMprKK+hPFTAr6G8hvIaVMCU11BeQ/lTwHkN5TWU11PAXkN5DeW1U8BDeQ3lNZRTwCivobyGclPADuU1lNdQU8DzGsprKC9TwNhQXkN5DVPAvobyGsrrUsCjvIbyGspSwIjyGsprqFLAbSivobyGUsBSXkN5DWVSwDeU11BeQ1LAHMprKK8hUsABAAAAAABSwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "GGnHCoRRQ0AYaccKhFFDQBhpxwqEUUNAGGnHCoRRQ0AYaccKhFFDQBhpxwqEUUNAGGnHCoRRQ0AYaccKhFFDQBhpxwqEUUNAGGnHCoRRQ0AYaccKhFFDQBhpxwqEUUNAGGnHCoRRQ0AYaccKhFFDQBhpxwqEUUNAGGnHCoRRQ0AYaccKhFFDQBhpxwqEUUNAGGnHCoRRQ0AYaccKhFFDQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "AAAAAACAVMDlNZTXUF5UwMprKK+hPFTAr6G8hvIaVMCU11BeQ/lTwHkN5TWU11PAXkN5DeW1U8BDeQ3lNZRTwCivobyGclPADuU1lNdQU8DzGsprKC9TwNhQXkN5DVPAvobyGsrrUsCjvIbyGspSwIjyGsprqFLAbSivobyGUsBSXkN5DWVSwDeU11BeQ1LAHMprKK8hUsABAAAAAABSwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "Tv2eW+KUQ0BO/Z5b4pRDQE79nlvilENATv2eW+KUQ0BO/Z5b4pRDQE79nlvilENATv2eW+KUQ0BO/Z5b4pRDQE79nlvilENATv2eW+KUQ0BO/Z5b4pRDQE79nlvilENATv2eW+KUQ0BO/Z5b4pRDQE79nlvilENATv2eW+KUQ0BO/Z5b4pRDQE79nlvilENATv2eW+KUQ0BO/Z5b4pRDQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "AAAAAACAVMDlNZTXUF5UwMprKK+hPFTAr6G8hvIaVMCU11BeQ/lTwHkN5TWU11PAXkN5DeW1U8BDeQ3lNZRTwCivobyGclPADuU1lNdQU8DzGsprKC9TwNhQXkN5DVPAvobyGsrrUsCjvIbyGspSwIjyGsprqFLAbSivobyGUsBSXkN5DWVSwDeU11BeQ1LAHMprKK8hUsABAAAAAABSwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "hJF2rEDYQ0CEkXasQNhDQISRdqxA2ENAhJF2rEDYQ0CEkXasQNhDQISRdqxA2ENAhJF2rEDYQ0CEkXasQNhDQISRdqxA2ENAhJF2rEDYQ0CEkXasQNhDQISRdqxA2ENAhJF2rEDYQ0CEkXasQNhDQISRdqxA2ENAhJF2rEDYQ0CEkXasQNhDQISRdqxA2ENAhJF2rEDYQ0CEkXasQNhDQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "AAAAAACAVMDlNZTXUF5UwMprKK+hPFTAr6G8hvIaVMCU11BeQ/lTwHkN5TWU11PAXkN5DeW1U8BDeQ3lNZRTwCivobyGclPADuU1lNdQU8DzGsprKC9TwNhQXkN5DVPAvobyGsrrUsCjvIbyGspSwIjyGsprqFLAbSivobyGUsBSXkN5DWVSwDeU11BeQ1LAHMprKK8hUsABAAAAAABSwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "uiVO/Z4bREC6JU79nhtEQLolTv2eG0RAuiVO/Z4bREC6JU79nhtEQLolTv2eG0RAuiVO/Z4bREC6JU79nhtEQLolTv2eG0RAuiVO/Z4bREC6JU79nhtEQLolTv2eG0RAuiVO/Z4bREC6JU79nhtEQLolTv2eG0RAuiVO/Z4bREC6JU79nhtEQLolTv2eG0RAuiVO/Z4bREC6JU79nhtEQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "AAAAAACAVMDlNZTXUF5UwMprKK+hPFTAr6G8hvIaVMCU11BeQ/lTwHkN5TWU11PAXkN5DeW1U8BDeQ3lNZRTwCivobyGclPADuU1lNdQU8DzGsprKC9TwNhQXkN5DVPAvobyGsrrUsCjvIbyGspSwIjyGsprqFLAbSivobyGUsBSXkN5DWVSwDeU11BeQ1LAHMprKK8hUsABAAAAAABSwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "8LklTv1eREDwuSVO/V5EQPC5JU79XkRA8LklTv1eREDwuSVO/V5EQPC5JU79XkRA8LklTv1eREDwuSVO/V5EQPC5JU79XkRA8LklTv1eREDwuSVO/V5EQPC5JU79XkRA8LklTv1eREDwuSVO/V5EQPC5JU79XkRA8LklTv1eREDwuSVO/V5EQPC5JU79XkRA8LklTv1eREDwuSVO/V5EQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "AAAAAACAVMDlNZTXUF5UwMprKK+hPFTAr6G8hvIaVMCU11BeQ/lTwHkN5TWU11PAXkN5DeW1U8BDeQ3lNZRTwCivobyGclPADuU1lNdQU8DzGsprKC9TwNhQXkN5DVPAvobyGsrrUsCjvIbyGspSwIjyGsprqFLAbSivobyGUsBSXkN5DWVSwDeU11BeQ1LAHMprKK8hUsABAAAAAABSwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "JU79nluiREAlTv2eW6JEQCVO/Z5bokRAJU79nluiREAlTv2eW6JEQCVO/Z5bokRAJU79nluiREAlTv2eW6JEQCVO/Z5bokRAJU79nluiREAlTv2eW6JEQCVO/Z5bokRAJU79nluiREAlTv2eW6JEQCVO/Z5bokRAJU79nluiREAlTv2eW6JEQCVO/Z5bokRAJU79nluiREAlTv2eW6JEQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "AAAAAACAVMDlNZTXUF5UwMprKK+hPFTAr6G8hvIaVMCU11BeQ/lTwHkN5TWU11PAXkN5DeW1U8BDeQ3lNZRTwCivobyGclPADuU1lNdQU8DzGsprKC9TwNhQXkN5DVPAvobyGsrrUsCjvIbyGspSwIjyGsprqFLAbSivobyGUsBSXkN5DWVSwDeU11BeQ1LAHMprKK8hUsABAAAAAABSwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "W+LU77nlREBb4tTvueVEQFvi1O+55URAW+LU77nlREBb4tTvueVEQFvi1O+55URAW+LU77nlREBb4tTvueVEQFvi1O+55URAW+LU77nlREBb4tTvueVEQFvi1O+55URAW+LU77nlREBb4tTvueVEQFvi1O+55URAW+LU77nlREBb4tTvueVEQFvi1O+55URAW+LU77nlREBb4tTvueVEQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "AAAAAACAVMDlNZTXUF5UwMprKK+hPFTAr6G8hvIaVMCU11BeQ/lTwHkN5TWU11PAXkN5DeW1U8BDeQ3lNZRTwCivobyGclPADuU1lNdQU8DzGsprKC9TwNhQXkN5DVPAvobyGsrrUsCjvIbyGspSwIjyGsprqFLAbSivobyGUsBSXkN5DWVSwDeU11BeQ1LAHMprKK8hUsABAAAAAABSwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "kXasQBgpRUCRdqxAGClFQJF2rEAYKUVAkXasQBgpRUCRdqxAGClFQJF2rEAYKUVAkXasQBgpRUCRdqxAGClFQJF2rEAYKUVAkXasQBgpRUCRdqxAGClFQJF2rEAYKUVAkXasQBgpRUCRdqxAGClFQJF2rEAYKUVAkXasQBgpRUCRdqxAGClFQJF2rEAYKUVAkXasQBgpRUCRdqxAGClFQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "AAAAAACAVMDlNZTXUF5UwMprKK+hPFTAr6G8hvIaVMCU11BeQ/lTwHkN5TWU11PAXkN5DeW1U8BDeQ3lNZRTwCivobyGclPADuU1lNdQU8DzGsprKC9TwNhQXkN5DVPAvobyGsrrUsCjvIbyGspSwIjyGsprqFLAbSivobyGUsBSXkN5DWVSwDeU11BeQ1LAHMprKK8hUsABAAAAAABSwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "xwqEkXZsRUDHCoSRdmxFQMcKhJF2bEVAxwqEkXZsRUDHCoSRdmxFQMcKhJF2bEVAxwqEkXZsRUDHCoSRdmxFQMcKhJF2bEVAxwqEkXZsRUDHCoSRdmxFQMcKhJF2bEVAxwqEkXZsRUDHCoSRdmxFQMcKhJF2bEVAxwqEkXZsRUDHCoSRdmxFQMcKhJF2bEVAxwqEkXZsRUDHCoSRdmxFQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "AAAAAACAVMDlNZTXUF5UwMprKK+hPFTAr6G8hvIaVMCU11BeQ/lTwHkN5TWU11PAXkN5DeW1U8BDeQ3lNZRTwCivobyGclPADuU1lNdQU8DzGsprKC9TwNhQXkN5DVPAvobyGsrrUsCjvIbyGspSwIjyGsprqFLAbSivobyGUsBSXkN5DWVSwDeU11BeQ1LAHMprKK8hUsABAAAAAABSwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "/Z5b4tSvRUD9nlvi1K9FQP2eW+LUr0VA/Z5b4tSvRUD9nlvi1K9FQP2eW+LUr0VA/Z5b4tSvRUD9nlvi1K9FQP2eW+LUr0VA/Z5b4tSvRUD9nlvi1K9FQP2eW+LUr0VA/Z5b4tSvRUD9nlvi1K9FQP2eW+LUr0VA/Z5b4tSvRUD9nlvi1K9FQP2eW+LUr0VA/Z5b4tSvRUD9nlvi1K9FQA==", "dtype": "f8" }, "yaxis": "y" }, { "line": { "color": "#00d4ff", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "AAAAAACAVMDlNZTXUF5UwMprKK+hPFTAr6G8hvIaVMCU11BeQ/lTwHkN5TWU11PAXkN5DeW1U8BDeQ3lNZRTwCivobyGclPADuU1lNdQU8DzGsprKC9TwNhQXkN5DVPAvobyGsrrUsCjvIbyGspSwIjyGsprqFLAbSivobyGUsBSXkN5DWVSwDeU11BeQ1LAHMprKK8hUsABAAAAAABSwA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "MzMzMzPzRUAzMzMzM/NFQDMzMzMz80VAMzMzMzPzRUAzMzMzM/NFQDMzMzMz80VAMzMzMzPzRUAzMzMzM/NFQDMzMzMz80VAMzMzMzPzRUAzMzMzM/NFQDMzMzMz80VAMzMzMzPzRUAzMzMzM/NFQDMzMzMz80VAMzMzMzPzRUAzMzMzM/NFQDMzMzMz80VAMzMzMzPzRUAzMzMzM/NFQA==", "dtype": "f8" }, "yaxis": "y" }, { "marker": { "color": "#ff4757", "size": 10 }, "mode": "markers", "name": "Center", "showlegend": true, "type": "scatter", "x": [ -77 ], "xaxis": "x", "y": [ 38.9 ], "yaxis": "y" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "NFG6dqXP4b80Ubp2pc/hvzRRunalz+G/NFG6dqXP4b80Ubp2pc/hvzRRunalz+G/NFG6dqXP4b80Ubp2pc/hvzRRunalz+G/NFG6dqXP4b80Ubp2pc/hvzRRunalz+G/NFG6dqXP4b80Ubp2pc/hvzRRunalz+G/NFG6dqXP4b80Ubp2pc/hvzRRunalz+G/NFG6dqXP4b80Ubp2pc/hvw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "myPKfrLuD0CgkJjqhT8QQD6iP1ooiBBADHNppkPREEAFTsH72hoRQKUvaZzxZBFAQe3e4IqvEUA5lOw4qvoRQNiwpCxTRhJAiDhrXYmSEkAh4QuHUN8SQNq83oCsLBNAhgP8PqF6E0CYAYDTMskTQEg54G9lGBRAnNVSZj1oFEAnpkkrv7gUQCDxAVfvCRVAQYUqp9JbFUDrj6EAbq4VQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "yJ7h/F3f37/InuH8Xd/fv8ie4fxd39+/yJ7h/F3f37/InuH8Xd/fv8ie4fxd39+/yJ7h/F3f37/InuH8Xd/fv8ie4fxd39+/yJ7h/F3f37/InuH8Xd/fv8ie4fxd39+/yJ7h/F3f37/InuH8Xd/fv8ie4fxd39+/yJ7h/F3f37/InuH8Xd/fv8ie4fxd39+/yJ7h/F3f37/InuH8Xd/fvw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "myPKfrLuD0CgkJjqhT8QQD6iP1ooiBBADHNppkPREEAFTsH72hoRQKUvaZzxZBFAQe3e4IqvEUA5lOw4qvoRQNiwpCxTRhJAiDhrXYmSEkAh4QuHUN8SQNq83oCsLBNAhgP8PqF6E0CYAYDTMskTQEg54G9lGBRAnNVSZj1oFEAnpkkrv7gUQCDxAVfvCRVAQYUqp9JbFUDrj6EAbq4VQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "KJtODHEf3L8om04McR/cvyibTgxxH9y/KJtODHEf3L8om04McR/cvyibTgxxH9y/KJtODHEf3L8om04McR/cvyibTgxxH9y/KJtODHEf3L8om04McR/cvyibTgxxH9y/KJtODHEf3L8om04McR/cvyibTgxxH9y/KJtODHEf3L8om04McR/cvyibTgxxH9y/KJtODHEf3L8om04McR/cvw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "myPKfrLuD0CgkJjqhT8QQD6iP1ooiBBADHNppkPREEAFTsH72hoRQKUvaZzxZBFAQe3e4IqvEUA5lOw4qvoRQNiwpCxTRhJAiDhrXYmSEkAh4QuHUN8SQNq83oCsLBNAhgP8PqF6E0CYAYDTMskTQEg54G9lGBRAnNVSZj1oFEAnpkkrv7gUQCDxAVfvCRVAQYUqp9JbFUDrj6EAbq4VQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "h5e7G4Rf2L+Hl7sbhF/Yv4eXuxuEX9i/h5e7G4Rf2L+Hl7sbhF/Yv4eXuxuEX9i/h5e7G4Rf2L+Hl7sbhF/Yv4eXuxuEX9i/h5e7G4Rf2L+Hl7sbhF/Yv4eXuxuEX9i/h5e7G4Rf2L+Hl7sbhF/Yv4eXuxuEX9i/h5e7G4Rf2L+Hl7sbhF/Yv4eXuxuEX9i/h5e7G4Rf2L+Hl7sbhF/Yvw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "myPKfrLuD0CgkJjqhT8QQD6iP1ooiBBADHNppkPREEAFTsH72hoRQKUvaZzxZBFAQe3e4IqvEUA5lOw4qvoRQNiwpCxTRhJAiDhrXYmSEkAh4QuHUN8SQNq83oCsLBNAhgP8PqF6E0CYAYDTMskTQEg54G9lGBRAnNVSZj1oFEAnpkkrv7gUQCDxAVfvCRVAQYUqp9JbFUDrj6EAbq4VQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "5pMoK5ef1L/mkygrl5/Uv+aTKCuXn9S/5pMoK5ef1L/mkygrl5/Uv+aTKCuXn9S/5pMoK5ef1L/mkygrl5/Uv+aTKCuXn9S/5pMoK5ef1L/mkygrl5/Uv+aTKCuXn9S/5pMoK5ef1L/mkygrl5/Uv+aTKCuXn9S/5pMoK5ef1L/mkygrl5/Uv+aTKCuXn9S/5pMoK5ef1L/mkygrl5/Uvw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "myPKfrLuD0CgkJjqhT8QQD6iP1ooiBBADHNppkPREEAFTsH72hoRQKUvaZzxZBFAQe3e4IqvEUA5lOw4qvoRQNiwpCxTRhJAiDhrXYmSEkAh4QuHUN8SQNq83oCsLBNAhgP8PqF6E0CYAYDTMskTQEg54G9lGBRAnNVSZj1oFEAnpkkrv7gUQCDxAVfvCRVAQYUqp9JbFUDrj6EAbq4VQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "RpCVOqrf0L9GkJU6qt/Qv0aQlTqq39C/RpCVOqrf0L9GkJU6qt/Qv0aQlTqq39C/RpCVOqrf0L9GkJU6qt/Qv0aQlTqq39C/RpCVOqrf0L9GkJU6qt/Qv0aQlTqq39C/RpCVOqrf0L9GkJU6qt/Qv0aQlTqq39C/RpCVOqrf0L9GkJU6qt/Qv0aQlTqq39C/RpCVOqrf0L9GkJU6qt/Qvw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "myPKfrLuD0CgkJjqhT8QQD6iP1ooiBBADHNppkPREEAFTsH72hoRQKUvaZzxZBFAQe3e4IqvEUA5lOw4qvoRQNiwpCxTRhJAiDhrXYmSEkAh4QuHUN8SQNq83oCsLBNAhgP8PqF6E0CYAYDTMskTQEg54G9lGBRAnNVSZj1oFEAnpkkrv7gUQCDxAVfvCRVAQYUqp9JbFUDrj6EAbq4VQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "SxkFlHo/yr9LGQWUej/Kv0sZBZR6P8q/SxkFlHo/yr9LGQWUej/Kv0sZBZR6P8q/SxkFlHo/yr9LGQWUej/Kv0sZBZR6P8q/SxkFlHo/yr9LGQWUej/Kv0sZBZR6P8q/SxkFlHo/yr9LGQWUej/Kv0sZBZR6P8q/SxkFlHo/yr9LGQWUej/Kv0sZBZR6P8q/SxkFlHo/yr9LGQWUej/Kvw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "myPKfrLuD0CgkJjqhT8QQD6iP1ooiBBADHNppkPREEAFTsH72hoRQKUvaZzxZBFAQe3e4IqvEUA5lOw4qvoRQNiwpCxTRhJAiDhrXYmSEkAh4QuHUN8SQNq83oCsLBNAhgP8PqF6E0CYAYDTMskTQEg54G9lGBRAnNVSZj1oFEAnpkkrv7gUQCDxAVfvCRVAQYUqp9JbFUDrj6EAbq4VQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "CRLfsqC/wr8JEt+yoL/CvwkS37Kgv8K/CRLfsqC/wr8JEt+yoL/CvwkS37Kgv8K/CRLfsqC/wr8JEt+yoL/CvwkS37Kgv8K/CRLfsqC/wr8JEt+yoL/CvwkS37Kgv8K/CRLfsqC/wr8JEt+yoL/CvwkS37Kgv8K/CRLfsqC/wr8JEt+yoL/CvwkS37Kgv8K/CRLfsqC/wr8JEt+yoL/Cvw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "myPKfrLuD0CgkJjqhT8QQD6iP1ooiBBADHNppkPREEAFTsH72hoRQKUvaZzxZBFAQe3e4IqvEUA5lOw4qvoRQNiwpCxTRhJAiDhrXYmSEkAh4QuHUN8SQNq83oCsLBNAhgP8PqF6E0CYAYDTMskTQEg54G9lGBRAnNVSZj1oFEAnpkkrv7gUQCDxAVfvCRVAQYUqp9JbFUDrj6EAbq4VQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "kRVyo41/tr+RFXKjjX+2v5EVcqONf7a/kRVyo41/tr+RFXKjjX+2v5EVcqONf7a/kRVyo41/tr+RFXKjjX+2v5EVcqONf7a/kRVyo41/tr+RFXKjjX+2v5EVcqONf7a/kRVyo41/tr+RFXKjjX+2v5EVcqONf7a/kRVyo41/tr+RFXKjjX+2v5EVcqONf7a/kRVyo41/tr+RFXKjjX+2vw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "myPKfrLuD0CgkJjqhT8QQD6iP1ooiBBADHNppkPREEAFTsH72hoRQKUvaZzxZBFAQe3e4IqvEUA5lOw4qvoRQNiwpCxTRhJAiDhrXYmSEkAh4QuHUN8SQNq83oCsLBNAhgP8PqF6E0CYAYDTMskTQEg54G9lGBRAnNVSZj1oFEAnpkkrv7gUQCDxAVfvCRVAQYUqp9JbFUDrj6EAbq4VQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "ORyYhGf/nb85HJiEZ/+dvzkcmIRn/52/ORyYhGf/nb85HJiEZ/+dvzkcmIRn/52/ORyYhGf/nb85HJiEZ/+dvzkcmIRn/52/ORyYhGf/nb85HJiEZ/+dvzkcmIRn/52/ORyYhGf/nb85HJiEZ/+dvzkcmIRn/52/ORyYhGf/nb85HJiEZ/+dvzkcmIRn/52/ORyYhGf/nb85HJiEZ/+dvw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "myPKfrLuD0CgkJjqhT8QQD6iP1ooiBBADHNppkPREEAFTsH72hoRQKUvaZzxZBFAQe3e4IqvEUA5lOw4qvoRQNiwpCxTRhJAiDhrXYmSEkAh4QuHUN8SQNq83oCsLBNAhgP8PqF6E0CYAYDTMskTQEg54G9lGBRAnNVSZj1oFEAnpkkrv7gUQCDxAVfvCRVAQYUqp9JbFUDrj6EAbq4VQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "ORyYhGf/nT85HJiEZ/+dPzkcmIRn/50/ORyYhGf/nT85HJiEZ/+dPzkcmIRn/50/ORyYhGf/nT85HJiEZ/+dPzkcmIRn/50/ORyYhGf/nT85HJiEZ/+dPzkcmIRn/50/ORyYhGf/nT85HJiEZ/+dPzkcmIRn/50/ORyYhGf/nT85HJiEZ/+dPzkcmIRn/50/ORyYhGf/nT85HJiEZ/+dPw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "myPKfrLuD0CgkJjqhT8QQD6iP1ooiBBADHNppkPREEAFTsH72hoRQKUvaZzxZBFAQe3e4IqvEUA5lOw4qvoRQNiwpCxTRhJAiDhrXYmSEkAh4QuHUN8SQNq83oCsLBNAhgP8PqF6E0CYAYDTMskTQEg54G9lGBRAnNVSZj1oFEAnpkkrv7gUQCDxAVfvCRVAQYUqp9JbFUDrj6EAbq4VQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "kRVyo41/tj+RFXKjjX+2P5EVcqONf7Y/kRVyo41/tj+RFXKjjX+2P5EVcqONf7Y/kRVyo41/tj+RFXKjjX+2P5EVcqONf7Y/kRVyo41/tj+RFXKjjX+2P5EVcqONf7Y/kRVyo41/tj+RFXKjjX+2P5EVcqONf7Y/kRVyo41/tj+RFXKjjX+2P5EVcqONf7Y/kRVyo41/tj+RFXKjjX+2Pw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "myPKfrLuD0CgkJjqhT8QQD6iP1ooiBBADHNppkPREEAFTsH72hoRQKUvaZzxZBFAQe3e4IqvEUA5lOw4qvoRQNiwpCxTRhJAiDhrXYmSEkAh4QuHUN8SQNq83oCsLBNAhgP8PqF6E0CYAYDTMskTQEg54G9lGBRAnNVSZj1oFEAnpkkrv7gUQCDxAVfvCRVAQYUqp9JbFUDrj6EAbq4VQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "CRLfsqC/wj8JEt+yoL/CPwkS37Kgv8I/CRLfsqC/wj8JEt+yoL/CPwkS37Kgv8I/CRLfsqC/wj8JEt+yoL/CPwkS37Kgv8I/CRLfsqC/wj8JEt+yoL/CPwkS37Kgv8I/CRLfsqC/wj8JEt+yoL/CPwkS37Kgv8I/CRLfsqC/wj8JEt+yoL/CPwkS37Kgv8I/CRLfsqC/wj8JEt+yoL/CPw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "myPKfrLuD0CgkJjqhT8QQD6iP1ooiBBADHNppkPREEAFTsH72hoRQKUvaZzxZBFAQe3e4IqvEUA5lOw4qvoRQNiwpCxTRhJAiDhrXYmSEkAh4QuHUN8SQNq83oCsLBNAhgP8PqF6E0CYAYDTMskTQEg54G9lGBRAnNVSZj1oFEAnpkkrv7gUQCDxAVfvCRVAQYUqp9JbFUDrj6EAbq4VQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "SxkFlHo/yj9LGQWUej/KP0sZBZR6P8o/SxkFlHo/yj9LGQWUej/KP0sZBZR6P8o/SxkFlHo/yj9LGQWUej/KP0sZBZR6P8o/SxkFlHo/yj9LGQWUej/KP0sZBZR6P8o/SxkFlHo/yj9LGQWUej/KP0sZBZR6P8o/SxkFlHo/yj9LGQWUej/KP0sZBZR6P8o/SxkFlHo/yj9LGQWUej/KPw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "myPKfrLuD0CgkJjqhT8QQD6iP1ooiBBADHNppkPREEAFTsH72hoRQKUvaZzxZBFAQe3e4IqvEUA5lOw4qvoRQNiwpCxTRhJAiDhrXYmSEkAh4QuHUN8SQNq83oCsLBNAhgP8PqF6E0CYAYDTMskTQEg54G9lGBRAnNVSZj1oFEAnpkkrv7gUQCDxAVfvCRVAQYUqp9JbFUDrj6EAbq4VQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "RpCVOqrf0D9GkJU6qt/QP0aQlTqq39A/RpCVOqrf0D9GkJU6qt/QP0aQlTqq39A/RpCVOqrf0D9GkJU6qt/QP0aQlTqq39A/RpCVOqrf0D9GkJU6qt/QP0aQlTqq39A/RpCVOqrf0D9GkJU6qt/QP0aQlTqq39A/RpCVOqrf0D9GkJU6qt/QP0aQlTqq39A/RpCVOqrf0D9GkJU6qt/QPw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "myPKfrLuD0CgkJjqhT8QQD6iP1ooiBBADHNppkPREEAFTsH72hoRQKUvaZzxZBFAQe3e4IqvEUA5lOw4qvoRQNiwpCxTRhJAiDhrXYmSEkAh4QuHUN8SQNq83oCsLBNAhgP8PqF6E0CYAYDTMskTQEg54G9lGBRAnNVSZj1oFEAnpkkrv7gUQCDxAVfvCRVAQYUqp9JbFUDrj6EAbq4VQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "5pMoK5ef1D/mkygrl5/UP+aTKCuXn9Q/5pMoK5ef1D/mkygrl5/UP+aTKCuXn9Q/5pMoK5ef1D/mkygrl5/UP+aTKCuXn9Q/5pMoK5ef1D/mkygrl5/UP+aTKCuXn9Q/5pMoK5ef1D/mkygrl5/UP+aTKCuXn9Q/5pMoK5ef1D/mkygrl5/UP+aTKCuXn9Q/5pMoK5ef1D/mkygrl5/UPw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "myPKfrLuD0CgkJjqhT8QQD6iP1ooiBBADHNppkPREEAFTsH72hoRQKUvaZzxZBFAQe3e4IqvEUA5lOw4qvoRQNiwpCxTRhJAiDhrXYmSEkAh4QuHUN8SQNq83oCsLBNAhgP8PqF6E0CYAYDTMskTQEg54G9lGBRAnNVSZj1oFEAnpkkrv7gUQCDxAVfvCRVAQYUqp9JbFUDrj6EAbq4VQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "h5e7G4Rf2D+Hl7sbhF/YP4eXuxuEX9g/h5e7G4Rf2D+Hl7sbhF/YP4eXuxuEX9g/h5e7G4Rf2D+Hl7sbhF/YP4eXuxuEX9g/h5e7G4Rf2D+Hl7sbhF/YP4eXuxuEX9g/h5e7G4Rf2D+Hl7sbhF/YP4eXuxuEX9g/h5e7G4Rf2D+Hl7sbhF/YP4eXuxuEX9g/h5e7G4Rf2D+Hl7sbhF/YPw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "myPKfrLuD0CgkJjqhT8QQD6iP1ooiBBADHNppkPREEAFTsH72hoRQKUvaZzxZBFAQe3e4IqvEUA5lOw4qvoRQNiwpCxTRhJAiDhrXYmSEkAh4QuHUN8SQNq83oCsLBNAhgP8PqF6E0CYAYDTMskTQEg54G9lGBRAnNVSZj1oFEAnpkkrv7gUQCDxAVfvCRVAQYUqp9JbFUDrj6EAbq4VQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "KJtODHEf3D8om04McR/cPyibTgxxH9w/KJtODHEf3D8om04McR/cPyibTgxxH9w/KJtODHEf3D8om04McR/cPyibTgxxH9w/KJtODHEf3D8om04McR/cPyibTgxxH9w/KJtODHEf3D8om04McR/cPyibTgxxH9w/KJtODHEf3D8om04McR/cPyibTgxxH9w/KJtODHEf3D8om04McR/cPw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "myPKfrLuD0CgkJjqhT8QQD6iP1ooiBBADHNppkPREEAFTsH72hoRQKUvaZzxZBFAQe3e4IqvEUA5lOw4qvoRQNiwpCxTRhJAiDhrXYmSEkAh4QuHUN8SQNq83oCsLBNAhgP8PqF6E0CYAYDTMskTQEg54G9lGBRAnNVSZj1oFEAnpkkrv7gUQCDxAVfvCRVAQYUqp9JbFUDrj6EAbq4VQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "yJ7h/F3f3z/InuH8Xd/fP8ie4fxd398/yJ7h/F3f3z/InuH8Xd/fP8ie4fxd398/yJ7h/F3f3z/InuH8Xd/fP8ie4fxd398/yJ7h/F3f3z/InuH8Xd/fP8ie4fxd398/yJ7h/F3f3z/InuH8Xd/fP8ie4fxd398/yJ7h/F3f3z/InuH8Xd/fP8ie4fxd398/yJ7h/F3f3z/InuH8Xd/fPw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "myPKfrLuD0CgkJjqhT8QQD6iP1ooiBBADHNppkPREEAFTsH72hoRQKUvaZzxZBFAQe3e4IqvEUA5lOw4qvoRQNiwpCxTRhJAiDhrXYmSEkAh4QuHUN8SQNq83oCsLBNAhgP8PqF6E0CYAYDTMskTQEg54G9lGBRAnNVSZj1oFEAnpkkrv7gUQCDxAVfvCRVAQYUqp9JbFUDrj6EAbq4VQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "NFG6dqXP4T80Ubp2pc/hPzRRunalz+E/NFG6dqXP4T80Ubp2pc/hPzRRunalz+E/NFG6dqXP4T80Ubp2pc/hPzRRunalz+E/NFG6dqXP4T80Ubp2pc/hPzRRunalz+E/NFG6dqXP4T80Ubp2pc/hPzRRunalz+E/NFG6dqXP4T80Ubp2pc/hPzRRunalz+E/NFG6dqXP4T80Ubp2pc/hPw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "myPKfrLuD0CgkJjqhT8QQD6iP1ooiBBADHNppkPREEAFTsH72hoRQKUvaZzxZBFAQe3e4IqvEUA5lOw4qvoRQNiwpCxTRhJAiDhrXYmSEkAh4QuHUN8SQNq83oCsLBNAhgP8PqF6E0CYAYDTMskTQEg54G9lGBRAnNVSZj1oFEAnpkkrv7gUQCDxAVfvCRVAQYUqp9JbFUDrj6EAbq4VQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "NFG6dqXP4b/InuH8Xd/fvyibTgxxH9y/h5e7G4Rf2L/mkygrl5/Uv0aQlTqq39C/SxkFlHo/yr8JEt+yoL/Cv5EVcqONf7a/ORyYhGf/nb85HJiEZ/+dP5EVcqONf7Y/CRLfsqC/wj9LGQWUej/KP0aQlTqq39A/5pMoK5ef1D+Hl7sbhF/YPyibTgxxH9w/yJ7h/F3f3z80Ubp2pc/hPw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "myPKfrLuD0CbI8p+su4PQJsjyn6y7g9AmyPKfrLuD0CbI8p+su4PQJsjyn6y7g9AmyPKfrLuD0CbI8p+su4PQJsjyn6y7g9AmyPKfrLuD0CbI8p+su4PQJsjyn6y7g9AmyPKfrLuD0CbI8p+su4PQJsjyn6y7g9AmyPKfrLuD0CbI8p+su4PQJsjyn6y7g9AmyPKfrLuD0CbI8p+su4PQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "NFG6dqXP4b/InuH8Xd/fvyibTgxxH9y/h5e7G4Rf2L/mkygrl5/Uv0aQlTqq39C/SxkFlHo/yr8JEt+yoL/Cv5EVcqONf7a/ORyYhGf/nb85HJiEZ/+dP5EVcqONf7Y/CRLfsqC/wj9LGQWUej/KP0aQlTqq39A/5pMoK5ef1D+Hl7sbhF/YPyibTgxxH9w/yJ7h/F3f3z80Ubp2pc/hPw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "oJCY6oU/EECgkJjqhT8QQKCQmOqFPxBAoJCY6oU/EECgkJjqhT8QQKCQmOqFPxBAoJCY6oU/EECgkJjqhT8QQKCQmOqFPxBAoJCY6oU/EECgkJjqhT8QQKCQmOqFPxBAoJCY6oU/EECgkJjqhT8QQKCQmOqFPxBAoJCY6oU/EECgkJjqhT8QQKCQmOqFPxBAoJCY6oU/EECgkJjqhT8QQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "NFG6dqXP4b/InuH8Xd/fvyibTgxxH9y/h5e7G4Rf2L/mkygrl5/Uv0aQlTqq39C/SxkFlHo/yr8JEt+yoL/Cv5EVcqONf7a/ORyYhGf/nb85HJiEZ/+dP5EVcqONf7Y/CRLfsqC/wj9LGQWUej/KP0aQlTqq39A/5pMoK5ef1D+Hl7sbhF/YPyibTgxxH9w/yJ7h/F3f3z80Ubp2pc/hPw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "PqI/WiiIEEA+oj9aKIgQQD6iP1ooiBBAPqI/WiiIEEA+oj9aKIgQQD6iP1ooiBBAPqI/WiiIEEA+oj9aKIgQQD6iP1ooiBBAPqI/WiiIEEA+oj9aKIgQQD6iP1ooiBBAPqI/WiiIEEA+oj9aKIgQQD6iP1ooiBBAPqI/WiiIEEA+oj9aKIgQQD6iP1ooiBBAPqI/WiiIEEA+oj9aKIgQQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "NFG6dqXP4b/InuH8Xd/fvyibTgxxH9y/h5e7G4Rf2L/mkygrl5/Uv0aQlTqq39C/SxkFlHo/yr8JEt+yoL/Cv5EVcqONf7a/ORyYhGf/nb85HJiEZ/+dP5EVcqONf7Y/CRLfsqC/wj9LGQWUej/KP0aQlTqq39A/5pMoK5ef1D+Hl7sbhF/YPyibTgxxH9w/yJ7h/F3f3z80Ubp2pc/hPw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "DHNppkPREEAMc2mmQ9EQQAxzaaZD0RBADHNppkPREEAMc2mmQ9EQQAxzaaZD0RBADHNppkPREEAMc2mmQ9EQQAxzaaZD0RBADHNppkPREEAMc2mmQ9EQQAxzaaZD0RBADHNppkPREEAMc2mmQ9EQQAxzaaZD0RBADHNppkPREEAMc2mmQ9EQQAxzaaZD0RBADHNppkPREEAMc2mmQ9EQQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "NFG6dqXP4b/InuH8Xd/fvyibTgxxH9y/h5e7G4Rf2L/mkygrl5/Uv0aQlTqq39C/SxkFlHo/yr8JEt+yoL/Cv5EVcqONf7a/ORyYhGf/nb85HJiEZ/+dP5EVcqONf7Y/CRLfsqC/wj9LGQWUej/KP0aQlTqq39A/5pMoK5ef1D+Hl7sbhF/YPyibTgxxH9w/yJ7h/F3f3z80Ubp2pc/hPw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "BU7B+9oaEUAFTsH72hoRQAVOwfvaGhFABU7B+9oaEUAFTsH72hoRQAVOwfvaGhFABU7B+9oaEUAFTsH72hoRQAVOwfvaGhFABU7B+9oaEUAFTsH72hoRQAVOwfvaGhFABU7B+9oaEUAFTsH72hoRQAVOwfvaGhFABU7B+9oaEUAFTsH72hoRQAVOwfvaGhFABU7B+9oaEUAFTsH72hoRQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "NFG6dqXP4b/InuH8Xd/fvyibTgxxH9y/h5e7G4Rf2L/mkygrl5/Uv0aQlTqq39C/SxkFlHo/yr8JEt+yoL/Cv5EVcqONf7a/ORyYhGf/nb85HJiEZ/+dP5EVcqONf7Y/CRLfsqC/wj9LGQWUej/KP0aQlTqq39A/5pMoK5ef1D+Hl7sbhF/YPyibTgxxH9w/yJ7h/F3f3z80Ubp2pc/hPw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "pS9pnPFkEUClL2mc8WQRQKUvaZzxZBFApS9pnPFkEUClL2mc8WQRQKUvaZzxZBFApS9pnPFkEUClL2mc8WQRQKUvaZzxZBFApS9pnPFkEUClL2mc8WQRQKUvaZzxZBFApS9pnPFkEUClL2mc8WQRQKUvaZzxZBFApS9pnPFkEUClL2mc8WQRQKUvaZzxZBFApS9pnPFkEUClL2mc8WQRQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "NFG6dqXP4b/InuH8Xd/fvyibTgxxH9y/h5e7G4Rf2L/mkygrl5/Uv0aQlTqq39C/SxkFlHo/yr8JEt+yoL/Cv5EVcqONf7a/ORyYhGf/nb85HJiEZ/+dP5EVcqONf7Y/CRLfsqC/wj9LGQWUej/KP0aQlTqq39A/5pMoK5ef1D+Hl7sbhF/YPyibTgxxH9w/yJ7h/F3f3z80Ubp2pc/hPw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "Qe3e4IqvEUBB7d7giq8RQEHt3uCKrxFAQe3e4IqvEUBB7d7giq8RQEHt3uCKrxFAQe3e4IqvEUBB7d7giq8RQEHt3uCKrxFAQe3e4IqvEUBB7d7giq8RQEHt3uCKrxFAQe3e4IqvEUBB7d7giq8RQEHt3uCKrxFAQe3e4IqvEUBB7d7giq8RQEHt3uCKrxFAQe3e4IqvEUBB7d7giq8RQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "NFG6dqXP4b/InuH8Xd/fvyibTgxxH9y/h5e7G4Rf2L/mkygrl5/Uv0aQlTqq39C/SxkFlHo/yr8JEt+yoL/Cv5EVcqONf7a/ORyYhGf/nb85HJiEZ/+dP5EVcqONf7Y/CRLfsqC/wj9LGQWUej/KP0aQlTqq39A/5pMoK5ef1D+Hl7sbhF/YPyibTgxxH9w/yJ7h/F3f3z80Ubp2pc/hPw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "OZTsOKr6EUA5lOw4qvoRQDmU7Diq+hFAOZTsOKr6EUA5lOw4qvoRQDmU7Diq+hFAOZTsOKr6EUA5lOw4qvoRQDmU7Diq+hFAOZTsOKr6EUA5lOw4qvoRQDmU7Diq+hFAOZTsOKr6EUA5lOw4qvoRQDmU7Diq+hFAOZTsOKr6EUA5lOw4qvoRQDmU7Diq+hFAOZTsOKr6EUA5lOw4qvoRQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "NFG6dqXP4b/InuH8Xd/fvyibTgxxH9y/h5e7G4Rf2L/mkygrl5/Uv0aQlTqq39C/SxkFlHo/yr8JEt+yoL/Cv5EVcqONf7a/ORyYhGf/nb85HJiEZ/+dP5EVcqONf7Y/CRLfsqC/wj9LGQWUej/KP0aQlTqq39A/5pMoK5ef1D+Hl7sbhF/YPyibTgxxH9w/yJ7h/F3f3z80Ubp2pc/hPw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "2LCkLFNGEkDYsKQsU0YSQNiwpCxTRhJA2LCkLFNGEkDYsKQsU0YSQNiwpCxTRhJA2LCkLFNGEkDYsKQsU0YSQNiwpCxTRhJA2LCkLFNGEkDYsKQsU0YSQNiwpCxTRhJA2LCkLFNGEkDYsKQsU0YSQNiwpCxTRhJA2LCkLFNGEkDYsKQsU0YSQNiwpCxTRhJA2LCkLFNGEkDYsKQsU0YSQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "NFG6dqXP4b/InuH8Xd/fvyibTgxxH9y/h5e7G4Rf2L/mkygrl5/Uv0aQlTqq39C/SxkFlHo/yr8JEt+yoL/Cv5EVcqONf7a/ORyYhGf/nb85HJiEZ/+dP5EVcqONf7Y/CRLfsqC/wj9LGQWUej/KP0aQlTqq39A/5pMoK5ef1D+Hl7sbhF/YPyibTgxxH9w/yJ7h/F3f3z80Ubp2pc/hPw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "iDhrXYmSEkCIOGtdiZISQIg4a12JkhJAiDhrXYmSEkCIOGtdiZISQIg4a12JkhJAiDhrXYmSEkCIOGtdiZISQIg4a12JkhJAiDhrXYmSEkCIOGtdiZISQIg4a12JkhJAiDhrXYmSEkCIOGtdiZISQIg4a12JkhJAiDhrXYmSEkCIOGtdiZISQIg4a12JkhJAiDhrXYmSEkCIOGtdiZISQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "NFG6dqXP4b/InuH8Xd/fvyibTgxxH9y/h5e7G4Rf2L/mkygrl5/Uv0aQlTqq39C/SxkFlHo/yr8JEt+yoL/Cv5EVcqONf7a/ORyYhGf/nb85HJiEZ/+dP5EVcqONf7Y/CRLfsqC/wj9LGQWUej/KP0aQlTqq39A/5pMoK5ef1D+Hl7sbhF/YPyibTgxxH9w/yJ7h/F3f3z80Ubp2pc/hPw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "IeELh1DfEkAh4QuHUN8SQCHhC4dQ3xJAIeELh1DfEkAh4QuHUN8SQCHhC4dQ3xJAIeELh1DfEkAh4QuHUN8SQCHhC4dQ3xJAIeELh1DfEkAh4QuHUN8SQCHhC4dQ3xJAIeELh1DfEkAh4QuHUN8SQCHhC4dQ3xJAIeELh1DfEkAh4QuHUN8SQCHhC4dQ3xJAIeELh1DfEkAh4QuHUN8SQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "NFG6dqXP4b/InuH8Xd/fvyibTgxxH9y/h5e7G4Rf2L/mkygrl5/Uv0aQlTqq39C/SxkFlHo/yr8JEt+yoL/Cv5EVcqONf7a/ORyYhGf/nb85HJiEZ/+dP5EVcqONf7Y/CRLfsqC/wj9LGQWUej/KP0aQlTqq39A/5pMoK5ef1D+Hl7sbhF/YPyibTgxxH9w/yJ7h/F3f3z80Ubp2pc/hPw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "2rzegKwsE0DavN6ArCwTQNq83oCsLBNA2rzegKwsE0DavN6ArCwTQNq83oCsLBNA2rzegKwsE0DavN6ArCwTQNq83oCsLBNA2rzegKwsE0DavN6ArCwTQNq83oCsLBNA2rzegKwsE0DavN6ArCwTQNq83oCsLBNA2rzegKwsE0DavN6ArCwTQNq83oCsLBNA2rzegKwsE0DavN6ArCwTQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "NFG6dqXP4b/InuH8Xd/fvyibTgxxH9y/h5e7G4Rf2L/mkygrl5/Uv0aQlTqq39C/SxkFlHo/yr8JEt+yoL/Cv5EVcqONf7a/ORyYhGf/nb85HJiEZ/+dP5EVcqONf7Y/CRLfsqC/wj9LGQWUej/KP0aQlTqq39A/5pMoK5ef1D+Hl7sbhF/YPyibTgxxH9w/yJ7h/F3f3z80Ubp2pc/hPw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "hgP8PqF6E0CGA/w+oXoTQIYD/D6hehNAhgP8PqF6E0CGA/w+oXoTQIYD/D6hehNAhgP8PqF6E0CGA/w+oXoTQIYD/D6hehNAhgP8PqF6E0CGA/w+oXoTQIYD/D6hehNAhgP8PqF6E0CGA/w+oXoTQIYD/D6hehNAhgP8PqF6E0CGA/w+oXoTQIYD/D6hehNAhgP8PqF6E0CGA/w+oXoTQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "NFG6dqXP4b/InuH8Xd/fvyibTgxxH9y/h5e7G4Rf2L/mkygrl5/Uv0aQlTqq39C/SxkFlHo/yr8JEt+yoL/Cv5EVcqONf7a/ORyYhGf/nb85HJiEZ/+dP5EVcqONf7Y/CRLfsqC/wj9LGQWUej/KP0aQlTqq39A/5pMoK5ef1D+Hl7sbhF/YPyibTgxxH9w/yJ7h/F3f3z80Ubp2pc/hPw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "mAGA0zLJE0CYAYDTMskTQJgBgNMyyRNAmAGA0zLJE0CYAYDTMskTQJgBgNMyyRNAmAGA0zLJE0CYAYDTMskTQJgBgNMyyRNAmAGA0zLJE0CYAYDTMskTQJgBgNMyyRNAmAGA0zLJE0CYAYDTMskTQJgBgNMyyRNAmAGA0zLJE0CYAYDTMskTQJgBgNMyyRNAmAGA0zLJE0CYAYDTMskTQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "NFG6dqXP4b/InuH8Xd/fvyibTgxxH9y/h5e7G4Rf2L/mkygrl5/Uv0aQlTqq39C/SxkFlHo/yr8JEt+yoL/Cv5EVcqONf7a/ORyYhGf/nb85HJiEZ/+dP5EVcqONf7Y/CRLfsqC/wj9LGQWUej/KP0aQlTqq39A/5pMoK5ef1D+Hl7sbhF/YPyibTgxxH9w/yJ7h/F3f3z80Ubp2pc/hPw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "SDngb2UYFEBIOeBvZRgUQEg54G9lGBRASDngb2UYFEBIOeBvZRgUQEg54G9lGBRASDngb2UYFEBIOeBvZRgUQEg54G9lGBRASDngb2UYFEBIOeBvZRgUQEg54G9lGBRASDngb2UYFEBIOeBvZRgUQEg54G9lGBRASDngb2UYFEBIOeBvZRgUQEg54G9lGBRASDngb2UYFEBIOeBvZRgUQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "NFG6dqXP4b/InuH8Xd/fvyibTgxxH9y/h5e7G4Rf2L/mkygrl5/Uv0aQlTqq39C/SxkFlHo/yr8JEt+yoL/Cv5EVcqONf7a/ORyYhGf/nb85HJiEZ/+dP5EVcqONf7Y/CRLfsqC/wj9LGQWUej/KP0aQlTqq39A/5pMoK5ef1D+Hl7sbhF/YPyibTgxxH9w/yJ7h/F3f3z80Ubp2pc/hPw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "nNVSZj1oFECc1VJmPWgUQJzVUmY9aBRAnNVSZj1oFECc1VJmPWgUQJzVUmY9aBRAnNVSZj1oFECc1VJmPWgUQJzVUmY9aBRAnNVSZj1oFECc1VJmPWgUQJzVUmY9aBRAnNVSZj1oFECc1VJmPWgUQJzVUmY9aBRAnNVSZj1oFECc1VJmPWgUQJzVUmY9aBRAnNVSZj1oFECc1VJmPWgUQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "NFG6dqXP4b/InuH8Xd/fvyibTgxxH9y/h5e7G4Rf2L/mkygrl5/Uv0aQlTqq39C/SxkFlHo/yr8JEt+yoL/Cv5EVcqONf7a/ORyYhGf/nb85HJiEZ/+dP5EVcqONf7Y/CRLfsqC/wj9LGQWUej/KP0aQlTqq39A/5pMoK5ef1D+Hl7sbhF/YPyibTgxxH9w/yJ7h/F3f3z80Ubp2pc/hPw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "J6ZJK7+4FEAnpkkrv7gUQCemSSu/uBRAJ6ZJK7+4FEAnpkkrv7gUQCemSSu/uBRAJ6ZJK7+4FEAnpkkrv7gUQCemSSu/uBRAJ6ZJK7+4FEAnpkkrv7gUQCemSSu/uBRAJ6ZJK7+4FEAnpkkrv7gUQCemSSu/uBRAJ6ZJK7+4FEAnpkkrv7gUQCemSSu/uBRAJ6ZJK7+4FEAnpkkrv7gUQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "NFG6dqXP4b/InuH8Xd/fvyibTgxxH9y/h5e7G4Rf2L/mkygrl5/Uv0aQlTqq39C/SxkFlHo/yr8JEt+yoL/Cv5EVcqONf7a/ORyYhGf/nb85HJiEZ/+dP5EVcqONf7Y/CRLfsqC/wj9LGQWUej/KP0aQlTqq39A/5pMoK5ef1D+Hl7sbhF/YPyibTgxxH9w/yJ7h/F3f3z80Ubp2pc/hPw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "IPEBV+8JFUAg8QFX7wkVQCDxAVfvCRVAIPEBV+8JFUAg8QFX7wkVQCDxAVfvCRVAIPEBV+8JFUAg8QFX7wkVQCDxAVfvCRVAIPEBV+8JFUAg8QFX7wkVQCDxAVfvCRVAIPEBV+8JFUAg8QFX7wkVQCDxAVfvCRVAIPEBV+8JFUAg8QFX7wkVQCDxAVfvCRVAIPEBV+8JFUAg8QFX7wkVQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "NFG6dqXP4b/InuH8Xd/fvyibTgxxH9y/h5e7G4Rf2L/mkygrl5/Uv0aQlTqq39C/SxkFlHo/yr8JEt+yoL/Cv5EVcqONf7a/ORyYhGf/nb85HJiEZ/+dP5EVcqONf7Y/CRLfsqC/wj9LGQWUej/KP0aQlTqq39A/5pMoK5ef1D+Hl7sbhF/YPyibTgxxH9w/yJ7h/F3f3z80Ubp2pc/hPw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "QYUqp9JbFUBBhSqn0lsVQEGFKqfSWxVAQYUqp9JbFUBBhSqn0lsVQEGFKqfSWxVAQYUqp9JbFUBBhSqn0lsVQEGFKqfSWxVAQYUqp9JbFUBBhSqn0lsVQEGFKqfSWxVAQYUqp9JbFUBBhSqn0lsVQEGFKqfSWxVAQYUqp9JbFUBBhSqn0lsVQEGFKqfSWxVAQYUqp9JbFUBBhSqn0lsVQA==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "NFG6dqXP4b/InuH8Xd/fvyibTgxxH9y/h5e7G4Rf2L/mkygrl5/Uv0aQlTqq39C/SxkFlHo/yr8JEt+yoL/Cv5EVcqONf7a/ORyYhGf/nb85HJiEZ/+dP5EVcqONf7Y/CRLfsqC/wj9LGQWUej/KP0aQlTqq39A/5pMoK5ef1D+Hl7sbhF/YPyibTgxxH9w/yJ7h/F3f3z80Ubp2pc/hPw==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "64+hAG6uFUDrj6EAbq4VQOuPoQBurhVA64+hAG6uFUDrj6EAbq4VQOuPoQBurhVA64+hAG6uFUDrj6EAbq4VQOuPoQBurhVA64+hAG6uFUDrj6EAbq4VQOuPoQBurhVA64+hAG6uFUDrj6EAbq4VQOuPoQBurhVA64+hAG6uFUDrj6EAbq4VQOuPoQBurhVA64+hAG6uFUDrj6EAbq4VQA==", "dtype": "f8" }, "yaxis": "y2" }, { "marker": { "color": "#ff4757", "size": 10 }, "mode": "markers", "showlegend": false, "type": "scatter", "x": [ 0 ], "xaxis": "x2", "y": [ 4.718080625629484 ], "yaxis": "y2" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "/gDhX6az3b/hvp9h6IHdv3IBTNbgT92/ST5TP48d3b+fl/wa8+rcv8jMZOQLuNy/gd95E9mE3L/LbfYcWlHcv/y/XHKOHdy/3orxgXXp27/pZLa2DrXbv8vuY3hZgNu/MK5jK1VL279jmskwARbbv0FaTeZc4Nq/yjJDpmeq2r9ipZTHIHTav229uJ2HPdq/8QuseJsG2r/WUOikW8/Zvw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "muDKUAJq4b+3N9SlXxTfv7dPsjD8VNu/zgRVw8+V179RXx7jz9bTv0wFOxnyF9C/dSJg5FeyyL9ITtL65TTBv/PqGjPzbrO/IxbIQu/Pkb/2IIC3hw6lP1mX43f1grk/aztSU6E/xD/ozfuEKr7LP5wiKJGVntE/09H9/lte1T8ps2v2ch7ZP6gHZ+Pk3tw/k8jvGd5P4D9j5xisgTDiPw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "NpU9GU+T2r/ND2M/0Gbav1Ys/pAPOtq/dtOrnAwN2r9oBTfuxt/Zv6UzlQ4+stm/OFfig3GE2b91w1zRYFbZv+W0YHcLKNm/HZxj83D52L+tI++/kMrYv3Pxm1Rqm9i/IyIMJv1r2L/xfuWlSDzYv7Jsy0JMDNi/z5NYaAfc179UQBh/eavXv7d5f+yhete/NNHlEoBJ179H5n1RExjXvw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "u28sCpl94b+2c4PAhzvfv9uq6MEdfNu/fx38l+m8179hmmHG4P3Tv/qKetT4PtC/3jnnmU4Ayb8YUKV6w4LBv1cTE9Z2CrS/AdrIdgw9lL8BUHzMe9ijPy4T2+M16Lg/MVNfQ2fywz9aIeO8GHHLP34/NhoieNE/xpurQP831T/CgqU+LvjYP+DJj4K5uNw//DxwvtU84D8zJUVQhx3iPw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "fKgwGPRy17+Djml6s0vXvyesdMI4JNe/KyYqjIP81r/tyuRwk9TWv5vWfgdorNa/CnxO5ACE1r+/MSKZXVvWvy7DPLV9Mta/uyVRxWAJ1r8JEX5TBuDVv3laSedtttW/NhObBZeM1b9zaLgwgWLVv0pFPugrONW/4LUbqZYN1b/mCoztwOLUv0+9EC2qt9S/HhFr3FGM1L8Hd5Vtt2DUvw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "UqhKjwGP4b9NsekRVF7fvxs+Gkvkntu/d9IYSKnf179wFPyKmCDUv+uxjJmnYdC/T8Kl+ZdFyb8wO0iB9sfBvyVOxMyrlLS/Ml07SQpllr8BvBTN8MSiPxjyatOuXrg/XFTTM8Wtwz//LgRrmizLP9pOpvT1VdE/NRMaRecV1T9sq9SVK9bYP6UXc1fNltw/gEFVfusr4D8pe119qQziPw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "qNlL0pVS1L/rA6OjkjDUv9+ixRZdDtS/6XzR1PTr07+JtruEWcnTv3QCTsuKptO/EZ4jS4iD0783GqakUWDTv/rvCXbmPNO/SeFKW0YZ07/HJCjucPXSvxFdIMZl0dK/i1pteCSt0r+ep/+XrIjSv+3eebX9Y9K/AMsrXxc/0r/ITg0h+RnSv9EWuYSi9NG/GRJnERPP0b9PsuZLSqnRvw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "6WWoOzye4b+wT35OxXzfv2awJ35Qvdu/0d/sgg/+17/Vmojd9z7Uv9CDXRL/f9C/V/8GUjWCyb9InKpXgATCv8JA+Z2UDbW/uneHqPJHmL99sa3Y4dOhPxoRrOFd5rc/qur697lxwz/TVHhorvDKP3Vb8Y8QONE/6Wi0fhP41D8OFFxxarjYPzbjcNofedw/aOFPFx8d4D+GdJby5/3hPw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "r9AkuzQy0b+b3f9JbhXRvyu2BDh9+NC/nsSfO2Hb0L+7o2kJGr7Qv9+7JFSnoNC/U7S6zAiD0L/FuDkiPmXQv9WS0QFHR9C/YpfQFiMp0L89Z6AK0grQv30GhQmn2M+/SmaZVU6bz78yfspAmV3Pv7j2fQ6HH8+/r0sq/hbhzr/wKU5LSKLOv0FvZy0aY86/3Mrp14sjzr8M/jR6nOPNvw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "ebhUX0mr4b89byMU3Jbfv/nMr/Zi19u/H47M4RwY2L/B7glV/1jUvzxfl9P/mdC/NIahxye2yb/Q05cdYjjCv9XWmH8zdbW/B5kmRc7lmb+Xo8uqSgWhPyeNWPZAf7c/rV+6iEQ+wz+MATazU73KP7LzoG1xHtE/8ZSXcYPe1D/L/vBX6p7YP3Zl25SwX9w/mPBZT3AQ4D/TvTx3QvHhPw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "DL8yiaIjzL8igmv1jfTLvxEYEJ0zxcu/G9ulB5OVy79FXrS5q2XLvwmDwTR9Ncu/hUdN9wYFy7/vTM18SNTKv/IVqD1Bo8q/v/wvr/Bxyr8G4J1DVkDKv92GC2pxDsq/pLptjkHcyb+iFo4ZxqnJv5qMBHH+dsm/050w9+lDyb+dRzILiBDJvx2j4gjY3Mi/6DbMSNmoyL8l+iIgi3TIvw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "w0PsPim24b9idyjqmKzfvxvREToc7du/3cgg6NEt2L++pOxyr27Uvz2gpFyqr9C/HCM6VXDhyb9SkLnJnGPCv1pjqlaKy7W/NQuxkaQ+m79FJw6bJ1mgP1IMykVWKbc/xiONBGQTwz9JoBBuiZLKP7hPTyEYCdE/6KySszbJ1D8bjpvhqonYPyfR9yB/Stw/uXu29N4F4D8uq7XauObhPw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "He4mvtfixb9i5weDOr7Fv105WgJnmcW/XTxc3lx0xb+Pgvi2G0/Fv/PKwimjKcW/krz00fIDxb/jaWpICt7EvyCcniPpt8S/Veam946RxL+Ify9W+2rEvxPkds4tRMS/Vj1J7SUdxL+lj/s84/XDv8ytZkVlzsO/yvHhi6umw78Kuj2TtX7Dv8yqvduCVsO/0LIS4xIuw7/j0lQkZQXDvw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "D22aE9y+4b/sQUxB/L3fv2tnb7d8/tu/rOloAy8/2L/VwAijCIDUv/gNsRf/wNC/mlfGyw8Eyr8L8ZkpMYbCvzkxWbeaELa/22bpwntSnL+dM1c6656fP/k/+FCc5LY/oGSFrxfxwj/kg7jgTnDKP+twp1AE+NA/Hywn7Cy41D9MNbe3q3jYP8zq/imLOdw/Gk/ku9X63z+bqn/0St7hPw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "/9sz5xNEv7+EeN6jxg+/v+yBddYr276/7Qn7+EKmvr8H2R2CC3G+v/8QNeWEO76/0H87kq4Fvr/Gosr1h8+9v4FZFXkQmb2/l0jigUdivb/G6oVyLCu9vxdR3Km+87y/k5BCg/27vL9Q3Y9W6IO8vzFSDnh+S7y/e2RzOL8SvL9kAtjkqdm7vzxcsMY9oLu/q1bDI3pmu7+fpSE+Xiy7vw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "1FYaC2LF4b/E6b5zBsvfv8hOrseEC9y/1jc8izRM2L+GDqM7C43Uv2wLq1n+zdC/Y29u0gYeyr+pTqXhH6DCvzh99+RlRLa/fCjGz1ghnb/j+9qBZNCePyWjd+URsbY/h7RL817Xwj+y1Lp3o1bKP1M7ZbM169A/TC+J1GWr1D+gFfOU7GvYP8aGHWzULNw/PwDH0yfu3z8BozKk+NfhPw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "dH1NDHTCsr/bxr/qEqOyv/qAS0KDg7K/0fiFwsRjsr9qowUZ10Oyv5R+X/G5I7K/CkIk9WwDsr+VYN3L7+Kxvy7ZCRtCwrG/1NcahmOhsb+WJXCuU4Cxv+BnVDMSX7G/Xy75sZ49sb9Kz3LF+Buxv6IRtAYg+rC/8qSJDBTYsL8RZpVr1LWwv5JwSbZgk7C/FvzifLhwsL8zBWVN202wvw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "RKq3R7vJ4b8xPiPFt9Pfv0etea00FNy/ohtLweJU2L+vNG59t5XUv2KMRGKo1tC/RSyP5lUvyr/6qSttabHCv4DbANLsZra/5Wd5cT+rnb8tE1tkt0aePy53eB22jrY/jMEeXznGwj/Of4HEhkXKPy+JVROs4tA/Q6OfN+Gi1D/yR1JFbWPYP0PtdLRaJNw/Mm9W/7Pl3z+SP4DRwdPhPw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "DKa2iEYDmb+8aSP6b9mYv3jqymFbr5i/AohwVAiFmL/VdS5kdlqYv7M7ciClL5i/rfb4FZQEmL8+WsvOQtmXv0hxOdKwrZe/yx7WpN2Bl79lXXLIyFWXv+09GLxxKZe/JaQF/Nf8lr89waYB+8+Wv6ZLkEPaopa/k3N5NXV1lr9lkzVIy0eWv7ubrenbGZa/9DnZhKbrlb/iuLeBKr2Vvw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "wy5P4OfL4b8g2Y9iENjfv8QOQ5WMGNy/yQRg0TlZ2L+yhIuTDZrUvxTN81v92tC/Pge7W/03yr9/v2EeDrrCvyEDHCAweLa/8KN2IzLwnb/o5aZx4QGeP/f/xV+IfbY/vx7Tp6a9wj/lKlN9+DzKP4k5Vkxn3tA/J2gE8p6e1D/PEyymLV/YPwMlG+EdINw/x6poHXrh3z+CKDRsptHhPw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "DKa2iEYDmT+8aSP6b9mYP3jqymFbr5g/AohwVAiFmD/VdS5kdlqYP7M7ciClL5g/rfb4FZQEmD8+WsvOQtmXP0hxOdKwrZc/yx7WpN2Blz9lXXLIyFWXP+09GLxxKZc/JaQF/Nf8lj89waYB+8+WP6ZLkEPaopY/k3N5NXV1lj9lkzVIy0eWP7ubrenbGZY/9DnZhKbrlT/iuLeBKr2VPw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "wy5P4OfL4b8g2Y9iENjfv8QOQ5WMGNy/yQRg0TlZ2L+yhIuTDZrUvxTN81v92tC/Pge7W/03yr9/v2EeDrrCvyEDHCAweLa/8KN2IzLwnb/o5aZx4QGeP/f/xV+IfbY/vx7Tp6a9wj/lKlN9+DzKP4k5Vkxn3tA/J2gE8p6e1D/PEyymLV/YPwMlG+EdINw/x6poHXrh3z+CKDRsptHhPw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "dH1NDHTCsj/bxr/qEqOyP/qAS0KDg7I/0fiFwsRjsj9qowUZ10OyP5R+X/G5I7I/CkIk9WwDsj+VYN3L7+KxPy7ZCRtCwrE/1NcahmOhsT+WJXCuU4CxP+BnVDMSX7E/Xy75sZ49sT9Kz3LF+BuxP6IRtAYg+rA/8qSJDBTYsD8RZpVr1LWwP5JwSbZgk7A/FvzifLhwsD8zBWVN202wPw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "RKq3R7vJ4b8xPiPFt9Pfv0etea00FNy/ohtLweJU2L+vNG59t5XUv2KMRGKo1tC/RSyP5lUvyr/6qSttabHCv4DbANLsZra/5Wd5cT+rnb8tE1tkt0aePy53eB22jrY/jMEeXznGwj/Of4HEhkXKPy+JVROs4tA/Q6OfN+Gi1D/yR1JFbWPYP0PtdLRaJNw/Mm9W/7Pl3z+SP4DRwdPhPw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "/9sz5xNEvz+EeN6jxg+/P+yBddYr274/7Qn7+EKmvj8H2R2CC3G+P/8QNeWEO74/0H87kq4Fvj/Gosr1h8+9P4FZFXkQmb0/l0jigUdivT/G6oVyLCu9PxdR3Km+87w/k5BCg/27vD9Q3Y9W6IO8PzFSDnh+S7w/e2RzOL8SvD9kAtjkqdm7PzxcsMY9oLs/q1bDI3pmuz+fpSE+Xiy7Pw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "1FYaC2LF4b/E6b5zBsvfv8hOrseEC9y/1jc8izRM2L+GDqM7C43Uv2wLq1n+zdC/Y29u0gYeyr+pTqXhH6DCvzh99+RlRLa/fCjGz1ghnb/j+9qBZNCePyWjd+URsbY/h7RL817Xwj+y1Lp3o1bKP1M7ZbM169A/TC+J1GWr1D+gFfOU7GvYP8aGHWzULNw/PwDH0yfu3z8BozKk+NfhPw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "He4mvtfixT9i5weDOr7FP105WgJnmcU/XTxc3lx0xT+Pgvi2G0/FP/PKwimjKcU/krz00fIDxT/jaWpICt7EPyCcniPpt8Q/Veam946RxD+Ify9W+2rEPxPkds4tRMQ/Vj1J7SUdxD+lj/s84/XDP8ytZkVlzsM/yvHhi6umwz8Kuj2TtX7DP8yqvduCVsM/0LIS4xIuwz/j0lQkZQXDPw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "D22aE9y+4b/sQUxB/L3fv2tnb7d8/tu/rOloAy8/2L/VwAijCIDUv/gNsRf/wNC/mlfGyw8Eyr8L8ZkpMYbCvzkxWbeaELa/22bpwntSnL+dM1c6656fP/k/+FCc5LY/oGSFrxfxwj/kg7jgTnDKP+twp1AE+NA/Hywn7Cy41D9MNbe3q3jYP8zq/imLOdw/Gk/ku9X63z+bqn/0St7hPw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "DL8yiaIjzD8igmv1jfTLPxEYEJ0zxcs/G9ulB5OVyz9FXrS5q2XLPwmDwTR9Ncs/hUdN9wYFyz/vTM18SNTKP/IVqD1Bo8o/v/wvr/Bxyj8G4J1DVkDKP92GC2pxDso/pLptjkHcyT+iFo4ZxqnJP5qMBHH+dsk/050w9+lDyT+dRzILiBDJPx2j4gjY3Mg/6DbMSNmoyD8l+iIgi3TIPw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "w0PsPim24b9idyjqmKzfvxvREToc7du/3cgg6NEt2L++pOxyr27Uvz2gpFyqr9C/HCM6VXDhyb9SkLnJnGPCv1pjqlaKy7W/NQuxkaQ+m79FJw6bJ1mgP1IMykVWKbc/xiONBGQTwz9JoBBuiZLKP7hPTyEYCdE/6KySszbJ1D8bjpvhqonYPyfR9yB/Stw/uXu29N4F4D8uq7XauObhPw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "r9AkuzQy0T+b3f9JbhXRPyu2BDh9+NA/nsSfO2Hb0D+7o2kJGr7QP9+7JFSnoNA/U7S6zAiD0D/FuDkiPmXQP9WS0QFHR9A/YpfQFiMp0D89Z6AK0grQP30GhQmn2M8/SmaZVU6bzz8yfspAmV3PP7j2fQ6HH88/r0sq/hbhzj/wKU5LSKLOP0FvZy0aY84/3Mrp14sjzj8M/jR6nOPNPw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "ebhUX0mr4b89byMU3Jbfv/nMr/Zi19u/H47M4RwY2L/B7glV/1jUvzxfl9P/mdC/NIahxye2yb/Q05cdYjjCv9XWmH8zdbW/B5kmRc7lmb+Xo8uqSgWhPyeNWPZAf7c/rV+6iEQ+wz+MATazU73KP7LzoG1xHtE/8ZSXcYPe1D/L/vBX6p7YP3Zl25SwX9w/mPBZT3AQ4D/TvTx3QvHhPw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "qNlL0pVS1D/rA6OjkjDUP9+ixRZdDtQ/6XzR1PTr0z+JtruEWcnTP3QCTsuKptM/EZ4jS4iD0z83GqakUWDTP/rvCXbmPNM/SeFKW0YZ0z/HJCjucPXSPxFdIMZl0dI/i1pteCSt0j+ep/+XrIjSP+3eebX9Y9I/AMsrXxc/0j/ITg0h+RnSP9EWuYSi9NE/GRJnERPP0T9PsuZLSqnRPw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "6WWoOzye4b+wT35OxXzfv2awJ35Qvdu/0d/sgg/+17/Vmojd9z7Uv9CDXRL/f9C/V/8GUjWCyb9InKpXgATCv8JA+Z2UDbW/uneHqPJHmL99sa3Y4dOhPxoRrOFd5rc/qur697lxwz/TVHhorvDKP3Vb8Y8QONE/6Wi0fhP41D8OFFxxarjYPzbjcNofedw/aOFPFx8d4D+GdJby5/3hPw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "fKgwGPRy1z+Djml6s0vXPyesdMI4JNc/KyYqjIP81j/tyuRwk9TWP5vWfgdorNY/CnxO5ACE1j+/MSKZXVvWPy7DPLV9MtY/uyVRxWAJ1j8JEX5TBuDVP3laSedtttU/NhObBZeM1T9zaLgwgWLVP0pFPugrONU/4LUbqZYN1T/mCoztwOLUP0+9EC2qt9Q/HhFr3FGM1D8Hd5Vtt2DUPw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "UqhKjwGP4b9NsekRVF7fvxs+Gkvkntu/d9IYSKnf179wFPyKmCDUv+uxjJmnYdC/T8Kl+ZdFyb8wO0iB9sfBvyVOxMyrlLS/Ml07SQpllr8BvBTN8MSiPxjyatOuXrg/XFTTM8Wtwz//LgRrmizLP9pOpvT1VdE/NRMaRecV1T9sq9SVK9bYP6UXc1fNltw/gEFVfusr4D8pe119qQziPw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "NpU9GU+T2j/ND2M/0GbaP1Ys/pAPOto/dtOrnAwN2j9oBTfuxt/ZP6UzlQ4+stk/OFfig3GE2T91w1zRYFbZP+W0YHcLKNk/HZxj83D52D+tI++/kMrYP3Pxm1Rqm9g/IyIMJv1r2D/xfuWlSDzYP7Jsy0JMDNg/z5NYaAfc1z9UQBh/eavXP7d5f+yhetc/NNHlEoBJ1z9H5n1RExjXPw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "u28sCpl94b+2c4PAhzvfv9uq6MEdfNu/fx38l+m8179hmmHG4P3Tv/qKetT4PtC/3jnnmU4Ayb8YUKV6w4LBv1cTE9Z2CrS/AdrIdgw9lL8BUHzMe9ijPy4T2+M16Lg/MVNfQ2fywz9aIeO8GHHLP34/NhoieNE/xpurQP831T/CgqU+LvjYP+DJj4K5uNw//DxwvtU84D8zJUVQhx3iPw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "/gDhX6az3T/hvp9h6IHdP3IBTNbgT90/ST5TP48d3T+fl/wa8+rcP8jMZOQLuNw/gd95E9mE3D/LbfYcWlHcP/y/XHKOHdw/3orxgXXp2z/pZLa2DrXbP8vuY3hZgNs/MK5jK1VL2z9jmskwARbbP0FaTeZc4No/yjJDpmeq2j9ipZTHIHTaP229uJ2HPdo/8QuseJsG2j/WUOikW8/ZPw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "muDKUAJq4b+3N9SlXxTfv7dPsjD8VNu/zgRVw8+V179RXx7jz9bTv0wFOxnyF9C/dSJg5FeyyL9ITtL65TTBv/PqGjPzbrO/IxbIQu/Pkb/2IIC3hw6lP1mX43f1grk/aztSU6E/xD/ozfuEKr7LP5wiKJGVntE/09H9/lte1T8ps2v2ch7ZP6gHZ+Pk3tw/k8jvGd5P4D9j5xisgTDiPw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "/gDhX6az3b82lT0ZT5Pav3yoMBj0cte/qNlL0pVS1L+v0CS7NDLRvwy/MomiI8y/He4mvtfixb//2zPnE0S/v3R9TQx0wrK/DKa2iEYDmb8MpraIRgOZP3R9TQx0wrI//9sz5xNEvz8d7ia+1+LFPwy/MomiI8w/r9AkuzQy0T+o2UvSlVLUP3yoMBj0ctc/NpU9GU+T2j/+AOFfprPdPw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "muDKUAJq4b+7bywKmX3hv1KoSo8Bj+G/6WWoOzye4b95uFRfSavhv8ND7D4ptuG/D22aE9y+4b/UVhoLYsXhv0Sqt0e7yeG/wy5P4OfL4b/DLk/g58vhv0Sqt0e7yeG/1FYaC2LF4b8PbZoT3L7hv8ND7D4ptuG/ebhUX0mr4b/pZag7PJ7hv1KoSo8Bj+G/u28sCpl94b+a4MpQAmrhvw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "4b6fYeiB3b/ND2M/0Gbav4OOaXqzS9e/6wOjo5Iw1L+b3f9JbhXRvyKCa/WN9Mu/YucHgzq+xb+EeN6jxg+/v9vGv+oSo7K/vGkj+m/ZmL+8aSP6b9mYP9vGv+oSo7I/hHjeo8YPvz9i5weDOr7FPyKCa/WN9Ms/m93/SW4V0T/rA6OjkjDUP4OOaXqzS9c/zQ9jP9Bm2j/hvp9h6IHdPw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "tzfUpV8U37+2c4PAhzvfv02x6RFUXt+/sE9+TsV83789byMU3Jbfv2J3KOqYrN+/7EFMQfy937/E6b5zBsvfvzE+I8W309+/INmPYhDY378g2Y9iENjfvzE+I8W309+/xOm+cwbL37/sQUxB/L3fv2J3KOqYrN+/PW8jFNyW37+wT35OxXzfv02x6RFUXt+/tnODwIc737+3N9SlXxTfvw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "cgFM1uBP3b9WLP6QDzravyesdMI4JNe/36LFFl0O1L8rtgQ4ffjQvxEYEJ0zxcu/XTlaAmeZxb/sgXXWK9u+v/qAS0KDg7K/eOrKYVuvmL946sphW6+YP/qAS0KDg7I/7IF11ivbvj9dOVoCZ5nFPxEYEJ0zxcs/K7YEOH340D/fosUWXQ7UPyesdMI4JNc/Viz+kA862j9yAUzW4E/dPw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "t0+yMPxU27/bqujBHXzbvxs+Gkvkntu/ZrAnflC927/5zK/2YtfbvxvREToc7du/a2dvt3z+27/ITq7HhAvcv0etea00FNy/xA5DlYwY3L/EDkOVjBjcv0etea00FNy/yE6ux4QL3L9rZ2+3fP7bvxvREToc7du/+cyv9mLX279msCd+UL3bvxs+Gkvkntu/26rowR1827+3T7Iw/FTbvw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "ST5TP48d3b9206ucDA3avysmKoyD/Na/6XzR1PTr07+exJ87YdvQvxvbpQeTlcu/XTxc3lx0xb/tCfv4Qqa+v9H4hcLEY7K/AohwVAiFmL8CiHBUCIWYP9H4hcLEY7I/7Qn7+EKmvj9dPFzeXHTFPxvbpQeTlcs/nsSfO2Hb0D/pfNHU9OvTPysmKoyD/NY/dtOrnAwN2j9JPlM/jx3dPw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "zgRVw8+V179/HfyX6bzXv3fSGEip39e/0d/sgg/+178fjszhHBjYv93IIOjRLdi/rOloAy8/2L/WNzyLNEzYv6IbS8HiVNi/yQRg0TlZ2L/JBGDROVnYv6IbS8HiVNi/1jc8izRM2L+s6WgDLz/Yv93IIOjRLdi/H47M4RwY2L/R3+yCD/7Xv3fSGEip39e/fx38l+m817/OBFXDz5XXvw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "n5f8GvPq3L9oBTfuxt/Zv+3K5HCT1Na/iba7hFnJ07+7o2kJGr7Qv0VetLmrZcu/j4L4thtPxb8H2R2CC3G+v2qjBRnXQ7K/1XUuZHZamL/VdS5kdlqYP2qjBRnXQ7I/B9kdggtxvj+Pgvi2G0/FP0VetLmrZcs/u6NpCRq+0D+JtruEWcnTP+3K5HCT1NY/aAU37sbf2T+fl/wa8+rcPw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "UV8e48/W079hmmHG4P3Tv3AU/IqYINS/1ZqI3fc+1L/B7glV/1jUv76k7HKvbtS/1cAIowiA1L+GDqM7C43Uv680bn23ldS/soSLkw2a1L+yhIuTDZrUv680bn23ldS/hg6jOwuN1L/VwAijCIDUv76k7HKvbtS/we4JVf9Y1L/Vmojd9z7Uv3AU/IqYINS/YZphxuD9079RXx7jz9bTvw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "yMxk5Au43L+lM5UOPrLZv5vWfgdorNa/dAJOy4qm07/fuyRUp6DQvwmDwTR9Ncu/88rCKaMpxb//EDXlhDu+v5R+X/G5I7K/sztyIKUvmL+zO3IgpS+YP5R+X/G5I7I//xA15YQ7vj/zysIpoynFPwmDwTR9Ncs/37skVKeg0D90Ak7LiqbTP5vWfgdorNY/pTOVDj6y2T/IzGTkC7jcPw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "TAU7GfIX0L/6inrU+D7Qv+uxjJmnYdC/0INdEv9/0L88X5fT/5nQvz2gpFyqr9C/+A2xF//A0L9sC6tZ/s3Qv2KMRGKo1tC/FM3zW/3a0L8UzfNb/drQv2KMRGKo1tC/bAurWf7N0L/4DbEX/8DQvz2gpFyqr9C/PF+X0/+Z0L/Qg10S/3/Qv+uxjJmnYdC/+op61Pg+0L9MBTsZ8hfQvw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "gd95E9mE3L84V+KDcYTZvwp8TuQAhNa/EZ4jS4iD079TtLrMCIPQv4VHTfcGBcu/krz00fIDxb/QfzuSrgW+vwpCJPVsA7K/rfb4FZQEmL+t9vgVlASYPwpCJPVsA7I/0H87kq4Fvj+SvPTR8gPFP4VHTfcGBcs/U7S6zAiD0D8RniNLiIPTPwp8TuQAhNY/OFfig3GE2T+B33kT2YTcPw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "dSJg5FeyyL/eOeeZTgDJv0/CpfmXRcm/V/8GUjWCyb80hqHHJ7bJvxwjOlVw4cm/mlfGyw8Eyr9jb27SBh7Kv0Usj+ZVL8q/Pge7W/03yr8+B7tb/TfKv0Usj+ZVL8q/Y29u0gYeyr+aV8bLDwTKvxwjOlVw4cm/NIahxye2yb9X/wZSNYLJv0/CpfmXRcm/3jnnmU4Ayb91ImDkV7LIvw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "y232HFpR3L91w1zRYFbZv78xIpldW9a/NxqmpFFg07/FuDkiPmXQv+9MzXxI1Mq/42lqSArexL/Gosr1h8+9v5Vg3cvv4rG/PlrLzkLZl78+WsvOQtmXP5Vg3cvv4rE/xqLK9YfPvT/jaWpICt7EP+9MzXxI1Mo/xbg5Ij5l0D83GqakUWDTP78xIpldW9Y/dcNc0WBW2T/LbfYcWlHcPw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "SE7S+uU0wb8YUKV6w4LBvzA7SIH2x8G/SJyqV4AEwr/Q05cdYjjCv1KQucmcY8K/C/GZKTGGwr+pTqXhH6DCv/qpK21pscK/f79hHg66wr9/v2EeDrrCv/qpK21pscK/qU6l4R+gwr8L8ZkpMYbCv1KQucmcY8K/0NOXHWI4wr9InKpXgATCvzA7SIH2x8G/GFClesOCwb9ITtL65TTBvw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "/L9cco4d3L/ltGB3CyjZvy7DPLV9Mta/+u8JduY807/VktEBR0fQv/IVqD1Bo8q/IJyeI+m3xL+BWRV5EJm9vy7ZCRtCwrG/SHE50rCtl79IcTnSsK2XPy7ZCRtCwrE/gVkVeRCZvT8gnJ4j6bfEP/IVqD1Bo8o/1ZLRAUdH0D/67wl25jzTPy7DPLV9MtY/5bRgdwso2T/8v1xyjh3cPw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "8+oaM/Nus79XExPWdgq0vyVOxMyrlLS/wkD5nZQNtb/V1ph/M3W1v1pjqlaKy7W/OTFZt5oQtr84fffkZUS2v4DbANLsZra/IQMcIDB4tr8hAxwgMHi2v4DbANLsZra/OH335GVEtr85MVm3mhC2v1pjqlaKy7W/1daYfzN1tb/CQPmdlA21vyVOxMyrlLS/VxMT1nYKtL/z6hoz826zvw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "3orxgXXp278dnGPzcPnYv7slUcVgCda/SeFKW0YZ079il9AWIynQv7/8L6/wccq/Veam946RxL+XSOKBR2K9v9TXGoZjobG/yx7WpN2Bl7/LHtak3YGXP9TXGoZjobE/l0jigUdivT9V5qb3jpHEP7/8L6/wcco/YpfQFiMp0D9J4UpbRhnTP7slUcVgCdY/HZxj83D52D/eivGBdenbPw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "IxbIQu/Pkb8B2sh2DD2UvzJdO0kKZZa/uneHqPJHmL8HmSZFzuWZvzULsZGkPpu/22bpwntSnL98KMbPWCGdv+VneXE/q52/8KN2IzLwnb/wo3YjMvCdv+VneXE/q52/fCjGz1ghnb/bZunCe1KcvzULsZGkPpu/B5kmRc7lmb+6d4eo8keYvzJdO0kKZZa/AdrIdgw9lL8jFshC78+Rvw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "6WS2tg6127+tI++/kMrYvwkRflMG4NW/xyQo7nD10r89Z6AK0grQvwbgnUNWQMq/iH8vVvtqxL/G6oVyLCu9v5YlcK5TgLG/ZV1yyMhVl79lXXLIyFWXP5YlcK5TgLE/xuqFciwrvT+Ify9W+2rEPwbgnUNWQMo/PWegCtIK0D/HJCjucPXSPwkRflMG4NU/rSPvv5DK2D/pZLa2DrXbPw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "9iCAt4cOpT8BUHzMe9ijPwG8FM3wxKI/fbGt2OHToT+Xo8uqSgWhP0UnDpsnWaA/nTNXOuuenz/j+9qBZNCePy0TW2S3Rp4/6OWmceEBnj/o5aZx4QGePy0TW2S3Rp4/4/vagWTQnj+dM1c6656fP0UnDpsnWaA/l6PLqkoFoT99sa3Y4dOhPwG8FM3wxKI/AVB8zHvYoz/2IIC3hw6lPw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "y+5jeFmA279z8ZtUapvYv3laSedtttW/EV0gxmXR0r99BoUJp9jPv92GC2pxDsq/E+R2zi1ExL8XUdypvvO8v+BnVDMSX7G/7T0YvHEpl7/tPRi8cSmXP+BnVDMSX7E/F1Hcqb7zvD8T5HbOLUTEP92GC2pxDso/fQaFCafYzz8RXSDGZdHSP3laSedtttU/c/GbVGqb2D/L7mN4WYDbPw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "WZfjd/WCuT8uE9vjNei4PxjyatOuXrg/GhGs4V3mtz8njVj2QH+3P1IMykVWKbc/+T/4UJzktj8lo3flEbG2Py53eB22jrY/9//FX4h9tj/3/8VfiH22Py53eB22jrY/JaN35RGxtj/5P/hQnOS2P1IMykVWKbc/J41Y9kB/tz8aEazhXea3PxjyatOuXrg/LhPb4zXouD9Zl+N39YK5Pw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "MK5jK1VL278jIgwm/WvYvzYTmwWXjNW/i1pteCSt0r9KZplVTpvPv6S6bY5B3Mm/Vj1J7SUdxL+TkEKD/bu8v18u+bGePbG/JaQF/Nf8lr8lpAX81/yWP18u+bGePbE/k5BCg/27vD9WPUntJR3EP6S6bY5B3Mk/SmaZVU6bzz+LWm14JK3SPzYTmwWXjNU/IyIMJv1r2D8wrmMrVUvbPw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "aztSU6E/xD8xU19DZ/LDP1xU0zPFrcM/qur697lxwz+tX7qIRD7DP8YjjQRkE8M/oGSFrxfxwj+HtEvzXtfCP4zBHl85xsI/vx7Tp6a9wj+/HtOnpr3CP4zBHl85xsI/h7RL817Xwj+gZIWvF/HCP8YjjQRkE8M/rV+6iEQ+wz+q6vr3uXHDP1xU0zPFrcM/MVNfQ2fywz9rO1JToT/EPw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "Y5rJMAEW27/xfuWlSDzYv3NouDCBYtW/nqf/l6yI0r8yfspAmV3Pv6IWjhnGqcm/pY/7POP1w79Q3Y9W6IO8v0rPcsX4G7G/PcGmAfvPlr89waYB+8+WP0rPcsX4G7E/UN2PVuiDvD+lj/s84/XDP6IWjhnGqck/Mn7KQJldzz+ep/+XrIjSP3NouDCBYtU/8X7lpUg82D9jmskwARbbPw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "6M37hCq+yz9aIeO8GHHLP/8uBGuaLMs/01R4aK7wyj+MATazU73KP0mgEG6Jkso/5IO44E5wyj+y1Lp3o1bKP85/gcSGRco/5SpTffg8yj/lKlN9+DzKP85/gcSGRco/stS6d6NWyj/kg7jgTnDKP0mgEG6Jkso/jAE2s1O9yj/TVHhorvDKP/8uBGuaLMs/WiHjvBhxyz/ozfuEKr7LPw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "QVpN5lzg2r+ybMtCTAzYv0pFPugrONW/7d55tf1j0r+49n0Ohx/Pv5qMBHH+dsm/zK1mRWXOw78xUg54fku8v6IRtAYg+rC/pkuQQ9qilr+mS5BD2qKWP6IRtAYg+rA/MVIOeH5LvD/MrWZFZc7DP5qMBHH+dsk/uPZ9Docfzz/t3nm1/WPSP0pFPugrONU/smzLQkwM2D9BWk3mXODaPw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "nCIokZWe0T9+PzYaInjRP9pOpvT1VdE/dVvxjxA40T+y86BtcR7RP7hPTyEYCdE/63CnUAT40D9TO2WzNevQPy+JVROs4tA/iTlWTGfe0D+JOVZMZ97QPy+JVROs4tA/UztlszXr0D/rcKdQBPjQP7hPTyEYCdE/svOgbXEe0T91W/GPEDjRP9pOpvT1VdE/fj82GiJ40T+cIiiRlZ7RPw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "yjJDpmeq2r/Pk1hoB9zXv+C1G6mWDdW/AMsrXxc/0r+vSyr+FuHOv9OdMPfpQ8m/yvHhi6umw797ZHM4vxK8v/KkiQwU2LC/k3N5NXV1lr+Tc3k1dXWWP/KkiQwU2LA/e2RzOL8SvD/K8eGLq6bDP9OdMPfpQ8k/r0sq/hbhzj8AyytfFz/SP+C1G6mWDdU/z5NYaAfc1z/KMkOmZ6raPw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "09H9/lte1T/Gm6tA/zfVPzUTGkXnFdU/6Wi0fhP41D/xlJdxg97UP+iskrM2ydQ/Hywn7Cy41D9ML4nUZavUP0OjnzfhotQ/J2gE8p6e1D8naATynp7UP0OjnzfhotQ/TC+J1GWr1D8fLCfsLLjUP+iskrM2ydQ/8ZSXcYPe1D/paLR+E/jUPzUTGkXnFdU/xpurQP831T/T0f3+W17VPw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "YqWUxyB02r9UQBh/eavXv+YKjO3A4tS/yE4NIfkZ0r/wKU5LSKLOv51HMguIEMm/Cro9k7V+w79kAtjkqdm7vxFmlWvUtbC/ZZM1SMtHlr9lkzVIy0eWPxFmlWvUtbA/ZALY5KnZuz8Kuj2TtX7DP51HMguIEMk/8ClOS0iizj/ITg0h+RnSP+YKjO3A4tQ/VEAYf3mr1z9ipZTHIHTaPw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "KbNr9nIe2T/CgqU+LvjYP2yr1JUr1tg/DhRccWq42D/L/vBX6p7YPxuOm+Gqidg/TDW3t6t42D+gFfOU7GvYP/JHUkVtY9g/zxMspi1f2D/PEyymLV/YP/JHUkVtY9g/oBXzlOxr2D9MNbe3q3jYPxuOm+Gqidg/y/7wV+qe2D8OFFxxarjYP2yr1JUr1tg/woKlPi742D8ps2v2ch7ZPw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "bb24nYc92r+3eX/soXrXv0+9EC2qt9S/0Ra5hKL00b9Bb2ctGmPOvx2j4gjY3Mi/zKq924JWw788XLDGPaC7v5JwSbZgk7C/u5ut6dsZlr+7m63p2xmWP5JwSbZgk7A/PFywxj2guz/Mqr3bglbDPx2j4gjY3Mg/QW9nLRpjzj/RFrmEovTRP0+9EC2qt9Q/t3l/7KF61z9tvbidhz3aPw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "qAdn4+Te3D/gyY+CubjcP6UXc1fNltw/NuNw2h953D92ZduUsF/cPyfR9yB/Stw/zOr+KYs53D/Ghh1s1CzcP0PtdLRaJNw/AyUb4R0g3D8DJRvhHSDcP0PtdLRaJNw/xoYdbNQs3D/M6v4pizncPyfR9yB/Stw/dmXblLBf3D8243DaH3ncP6UXc1fNltw/4MmPgrm43D+oB2fj5N7cPw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "8QuseJsG2r800eUSgEnXvx4Ra9xRjNS/GRJnERPP0b/cyunXiyPOv+g2zEjZqMi/0LIS4xIuw7+rVsMjema7vxb84ny4cLC/9DnZhKbrlb/0OdmEpuuVPxb84ny4cLA/q1bDI3pmuz/QshLjEi7DP+g2zEjZqMg/3Mrp14sjzj8ZEmcRE8/RPx4Ra9xRjNQ/NNHlEoBJ1z/xC6x4mwbaPw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "k8jvGd5P4D/8PHC+1TzgP4BBVX7rK+A/aOFPFx8d4D+Y8FlPcBDgP7l7tvTeBeA/Gk/ku9X63z8/AMfTJ+7fPzJvVv+z5d8/x6poHXrh3z/HqmgdeuHfPzJvVv+z5d8/PwDH0yfu3z8aT+S71frfP7l7tvTeBeA/mPBZT3AQ4D9o4U8XHx3gP4BBVX7rK+A//DxwvtU84D+TyO8Z3k/gPw==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#a855f7", "width": 1 }, "mode": "lines", "opacity": 0.5, "showlegend": false, "type": "scatter", "x": { "bdata": "1lDopFvP2b9H5n1RExjXvwd3lW23YNS/T7LmS0qp0b8M/jR6nOPNvyX6IiCLdMi/49JUJGUFw7+fpSE+Xiy7vzMFZU3bTbC/4ri3gSq9lb/iuLeBKr2VPzMFZU3bTbA/n6UhPl4suz/j0lQkZQXDPyX6IiCLdMg/DP40epzjzT9PsuZLSqnRPwd3lW23YNQ/R+Z9URMY1z/WUOikW8/ZPw==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "Y+cYrIEw4j8zJUVQhx3iPyl7XX2pDOI/hnSW8uf94T/TvTx3QvHhPy6rtdq45uE/m6p/9Ere4T8BozKk+NfhP5I/gNHB0+E/gig0bKbR4T+CKDRsptHhP5I/gNHB0+E/AaMypPjX4T+bqn/0St7hPy6rtdq45uE/0708d0Lx4T+GdJby5/3hPyl7XX2pDOI/MyVFUIcd4j9j5xisgTDiPw==", "dtype": "f8" }, "yaxis": "y3" }, { "marker": { "color": "#ff4757", "size": 10 }, "mode": "markers", "showlegend": false, "type": "scatter", "x": [ 0 ], "xaxis": "x3", "y": [ 0 ], "yaxis": "y3" } ], "layout": { "annotations": [ { "font": { "size": 16 }, "showarrow": false, "text": "Geographic (Lat/Lon)", "x": 0.13999999999999999, "xanchor": "center", "xref": "paper", "y": 1, "yanchor": "bottom", "yref": "paper" }, { "font": { "size": 16 }, "showarrow": false, "text": "Mercator Projection", "x": 0.49999999999999994, "xanchor": "center", "xref": "paper", "y": 1, "yanchor": "bottom", "yref": "paper" }, { "font": { "size": 16 }, "showarrow": false, "text": "Stereographic Projection", "x": 0.86, "xanchor": "center", "xref": "paper", "y": 1, "yanchor": "bottom", "yref": "paper" } ], "height": 400, "template": { "layout": { "font": { "color": "#e6edf3" }, "paper_bgcolor": "#0d1117", "plot_bgcolor": "#0d1117", "xaxis": { "gridcolor": "#30363d", "zerolinecolor": "#30363d" }, "yaxis": { "gridcolor": "#30363d", "zerolinecolor": "#30363d" } } }, "xaxis": { "anchor": "y", "domain": [ 0, 0.27999999999999997 ], "scaleanchor": "y", "scaleratio": 1, "title": { "text": "Longitude (°)" } }, "xaxis2": { "anchor": "y2", "domain": [ 0.36, 0.6399999999999999 ], "scaleanchor": "y2", "scaleratio": 1, "title": { "text": "Easting (million m)" } }, "xaxis3": { "anchor": "y3", "domain": [ 0.72, 1 ], "scaleanchor": "y3", "scaleratio": 1, "title": { "text": "Easting (million m)" } }, "yaxis": { "anchor": "x", "domain": [ 0, 1 ], "title": { "text": "Latitude (°)" } }, "yaxis2": { "anchor": "x2", "domain": [ 0, 1 ], "title": { "text": "Northing (million m)" } }, "yaxis3": { "anchor": "x3", "domain": [ 0, 1 ], "title": { "text": "Northing (million m)" } } } } }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Visualize projection comparison\n", "fig = make_subplots(rows=1, cols=3, \n", " subplot_titles=['Geographic (Lat/Lon)', 'Mercator Projection', 'Stereographic Projection'],\n", " horizontal_spacing=0.08)\n", "\n", "# Original lat/lon grid\n", "for i in range(LAT.shape[0]):\n", " fig.add_trace(\n", " go.Scatter(x=np.degrees(LON[i, :]), y=np.degrees(LAT[i, :]),\n", " mode='lines', line=dict(color='#00d4ff', width=1), opacity=0.5,\n", " showlegend=False),\n", " row=1, col=1\n", " )\n", "for j in range(LAT.shape[1]):\n", " fig.add_trace(\n", " go.Scatter(x=np.degrees(LON[:, j]), y=np.degrees(LAT[:, j]),\n", " mode='lines', line=dict(color='#00d4ff', width=1), opacity=0.5,\n", " showlegend=False),\n", " row=1, col=1\n", " )\n", "fig.add_trace(\n", " go.Scatter(x=[np.degrees(center_lon)], y=[np.degrees(center_lat)],\n", " mode='markers', marker=dict(color='#ff4757', size=10),\n", " name='Center', showlegend=True),\n", " row=1, col=1\n", ")\n", "\n", "# Mercator\n", "for i in range(LAT.shape[0]):\n", " fig.add_trace(\n", " go.Scatter(x=mercator_x[i, :], y=mercator_y[i, :],\n", " mode='lines', line=dict(color='#00ff88', width=1), opacity=0.5,\n", " showlegend=False),\n", " row=1, col=2\n", " )\n", "for j in range(LAT.shape[1]):\n", " fig.add_trace(\n", " go.Scatter(x=mercator_x[:, j], y=mercator_y[:, j],\n", " mode='lines', line=dict(color='#00ff88', width=1), opacity=0.5,\n", " showlegend=False),\n", " row=1, col=2\n", " )\n", "fig.add_trace(\n", " go.Scatter(x=[0], y=[mercator_y[10, 10]],\n", " mode='markers', marker=dict(color='#ff4757', size=10),\n", " showlegend=False),\n", " row=1, col=2\n", ")\n", "\n", "# Stereographic\n", "for i in range(LAT.shape[0]):\n", " fig.add_trace(\n", " go.Scatter(x=stereo_x[i, :], y=stereo_y[i, :],\n", " mode='lines', line=dict(color='#a855f7', width=1), opacity=0.5,\n", " showlegend=False),\n", " row=1, col=3\n", " )\n", "for j in range(LAT.shape[1]):\n", " fig.add_trace(\n", " go.Scatter(x=stereo_x[:, j], y=stereo_y[:, j],\n", " mode='lines', line=dict(color='#a855f7', width=1), opacity=0.5,\n", " showlegend=False),\n", " row=1, col=3\n", " )\n", "fig.add_trace(\n", " go.Scatter(x=[0], y=[0],\n", " mode='markers', marker=dict(color='#ff4757', size=10),\n", " showlegend=False),\n", " row=1, col=3\n", ")\n", "\n", "fig.update_layout(\n", " template=dark_template,\n", " height=400,\n", ")\n", "fig.update_xaxes(title_text='Longitude (°)', row=1, col=1, scaleanchor='y', scaleratio=1)\n", "fig.update_xaxes(title_text='Easting (million m)', row=1, col=2, scaleanchor='y2', scaleratio=1)\n", "fig.update_xaxes(title_text='Easting (million m)', row=1, col=3, scaleanchor='y3', scaleratio=1)\n", "fig.update_yaxes(title_text='Latitude (°)', row=1, col=1)\n", "fig.update_yaxes(title_text='Northing (million m)', row=1, col=2)\n", "fig.update_yaxes(title_text='Northing (million m)', row=1, col=3)\n", "\n", "fig.show()" ] }, { "cell_type": "code", "execution_count": 16, "id": "cell-21", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "UTM Zone Coverage\n", "==================================================\n", " Longitude | UTM Zone | Central Meridian\n", "--------------------------------------------------\n", " -180° | 1 | -177°\n", " -150° | 6 | -147°\n", " -120° | 11 | -117°\n", " -90° | 16 | -87°\n", " -60° | 21 | -57°\n", " -30° | 26 | -27°\n", " 0° | 31 | 3°\n", " 30° | 36 | 33°\n", " 60° | 41 | 63°\n", " 90° | 46 | 93°\n", " 120° | 51 | 123°\n", " 150° | 56 | 153°\n", " 180° | 1 | -177°\n" ] } ], "source": [ "# UTM zone visualization\n", "print(\"UTM Zone Coverage\")\n", "print(\"=\" * 50)\n", "\n", "# Show UTM zones for various longitudes\n", "longitudes = np.arange(-180, 181, 30)\n", "print(f\"{'Longitude':>12s} | {'UTM Zone':>10s} | {'Central Meridian':>18s}\")\n", "print(\"-\" * 50)\n", "\n", "for lon_deg in longitudes:\n", " lon = np.radians(lon_deg)\n", " lat = 0 # Equator\n", " \n", " utm_result = geodetic2utm(lat, lon)\n", " \n", " from pytcl.coordinate_systems import utm_central_meridian\n", " central = np.degrees(utm_central_meridian(utm_result.zone))\n", " \n", " print(f\"{lon_deg:12.0f}° | {utm_result.zone:10d} | {central:18.0f}°\")" ] }, { "cell_type": "markdown", "id": "cell-22", "metadata": {}, "source": [ "## 6. Practical Example: Aircraft Tracking\n", "\n", "Let's put it all together with a complete aircraft tracking example." ] }, { "cell_type": "code", "execution_count": 17, "id": "cell-23", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Flight from (38.95°, -77.05°) to (39.70°, -76.20°)\n", "Max altitude: 9995 m\n" ] } ], "source": [ "# Simulate an aircraft trajectory\n", "# Takeoff from Washington DC, fly northeast\n", "\n", "# Radar station location\n", "radar_lat = np.radians(38.9)\n", "radar_lon = np.radians(-77.0)\n", "radar_alt = 100.0 # 100m tower\n", "\n", "# Generate flight path (geodetic)\n", "n_points = 50\n", "t = np.linspace(0, 1, n_points)\n", "\n", "# Start position\n", "start_lat = np.radians(38.95)\n", "start_lon = np.radians(-77.05)\n", "\n", "# End position (100km northeast)\n", "end_lat = np.radians(39.7)\n", "end_lon = np.radians(-76.2)\n", "\n", "# Interpolate position\n", "flight_lat = start_lat + t * (end_lat - start_lat)\n", "flight_lon = start_lon + t * (end_lon - start_lon)\n", "flight_alt = 1000 + 9000 * np.sin(np.pi * t) # Climb to 10km, then descend\n", "\n", "print(f\"Flight from ({np.degrees(start_lat):.2f}°, {np.degrees(start_lon):.2f}°) \"\n", " f\"to ({np.degrees(end_lat):.2f}°, {np.degrees(end_lon):.2f}°)\")\n", "print(f\"Max altitude: {max(flight_alt):.0f} m\")" ] }, { "cell_type": "code", "execution_count": 18, "id": "cell-24", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Flight Path Statistics:\n", " Range: 7.1 km to 112.5 km\n", " Azimuth: -38.0° to 37.6°\n", " Elevation: 8.0° to 14.8°\n" ] } ], "source": [ "# Convert to various coordinate systems\n", "flight_ecef = np.array([geodetic2ecef(lat, lon, alt) \n", " for lat, lon, alt in zip(flight_lat, flight_lon, flight_alt)])\n", "\n", "flight_enu = np.array([ecef2enu(ecef, radar_lat, radar_lon) \n", " for ecef in flight_ecef])\n", "\n", "flight_ned = np.array([ecef2ned(ecef, radar_lat, radar_lon) \n", " for ecef in flight_ecef])\n", "\n", "# Compute range and angles from radar\n", "ranges = np.linalg.norm(flight_enu, axis=1)\n", "azimuths = np.degrees(np.arctan2(flight_enu[:, 0], flight_enu[:, 1])) # From north\n", "elevations = np.degrees(np.arcsin(flight_enu[:, 2] / ranges))\n", "\n", "print(\"\\nFlight Path Statistics:\")\n", "print(f\" Range: {ranges[0]/1e3:.1f} km to {ranges.max()/1e3:.1f} km\")\n", "print(f\" Azimuth: {azimuths[0]:.1f}° to {azimuths[-1]:.1f}°\")\n", "print(f\" Elevation: {elevations[0]:.1f}° to {elevations.max():.1f}°\")" ] }, { "cell_type": "code", "execution_count": 19, "id": "cell-25", "metadata": {}, "outputs": [ { "data": { "application/vnd.plotly.v1+json": { "config": { "plotlyServerURL": "https://plot.ly" }, "data": [ { "line": { "color": "#00d4ff", "width": 4 }, "mode": "lines", "name": "Flight path", "scene": "scene", "type": "scatter3d", "x": { "bdata": "Q/p4DRZXEcA52ZVBRKUGwKUrB6dBOvW/JeQ0B8+jxj825q9EpeH6P/eTFrWcdglASmQqPsu9EkDtrgYa3b8YQN0M84SAwR5A44IMylhhIkASDKTwtWElQLYXBUnVYShAsHa5L7RhK0AvR0/PT2EuQI4NdZJSsDBA5Z2PgtgvMkArC4sQOK8zQIq08oVvLjVA2sESIH2tNkDTydcSXyw4QC3YwIsTqzlAEpfftJgpO0DlQuK37Kc8QKEFI8ENJj5ATkK4AvqjP0Dgr8Db15BAQBbOFZOWT0FA0zwVUjgOQkC4tE9MvMxCQB0wlr8hi0NAkpRW9WdJREDBrelDjgdFQLCB0A+UxUVAph3fzHiDRkB1C1P/O0FHQKnA0zzd/kdArm9bLVy8SECyxAaMuHlJQAU3yifyNkpATrwL5Aj0SkCTyh+5/LBLQBvEqLTNbUxAWATY+XsqTUCJ+Y/BB+dNQNnUZlpxo05ALY2JKLlfT0CSjL/S7w1QQEf15a/ya1BAqvU6feXJUEC+rjSWyCdRQA==", "dtype": "f8" }, "y": { "bdata": "x1v0UAc2FkBGwu3/QgIdQO6RzkuN5yFAtMsVQEZOJUD0Gn89S7UoQLiA59KaHCxAEPNkPzOEL0BiEWo6CXYxQJIccQ0bKjNAWgdHyU3eNEAOPQ79n5I2QEPtvBgQRzhACpqBb5z7OUDD6Vc6Q7A7QHNNypoCZT1AJoncndgZP0Dwj42fYWdAQEyY5TXgQUFA9jsbA2ccQkCeT4f09PZCQNKXcfWI0UNA+47S8CGsREDngBnTvoZFQBxp9IteYUZAEgcXEAA8R0Bckf5aohZIQEt+r3BE8UhAOcdqX+XLSUDQN1hBhKZKQG82Iz4ggUtA8LmHjLhbTECE+MxzTDZNQCimK03bEE5ARosdhWTrTkDycpSc58VPQEI3CxUyUFBAheBe7Wy9UEBuUo05pCpRQM3F+ufXl1FAAC948wcFUkAU1IJjNHJSQGVMckxd31JA3IWUz4JMU0BHeTcbpblTQNtQoGrEJlRApeTvBeGTVECvfvRB+wBVQNLy6H8TblVAVT0hLSrbVUAq4qTCP0hWQA==", "dtype": "f8" }, "z": { "bdata": "ZBcm2xjg7z/+9Y2wYib5P2SokxTaJwFAFMLGOiuxBUD9tjvLWSoKQJaEuAKqjg5ASYrGKrpsEUDljLUqFYMTQME/aL4tiBVA2EF87dx5F0B8gbRND1YZQA+5KzLHGhtAnnOmwx7GHEDBYND/SVYeQAyySp2YyR9ADDFH6TuPIEB10OH+uSkhQNZF6BWdsyFAmbyBvkwsIkCH6fAyQpMiQHnnZOUI6CJAqEee+j4qI0CeY+ewlVkjQJlx87LRdSNAeWlNVst+I0DP3BTFbnQjQNXu3BK8ViNAOY+XPMclI0A/8owTuOEiQKiedRPKiiJAAAjjI0whIkDPrThFoKUhQFBIjSk7GCFAF0vguaN5IEDBbEoQ5ZQfQKxMdF2iFh5AppvkO/N5HEAjleGwasAaQInZQT656xhAG8FXG6v9FkAfjbVQJvgUQCMzyLgo3RJAbypj58WuEEAffeP0Sd4MQGokNaz8QAhAi4RunTKKA0Bx3VcMJ339P+nmKqa2xfM/uB4ek1Tv4z+iRSaCiax8Pw==", "dtype": "f8" } }, { "marker": { "color": "#ff4757", "size": 8, "symbol": "diamond" }, "mode": "markers", "name": "Radar", "scene": "scene", "type": "scatter3d", "x": [ 0 ], "y": [ 0 ], "z": [ 0.1 ] }, { "marker": { "color": "#00ff88", "size": 8 }, "mode": "markers", "name": "Takeoff", "scene": "scene", "type": "scatter3d", "x": [ -4.3350450615967615 ], "y": [ 5.552762284197292 ], "z": [ 0.9961056022882357 ] }, { "marker": { "color": "#ffb800", "size": 8, "symbol": "square" }, "mode": "markers", "name": "Landing", "scene": "scene", "type": "scatter3d", "x": [ 68.62161784310135 ], "y": [ 89.12889162160778 ], "z": [ 0.0070004817411172555 ] }, { "line": { "color": "rgba(0,212,255,0.3)", "width": 1 }, "marker": { "color": { "bdata": "AAAAAAAA8D8/6nJ04jn5P6B/8CYINQFA6q58k2/DBUBsxYp9XEMKQLMV4B0TsA5AnBeM8XWCEUCd8I8rrJ4TQLt7I/VzqhVAq+5uT6ajF0AYtTrIL4gZQKut/qgSVhtAW6IUD2kLHUBW7dnqZqYeQApN0/GtEiBA/nJOj1rDIEC8Vzlzf2QhQH+COxlz9SFArj6cBZ11IkCDlaplduQiQINXkZ2KQSNASwMCw3eMI0APfzUE78QjQBJK1vq06iNA4ex86qH9I0Dh7Hzqof0jQBJK1vq06iNAEH81BO/EI0BLAwLDd4wjQIRXkZ2KQSNAhJWqZXbkIkCvPpwFnXUiQH+COxlz9SFAvVc5c39kIUAAc06PWsMgQAxN0/GtEiBAWO3Z6mamHkBcohQPaQsdQKyt/qgSVhtAHrU6yC+IGUCv7m5PpqMXQL17I/VzqhVAnvCPK6yeE0CgF4zxdYIRQL8V4B0TsA5AdcWKfVxDCkDwrnyTb8MFQKJ/8CYINQFATOpydOI5+T8FAAAAAADwPw==", "dtype": "f8" }, "colorbar": { "len": 0.4, "title": { "text": "Alt (km)" }, "x": 0.45, "y": 0.85 }, "colorscale": [ [ 0, "#440154" ], [ 0.1111111111111111, "#482878" ], [ 0.2222222222222222, "#3e4989" ], [ 0.3333333333333333, "#31688e" ], [ 0.4444444444444444, "#26828e" ], [ 0.5555555555555556, "#1f9e89" ], [ 0.6666666666666666, "#35b779" ], [ 0.7777777777777778, "#6ece58" ], [ 0.8888888888888888, "#b5de2b" ], [ 1, "#fde725" ] ], "size": 6 }, "mode": "markers+lines", "name": "Flight", "showlegend": false, "type": "scatter", "x": { "bdata": "Q/p4DRZXEcA52ZVBRKUGwKUrB6dBOvW/JeQ0B8+jxj825q9EpeH6P/eTFrWcdglASmQqPsu9EkDtrgYa3b8YQN0M84SAwR5A44IMylhhIkASDKTwtWElQLYXBUnVYShAsHa5L7RhK0AvR0/PT2EuQI4NdZJSsDBA5Z2PgtgvMkArC4sQOK8zQIq08oVvLjVA2sESIH2tNkDTydcSXyw4QC3YwIsTqzlAEpfftJgpO0DlQuK37Kc8QKEFI8ENJj5ATkK4AvqjP0Dgr8Db15BAQBbOFZOWT0FA0zwVUjgOQkC4tE9MvMxCQB0wlr8hi0NAkpRW9WdJREDBrelDjgdFQLCB0A+UxUVAph3fzHiDRkB1C1P/O0FHQKnA0zzd/kdArm9bLVy8SECyxAaMuHlJQAU3yifyNkpATrwL5Aj0SkCTyh+5/LBLQBvEqLTNbUxAWATY+XsqTUCJ+Y/BB+dNQNnUZlpxo05ALY2JKLlfT0CSjL/S7w1QQEf15a/ya1BAqvU6feXJUEC+rjSWyCdRQA==", "dtype": "f8" }, "xaxis": "x", "y": { "bdata": "x1v0UAc2FkBGwu3/QgIdQO6RzkuN5yFAtMsVQEZOJUD0Gn89S7UoQLiA59KaHCxAEPNkPzOEL0BiEWo6CXYxQJIccQ0bKjNAWgdHyU3eNEAOPQ79n5I2QEPtvBgQRzhACpqBb5z7OUDD6Vc6Q7A7QHNNypoCZT1AJoncndgZP0Dwj42fYWdAQEyY5TXgQUFA9jsbA2ccQkCeT4f09PZCQNKXcfWI0UNA+47S8CGsREDngBnTvoZFQBxp9IteYUZAEgcXEAA8R0Bckf5aohZIQEt+r3BE8UhAOcdqX+XLSUDQN1hBhKZKQG82Iz4ggUtA8LmHjLhbTECE+MxzTDZNQCimK03bEE5ARosdhWTrTkDycpSc58VPQEI3CxUyUFBAheBe7Wy9UEBuUo05pCpRQM3F+ufXl1FAAC948wcFUkAU1IJjNHJSQGVMckxd31JA3IWUz4JMU0BHeTcbpblTQNtQoGrEJlRApeTvBeGTVECvfvRB+wBVQNLy6H8TblVAVT0hLSrbVUAq4qTCP0hWQA==", "dtype": "f8" }, "yaxis": "y" }, { "marker": { "color": "#ff4757", "size": 12, "symbol": "triangle-up" }, "mode": "markers", "showlegend": false, "type": "scatter", "x": [ 0 ], "xaxis": "x", "y": [ 0 ], "yaxis": "y" }, { "fill": "tozeroy", "fillcolor": "rgba(0,212,255,0.3)", "line": { "color": "#00d4ff", "width": 2 }, "mode": "lines", "name": "Altitude", "showlegend": false, "type": "scatter", "x": { "bdata": "sNUOYKAtHEDHQCNk6iMfQKLNHQOdGSJAW9SFsgZPJUABd/CAhO8oQJfytETQ0ixA44PMhaNwMEBjhSJXYYYyQMj/BHM+pjRAhKLQXGfNNkDtg/Lx+Pk4QGXTANqlKjtAeI6FRYFePUBDZHaJ3pQ/QGDTNGSe5kBA3ilv5pwDQkCyUdSnRCFDQCYcHYV3P0RAVh2dTB1eRUD6B6tJIn1GQLbshDh2nEdAkZdqggu8SEAEroGs1ttJQHw7BevN+0pASXHGzugbTEDCqgMGIDxNQO3UoCttXE5ACo0vocp8T0B5VZa4mU5QQAOYw5vR3lBAZ7WABwtvUUBshStBRP9RQCR7KsB7j1JA0yQgKbAfU0B8LAdK4K9TQN1tBRcLQFRAYjbPpy/QVEAeqXs1TWBVQB+PsRhj8FVAJpgYyHCAVkDi9f7WdRBXQFMwJvRxoFdAHYms6GQwWEDOMwqXTsBYQLg+G/ouUFlAFGAwJAbgWUCE5yE+1G9aQHX7YIaZ/1pA+RsEUFaPW0C1ecwBCx9cQA==", "dtype": "f8" }, "xaxis": "x2", "y": { "bdata": "AAAAAAAA8D8/6nJ04jn5P6B/8CYINQFA6q58k2/DBUBsxYp9XEMKQLMV4B0TsA5AnBeM8XWCEUCd8I8rrJ4TQLt7I/VzqhVAq+5uT6ajF0AYtTrIL4gZQKut/qgSVhtAW6IUD2kLHUBW7dnqZqYeQApN0/GtEiBA/nJOj1rDIEC8Vzlzf2QhQH+COxlz9SFArj6cBZ11IkCDlaplduQiQINXkZ2KQSNASwMCw3eMI0APfzUE78QjQBJK1vq06iNA4ex86qH9I0Dh7Hzqof0jQBJK1vq06iNAEH81BO/EI0BLAwLDd4wjQIRXkZ2KQSNAhJWqZXbkIkCvPpwFnXUiQH+COxlz9SFAvVc5c39kIUAAc06PWsMgQAxN0/GtEiBAWO3Z6mamHkBcohQPaQsdQKyt/qgSVhtAHrU6yC+IGUCv7m5PpqMXQL17I/VzqhVAnvCPK6yeE0CgF4zxdYIRQL8V4B0TsA5AdcWKfVxDCkDwrnyTb8MFQKJ/8CYINQFATOpydOI5+T8FAAAAAADwPw==", "dtype": "f8" }, "yaxis": "y2" }, { "line": { "color": "#8B4513", "width": 4 }, "mode": "lines", "name": "Ground", "showlegend": false, "type": "scatter", "x": [ 7.044557095437469, 112.4850468155699 ], "xaxis": "x2", "y": [ 0, 0 ], "yaxis": "y2" }, { "line": { "color": "#00ff88", "width": 2 }, "mode": "lines", "name": "Azimuth", "type": "scatter", "x": { "bdata": "AAAAAAAAAAAVvJyCl1MAQBW8nIKXUxBAHxrrQ2N9GEAVvJyCl1MgQBnrQ2N9aCRAHxrrQ2N9KEAkSZIkSZIsQBW8nIKXUzBAl1PwcgpeMkAZ60NjfWg0QJyCl1PwcjZAHxrrQ2N9OEChsT401oc6QCRJkiRJkjxApuDlFLycPkAVvJyCl1NAQNaHxvrQWEFAl1PwcgpeQkBZHxrrQ2NDQBnrQ2N9aERA27Zt27ZtRUCcgpdT8HJGQF5OwcspeEdAHxrrQ2N9SEDh5RS8nIJJQKGxPjTWh0pAYn1orA+NS0AkSZIkSZJMQOYUvJyCl01ApuDlFLycTkBnrA+N9aFPQBW8nIKXU1BA9aGxPjTWUEDWh8b60FhRQLZt27Zt21FAl1PwcgpeUkB4OQUvp+BSQFkfGutDY1NAOQUvp+DlU0AZ60NjfWhUQPrQWB8a61RA27Zt27ZtVUC8nIKXU/BVQJyCl1PwclZAfWisD431VkBeTsHLKXhXQD401ofG+ldAHxrrQ2N9WEAAAAAAAABZQA==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "MwG3zlX9QsAm8j8uYVI1wIZ8QiwY3CDA3DXLmV9w7j8WInx+RfoeQHc2jZ/ChClAV+OMEgSPMECRN/OPCoMzQFdqSz9y3DVAXwhNmJvEN0BtpZMJ0Vc5QEvkyhrnqTpAYN4NSRnJO0B5O4MI2L88QI49O5HylT1AZLQ2Q1tRPkCjI4EOrPY+QBOSv5eBiT9ArkX+ll0GQEDdn5s9VEFAQD4RwViVdkBAhdazf+amQECGUV5r69JAQC/AGeEs+0BAPAXh/h0gQUCeVVFVIEJBQPaGzxyHYUFADY23vZl+QUC2R3nUlZlBQHqV4c+wskFAJbMrQBnKQUAScOzn999BQElE2Jtw9EFATMpi+6IHQkBz4vUJqxlCQHJCzK6hKkJAPpAwIJ06QkAY5+Q9sUlCQJLXst3vV0JAquGLDGllQkD7JCtGK3JCQJ85y6RDfkJAgKQ4Cr6JQkAaE05DpZRCQAX0tyYDn0JAe6y2r+CoQkBLqHcVRrJCQN08hN86u0JAk66w98XDQkCTveS57ctCQA==", "dtype": "f8" }, "yaxis": "y3" }, { "line": { "color": "#ff4757", "width": 2 }, "mode": "lines", "name": "Elevation", "type": "scatter", "x": { "bdata": "AAAAAAAAAAAVvJyCl1MAQBW8nIKXUxBAHxrrQ2N9GEAVvJyCl1MgQBnrQ2N9aCRAHxrrQ2N9KEAkSZIkSZIsQBW8nIKXUzBAl1PwcgpeMkAZ60NjfWg0QJyCl1PwcjZAHxrrQ2N9OEChsT401oc6QCRJkiRJkjxApuDlFLycPkAVvJyCl1NAQNaHxvrQWEFAl1PwcgpeQkBZHxrrQ2NDQBnrQ2N9aERA27Zt27ZtRUCcgpdT8HJGQF5OwcspeEdAHxrrQ2N9SEDh5RS8nIJJQKGxPjTWh0pAYn1orA+NS0AkSZIkSZJMQOYUvJyCl01ApuDlFLycTkBnrA+N9aFPQBW8nIKXU1BA9aGxPjTWUEDWh8b60FhRQLZt27Zt21FAl1PwcgpeUkB4OQUvp+BSQFkfGutDY1NAOQUvp+DlU0AZ60NjfWhUQPrQWB8a61RA27Zt27ZtVUC8nIKXU/BVQJyCl1PwclZAfWisD431VkBeTsHLKXhXQD401ofG+ldAHxrrQ2N9WEAAAAAAAABZQA==", "dtype": "f8" }, "xaxis": "x3", "y": { "bdata": "Zh5T9rsYIEAVipuzftQmQIx5eJhTqSpA44U4wJuOLEAGNgLa+2UtQBqpJBJDsC1AElu6M4WuLUAQGW1KMYEtQO182J3ROC1AYXTp4x/eLEAInVL84XUsQBGot8vNAixATKXw8n2GK0CbmPTb8QErQF8ww+PSdSpAlfENxpriKUBdiTx4qUgpQOAYydRRqChAiTg4DOEBKEBWRFsKo1UnQKZknAvloyZApaTBGPfsJUCznqHULDElQHkjN9zdcCRADcpN4GWsI0DMNgGRJOQiQOORPGp9GCJAG93iatdJIUAPgeS8nHggQBr73qR0Sh9AYpc69j6gHUD+JG/mevMbQFwBZN0NRRpAeshbQt+VGEBrCWKI1+YWQC+tPjnfOBVAsYXtAN6ME0DuvIK7ueMRQPAPTodVPhBAOsH1uSE7DUCYjJ5ejQQKQHTiGyiZ2gZAf9W07uO+A0Cr4qu1/rIAQGBJ+IXWcPs/RwGXpDWh9T8zUoGRs/PvP0ABD7C4+uQ/Ua+vxry41D+aFDrxADZtPw==", "dtype": "f8" }, "yaxis": "y3" } ], "layout": { "annotations": [ { "font": { "size": 16 }, "showarrow": false, "text": "ENU Coordinates from Radar", "x": 0.225, "xanchor": "center", "xref": "paper", "y": 1, "yanchor": "bottom", "yref": "paper" }, { "font": { "size": 16 }, "showarrow": false, "text": "Overhead View", "x": 0.775, "xanchor": "center", "xref": "paper", "y": 1, "yanchor": "bottom", "yref": "paper" }, { "font": { "size": 16 }, "showarrow": false, "text": "Range-Altitude Profile", "x": 0.225, "xanchor": "center", "xref": "paper", "y": 0.44, "yanchor": "bottom", "yref": "paper" }, { "font": { "size": 16 }, "showarrow": false, "text": "Radar Angles", "x": 0.775, "xanchor": "center", "xref": "paper", "y": 0.44, "yanchor": "bottom", "yref": "paper" } ], "height": 700, "scene": { "domain": { "x": [ 0, 0.45 ], "y": [ 0.56, 1 ] }, "xaxis": { "gridcolor": "#30363d", "title": { "text": "East (km)" } }, "yaxis": { "gridcolor": "#30363d", "title": { "text": "North (km)" } }, "zaxis": { "gridcolor": "#30363d", "title": { "text": "Up (km)" } } }, "template": { "layout": { "font": { "color": "#e6edf3" }, "paper_bgcolor": "#0d1117", "plot_bgcolor": "#0d1117", "xaxis": { "gridcolor": "#30363d", "zerolinecolor": "#30363d" }, "yaxis": { "gridcolor": "#30363d", "zerolinecolor": "#30363d" } } }, "xaxis": { "anchor": "y", "domain": [ 0.55, 1 ], "title": { "text": "East (km)" } }, "xaxis2": { "anchor": "y2", "domain": [ 0, 0.45 ], "title": { "text": "Horizontal Range (km)" } }, "xaxis3": { "anchor": "y3", "domain": [ 0.55, 1 ], "title": { "text": "Flight Progress (%)" } }, "yaxis": { "anchor": "x", "domain": [ 0.56, 1 ], "scaleanchor": "x2", "scaleratio": 1, "title": { "text": "North (km)" } }, "yaxis2": { "anchor": "x2", "domain": [ 0, 0.44 ], "title": { "text": "Altitude (km)" } }, "yaxis3": { "anchor": "x3", "domain": [ 0, 0.44 ], "title": { "text": "Angle (degrees)" } } } } }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Comprehensive visualization\n", "fig = make_subplots(\n", " rows=2, cols=2,\n", " specs=[[{'type': 'scene'}, {'type': 'xy'}],\n", " [{'type': 'xy'}, {'type': 'xy'}]],\n", " subplot_titles=['ENU Coordinates from Radar', 'Overhead View', \n", " 'Range-Altitude Profile', 'Radar Angles'],\n", " vertical_spacing=0.12,\n", " horizontal_spacing=0.1\n", ")\n", "\n", "# 3D ENU view\n", "fig.add_trace(\n", " go.Scatter3d(x=flight_enu[:, 0]/1e3, y=flight_enu[:, 1]/1e3, z=flight_enu[:, 2]/1e3,\n", " mode='lines', line=dict(color='#00d4ff', width=4),\n", " name='Flight path'),\n", " row=1, col=1\n", ")\n", "fig.add_trace(\n", " go.Scatter3d(x=[0], y=[0], z=[0.1],\n", " mode='markers', marker=dict(color='#ff4757', size=8, symbol='diamond'),\n", " name='Radar'),\n", " row=1, col=1\n", ")\n", "fig.add_trace(\n", " go.Scatter3d(x=[flight_enu[0, 0]/1e3], y=[flight_enu[0, 1]/1e3], z=[flight_enu[0, 2]/1e3],\n", " mode='markers', marker=dict(color='#00ff88', size=8),\n", " name='Takeoff'),\n", " row=1, col=1\n", ")\n", "fig.add_trace(\n", " go.Scatter3d(x=[flight_enu[-1, 0]/1e3], y=[flight_enu[-1, 1]/1e3], z=[flight_enu[-1, 2]/1e3],\n", " mode='markers', marker=dict(color='#ffb800', size=8, symbol='square'),\n", " name='Landing'),\n", " row=1, col=1\n", ")\n", "\n", "# 2D overhead view with altitude coloring\n", "fig.add_trace(\n", " go.Scatter(x=flight_enu[:, 0]/1e3, y=flight_enu[:, 1]/1e3,\n", " mode='markers+lines', \n", " marker=dict(color=flight_alt/1e3, colorscale='Viridis', size=6,\n", " colorbar=dict(title='Alt (km)', x=0.45, len=0.4, y=0.85)),\n", " line=dict(color='rgba(0,212,255,0.3)', width=1),\n", " name='Flight', showlegend=False),\n", " row=1, col=2\n", ")\n", "fig.add_trace(\n", " go.Scatter(x=[0], y=[0], mode='markers',\n", " marker=dict(color='#ff4757', size=12, symbol='triangle-up'),\n", " showlegend=False),\n", " row=1, col=2\n", ")\n", "\n", "# Range-altitude profile\n", "horizontal_range = np.sqrt(flight_enu[:, 0]**2 + flight_enu[:, 1]**2) / 1e3\n", "fig.add_trace(\n", " go.Scatter(x=horizontal_range, y=flight_alt/1e3, mode='lines',\n", " fill='tozeroy', fillcolor='rgba(0,212,255,0.3)',\n", " line=dict(color='#00d4ff', width=2),\n", " name='Altitude', showlegend=False),\n", " row=2, col=1\n", ")\n", "fig.add_trace(\n", " go.Scatter(x=[horizontal_range[0], horizontal_range[-1]], y=[0, 0],\n", " mode='lines', line=dict(color='#8B4513', width=4),\n", " name='Ground', showlegend=False),\n", " row=2, col=1\n", ")\n", "\n", "# Radar angles\n", "fig.add_trace(\n", " go.Scatter(x=t * 100, y=azimuths, mode='lines',\n", " name='Azimuth', line=dict(color='#00ff88', width=2)),\n", " row=2, col=2\n", ")\n", "fig.add_trace(\n", " go.Scatter(x=t * 100, y=elevations, mode='lines',\n", " name='Elevation', line=dict(color='#ff4757', width=2)),\n", " row=2, col=2\n", ")\n", "\n", "fig.update_layout(\n", " template=dark_template,\n", " height=700,\n", " scene=dict(\n", " xaxis_title='East (km)',\n", " yaxis_title='North (km)',\n", " zaxis_title='Up (km)',\n", " xaxis=dict(gridcolor='#30363d'),\n", " yaxis=dict(gridcolor='#30363d'),\n", " zaxis=dict(gridcolor='#30363d'),\n", " ),\n", ")\n", "\n", "fig.update_xaxes(title_text='East (km)', row=1, col=2)\n", "fig.update_yaxes(title_text='North (km)', row=1, col=2, scaleanchor='x2', scaleratio=1)\n", "fig.update_xaxes(title_text='Horizontal Range (km)', row=2, col=1)\n", "fig.update_yaxes(title_text='Altitude (km)', row=2, col=1)\n", "fig.update_xaxes(title_text='Flight Progress (%)', row=2, col=2)\n", "fig.update_yaxes(title_text='Angle (degrees)', row=2, col=2)\n", "\n", "fig.show()" ] }, { "cell_type": "markdown", "id": "cell-26", "metadata": {}, "source": [ "## Summary\n", "\n", "Key takeaways:\n", "\n", "1. **Geodetic coordinates** are intuitive but require conversion for calculations\n", "2. **ECEF** is ideal for global calculations but unintuitive for local work\n", "3. **ENU/NED** local frames are best for tracking near a reference point\n", "4. **Quaternions** avoid gimbal lock and provide smooth interpolation\n", "5. **Map projections** trade off different properties - choose based on use case\n", "\n", "## Exercises\n", "\n", "1. Implement a coordinate converter that handles all transitions between geodetic, ECEF, ENU, and NED\n", "2. Compare quaternion SLERP to linear interpolation of Euler angles\n", "3. Visualize how projection distortion varies with distance from the projection center\n", "4. Track a satellite in ECEF and display its ground track on a map projection\n", "\n", "## References\n", "\n", "1. Groves, P. D. (2013). *Principles of GNSS, Inertial, and Multisensor Integrated Navigation Systems*\n", "2. Snyder, J. P. (1987). *Map Projections: A Working Manual*. USGS Professional Paper 1395.\n", "3. Kuipers, J. B. (1999). *Quaternions and Rotation Sequences*." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "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.13.0" } }, "nbformat": 4, "nbformat_minor": 5 }