genome-browser.ts 3.31 KB
Newer Older
1
import GeneComponent from "./sequence/gene";
2
3
import GenomeAxis from "./axis/genome-axis";
import BrushableGenomeAxis from "./axis/brushable-genome-axis";
4
5
// D3
import { select, Selection } from "d3-selection";
6
7
import { drag } from "d3-drag";

8
//types
9
import { GeneData, GenomeBrowserData, GenericAxisData, BrushableAxisData } from "../types";
10
11
12
13



export default function () {
14
  const selectedChromosomeAxis = GenomeAxis();
15
  const geneComponent = GeneComponent();
16
17
18
  const wholeChromosomeAxis = BrushableGenomeAxis();
  let width = 900;
  let genomesBrowserU: Selection<SVGElement, GenomeBrowserData, SVGElement, any> | null = null;
19
20
21

  function genomeBrowser(
    _selection: Selection<SVGElement, Array<GenomeBrowserData>, HTMLElement, any>,
22
    w: number,
23
24
    height: number
  ) {
25
    width = w;
26
27
28
    _selection.each(function (_data: Array<GenomeBrowserData>) {
      const container = select(this);
      const genomeBrowser = container
Remi  PLANEL's avatar
Remi PLANEL committed
29
        .selectAll<SVGElement, GenomeBrowserData>(".genome-browser")
30
31
32
        .data(_data);

      //ENTER
Remi  PLANEL's avatar
Remi PLANEL committed
33
      const genomeBrowserE = genomeBrowser
34
        .enter()
Remi  PLANEL's avatar
Remi PLANEL committed
35
        .append<SVGElement>("g")
36
37
        .classed("genome-browser", true);

Remi  PLANEL's avatar
Remi PLANEL committed
38
39
      genomeBrowserE.append("rect")
        .classed("genome-browser-background", true);
40
41


42
      genomeBrowserE.append("g").classed("chromosome-axis", true);
43
      genomeBrowserE.append("g").classed("selected-chromosome", true);
Remi  PLANEL's avatar
Remi PLANEL committed
44
45
      genomeBrowserE.append("g").classed("axis", true);
      genomeBrowserE.append("g").classed("genes", true);
46
47
48
49
50

      //EXIT
      genomeBrowser.exit().remove();

      //UPDATE
51
      genomesBrowserU = genomeBrowser.merge(genomeBrowserE);
52
53
54
      genomesBrowserU
        .select<SVGRectElement>("rect.genome-browser-background")
        .attr("width", width)
55
56
        .attr("height", height)
        .call(
57
          drag<SVGRectElement, GenomeBrowserData>()
Remi  PLANEL's avatar
Remi PLANEL committed
58
59
            .on("start", (d: GenomeBrowserData) => {

60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
              if (d.eventHandler) {
                d.eventHandler.dragstarted(this);
              }
            })
            .on("drag", d => {
              if (d.eventHandler) {
                d.eventHandler.dragged();
              }
            })
            .on("end", d => {
              if (d.eventHandler) {
                d.eventHandler.dragended(this);
              }
            })
        );
75
76
77
78
79
80
81
82
83
      genomesBrowserU.each(function (data) {
        const { chromosome: { genes }, axis: { chromosome, global } } = data;
        updateWholeChromosomeAxis(global);
        updateSelectedChromosome(chromosome, genes);
      });
    });
  }
  function updateSelectedChromosome(axis: GenericAxisData, genes: GeneData[]) {
    if (genomesBrowserU !== null) {
84
85
      genomesBrowserU
        .select<SVGElement>("g.axis")
86
87
        .datum(axis)
        .call(selectedChromosomeAxis, width, 70);
88
89
90

      genomesBrowserU
        .select<SVGElement>(".genes")
91
        .attr("transform", "translate(0, 80)")
92
93
94
95
        .datum(genes)
        .call(geneComponent, selectedChromosomeAxis.scale(), 30)
    }
  };
96

97
98
99
100
101
102
103
  function updateWholeChromosomeAxis(axis: BrushableAxisData) {
    if (genomesBrowserU) {
      genomesBrowserU
        .select<SVGElement>("g.chromosome-axis")
        .datum(({ axis: { global } }) => global)
        .call(wholeChromosomeAxis, width, 0);
    }
104
  }
105
106

  genomeBrowser.updateSelectedChromosome = updateSelectedChromosome;
107
108
109
  return genomeBrowser;
}

110
111