Skip to content

Commit b1def1e

Browse files
canvas2svg.js translation; better inference based on type+format+url
Signed-off-by: eternal-flame-AD <yume@yumechi.jp>
1 parent 3f38ef7 commit b1def1e

File tree

1 file changed

+216
-67
lines changed

1 file changed

+216
-67
lines changed

js/igv.d.ts

Lines changed: 216 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
2-
// allow extra keys
3-
type ExtraKeys<T> = T & { [key: string]: any };
4-
5-
type Override<T, R> = Omit<T, keyof R> & R;
6-
1+
// either uppercase or lowercase
72
type AnyCase<T extends string> = Uppercase<T> | Lowercase<T>;
83

4+
// any action that can be deferred as a promise or a thenable
5+
type Deferrable<T> = T | Promise<T> | Thenable<T, any> | (() => T | Promise<T> | Thenable<T, any>);
6+
97
export interface Thenable<T, E> {
108
then(resolve: (value: T) => void, reject: (error: E) => void): void;
119
}
@@ -21,24 +19,99 @@ export type TrackType =
2119
"snp" | "eqtl";
2220

2321
export type TrackLoad<T extends TrackType> =
24-
Override<Tracks.TrackCommonOptions,
25-
(T extends "annotation" ? (Tracks.AnnotationTrackOptions & Tracks.TypeFormatPair<'annotation', Tracks.AnnotationFormat>) :
26-
T extends "wig" ? (Tracks.WigTrackOptions & Tracks.TypeFormatPair<'wig', Tracks.WigFormat>) :
27-
T extends "alignment" ? (Tracks.AlignmentTrackOptions & Tracks.TypeFormatPair<'alignment', Tracks.AlignmentFormat>) :
28-
T extends "variant" ? (Tracks.VariantTrackOptions & Tracks.TypeFormatPair<'variant', Tracks.VariantFormat>) :
29-
T extends "mut" ? (Tracks.MutationTrackOptions & Tracks.TypeFormatPair<'mut', Tracks.MutationFormat>) :
30-
T extends "seg" ? (Tracks.SegTrackOptions & Tracks.TypeFormatPair<'seg', Tracks.SegFormat>) :
31-
T extends "gwas" ? (Tracks.GWASTrackOptions<Tracks.GWASFormat> & Tracks.TypeFormatPair<'gwas', Tracks.GWASFormat>) :
32-
T extends "interact" | "interaction" ? (Tracks.InteractTrackOptions & Tracks.TypeFormatPair<'interact' | 'interaction', Tracks.InteractFormat>) :
33-
T extends "qtl" ? (Tracks.QTLTrackOptions & Tracks.TypeFormatPair<'qtl', Tracks.QTLFormat>) :
34-
T extends "junction" ? (Tracks.JunctionTrackOptions & Tracks.TypeFormatPair<'junction', Tracks.JunctionFormat>) :
35-
T extends "cnvpytor" ? (Tracks.CnvPyTorTrackOptions & Tracks.TypeFormatPair<'cnvpytor', Tracks.CnvPyTorFormat>) :
36-
T extends "merged" ? (Tracks.WigMergedTrackOptions & { type: 'merged' }) :
37-
T extends "arc" ? (Tracks.ArcTrackOptions & Tracks.TypeFormatPair<'arc', Tracks.ArcFormat>) :
38-
/* undocumented options */
39-
T extends "snp" ? (Tracks.SNPTrackOptions & Tracks.TypeFormatPair<'snp', Tracks.SNPFormat>) :
40-
T extends "eqtl" ? (Tracks.EQTLTrackOptions & Tracks.TypeFormatPair<'eqtl', Tracks.EQTLFormat>) :
41-
never)>;
22+
Tracks.TrackCommonOptions &
23+
(T extends "annotation" ? Tracks.AnnotationTrackOptions & TypeFormatPair<'annotation'> :
24+
T extends "wig" ? Tracks.WigTrackOptions & TypeFormatPair<'wig'> :
25+
T extends "alignment" ? Tracks.AlignmentTrackOptions & TypeFormatPair<'alignment'> :
26+
T extends "variant" ? Tracks.VariantTrackOptions & TypeFormatPair<'variant'> :
27+
T extends "mut" ? Tracks.MutationTrackOptions & TypeFormatPair<'mut'> :
28+
T extends "seg" ? Tracks.SegTrackOptions & TypeFormatPair<'seg'> :
29+
T extends "gwas" ? Tracks.GWASTrackOptions<Tracks.GWASFormat> & TypeFormatPair<'gwas'> :
30+
T extends "interact" | "interaction" ? Tracks.InteractTrackOptions & TypeFormatPair<'interact' | 'interaction'> :
31+
T extends "qtl" ? Tracks.QTLTrackOptions & TypeFormatPair<'qtl'> :
32+
T extends "junction" ? Tracks.JunctionTrackOptions & TypeFormatPair<'junction'> :
33+
T extends "cnvpytor" ? Tracks.CnvPyTorTrackOptions & TypeFormatPair<'cnvpytor'> :
34+
T extends "merged" ? Tracks.WigMergedTrackOptions & { type: 'merged' } :
35+
T extends "arc" ? Tracks.ArcTrackOptions & TypeFormatPair<'arc'> :
36+
/* undocumented options */
37+
T extends "snp" ? Tracks.SNPTrackOptions & TypeFormatPair<'snp'> :
38+
T extends "eqtl" ? Tracks.EQTLTrackOptions & TypeFormatPair<'eqtl'> :
39+
never);
40+
41+
export type TypeFormatPair<T extends TrackType> = {
42+
type?: T;
43+
format: TrackFormatOf<T>;
44+
url?: string;
45+
} | {
46+
type?: T;
47+
format?: TrackFormatOf<T>;
48+
url: TrackFormatOf<T> extends string ? Deferrable<URLInference.URLWithExtension<TrackFormatOf<T>>> : never;
49+
} | ({
50+
type?: T;
51+
format?: never;
52+
url?: never;
53+
} & (CustomReaderOf<T> | ManualFeatureOf<T>)) | {
54+
type: T;
55+
format?: TrackFormatOf<T>;
56+
// if there is only one possible format, we permit it to be omitted
57+
url: TrackFormatOf<T> extends string ? (string extends TrackFormatOf<T> ? never : string) : never;
58+
};
59+
60+
export type TrackFormatOf<T extends TrackType> =
61+
T extends "annotation" ? Tracks.AnnotationFormat :
62+
T extends "wig" ? Tracks.WigFormat :
63+
T extends "alignment" ? Tracks.AlignmentFormat :
64+
T extends "variant" ? Tracks.VariantFormat :
65+
T extends "mut" ? Tracks.MutationFormat :
66+
T extends "seg" ? Tracks.SegFormat :
67+
T extends "gwas" ? Tracks.GWASFormat :
68+
T extends "interact" | 'interaction' ? Tracks.InteractFormat :
69+
T extends "qtl" ? Tracks.QTLFormat :
70+
T extends "junction" ? Tracks.JunctionFormat :
71+
T extends "cnvpytor" ? Tracks.CnvPyTorFormat :
72+
T extends "arc" ? Tracks.ArcFormat :
73+
/* undocumented options */
74+
T extends "snp" ? Tracks.SNPFormat :
75+
T extends "eqtl" ? Tracks.EQTLFormat :
76+
never;
77+
78+
export type ManualFeatureOf<T extends TrackType> =
79+
T extends "annotation" ? {
80+
features: Record<string, any>[];
81+
} :
82+
T extends "wig" ? {
83+
features: Tracks.WigTrackManualFeatures;
84+
} :
85+
T extends "seg" ? {
86+
features: Array<{
87+
chr: string;
88+
start: number;
89+
end: number;
90+
value: number;
91+
sample: string;
92+
}>;
93+
} : never;
94+
95+
export type CustomReaderOf<T extends TrackType> =
96+
T extends "annotation" ? { reader: Tracks.AnnotationCustomReader } |
97+
{
98+
source: {
99+
url: string;
100+
method?: "GET" | "POST";
101+
contentType?: string;
102+
body?: string;
103+
}
104+
} :
105+
T extends "seg" ? {
106+
source: {
107+
url: (options: { chr: string }) => string;
108+
method?: "GET" | "POST";
109+
contentType?: string;
110+
body?: string;
111+
mappings: Record<string, string>;
112+
}
113+
} :
114+
never;
42115

