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

Performance roadmap: reducing redraws and reducing GoslingTrackModel initializations #1036

Open
etowahadams opened this issue Jan 22, 2024 · 1 comment · May be fixed by #1039
Open

Performance roadmap: reducing redraws and reducing GoslingTrackModel initializations #1036

etowahadams opened this issue Jan 22, 2024 · 1 comment · May be fixed by #1039
Labels
enhancement New feature or request

Comments

@etowahadams
Copy link
Contributor

etowahadams commented Jan 22, 2024

The frame-rate of certain Gosling visualizations is very low when zooming and panning. What are the main bottlenecks?

Flame charts

We can interact with laggy visualzations and observe their flame charts to understand what is causing poor performance.

Multiple Sequence Alignment

{"zoomLimits": [1, 396],"xDomain": {"interval": [350, 396]},"assembly": "unknown","views": [{"tracks": [{"alignment": "overlay","data": {"url": "https://raw.githubusercontent.com/sehilyi/gemini-datasets/master/data/alignment_viewer_p53.fasta.csv","type": "csv","genomicFields": ["pos"],"sampleLength": 99999},"tracks": [{"mark": "rect"},{"mark": "text","x": {"field": "start", "type": "genomic"},"xe": {"field": "end", "type": "genomic"},"color": {"value": "black"},"size": {"value": 12},"visibility": [{"measure": "zoomLevel","target": "track","threshold": 10,"operation": "LT","transitionPadding": 100}]}],"x": {"field": "pos", "type": "genomic", "axis": "none"},"row": {"field": "name", "type": "nominal", "legend": false},"color": {"field": "base","type": "nominal","range": ["#d60000","#018700","#b500ff","#05acc6","#97ff00","#ffa52f","#ff8ec8","#79525e","#00fdcf","#afa5ff","#93ac83","#9a6900","#366962","#d3008c","#fdf490","#c86e66","#9ee2ff","#00c846","#a877ac","#b8ba01"],"legend": false},"stroke": {"value": "white"},"strokeWidth": {"value": 0},"text": {"field": "base", "type": "nominal"},"width": 800,"height": 400,"title": "Original Approach"}]}]}

Here's a flame graph when zooming in and out of :

image

SARS-Cov2

