Note

Using interactive maps requires ipyleaflet, an optional dependency. See the guide for installation and troubleshooting instructions.

Interactive

Classes:

WorkflowsLayer(imagery[, scales, colormap, …]) Subclass of ipyleaflet.TileLayer for displaying a Workflows Image or ImageCollection.
LayerController(map, **kwargs) An ipyleaflet.WidgetControl for managing WorkflowsLayer.
LayerControllerList(map[, …]) Widget displaying a list of LayerControllerRow widgets for a Map.
ImagePickerWidget([map, default_layer, …]) Widget to pick a layer from the map, as an Image.
ImageCollectionPickerWidget([map, …]) Widget to pick a layer from the map, as an ImageCollection.
Map(**kwargs) Subclass of ipyleaflet.Map with Workflows defaults and extra helper methods.
MapApp([map, layer_controller_list, …]) Widget displaying a map, layers, and output logs in a nicer layout.
ParameterSet(notify_object, notify_name, …) Parameters for a WorkflowsLayer, which updates the layer when new values are assigned.
ProxytypeInstance([klass, args, kw]) Trait type that tries to promote values to a given Proxytype
PixelInspector(map[, position, layout]) Display pixel values when clicking on the map.
WorkflowsBrowser([map]) Widget displaying a UI for browsing and searching Workflow objects, and displaying them on the map.

Data:

map A single MapApp instance that all visualize calls are automatically added to.
flows Browse shared Workflow objects (and add them to the map) with a predefined WorkflowsBrowser instance.
class WorkflowsLayer(imagery, scales=None, colormap=None, checkerboard=None, reduction=None, log_level=10, parameter_overrides=None, **kwargs)[source]

Subclass of ipyleaflet.TileLayer for displaying a Workflows Image or ImageCollection.

imagery

Read-only: the Image or ImageCollection to use. Change it with set_imagery.

Type:Image or ImageCollection
value

Read-only: a parametrized version of imagery, with all the values of parameters embedded in it.

Type:Image or ImageCollection
image_value

Read-only: a parametrized version of imagery as an Image, with any reduction applied and all the values of parameters embedded in it

Type:Image
parameters

Parameters to use while computing; modify attributes under .parameters (like layer.parameters.foo = "bar") to cause the layer to recompute and update under those new parameters. This trait is read-only in that you can’t do layer.parameters = a_new_parameter_set, but you can change the attributes within layer.parameters.

Type:ParameterSet
clear_on_update

Whether to clear all tiles from the map as soon as the layer changes, or leave out-of-date tiles visible until new ones have loaded. True (default) makes it easier to tell whether the layer is done loading and up-to-date or not. False prevents fast-loading layers from appearing to “flicker” as you interact with them.

Type:bool, default True
xyz_obj

Read-only: The XYZ object this layer is displaying.

Type:XYZ
session_id

Read-only: Unique ID that logs will be stored under, generated automatically.

Type:str
checkerboard

Whether to display a checkerboarded background for missing or masked data.

Type:bool, default True
colormap

Name of the colormap to use. If set, imagery must have 1 band.

Type:str, optional, default None
reduction

If displaying an ImageCollection, this method is used to reduce it into an Image. Reduction is performed before applying a colormap or scaling.

Type:{“min”, “max”, “mean”, “median”, “mosaic”, “sum”, “std”, “count”}
r_min

Min value for scaling the red band. Along with r_max, controls scaling when a colormap is enabled.

Type:float, optional, default None
r_max

Max value for scaling the red band. Along with r_min, controls scaling when a colormap is enabled.

Type:float, optional, default None
g_min

Min value for scaling the green band.

Type:float, optional, default None
g_max

Max value for scaling the green band.

Type:float, optional, default None
b_min

Min value for scaling the blue band.

Type:float, optional, default None
b_max

Max value for scaling the blue band.

Type:float, optional, default None
log_output

If set, write unique log records from tiles computation to this output area from a background thread. Setting to None stops the listener thread.

Type:ipywidgets.Output, optional, default None
log_level

Only listen for log records at or above this log level during tile computation. See https://docs.python.org/3/library/logging.html#logging-levels for valid log levels.

Type:int, default logging.DEBUG

Example

>>> import descarteslabs.workflows as wf
>>> wf.map 
>>> # ^ display interactive map
>>> img = wf.Image.from_id("landsat:LC08:PRE:TOAR:meta_LC80330352016022_v1").pick_bands("red")
>>> masked_img = img.mask(img > wf.parameter("threshold", wf.Float))
>>> layer = masked_img.visualize("sample", colormap="viridis", threshold=0.07) 
>>> layer.colormap = "plasma" 
>>> # ^ change colormap (this will update the layer on the map)
>>> layer.parameters.threshold = 0.13 
>>> # ^ adjust parameters (this also updates the layer)
>>> layer.set_scales((0.01, 0.3)) 
>>> # ^ adjust scaling (this also updates the layer)

Public constructor

Attributes:

attribution A trait for unicode strings.
autoscale_progress A trait whose value must be an instance of a specified class.
b_max Casting Float traitlet that also considers the empty string as None
b_min Casting Float traitlet that also considers the empty string as None
checkerboard A boolean (True, False) trait.
clear_on_update A boolean (True, False) trait.
colormap A trait for unicode strings.
g_max Casting Float traitlet that also considers the empty string as None
g_min Casting Float traitlet that also considers the empty string as None
image_value A trait whose value must be an instance of a specified class.
imagery A trait type representing a Union type.
log_level An int trait.
log_output A trait whose value must be an instance of a specified class.
min_zoom An int trait.
parameters A trait whose value must be an instance of a specified class.
r_max Casting Float traitlet that also considers the empty string as None
r_min Casting Float traitlet that also considers the empty string as None
reduction A trait for unicode strings.
session_id A trait for unicode strings.
url A trait for unicode strings.
value A trait type representing a Union type.
xyz_obj A trait whose value must be an instance of a specified class.

