Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ecoscope fork merge #613

Draft
wants to merge 31 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
2e84d8b
bump to decck.gl v9 - refers to a local build of @geoarrow/deck.gl-la…
atmorling Apr 22, 2024
d8229da
Fixing linking issue with local package
atmorling Apr 27, 2024
2ebbca9
making a start on widgets
atmorling Apr 25, 2024
92d7b68
testing title port + native deck.gl widgets
atmorling Apr 26, 2024
3225f09
More widget stuffs
atmorling Apr 29, 2024
5bebe6f
adding zoom and compass widgets
atmorling Apr 30, 2024
bf4dd4e
widget style updates
atmorling May 6, 2024
aa8ab19
Tentative north arrow implementation
atmorling May 7, 2024
a63cad9
Legend widget implementation
atmorling May 7, 2024
09d5da5
scale widget implementation
atmorling May 22, 2024
456b4d2
Merge branch 'main' into v9
atmorling May 23, 2024
01af15f
Merge branch 'v9' into widgets
atmorling May 23, 2024
dbb6446
Bump to deck 9.0.15 for upstream bugfixes
atmorling May 24, 2024
fcdb11a
Merge branch 'v9' into widgets
atmorling May 24, 2024
5c6e50a
set deck width and height
atmorling May 27, 2024
ca6b4bc
re-add widgets
atmorling May 27, 2024
62dba95
deck version bump and expose height/width map props
atmorling May 28, 2024
5035bcd
widget style cleanup
atmorling May 28, 2024
e11032c
first cut of PNG export button
atmorling Jun 17, 2024
ce9f2e3
Second pass of png export widget
atmorling Jun 18, 2024
e9d8cc0
Cut to public release of deck.gl-layers
atmorling Jun 18, 2024
4593110
fix set_props
atmorling Jun 21, 2024
7f52889
support static maps
atmorling Jun 21, 2024
00fea80
add map_view to allow setting repeat=true
atmorling Jun 24, 2024
caa5f5d
add viz_layer()
atmorling Jun 24, 2024
5c9aa65
fix save image click handler bug
atmorling Jun 24, 2024
77c56d3
static components
atmorling Jun 25, 2024
6ca2853
fix png export button
atmorling Jul 23, 2024
a8adb48
allow width/height vals to be strings - ie "100%"
atmorling Aug 20, 2024
da7be6b
Merge commit 'a8adb48ec43fff795506db5a9e7e0103f877d65c' into merge/ec…
vgeorge Aug 27, 2024
7aee870
Set default mapWidth and mapHeight
vgeorge Aug 27, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions lonboard/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,14 @@
from ._map import Map
from ._version import __version__
from ._viz import viz
from ._deck_widget import (
BaseDeckWidget,
FullscreenWidget,
ZoomWidget,
CompassWidget,
TitleWidget,
NorthArrowWidget,
LegendWidget,
ScaleWidget,
SaveImageWidget,
)
96 changes: 96 additions & 0 deletions lonboard/_deck_widget.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import traitlets
from lonboard._base import BaseWidget

class BaseDeckWidget(BaseWidget):

# props = traitlets.Dict({}).tag(sync=True) # make me a class
placement = traitlets.Enum(
values=["top-left", "top-right", "bottom-left", "bottom-right", "fill"],
default_value=None,
allow_none=True
).tag(sync=True)
class_name = traitlets.Unicode(default_value=None, allow_none=True).tag(sync=True)

def __init__(self, **kwargs):
super().__init__(**kwargs)

class FullscreenWidget(BaseDeckWidget):
_widget_type = traitlets.Unicode("fullscreen").tag(sync=True)

enter_label = traitlets.Unicode(default_value=None, allow_none=True).tag(sync=True)
exit_label = traitlets.Unicode(default_value=None, allow_none=True).tag(sync=True)
style = traitlets.Dict(default_value=None, allow_none=True).tag(sync=True)
class_name = traitlets.Unicode(default_value=None, allow_none=True).tag(sync=True)

def __init__(self, **kwargs):
super().__init__(**kwargs)

class ZoomWidget(BaseDeckWidget):
_widget_type = traitlets.Unicode("zoom").tag(sync=True)

zoom_in_label = traitlets.Unicode(default_value=None, allow_none=True).tag(sync=True)
zoom_out_label = traitlets.Unicode(default_value=None, allow_none=True).tag(sync=True)
transition_duration = traitlets.Int(default_value=None, allow_none=True).tag(sync=True)
style = traitlets.Dict(default_value=None, allow_none=True).tag(sync=True)
class_name = traitlets.Unicode(default_value=None, allow_none=True).tag(sync=True)

def __init__(self, **kwargs):
super().__init__(**kwargs)

class CompassWidget(BaseDeckWidget):
_widget_type = traitlets.Unicode("compass").tag(sync=True)

label = traitlets.Unicode(default_value=None, allow_none=True).tag(sync=True)
transition_duration = traitlets.Int(default_value=None, allow_none=True).tag(sync=True)
style = traitlets.Dict(default_value=None, allow_none=True).tag(sync=True)
class_name = traitlets.Unicode(default_value=None, allow_none=True).tag(sync=True)

def __init__(self, **kwargs):
super().__init__(**kwargs)

class NorthArrowWidget(BaseDeckWidget):
_widget_type = traitlets.Unicode("north-arrow").tag(sync=True)

label = traitlets.Unicode(default_value=None, allow_none=True).tag(sync=True)
transition_duration = traitlets.Int(default_value=None, allow_none=True).tag(sync=True)
style = traitlets.Dict(default_value=None, allow_none=True).tag(sync=True)
class_name = traitlets.Unicode(default_value=None, allow_none=True).tag(sync=True)