{"title": "SARS-CoV-2","subtitle": "Data Source: WashU Virus Genome Browser, NCBI, GISAID","assembly": [["NC_045512.2", 29903]],"layout": "linear","spacing": 50,"views": [{"alignment": "overlay","title": "NC_045512.2 Genes","data": {"type": "csv","url": "https://s3.amazonaws.com/gosling-lang.org/data/COVID/NC_045512.2-Genes.csv","chromosomeField": "Accession","genomicFields": ["Start", "Stop"]},"tracks": [{"mark": "rect","color": {"value": "#0072B2"},"stroke": {"value": "white"},"strokeWidth": {"value": 2}},{"mark": "rule","color": {"value": "white"},"opacity": {"value": 0.6},"strokeWidth": {"value": 0},"style": {"linePattern": {"type": "triangleRight", "size": 10}}},{"mark": "text","text": {"field": "Gene symbol", "type": "nominal"},"color": {"value": "black"},"stroke": {"value": "white"},"strokeWidth": {"value": 3},"visibility": [{"target": "mark","measure": "width","threshold": "|xe-x|","operation": "LTET","transitionPadding": 30}]},{"mark": "brush", "x": {"linkingId": "detail"}}],"x": {"field": "Start", "type": "genomic"},"xe": {"field": "Stop", "type": "genomic"},"width": 800,"height": 30,"static": true,"layout": "linear","xDomain": {"interval": [1, 29903]}},{"centerRadius": 0,"xDomain": {"interval": [1, 29903]},"linkingId": "detail","alignment": "stack","tracks": [{"alignment": "overlay","title": "S Protein Annotation","data": {"type": "csv","url": "https://s3.amazonaws.com/gosling-lang.org/data/COVID/sars-cov-2_Sprot_annot_sorted.bed","chromosomeField": "Accession","genomicFields": ["Start", "Stop"]},"tracks": [{"mark": "rect","color": {"field": "Protein","type": "nominal","domain": ["receptor-binding domain (RBD)","receptor-binding motif (RBM)","S1/S2 cleavage site","heptad repeat 1 (HR1)","heptad repeat 2 (HR2)"]},"xe": {"field": "Stop", "type": "genomic"}},{"mark": "text","text": {"field": "Protein", "type": "nominal"},"color": {"value": "#333"},"stroke": {"value": "white"},"strokeWidth": {"value": 3},"style": {"textAnchor": "end"}}],"x": {"field": "Start", "type": "genomic"},"row": {"field": "Protein","type": "nominal","domain": ["receptor-binding domain (RBD)","receptor-binding motif (RBM)","S1/S2 cleavage site","heptad repeat 1 (HR1)","heptad repeat 2 (HR2)"]},"width": 800,"height": 80},{"alignment": "overlay","title": "NC_045512.2 Genes","data": {"type": "csv","url": "https://s3.amazonaws.com/gosling-lang.org/data/COVID/NC_045512.2-Genes.csv","chromosomeField": "Accession","genomicFields": ["Start", "Stop"]},"tracks": [{"mark": "rect","color": {"value": "#0072B2"},"stroke": {"value": "white"},"strokeWidth": {"value": 2}},{"mark": "rule","color": {"value": "white"},"opacity": {"value": 0.6},"strokeWidth": {"value": 0},"style": {"linePattern": {"type": "triangleRight", "size": 10}}},{"mark": "text","text": {"field": "Gene symbol", "type": "nominal"},"color": {"value": "black"},"stroke": {"value": "white"},"strokeWidth": {"value": 3},"visibility": [{"target": "mark","measure": "width","threshold": "|xe-x|","operation": "LTET","transitionPadding": 30}]}],"x": {"field": "Start", "type": "genomic"},"xe": {"field": "Stop", "type": "genomic"},"width": 800,"height": 30},{"title": "NC_045512.2 Sequence","alignment": "overlay","data": {"url": "https://server.gosling-lang.org/api/v1/tileset_info/?d=NC_045512_2-multivec","type": "multivec","row": "base","column": "position","value": "count","categories": ["A", "T", "G", "C"],"start": "start","end": "end"},"tracks": [{"mark": "bar","y": {"field": "count", "type": "quantitative", "axis": "none"}},{"dataTransform": [{"type": "filter", "field": "count", "oneOf": [0], "not": true}],"mark": "text","x": {"field": "start", "type": "genomic"},"xe": {"field": "end", "type": "genomic"},"size": {"value": 24},"color": {"value": "white"},"visibility": [{"operation": "less-than","measure": "width","threshold": "|xe-x|","transitionPadding": 30,"target": "mark"},{"operation": "LT","measure": "zoomLevel","threshold": 40,"target": "track"}]}],"x": {"field": "position", "type": "genomic"},"color": {"field": "base","type": "nominal","domain": ["A", "T", "G", "C"],"legend": true},"text": {"field": "base", "type": "nominal"},"style": {"inlineLegend": true},"width": 800,"height": 40},{"title": "TRS-L-Dependent Recombination Events","data": {"type": "csv","url": "https://s3.amazonaws.com/gosling-lang.org/data/COVID/TRS-L-dependent_recombinationEvents_sorted.bed","chromosomeField": "Accession","genomicFields": ["Start1", "Stop1", "Start2", "Stop2"],"sampleLength": 100},"mark": "withinLink","x": {"field": "Start1", "type": "genomic"},"xe": {"field": "Stop1", "type": "genomic"},"x1": {"field": "Start2", "type": "genomic"},"x1e": {"field": "Stop2", "type": "genomic"},"stroke": {"value": "#0072B2"},"color": {"value": "#0072B2"},"opacity": {"value": 0.1},"width": 800,"height": 400}]}]}
image

Corces et al.