Methods:

clear_logs() Clear any logs currently displayed for this layer
forget_logs() Clear the set of known log records, so they are re-displayed if they occur again
get_scales() Get scales for a layer.
hold_url_updates() Context manager to prevent the layer URL from being updated multiple times.
make_url() Generate the URL for this layer.
set_imagery(imagery, **parameter_overrides) Set a new Image or ImageCollection object for this layer to use.
set_scales(scales[, new_colormap]) Update the scales for this layer by giving a list of scales
trait_has_value(name) Returns True if the specified trait has a value.
clear_logs()[source]

Clear any logs currently displayed for this layer

Example

>>> import descarteslabs.workflows as wf
>>> wf.map 
>>> img = wf.Image.from_id("landsat:LC08:PRE:TOAR:meta_LC80330352016022_v1") 
>>> layer = img.visualize("sample visualization") 
>>> # ^ will show an error for attempting to visualize more than 3 bands
>>> layer.clear_logs() 
>>> # ^ the errors will disappear
>>> wf.map.zoom = 10 
>>> # ^ attempting to load more tiles from img will cause the same error to appear
forget_logs()[source]

Clear the set of known log records, so they are re-displayed if they occur again

Example

>>> import descarteslabs.workflows as wf
>>> wf.map 
>>> img = wf.Image.from_id("landsat:LC08:PRE:TOAR:meta_LC80330352016022_v1") 
>>> layer = img.visualize("sample visualization") 
>>> # ^ will show an error for attempting to visualize more than 3 bands
>>> layer.forget_logs() 
>>> wf.map.zoom = 10 
>>> # ^ attempting to load more tiles from img will cause the same error to appear
get_scales()[source]

Get scales for a layer.

Returns:scales – A list containing a list of scales for each band in the layer or None if the layer has no scales set.
Return type:List[List[int]] or None

Example

>>> import descarteslabs.workflows as wf
>>> img = wf.Image.from_id("landsat:LC08:PRE:TOAR:meta_LC80330352016022_v1")
>>> img = img.pick_bands("red") 
>>> layer = img.visualize("sample visualization") 
>>> layer.set_scales((0.08, 0.3), 'viridis') 
>>> layer.get_scales() 
[[0.08, 0.3]]
hold_url_updates()[source]

Context manager to prevent the layer URL from being updated multiple times.

When leaving the context manager, the URL is always updated exactly once.

Also applies hold_trait_notifications.

Example

>>> import descarteslabs.workflows as wf
>>> img = wf.Image.from_id("landsat:LC08:PRE:TOAR:meta_LC80330352016022_v1") 
>>> img = img.pick_bands("red") 
>>> layer = img.visualize("sample visualization", colormap="viridis") 
>>> with layer.hold_url_updates(): 
...     layer.checkerboard = False 
...     layer.set_scales([0, 1], new_colormap="magma") 
...     layer.set_scales([0, 1], new_colormap="magma") 
>>> # ^ the layer will now update only once, instead of 3 times.
make_url()[source]

Generate the URL for this layer.

This is called automatically as the attributes (imagery, colormap, scales, etc.) are changed.

Example

>>> import descarteslabs.workflows as wf
>>> img = wf.Image.from_id("landsat:LC08:PRE:TOAR:meta_LC80330352016022_v1") 
>>> img = img.pick_bands("red blue green") 
>>> layer = img.visualize("sample") 
>>> layer.make_url() 
'https://workflows.descarteslabs.com/master/xyz/9ec70d0e99db7f50c856c774809ae454ffd8475816e05c5c/{z}/{x}/{y}.png?session_id=xxx&checkerboard=true'
set_imagery(imagery: Union[descarteslabs.workflows.types.geospatial.image.Image, descarteslabs.workflows.types.geospatial.imagecollection.ImageCollection], **parameter_overrides)[source]

Set a new Image or ImageCollection object for this layer to use. You can set/override the values of any parameters the imagery depends on by passing them as kwargs.

If the imagery depends on parameters that don’t have default values (created with wf.parameter("name", wf.Int) for example, versus wf.widget.input("name", default=1)), then you must pass values for those parameters.

Parameters:**parameter_overrides (JSON-serializable value, Proxytype, or ipywidgets.Widget) – Paramter names to values. Values can be Python types, Proxytype instances, or ipywidgets.Widget instances. Names must correspond to parameters that imagery depends on.

Example

>>> import descarteslabs.workflows as wf
>>> wf.map 
>>> img = wf.Image.from_id("landsat:LC08:PRE:TOAR:meta_LC80330352016022_v1") 
>>> red = img.pick_bands("red") 
>>> blue = img.pick_bands("blue") 
>>> layer = red.visualize(name="sample visualization") 
>>> layer.set_imagery(blue) 
set_scales(scales, new_colormap=False)[source]

Update the scales for this layer by giving a list of scales

Parameters:
  • scales (list of lists, default None) –

    The scaling to apply to each band in the Image or ImageCollection. If displaying an ImageCollection, it is reduced into an Image before applying scaling.

    If Image or ImageCollection contains 3 bands, scales must be a list like [(0, 1), (0, 1), (-1, 1)].

    If Image or ImageCollection contains 1 band, scales must be a list like [(0, 1)], or just (0, 1) for convenience

    If None, each 256x256 tile will be scaled independently based on the min and max values of its data.

  • new_colormap (str, None, or False, optional, default False) – A new colormap to set at the same time, or False to use the current colormap.

