Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: enable showing track titles in circular layouts #464

Merged
merged 1 commit into from
Aug 14, 2021
Merged
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
2 changes: 1 addition & 1 deletion src/core/gosling-to-higlass.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export function goslingToHiGlass(
showMousePosition: firstResolvedSpec.layout === 'circular' ? false : true, // show mouse position only for linear tracks // TODO: or vertical
mousePositionColor: theme.root.mousePositionColor,
/* Track title */
name: firstResolvedSpec.title,
name: firstResolvedSpec.layout === 'linear' ? firstResolvedSpec.title : ' ',
fontSize: theme.track.titleFontSize,
labelPosition: firstResolvedSpec.title
? theme.track.titleAlign === 'left'
Expand Down
2 changes: 2 additions & 0 deletions src/core/mark/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { drawText } from './text';
import { drawRule } from './rule';
import { drawLink } from './link';
import { drawGrid } from './grid';
import { drawCircularTitle } from './title';
import { drawChartOutlines } from './outline';
import { drawColorLegend, drawRowLegend } from './legend';
import { drawCircularYAxis, drawLinearYAxis } from './axis';
Expand Down Expand Up @@ -201,6 +202,7 @@ export function drawPostEmbellishment(

if (CIRCULAR) {
drawCircularYAxis(HGC, trackInfo, tile, model, theme);
drawCircularTitle(HGC, trackInfo, tile, model, theme);
} else {
drawLinearYAxis(HGC, trackInfo, tile, model, theme);
drawRowLegend(HGC, trackInfo, tile, model, theme);
Expand Down
91 changes: 91 additions & 0 deletions src/core/mark/title.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { GoslingTrackModel } from '../gosling-track-model';
import { cartesianToPolar, valueToRadian } from '../utils/polar';
import colorToHex from '../utils/color-to-hex';
import { CompleteThemeDeep } from '../utils/theme';
import { getTextStyle } from '../utils/text-style';

export function drawCircularTitle(
HGC: any,
trackInfo: any,
tile: any,
gos: GoslingTrackModel,
theme: Required<CompleteThemeDeep>
) {
const spec = gos.spec();
const { title } = spec;

if (spec.layout !== 'circular') {
// Wrong function call, this is for circular tracks.
return;
}

if (!title) {
// No point to render a title.
return;
}

/* track size */
const [tw, th] = trackInfo.dimensions;

/* circular parameters */
const trackOuterRadius = spec.outerRadius ?? 300;
const startAngle = spec.startAngle ?? 0;
const endAngle = spec.endAngle ?? 360;
const cx = tw / 2.0;
const cy = th / 2.0;

/* render */
const g = tile.graphics; // We do not use `pBorder` as in linear layouts.

// The current position, i.e., radius, of this label
const titleR = trackOuterRadius - 1;

// The position of a tick in the polar system
const padding = 1;
const pos = cartesianToPolar(padding, tw, titleR, cx, cy, startAngle, endAngle);

/* Title label */
const styleConfig = getTextStyle({
color: theme.track.titleColor,
size: theme.axis.labelFontSize, // `theme.track.titleFontSize` seems to use much larger fonts
fontFamily: theme.axis.labelFontFamily, // TODO: support
fontWeight: theme.axis.labelFontWeight // TODO: support
});
const textGraphic = new HGC.libraries.PIXI.Text(title, styleConfig);
textGraphic.anchor.x = 1;
textGraphic.anchor.y = 0.5;
textGraphic.position.x = pos.x;
textGraphic.position.y = pos.y;

textGraphic.resolution = 4;
const txtStyle = new HGC.libraries.PIXI.TextStyle(styleConfig);
const metric = HGC.libraries.PIXI.TextMetrics.measureText(textGraphic.text, txtStyle);

// Scale the width of text label so that its width is the same when converted into circular form
const txtWidth = ((metric.width / (2 * titleR * Math.PI)) * tw * 360) / (endAngle - startAngle);
const scaledStartX = padding;
const scaledEndX = padding + txtWidth;

// Determine the points of a rope element for a lebel
const ropePoints: number[] = [];
for (let i = scaledEndX; i >= scaledStartX; i -= txtWidth / 10.0) {
const p = cartesianToPolar(i, tw, titleR - metric.height / 2.0, cx, cy, startAngle, endAngle);
ropePoints.push(new HGC.libraries.PIXI.Point(p.x, p.y));
}

/* Background */
const startRad = valueToRadian(scaledStartX, tw, startAngle, endAngle);
const endRad = valueToRadian(scaledEndX + padding, tw, startAngle, endAngle);

g.lineStyle(1, colorToHex('red'), 0, 0.5);
g.beginFill(colorToHex(theme.track.titleBackground), 0.8); // override the opacity
g.moveTo(pos.x, pos.y);
g.arc(cx, cy, titleR - metric.height, startRad, endRad, true);
g.arc(cx, cy, titleR, endRad, startRad, false);
g.closePath();

// Render a label
textGraphic.updateText();
const rope = new HGC.libraries.PIXI.SimpleRope(textGraphic.texture, ropePoints);
g.addChild(rope);
}
4 changes: 4 additions & 0 deletions src/editor/example/cancer-variant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export const EX_SPEC_CANCER_VARIANT_PROTOTYPE: GoslingSpec = {
height: 100
},
{
title: 'Putative Driver',
alignment: 'overlay',
data: {
url: 'https://s3.amazonaws.com/gosling-lang.org/data/SV/driver.df.scanb.complete.csv',
Expand All @@ -81,6 +82,7 @@ export const EX_SPEC_CANCER_VARIANT_PROTOTYPE: GoslingSpec = {
height: 40
},
{
title: 'LOH',
style: { background: 'lightgray', backgroundOpacity: 0.2 },
alignment: 'overlay',
data: {
Expand Down Expand Up @@ -117,6 +119,7 @@ export const EX_SPEC_CANCER_VARIANT_PROTOTYPE: GoslingSpec = {
height: 40
},
{
title: 'Gain',
style: { background: 'lightgray', backgroundOpacity: 0.2 },
alignment: 'overlay',
data: {
Expand Down Expand Up @@ -157,6 +160,7 @@ export const EX_SPEC_CANCER_VARIANT_PROTOTYPE: GoslingSpec = {
height: 40
},
{
title: 'Structural Variant',
data: {
url: 'https://s3.amazonaws.com/gosling-lang.org/data/cancer/rearrangement.PD35930a.csv',
type: 'csv',
Expand Down
2 changes: 1 addition & 1 deletion src/editor/example/circos.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export const EX_SPEC_CIRCOS: GoslingSpec = {
},
mark: 'bar',
x: { field: 'position', type: 'genomic', axis: 'top' },
y: { field: 'peak', type: 'quantitative' },
y: { field: 'peak', type: 'quantitative', axis: 'right' },
color: { value: '#EEEDA1' },
width: 700,
height: 60
Expand Down