Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
52 changes: 34 additions & 18 deletions docs/javascript/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

The JavaScript component of Celldega is used within the Jupyter Widgets framework to provide interactive visualization in the context of a Jupyter notebook but can also be used as a standalone JavaScript library.


## `landscape_ist` API Documentation

The `landscape_ist` function initializes and renders an interactive spatial transcriptomics (IST) landscape visualization. This API is designed to work with Deck.gl and includes customizable visualization options, dynamic data updates, and UI interactions.
Expand Down Expand Up @@ -32,9 +31,11 @@ The `landscape_ist` function returns an object (`landscape`) with several method
Updates the visualization to highlight data for a specific gene.

##### Parameters

- **`inst_gene`** (`string`): The gene to highlight.

##### Behavior

- Updates the transcript layer to show data for the specified gene.
- Scrolls the bar graph to bring the selected gene into view.
- Toggles visibility of image layers and controls based on the selected gene.
Expand All @@ -46,9 +47,11 @@ Updates the visualization to highlight data for a specific gene.
Updates the visualization to highlight data for a specific column (e.g., cluster).

##### Parameters

- **`inst_col`** (`string`): The column to highlight.

##### Behavior

- Highlights the bar graph corresponding to the selected column.
- Updates cell and path layers to reflect the selected column.
- Toggles visibility of layers based on the column selection.
Expand All @@ -60,9 +63,11 @@ Updates the visualization to highlight data for a specific column (e.g., cluster
Updates the visualization based on a dendrogram selection of columns.

##### Parameters

- **`selected_cols`** (`Array<string>`): The list of selected column names.

##### Behavior

- Highlights the selected columns in the bar graph.
- Updates layers to reflect the selection.

Expand All @@ -73,11 +78,13 @@ Updates the visualization based on a dendrogram selection of columns.
Updates the view state of the Deck.gl visualization.

##### Parameters

- **`new_view_state`** (`Object`): The new view state configuration.
- **`close_up`** (`boolean`): Whether the view should zoom in closely.
- **`trx_layer`** (`Object`): The transcript layer to update.

##### Behavior

- Adjusts the viewport and reconfigures layers based on the new view state.

---
Expand All @@ -87,6 +94,7 @@ Updates the view state of the Deck.gl visualization.
Updates all visualization layers.

##### Behavior

- Refreshes the Deck.gl layers with the current visualization state.

---
Expand All @@ -96,6 +104,7 @@ Updates all visualization layers.
Finalizes the Deck.gl instance and cleans up resources.

##### Behavior

- Disposes of all Deck.gl resources and event listeners to prevent memory leaks.

---
Expand Down Expand Up @@ -155,26 +164,29 @@ The `matrix_viz` function initializes and renders a matrix visualization. This A
### Internal Behavior

The function performs the following setup:

1. **Deck.gl Integration**:

- Initializes a Deck.gl instance for the matrix visualization.
- Sets properties for interactivity, including tooltips, view state changes, and layer filtering.

2. **Matrix Data Setup**:

- Parses and structures the matrix data from the `network` object.
- Configures labels, categories, and dendrograms for both rows and columns.
- Configures labels, attributes, and dendrograms for both rows and columns.

3. **Layer Initialization**:

- Creates layers for:
- Matrix cells.
- Row and column labels.
- Row and column categories.
- Row and column attributes.
- Row and column dendrograms.
- Attaches interactions (e.g., click events) to these layers.

4. **UI Setup**:
- Creates a container for the visualization and appends it to the root DOM element.


---

### Example Usage
Expand All @@ -183,31 +195,35 @@ The function performs the following setup:
import { matrix_viz } from 'path/to/matrix_viz';

const rootElement = document.getElementById('matrix-container');
const model = { /* Model containing visualization data */ };
const network = { /* Network object representing the matrix data */ };
const model = {
/* Model containing visualization data */
};
const network = {
/* Network object representing the matrix data */
};

// Callback functions
const rowLabelCallback = (row) => {
console.log('Row label clicked:', row);
console.log('Row label clicked:', row);
};

const colLabelCallback = (col) => {
console.log('Column label clicked:', col);
console.log('Column label clicked:', col);
};

const colDendroCallback = (dendro) => {
console.log('Column dendrogram clicked:', dendro);
console.log('Column dendrogram clicked:', dendro);
};

// Initialize the matrix visualization
await matrix_viz(
model,
rootElement,
network,
800,
800,
rowLabelCallback,
colLabelCallback,
colDendroCallback
model,
rootElement,
network,
800,
800,
rowLabelCallback,
colLabelCallback,
colDendroCallback
);
```
```
59 changes: 59 additions & 0 deletions js/deck-gl/matrix/attr_label_layers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import * as d3 from 'd3';
import { TextLayer } from 'deck.gl';

export const ini_row_attr_label_layer = (viz_state) => {
const transitions = {
getPosition: { duration: viz_state.animate.duration, easing: d3.easeCubic },
};

const layer = new TextLayer({
id: 'row-attr-label-layer',
data: viz_state.cats.row_attr_label_data,
getPosition: (d) => [
viz_state.viz.row_cat_offset * (d.index + 0.5) +
20 +
viz_state.viz.cat_shift_row,
10,
],
getText: (d) => d.name,
getSize: 12,
getColor: [0, 0, 0],
getTextAnchor: 'start',
getAlignmentBaseline: 'bottom',
fontFamily: 'Arial',
sizeUnits: 'pixels',
sizeScale: 1,
pickable: false,
transitions,
});

return layer;
};

export const ini_col_attr_label_layer = (viz_state) => {
const transitions = {
getPosition: { duration: viz_state.animate.duration, easing: d3.easeCubic },
};

const layer = new TextLayer({
id: 'col-attr-label-layer',
data: viz_state.cats.col_attr_label_data,
getPosition: (d) => [
10,
viz_state.viz.col_cat_offset * (d.index + 0.5) +
viz_state.viz.cat_shift_col,
],
getText: (d) => d.name,
getSize: 12,
getColor: [0, 0, 0],
getTextAnchor: 'start',
getAlignmentBaseline: 'middle',
fontFamily: 'Arial',
sizeUnits: 'pixels',
sizeScale: 1,
pickable: false,
transitions,
});

return layer;
};
6 changes: 6 additions & 0 deletions js/deck-gl/matrix/matrix_layers.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ export const get_mat_layers_list = (layers_mat) => {
layers_mat.mat_layer,
layers_mat.row_cat_layer,
layers_mat.col_cat_layer,
layers_mat.row_attr_label_layer,
layers_mat.col_attr_label_layer,
layers_mat.row_label_layer,
layers_mat.col_label_layer,
layers_mat.row_dendro_layer,
Expand All @@ -21,8 +23,12 @@ export const layer_filter = ({ layer, viewport }) => {
return true;
} else if (viewport.id === 'rows' && layer.id.includes('row-label-layer')) {
return true;
} else if (viewport.id === 'rows' && layer.id === 'row-attr-label-layer') {
return true;
} else if (viewport.id === 'cols' && layer.id === 'col-label-layer') {
return true;
} else if (viewport.id === 'cols' && layer.id === 'col-attr-label-layer') {
return true;
} else if (
(viewport.id === 'dendro_rows') &
(layer.id === 'row-dendro-layer')
Expand Down
32 changes: 32 additions & 0 deletions js/matrix/attr_label_data.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
export const set_attr_label_data = (network, viz_state, axis) => {
const isRow = axis === 'row';
const nodes = isRow ? network.row_nodes : network.col_nodes;
const numAttrs = isRow
? viz_state.cats.num_cats.row
: viz_state.cats.num_cats.col;

const titles = [];
for (let i = 0; i < numAttrs; i++) {
const catName = `cat-${i}`;
let example = nodes.find((n) => n[catName]);
let title = `attr-${i}`;
if (example) {
const val = example[catName];
if (typeof val === 'string' && val.includes(':')) {
title = val.split(':')[0];
}
}
titles.push({ name: title, index: i });
}

if (!viz_state.cats.attr_titles) viz_state.cats.attr_titles = {};
viz_state.cats.attr_titles[axis] = titles.map((d) => d.name);

return titles;
};

export const set_row_attr_label_data = (network, viz_state) =>
set_attr_label_data(network, viz_state, 'row');

export const set_col_attr_label_data = (network, viz_state) =>
set_attr_label_data(network, viz_state, 'col');
15 changes: 15 additions & 0 deletions js/matrix/set_constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,21 @@ export const set_mat_constants = (
viz_state.cats.num_cats.row +
viz_state.viz.row_label;

// reduce matrix size to make room for attribute bars
viz_state.viz.mat_width =
width -
viz_state.viz.row_region -
viz_state.viz.dendrogram_width -
viz_state.viz.label_buffer;
viz_state.viz.mat_height =
height -
viz_state.viz.col_region -
viz_state.viz.dendrogram_width -
viz_state.viz.label_buffer;

viz_state.viz.mat_width = Math.max(20, viz_state.viz.mat_width);
viz_state.viz.mat_height = Math.max(20, viz_state.viz.mat_height);

viz_state.viz.col_width = viz_state.viz.mat_width / viz_state.mat.num_cols;
viz_state.viz.row_offset = viz_state.viz.mat_height / viz_state.mat.num_rows;
viz_state.viz.col_offset = viz_state.viz.mat_width / viz_state.mat.num_cols;
Expand Down
20 changes: 19 additions & 1 deletion js/viz/matrix_viz.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ import {
ini_row_cat_layer,
ini_col_cat_layer,
} from '../deck-gl/matrix/cat_layers';
import {
ini_row_attr_label_layer,
ini_col_attr_label_layer,
} from '../deck-gl/matrix/attr_label_layers';
import { ini_deck } from '../deck-gl/matrix/deck_mat';
import {
ini_dendro_layer,
Expand All @@ -53,6 +57,10 @@ import { on_view_state_change } from '../deck-gl/matrix/on_view_state_change';
import { ini_views, ini_view_state } from '../deck-gl/matrix/views';
import { ini_zoom_data } from '../deck-gl/matrix/zoom';
import { set_row_cat_data, set_col_cat_data } from '../matrix/cat_data';
import {
set_row_attr_label_data,
set_col_attr_label_data,
} from '../matrix/attr_label_data';
import { calc_dendro_polygons, ini_dendro } from '../matrix/dendro';
import { set_row_label_data, set_col_label_data } from '../matrix/label_data';
import { set_mat_data } from '../matrix/mat_data';
Expand All @@ -69,7 +77,6 @@ export const matrix_viz = async (
col_label_callback = null,
col_dendro_callback = null
) => {

const root = document.createElement('div');
root.style.border = '1px solid #d3d3d3';
// root.style.width = width
Expand Down Expand Up @@ -102,6 +109,15 @@ export const matrix_viz = async (
set_row_label_data(network, viz_state);
set_col_label_data(network, viz_state);

viz_state.cats.row_attr_label_data = set_row_attr_label_data(
network,
viz_state
);
viz_state.cats.col_attr_label_data = set_col_attr_label_data(
network,
viz_state
);

viz_state.cats.row_cat_data = set_row_cat_data(network, viz_state);
viz_state.cats.col_cat_data = set_col_cat_data(network, viz_state);

Expand All @@ -115,6 +131,8 @@ export const matrix_viz = async (
layers_mat.mat_layer = ini_mat_layer(viz_state);
layers_mat.row_label_layer = ini_row_label_layer(viz_state);
layers_mat.col_label_layer = ini_col_label_layer(viz_state);
layers_mat.row_attr_label_layer = ini_row_attr_label_layer(viz_state);
layers_mat.col_attr_label_layer = ini_col_attr_label_layer(viz_state);
layers_mat.row_cat_layer = ini_row_cat_layer(viz_state);
layers_mat.col_cat_layer = ini_col_cat_layer(viz_state);
layers_mat.row_dendro_layer = ini_dendro_layer(layers_mat, viz_state, 'row');
Expand Down
Loading