Example

>>> import descarteslabs.workflows as wf
>>> wf.map 
>>> img = wf.Image.from_id("landsat:LC08:PRE:TOAR:meta_LC80330352016022_v1") 
>>> img = img.pick_bands("red") 
>>> layer = img.visualize("sample visualization", colormap="viridis") 
>>> layer.set_scales((0.08, 0.3), new_colormap="plasma") 
>>> # ^ optionally set new colormap
trait_has_value(name)[source]

Returns True if the specified trait has a value.

This will return false even if getattr would return a dynamically generated default value. These default values will be recognized as existing only after they have been generated.

Example

class MyClass(HasTraits):
    i = Int()

mc = MyClass()
assert not mc.trait_has_value("i")
mc.i # generates a default value
assert mc.trait_has_value("i")
attribution

A trait for unicode strings.

autoscale_progress

A trait whose value must be an instance of a specified class.

The value can also be an instance of a subclass of the specified class.

Subclasses can declare default classes by overriding the klass attribute

b_max

Casting Float traitlet that also considers the empty string as None

b_min

Casting Float traitlet that also considers the empty string as None

checkerboard

A boolean (True, False) trait.

clear_on_update

A boolean (True, False) trait.

colormap

A trait for unicode strings.

g_max

Casting Float traitlet that also considers the empty string as None

g_min

Casting Float traitlet that also considers the empty string as None

image_value

A trait whose value must be an instance of a specified class.

The value can also be an instance of a subclass of the specified class.

Subclasses can declare default classes by overriding the klass attribute

imagery

A trait type representing a Union type.

log_level

An int trait.

log_output

A trait whose value must be an instance of a specified class.

The value can also be an instance of a subclass of the specified class.

Subclasses can declare default classes by overriding the klass attribute

min_zoom

An int trait.

parameters

A trait whose value must be an instance of a specified class.

The value can also be an instance of a subclass of the specified class.

Subclasses can declare default classes by overriding the klass attribute

r_max

Casting Float traitlet that also considers the empty string as None

r_min

Casting Float traitlet that also considers the empty string as None

reduction

A trait for unicode strings.

session_id

A trait for unicode strings.

url

A trait for unicode strings.

value

A trait type representing a Union type.

xyz_obj

A trait whose value must be an instance of a specified class.

The value can also be an instance of a subclass of the specified class.

Subclasses can declare default classes by overriding the klass attribute

class LayerController(map, **kwargs)[source]

An ipyleaflet.WidgetControl for managing WorkflowsLayer.

Unlike other ipyleaflet controls, a Map must be passed in on instantiation. Creating a LayerController automatically adds it to the given Map.

controller_list

The LayerControllerList widget displayed.

Type:LayerControllerList

Example

>>> import descarteslabs.workflows as wf
>>> img = wf.Image.from_id("landsat:LC08:PRE:TOAR:meta_LC80330352016022_v1").pick_bands("red green blue")
>>> my_map = wf.Map()  
>>> layer = wf.WorkflowsLayer(img)  
>>> my_map.add_layer(layer)  
>>> ctl = wf.LayerController(my_map)  
>>> my_map  

Create the LayerController.

Parameters:map (Map) – The Map to which to add this control.
class LayerControllerList(map, control_tile_layers=True, control_other_layers=False)[source]

Widget displaying a list of LayerControllerRow widgets for a Map.

Example

>>> import descarteslabs.workflows as wf
>>> my_map = wf.Map() 
>>> img = wf.Image.from_id("landsat:LC08:PRE:TOAR:meta_LC80330352016022_v1").pick_bands("red") 
>>> img.visualize("sample visualization", map=my_map) 
>>> my_map 
>>> # ^ shows map with no layer controls
>>> layer_controller = wf.interactive.LayerControllerList(my_map) 
>>> layer_controller 
>>> # ^ shows layer controls as a separate widget
>>> layer_controller.children 
>>> # ^ list of individual widgets controlling each layer

Public constructor

Attributes:

control_other_layers Show generic controls for other ipyleaflet layer types
control_tile_layers Show controls for `ipyleaflet.TileLayer`s
map The map being controlled
control_other_layers

Show generic controls for other ipyleaflet layer types

control_tile_layers

Show controls for `ipyleaflet.TileLayer`s

map

The map being controlled

class ImagePickerWidget(map=None, default_layer: Optional[descarteslabs.workflows.interactive.layer.WorkflowsLayer] = None, hide_deps_of: Optional[descarteslabs.workflows.types.core.core.Proxytype] = None, **kwargs)[source]

Widget to pick a layer from the map, as an Image.

If selecting an ImageCollection layer, this gives it with its reduction applied.

Note you cannot change the selected layer programmatically, only by using the widget.

Construct a LayerPicker widget for a map.

Parameters:
  • map (ipyleaflet.Map) – The map instance to pick from. Defaults to wf.map.
  • default_layer (WorkflowsLayer) – The layer instance to have selected by default
  • hide_deps_of (Proxytype) – Hide any layers from the dropdown that have this object in their .params. Mainly used by the Picker parameter widget to hide its own layer from the dropdown, avoiding graft cycles.

Attributes:

value A trait whose value must be an instance of a specified class.
value

A trait whose value must be an instance of a specified class.

The value can also be an instance of a subclass of the specified class.

Subclasses can declare default classes by overriding the klass attribute

class ImageCollectionPickerWidget(map=None, default_layer: Optional[descarteslabs.workflows.interactive.layer.WorkflowsLayer] = None, hide_deps_of: Optional[descarteslabs.workflows.types.core.core.Proxytype] = None, **kwargs)[source]