{"title": "Single-cell Epigenomic Analysis","subtitle": "Corces et al. 2020","layout": "linear","arrangement": "vertical","views": [{"layout": "linear","xDomain": {"chromosome": "chr3"},"centerRadius": 0.8,"tracks": [{"alignment": "overlay","title": "chr3","data": {"url": "https://raw.githubusercontent.com/sehilyi/gemini-datasets/master/data/cytogenetic_band.csv","type": "csv","chromosomeField": "Chr.","genomicFields": ["ISCN_start","ISCN_stop","Basepair_start","Basepair_stop"]},"tracks": [{"mark": "rect","dataTransform": [{"type": "filter","field": "Stain","oneOf": ["acen-1", "acen-2"],"not": true}],"color": {"field": "Density","type": "nominal","domain": ["", "25", "50", "75", "100"],"range": ["white", "#D9D9D9", "#979797", "#636363", "black"]},"size": {"value": 20}},{"mark": "rect","dataTransform": [{"type": "filter", "field": "Stain", "oneOf": ["gvar"]}],"color": {"value": "#A0A0F2"},"size": {"value": 20}},{"mark": "triangleRight","dataTransform": [{"type": "filter", "field": "Stain", "oneOf": ["acen-1"]}],"color": {"value": "#B40101"},"size": {"value": 20}},{"mark": "triangleLeft","dataTransform": [{"type": "filter", "field": "Stain", "oneOf": ["acen-2"]}],"color": {"value": "#B40101"},"size": {"value": 20}},{"mark": "brush","x": {"linkingId": "detail"},"color": {"value": "red"},"opacity": {"value": 0.3},"strokeWidth": {"value": 1},"stroke": {"value": "red"}}],"x": {"field": "Basepair_start", "type": "genomic", "axis": "none"},"xe": {"field": "Basepair_stop", "type": "genomic"},"stroke": {"value": "black"},"strokeWidth": {"value": 1},"style": {"outlineWidth": 0},"width": 400,"height": 25}]},{"xDomain": {"chromosome": "chr3", "interval": [52168000, 52890000]},"linkingId": "detail","x": {"field": "position", "type": "genomic"},"y": {"field": "peak", "type": "quantitative", "axis": "right"},"style": {"outline": "#20102F"},"width": 400,"height": 40,"tracks": [{"data": {"url": "https://s3.amazonaws.com/gosling-lang.org/data/ExcitatoryNeurons-insertions_bin100_RIPnorm.bw","type": "bigwig","column": "position","value": "peak"},"title": "Excitatory neurons","mark": "bar","color": {"value": "#F29B67"}},{"data": {"url": "https://s3.amazonaws.com/gosling-lang.org/data/InhibitoryNeurons-insertions_bin100_RIPnorm.bw","type": "bigwig","column": "position","value": "peak"},"title": "Inhibitory neurons","mark": "bar","color": {"value": "#3DC491"}},{"data": {"url": "https://s3.amazonaws.com/gosling-lang.org/data/DopaNeurons_Cluster10_AllFrags_projSUNI2_insertions_bin100_RIPnorm.bw","type": "bigwig","column": "position","value": "peak"},"title": "Dopaminergic neurons","mark": "bar","color": {"value": "#565C8B"}},{"data": {"url": "https://s3.amazonaws.com/gosling-lang.org/data/Microglia-insertions_bin100_RIPnorm.bw","type": "bigwig","column": "position","value": "peak"},"title": "Microglia","mark": "bar","color": {"value": "#77C0FA"}},{"data": {"url": "https://s3.amazonaws.com/gosling-lang.org/data/Oligodendrocytes-insertions_bin100_RIPnorm.bw","type": "bigwig","column": "position","value": "peak"},"title": "Oligodendrocytes","mark": "bar","color": {"value": "#9B46E5"}},{"data": {"url": "https://s3.amazonaws.com/gosling-lang.org/data/Astrocytes-insertions_bin100_RIPnorm.bw","type": "bigwig","column": "position","value": "peak"},"title": "Astrocytes","mark": "bar","color": {"value": "#D73636"}},{"data": {"url": "https://s3.amazonaws.com/gosling-lang.org/data/OPCs-insertions_bin100_RIPnorm.bw","type": "bigwig","column": "position","value": "peak"},"title": "OPCs","mark": "bar","color": {"value": "#E38ADC"}},{"alignment": "overlay","title": "Genes","data": {"url": "https://server.gosling-lang.org/api/v1/tileset_info/?d=gene-annotation","type": "beddb","genomicFields": [{"index": 1, "name": "start"},{"index": 2, "name": "end"}],"valueFields": [{"index": 5, "name": "strand", "type": "nominal"},{"index": 3, "name": "name", "type": "nominal"}],"exonIntervalFields": [{"index": 12, "name": "start"},{"index": 13, "name": "end"}]},"style": {"outline": "#20102F"},"tracks": [{"dataTransform": [{"type": "filter", "field": "type", "oneOf": ["gene"]},{"type": "filter", "field": "strand", "oneOf": ["+"]}],"mark": "text","text": {"field": "name", "type": "nominal"},"x": {"field": "start", "type": "genomic"},"size": {"value": 8},"xe": {"field": "end", "type": "genomic"},"style": {"textFontSize": 8, "dy": -12}},{"dataTransform": [{"type": "filter", "field": "type", "oneOf": ["gene"]},{"type": "filter", "field": "strand", "oneOf": ["-"]}],"mark": "text","text": {"field": "name", "type": "nominal"},"x": {"field": "start", "type": "genomic"},"xe": {"field": "end", "type": "genomic"},"size": {"value": 8},"style": {"textFontSize": 8, "dy": 10}},{"dataTransform": [{"type": "filter", "field": "type", "oneOf": ["gene"]},{"type": "filter", "field": "strand", "oneOf": ["+"]}],"mark": "rect","x": {"field": "end", "type": "genomic"},"size": {"value": 7}},{"dataTransform": [{"type": "filter", "field": "type", "oneOf": ["gene"]},{"type": "filter", "field": "strand", "oneOf": ["-"]}],"mark": "rect","x": {"field": "start", "type": "genomic"},"size": {"value": 7}},{"dataTransform": [{"type": "filter", "field": "type", "oneOf": ["exon"]}],"mark": "rect","x": {"field": "start", "type": "genomic"},"xe": {"field": "end", "type": "genomic"},"size": {"value": 14}},{"dataTransform": [{"type": "filter", "field": "type", "oneOf": ["gene"]}],"mark": "rule","x": {"field": "start", "type": "genomic"},"xe": {"field": "end", "type": "genomic"},"strokeWidth": {"value": 3}}],"row": {"field": "strand", "type": "nominal", "domain": ["+", "-"]},"color": {"field": "strand","type": "nominal","domain": ["+", "-"],"range": ["#012DB8", "#BE1E2C"]},"visibility": [{"operation": "less-than","measure": "width","threshold": "|xe-x|","transitionPadding": 10,"target": "mark"}],"width": 400,"height": 80},{"title": "PLAC-seq (H3K4me3) Nott et al.","data": {"url": "https://server.gosling-lang.org/api/v1/tileset_info/?d=oligodendrocyte-plac-seq-bedpe","type": "beddb","genomicFields": [{"name": "start", "index": 1},{"name": "end", "index": 2}]},"mark": "withinLink","x": {"field": "start", "type": "genomic"},"xe": {"field": "end", "type": "genomic"},"y": {"flip": true},"strokeWidth": {"value": 1},"color": {"value": "none"},"stroke": {"value": "#F97E2A"},"opacity": {"value": 0.1},"overlayOnPreviousTrack": false,"width": 400,"height": 60},{"title": "","data": {"url": "https://server.gosling-lang.org/api/v1/tileset_info/?d=microglia-plac-seq-bedpe","type": "beddb","genomicFields": [{"name": "start", "index": 1},{"name": "end", "index": 2}]},"mark": "withinLink","x": {"field": "start", "type": "genomic"},"xe": {"field": "end", "type": "genomic"},"y": {"flip": true},"strokeWidth": {"value": 1},"color": {"value": "none"},"stroke": {"value": "#50ADF9"},"opacity": {"value": 0.1},"overlayOnPreviousTrack": true,"width": 400,"height": 60},{"title": "","data": {"url": "https://server.gosling-lang.org/api/v1/tileset_info/?d=neuron-plac-seq-bedpe","type": "beddb","genomicFields": [{"name": "start", "index": 1},{"name": "end", "index": 2}]},"mark": "withinLink","x": {"field": "start", "type": "genomic"},"xe": {"field": "end", "type": "genomic"},"y": {"flip": true},"strokeWidth": {"value": 1},"color": {"value": "none"},"stroke": {"value": "#7B0EDC"},"opacity": {"value": 0.1},"overlayOnPreviousTrack": true,"width": 400,"height": 60}]}]}
image

