-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Closes #29, closes #28, closes #27, closes #26, and closes #21 Adds basic capabilities for all maps with the exception of choropleth I originally was trying to include choropleths as well but they're a bit more complicated and I already have spent a bit too long on this for the moment. The other maps are basically free to implement. There is a graphical issue with density mapbox that would be good for @mattrunyon to look at when adding the defaults. The data is there but not being drawn. Here's some code to recreate the issue: ``` import deephaven.plot.express as dx from deephaven import time_table import random import pandas as pd import deephaven.pandas as dhpd df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/earthquakes-23k.csv') t = dhpd.to_table(df) fig = dx.density_mapbox(t, lat='Latitude', lon='Longitude', z='Magnitude', radius=10, center=dict(lat=0, lon=180), zoom=0, mapbox_style="stamen-terrain") ``` I see a ton of errors in the console, some along the line of "The layer 'plotly-trace-layer-ea2295-heatmap' does not exist in the map's style and cannot be styled." Additionally, geo plots have the snapping issue when dragging when new data loads in that 3d plots had. Using the same imports: ``` sourceh = time_table("PT1S").update(formulas=[ "X = (float) random.uniform(-90, 90)", "Y = (float) random.uniform(-180, 180)", "Z = (float)random.gauss(3, 3)", "l1 = i % 20", "l2 = i % 30", ]) def update(fig): fig.update_geos(showland=True, landcolor="gray") figs = dx.scatter_geo( sourceh, lat="X", lon="Y", by="l1", size="Z", color_discrete_sequence=["salmon", "lemonchiffon"], projection="natural earth", unsafe_update_figure=update ) ``` --------- Co-authored-by: Matthew Runyon <[email protected]>
- Loading branch information
1 parent
f885ea0
commit 77507b9
Showing
7 changed files
with
1,003 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
734 changes: 734 additions & 0 deletions
734
plugins/plotly-express/src/deephaven/plot/express/plots/maps.py
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
232 changes: 232 additions & 0 deletions
232
plugins/plotly-express/test/deephaven/plot/express/plots/test_maps.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,232 @@ | ||
import unittest | ||
|
||
from ..BaseTest import BaseTestCase | ||
|
||
|
||
class MapTestCase(BaseTestCase): | ||
def setUp(self) -> None: | ||
from deephaven import new_table | ||
from deephaven.column import int_col | ||
|
||
self.source = new_table( | ||
[ | ||
int_col("lat", [1, 2, 2, 3, 3, 3, 4, 4, 5]), | ||
int_col("lon", [1, 2, 2, 3, 3, 3, 4, 4, 5]), | ||
int_col("z", [1, 2, 2, 3, 3, 3, 4, 4, 5]), | ||
] | ||
) | ||
|
||
def test_basic_scatter_geo(self): | ||
import src.deephaven.plot.express as dx | ||
from deephaven.constants import NULL_INT | ||
|
||
chart = dx.scatter_geo(self.source, lat="lat", lon="lon").to_dict(self.exporter) | ||
plotly, deephaven = chart["plotly"], chart["deephaven"] | ||
|
||
# pop template as we currently do not modify it | ||
plotly["layout"].pop("template") | ||
|
||
expected_data = [ | ||
{ | ||
"featureidkey": "id", | ||
"geo": "geo", | ||
"hovertemplate": "lat=%{lat}<br>lon=%{lon}<extra></extra>", | ||
"lat": [NULL_INT], | ||
"legendgroup": "", | ||
"lon": [NULL_INT], | ||
"marker": {"color": "#636efa", "symbol": "circle"}, | ||
"mode": "markers", | ||
"name": "", | ||
"showlegend": False, | ||
"type": "scattergeo", | ||
} | ||
] | ||
|
||
self.assertEqual(plotly["data"], expected_data) | ||
|
||
expected_layout = { | ||
"geo": {"domain": {"x": [0.0, 1.0], "y": [0.0, 1.0]}, "fitbounds": False}, | ||
"legend": {"tracegroupgap": 0}, | ||
"margin": {"t": 60}, | ||
} | ||
|
||
self.assertEqual(plotly["layout"], expected_layout) | ||
|
||
def test_basic_scatter_mapbox(self): | ||
import src.deephaven.plot.express as dx | ||
from deephaven.constants import NULL_INT | ||
|
||
chart = dx.scatter_mapbox(self.source, lat="lat", lon="lon").to_dict( | ||
self.exporter | ||
) | ||
plotly, deephaven = chart["plotly"], chart["deephaven"] | ||
|
||
# pop template as we currently do not modify it | ||
plotly["layout"].pop("template") | ||
|
||
expected_data = [ | ||
{ | ||
"hovertemplate": "lat=%{lat}<br>lon=%{lon}<extra></extra>", | ||
"lat": [NULL_INT], | ||
"legendgroup": "", | ||
"lon": [NULL_INT], | ||
"marker": {"color": "#636efa"}, | ||
"mode": "markers", | ||
"name": "", | ||
"showlegend": False, | ||
"subplot": "mapbox", | ||
"type": "scattermapbox", | ||
} | ||
] | ||
|
||
self.assertEqual(plotly["data"], expected_data) | ||
|
||
expected_layout = { | ||
"legend": {"tracegroupgap": 0}, | ||
"mapbox": { | ||
"center": {"lat": NULL_INT, "lon": NULL_INT}, | ||
"domain": {"x": [0.0, 1.0], "y": [0.0, 1.0]}, | ||
"style": "open-street-map", | ||
"zoom": 8, | ||
}, | ||
"margin": {"t": 60}, | ||
} | ||
|
||
self.assertEqual(plotly["layout"], expected_layout) | ||
|
||
def test_basic_line_geo(self): | ||
import src.deephaven.plot.express as dx | ||
from deephaven.constants import NULL_INT | ||
|
||
chart = dx.line_geo(self.source, lat="lat", lon="lon").to_dict(self.exporter) | ||
plotly, deephaven = chart["plotly"], chart["deephaven"] | ||
|
||
# pop template as we currently do not modify it | ||
plotly["layout"].pop("template") | ||
|
||
expected_data = [ | ||
{ | ||
"featureidkey": "id", | ||
"geo": "geo", | ||
"hovertemplate": "lat=%{lat}<br>lon=%{lon}<extra></extra>", | ||
"lat": [NULL_INT], | ||
"legendgroup": "", | ||
"line": {"color": "#636efa", "dash": "solid"}, | ||
"lon": [NULL_INT], | ||
"marker": {"symbol": "circle"}, | ||
"mode": "lines", | ||
"name": "", | ||
"showlegend": False, | ||
"type": "scattergeo", | ||
} | ||
] | ||
|
||
self.assertEqual(plotly["data"], expected_data) | ||
|
||
expected_layout = { | ||
"geo": {"domain": {"x": [0.0, 1.0], "y": [0.0, 1.0]}, "fitbounds": False}, | ||
"legend": {"tracegroupgap": 0}, | ||
"margin": {"t": 60}, | ||
} | ||
|
||
self.assertEqual(plotly["layout"], expected_layout) | ||
|
||
def test_basic_line_mapbox(self): | ||
import src.deephaven.plot.express as dx | ||
from deephaven.constants import NULL_INT | ||
|
||
chart = dx.line_mapbox(self.source, lat="lat", lon="lon").to_dict(self.exporter) | ||
plotly, deephaven = chart["plotly"], chart["deephaven"] | ||
|
||
# pop template as we currently do not modify it | ||
plotly["layout"].pop("template") | ||
|
||
expected_data = [ | ||
{ | ||
"hovertemplate": "lat=%{lat}<br>lon=%{lon}<extra></extra>", | ||
"lat": [NULL_INT], | ||
"legendgroup": "", | ||
"line": {"color": "#636efa"}, | ||
"lon": [NULL_INT], | ||
"mode": "lines", | ||
"name": "", | ||
"showlegend": False, | ||
"subplot": "mapbox", | ||
"type": "scattermapbox", | ||
} | ||
] | ||
|
||
self.assertEqual(plotly["data"], expected_data) | ||
|
||
expected_layout = { | ||
"legend": {"tracegroupgap": 0}, | ||
"mapbox": { | ||
"center": {"lat": NULL_INT, "lon": NULL_INT}, | ||
"domain": {"x": [0.0, 1.0], "y": [0.0, 1.0]}, | ||
"style": "open-street-map", | ||
"zoom": 8, | ||
}, | ||
"margin": {"t": 60}, | ||
} | ||
|
||
self.assertEqual(plotly["layout"], expected_layout) | ||
|
||
def test_basic_density_mapbox(self): | ||
import src.deephaven.plot.express as dx | ||
from deephaven.constants import NULL_INT | ||
|
||
chart = dx.density_mapbox(self.source, lat="lat", lon="lon", z="z").to_dict( | ||
self.exporter | ||
) | ||
plotly, deephaven = chart["plotly"], chart["deephaven"] | ||
|
||
# pop template as we currently do not modify it | ||
plotly["layout"].pop("template") | ||
|
||
expected_data = [ | ||
{ | ||
"coloraxis": "coloraxis", | ||
"hovertemplate": "lat=%{lat}<br>lon=%{lon}<br>z=%{z}<extra></extra>", | ||
"lat": [NULL_INT], | ||
"lon": [NULL_INT], | ||
"name": "", | ||
"radius": 30, | ||
"subplot": "mapbox", | ||
"z": [-2147483648], | ||
"type": "densitymapbox", | ||
} | ||
] | ||
|
||
self.assertEqual(plotly["data"], expected_data) | ||
|
||
expected_layout = { | ||
"coloraxis": { | ||
"colorbar": {"title": {"text": "z"}}, | ||
"colorscale": [ | ||
[0.0, "#0d0887"], | ||
[0.1111111111111111, "#46039f"], | ||
[0.2222222222222222, "#7201a8"], | ||
[0.3333333333333333, "#9c179e"], | ||
[0.4444444444444444, "#bd3786"], | ||
[0.5555555555555556, "#d8576b"], | ||
[0.6666666666666666, "#ed7953"], | ||
[0.7777777777777778, "#fb9f3a"], | ||
[0.8888888888888888, "#fdca26"], | ||
[1.0, "#f0f921"], | ||
], | ||
}, | ||
"legend": {"tracegroupgap": 0}, | ||
"mapbox": { | ||
"center": {"lat": NULL_INT, "lon": NULL_INT}, | ||
"domain": {"x": [0.0, 1.0], "y": [0.0, 1.0]}, | ||
"style": "open-street-map", | ||
"zoom": 8, | ||
}, | ||
"margin": {"t": 60}, | ||
} | ||
|
||
self.assertEqual(plotly["layout"], expected_layout) | ||
|
||
|
||
if __name__ == "__main__": | ||
unittest.main() |