diff --git a/demo/GoslingComponent.tsx b/demo/GoslingComponent.tsx index 429e41e56..a3a931355 100644 --- a/demo/GoslingComponent.tsx +++ b/demo/GoslingComponent.tsx @@ -26,7 +26,7 @@ export function GoslingComponent({ spec, width, height, urlToFetchOptions }: Gos if (!pixiManager) { const canvasWidth = 1000, canvasHeight = 1000; // These initial sizes don't matter because the size will be updated - const pixiManager = new PixiManager(canvasWidth, canvasHeight, plotElement, () => {}); + const pixiManager = new PixiManager(canvasWidth, canvasHeight, plotElement, () => { }); renderGosling(spec, plotElement, pixiManager, urlToFetchOptions); setPixiManager(pixiManager); } else { @@ -37,6 +37,8 @@ export function GoslingComponent({ spec, width, height, urlToFetchOptions }: Gos return
; } + +const baseTheme = getTheme('light'); /** * This is the main function. It takes a Gosling spec and renders it using the PixiManager */ @@ -47,7 +49,12 @@ function renderGosling( urlToFetchOptions?: UrlToFetchOptions ) { // 1. Compile the spec - const compileResult = compile(gs, [], getTheme('light'), { containerSize: { width: 0, height: 0 } }); + const compileResult = compile( + gs, + [], + { ...baseTheme, axis: { ...baseTheme.axis, labelExcludeChrPrefix: true, labelMargin: 1 } }, + { containerSize: { width: 0, height: 0 } } + ); const { trackInfos, gs: processedSpec, theme } = compileResult; console.warn('Spec', processedSpec); // 2. Extract all of the linking information from the spec @@ -93,7 +100,7 @@ function renderGosling( /** Debounces the resize observer */ function debounce(f: (arg0: unknown) => unknown, delay: number) { let timer = 0; - return function (...args: [arg0: unknown]) { + return function(...args: [arg0: unknown]) { clearTimeout(timer); timer = setTimeout(() => f.apply(this, args), delay); }; diff --git a/demo/renderer/dataFetcher.ts b/demo/renderer/dataFetcher.ts index d9235c0e3..218646a01 100644 --- a/demo/renderer/dataFetcher.ts +++ b/demo/renderer/dataFetcher.ts @@ -15,6 +15,9 @@ import type { UrlToFetchOptions } from 'src/compiler/compile'; export function getDataFetcher(spec: ProcessedTrack, urlToFetchOptions?: UrlToFetchOptions) { if (!('data' in spec)) { console.warn('No data in the track spec', spec); + // A data object can be missing in 3D tracks. In this case, just pass an empty data. + // The 3d track can still use the 3D genome model for visual encoding. + return new JsonDataFetcher({ type: 'json', values: [], assembly: spec.assembly }); } const urlFetchOptions = ('url' in spec.data && urlToFetchOptions?.[spec.data.url]) || {}; diff --git a/demo/renderer/main.ts b/demo/renderer/main.ts index eddba36b2..c2fec6fb7 100644 --- a/demo/renderer/main.ts +++ b/demo/renderer/main.ts @@ -13,6 +13,8 @@ import { HeatmapTrack } from '@gosling-lang/heatmap'; import type { PixiManager } from '@pixi-manager'; import { DummyTrack } from '@gosling-lang/dummy-track'; import type { UrlToFetchOptions } from 'src/compiler/compile'; +import { createSpatialTrack } from '../../src/tracks/spatial-track/spatial-track'; +import type { CsvDataFetcherClass } from 'src/data-fetchers/csv/csv-data-fetcher'; /** * Takes a list of track definitions and linkedEncodings and renders them @@ -109,6 +111,21 @@ export function renderTrackDefs( if (type === TrackType.Dummy) { new DummyTrack(options, pixiManager.makeContainer(boundingBox).overlayDiv); } + // Add a new track type for Chromospace + if (type === TrackType.Spatial) { + // Even though Chromospace doesn't use PixiJS, we can use the PixiManager to create a div container that the canvas can be placed into. + // In the final version, we would probably want Chromospace to use an existing canvas element (to limit the creation of new elements). + // But for now this gets the job done. + const container = pixiManager.makeContainer(boundingBox).overlayDiv; + console.log('!@$!#%@#'); + console.log(options.spec); + if (options.spec.data) { + // Ensure to pull all data needed + options.spec.data.sampleLength = 30000; + } + const datafetcher = getDataFetcher(options.spec, urlToFetchOptions); + createSpatialTrack(options, datafetcher as CsvDataFetcherClass, container); + } }); } diff --git a/demo/track-def/axis.ts b/demo/track-def/axis.ts index 120090704..f45caea75 100644 --- a/demo/track-def/axis.ts +++ b/demo/track-def/axis.ts @@ -104,7 +104,7 @@ function getAxisTrackLinearOptions( startAngle: 0, endAngle: 0, layout: 'linear', - assembly: 'hg38', + assembly: track.assembly ?? 'hg38', stroke: 'transparent', // text outline color: theme.axis.labelColor, labelMargin: theme.axis.labelMargin, @@ -165,7 +165,7 @@ function getAxisTrackCircularOptions( height: boundingBox.height, startAngle, endAngle, - assembly: 'hg38', + assembly: track.assembly, stroke: 'transparent', // text outline color: theme.axis.labelColor, labelMargin: theme.axis.labelMargin, diff --git a/demo/track-def/main.ts b/demo/track-def/main.ts index 90a76f8aa..193e538e3 100644 --- a/demo/track-def/main.ts +++ b/demo/track-def/main.ts @@ -6,6 +6,7 @@ import { type BrushLinearTrackOptions } from '@gosling-lang/brush-linear'; import type { TrackInfo } from '../../src/compiler/bounding-box'; import type { CompleteThemeDeep } from '../../src/core/utils/theme'; import type { GoslingTrackOptions } from '../../src/tracks/gosling-track/gosling-track'; +import type { SpatialTrackOptions } from 'src/tracks/spatial-track/spatial-track'; import { proccessTextHeader } from './text'; import { processHeatmapTrack, isHeatmapTrack } from './heatmap'; @@ -25,9 +26,11 @@ export enum TrackType { Axis, BrushLinear, BrushCircular, - Heatmap + Heatmap, + Spatial } + /** * Associate options to each track type */ @@ -39,6 +42,7 @@ interface TrackOptionsMap { [TrackType.BrushLinear]: BrushLinearTrackOptions; [TrackType.BrushCircular]: BrushCircularTrackOptions; [TrackType.Heatmap]: HeatmapTrackOptions; + [TrackType.Spatial]: SpatialTrackOptions; //~ TODO: add actual options } /** @@ -83,6 +87,21 @@ export function createTrackDefs(trackInfos: TrackInfo[], theme: Required