### Run Built-in Example Source: https://redhog.github.io/gladly/docs/docs/Quickstart Install dependencies and start the development server to view the built-in Gladly demo. ```bash npm install npm start ``` -------------------------------- ### Install Dependencies Source: https://redhog.github.io/gladly/docs Use this command to install project dependencies. ```bash npm install ``` -------------------------------- ### Install Dependencies from Source Source: https://redhog.github.io/gladly/docs/docs/Quickstart When building from source, install the required dependencies like regl and d3. ```bash npm install regl d3 ``` -------------------------------- ### Complete Plot Configuration Example Source: https://redhog.github.io/gladly/docs/docs/configuration/PlotConfiguration Demonstrates a full HTML page setup for creating a scatter plot with custom data and axis ranges. Ensure the Plotly.js library and necessary layer modules are imported. ```html
``` -------------------------------- ### Install Gladly from npm Source: https://redhog.github.io/gladly/docs/docs/Quickstart Install the Gladly plotting library using npm for use in Node.js projects or with bundlers. ```bash npm install gladly-plot ``` -------------------------------- ### Points Layer Example (Simple Flat Format) Source: https://redhog.github.io/gladly/docs/docs/configuration/BuiltInLayerTypes Example of using the points layer with a simple flat data format. It maps 'x' and 'y' for coordinates and 'temperature' for color, with a specified colorscale for the temperature axis. ```javascript plot.update({ data: { x, y, temperature }, config: { layers: [ { points: { xData: "x", yData: "y", vData: "temperature" } } ], axes: { temperature: { min: 0, max: 100, colorscale: "plasma" } } } }) ``` -------------------------------- ### Install Gladly via CDN Source: https://redhog.github.io/gladly/docs/docs/Quickstart Include the pre-built standalone bundle directly in your HTML using a script tag. No build step or npm is required. ```html ``` -------------------------------- ### WeightedAverageComputation Example Source: https://redhog.github.io/gladly/docs/docs/extension-api/Computations Example implementation of a custom texture computation for weighted average, demonstrating the use of `compute` and `schema` methods. ```APIDOC ## WeightedAverageComputation ### Description An example implementation of a `TextureComputation` that calculates a weighted average. It demonstrates how to access `ArrayColumn` data, perform calculations, and upload results to a texture. ### Methods #### compute(regl, inputs, getAxisDomain) ##### Description Calculates the weighted average of values binned according to the `bins` parameter. ##### Parameters - **regl** (regl context) - Required - The regl rendering context. - **inputs** (object) - Required - Contains `values` (ArrayColumn), `weights` (ArrayColumn), and `bins` (number). - **getAxisDomain** (`(axisId: string) => [min|null, max|null] | null`) - Required - Function to get axis domains. ##### Return value A regl texture containing the computed weighted averages for each bin. #### schema(data) ##### Description Defines the schema for the `weightedAverage` computation parameters. ##### Return value A JSON schema object specifying `values`, `weights`, and `bins` as required properties. ``` -------------------------------- ### Points Layer Example (Columnar Format with Quantity Kinds) Source: https://redhog.github.io/gladly/docs/docs/configuration/BuiltInLayerTypes Example demonstrating the points layer with columnar data format and quantity kinds. The axis key in `config.axes` uses the resolved quantity kind (e.g., 'temperature_K') instead of the raw column name. ```javascript plot.update({ data: { data: { x, y, temperature }, quantity_kinds: { x: "distance_m", y: "voltage_V", temperature: "temperature_K" } }, config: { layers: [ { points: { xData: "x", yData: "y", vData: "temperature" } } ], axes: { // key is the resolved quantity kind, not the column name "temperature" temperature_K: { min: 0, max: 100, colorscale: "plasma" } } } }) ``` -------------------------------- ### Minimal Gladly Plot Example Source: https://redhog.github.io/gladly/docs/docs/Quickstart Create a basic Gladly plot by preparing data as Float32Arrays, initializing the Plot, and updating it with configuration and data. ```javascript import { Plot, pointsLayerType } from 'gladly-plot' // 1. Register layer types once at startup // pointsLayerType is auto-registered on import — no manual registerLayerType call needed // 2. Prepare data as Float32Arrays const x = new Float32Array([10, 20, 30, 40, 50]) const y = new Float32Array([15, 25, 35, 25, 45]) const v = new Float32Array([0.2, 0.4, 0.6, 0.8, 1.0]) // 3. Create plot const plot = new Plot(document.getElementById("plot-container")) // 4. Apply configuration and data plot.update({ data: { x, y, v }, config: { layers: [ { points: { xData: "x", yData: "y", vData: "v" } } ], axes: { xaxis_bottom: { min: 0, max: 60 }, yaxis_left: { min: 0, max: 50 } } } }) ``` -------------------------------- ### Import Gladly from npm Source: https://redhog.github.io/gladly/docs/docs/Quickstart Import necessary components like Plot and layer types when using Gladly installed via npm. ```javascript import { Plot, pointsLayerType } from 'gladly-plot' ``` -------------------------------- ### Usage in createLayer Source: https://redhog.github.io/gladly/docs/docs/extension-api/Computations Example of how to use a registered texture computation within the `createLayer` function's attributes. ```javascript attributes: { count: { weightedAverage: { values: 'normalized', weights: 'importance', bins: 50 } } } ``` -------------------------------- ### Install Gladly via ES Module CDN Source: https://redhog.github.io/gladly/docs/docs/Quickstart Use the ES module build with an import map or a script tag of type "module" for modern JavaScript projects. ```html ``` -------------------------------- ### Quick Start: Enable Lasso Selection Source: https://redhog.github.io/gladly/docs/docs/configuration/Selection Initializes a plot and updates it with data and configuration, enabling lasso selection by default. Ensure 'myData' is defined and the container element exists. ```javascript import { Plot } from 'gladly' const plot = new Plot(container) await plot.update({ data: myData, config: { layers: [ { points: { xData: 'input.x', yData: 'input.y', color: 'input.value', selection: 'brush1' // opt this layer into a named selection channel } } ], interactions: { lasso: true } // shift-drag to draw a lasso over any selection } }) ``` -------------------------------- ### Create Layer with 2D Column Source: https://redhog.github.io/gladly/docs/docs/extension-api/Computations Example of creating a layer attribute backed by a 2D column using ArrayColumn. This sets up the data structure for shader access. ```javascript const weightsCol = new ArrayColumn(myFloat32Array, { shape: [rows, cols] }) return [{ attributes: { weights: weightsCol }, ... }] ``` -------------------------------- ### WebGL 2.0 Context Setup Shims Source: https://redhog.github.io/gladly/docs/docs/architecture/Modules Compatibility shims for regl to use WebGL 2.0 features, specifically for `gl.getExtension` and `gl.texImage2D` to handle float textures and ANGLE extensions. ```javascript gl.getExtension("OES_texture_float") gl.getExtension("OES_texture_float_linear") gl.getExtension("ANGLE_instanced_arrays") ``` ```javascript gl.texImage2D(target, level, internalformat, width, height, border, format, type, pixels) ``` -------------------------------- ### Subscribe to Selection Changes Source: https://redhog.github.io/gladly/docs/docs/user-api/Selection Subscribe to selection changes to receive updates on selected points. This example logs the number of selected points per tile when a lasso is drawn and points are selected. ```javascript plot.selections['brush1'].subscribe(sel => { const arrays = sel.arrays // Float32Array[] | null if (arrays) { arrays.forEach((tileArr, t) => { const indices = [...tileArr.keys()].filter(i => tileArr[i] > 0.5) console.log(`tile ${t}: ${indices.length} points selected`) }) } }) ``` -------------------------------- ### Filter Axis Range Examples Source: https://redhog.github.io/gladly/docs/docs/concepts/Overview Demonstrates different ways to define filter axis ranges, including open and closed intervals. Bounds are optional. ```javascript { min: 10 } // discards values below 10, no upper limit ``` ```javascript { max: 500 } // discards values above 500, no lower limit ``` ```javascript { min: 10, max: 500 } // closed interval ``` -------------------------------- ### GLSL Filter Integration Example Source: https://redhog.github.io/gladly/docs/docs/extension-api/LayerTypes Demonstrates how to use the `filter_in_range` function in GLSL to discard vertices that do not meet the filter criteria. The `filter_range` uniform and `filter_data` input are used for this check. ```glsl // Using suffix '' — GLSL uniform name is: filter_range uniform vec4 filter_range; in float filter_data; void main() { if (!filter_in_range(filter_range, filter_data)) { gl_Position = vec4(2.0, 2.0, 2.0, 1.0); // vertex shader discard return; } // ... } ``` -------------------------------- ### Attribute Value Examples Source: https://redhog.github.io/gladly/docs/docs/concepts/Overview Illustrates different types of values that can be assigned to attributes. Column names are resolved to ColumnData at draw time, while computed expressions are resolved during command build time. ```javascript // Attribute values — column name string, ColumnData, or computed expression attributes: { x: 'survey1.x', // column name → resolved to ColumnData at draw time count: { histogram: { input: 'input.v', bins: 50 } } // computed expression } ``` -------------------------------- ### Get All Column Names Source: https://redhog.github.io/gladly/docs/docs/user-api/ComputePipeline Use `output.columns()` to retrieve an array of all available column names, including input data and transform outputs. Column names use dot notation. ```javascript output.columns() // ['input.depth', 'input.vp', 'hist.counts', 'hist.binCenters', ...] ``` -------------------------------- ### Vertex Shader Call to Sample 2D Column Source: https://redhog.github.io/gladly/docs/docs/extension-api/Computations Example of how to call the injected sampling function within the vertex shader's main function to access the 'weights' attribute. ```glsl void main() { float w = sample_weights(ivec2(row, col)); // ... } ``` -------------------------------- ### Expression Types for Parameters Source: https://redhog.github.io/gladly/docs/docs/configuration/BuiltInLayerTypes Examples of how to specify expressions for parameters. Expressions can be plain data column names, computed attributes, or transform outputs. This allows for flexible data binding and computation. ```javascript xData: "temperature" ``` ```javascript xData: { histogram: { input: "raw_data", bins: 50 } } ``` ```javascript xData: "histogram.binCenters" ``` -------------------------------- ### Constructor Source: https://redhog.github.io/gladly/docs/docs/user-api/ComputePipeline Initializes a new ComputePipeline instance. The WebGL context is created immediately upon construction. ```APIDOC ## Constructor ```javascript new ComputePipeline() ``` No arguments. The WebGL context is created immediately in the constructor. ``` -------------------------------- ### Get Colorscale Index Source: https://redhog.github.io/gladly/docs/docs/architecture/Modules Returns the integer colorscale index used as a GLSL uniform. Implemented in AxisRegistry.js. ```javascript getColorscaleIndex(qk) ``` -------------------------------- ### Run Test Suite Source: https://redhog.github.io/gladly/docs Execute the test suite to verify functionality. This launches a real Chromium browser via Playwright. ```bash npm test ``` -------------------------------- ### Instantiate ComputePipeline Source: https://redhog.github.io/gladly/docs/docs/user-api/ComputePipeline Creates a new ComputePipeline instance. The WebGL context is created immediately upon construction. No arguments are required. ```javascript new ComputePipeline() ``` -------------------------------- ### Get Registered Axis Quantity Kinds Source: https://redhog.github.io/gladly/docs/docs/architecture/Modules Returns an array of all registered quantity kind names. Used to iterate over available axis types. ```javascript getRegisteredAxisQuantityKinds() ``` -------------------------------- ### Update Plot with Lines Layer Source: https://redhog.github.io/gladly/docs/docs/configuration/BuiltInLayerTypes Example of updating a plot with data and configuration, including the lines layer with specified data mappings and axis configurations. ```javascript plot.update({ data: { x, y, temperature }, config: { layers: [ { lines: { xData: "x", yData: "y", vData: "temperature", lineColorMode: "gradient" } } ], axes: { temperature: { min: 0, max: 100, colorscale: "plasma" } } }) } ``` -------------------------------- ### Import Gladly from Source Source: https://redhog.github.io/gladly/docs/docs/Quickstart Import Gladly components when working directly with the source code. ```javascript import { Plot, pointsLayerType } from './src/index.js' ``` -------------------------------- ### Configure Tile Layer with XYZ Source Source: https://redhog.github.io/gladly/docs/docs/configuration/BuiltInLayerTypes Configure a tile layer to display geographic maps using XYZ tile services. The 'url' parameter should be a template for tile URLs. ```javascript { tile: { source: { xyz: { url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" } }, tileCrs: "EPSG:3857" } } ``` -------------------------------- ### Get Quantity Kind Source: https://redhog.github.io/gladly/docs/docs/user-api/Data Retrieves the quantity kind string for a column, falling back to the column name if none is specified. Used for axis identity. ```javascript const qk = d.getQuantityKind(params.vData) ?? params.vData ``` -------------------------------- ### Render Cycle Overview Source: https://redhog.github.io/gladly/docs/docs/architecture/DataFlow This diagram outlines the main steps in the per-frame rendering process, from clearing the canvas to executing post-render callbacks. ```mermaid plot.render() │ ├─> regl.clear({ color: [1, 1, 1, 1] }) — white background │ ├─> Refresh axis-reactive column data: │ └─> For each ColumnData in layer._dataColumns (populated during createDrawCommand): │ └─> col.refresh(plot) │ └─> If any tracked axis domain changed: recompute texture in-place │ (dynamic uniform fn () => ref.texture picks up new texture automatically) │ ├─> For each (layer, drawCommand): │ │ │ ├─> Collect runtimeProps: │ │ ├─> xDomain ← axisRegistry.scales[layer.xAxis].domain() │ │ ├─> yDomain ← axisRegistry.scales[layer.yAxis].domain() │ │ ├─> viewport ← { x:0, y:0, width, height } │ │ ├─> count ← layer.vertexCount ?? layer.attributes.x.length │ │ ├─> Per color slot: │ │ │ colorscale_ ← axisRegistry.getColorscaleIndex(quantityKind) │ │ │ color_range_ ← axisRegistry color range for quantityKind │ │ └─> Per filter slot: │ │ filter_range_ ← axisRegistry.getRangeUniform(quantityKind) │ │ → vec4 [min, max, hasMin, hasMax] │ │ │ └─> drawCommand(runtimeProps) │ │ │ ├─> For t in 0 .. N-1 (N = tile count; N=1 for non-tiled layers): │ │ ├─> Resolve per-tile texture uniforms: u_col_ ← fn[t]() │ │ ├─> Override per-tile buffer attrs (tileBufferOverrides[t]) + a_pickId for tile t │ │ ├─> Set count = tileCounts[t] (if buffer-tiled) or runtimeProps.count │ │ └─> Compiled regl command(tileProps) — one GPU draw call │ │ │ │ │ └─> GPU execution (no clear between tiles — geometry accumulates): │ │ ├─> Vertex shader (once per data point in this tile): │ │ │ ├─> Read attribute values (x, y, v, z, …) │ │ │ ├─> Optionally: filter_in_range() → move to clip discard position │ │ │ ├─> Normalise to clip space using xDomain / yDomain │ │ │ └─> Write gl_Position, gl_PointSize, varyings │ │ │ │ │ └─> Fragment shader (once per rasterised pixel): │ │ ├─> Optionally: discard via filter_in_range() │ │ ├─> map_color() → look up colorscale, normalise value → RGBA │ │ └─> Write fragColor (out vec4) │ │ │ └─> (end tile loop) │ ├─> plot.renderAxes() │ └─> For each axis in AxisRegistry: │ ├─> Create D3 axis generator (axisBottom / axisTop / axisLeft / axisRight) │ ├─> Select or create SVG element, position with transform │ ├─> Call generator → draws ticks and tick labels │ └─> Add unit label │ └─> Fire all callbacks in Plot._renderCallbacks └─> e.g. Colorbar.render() re-syncs from target plot and re-renders ``` -------------------------------- ### Get Scale Type Float Source: https://redhog.github.io/gladly/docs/docs/architecture/Modules Determines if a quantity kind uses a log scale (1.0) or linear scale (0.0). Reads from axesConfig with fallback to registered definition. ```javascript getScaleTypeFloat(quantityKind, axesConfig) ``` -------------------------------- ### Create and Initialize Plot Source: https://redhog.github.io/gladly/docs/docs/architecture/DataFlow Initializes a new Plot instance, setting up the canvas and SVG elements, and attaching a ResizeObserver. The initial update is deferred until plot.update() is called. ```javascript new Plot(container) // Creates and appends to container // Creates and appends to container // Attaches ResizeObserver (calls update({}) on resize) // No rendering yet — waits for update() ``` -------------------------------- ### Basic Plot Configuration Source: https://redhog.github.io/gladly/docs/docs/configuration/PlotConfiguration Initializes a plot with data and configuration, including layers and axes. Ensure the plot container element exists and the necessary layer types are imported. ```javascript import { Plot } from './src/index.js' import './src/PointsLayer.js' // auto-registers "points" layer type const x = new Float32Array([10, 20, 30, 40, 50]) const y = new Float32Array([15, 25, 35, 25, 45]) const v = new Float32Array([0.2, 0.4, 0.6, 0.8, 1.0]) const plot = new Plot(document.getElementById("plot-container")) plot.update({ data: { x, y, v }, config: { layers: [ { points: { xData: "x", yData: "y", vData: "v" } } ], axes: { xaxis_bottom: { min: 0, max: 60 }, yaxis_left: { min: 0, max: 50 } } } }) ``` -------------------------------- ### Get Stable Selection Instance Source: https://redhog.github.io/gladly/docs/docs/user-api/Selection Retrieve a stable `Selection` instance for a given name. The same instance is returned across `plot.update()` calls, ensuring subscriptions survive updates. ```javascript const sel = plot.selections['brush1'] ``` -------------------------------- ### Usage of Minimal Custom Axis Source: https://redhog.github.io/gladly/docs/docs/user-api/Axis Demonstrates how to instantiate and link a custom `ExternalAxis` object with a Gladly plot axis. This setup allows for bidirectional synchronization of axis domains. ```javascript const externalAxis = new ExternalAxis("velocity_ms") const link = linkAxes(plot.axes["velocity_ms"], externalAxis) // Pan/zoom on the plot → externalAxis._domain is updated automatically. // Call externalAxis.setDomain([0, 10]) → plot re-renders with the new range. // link.unlink() when you no longer want the two to be connected. ``` -------------------------------- ### Gladly Project Structure Source: https://redhog.github.io/gladly/docs/docs/architecture/overview This tree outlines the directory and file structure of the Gladly project, detailing the location of public API exports, core rendering logic, data handling, axes management, colorscales, various layer types, floating widgets, geo utilities, and compute modules. ```tree gladly/ ├── src/ │ ├── index.js # Public API exports │ ├── core/ │ │ ├── Plot.js # Main rendering orchestrator │ │ ├── Layer.js # Data container (DTO) │ │ ├── LayerType.js # Shader + metadata + schema + factory │ │ └── LayerTypeRegistry.js # Global layer type registration │ ├── data/ │ │ └── Data.js # Data normalisation wrapper │ ├── axes/ │ │ ├── Axis.js # First-class axis object (stable across update()) │ │ ├── AxisRegistry.js # Spatial, color, and filter axis management │ │ ├── AxisLink.js # Cross-plot axis linking │ │ ├── AxisQuantityKindRegistry.js # Global quantity kind definitions │ │ ├── ColorAxisRegistry.js # Stub — merged into AxisRegistry.js │ │ ├── FilterAxisRegistry.js # Stub — merged into AxisRegistry.js │ │ └── ZoomController.js # Zoom and pan interaction │ ├── colorscales/ │ │ ├── ColorscaleRegistry.js # GLSL colorscale registration + dispatch builder │ │ ├── MatplotlibColorscales.js # All matplotlib 1D colorscales pre-registered │ │ └── BivariateColorscales.js # 2D colorscales pre-registered │ ├── layers/ │ │ ├── ScatterShared.js # Shared base class for points/lines layer types │ │ ├── PointsLayer.js # Built-in points LayerType │ │ ├── LinesLayer.js # Built-in lines LayerType │ │ ├── ColorbarLayer.js # Built-in 1D colorbar gradient LayerType │ │ ├── ColorbarLayer2d.js # Built-in 2D colorbar LayerType │ │ ├── FilterbarLayer.js # Built-in filterbar axis LayerType │ │ └── TileLayer.js # Built-in map tile LayerType (XYZ/WMS/WMTS) │ ├── floats/ │ │ ├── Float.js # Draggable, resizable floating widget container │ │ ├── Colorbar.js # 1D colorbar plot (extends Plot) │ │ ├── Colorbar2d.js # 2D colorbar plot (extends Plot) │ │ └── Filterbar.js # Filterbar plot (extends Plot) │ ├── geo/ │ │ └── EpsgUtils.js # EPSG/CRS projection utilities │ └── compute/ │ ├── ComputationRegistry.js # Base classes, registry, schema, attribute resolver │ ├── hist.js # 'histogram' TextureComputation │ ├── axisFilter.js # 'filteredHistogram' TextureComputation │ ├── kde.js # 'kde' TextureComputation │ ├── filter.js # 'filter1D', 'lowPass', 'highPass', 'bandPass' TextureComputations │ ├── fft.js # 'fft1d', 'fftConvolution' TextureComputations │ └── conv.js # 'convolution' TextureComputation ├── example/ │ ├── main.js # Example usage │ └── index.html # Demo page ├── package.json └── docs/ ├── Quickstart.md # Installation and minimal example ├── README.md # Documentation index ├── configuration/ # Plot configuration docs ├── user-api/ # Programmatic API docs ├── extension-api/ # Extension API docs └── architecture/ # Architecture docs ``` -------------------------------- ### Instantiate Colorbar Widget Source: https://redhog.github.io/gladly/docs/docs/user-api/Widgets Use this constructor to create a Colorbar widget. Ensure the container element has explicit CSS dimensions. Call `destroy()` to clean up. ```javascript new Colorbar(container, targetPlot, colorAxisName, { orientation, margin }) ``` ```javascript import { Colorbar } from './src/index.js' const cb = new Colorbar( document.getElementById("colorbar-container"), plot, "temperature", { orientation: "vertical" } ) // Later: cb.destroy() ``` -------------------------------- ### Usage of Normalized Difference Computation Source: https://redhog.github.io/gladly/docs/docs/extension-api/Computations Example of how to use a registered GLSL computation like 'normalizedDiff' within the attributes of a layer configuration. Column names are resolved to GLSL expressions. ```javascript attributes: { ndvi: { normalizedDiff: { a: 'nir', // column name — resolved to ColumnData, then to GLSL expr b: 'red', } } } ``` -------------------------------- ### Get Axis Quantity Kind Source: https://redhog.github.io/gladly/docs/docs/architecture/Modules Retrieves the definition for a quantity kind, falling back to a default linear scale for unknown names. Used to access registered axis properties. ```javascript getAxisQuantityKind(name) ``` -------------------------------- ### Registering a GLSL Computation Source: https://redhog.github.io/gladly/docs/docs/extension-api/Computations Use the `registerGlslComputation` function to make a custom GLSL computation available in Gladly. This involves creating a class that extends `GlslComputation` and implementing the `glsl` and `schema` methods. ```APIDOC ## registerGlslComputation(name, computation) ### Description Registers a custom GLSL computation with a given name. ### Parameters #### Parameters - **`name`** (string) - Required - Key used in computation expressions: `{ [name]: params }`. - **`computation`** (`GlslComputation`) - Required - Instance of a class extending `GlslComputation`. ### Subclassing `GlslComputation` To create a custom computation, subclass `GlslComputation` and implement the following methods: #### `glsl(resolvedGlslParams)` ##### Parameters - **`resolvedGlslParams`** (object) - Required - Each value is a **GLSL expression string**. Each column-reference param is recursively resolved: `ArrayColumn` → texture-sample expression, `GlslColumn` → composed expression, `TextureColumn` → texture-sample expression. ##### Return Value A GLSL expression string that evaluates to a `float`. #### `schema(data)` ##### Description Returns a JSON Schema describing the `params` object. ##### Parameters - **`data`** (any) - The input data for schema generation. ### Example ```javascript import { GlslComputation, EXPRESSION_REF, registerGlslComputation } from 'gladly-plot' class NormalizedDiffComputation extends GlslComputation { glsl({ a, b }) { return `((${a}) - (${b})) / ((${a}) + (${b}) + 1e-6)` } schema(data) { return { type: 'object', properties: { a: EXPRESSION_REF, b: EXPRESSION_REF }, required: ['a', 'b'] } } } registerGlslComputation('normalizedDiff', new NormalizedDiffComputation()) ``` ### Usage in `createLayer` ```javascript attributes: { ndvi: { normalizedDiff: { a: 'nir', // column name — resolved to ColumnData, then to GLSL expr b: 'red', } } } ``` ``` -------------------------------- ### JavaScript Layer Creation Methods Source: https://redhog.github.io/gladly/docs/docs/extension-api/LayerTypes Utility methods for creating and configuring layers. Use `createDrawCommand` to compile shaders and `createLayer` for the main layer instantiation process. ```javascript createDrawCommand(regl, layer) // Compiles shaders and returns a regl draw function; maps color/filter axis uniforms via `colorAxisQuantityKinds`/`filterAxisQuantityKinds` suffixes ``` ```javascript schema(data) // Returns JSON Schema for layer parameters ``` ```javascript createLayer(parameters, data) // Calls user factory + `resolveAxisConfig`, returns a ready-to-render Layer ``` ```javascript resolveAxisConfig(parameters, data) // Merges static declarations with `getAxisConfig` output (dynamic wins on non-`undefined`) ``` -------------------------------- ### Scatter-Write Packing in Fragment Shader Source: https://redhog.github.io/gladly/docs/docs/architecture/Selection Demonstrates the scatter-write mechanism used in the fragment shader for packing selection data. It positions sprites and writes to specific channels based on `pickId` to avoid conflicts with additive blending. ```glsl floor(pickId / 4.0) ``` ```glsl mod(pickId, 4.0) ``` -------------------------------- ### Selection Propagation Flow Visualization Source: https://redhog.github.io/gladly/docs/docs/architecture/Selection This visualization outlines the sequence of operations from `selectLasso()` to linked plot updates and subsequent notifications. It highlights GPU operations and callback registrations. ```text selectLasso() └─ SelectionPipeline.runLasso() [GPU: 2-pass per tile → per-tile SelectionColumn FBOs] └─ Selection._readbackAndNotify() └─ per-tile GPU readback → _arrays: Float32Array[] └─ col.activate() / col.clear() └─ col._onClear = () => { _arrays=null; notify } └─ plot.scheduleRender() └─ _notify() → subscribers └─ otherSelection.applyFrom(selection) └─ selCol._rebuild() if tile structure differs └─ col.upload(_arrays) [GPU: per-tile Float32Array[] → per-tile subimages] └─ plot.scheduleRender() └─ _notify() → … ``` -------------------------------- ### Computed Attribute: Histogram Example Source: https://redhog.github.io/gladly/docs/docs/configuration/Computations This snippet demonstrates how to configure a computed attribute to generate a histogram from a 'raw_data' column, using 50 bins. Computed attributes are used for element-wise transformations. ```javascript { points: { xData: { histogram: { input: "raw_data", bins: 50 } } } } ``` -------------------------------- ### Plot Constructor Source: https://redhog.github.io/gladly/docs/docs/user-api/Plot Initializes a new Plot instance. The container must have explicit CSS dimensions. Margins can be customized. ```APIDOC ## new Plot(container, { margin } = {}) ### Description Initializes a new Plot instance. The container must have explicit CSS dimensions. Margins can be customized. ### Parameters #### Path Parameters - **container** (HTMLElement) - Required - Parent `
`. Must have explicit CSS dimensions. Canvas and SVG are created inside it automatically. - **margin** (object) - Optional - Plot margin in px: `{ top, right, bottom, left }`. Defaults to `{ top: 60, right: 60, bottom: 60, left: 60 }`. ``` -------------------------------- ### Create OffsetColumn Instance Source: https://redhog.github.io/gladly/docs/docs/extension-api/Computations Create an OffsetColumn to shift GLSL sampling indices per-vertex. Preferred method is using the withOffset helper. ```javascript import { OffsetColumn } from 'gladly-plot' // Produced via the helper method (preferred): const start = colX.withOffset('0.0') // samples colX at a_pickId + 0 const end = colX.withOffset('1.0') // samples colX at a_pickId + 1 const interp = colX.withOffset('a_endPoint') // per-vertex offset from a template attribute // Or constructed directly: const col = new OffsetColumn(baseCol, '1.0') ``` -------------------------------- ### SAMPLE_COLUMN_GLSL Source: https://redhog.github.io/gladly/docs/docs/extension-api/Computations A GLSL helper string for sampling 1D column data from a texture. It unpacks values stored 4 per texel. ```APIDOC ## `SAMPLE_COLUMN_GLSL` ### Description A GLSL helper string defining `sampleColumn(sampler2D tex, float idx)`. This function is automatically injected into vertex shaders that use 1D column data. It is primarily needed when writing custom shaders or compute passes that require direct sampling of column textures. Values are packed **4 per texel** in RGBA channels. Element `i` maps to texel `i/4` and channel `i%4`. ### GLSL Code ```glsl float sampleColumn(sampler2D tex, float idx) { ivec2 sz = textureSize(tex, 0); int i = int(idx); int texelI = i / 4; int chan = i % 4; ivec2 coord = ivec2(texelI % sz.x, texelI / sz.x); vec4 texel = texelFetch(tex, coord, 0); if (chan == 0) return texel.r; if (chan == 1) return texel.g; if (chan == 2) return texel.b; return texel.a; } ``` ### Usage ```javascript import { SAMPLE_COLUMN_GLSL } from 'gladly-plot' ``` ``` -------------------------------- ### Get Current Plot Configuration Source: https://redhog.github.io/gladly/docs/docs/user-api/Plot Retrieve a snapshot of the current plot configuration, including live axis state (min/max values). The result can be used to restore the current view or for state-saving. ```javascript const config = plot.getConfig() // config has the same shape as the object passed to update({ config }) // Spatial axes min/max reflect current zoom domain. // Color axes min/max reflect current color range. // Filter axes min/max reflect current filter bounds. ``` -------------------------------- ### Get Data for a Specific Column Source: https://redhog.github.io/gladly/docs/docs/user-api/ComputePipeline Use `output.getData(col)` to retrieve a `ColumnData` object for a specified column. This object is extended with a `getArray()` method to access the column's data as a `Float32Array`. ```javascript const col = output.getData('hist.counts') const arr = col.getArray() // Float32Array — GPU readback if needed ``` -------------------------------- ### Get Axis Quantity Kind Definition Source: https://redhog.github.io/gladly/docs/docs/user-api/Registries Retrieves the definition object for a given quantity kind name. If the name is not registered, it returns a default definition with the name as the label and 'linear' as the scale, without registering it. ```javascript const def = getAxisQuantityKind("velocity_ms") // { label: "Velocity (m/s)", scale: "linear", colorscale: "Blues" } ``` -------------------------------- ### Kernel Density Estimate Computation (kde.js) Source: https://redhog.github.io/gladly/docs/docs/architecture/Modules Registers the 'kde' computation for performing Gaussian-smoothed kernel density estimation over a histogram or raw array. ```javascript registerTextureComputation('kde', new KdeComputation()) ``` -------------------------------- ### Switching Quantity Kinds Atomically Source: https://redhog.github.io/gladly/docs/docs/user-api/PlotGroup This example demonstrates how PlotGroup's auto-linking handles atomic switching of quantity kinds for axes across multiple plots. Updating plots simultaneously before re-establishing the link prevents errors. ```javascript // Change both plots from 'time' x-axis to 'depth' x-axis simultaneously. // Without PlotGroup, updating plot A first would leave A on 'depth' and B on 'time' // when the link was re-established, causing a QK mismatch error. group.update({ plots: { left: { layers: [{ points: { xData: 'input.depth', yData: 'input.vp' } }] }, right: { layers: [{ points: { xData: 'input.depth', yData: 'input.rho' } }] } } }) // Both plots update first; then auto-link re-establishes the shared 'depth' axis cleanly. ``` -------------------------------- ### Abstract Computation Base Class Source: https://redhog.github.io/gladly/docs/docs/extension-api/Computations Import the abstract `Computation` base class from 'gladly-plot'. Subclass `TextureComputation` or `GlslComputation` instead of this directly. ```javascript import { Computation } from 'gladly-plot' ``` -------------------------------- ### Two Plots with Shared X-Axis (Auto-Link) Source: https://redhog.github.io/gladly/docs/docs/user-api/PlotGroup Initialize a PlotGroup with autoLink enabled to automatically synchronize axes between plots. This example sets up two plots and updates them, resulting in shared x-axis ranges for synchronized panning and zooming. ```javascript import { Plot, PlotGroup } from 'gladly-plot' const plotTop = new Plot(document.getElementById('top')) const plotBottom = new Plot(document.getElementById('bottom')) const group = new PlotGroup( { top: plotTop, bottom: plotBottom }, { autoLink: true } ) group.update({ data: { x: new Float32Array([...]), y1: new Float32Array([...]), y2: new Float32Array([...]) }, plots: { top: { layers: [{ points: { xData: 'input.x', yData: 'input.y1' } }] }, bottom: { layers: [{ points: { xData: 'input.x', yData: 'input.y2' } }] } } }) // Both plots now share the same x-axis range. Panning/zooming one updates the other. ``` -------------------------------- ### Plotting Large Datasets Efficiently Source: https://redhog.github.io/gladly/docs/docs/configuration/PlotConfiguration Prepare and plot a large dataset (100k points) using Float32Array for efficiency. The plot configuration uses a single layer, and axis ranges are auto-calculated from the data. This setup is optimized for high performance, rendering efficiently at 60fps. ```javascript const N = 100000 const x = new Float32Array(N) const y = new Float32Array(N) const v = new Float32Array(N) for (let i = 0; i < N; i++) { x[i] = Math.random() * 1000 y[i] = Math.sin(x[i] * 0.01) * 50 + Math.random() * 10 v[i] = Math.random() } const plot = new Plot(document.getElementById("plot-container")) plot.update({ data: { x, y, v }, config: { layers: [{ points: { xData: "x", yData: "y", vData: "v" } }] // Ranges auto-calculated from data } }) // GPU renders 100k points efficiently at 60fps ``` -------------------------------- ### Pass 1: Position Capture Source: https://redhog.github.io/gladly/docs/docs/architecture/Selection In capture mode, the vertex shader writes NDC screen positions and local pick IDs to a position FBO. Set `u_tile_pick_offset = 0` to use local pick IDs. For instanced layers, this pass runs twice per tile to capture start and end points separately. ```glsl Data attributes → [same vertex shader + axis/zoom/pan transform, u_mode=1, u_tile_pick_offset=0] → per-tile Position FBO texel i = (ndcX, ndcY, localPickId, endPoint) ``` -------------------------------- ### output.getArrays() Source: https://redhog.github.io/gladly/docs/docs/user-api/ComputePipeline Reads all columns to the CPU at once and returns them as a plain object. ```APIDOC ## output.getArrays() ### Description Reads all available columns to the CPU simultaneously and returns them as a plain JavaScript object, where keys are column names and values are `Float32Array` instances. ### Returns - `object`: An object containing all columns as `Float32Array`s. ### Example ```javascript const arrays = output.getArrays() // { // 'input.depth': Float32Array([...]), // 'input.vp': Float32Array([...]), // 'hist.counts': Float32Array([...]), // 'hist.binCenters': Float32Array([...]), // } ``` ### Note Columns that cannot be read (e.g., due to an uninitialized texture) will be skipped, and a `console.warn` will be issued. The remaining successfully read columns will still be returned in the object. ``` -------------------------------- ### destroy() Source: https://redhog.github.io/gladly/docs/docs/user-api/ComputePipeline Frees GPU resources by destroying the WebGL context. Subsequent calls to `update()` after `destroy()` will result in an error. ```APIDOC ### `destroy()` Destroys the WebGL context and frees GPU resources. After `destroy()`, calling `update()` will throw. ``` -------------------------------- ### qkToEpsgCode Source: https://redhog.github.io/gladly/docs/docs/architecture/Modules Converts a quantity kind string back to an EPSG code. ```APIDOC ## qkToEpsgCode(qk) ### Description Reverses the `crsToQkX`/`crsToQkY` conversion, parsing a quantity kind string (e.g., `"epsg_26911_x"`) back to its EPSG code (e.g., `26911`). ### Parameters - **qk** (string) - The quantity kind string to parse. ``` -------------------------------- ### Correct Fragment Shader for GPU Picking Source: https://redhog.github.io/gladly/docs/docs/extension-api/LayerTypes Ensure fragment shaders write to `fragColor` through `gladly_apply_color()` for GPU picking to function correctly. This is the recommended approach. ```glsl // ✅ Correct — picking works automatically out vec4 fragColor; void main() { vec4 color = /* your color calculation */; fragColor = gladly_apply_color(color); } ``` -------------------------------- ### Dynamic Tile Rebuilding Logic Source: https://redhog.github.io/gladly/docs/docs/architecture/Selection Explains the automatic rebuilding of selection tiles when tile counts or sizes change. This process ensures consistency between rendered tiles and the underlying data structures. ```javascript selCol._rebuild(layer._tileSizes) ``` ```javascript selCol._onClear ``` -------------------------------- ### Selection Properties Source: https://redhog.github.io/gladly/docs/docs/user-api/Selection Provides details on the properties of a Selection instance, including its active state, the arrays representing selected points per tile, and the total number of selected points. ```APIDOC ## Selection Properties ### `selection.active` #### Description `true` when a lasso has been drawn and at least one point is selected; `false` otherwise (including before any lasso has been drawn). ### `selection.arrays` #### Description A `Float32Array[]` with one array per data tile: each element is `1` if selected, `0` if not. Returns `null` when `selection.active` is `false`. For single-tile layers, `selection.arrays` has length 1. For tiled layers, `selection.arrays[t][i]` is `1` when local point `i` within tile `t` is selected. This matches the tile/index pair returned by `plot.pick()`. #### Example Subscription ```js plot.selections['brush1'].subscribe(sel => { const arrays = sel.arrays // Float32Array[] | null if (arrays) { arrays.forEach((tileArr, t) => { const indices = [...tileArr.keys()].filter(i => tileArr[i] > 0.5) console.log(`tile ${t}: ${indices.length} points selected`) }) } }) ``` ### `selection.length` #### Description Total number of data points tracked by this selection channel across all tiles, or `null` if no layer has registered it yet. ```