Mark Displacement

{"title": "Mark Displacement","subtitle": "Reposition marks to address visual overlaps using displacement options","spacing": 1,"centerRadius": 0.8,"xDomain": {"chromosome": "chr17", "interval": [43080000, 43120000]},"views": [{"alignment": "overlay","xDomain": {"chromosome": "chr3", "interval": [142500000, 143000000]},"data": {"url": "https://server.gosling-lang.org/api/v1/tileset_info/?d=transcript-hg38-beddb","type": "beddb","genomicFields": [{"index": 1, "name": "start"},{"index": 2, "name": "end"}],"valueFields": [{"index": 0, "name": "chr", "type": "nominal"},{"index": 5, "name": "strand", "type": "nominal"},{"index": 3, "name": "name", "type": "nominal"},{"index": 9, "name": "exon_start", "type": "nominal"},{"index": 10, "name": "exon_end", "type": "nominal"}]},"dataTransform": [{"type": "filter", "field": "type", "oneOf": ["gene"]},{"type": "displace","method": "pile","boundingBox": {"startField": "start", "endField": "end"},"newField": "row","maxRows": 15}],"title": "hg38 | Transcript (Max. 15 Rows)","tracks": [{"dataTransform": [{"type": "displace","method": "pile","boundingBox": {"startField": "start", "endField": "end"},"newField": "row","maxRows": 15},{"type": "filter", "field": "type", "oneOf": ["gene"]},{"type": "filter", "field": "strand", "oneOf": ["+"]}],"mark": "triangleRight","x": {"field": "end", "type": "genomic", "axis": "top"},"size": {"value": 15}},{"dataTransform": [{"type": "displace","method": "pile","boundingBox": {"startField": "start", "endField": "end"},"newField": "row","maxRows": 15},{"type": "filter", "field": "type", "oneOf": ["gene"]}],"mark": "text","text": {"field": "name", "type": "nominal"},"x": {"field": "start", "type": "genomic"},"xe": {"field": "end", "type": "genomic"},"style": {"dy": -10}},{"dataTransform": [{"type": "displace","method": "pile","boundingBox": {"startField": "start", "endField": "end"},"newField": "row","maxRows": 15},{"type": "filter", "field": "type", "oneOf": ["gene"]},{"type": "filter", "field": "strand", "oneOf": ["-"]}],"mark": "triangleLeft","x": {"field": "start", "type": "genomic"},"size": {"value": 15},"style": {"align": "right"}},{"dataTransform": [{"type": "displace","method": "pile","boundingBox": {"startField": "start", "endField": "end"},"newField": "row","maxRows": 15},{"type": "exonSplit","separator": ",","flag": {"field": "type", "value": "exon"},"fields": [{"field": "exon_start","type": "genomic","newField": "start","chrField": "chr"},{"field": "exon_end","type": "genomic","newField": "end","chrField": "chr"}]},{"type": "filter", "field": "type", "oneOf": ["exon"]}],"mark": "rect","size": {"value": 10},"x": {"field": "start", "type": "genomic"},"xe": {"field": "end", "type": "genomic"}},{"dataTransform": [{"type": "displace","method": "pile","boundingBox": {"startField": "start", "endField": "end"},"newField": "row","maxRows": 15},{"type": "filter", "field": "type", "oneOf": ["gene"]},{"type": "filter", "field": "strand", "oneOf": ["+"]}],"mark": "rule","x": {"field": "start", "type": "genomic"},"strokeWidth": {"value": 3},"xe": {"field": "end", "type": "genomic"},"style": {"linePattern": {"type": "triangleRight", "size": 5}}},{"dataTransform": [{"type": "displace","method": "pile","boundingBox": {"startField": "start", "endField": "end"},"newField": "row","maxRows": 15},{"type": "filter", "field": "type", "oneOf": ["gene"]},{"type": "filter", "field": "strand", "oneOf": ["-"]}],"mark": "rule","x": {"field": "start", "type": "genomic"},"strokeWidth": {"value": 3},"xe": {"field": "end", "type": "genomic"},"style": {"linePattern": {"type": "triangleRight", "size": 5}}}],"row": {"field": "row", "type": "nominal"},"color": {"field": "strand","type": "nominal","domain": ["+", "-"],"range": ["#0072B2", "#D45E00"]},"visibility": [{"operation": "less-than","measure": "width","threshold": "|xe-x|","transitionPadding": 10,"target": "mark"}],"opacity": {"value": 0.8},"style": {"outline": "black"},"width": 700,"height": 500},{"xDomain": {"chromosome": "chr2", "interval": [126800000, 127700000]},"tracks": [{"alignment": "overlay","title": "Likely Benign","data": {"url": "https://server.gosling-lang.org/api/v1/tileset_info/?d=clinvar-beddb","type": "beddb","genomicFields": [{"index": 1, "name": "start"},{"index": 2, "name": "end"}],"valueFields": [{"index": 7, "name": "significance", "type": "nominal"},{"type": "nominal", "index": 3, "name": "3"},{"type": "nominal", "index": 4, "name": "4"}]},"dataTransform": [{"type": "filter","field": "significance","oneOf": ["Likely_benign"]},{"type": "displace","boundingBox": {"startField": "start","endField": "end","padding": 5},"method": "spread","newField": "a"}],"tracks": [{"mark": "point","size": {"value": 4},"color": {"value": "#029F73"},"stroke": {"value": "black"},"strokeWidth": {"value": 1}},{"mark": "text","color": {"field": "3","type": "nominal","domain": ["A", "T", "G", "C"],"legend": true},"text": {"field": "3", "type": "nominal"},"y": {"value": 48}},{"mark": "text","color": {"field": "4","type": "nominal","domain": ["A", "T", "G", "C"]},"text": {"field": "4", "type": "nominal"},"y": {"value": 18}},{"mark": "text","color": {"value": "gray"},"text": {"value": "↓"},"y": {"value": 33}}],"x": {"field": "aStart", "type": "genomic"},"xe": {"field": "aEnd", "type": "genomic"},"y": {"value": 5},"opacity": {"value": 0.8},"style": {"inlineLegend": true},"width": 700,"height": 60},{"data": {"url": "https://server.gosling-lang.org/api/v1/tileset_info/?d=clinvar-beddb","type": "beddb","genomicFields": [{"index": 1, "name": "start"},{"index": 2, "name": "end"}],"valueFields": [{"index": 7, "name": "significance", "type": "nominal"}]},"dataTransform": [{"type": "filter","field": "significance","oneOf": ["Likely_benign"]},{"type": "displace","boundingBox": {"startField": "start","endField": "end","padding": 5},"method": "spread","newField": "a"}],"mark": "betweenLink","xe": {"field": "start", "type": "genomic"},"x": {"field": "aStart", "type": "genomic"},"color": {"value": "#029F73"},"stroke": {"value": "lightgrey"},"strokeWidth": {"value": 0.5},"opacity": {"value": 0.8},"width": 700,"height": 60},{"alignment": "overlay","tracks": [{"data": {"url": "https://server.gosling-lang.org/api/v1/tileset_info/?d=clinvar-beddb","type": "beddb","genomicFields": [{"index": 1, "name": "start"},{"index": 2, "name": "end"}],"valueFields": [{"index": 7, "name": "significance", "type": "nominal"}]},"dataTransform": [{"type": "filter","field": "significance","oneOf": ["Likely_benign"]}],"mark": "rect","color": {"value": "lightgray"},"stroke": {"value": "lightgray"},"strokeWidth": {"value": 0.5},"x": {"field": "start", "type": "genomic"},"xe": {"field": "end", "type": "genomic"},"opacity": {"value": 0.8}},{"data": {"url": "https://server.gosling-lang.org/api/v1/tileset_info/?d=gene-annotation","type": "beddb","genomicFields": [{"index": 1, "name": "start"},{"index": 2, "name": "end"}],"valueFields": [{"index": 5, "name": "strand", "type": "nominal"},{"index": 3, "name": "name", "type": "nominal"}],"exonIntervalFields": [{"index": 12, "name": "start"},{"index": 13, "name": "end"}]},"row": {"field": "strand","type": "nominal","domain": ["+", "-"]},"color": {"field": "strand","type": "nominal","domain": ["+", "-"],"range": ["#7585FF", "#FF8A85"]},"visibility": [{"operation": "less-than","measure": "width","threshold": "|xe-x|","transitionPadding": 10,"target": "mark"}],"opacity": {"value": 0.8},"dataTransform": [{"type": "filter", "field": "type", "oneOf": ["gene"]},{"type": "filter", "field": "strand", "oneOf": ["+"]}],"mark": "triangleRight","x": {"field": "end", "type": "genomic", "axis": "none"},"size": {"value": 15}},{"data": {"url": "https://server.gosling-lang.org/api/v1/tileset_info/?d=gene-annotation","type": "beddb","genomicFields": [{"index": 1, "name": "start"},{"index": 2, "name": "end"}],"valueFields": [{"index": 5, "name": "strand", "type": "nominal"},{"index": 3, "name": "name", "type": "nominal"}],"exonIntervalFields": [{"index": 12, "name": "start"},{"index": 13, "name": "end"}]},"row": {"field": "strand","type": "nominal","domain": ["+", "-"]},"color": {"field": "strand","type": "nominal","domain": ["+", "-"],"range": ["#7585FF", "#FF8A85"]},"visibility": [{"operation": "less-than","measure": "width","threshold": "|xe-x|","transitionPadding": 10,"target": "mark"}],"opacity": {"value": 0.8},"dataTransform": [{"type": "filter", "field": "type", "oneOf": ["gene"]}],"mark": "text","text": {"field": "name", "type": "nominal"},"x": {"field": "start", "type": "genomic"},"xe": {"field": "end", "type": "genomic"},"style": {"dy": -15}},{"data": {"url": "https://server.gosling-lang.org/api/v1/tileset_info/?d=gene-annotation","type": "beddb","genomicFields": [{"index": 1, "name": "start"},{"index": 2, "name": "end"}],"valueFields": [{"index": 5, "name": "strand", "type": "nominal"},{"index": 3, "name": "name", "type": "nominal"}],"exonIntervalFields": [{"index": 12, "name": "start"},{"index": 13, "name": "end"}]},"row": {"field": "strand","type": "nominal","domain": ["+", "-"]},"color": {"field": "strand","type": "nominal","domain": ["+", "-"],"range": ["#7585FF", "#FF8A85"]},"visibility": [{"operation": "less-than","measure": "width","threshold": "|xe-x|","transitionPadding": 10,"target": "mark"}],"opacity": {"value": 0.8},"dataTransform": [{"type": "filter", "field": "type", "oneOf": ["gene"]},{"type": "filter", "field": "strand", "oneOf": ["-"]}],"mark": "triangleLeft","x": {"field": "start", "type": "genomic"},"size": {"value": 15},"style": {"align": "right"}},{"data": {"url": "https://server.gosling-lang.org/api/v1/tileset_info/?d=gene-annotation","type": "beddb","genomicFields": [{"index": 1, "name": "start"},{"index": 2, "name": "end"}],"valueFields": [{"index": 5, "name": "strand", "type": "nominal"},{"index": 3, "name": "name", "type": "nominal"}],"exonIntervalFields": [{"index": 12, "name": "start"},{"index": 13, "name": "end"}]},"row": {"field": "strand","type": "nominal","domain": ["+", "-"]},"color": {"field": "strand","type": "nominal","domain": ["+", "-"],"range": ["#7585FF", "#FF8A85"]},"visibility": [{"operation": "less-than","measure": "width","threshold": "|xe-x|","transitionPadding": 10,"target": "mark"}],"opacity": {"value": 0.8},"dataTransform": [{"type": "filter", "field": "type", "oneOf": ["exon"]}],"mark": "rect","x": {"field": "start", "type": "genomic"},"size": {"value": 15},"xe": {"field": "end", "type": "genomic"}},{"data": {"url": "https://server.gosling-lang.org/api/v1/tileset_info/?d=gene-annotation","type": "beddb","genomicFields": [{"index": 1, "name": "start"},{"index": 2, "name": "end"}],"valueFields": [{"index": 5, "name": "strand", "type": "nominal"},{"index": 3, "name": "name", "type": "nominal"}],"exonIntervalFields": [{"index": 12, "name": "start"},{"index": 13, "name": "end"}]},"row": {"field": "strand","type": "nominal","domain": ["+", "-"]},"color": {"field": "strand","type": "nominal","domain": ["+", "-"],"range": ["#7585FF", "#FF8A85"]},"visibility": [{"operation": "less-than","measure": "width","threshold": "|xe-x|","transitionPadding": 10,"target": "mark"}],"opacity": {"value": 0.8},"dataTransform": [{"type": "filter", "field": "type", "oneOf": ["gene"]},{"type": "filter", "field": "strand", "oneOf": ["+"]}],"mark": "rule","x": {"field": "start", "type": "genomic"},"strokeWidth": {"value": 3},"xe": {"field": "end", "type": "genomic"},"style": {"linePattern": {"type": "triangleRight", "size": 5}}},{"data": {"url": "https://server.gosling-lang.org/api/v1/tileset_info/?d=gene-annotation","type": "beddb","genomicFields": [{"index": 1, "name": "start"},{"index": 2, "name": "end"}],"valueFields": [{"index": 5, "name": "strand", "type": "nominal"},{"index": 3, "name": "name", "type": "nominal"}],"exonIntervalFields": [{"index": 12, "name": "start"},{"index": 13, "name": "end"}]},"row": {"field": "strand","type": "nominal","domain": ["+", "-"]},"color": {"field": "strand","type": "nominal","domain": ["+", "-"],"range": ["#7585FF", "#FF8A85"]},"visibility": [{"operation": "less-than","measure": "width","threshold": "|xe-x|","transitionPadding": 10,"target": "mark"}],"opacity": {"value": 0.8},"dataTransform": [{"type": "filter", "field": "type", "oneOf": ["gene"]},{"type": "filter", "field": "strand", "oneOf": ["-"]}],"mark": "rule","x": {"field": "start", "type": "genomic"},"strokeWidth": {"value": 3},"xe": {"field": "end", "type": "genomic"},"style": {"linePattern": {"type": "triangleLeft", "size": 5}}}],"width": 700,"height": 100}]},{"tracks": [{"data": {"url": "https://server.gosling-lang.org/api/v1/tileset_info/?d=clinvar-beddb","type": "beddb","genomicFields": [{"index": 1, "name": "start"},{"index": 2, "name": "end"}],"valueFields": [{"index": 7, "name": "significance", "type": "nominal"}]},"displacement": {"type": "pile", "padding": 3.5},"mark": "point","x": {"field": "start", "type": "genomic"},"xe": {"field": "end", "type": "genomic"},"size": {"value": 3},"color": {"field": "significance","type": "nominal","domain": ["Pathogenic","Pathogenic/Likely_pathogenic","Likely_pathogenic","Uncertain_significance","Likely_benign","Benign/Likely_benign","Benign"],"range": ["#CB3B8C","#CB71A3","#CB96B3","gray","#029F73","#5A9F8C","#5A9F8C"],"legend": true},"width": 700,"height": 260}]}],"style": {"outlineWidth": 0}}
image