Widget to pick a layer from the map, as an ImageCollection.

Only layers showing ImageCollections (not Images) will be shown.

Note you cannot change the selected layer programmatically, only by using the widget.

Construct a LayerPicker widget for a map.

Parameters:
  • map (ipyleaflet.Map) – The map instance to pick from. Defaults to wf.map.
  • default_layer (WorkflowsLayer) – The layer instance to have selected by default
  • hide_deps_of (Proxytype) – Hide any layers from the dropdown that have this object in their .params. Mainly used by the Picker parameter widget to hide its own layer from the dropdown, avoiding graft cycles.
class Map(**kwargs)[source]

Subclass of ipyleaflet.Map with Workflows defaults and extra helper methods.

output_log

Widget where functions doing operations on this map (especially compute operations, like autoscaling or timeseries) can log their output.

Type:ipywidgets.Output

Example

>>> import descarteslabs.workflows as wf
>>> from ipywidgets import HBox 
>>> map1 = wf.Map() 
>>> map2 = wf.Map() 
>>> HBox([map1, map2]) 
>>> # ^ view multiple maps in a custom layout

Public constructor

Attributes:

autoscale_outputs Widget containing all layers’ autoscale output widgets
center Initial geographic center of the map
inspecting_pixels Whether the pixel inspector is active, and clicking on the map displays pixel values
logs Widget where tiles layers can write their log messages.
min_zoom Minimum allowable zoom level of the map
output_log Widget where functions doing operations on this map (especially compute operations) can log their output.
scroll_wheel_zoom Whether the map can be zoomed by using the mouse wheel
zoom_start Initial map zoom level

Methods:

clear_layers() Remove all layers from the map (besides the base layer)
geocontext([resolution, shape, crs]) A AOI representing the current view area and resolution of the map.
map_dimensions() Width, height of this Map, in pixels.
move_layer(layer, new_index) Move a layer to a new index.
move_layer_down(layer) Move a layer down one, if not already at the bottom.
move_layer_up(layer) Move a layer up one, if not already at the top.
remove_layer(layer_name) Remove a named layer or layer instance from the map
clear_layers()[source]

Remove all layers from the map (besides the base layer)

Example

>>> import descarteslabs.workflows as wf
>>> wf.map 
>>> img = wf.Image.from_id("landsat:LC08:PRE:TOAR:meta_LC80330352016022_v1")
>>> red = img.pick_bands("red").visualize("red layer") 
>>> wf.map.clear_layers() 
geocontext(resolution=None, shape=None, crs='EPSG:3857')[source]

A AOI representing the current view area and resolution of the map. The bounds of the of the returned geocontext are the current bounds of the map viewport.

Parameters:
  • crs (str, default "EPSG:3857") – Coordinate reference system into which data will be projected, expressed as an EPSG code (like EPSG:4326), PROJ.4 definition, or "utm". If crs is "utm", the zone is calculated automatically from lat, lng of map center. Defaults to the Web Mercator projection (EPSG:3857).
  • resolution (float, default: None) – Distance, in units of the crs, that the edge of each pixel represents on the ground. Only one of resolution or shape can be given. If neither shape nor resolution is given, shape defaults to the current dimensions of the map viewport.
  • shape (tuple, default: None) – The dimensions (rows, columns), in pixels, to fit the output array within. Only one of resolution or shape can be given. If neither shape nor resolution is given, shape defaults to the current dimensions of the map viewport.

Example

>>> import descarteslabs.workflows as wf
>>> wf.map.geocontext() 
AOI(geometry=None,
    resolution=None,
    crs='EPSG:3857',
    align_pixels=False,
    bounds=(-106.14303588867188, 35.631349127185125, -105.73276519775392, 35.7428898051826),
    bounds_crs='EPSG:4326',
    shape=(1195, 398))
>>> wf.map.geocontext(crs="utm") 
AOI(geometry=None,
    resolution=None,
    crs='+proj=utm +zone=13 +datum=WGS84 +units=m +no_defs ',
    align_pixels=False,
    bounds=(-106.14303588867188, 35.631349127185125, -105.73276519775392, 35.7428898051826),
    bounds_crs='EPSG:4326',
    shape=(1195, 398))
>>> wf.map 
Returns:geoctx
Return type:descarteslabs.geo.AOI
map_dimensions()[source]

Width, height of this Map, in pixels.

Example

>>> import descarteslabs.workflows as wf
>>> wf.map 
>>> wf.map.map_dimensions() 
(1182, 398)
move_layer(layer, new_index)[source]

Move a layer to a new index. Indices are one-indexed.

Parameters:
  • layer (ipyleaflet.Layer) – Leaflet layer object to move
  • new_index (Int) – Index to move layer to. Indices are one-indexed.
Raises:

ValueError – If layer is a base layer, or does not already exist on the map.

Example

>>> import descarteslabs.workflows as wf
>>> img = wf.Image.from_id("landsat:LC08:PRE:TOAR:meta_LC80330352016022_v1")
>>> red_layer = img.pick_bands("red").visualize("red layer") 
>>> blue = img.pick_bands("blue").visualize("blue layer") 
>>> wf.map.move_layer(red_layer, 2) 
>>> # "red layer" will now be displayed on top of "blue layer"
>>> wf.map 
move_layer_down(layer)[source]

Move a layer down one, if not already at the bottom.

Parameters:layer (ipyleaflet.Layer) –
Raises:ValueError – If layer is a base layer, or does not already exist on the map.

Example

