genome-browser.ts 2.69 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import { select, Selection } from "d3-selection"

import GeneComponent, { GeneData } from "./sequence/gene";
import GenomeAxis from "./sequence/genome-axis";
import { drag } from "d3-drag";



export interface GenomeBrowserData {
  width: number,
  genomeWindow: {
    center: number,
    size: number
  },
  eventHandler?: {
    dragstarted: (elem: SVGElement) => void,
    dragged: () => void,
    dragended: (elem: SVGElement) => void
  },
  currentMousePosition: number,
  genes: GeneData[],
  x: number,
  y: number
}


export default function () {
  const genomeAxis = GenomeAxis();
  const geneComponent = GeneComponent();

  function genomeBrowser(
    _selection: Selection<SVGElement, Array<GenomeBrowserData>, HTMLElement, any>,
    width: number,
    height: number
  ) {
    _selection.each(function (_data: Array<GenomeBrowserData>) {
      const container = select(this);
      const genomeBrowser = container
Remi  PLANEL's avatar
Remi PLANEL committed
39
        .selectAll<SVGElement, GenomeBrowserData>(".genome-browser")
40
41
42
        .data(_data);

      //ENTER
Remi  PLANEL's avatar
Remi PLANEL committed
43
      const genomeBrowserE = genomeBrowser
44
        .enter()
Remi  PLANEL's avatar
Remi PLANEL committed
45
        .append<SVGElement>("g")
46
47
        .classed("genome-browser", true);

Remi  PLANEL's avatar
Remi PLANEL committed
48
49
      genomeBrowserE.append("rect")
        .classed("genome-browser-background", true);
50
51


Remi  PLANEL's avatar
Remi PLANEL committed
52
53
      genomeBrowserE.append("g").classed("axis", true);
      genomeBrowserE.append("g").classed("genes", true);
54
55
56
57
58

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

      //UPDATE
Remi  PLANEL's avatar
Remi PLANEL committed
59
      const genomesBrowserU = genomeBrowser.merge(genomeBrowserE);
60
61
62
      genomesBrowserU
        .select<SVGRectElement>("rect.genome-browser-background")
        .attr("width", width)
Remi  PLANEL's avatar
Remi PLANEL committed
63
        .attr("height", height).call(
64
          drag<SVGRectElement, GenomeBrowserData>()
Remi  PLANEL's avatar
Remi PLANEL committed
65
66
            .on("start", (d: GenomeBrowserData) => {

67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
              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);
              }
            })
        );
      genomesBrowserU
        .select<SVGElement>("g.axis")
        .datum(({ genomeWindow: { center, size } }): [number, number] => getGenomeWindow(center, size))
        .call(genomeAxis, width, 0);

      genomesBrowserU
        .select<SVGElement>(".genes")
        .datum(({ genes }) => genes)
        .call(geneComponent, genomeAxis.scale(), 40)


    });
  }
  return genomeBrowser;
}


function getGenomeWindow(center: number, genomeWindowSize: number): [number, number] {
  const halfWindow = genomeWindowSize / 2;
  return [center - halfWindow, center + halfWindow]

}