def __init__(self, **kwargs):
super().__init__(**kwargs)

class TitleWidget(BaseDeckWidget):

_widget_type = traitlets.Unicode("title").tag(sync=True)
title = traitlets.Unicode(allow_none=False).tag(sync=True)
style = traitlets.Dict(default_value=None, allow_none=True).tag(sync=True)
def __init__(self, **kwargs):
super().__init__(**kwargs)

class LegendWidget(BaseDeckWidget):

_widget_type = traitlets.Unicode("legend").tag(sync=True)
title = traitlets.Unicode(default_value=None, allow_none=True).tag(sync=True)
labels = traitlets.List(traitlets.Unicode()).tag(sync=True)
colors = traitlets.List(traitlets.Unicode()).tag(sync=True)
style = traitlets.Dict(default_value=None, allow_none=True).tag(sync=True)
def __init__(self, **kwargs):
super().__init__(**kwargs)

class ScaleWidget(BaseDeckWidget):

_widget_type = traitlets.Unicode("scale").tag(sync=True)
style = traitlets.Dict(default_value=None, allow_none=True).tag(sync=True)
max_width = traitlets.Int(default_value=None, allow_none=True).tag(sync=True)
use_imperial = traitlets.Bool(default_value=None, allow_none=True).tag(sync=True)

def __init__(self, **kwargs):
super().__init__(**kwargs)

class SaveImageWidget(BaseDeckWidget):

_widget_type = traitlets.Unicode("save-image").tag(sync=True)
style = traitlets.Dict(default_value=None, allow_none=True).tag(sync=True)

def __init__(self, **kwargs):
super().__init__(**kwargs)
29 changes: 25 additions & 4 deletions lonboard/_map.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

import sys
from math import log2
from io import StringIO
from pathlib import Path
from typing import IO, TYPE_CHECKING, Optional, Sequence, TextIO, Union, overload
Expand All @@ -12,6 +13,7 @@
from lonboard._base import BaseAnyWidget
from lonboard._environment import DEFAULT_HEIGHT
from lonboard._layer import BaseLayer
from lonboard._deck_widget import BaseDeckWidget
from lonboard._viewport import compute_view
from lonboard.basemap import CartoBasemap
from lonboard.traits import DEFAULT_INITIAL_VIEW_STATE, BasemapUrl, ViewStateTrait
Expand Down Expand Up @@ -123,11 +125,20 @@ def __init__(

"""

_height = traitlets.Int(default_value=DEFAULT_HEIGHT, allow_none=True).tag(
sync=True
)
height = traitlets.Union(
[traitlets.Int(),traitlets.Unicode()],
default_value=DEFAULT_HEIGHT, allow_none=True
).tag(sync=True)
"""Height of the map in pixels.

This API is not yet stabilized and may change in the future.
"""
width = traitlets.Union(
[traitlets.Int(),traitlets.Unicode()],
default_value=DEFAULT_HEIGHT, allow_none=True
).tag(sync=True)
"""Width of the map in pixels.

This API is not yet stabilized and may change in the future.
"""

Expand Down Expand Up @@ -156,7 +167,17 @@ def __init__(
- Default: `5`
"""

basemap_style = BasemapUrl(CartoBasemap.PositronNoLabels)
deck_widgets = traitlets.List(trait=traitlets.Instance(BaseDeckWidget)).tag(
sync=True, **ipywidgets.widget_serialization
)
"""One or more `Widget` objects to display on this map.
"""

controller = traitlets.Bool(default_value=True).tag(sync=True)
"""Whether or not the map is interactive
"""

basemap_style = traitlets.Unicode(CartoBasemap.PositronNoLabels).tag(sync=True)
"""
A URL to a MapLibre-compatible basemap style.

Expand Down
42 changes: 42 additions & 0 deletions lonboard/_viz.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,48 @@ def viz(

return Map(layers=layers, **map_kwargs)

def viz_layer(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we add viz_layer, then we should change viz() to use viz_layer under the hood, because it looks like it's entirely duplicated.

Separately, I want to think over this API a bit more.

data: Union[VizDataInput, List[VizDataInput], Tuple[VizDataInput, ...]],
*,
scatterplot_kwargs: Optional[ScatterplotLayerKwargs] = None,
path_kwargs: Optional[PathLayerKwargs] = None,
polygon_kwargs: Optional[PolygonLayerKwargs] = None,
map_kwargs: Optional[MapKwargs] = None,
con: Optional[duckdb.DuckDBPyConnection] = None,
) -> List[Union[ScatterplotLayer, PathLayer, PolygonLayer]]:
"""Same as viz but returns only the created layers
"""
color_ordering = COLORS.copy()
shuffle(color_ordering)

if isinstance(data, (list, tuple)):
layers: List[Union[ScatterplotLayer, PathLayer, PolygonLayer]] = []
for i, item in enumerate(data):
ls = create_layers_from_data_input(
item,
_viz_color=color_ordering[i % len(color_ordering)],
scatterplot_kwargs=scatterplot_kwargs,
path_kwargs=path_kwargs,
polygon_kwargs=polygon_kwargs,
con=con,
)
layers.extend(ls)
else:
layers = create_layers_from_data_input(
data,
_viz_color=color_ordering[0],
scatterplot_kwargs=scatterplot_kwargs,
path_kwargs=path_kwargs,
polygon_kwargs=polygon_kwargs,
con=con,
)

map_kwargs = {} if not map_kwargs else map_kwargs

if "basemap_style" not in map_kwargs.keys():
map_kwargs["basemap_style"] = CartoBasemap.DarkMatter

return layers

DUCKDB_PY_CONN_ERROR = dedent("""\
Must pass in DuckDBPyRelation object, not DuckDBPyConnection.
Expand Down
Loading
Loading