>>> import descarteslabs.workflows as wf
>>> wf.map 
>>> img = wf.Image.from_id("landsat:LC08:PRE:TOAR:meta_LC80330352016022_v1")
>>> red = img.pick_bands("red").visualize("red layer") 
>>> blue_layer = img.pick_bands("blue").visualize("blue layer") 
>>> wf.map.move_layer_down(blue_layer) 
>>> # ^ display blue_layer below red_layer
move_layer_up(layer)[source]

Move a layer up one, if not already at the top.

Parameters:layer (ipyleaflet.Layer) –
Raises:ValueError – If layer is a base layer, or does not already exist on the map.

Example

>>> import descarteslabs.workflows as wf
>>> wf.map 
>>> img = wf.Image.from_id("landsat:LC08:PRE:TOAR:meta_LC80330352016022_v1")
>>> red_layer = img.pick_bands("red").visualize("red layer") 
>>> blue = img.pick_bands("blue").visualize("blue layer") 
>>> wf.map.move_layer_up(red_layer) 
>>> # ^ display red_layer above blue_layer
remove_layer(layer_name)[source]

Remove a named layer or layer instance from the map

Parameters:layer_name (Str or ipyleaflet.Layer) – Name of the layer or Layer instance to remove

Example

>>> import descarteslabs.workflows as wf
>>> wf.map 
>>> img = wf.Image.from_id("landsat:LC08:PRE:TOAR:meta_LC80330352016022_v1")
>>> red = img.pick_bands("red").visualize("red layer") 
>>> blue = img.pick_bands("blue").visualize("blue layer") 
>>> wf.map.remove_layer("red layer") 
>>> # ^ remove "red layer" from the map (by name)
autoscale_outputs

Widget containing all layers’ autoscale output widgets

center

Initial geographic center of the map

inspecting_pixels

Whether the pixel inspector is active, and clicking on the map displays pixel values

logs

Widget where tiles layers can write their log messages.

min_zoom

Minimum allowable zoom level of the map

output_log

Widget where functions doing operations on this map (especially compute operations) can log their output.

scroll_wheel_zoom

Whether the map can be zoomed by using the mouse wheel

zoom_start

Initial map zoom level

class MapApp(map=None, layer_controller_list=None, map_controller=None)[source]

Widget displaying a map, layers, and output logs in a nicer layout.

Forwards attributes and methods to self.map.

Note: to change the size of the map when displayed inline in a notebook, set wf.map.map.layout.height = "1000px". (wf.map.map is the actual map widget, wf.map is the container with the layer controls, which will resize accordingly.) Setting the height on just wf.map will also work, but if you use an output view, then the map won’t resize itself to fit in within it.

Example

>>> import descarteslabs.workflows as wf
>>> from ipywidgets import HBox 
>>> map1 = wf.interactive.MapApp() 
>>> map2 = wf.interactive.MapApp() 
>>> img = wf.Image.from_id("landsat:LC08:PRE:TOAR:meta_LC80330352016022_v1") 
>>> img1 = img.pick_bands("red") 
>>> img2 = img.pick_bands("nir") 
>>> img1.visualize("red band", map=map1) 
>>> img2.visualize("nir band", map=map2) 
>>> # ^ view the red band on map1 and the nir band on map2
>>> HBox([map1, map2]) 
>>> # ^ view the two maps in a custom layout
>>> ctx = map1.geocontext() 
>>> # get the geocontext of the first map

Public constructor

Attributes:

control_other_layers Show generic controls for other ipyleaflet layer types
control_tile_layers Show controls for `ipyleaflet.TileLayer`s
control_other_layers

Show generic controls for other ipyleaflet layer types

control_tile_layers

Show controls for `ipyleaflet.TileLayer`s

class ParameterSet(notify_object, notify_name, **traits)[source]

Parameters for a WorkflowsLayer, which updates the layer when new values are assigned.

A ParameterSet is constructed automatically when calling Image.visualize and added to the WorkflowsLayer; you shouldn’t construct one manually.

You can access a widget for interactively controlling these parameters at widget.

widget

A widget showing a table of controls, linked to this ParameterSet. Updating the controls causes the map to update.

Type:ipywidgets.Widget

Example

>>> import descarteslabs.workflows as wf
>>> imgs = wf.ImageCollection.from_id(
...     "sentinel-1:GRD", start_datetime=wf.parameter("start", wf.Datetime)
... )
>>> filtered = imgs.filter(lambda img: img.properties['pass'] == wf.parameter("pass_dir", wf.Str))
>>> composite = imgs.mean(axis="images").pick_bands("vv")
>>> lyr = composite.visualize("vv mean", start=wf.Datetime(2018), pass_dir="ASCENDING")  
>>> params = lyr.parameters  
>>> # ^ get the ParameterSet for the layer
>>> params.pass_dir  
"ASCENDING"
>>> params.pass_dir = "DESCENDING"  
>>> # ^ this updates the layer on the map
>>> params.start = "2019-01-01"  
>>> # ^ as does this
>>> params.link("start", my_ipywidget)  
>>> # ^ this links the "start" parameter to an ipywidget's value

Notes

The names and types of fields on a ParameterSet are fixed, and can only be changed using update. This means that on a ParameterSet that only has the field x, which holds a float, params.x = "foo" will fail (wrong type), as will params.y = "bar" (y doesn’t exist).

When Image.visualize creates a ParameterSet for you, it adds fields for whichever parameter the imagery depends on. If img depends on wf.widgets.slider("slidey", 0, 1) and wf.parameter("td", wf.Timedelta) for example, then img.visualize("my layer", td=wf.Timedelta(days=2)) will create the fields slidey and td. More importantly, it infers the type of those fields from their parameter types, so slidey would only accept floats, and td would only accept Timedeltas.

