Skip to content

The notebook map

Map shows a database as an interactive map in a notebook cell. It needs the widget extra, mosaica[widget], and you rarely make one directly, because Database.map, Viewer.map and Selection.map make one for you.

Map

Map(
    url: str,
    token: Optional[TokenSource] = None,
    *,
    view: Optional[str] = None,
    layers: Optional[Sequence[str]] = None,
    colour_by: Optional[str] = None,
    palette: Optional[str] = None,
    value_colours: Optional[dict] = None,
    cluster_colours: Optional[dict] = None,
    size_by: Optional[str] = None,
    size_min: Optional[float] = None,
    size_max: Optional[float] = None,
    size_scale: Optional[str] = None,
    filters: Optional[dict] = None,
    bbox: Optional[Sequence[float]] = None,
    height: int = 480,
    explorer_layout: str = "docked",
    title_field: Optional[str] = None,
    image_fields: Union[str, Sequence[str], None] = None,
    artifacts_per_tile: Optional[int] = None,
    budget: int = 0,
    budget_min: int = 1000,
    budget_max: int = 2000000,
    cluster_budget: int = 1000,
    cluster_budget_min: int = 10,
    cluster_budget_max: int = 10000,
    basemap: Any = None,
    **kwargs: Any,
)

Bases: AnyWidget

An interactive map of a Mosaica database, shown in a notebook cell.

The map in the browser fetches its data from the database's viewer plane with the token you give it, so it shows only the items that token may see.

m = mosaica.Map(viewer_url, token=token, colour_by="venue")
m

The token reaches the page as a message and is never part of the widget's state, so saving the notebook does not save it. The page calls url from the notebook's origin, which the server must admit: a database made with create() admits loopback pages, and another server needs the origin in serve.cors_origins. VS Code and Colab notebooks have origins no list can name, so the map cannot reach a database from them.

  • url: the address of the database's viewer plane.
  • token: the token the map reads with, in any of the forms TokenSource describes. It is required, so a Map made without one raises TypeError despite the default of None.
  • view: the view to open on. None, the default, opens the first one.
  • layers: the annotation layers to draw, each drawn with the layers it depends on. None, the default, lets the map choose, [] draws none, and "all" is refused.
  • colour_by: a rendered column to colour points by, or "cluster:<layer>" to colour them by the annotations of that layer.
  • palette: the palette that annotations are coloured from under "cluster:<layer>", which is one of "okabe-ito" (8 colours that colour-blind readers can tell apart), "tableau10" (10), "tableau20" (20, in light and dark pairs) and "kelly" (22, as distinct as possible). None, the default, leaves the map's choice, Tableau 10 at first.
  • value_colours: colours that replace the palette colour of single values of category columns, as {column: {value: "#rrggbb"}}. None, the default, keeps the colours chosen in the map, and {} gives every value its palette colour.
  • cluster_colours: colours that replace the palette colour of single annotations under "cluster:<layer>", as {layer: {mosaica_id: "#rrggbb"}} with each mosaica_id a decimal string. None, the default, keeps the colours chosen in the map, and {} gives every annotation its palette colour.
  • size_by: a number column to size points by. None, the default, draws every point at one size.
  • size_min, size_max: the radius in pixels of the point with the smallest and the largest value of size_by, where a point with no value is drawn as a ring. The page ignores a radius that is not a number above zero. None leaves the map's choice, 2 and 9 at first.
  • size_scale: how values are spread between the two radii, as "linear", "log" or "rank", which ranks each value among a sample of those drawn. None leaves the map's choice, "linear" at first.
  • filters: a filter expression, in the form Selection.filter takes.
  • bbox: the box to frame the camera on, as (min_x, min_y, max_x, max_y). Without it the map opens framed on the items that filters matches.
  • height: the widget's height in pixels in the notebook, 480 by default. The map fills the screen instead while its output is shown full screen. Its width is its container's, or the one an ipywidgets layout= states.
  • basemap: what is drawn under the points, as one of the values described below, or as a dictionary from view id to value for the views the map can switch to. None, the default, draws the world outline on a view with a map projection and nothing on any other view.
  • explorer_layout: where the controls go. "docked", the default, puts them in a sidebar beside the map, and "overlay" floats them over a map that fills the whole widget. A change shows the next time the map is displayed.
  • title_field: the field whose value titles a point in the hover and the item card. None, the default, titles a point by its id.
  • image_fields: the fields whose value is the address of an image, which the item card draws as that image. The address is an http: or https: one, or a path resolved against the page that shows the map. The viewer's browser loads the image from the host serving it. Any other value, and an image that does not load, is shown as text.
  • artifacts_per_tile: the most annotations each level of a layer draws in one map tile, largest first. None, the default, asks for 50, or for the server's max_artifacts_per_tile when that is smaller, and the server refuses a value above its maximum.
  • budget: how many points the map aims to draw on screen. 0, the default, keeps the map's own budget, which starts at 250,000.
  • budget_min, budget_max: the ends of the Most points slider in the map's Layers popover, 1,000 and 2,000,000 by default. Neither changes budget.
  • cluster_budget: the most clusters a nested or dag layer is drawn with, which the map meets by drawing parents in place of their children. The default is 1,000, and 0 draws every cluster.
  • cluster_budget_min, cluster_budget_max: the ends of the Most clusters slider, which the Layers popover shows while such a layer is drawn. They are 10 and 10,000 by default, and neither changes cluster_budget.