43116
export type TrackOf<T extends TrackType> =
44117
T extends "annotation" ? Tracks.Track :
@@ -68,22 +141,34 @@ export type StaticFeatureConfig<T extends Record<string, any>> = {
68141
mappings: Record<keyof T, string>;
69142
}
70143

144+
// ref: https://github.com/igvteam/igv-utils/blob/master/src/fileUtils.js
145+
export namespace URLInference {
146+
type StripLast<S extends string, SEP extends string> = S extends `${infer _}${SEP}${infer P}` ? StripLast<P, SEP> : S;
147+
type StripQuery<S extends string> = S extends `${infer P}?${infer _}` ? P : S;
148+
type StripSuffix<S extends string, T extends string> = S extends `${infer P}.${T}` ? P : S;
149+
150+
export type FilenameOfURL<U extends string> = StripLast<StripQuery<U>, '/'>
151+
152+
type AuxExtensions = ".gz" | ".tab" | ".txt" | ".bgz";
153+
154+
export type InferExtension<F extends string> = Lowercase<F> extends `${infer B}${AuxExtensions}` ? StripLast<B, '.'> : StripLast<Lowercase<F>, '.'>
155+
156+
type Query = `?${string}`;
157+
158+
export type URLWithExtension<E extends string> =
159+
`${string}.${E}${AuxExtensions | ''}${Query | ''}`;
160+
}
161+
71162
export namespace Tracks {
72163
export class Track {
73164
public readonly id: string;
74165
public readonly type: string;
75166
public readonly name?: string;
76167
}
77168

78-
export interface TypeFormatPair<K extends string, F extends string> {
79-
type?: K;
80-
format?: F;
81-
}
82169

83170
export interface TrackCommonOptions {
84171
name?: string;
85-
url?: string | Promise<string> | (() => string | Promise<string>) |
86-
Thenable<string, any> | (() => Thenable<string, any>);
87172
indexURL?: string | Promise<string>;
88173
indexed?: false;
89174
order?: number;
@@ -97,6 +182,12 @@ export namespace Tracks {
97182
oauthToken?: string | (() => string | Promise<string>);
98183
sourceType?: string;
99184
filename?: string;
185+
roi?: DefineROI[];
186+
}
187+
188+
export class AnnotationCustomReader {
189+
constructor(config: TrackCommonOptions & AnnotationTrackOptions);
190+
readFeatures(chr: string, start: number, end: number): Promise<Record<string, any>[]>;
100191
}
101192

102193
export type AnnotationFormat = "bed" | "gff3" | "gtf" |
@@ -230,11 +321,11 @@ export namespace Tracks {
230321
colorTable?: Record<string, string>,
231322
}
232323

233-
export type AnnotationTrackOptions = ExtraKeys<AnnotationTrackDisplay & AnnotationTrackSearch & AnnotationTrackCommonOptions>;
324+
export type AnnotationTrackOptions = AnnotationTrackDisplay & AnnotationTrackSearch & AnnotationTrackCommonOptions;
234325

235-
export type WigFormat = "wig" | "bigWig" | "bigwig";
326+
export type WigFormat = AnyCase<"wig"> | "bigWig" | AnyCase<'bigWig'> | AnyCase<'tdf'> | AnyCase<'bw'>;
236327

237-
export interface WigTrackCommonOptions {
328+
export interface WigTrackOptions {
238329
/**
239330
* Autoscale track to maximum value in view
240331
*
@@ -305,13 +396,20 @@ export namespace Tracks {
305396
windowFunction?: "mean" | "max" | "min";
306397

307398
height?: number;
399+
400+
displayMode?: AnyCase<"EXPANDED" | "SQUISHED" | "COLLAPSED">;
308401
}
309402

310-
export type WigTrackOptions = ExtraKeys<WigTrackCommonOptions>;
403+
export type WigTrackManualFeatures = {
404+
chr: string;
405+
start: number;
406+
end: number;
407+
value: number;
408+
}[];
311409

312-
export type WigMergedTrackOptions = ExtraKeys<{
313-
tracks: (Partial<TrackCommonOptions> & ((TypeFormatPair<'wig', WigFormat> & WigTrackOptions) | (TypeFormatPair<'junction', JunctionFormat> & JunctionTrackOptions)))[];
314-
}>;
410+
export type WigMergedTrackOptions = {
411+
tracks: (Partial<TrackCommonOptions> & ((TypeFormatPair<'wig'> & WigTrackOptions) | (TypeFormatPair<'junction'> & JunctionTrackOptions)))[];
412+
};
315413

316414
export type VariantFormat = "vcf";
317415

@@ -326,7 +424,7 @@ export namespace Tracks {
326424
info: Record<string, string>;
327425
}
328426

329-
export type VariantTrackOptions = ExtraKeys<{
427+
export type VariantTrackOptions = {
330428
displayMode?: AnyCase<"EXPANDED" | "SQUISHED" | "COLLAPSED">;
331429
squishedCallHeight?: number;
332430
expandedCallHeight?: number;
@@ -337,7 +435,11 @@ export namespace Tracks {
337435
homvarColor?: string;
338436
hetvarColor?: string;
339437
homrefColor?: string;
340-
}>;
438+
supportsWholeGenome?: boolean;
439+
showGenotypes?: boolean;
440+
strokecolor?: (variant: VCFItem) => string | void;
441+
context_hook?: (variant: VCFItem, ctx: Draw.CanvasContext, x: number, y: number, w: number, h: number) => void;
442+
};
341443

342444
export type CnvPyTorFormat = "pytor" | "vcf";
343445

@@ -454,34 +556,7 @@ export namespace Tracks {
454556
} | {
455557
log?: boolean;
456558
isLog?: never;
457-
})
458-
& (
459-
{
460-
features: Array<{
461-
chr: string;
462-
start: number;
463-
end: number;
464-
value: number;
465-
sample: string;
466-
}>;
467-
url?: never;
468-
source?: never;
469-
} | ({
470-
features?: never;
471-
source?: never;
472-
} & Required<Pick<TrackCommonOptions, 'url'>>) |
473-
{
474-
source: StaticFeatureConfig<{
475-
chr: string;
476-
value: number;
477-
sampleKey: string;
478-
sample: string;
479-
}>;
480-
features?: never;
481-
url?: never;
482-
}
483-
484-
)
559+
});
485560

486561

487562
export type InteractFormat = "interact" | "bedpe" | "bigInteract" | "bb";
@@ -742,6 +817,7 @@ export type CreateOpt = (GenomeOpt & CreateOptExtras) | (
742817
export interface ROISet {
743818
url: string;
744819
name: string;
820+
indexed: boolean;
745821
isUserDefined: boolean;
746822
color: string;
747823
headerColor: string;
@@ -853,6 +929,79 @@ export type IGV = {
853929
readonly version: () => string;
854930
}
855931

932+
declare namespace Draw {
933+
// ref: canvas2svg.js
934+
export class CanvasContext {
935+
public readonly canvas: this;
936+
public readonly isSVG: boolean;
937+
938+
public strokeStyle: string;
939+
public lineWidth: number;
940+
941+
private constructor(config: {
942+
ctx?: any;
943+
width?: number;
944+
height?: number;
945+
enableMirroring?: boolean;
946+
viewBox?: {
947+
x: number;
948+
y: number;
949+
width: number;
950+
height: number;
951+
};
952+
multiLocusGap?: any;
953+
backdropColor?: string;
954+
document?: Document;
955+
});
956+
setWidth(width: number): void;
957+
setHeight(height: number): void;
958+
getSerializedSvg(fixNamedEntitles?: boolean): string;
959+
getSvg(): SVGSVGElement;
960+
saveWithTranslationAndClipRect(id: string, tx: number, ty: number, width: number, height: number, clipYOffset: number): void;
961+
save(): void;
962+
restore(): void;
963+
addTrackGroupWithTranslationAndClipRect(
964+
id: string,
965+
tx: number,
966+
ty: number,
967+
width: number,
968+
height: number,
969+
clipYOffset: number,
970+
)
971+
scale(x: number, y: number): void;
972+
rotate(angle: number): void;
973+
translate(x: number, y: number): void;
974+
transform(a: number, b: number, c: number, d: number, e: number, f: number): void;
975+
beginPath(): void;
976+
moveTo(x: number, y: number): void;
977+
closePath(): void;
978+
lineTo(x: number, y: number): void;
979+
bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number): void;
980+
quadraticCurveTo(cp1x: number, cp1y: number, x: number, y: number): void;
981+
arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): void;
982+
stroke(): void;
983+
fill(): void;
984+
rect(x: number, y: number, w: number, h: number): void;
985+
fillRect(x: number, y: number, w: number, h: number): void;
986+
strokeRect(x: number, y: number, w: number, h: number): void;
987+
strokeEllipse(cx: number, cy: number, rx: number, ry: number,
988+
rotation: number, startAngle: number, endAngle: number,
989+
isCCW: boolean): void;
990+
fillEllipse(cx: number, cy: number, rx: number, ry: number,
991+
rotation: number, startAngle: number, endAngle: number,
992+
isCCW: boolean): void;
993+
clearRect(x: number, y: number, w: number, h: number): void;
994+
createLinearGradient(x0: number, y0: number, x1: number, y1: number): CanvasGradient;
995+
createRadialGradient(x0: number, y0: number, r0: number, x1: number, y1: number, r1: number): CanvasGradient;
996+
strokeText(text: string, x: number, y: number): void;
997+
measureText(text: string): TextMetrics;
998+
arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, anticlockwise?: boolean): void;
999+
clip(): void;
1000+
drawImage();
1001+
createPattern(image: CanvasImageSource, repetition?: string): CanvasPattern;
1002+
}
1003+
}
1004+
8561005
declare const igv: IGV;
8571006

8581007
export default igv;

0 commit comments

Comments
 (0)