Therefore, if you experience a TypeError assiging to a ParameterSet field, you may need to change types of the initial parameters img depends on.

You shouldn’t need to construct a ParameterSet manually, but here’s how you would:

Parameters:
  • notify_object (traitlets.HasTraits instance) – The object to notify when any of the traits on this ParameterSet change
  • notify_name (str) – The name to use in the change notification sent to that object
  • **traits (traitlets.TraitType instances) – The traits to add to this ParameterSet

Methods:

add_traits(**traits) Dynamically add trait attributes to the HasTraits instance.
link(name, target[, attr]) Link an attribute to an ipywidget (or other object).
make_widget([skip]) Make a widget for controlling these parameters.
remove_traits(*names) Remove traits that were dynamically added to the HasTraits instance
to_dict() Key-value pairs of the parameters, in order.
update(**new_values) Update the ParameterSet with new values.
add_traits(**traits)[source]

Dynamically add trait attributes to the HasTraits instance.

If you are manipulating a ParameterSet generated from a layer, instead use update, which handles adding and removing traits in a more delclarative way.

Example

>>> import traitlets
>>> import descarteslabs.workflows as wf
>>> class Listener(traitlets.HasTraits):
...     @traitlets.observe("param")
...     def handler(self, change):
...         print(change['key'])
...         print(change)
>>> listener = Listener()
>>> ps = wf.interactive.ParameterSet(listener, "param", foo=traitlets.Float()) 
>>> ps.foo = 1.1 
foo
{'name': 'param',
 'old': 0.0,
 'new': 1.1,
 'owner': ParameterSet({'foo': 1.1}),
 'type': 'change',
 'key': 'foo'
 }
>>> ps.bar = "baz" 
>>> # ^ nothing is printed, `bar` is not a trait
>>> ps.add_traits(bar=traitlets.Unicode()) 
>>> ps.bar 
''
>>> ps.bar = "quix" 
bar
{'name': 'param',
 'old': '',
 'new': 'quix',
 'owner': ParameterSet({'bar': 'quix', 'foo': 1.1}),
 'type': 'change',
 'key': 'bar'
 }

Link an attribute to an ipywidget (or other object).

If a link to the attribute was previously created, it is unlinked.

Parameters:
  • name (str) – The name of the parameter to link
  • target (ipywidgets.Widget, any traitlets.HasTraits instance, or None) – The object to link to. If None, any existing link to name is removed.
  • attr (str, default "value") – The name of the attribute on target to link to. Defaults to "value", since that works for most ipywidgets.

Example

>>> import descarteslabs.workflows as wf
>>> from ipywidgets import FloatSlider
>>> img = wf.Image.from_id("landsat:LC08:PRE:TOAR:meta_LC80330352016022_v1") 
>>> img = img.pick_bands("red") 
>>> masked_img = img.mask(img > wf.parameter("threshold", wf.Float)) 
>>> layer = masked_img.visualize("sample", colormap="plasma", threshold=0.07) 
>>> layer.parameters.link("threshold", my_ipywidget) 
>>> # ^ links the "threshold" parameter to an ipywidget's value
>>> layer2 = masked_img.visualize("sample", colormap="plasma", threshold=0.3) 
>>> layer2.parameters.link("threshold", layer.parameters, attr="threshold") 
>>> # ^ now the `threshold` parameter is linked between `layer` and `layer2`
>>> widget = FloatSlider(min=0, max=1) 
>>> layer2.parameters.link("threshold", widget) 
>>> # ^ now `threshold` is linked to the widget, and the link is broken to `layer`
make_widget(skip=None)[source]

Make a widget for controlling these parameters.

Widgets that were passed in or linked are displayed. For values that aren’t already linked to a widget, an appropriate widget type is chosen if possible.

Note that this widget can become out of date and unlinked once update is called; use the widget property for an always-up-to-date widget.

Parameters:skip (list[str]) – Sequence of parameter names to not include in the widget
Returns:widget – A widget showing a table of controls, linked to this ParameterSet. Updating the widgets causes the map to update. If there are no parameters to display, returns None.
Return type:ipywidgets.Widget or None

Example

>>> import traitlets
>>> import descarteslabs.workflows as wf
>>> img = wf.Image.from_id("landsat:LC08:PRE:TOAR:meta_LC80330352016022_v1") 
>>> img = img.pick_bands("red") 
>>> masked_img = img.mask(img > wf.parameter("threshold", wf.Float)) 
>>> layer = masked_img.visualize("sample", colormap="plasma", threshold=0.07, sample_param=0.0) 
>>> layer.parameters.make_widget(skip=["sample_param"]) 
>>> # ^ displays a widget for modifying a layer's parameters, optionally skipping params
remove_traits(*names)[source]

Remove traits that were dynamically added to the HasTraits instance

If you are manipulating a ParameterSet generated from a layer, instead use update, which handles adding and removing traits in a more delclarative way.

Example

>>> import traitlets
>>> import descarteslabs.workflows as wf
>>> class Listener(traitlets.HasTraits):
...     @traitlets.observe("param")
...     def handler(self, change):
...         print(change['key'])
...         print(change)
>>> listener = Listener()
>>> ps = wf.interactive.ParameterSet(listener, "param", foo=traitlets.Float()) 
>>> ps.foo = 1.1 
foo
{'name': 'param',
 'old': 0.0,
 'new': 1.1,
 'owner': ParameterSet({'foo': 1.1}),
 'type': 'change',
 'key': 'foo'
 }