A basemap is one of these values:

  • "world": land, coastlines and country borders from the database's world outline, for a view with a map projection.
  • "none": nothing.
  • {"tiles": url_template, "attribution": text}: raster tiles from a tile server, for a view whose frame lines up with web map tiles. The template holds {z}, {x} and {y}, and the map shows attribution in its corner.
  • {"image": url_or_path, "bounds": [x0, y0, x1, y1]}: one image, stretched without reprojection over bounds in the view's coordinates, or over the whole frame when bounds is left out.

An image may be an http(s): or data: URL, or the path of a local file as a pathlib.Path or any other string, which is not expanded for ~. The file is read each time basemap is set and sent to the page as a message, so its bytes are not saved with the notebook. A file that cannot be read raises traitlets.TraitError and leaves basemap as it was, and a file: URL is refused. A key holding None is left out. Because a dictionary with a tiles or image key is read as one basemap, a dictionary by view cannot name a view called tiles or image. A value of the wrong shape raises traitlets.TraitError, and the page refuses a value that does not fit the view and reports why in last_error and a warning.

Every argument except token is also an attribute of the same name, and setting one in a later cell applies it to the map, apart from explorer_layout. The map writes the changes made in it back into these attributes:

  • view, bbox, filters, layers, colour_by and the four size settings, when the map settles after a change, once it has finished fetching for the new view.
  • palette, when one is chosen in the map's Colour section.
  • budget and cluster_budget, when the Most points or Most clusters slider is let go.
  • value_colours and cluster_colours, as each colour is chosen on a field card or in Edit colours. Setting either replaces every colour of its kind that the map holds.

The page applies a filters expression only when its filter panel can show it, so it refuses any_of, none_of, mosaica_id and two tests on one column, applying nothing and saying why in last_error and a warning. A member_of test, alone or in none_of, is shown as a chip beside the panel's fields and keeps the map to an annotation's members or to the items outside it; one naming its annotation by key is refused, since the map holds an annotation by its mosaica_id.

The map also keeps these attributes, which you read and do not set:

  • selected: the mosaica_id of the picked item, as a decimal string, or None. It changes on each pick.
  • selected_artifact: the mosaica_id of the opened annotation, as a decimal string, or None.
  • region: the box or lasso drawn on the map, or None once it is cleared, as a dictionary of its shape, status, the counts visible, matched and served inside it, a verdict saying whether they are exact for the shape or cover the grid cells around it, and any refusal. It changes when the region's counts arrive.
  • last_error: why the page last refused something set from Python, or None.
  • tokens_sent: how many tokens the kernel has sent the page.

To run code when someone picks an item on the map, call m.observe(fn, names="selected"). In marimo, observe selected in place of reading .value, because mo.ui.anywidget(m) holds every attribute in that one value and a cell that reads it runs again each time the map settles.

A Map made without the components' JavaScript bundle, which bundle_path() finds, raises RuntimeError naming what to install.

side_by_side

side_by_side(*maps: Map) -> Any

Several maps in one row, sharing its width equally, in a notebook cell.

Each map keeps its own view, camera, filters and colours; moving one moves no other. In a marimo notebook the row is marimo.hstack over the maps, and elsewhere, as in Jupyter, an ipywidgets.HBox. Show it as a cell's last value, as a map is shown.

mosaica.side_by_side(db.map(view="topics"), db.map(view="topics-wide"))

A call with no map, or with something that is not a Map, raises TypeError.

bundle_path

bundle_path() -> Optional[Path]

The path of the components' JavaScript bundle that Map loads, or None when there is none.

The copy packaged in the wheel under mosaica/static/ is used when it is there, and a checkout's own build in clients/ts/components/dist/ otherwise.