Skip to content

Commit

Permalink
feat(core): remove DataTrack from schema and compiler (#1074)
Browse files Browse the repository at this point in the history
* feat: remove DataTrack from schema

* feat: remove data track from compiler

* feat: update schema

* feat: remove overrideTemplate

* feat: remove tests

* fix(core): remove `"template"` key from template track after processing (#1079)

fix(core): remove 'template' key from a trample track after spec processing

---------

Co-authored-by: SEHI L'YI <sehilyi@gmail.com>
  • Loading branch information
etowahadams and sehilyi authored Jun 12, 2024
1 parent 1aa335b commit 2440948
Show file tree
Hide file tree
Showing 9 changed files with 16 additions and 362 deletions.
5 changes: 1 addition & 4 deletions src/compiler/compile.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { GoslingSpec, TemplateTrackDef, VisUnitApiData } from '@gosling-lang/gosling-schema';
import type { HiGlassSpec } from '@gosling-lang/higlass-schema';
import { traverseToFixSpecDownstream, overrideDataTemplates } from './spec-preprocess';
import { traverseToFixSpecDownstream } from './spec-preprocess';
import { replaceTrackTemplates } from '../core/utils/template';
import { getRelativeTrackInfo, type Size } from './bounding-box';
import type { CompleteThemeDeep } from '../core/utils/theme';
Expand Down Expand Up @@ -32,9 +32,6 @@ export function compile(
// Make sure to keep the original spec as-is
const specCopy = JSON.parse(JSON.stringify(spec));

// Override default visual encoding (i.e., `DataTrack` => `BasicSingleTrack`)
overrideDataTemplates(specCopy);

// Replace track templates with raw gosling specs (i.e., `TemplateTrack` => `SingleTrack | OverlaidTrack`)
replaceTrackTemplates(specCopy, templates);

Expand Down
32 changes: 1 addition & 31 deletions src/compiler/spec-preprocess.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { GoslingSpec, SingleView, Track } from '@gosling-lang/gosling-schema';
import { getBoundingBox, getRelativeTrackInfo } from './bounding-box';
import { traverseToFixSpecDownstream, overrideDataTemplates, convertToFlatTracks } from './spec-preprocess';
import { traverseToFixSpecDownstream, convertToFlatTracks } from './spec-preprocess';
import { getTheme } from '../core/utils/theme';

describe('Fix Spec Downstream', () => {
Expand Down Expand Up @@ -259,36 +259,6 @@ describe('Spec Preprocess', () => {
expect(spec.tracks[1].static).toEqual(false);
});

it('override template (higlass-vector)', () => {
const spec: GoslingSpec = {
tracks: [{ data: { type: 'vector', url: '', column: 'c', value: 'v' }, overrideTemplate: true } as Track]
};
overrideDataTemplates(spec);
expect(spec.tracks[0]).toHaveProperty('mark');
});

it('override template (higlass-multivec)', () => {
{
const spec: GoslingSpec = {
tracks: [
{
data: { type: 'multivec', url: '', row: 'r', column: 'c', value: 'v' },
overrideTemplate: true
} as Track
]
};
overrideDataTemplates(spec);
expect(spec.tracks[0]).toHaveProperty('mark');
}
{
const spec: GoslingSpec = {
tracks: [{ data: { type: 'multivec', url: '', row: 'r', column: 'c', value: 'v' } } as Track]
};
overrideDataTemplates(spec);
expect(spec.tracks[0]).not.toHaveProperty('mark'); // overrideTemplate is not set, so do not override templates
}
});

it('Convert To FlatTracks', () => {
const dummySpec: Track = { data: { type: 'csv', url: '' }, mark: 'bar', width: 10, height: 10 };
{
Expand Down
106 changes: 0 additions & 106 deletions src/compiler/spec-preprocess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ import type {
DisplaceTransform
} from '@gosling-lang/gosling-schema';
import {
IsDataTemplate,
IsDataDeepTileset,
IsSingleTrack,
IsChannelDeep,
IsOverlaidTrack,
Expand Down Expand Up @@ -461,107 +459,3 @@ export function traverseToFixSpecDownstream(spec: GoslingSpec | SingleView, pare
});
}
}

/**
* Get an encoding template for the `higlass-vector` data type.
* @param column
* @param value
*/
export function getVectorTemplate(column: string, value: string): SingleTrack {
return {
data: {
type: 'vector',
url: '',
column,
value
},
mark: 'bar',
x: { field: column, type: 'genomic', axis: 'top' },
y: { field: value, type: 'quantitative' },
width: 400,
height: 100
};
}

export function getMultivecTemplate(
row: string,
column: string,
value: string,
categories: string[] | undefined
): SingleTrack {
return categories && categories.length < 10
? {
data: {
type: 'multivec',
url: '',
row,
column,
value,
categories
},
mark: 'bar',
x: { field: column, type: 'genomic', axis: 'top' },
y: { field: value, type: 'quantitative' },
row: { field: row, type: 'nominal', legend: true },
color: { field: row, type: 'nominal' },
width: 400,
height: 100
}
: {
data: {
type: 'multivec',
url: '',
row,
column,
value,
categories
},
mark: 'rect',
x: { field: column, type: 'genomic', axis: 'top' },
row: { field: row, type: 'nominal', legend: true },
color: { field: value, type: 'quantitative' },
width: 400,
height: 100
};
}

/**
* Override default visual encoding in each track for given data type.
* @param spec
*/
export function overrideDataTemplates(spec: GoslingSpec) {
traverseTracks(spec, (t, i, ts) => {
if (!('data' in t) || !t.data || !IsDataDeepTileset(t.data)) {
// if `data` is not specified, we can not provide a correct template.
return;
}

if ('alignment' in t) {
// This is an OverlaidTracks, so skip this.
return;
}

if (!IsDataTemplate(t)) {
// This is not partial specification that we need to use templates
return;
}

switch (t.data.type) {
case 'vector':
case 'bigwig':
ts[i] = Object.assign(getVectorTemplate(t.data.column ?? 'position', t.data.value ?? 'value'), t);
break;
case 'multivec':
ts[i] = Object.assign(
getMultivecTemplate(
t.data.row ?? 'category',
t.data.column ?? 'position',
t.data.value ?? 'value',
t.data.categories
),
t
);
break;
}
});
}
12 changes: 9 additions & 3 deletions src/core/utils/overlay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,20 @@ import type {
ChannelDeep,
DataDeep
} from '@gosling-lang/gosling-schema';
import { IsChannelDeep, IsDataTrack, IsOverlaidTrack, IsSingleTrack, IsDummyTrack } from '@gosling-lang/gosling-schema';
import {
IsChannelDeep,
IsOverlaidTrack,
IsSingleTrack,
IsDummyTrack,
IsTemplateTrack
} from '@gosling-lang/gosling-schema';

/**
* Resolve superposed tracks into multiple track specifications.
* Some options are corrected to ensure the resolved tracks use consistent visual properties, such as the existence of the axis for genomic coordinates.
*/
export function resolveSuperposedTracks(track: Track): SingleTrack[] {
if (IsDataTrack(track) || IsDummyTrack(track)) {
if (IsTemplateTrack(track) || IsDummyTrack(track)) {
// no BasicSingleTrack to return
return [];
}
Expand Down Expand Up @@ -69,7 +75,7 @@ export function resolveSuperposedTracks(track: Track): SingleTrack[] {
export function spreadTracksByData(tracks: Track[]): Track[] {
return ([] as Track[]).concat(
...tracks.map(t => {
if (IsDataTrack(t) || !IsOverlaidTrack(t) || t._overlay.length <= 1) {
if (!IsOverlaidTrack(t) || t._overlay.length <= 1) {
// no overlaid tracks to spread
return [t];
}
Expand Down
4 changes: 4 additions & 0 deletions src/core/utils/template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,10 @@ export function replaceTrackTemplates(spec: GoslingSpec, templates: TemplateTrac
if ('encoding' in viewBase) {
delete viewBase.encoding;
}
// Remove a template property since it is not a template anymore
if('template' in viewBase) {
delete viewBase.template;
}
const convertedView: OverlaidTracks = {
...viewBase,
alignment: 'overlay',
Expand Down
9 changes: 0 additions & 9 deletions src/gosling-schema/gosling.schema.guards.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import type {
MultivecData,
MatrixData,
VectorData,
DataTrack,
BigWigData,
SingleView,
FlatTracks,
Expand Down Expand Up @@ -92,18 +91,10 @@ export function IsStackedTracks(_: SingleView): _ is StackedTracks {
return !IsFlatTracks(_) && !IsOverlaidTracks(_);
}

export function IsDataTrack(_: Track): _ is DataTrack {
// !!! Track might not contain `mark` when it is superposed one
return !IsOverlaidTrack(_) && 'data' in _ && !('mark' in _);
}
export function IsDummyTrack(_: Track): _ is DummyTrack {
return 'type' in _ && _.type == 'dummy-track';
}

export function IsDataTemplate(_: Partial<Track>): boolean {
return !!('data' in _ && 'overrideTemplate' in _ && _.overrideTemplate);
}

export function IsDataDeep(data: DataDeep | Datum[]): data is DataDeep {
return typeof data === 'object';
}
Expand Down
Loading

0 comments on commit 2440948

Please sign in to comment.