>>> ps.add_traits(bar=traitlets.Unicode()) 
>>> ps.bar = 'quix' 
bar
{'name': 'param',
 'old': '',
 'new': 'quix',
 'owner': ParameterSet({'bar': 'quix', 'foo': 1.1}),
 'type': 'change',
 'key': 'bar'
 }
>>> ps.remove_traits("foo") 
>>> ps.foo = 2.2 
>>> # ^ nothing is printed, `foo` is no longer a trait
>>> ps.to_dict() 
{'bar': 'quix'}
to_dict()[source]

Key-value pairs of the parameters, in order.

Example

>>> import descarteslabs.workflows as wf
>>> img = wf.Image.from_id("landsat:LC08:PRE:TOAR:meta_LC80330352016022_v1") 
>>> img = img.pick_bands("red") 
>>> masked_img = img.mask(img > wf.parameter("threshold", wf.Float)) 
>>> layer = masked_img.visualize("sample", colormap="plasma", threshold=0.07) 
>>> layer.parameters.to_dict() 
{'threshold': 0.07}
update(**new_values)[source]

Update the ParameterSet with new values.

New parameters are added as fields on the ParameterSet, with their trait type inferred from the value.

Current parameters that are not present in new_values are removed from the ParameterSet.

Passing a value of a different type to a current parameter will change its trait type.

If a value is an ipywidgets Widget, it will be linked (via its "value" attribute) to that parameter. If a parameter was previously linked to a widget, and a different widget instance (or non-widget) is passed for its new value, the old widget is automatically unlinked. If the same widget instance is passed as is already linked, no change occurs.

The ParameterSet will be reordered to the order of these new values.

Parameters:**new_values (JSON-serializable value, Proxytype, or ipywidgets.Widget) – Parameter names to new values. Values can be Python types, Proxytype instances, or ipywidgets.Widget instances.

Example

>>> import descarteslabs.workflows as wf
>>> from ipywidgets import FloatSlider
>>> img = wf.Image.from_id("landsat:LC08:PRE:TOAR:meta_LC80330352016022_v1") 
>>> img = img.pick_bands("red") 
>>> masked_img = img.mask(img > wf.parameter("threshold", wf.Float)) 
>>> layer = masked_img.visualize("sample", colormap="plasma", threshold=0.07) 
>>> scaled_img = img * wf.parameter("scale", wf.Float) + wf.parameter("offset", wf.Float) 
>>> with layer.hold_trait_notifications(): 
...     layer.imagery = scaled_img 
...     layer.parameters.update(scale=FloatSlider(min=0, max=10, value=2), offset=2.5) 
>>> # ^ re-use the same layer instance for a new Image with different parameters
class ProxytypeInstance(klass=None, args=None, kw=None, **kwargs)[source]

Trait type that tries to promote values to a given Proxytype

Example

>>> import traitlets
>>> import descarteslabs.workflows as wf
>>> from descarteslabs.workflows.interactive import ProxytypeInstance
>>> class ProxyTraits(traitlets.HasTraits): 
...     int_list = ProxytypeInstance(klass=wf.List[wf.Int]) 
...     @traitlets.observe('int_list') 
...     def int_list_changed(self, change): 
...         print(f"new int list: {change['new']}") 
>>> pt = ProxyTraits() 
>>> pt.int_list = [1, 2, 3] 
new int list: <descarteslabs.workflows.types.containers.list_.List[Int] object at 0x...>
>>> pt.int_list = [1, 2, "not an int"] 
TraitError: For parameter 'int_list', could not promote [1, 2, 'not an int']
to <class 'descarteslabs.workflows.types.containers.list_.List[Int]'>: List[Int]:
Expected iterable values of type <class 'descarteslabs.workflows.types.primitives.number.Int'>,
but for item 2, got 'not an int'

Construct an Instance trait.

This trait allows values that are instances of a particular class or its subclasses. Our implementation is quite different from that of enthough.traits as we don’t allow instances to be used for klass and we handle the args and kw arguments differently.

Parameters:
  • klass (class, str) – The class that forms the basis for the trait. Class names can also be specified as strings, like ‘foo.bar.Bar’.
  • args (tuple) – Positional arguments for generating the default value.
  • kw (dict) – Keyword arguments for generating the default value.
  • allow_none (bool [ default False ]) – Indicates whether None is allowed as a value.
  • **kwargs – Extra kwargs passed to ClassBasedTraitType

Notes

If both args and kw are None, then the default value is None. If args is a tuple and kw is a dict, then the default is created as klass(*args, **kw). If exactly one of args or kw is None, the None is replaced by () or {}, respectively.

Methods:

validate(obj, value)
validate(obj, value)[source]
class PixelInspector(map, position='topright', layout=None)[source]

Display pixel values when clicking on the map.

Whenever you click on the map, it fetches the pixel values at that location for all active Workflows layers and displays them in a table overlaid on the map. It also shows a marker on the map indicating the last position clicked. As layers change, or are added or removed, the table keeps fetching pixel values for the new layers at the last-clicked point (the marker’s current position).

For performance, the inspector does not use full-resolution data, but rather whatever resolution (zoom level) the map is currently displaying. Therefore, it’s possible that values for the same point would come back slightly different at different zoom levels. (Note that the resampling method used is whatever the input Image or ImageCollection was constructed with.)

To unlink from the map, call unlink.

Example

>>> import descarteslabs.workflows as wf
>>> my_map = wf.interactive.Map()
>>> img = wf.Image.from_id("landsat:LC08:PRE:TOAR:meta_LC80330352016022_v1").pick_bands("red")
>>> img.pick_bands("red").visualize("Red", colormap="Reds", map=my_map)  
>>> img.pick_bands("green").visualize("Green", colormap="Greens", map=my_map)  
>>> inspector = wf.interactive.PixelInspector(my_map)
>>> my_map  
>>> # ^ display the map
>>> # click on the map; a table will pop up showing pixel values for the Red and Green layers
>>> inspector.unlink()
>>> # table and marker disappear; click again and nothing happens

