Widget plugins
Vitessce supports multiple types of plugins defined using JavaScript code.
Leveraging concepts from anywidget, we can define such plugins directly from Python: plugin developers can supply custom JavaScript code via a Python string.
The most minimal example of such plugin JavaScript code is the following:
PLUGIN_ESM = """
function createPlugins(utilsForPlugins) {
const {
React,
PluginFileType,
PluginViewType,
PluginCoordinationType,
PluginJointFileType,
z,
useCoordination,
} = utilsForPlugins;
return {
pluginViewTypes: undefined,
pluginFileTypes: undefined,
pluginCoordinationTypes: undefined,
pluginJointFileTypes: undefined,
};
}
export default { createPlugins };
"""
The plugin string must be defined as an EcmaScript Module (ESM) that exports a function named createPlugins
.
The createPlugins
function is called (on the initial render of the Jupyter widget) with the utilsForPlugins
argument (to facilitate dependency injection) and returns an object with the following properties:
pluginViewTypes
: an array of objects that define the view types of the plugin.pluginFileTypes`
: an array of objects that define the file types of the plugin.pluginCoordinationTypes
: an array of objects that define the coordination types of the plugin.pluginJointFileTypes
: an array of objects that define the joint file types of the plugin.
If defined, these plugin arrays are passed to the Vitessce component as props with the same names.
Note: For maximum stability of plugins, we recommend that plugin developers document which version(s) of the vitessce Python package that plugins have been developed under.
Passing plugin ESM to the widget
The plugin string can be passed to the widget using the plugins
parameter and passing a subclass of VitesscePlugin
:
from vitessce import VitessceConfig, VitesscePlugin
class MyPlugin(VitesscePlugin):
plugin_esm = PLUGIN_ESM
vc = VitessceConfig(description="A Vitessce widget with a custom plugin")
# Some more configuration here...
plugin = MyPlugin()
vc.widget(plugins=[plugin])
Defining plugin views using JSX
Vitessce plugin view types are defined as React components. During typical React component development, JSX syntax is used. However, JSX is not valid JavaScript and therefore must be transformed to valid JavaScript before it can be passed to the widget where it will be interpreted as ESM. Vitessce plugin developers then have two options for defining React components for plugin view types:
Use
React.createElement
directly (without JSX).Use the
transform
function from esbuild_py to perform JSX to JS transformation.
from esbuild_py import transform
PLUGIN_ESM = transform("""
function createPlugins(utilsForPlugins) {
const {
React,
PluginFileType,
PluginViewType,
PluginCoordinationType,
PluginJointFileType,
z,
useCoordination,
} = utilsForPlugins;
function MyPluginView(props) {
return (
<p>Hello world from JSX!</p>
);
}
const pluginViewTypes = [
new PluginViewType('myPlugin', MyPluginView, []),
];
return { pluginViewTypes };
}
export default { createPlugins };
""")
To import additional dependencies, JavaScript (more specifically, ESM) can be dynamically imported from CDN (such as unpkg
or esm.sh
) within the createPlugins
function:
PLUGIN_ESM = """
async function createPlugins(utilsForPlugins) {
const {
React,
PluginFileType,
PluginViewType,
PluginCoordinationType,
PluginJointFileType,
z,
useCoordination,
} = utilsForPlugins;
const d3 = await import('https://cdn.jsdelivr.net/npm/d3@7/+esm');
// Do something with d3 here...
return {
pluginViewTypes: undefined,
pluginFileTypes: undefined,
pluginCoordinationTypes: undefined,
pluginJointFileTypes: undefined,
};
}
export default { createPlugins };
"""
To support more complex import scenarios, see dynamic-importmap.
vitessce.widget_plugins
- class vitessce.widget_plugins.demo_plugin.DemoPlugin[source]
Example of a minimal plugin view that gets the obsType coordination value from the coordination space and renders a button. This plugin view is not meant to be useful for end-users, but rather to demonstrate how to develop a plugin view that uses coordination (and uses eslint_py for JSX transformation).
from vitessce.widget_plugins import DemoPlugin # ... vc.widget(plugins=[DemoPlugin()])
- class vitessce.widget_plugins.spatial_query.SpatialQueryPlugin(adata, spatial_key='X_spatial', label_key='cell_type')[source]
Spatial-Query plugin view renders controls to change parameters passed to the Spatial-Query methods.
Construct a new Vitessce widget.
- Parameters
adata (anndata.AnnData) – AnnData.
spatial_key (str) – The key in adata.obsm that contains the (x, y) coordinates of each cell. By default, “X_spatial”.
label_key (str) – The column in adata.obs that contains the cell type labels. By default, “cell_type”.
from vitessce.widget_plugins import SpatialQueryPlugin plugin = SpatialQueryPlugin(adata, spatial_key="X_spatial", label_key="cell_type") # ... vc.widget(plugins=[plugin], remount_on_uid_change=False)