class HoloMap
HoloMap is an n-dimensional mapping container that stores viewable elements or overlays indexed by tuple keys along declared key dimensions, enabling interactive exploration through widgets.
/tf/active/vicechatdev/patches/spaces.py
30 - 431
complex
Purpose
HoloMap serves as a container for organizing and visualizing collections of viewable elements across multiple dimensions. It allows users to create interactive visualizations where elements can be explored by varying widgets that map to the key dimensions. The class supports operations like overlaying, gridding, layouting, and collating nested structures. It's particularly useful for time series data, parameter sweeps, or any multi-dimensional data exploration where you want to interactively navigate through different views of your data.
Source Code
class HoloMap(Layoutable, UniformNdMapping, Overlayable):
"""
A HoloMap is an n-dimensional mapping of viewable elements or
overlays. Each item in a HoloMap has an tuple key defining the
values along each of the declared key dimensions, defining the
discretely sampled space of values.
The visual representation of a HoloMap consists of the viewable
objects inside the HoloMap which can be explored by varying one
or more widgets mapping onto the key dimensions of the HoloMap.
"""
data_type = (ViewableElement, NdMapping, Layout)
def __init__(self, initial_items=None, kdims=None, group=None, label=None, **params):
super().__init__(initial_items, kdims, group, label, **params)
@property
def opts(self):
return Opts(self, mode='holomap')
def overlay(self, dimensions=None, **kwargs):
"""Group by supplied dimension(s) and overlay each group
Groups data by supplied dimension(s) overlaying the groups
along the dimension(s).
Args:
dimensions: Dimension(s) of dimensions to group by
Returns:
NdOverlay object(s) with supplied dimensions
"""
dimensions = self._valid_dimensions(dimensions)
if len(dimensions) == self.ndims:
with item_check(False):
return NdOverlay(self, **kwargs).reindex(dimensions)
else:
dims = [d for d in self.kdims if d not in dimensions]
return self.groupby(dims, group_type=NdOverlay, **kwargs)
def grid(self, dimensions=None, **kwargs):
"""Group by supplied dimension(s) and lay out groups in grid
Groups data by supplied dimension(s) laying the groups along
the dimension(s) out in a GridSpace.
Args:
dimensions: Dimension/str or list
Dimension or list of dimensions to group by
Returns:
GridSpace with supplied dimensions
"""
dimensions = self._valid_dimensions(dimensions)
if len(dimensions) == self.ndims:
with item_check(False):
return GridSpace(self, **kwargs).reindex(dimensions)
return self.groupby(dimensions, container_type=GridSpace, **kwargs)
def layout(self, dimensions=None, **kwargs):
"""Group by supplied dimension(s) and lay out groups
Groups data by supplied dimension(s) laying the groups along
the dimension(s) out in a NdLayout.
Args:
dimensions: Dimension(s) to group by
Returns:
NdLayout with supplied dimensions
"""
dimensions = self._valid_dimensions(dimensions)
if len(dimensions) == self.ndims:
with item_check(False):
return NdLayout(self, **kwargs).reindex(dimensions)
return self.groupby(dimensions, container_type=NdLayout, **kwargs)
def options(self, *args, **kwargs):
"""Applies simplified option definition returning a new object
Applies options defined in a flat format to the objects
returned by the DynamicMap. If the options are to be set
directly on the objects in the HoloMap a simple format may be
used, e.g.:
obj.options(cmap='viridis', show_title=False)
If the object is nested the options must be qualified using
a type[.group][.label] specification, e.g.:
obj.options('Image', cmap='viridis', show_title=False)
or using:
obj.options({'Image': dict(cmap='viridis', show_title=False)})
Args:
*args: Sets of options to apply to object
Supports a number of formats including lists of Options
objects, a type[.group][.label] followed by a set of
keyword options to apply and a dictionary indexed by
type[.group][.label] specs.
backend (optional): Backend to apply options to
Defaults to current selected backend
clone (bool, optional): Whether to clone object
Options can be applied inplace with clone=False
**kwargs: Keywords of options
Set of options to apply to the object
Returns:
Returns the cloned object with the options applied
"""
data = OrderedDict([(k, v.options(*args, **kwargs))
for k, v in self.data.items()])
return self.clone(data)
def _split_overlays(self):
"Splits overlays inside the HoloMap into list of HoloMaps"
if not issubclass(self.type, CompositeOverlay):
return None, self.clone()
item_maps = OrderedDict()
for k, overlay in self.data.items():
for key, el in overlay.items():
if key not in item_maps:
item_maps[key] = [(k, el)]
else:
item_maps[key].append((k, el))
maps, keys = [], []
for k, layermap in item_maps.items():
maps.append(self.clone(layermap))
keys.append(k)
return keys, maps
def _dimension_keys(self):
"""
Helper for __mul__ that returns the list of keys together with
the dimension labels.
"""
return [tuple(zip([d.name for d in self.kdims], [k] if self.ndims == 1 else k))
for k in self.keys()]
def _dynamic_mul(self, dimensions, other, keys):
"""
Implements dynamic version of overlaying operation overlaying
DynamicMaps and HoloMaps where the key dimensions of one is
a strict superset of the other.
"""
# If either is a HoloMap compute Dimension values
if not isinstance(self, DynamicMap) or not isinstance(other, DynamicMap):
keys = sorted((d, v) for k in keys for d, v in k)
grouped = dict([(g, [v for _, v in group])
for g, group in groupby(keys, lambda x: x[0])])
dimensions = [d.clone(values=grouped[d.name]) for d in dimensions]
map_obj = None
# Combine streams
map_obj = self if isinstance(self, DynamicMap) else other
if isinstance(self, DynamicMap) and isinstance(other, DynamicMap):
self_streams = util.dimensioned_streams(self)
other_streams = util.dimensioned_streams(other)
streams = list(util.unique_iterator(self_streams+other_streams))
else:
streams = map_obj.streams
def dynamic_mul(*key, **kwargs):
key_map = {d.name: k for d, k in zip(dimensions, key)}
layers = []
try:
self_el = self.select(HoloMap, **key_map) if self.kdims else self[()]
layers.append(self_el)
except KeyError:
pass
try:
other_el = other.select(HoloMap, **key_map) if other.kdims else other[()]
layers.append(other_el)
except KeyError:
pass
return Overlay(layers)
callback = Callable(dynamic_mul, inputs=[self, other])
callback._is_overlay = True
if map_obj:
return map_obj.clone(callback=callback, shared_data=False,
kdims=dimensions, streams=streams)
else:
return DynamicMap(callback=callback, kdims=dimensions,
streams=streams)
def __mul__(self, other, reverse=False):
"""Overlays items in the object with another object
The mul (*) operator implements overlaying of different
objects. This method tries to intelligently overlay mappings
with differing keys. If the UniformNdMapping is mulled with a
simple ViewableElement each element in the UniformNdMapping is
overlaid with the ViewableElement. If the element the
UniformNdMapping is mulled with is another UniformNdMapping it
will try to match up the dimensions, making sure that items
with completely different dimensions aren't overlaid.
"""
if isinstance(other, HoloMap):
self_set = {d.name for d in self.kdims}
other_set = {d.name for d in other.kdims}
# Determine which is the subset, to generate list of keys and
# dimension labels for the new view
self_in_other = self_set.issubset(other_set)
other_in_self = other_set.issubset(self_set)
dims = [other.kdims, self.kdims] if self_in_other else [self.kdims, other.kdims]
dimensions = util.merge_dimensions(dims)
if self_in_other and other_in_self: # superset of each other
keys = self._dimension_keys() + other._dimension_keys()
super_keys = util.unique_iterator(keys)
elif self_in_other: # self is superset
dimensions = other.kdims
super_keys = other._dimension_keys()
elif other_in_self: # self is superset
super_keys = self._dimension_keys()
else: # neither is superset
raise Exception('One set of keys needs to be a strict subset of the other.')
if isinstance(self, DynamicMap) or isinstance(other, DynamicMap):
return self._dynamic_mul(dimensions, other, super_keys)
items = []
for dim_keys in super_keys:
# Generate keys for both subset and superset and sort them by the dimension index.
self_key = tuple(k for p, k in sorted(
[(self.get_dimension_index(dim), v) for dim, v in dim_keys
if dim in self.kdims]))
other_key = tuple(k for p, k in sorted(
[(other.get_dimension_index(dim), v) for dim, v in dim_keys
if dim in other.kdims]))
new_key = self_key if other_in_self else other_key
# Append SheetOverlay of combined items
if (self_key in self) and (other_key in other):
if reverse:
value = other[other_key] * self[self_key]
else:
value = self[self_key] * other[other_key]
items.append((new_key, value))
elif self_key in self:
items.append((new_key, Overlay([self[self_key]])))
else:
items.append((new_key, Overlay([other[other_key]])))
return self.clone(items, kdims=dimensions, label=self._label, group=self._group)
elif isinstance(other, self.data_type) and not isinstance(other, Layout):
if isinstance(self, DynamicMap):
def dynamic_mul(*args, **kwargs):
element = self[args]
if reverse:
return other * element
else:
return element * other
callback = Callable(dynamic_mul, inputs=[self, other])
callback._is_overlay = True
return self.clone(shared_data=False, callback=callback,
streams=util.dimensioned_streams(self))
items = [(k, other * v) if reverse else (k, v * other)
for (k, v) in self.data.items()]
return self.clone(items, label=self._label, group=self._group)
else:
return NotImplemented
def __lshift__(self, other):
"Adjoin another object to this one returning an AdjointLayout"
if isinstance(other, (ViewableElement, UniformNdMapping, Empty)):
return AdjointLayout([self, other])
elif isinstance(other, AdjointLayout):
return AdjointLayout(other.data+[self])
else:
raise TypeError('Cannot append {0} to a AdjointLayout'.format(type(other).__name__))
def collate(self, merge_type=None, drop=[], drop_constant=False):
"""Collate allows reordering nested containers
Collation allows collapsing nested mapping types by merging
their dimensions. In simple terms in merges nested containers
into a single merged type.
In the simple case a HoloMap containing other HoloMaps can
easily be joined in this way. However collation is
particularly useful when the objects being joined are deeply
nested, e.g. you want to join multiple Layouts recorded at
different times, collation will return one Layout containing
HoloMaps indexed by Time. Changing the merge_type will allow
merging the outer Dimension into any other UniformNdMapping
type.
Args:
merge_type: Type of the object to merge with
drop: List of dimensions to drop
drop_constant: Drop constant dimensions automatically
Returns:
Collated Layout or HoloMap
"""
from .element import Collator
merge_type=merge_type if merge_type else self.__class__
return Collator(self, merge_type=merge_type, drop=drop,
drop_constant=drop_constant)()
def decollate(self):
"""Packs HoloMap of DynamicMaps into a single DynamicMap that returns an
HoloMap
Decollation allows packing a HoloMap of DynamicMaps into a single DynamicMap
that returns an HoloMap of simple (non-dynamic) elements. All nested streams
are lifted to the resulting DynamicMap, and are available in the `streams`
property. The `callback` property of the resulting DynamicMap is a pure,
stateless function of the stream values. To avoid stream parameter name
conflicts, the resulting DynamicMap is configured with
positional_stream_args=True, and the callback function accepts stream values
as positional dict arguments.
Returns:
DynamicMap that returns an HoloMap
"""
from .decollate import decollate
return decollate(self)
def relabel(self, label=None, group=None, depth=1):
"""Clone object and apply new group and/or label.
Applies relabeling to children up to the supplied depth.
Args:
label (str, optional): New label to apply to returned object
group (str, optional): New group to apply to returned object
depth (int, optional): Depth to which relabel will be applied
If applied to container allows applying relabeling to
contained objects up to the specified depth
Returns:
Returns relabelled object
"""
return super().relabel(label=label, group=group, depth=depth)
def hist(self, dimension=None, num_bins=20, bin_range=None,
adjoin=True, individually=True, **kwargs):
"""Computes and adjoins histogram along specified dimension(s).
Defaults to first value dimension if present otherwise falls
back to first key dimension.
Args:
dimension: Dimension(s) to compute histogram on
num_bins (int, optional): Number of bins
bin_range (tuple optional): Lower and upper bounds of bins
adjoin (bool, optional): Whether to adjoin histogram
Returns:
AdjointLayout of HoloMap and histograms or just the
histograms
"""
if dimension is not None and not isinstance(dimension, list):
dimension = [dimension]
histmaps = [self.clone(shared_data=False) for _ in (dimension or [None])]
if individually:
map_range = None
else:
if dimension is None:
raise Exception("Please supply the dimension to compute a histogram for.")
map_range = self.range(kwargs['dimension'])
bin_range = map_range if bin_range is None else bin_range
style_prefix = 'Custom[<' + self.name + '>]_'
if issubclass(self.type, (NdOverlay, Overlay)) and 'index' not in kwargs:
kwargs['index'] = 0
for k, v in self.data.items():
hists = v.hist(adjoin=False, dimension=dimension,
bin_range=bin_range, num_bins=num_bins,
style_prefix=style_prefix, **kwargs)
if isinstance(hists, Layout):
for i, hist in enumerate(hists):
histmaps[i][k] = hist
else:
histmaps[0][k] = hists
if adjoin:
layout = self
for hist in histmaps:
layout = (layout << hist)
if issubclass(self.type, (NdOverlay, Overlay)):
layout.main_layer = kwargs['index']
return layout
else:
if len(histmaps) > 1:
return Layout(histmaps)
else:
return histmaps[0]
Parameters
| Name | Type | Default | Kind |
|---|---|---|---|
bases |
Layoutable, UniformNdMapping, Overlayable | - |
Parameter Details
initial_items: Initial data items to populate the HoloMap. Can be a list of (key, value) tuples, a dictionary, or another mapping object. Keys should be tuples matching the dimensionality of kdims.
kdims: Key dimensions that define the indexing structure of the HoloMap. Can be a list of Dimension objects or strings that will be converted to Dimensions. These dimensions define the parameter space that can be explored.
group: String identifier for grouping related HoloMaps together. Used for organization and identification purposes.
label: String label for the HoloMap instance. Used for display and identification purposes.
params: Additional keyword parameters passed to parent classes (Layoutable, UniformNdMapping, Overlayable). Can include various configuration options.
Return Value
Instantiation returns a HoloMap object that acts as a container for viewable elements. Methods return various types: overlay() returns NdOverlay objects, grid() returns GridSpace, layout() returns NdLayout, options() returns a cloned HoloMap with applied options, collate() returns a collated Layout or HoloMap, decollate() returns a DynamicMap, hist() returns AdjointLayout or histograms, and relabel() returns a relabeled clone.
Class Interface
Methods
__init__(self, initial_items=None, kdims=None, group=None, label=None, **params)
Purpose: Initialize a HoloMap instance with optional initial data and configuration
Parameters:
initial_items: Initial data items to populate the HoloMapkdims: Key dimensions defining the indexing structuregroup: Group identifier for organizationlabel: Label for display and identificationparams: Additional configuration parameters
Returns: None (constructor)
@property opts(self)
property
Purpose: Returns an Opts accessor for applying options in holomap mode
Returns: Opts object configured for holomap mode
overlay(self, dimensions=None, **kwargs) -> NdOverlay
Purpose: Group data by supplied dimension(s) and overlay each group into NdOverlay objects
Parameters:
dimensions: Dimension(s) to group by for overlayingkwargs: Additional keyword arguments passed to groupby or NdOverlay
Returns: NdOverlay object(s) with elements overlaid along the specified dimensions
grid(self, dimensions=None, **kwargs) -> GridSpace
Purpose: Group data by supplied dimension(s) and lay out groups in a grid structure
Parameters:
dimensions: Dimension(s) to group by for grid layoutkwargs: Additional keyword arguments passed to groupby or GridSpace
Returns: GridSpace with elements arranged in a grid along specified dimensions
layout(self, dimensions=None, **kwargs) -> NdLayout
Purpose: Group data by supplied dimension(s) and create an NdLayout arrangement
Parameters:
dimensions: Dimension(s) to group by for layoutkwargs: Additional keyword arguments passed to groupby or NdLayout
Returns: NdLayout with elements arranged along specified dimensions
options(self, *args, **kwargs) -> HoloMap
Purpose: Apply simplified option definitions to all elements in the HoloMap, returning a new object
Parameters:
args: Sets of options in various formats (Options objects, type specs, or dictionaries)backend: Backend to apply options to (defaults to current selected backend)clone: Whether to clone the object (default True); False applies options in-placekwargs: Keyword options to apply to elements
Returns: Cloned HoloMap with options applied to all contained elements
_split_overlays(self) -> tuple
Purpose: Internal method to split overlays inside the HoloMap into a list of HoloMaps
Returns: Tuple of (keys, maps) where keys are overlay keys and maps are corresponding HoloMaps
_dimension_keys(self) -> list
Purpose: Internal helper for __mul__ that returns keys with dimension labels
Returns: List of tuples pairing dimension names with key values
_dynamic_mul(self, dimensions, other, keys) -> DynamicMap
Purpose: Internal method implementing dynamic overlaying of DynamicMaps and HoloMaps
Parameters:
dimensions: Merged dimensions for the resultother: Other object to overlay withkeys: Keys for the overlay operation
Returns: DynamicMap that dynamically overlays elements from both objects
__mul__(self, other, reverse=False) -> HoloMap | DynamicMap
Purpose: Overlay items in the HoloMap with another object using the * operator
Parameters:
other: Object to overlay with (HoloMap, ViewableElement, or compatible type)reverse: Whether to reverse the overlay order
Returns: New HoloMap or DynamicMap with overlaid elements
__lshift__(self, other) -> AdjointLayout
Purpose: Adjoin another object to this HoloMap using the << operator
Parameters:
other: Object to adjoin (ViewableElement, UniformNdMapping, Empty, or AdjointLayout)
Returns: AdjointLayout containing this HoloMap and the adjoined object
collate(self, merge_type=None, drop=[], drop_constant=False) -> HoloMap | Layout
Purpose: Reorder and merge nested containers by collapsing dimensions
Parameters:
merge_type: Type of object to merge into (defaults to HoloMap)drop: List of dimensions to drop during collationdrop_constant: Whether to automatically drop constant dimensions
Returns: Collated Layout or HoloMap with restructured nesting
decollate(self) -> DynamicMap
Purpose: Pack a HoloMap of DynamicMaps into a single DynamicMap that returns a HoloMap
Returns: DynamicMap with lifted streams that returns HoloMap of non-dynamic elements
relabel(self, label=None, group=None, depth=1) -> HoloMap
Purpose: Clone the HoloMap and apply new group and/or label to specified depth
Parameters:
label: New label to applygroup: New group to applydepth: Depth to which relabeling is applied to nested objects
Returns: Relabeled clone of the HoloMap
hist(self, dimension=None, num_bins=20, bin_range=None, adjoin=True, individually=True, **kwargs) -> AdjointLayout | HoloMap | Layout
Purpose: Compute and optionally adjoin histograms along specified dimension(s)
Parameters:
dimension: Dimension(s) to compute histogram on (defaults to first value dimension)num_bins: Number of bins for the histogrambin_range: Tuple of (lower, upper) bounds for binsadjoin: Whether to adjoin histogram to original HoloMapindividually: Whether to compute histogram ranges individually per elementkwargs: Additional arguments like 'index' for overlay selection
Returns: AdjointLayout of HoloMap and histograms if adjoin=True, otherwise just histograms as HoloMap or Layout
Attributes
| Name | Type | Description | Scope |
|---|---|---|---|
data_type |
tuple | Class variable defining allowed data types that can be stored in the HoloMap: (ViewableElement, NdMapping, Layout) | class |
kdims |
list[Dimension] | Key dimensions that define the indexing structure and parameter space of the HoloMap | instance |
data |
OrderedDict | Internal storage for the mapping of keys to viewable elements (inherited from UniformNdMapping) | instance |
group |
str | Group identifier for organizing related HoloMaps | instance |
label |
str | Label for display and identification of the HoloMap instance | instance |
ndims |
int | Number of key dimensions (inherited property from parent classes) | instance |
type |
type | Type of elements stored in the HoloMap (inherited from UniformNdMapping) | instance |
Dependencies
numpyparamitertoolsfunctoolscollectionscontextlibtypesnumbersinspect
Required Imports
import numpy as np
import param
from itertools import groupby
from functools import partial
from collections import defaultdict, OrderedDict
from contextlib import contextmanager
from types import FunctionType
from numbers import Number
Conditional/Optional Imports
These imports are only needed under specific conditions:
from inspect import FullArgSpec
Condition: Python 3.x
Required (conditional)from inspect import ArgSpec as FullArgSpec
Condition: Python 2.x fallback
OptionalUsage Example
import holoviews as hv
from holoviews import HoloMap, Curve
import numpy as np
# Create data for different time points
data = {}
for i in range(5):
xs = np.linspace(0, 10, 100)
ys = np.sin(xs + i)
data[i] = Curve((xs, ys))
# Create HoloMap with time dimension
holomap = HoloMap(data, kdims=['time'])
# Overlay all elements
overlaid = holomap.overlay()
# Create grid layout
grid = holomap.grid()
# Apply options
styled = holomap.options(color='red', line_width=2)
# Compute histogram
hist_layout = holomap.hist(dimension='y', adjoin=True)
# Relabel
relabeled = holomap.relabel(label='Sine Waves', group='Timeseries')
Best Practices
- Always define kdims when creating a HoloMap to ensure proper indexing and widget generation
- Use consistent key tuple lengths matching the number of key dimensions
- When overlaying HoloMaps, ensure dimension compatibility - one set of dimensions should be a subset of the other
- Use clone=False in options() method only when you're certain you don't need the original object
- For large datasets, consider using DynamicMap instead of HoloMap to avoid memory issues
- When using collate(), be aware it restructures nested containers and may change the navigation structure
- Use overlay() for combining elements along dimensions, grid() for spatial layouts, and layout() for flexible arrangements
- The hist() method with adjoin=True creates side-by-side layouts; use adjoin=False to get just the histograms
- When multiplying HoloMaps with *, ensure dimensional compatibility to avoid exceptions
- Store the result of operations like overlay(), grid(), and layout() as they return new objects rather than modifying in place
Tags
Similar Components
AI-powered semantic similarity - components with related functionality:
-
class DynamicMap 70.1% similar
-
class GridSpace 59.4% similar
-
function layer_sort 57.9% similar
-
class GridMatrix 55.4% similar
-
class Config_v4 55.2% similar