Construct a PixelInspector and attach it to a map.

Parameters:
  • map (ipyleaflet.Map, workflows.interactive.MapApp) – The map to attach to
  • position (str, optional, default "topright") – Where on the map to display the values table
  • layout (ipywidgets.Layout, optional) – Layout for the values table. Defaults to Layout(max_height="350px", overflow="scroll", padding="4px")

Attributes:

marker A trait whose value must be an instance of a specified class.
n_bands An int trait.

Methods:

unlink() Stop listening for click events or layer updates and remove the table from the map

Stop listening for click events or layer updates and remove the table from the map

marker

A trait whose value must be an instance of a specified class.

The value can also be an instance of a subclass of the specified class.

Subclasses can declare default classes by overriding the klass attribute

n_bands

An int trait.

class WorkflowsBrowser(map=None, **kwargs)[source]

Widget displaying a UI for browsing and searching Workflow objects, and displaying them on the map.

name

The name prefix used in the search

Type:str
mine

Whether to seach for only the current user’s Workflows. If True, email is ignored.

Type:bool
email

The email used in the search

Type:str
selected_id

The currently-selected Workflow ID (like you@example.com:workflow_name).

Type:str
selected_version

The currently-selected version name (like 1.2.0).

Type:str
map

Map instance used by the “Add to map” button and add_current_to_map. Defaults to wf.map.

Type:ipyleaflet.Map, MapApp
flows

List of Workflow objects currently being displayed that matched the search. Read-only.

Type:List[Workflow]
current_flow

The currently-selected Workflow object, or None.

Type:Optional[Workflow]
current_vg

The currently-selected VersionedGraft object, or None.

Type:Optional[VersionedGraft]

Example

>>> import descarteslabs.workflows as wf
>>> wf.flows  
>>> # displays the Workflow browser widget

Public constructor

Methods:

add_current_to_map() Add the currently-selected Workflow to wf.map or self.map, if possible.

Attributes:

current_flow A trait whose value must be an instance of a specified class.
current_vg A trait whose value must be an instance of a specified class.
email A trait for unicode strings.
flows An instance of a Python list.
mine A boolean (True, False) trait.
name A trait for unicode strings.
selected_id A trait for unicode strings.
selected_version A trait for unicode strings.
add_current_to_map()[source]

Add the currently-selected Workflow to wf.map or self.map, if possible.

The Workflow must be one of these types:

If the version has viz_options, the first VizOption will be used to style the layer on the map.

If self.map is None, the layer will be added to wf.map, otherwise to self.map.

Returns:

lyr – The layer added to the map

Return type:

WorkflowsLayer

Raises:
  • ValueError – If a Workflow and version are not currently selected. If the currently-selected Workflow and version is incompatible with this client version.
  • TypeError – If the selected version is not one of the supported types.
current_flow

A trait whose value must be an instance of a specified class.

The value can also be an instance of a subclass of the specified class.

Subclasses can declare default classes by overriding the klass attribute

current_vg

A trait whose value must be an instance of a specified class.

The value can also be an instance of a subclass of the specified class.

Subclasses can declare default classes by overriding the klass attribute

email

A trait for unicode strings.

flows

An instance of a Python list.

mine

A boolean (True, False) trait.

name

A trait for unicode strings.

selected_id

A trait for unicode strings.

selected_version

A trait for unicode strings.

map = `ipyleaflet` and/or `ipywidgets` Jupyter extensions are not installed! (or you're not in a Jupyter notebook.) To install for JupyterLab, run this in a cell: !jupyter labextension install jupyter-leaflet @jupyter-widgets/jupyterlab-manager To install for plain Jupyter Notebook, run this in a cell: !jupyter nbextension enable --py --sys-prefix ipyleaflet Then, restart the kernel and refresh the webpage.

A single MapApp instance that all visualize calls are automatically added to. This is the best starting point for using Workflows interactive maps.

Run:

wf.map

in a JupyterLab cell to display the map the first time, then right-click and select “New View for Output”. You can then position and rearrange the map as a tab however you like.

Calling Image.visualize will by default add new layers to this map.

flows = WorkflowsBrowser(children=(HBox(children=(Button(icon='repeat', layout=Layout(overflow='visible', width='initial'), style=ButtonStyle(), tooltip='Reload'), Text(value='', description='Name prefix:'), Checkbox(value=False, description='Only mine'), Text(value='', description='Email:'), HTML(value=''))), HTML(value='<hr>'), WorkflowsListerWidget(children=(VBox(children=(HTML(value='<h2>Workflows</h2>'), Select(layout=Layout(height='100%', width='initial'), options=(), value=None)), layout=Layout(flex='1 0 auto', grid_area='widget001')), WorkflowWidget(layout=Layout(flex='1 0 auto', grid_area='widget002')), VersionGraftWidget(value='', layout=Layout(flex='1 0 auto', grid_area='widget003'))), layout=Layout(grid_gap='10px', grid_template_areas='"widget001 widget002 widget003"', grid_template_columns='repeat(3, 1fr)', grid_template_rows='repeat(1, 1fr)')), HTML(value='<hr>'), HBox(children=(HTML(value=''), Button(button_style='info', description='Add to map', style=ButtonStyle())), layout=Layout(justify_content='space-between'))))

Browse shared Workflow objects (and add them to the map) with a predefined WorkflowsBrowser instance.