Observations

Based on the flame charts, we observe three main bottlenecks:

  1. Redrawing over and over
  2. Data transformations - converting a data into a form that that makes it ready to visualize. This involves use of
  3. Creating GoslingTrackModel over over again

Reduce redrawing

Redrawing everything to the same Graphics object is expensive. There are several strategies to overcome this

  • Stretch the Graphics object everything is drawn to. This was implemented in perf(core): stretch certain marks instead of redraw #1018. However, this strategy does not work well for shapes that do not have right angle corners, since only the x-direction gets stretched.
  • Draw everything as a Sprite and translate the Sprites on zoom. Compared to redrawing at every frame, translating Sprites is much more performant according to my testing.

Initialize GoslingTrackModel only when needed

GoslingTrackModels are reinitialized every time draw() is called. However, it only changes when the data, spec, or theme changes. We need to persist the models unless the data, spec, or theme changes.

@etowahadams etowahadams added the enhancement New feature or request label Jan 22, 2024
@etowahadams
Copy link
Contributor Author

Optimizing the point mark: 4.2X speedup

Spec:

{"layout": "linear","arrangement": "vertical","centerRadius": 0.8,"xDomain": {"chromosome": "chr1", "interval": [1, 3000500]},"views": [{"tracks": [{"id": "track-6","data": {"url": "https://server.gosling-lang.org/api/v1/tileset_info/?d=cistrome-multivec","type": "multivec","row": "sample","column": "position","value": "peak","categories": ["sample 1", "sample 2", "sample 3", "sample 4"]},"mark": "point","x": {"field": "position", "type": "genomic", "axis": "top"},"y": {"field": "peak", "type": "quantitative", "grid": true},"size": {"field": "peak", "type": "quantitative"},"color": {"field": "sample", "type": "nominal", "legend": true},"opacity": {"value": 0.5},"tooltip": [{"field": "start", "type": "genomic", "alt": "Start Position"},{"field": "end", "type": "genomic", "alt": "End Position"},{"field": "peak","type": "quantitative","alt": "Value","format": ".2"},{"field": "sample", "type": "nominal", "alt": "Sample"}],"width": 600,"height": 130}]}]}
image

Stack charts

Before: 5.5 ms to draw a frame
image

After: 1.3 ms to draw, or a 4.2X speedup
image

Frame charts (firefox)

image

After
image

Changes:

  • Persist GoslingTrackModel between draws
  • Looking up values using encodedPIXIvalues is expensive -> instead look up once and cache the results in GoslingTrackModel
  • Similarly, create UUIDs for each data point once and store with the data in GoslingTrackModel
  • Access the scale in the tile directly

How does draw time scale with the number of tracks?

Theoretically, it should take 1.3 ms to draw each track. Does draw time scale linearly with the number of tracks? Yes, but not with the relation that we want. Specifically, it draws 2x-1 times more than it needs to.

For example, here a visualization with 3 tracks. We expect each track to be drawn only once (3 total calls to draw) but instead we see 5.

image

Overall, this amounts in the following relationship:

image

@etowahadams etowahadams linked a pull request Feb 10, 2024 that will close this issue
5 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant