sequenceserver 3.1.3 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/lib/sequenceserver/api_errors.rb +18 -0
  3. data/lib/sequenceserver/blast/hit.rb +1 -2
  4. data/lib/sequenceserver/blast/job.rb +15 -5
  5. data/lib/sequenceserver/blast/report.rb +5 -1
  6. data/lib/sequenceserver/database.rb +5 -1
  7. data/lib/sequenceserver/job.rb +26 -10
  8. data/lib/sequenceserver/makeblastdb.rb +2 -1
  9. data/lib/sequenceserver/routes.rb +37 -12
  10. data/lib/sequenceserver/version.rb +1 -1
  11. data/lib/sequenceserver/zip_file_generator.rb +1 -1
  12. data/public/404.html +8 -16
  13. data/public/css/app.css +794 -111
  14. data/public/css/app.min.css +1 -1
  15. data/public/css/sequenceserver.min.css +1 -8
  16. data/public/js/circos.js +103 -96
  17. data/public/{packages/circosJS@1.7.0.js → js/circosjs.js} +156 -778
  18. data/public/js/cloud_share_modal.js +55 -58
  19. data/public/js/collapse_preferences.js +13 -15
  20. data/public/js/databases.js +4 -3
  21. data/public/js/databases_tree.js +51 -30
  22. data/public/js/error_modal.js +35 -22
  23. data/public/js/exporter.js +2 -0
  24. data/public/js/form.js +43 -7
  25. data/public/js/grapher.js +94 -92
  26. data/public/js/hit.js +21 -19
  27. data/public/js/hits.js +45 -38
  28. data/public/js/hits_overview.js +8 -27
  29. data/public/js/hsp.js +140 -144
  30. data/public/js/jquery_world.js +24 -15
  31. data/public/js/kablammo.js +14 -10
  32. data/public/js/length_distribution.js +23 -37
  33. data/public/js/null_plugins/report_plugins.js +3 -5
  34. data/public/js/options.js +17 -19
  35. data/public/js/query.js +36 -35
  36. data/public/js/report/alignment_results.js +18 -0
  37. data/public/js/report/graphical_overview.js +38 -0
  38. data/public/js/report/report_header.js +28 -0
  39. data/public/js/report/run_summary.js +43 -0
  40. data/public/js/report.js +62 -102
  41. data/public/js/report_root.js +3 -3
  42. data/public/js/search.js +5 -2
  43. data/public/js/search_button.js +85 -78
  44. data/public/js/sequence.js +11 -22
  45. data/public/js/sequence_modal.js +38 -37
  46. data/public/js/share_url.js +5 -5
  47. data/public/js/sidebar.js +148 -86
  48. data/public/js/svgExporter.js +8 -3
  49. data/public/js/tests/form.spec.js +1 -1
  50. data/public/js/tests/visualisation_helpers.spec.js +28 -0
  51. data/public/js/visualisation_helpers.js +24 -27
  52. data/public/sequenceserver-report.min.js +1 -1
  53. data/public/sequenceserver-report.min.js.LICENSE.txt +1 -88
  54. data/public/sequenceserver-report.min.js.map +1 -1
  55. data/public/sequenceserver-search.min.js +1 -1
  56. data/public/sequenceserver-search.min.js.LICENSE.txt +0 -30
  57. data/public/sequenceserver-search.min.js.map +1 -1
  58. data/views/error.erb +1 -1
  59. data/views/layout.erb +123 -130
  60. data/views/report.erb +3 -2
  61. data/views/search.erb +10 -14
  62. metadata +13 -26
  63. data/public/css/fonts.css +0 -31
  64. data/public/css/grapher.css +0 -670
  65. data/public/css/sequenceserver.css +0 -509
  66. data/public/vendor/github/mbostock/d3@3.5.6/d3.js +0 -9506
  67. data/public/vendor/github/mbostock/d3@3.5.6.js +0 -1
  68. data/views/search_layout.erb +0 -153
data/public/js/hsp.js CHANGED
@@ -1,72 +1,48 @@
1
- import React, { createRef } from "react";
1
+ import React, { useState, createRef, useEffect } from "react";
2
+ import useDetectPrint from "react-detect-print";
2
3
  import _ from "underscore";
3
4
 
4
5
  import Utils from "./utils";
5
6
  import * as Helpers from "./visualisation_helpers";
6
7
 
7
- var HSPComponents = {};
8
-
9
8
  /**
10
9
  * Alignment viewer.
11
10
  */
12
- export default class HSP extends React.Component {
13
- constructor(props) {
14
- super(props);
15
- this.hsp = props.hsp;
16
- this.hspRef = createRef();
17
- }
18
-
19
- domID() {
20
- return (
21
- "Query_" +
22
- this.props.query.number +
23
- "_hit_" +
24
- this.props.hit.number +
25
- "_" +
26
- this.props.hsp.number
27
- );
28
- }
29
-
30
- hitDOM_ID() {
31
- return "Query_" + this.props.query.number + "_hit_" + this.props.hit.number;
32
- }
33
-
34
- // Renders pretty formatted alignment.
35
- render() {
36
- return (
37
- <div
38
- className="hsp"
39
- id={this.domID()}
40
- ref={this.hspRef}
41
- data-parent-hit={this.hitDOM_ID()}
42
- >
43
- <p className="pre-reset hsp-stats">
44
- {this.props.showHSPNumbers &&
45
- `${Helpers.toLetters(this.hsp.number)}. `}
46
- {this.hspStats().map((s, i) => (
47
- <span key={i}>{s}</span>
48
- ))}
49
- </p>
50
- {this.hspLines()}
51
- </div>
52
- );
11
+ // export default class HSP extends React.Component {
12
+ export default function HSP(props) {
13
+ const hsp = props.hsp;
14
+ const hspRef = createRef();
15
+ const printing = useDetectPrint();
16
+ const [chars, setChars] = useState(0)
17
+ const [width, setWidth] = useState(window.innerWidth);
18
+
19
+ const domID = () => {
20
+ const { query, hit, hsp } = props;
21
+ return `Query_${query.number}_hit_${hit.number}_${hsp.number}`;
53
22
  }
54
23
 
55
- componentDidMount() {
56
- HSPComponents[this.domID()] = this;
57
- this.draw();
24
+ const hitDOM_ID = () => {
25
+ return "Query_" + props.query.number + "_hit_" + props.hit.number;
58
26
  }
59
27
 
60
- draw() {
61
- var charWidth = this.props.getCharacterWidth();
62
- var containerWidth = $(this.hspRef.current).width();
63
- this.chars = Math.floor((containerWidth - 4) / charWidth);
64
- this.forceUpdate();
65
- }
66
-
67
- // See Query.shouldComponentUpdate. The same applies for hsp.
68
- shouldComponentUpdate() {
69
- return !this.props.hsp;
28
+ useEffect(() => {
29
+ // Attach a debounced listener to handle window resize events
30
+ // Updates the width state with the current window width, throttled to run at most once every 125ms
31
+ const handleResize = _.debounce(() => setWidth(window.innerWidth), 125);
32
+ window.addEventListener("resize", handleResize);
33
+
34
+ // TODO: print handler
35
+ draw();
36
+ }, [])
37
+
38
+ useEffect(() => {
39
+ draw(printing);
40
+ }, [printing, width])
41
+
42
+ const draw = (printing = false) => {
43
+ const charWidth = props.getCharacterWidth();
44
+ const containerWidth = printing ? 900 : $(hspRef.current).width();
45
+ setChars(Math.floor((containerWidth - 4) / charWidth))
70
46
  }
71
47
 
72
48
  /**
@@ -77,141 +53,155 @@ export default class HSP extends React.Component {
77
53
  * We cannot return a string from this method otherwise we wouldn't be able
78
54
  * to use JSX elements to format text (like, superscript).
79
55
  */
80
- hspStats() {
56
+ const hspStats = () => {
81
57
  // An array to hold text or span elements that make up the line.
82
58
  let line = [];
83
59
 
84
60
  // Bit score and total score.
85
61
  line.push(
86
- `Score: ${Utils.inTwoDecimal(this.hsp.bit_score)} (${this.hsp.score}), `
62
+ `Score: ${Utils.inTwoDecimal(hsp.bit_score)} (${hsp.score}), `
87
63
  );
88
64
 
89
65
  // E value
90
66
  line.push("E value: ");
91
- line.push(Utils.inExponential(this.hsp.evalue));
67
+ line.push(Utils.inExponential(hsp.evalue));
92
68
  line.push(", ");
93
69
 
94
70
  // Identity
95
71
  line.push([
96
72
  `Identity: ${Utils.inFraction(
97
- this.hsp.identity,
98
- this.hsp.length
99
- )} (${Utils.inPercentage(this.hsp.identity, this.hsp.length)}), `,
73
+ hsp.identity,
74
+ hsp.length
75
+ )} (${Utils.inPercentage(hsp.identity, hsp.length)}), `,
100
76
  ]);
101
77
 
102
78
  // Positives (for protein alignment).
103
79
  if (
104
- this.props.algorithm === "blastp" ||
105
- this.props.algorithm === "blastx" ||
106
- this.props.algorithm === "tblastn" ||
107
- this.props.algorithm === "tblastx"
80
+ props.algorithm === "blastp" ||
81
+ props.algorithm === "blastx" ||
82
+ props.algorithm === "tblastn" ||
83
+ props.algorithm === "tblastx"
108
84
  ) {
109
85
  line.push(
110
86
  `Positives: ${Utils.inFraction(
111
- this.hsp.positives,
112
- this.hsp.length
113
- )} (${Utils.inPercentage(this.hsp.positives, this.hsp.length)}), `
87
+ hsp.positives,
88
+ hsp.length
89
+ )} (${Utils.inPercentage(hsp.positives, hsp.length)}), `
114
90
  );
115
91
  }
116
92
 
117
93
  // Gaps
118
94
  line.push(
119
95
  `Gaps: ${Utils.inFraction(
120
- this.hsp.gaps,
121
- this.hsp.length
122
- )} (${Utils.inPercentage(this.hsp.gaps, this.hsp.length)})`
96
+ hsp.gaps,
97
+ hsp.length
98
+ )} (${Utils.inPercentage(hsp.gaps, hsp.length)})`
123
99
  );
124
100
 
125
101
  // Query coverage
126
102
  //line.push(`Query coverage: ${this.hsp.qcovhsp}%, `)
127
103
 
128
- switch (this.props.algorithm) {
104
+ switch (props.algorithm) {
129
105
  case "tblastx":
130
106
  line.push(
131
- `, Frame: ${Utils.inFraction(this.hsp.qframe, this.hsp.sframe)}`
107
+ `, Frame: ${Utils.inFraction(hsp.qframe, hsp.sframe)}`
132
108
  );
133
109
  break;
134
110
  case "blastn":
135
111
  line.push(
136
- `, Strand: ${this.hsp.qframe > 0 ? "+" : "-"} / ${
137
- this.hsp.sframe > 0 ? "+" : "-"
112
+ `, Strand: ${hsp.qframe > 0 ? "+" : "-"} / ${
113
+ hsp.sframe > 0 ? "+" : "-"
138
114
  }`
139
115
  );
140
116
  break;
141
117
  case "blastx":
142
- line.push(`, Query Frame: ${this.hsp.qframe}`);
118
+ line.push(`, Query Frame: ${hsp.qframe}`);
143
119
  break;
144
120
  case "tblastn":
145
- line.push(`, Hit Frame: ${this.hsp.sframe}`);
121
+ line.push(`, Hit Frame: ${hsp.sframe}`);
146
122
  break;
147
123
  }
148
124
 
149
125
  return line;
150
126
  }
151
127
 
128
+
129
+ // Width of the coordinate part of hsp lines. Essentially the length of
130
+ // the largest coordinate.
131
+ const hspLinesWidth = () => {
132
+ return _.max(
133
+ _.map(
134
+ [hsp.qstart, hsp.qend, hsp.sstart, hsp.send],
135
+ (n) => {
136
+ return n.toString().length;
137
+ }
138
+ )
139
+ );
140
+ }
141
+
152
142
  /**
153
143
  * Returns array of pre tags containing the three query, middle, and subject
154
144
  * lines that together comprise one 'rendered line' of HSP.
155
145
  */
156
- hspLines() {
146
+ const hspLines = () => {
157
147
  // Space reserved for showing coordinates
158
- var width = this.width();
148
+ const width = hspLinesWidth();
159
149
 
160
150
  // Number of residues we can draw per line is the total number of
161
151
  // characters we can have in a line minus space required to show left
162
152
  // and right coordinates minus 10 characters reserved for displaying
163
153
  // the words Query, Subject and three blank spaces per line.
164
- var chars = this.chars - 2 * width - 10;
154
+ const adjustedLineWidth = chars - 2 * width - 10;
165
155
 
166
156
  // Number of lines of pairwise-alignment (i.e., each line consists of 3
167
157
  // lines). We draw as many pre tags.
168
- var lines = Math.ceil(this.hsp.length / chars);
158
+ const lines = Math.ceil(hsp.length / adjustedLineWidth);
169
159
 
170
- var pp = [];
171
- var nqseq = this.nqseq();
172
- var nsseq = this.nsseq();
160
+ let pp = [];
161
+ let nqseq = getNqseq();
162
+ let nsseq = getNsseq();
173
163
  for (let i = 1; i <= lines; i++) {
174
- let seq_start_index = chars * (i - 1);
175
- let seq_stop_index = seq_start_index + chars;
164
+ let seq_start_index = adjustedLineWidth * (i - 1);
165
+ let seq_stop_index = seq_start_index + adjustedLineWidth;
176
166
 
177
167
  let lqstart = nqseq;
178
- let lqseq = this.hsp.qseq.slice(seq_start_index, seq_stop_index);
168
+ let lqseq = hsp.qseq.slice(seq_start_index, seq_stop_index);
179
169
  let lqend =
180
170
  nqseq +
181
171
  (lqseq.length - lqseq.split("-").length) *
182
- this.qframe_unit() *
183
- this.qframe_sign();
184
- nqseq = lqend + this.qframe_unit() * this.qframe_sign();
172
+ qframe_unit() *
173
+ qframe_sign();
174
+ nqseq = lqend + qframe_unit() * qframe_sign();
185
175
 
186
- let lmseq = this.hsp.midline.slice(seq_start_index, seq_stop_index);
176
+ let lmseq = hsp.midline.slice(seq_start_index, seq_stop_index);
187
177
 
188
178
  let lsstart = nsseq;
189
- let lsseq = this.hsp.sseq.slice(seq_start_index, seq_stop_index);
179
+ let lsseq = hsp.sseq.slice(seq_start_index, seq_stop_index);
190
180
  let lsend =
191
181
  nsseq +
192
182
  (lsseq.length - lsseq.split("-").length) *
193
- this.sframe_unit() *
194
- this.sframe_sign();
195
- nsseq = lsend + this.sframe_unit() * this.sframe_sign();
183
+ sframe_unit() *
184
+ sframe_sign();
185
+ nsseq = lsend + sframe_unit() * sframe_sign();
196
186
 
197
187
  pp.push(
198
- <pre key={this.hsp.number + "," + i} className="pre-reset hsp-lines">
199
- <span className="hsp-coords">
200
- {`Query ${this.formatCoords(lqstart, width)} `}
188
+ <pre key={hsp.number + "," + i} className="pre-item m-0 p-0 rounded-none border-0 bg-inherit whitespace-pre-wrap break-keep mt-1 tracking-wider">
189
+ <span className="text-gray-500">
190
+ {`Query ${formatCoords(lqstart, width)} `}
201
191
  </span>
202
192
  <span>{lqseq}</span>
203
- <span className="hsp-coords">{` ${lqend}`}</span>
193
+ <span className="text-gray-500">{` ${lqend}`}</span>
204
194
  <br />
205
- <span className="hsp-coords">
206
- {`${this.formatCoords("", width + 8)} `}
195
+ <span className="text-gray-500">
196
+ {`${formatCoords("", width + 8)} `}
207
197
  </span>
208
198
  <span>{lmseq}</span>
209
199
  <br />
210
- <span className="hsp-coords">
211
- {`Subject ${this.formatCoords(lsstart, width)} `}
200
+ <span className="text-gray-500">
201
+ {`Subject ${formatCoords(lsstart, width)} `}
212
202
  </span>
213
203
  <span>{lsseq}</span>
214
- <span className="hsp-coords">{` ${lsend}`}</span>
204
+ <span className="text-gray-500">{` ${lsend}`}</span>
215
205
  <br />
216
206
  </pre>
217
207
  );
@@ -220,35 +210,23 @@ export default class HSP extends React.Component {
220
210
  return pp;
221
211
  }
222
212
 
223
- // Width of the coordinate part of hsp lines. Essentially the length of
224
- // the largest coordinate.
225
- width() {
226
- return _.max(
227
- _.map(
228
- [this.hsp.qstart, this.hsp.qend, this.hsp.sstart, this.hsp.send],
229
- (n) => {
230
- return n.toString().length;
231
- }
232
- )
233
- );
234
- }
235
213
 
236
214
  // Alignment start coordinate for query sequence.
237
215
  //
238
216
  // This will be qstart or qend depending on the direction in which the
239
217
  // (translated) query sequence aligned.
240
- nqseq() {
241
- switch (this.props.algorithm) {
218
+ const getNqseq = () => {
219
+ switch (props.algorithm) {
242
220
  case "blastp":
243
221
  case "blastx":
244
222
  case "tblastn":
245
223
  case "tblastx":
246
- return this.hsp.qframe >= 0 ? this.hsp.qstart : this.hsp.qend;
224
+ return hsp.qframe >= 0 ? hsp.qstart : hsp.qend;
247
225
  case "blastn":
248
226
  // BLASTN is a bit weird in that, no matter which direction the query
249
227
  // sequence aligned in, qstart is taken as alignment start coordinate
250
228
  // for query.
251
- return this.hsp.qstart;
229
+ return hsp.qstart;
252
230
  }
253
231
  }
254
232
 
@@ -256,18 +234,18 @@ export default class HSP extends React.Component {
256
234
  //
257
235
  // This will be sstart or send depending on the direction in which the
258
236
  // (translated) subject sequence aligned.
259
- nsseq() {
260
- switch (this.props.algorithm) {
237
+ const getNsseq = () => {
238
+ switch (props.algorithm) {
261
239
  case "blastp":
262
240
  case "blastx":
263
241
  case "tblastn":
264
242
  case "tblastx":
265
- return this.hsp.sframe >= 0 ? this.hsp.sstart : this.hsp.send;
243
+ return hsp.sframe >= 0 ? hsp.sstart : hsp.send;
266
244
  case "blastn":
267
245
  // BLASTN is a bit weird in that, no matter which direction the
268
246
  // subject sequence aligned in, sstart is taken as alignment
269
247
  // start coordinate for subject.
270
- return this.hsp.sstart;
248
+ return hsp.sstart;
271
249
  }
272
250
  }
273
251
 
@@ -279,8 +257,8 @@ export default class HSP extends React.Component {
279
257
  //
280
258
  // This will be 1 or 3 depending on whether the query sequence was
281
259
  // translated or not.
282
- qframe_unit() {
283
- switch (this.props.algorithm) {
260
+ const qframe_unit = () => {
261
+ switch (props.algorithm) {
284
262
  case "blastp":
285
263
  case "blastn":
286
264
  case "tblastn":
@@ -302,8 +280,8 @@ export default class HSP extends React.Component {
302
280
  //
303
281
  // This will be 1 or 3 depending on whether the subject sequence was
304
282
  // translated or not.
305
- sframe_unit() {
306
- switch (this.props.algorithm) {
283
+ const sframe_unit = () => {
284
+ switch (props.algorithm) {
307
285
  case "blastp":
308
286
  case "blastx":
309
287
  case "blastn":
@@ -326,8 +304,8 @@ export default class HSP extends React.Component {
326
304
  //
327
305
  // This will be +1 or -1, depending on the direction in which the
328
306
  // (translated) query sequence aligned.
329
- qframe_sign() {
330
- return this.hsp.qframe >= 0 ? 1 : -1;
307
+ const qframe_sign = () => {
308
+ return hsp.qframe >= 0 ? 1 : -1;
331
309
  }
332
310
 
333
311
  // If we should add or subtract sframe_unit from sstart to arrive at send.
@@ -338,15 +316,15 @@ export default class HSP extends React.Component {
338
316
  //
339
317
  // This will be +1 or -1, depending on the direction in which the
340
318
  // (translated) subject sequence aligned.
341
- sframe_sign() {
342
- return this.hsp.sframe >= 0 ? 1 : -1;
319
+ const sframe_sign = () => {
320
+ return hsp.sframe >= 0 ? 1 : -1;
343
321
  }
344
322
 
345
323
  /**
346
324
  * Pad given coord with ' ' till its length == width. Returns undefined if
347
325
  * width is not supplied.
348
326
  */
349
- formatCoords(coord, width) {
327
+ const formatCoords = (coord, width) => {
350
328
  if (width) {
351
329
  let padding = width - coord.toString().length;
352
330
  return Array(padding + 1)
@@ -355,16 +333,34 @@ export default class HSP extends React.Component {
355
333
  }
356
334
  }
357
335
 
358
- spanCoords(text) {
359
- return <span className="hsp-coords">{text}</span>;
336
+ const spanCoords = (text) => {
337
+ return <span className="text-gray-700">{text}</span>;
360
338
  }
339
+
340
+ return (
341
+ <div
342
+ className="hsp pt-px pb-5 border-l-2 border-transparent pl-1 -ml-1"
343
+ id={domID()}
344
+ ref={hspRef}
345
+ data-parent-hit={hitDOM_ID()}
346
+ >
347
+ <p className="m-0 p-0 rounded-none border-0 bg-inherit whitespace-pre-wrap break-keep text-sm text-neutral-500 font-semibold tracking-wide">
348
+ {props.showHSPNumbers &&
349
+ `${Helpers.toLetters(hsp.number)}. `}
350
+ {hspStats().map((s, i) => (
351
+ <span key={i}>{s}</span>
352
+ ))}
353
+ </p>
354
+ {hspLines()}
355
+ </div>
356
+ );
361
357
  }
362
358
 
363
359
  // Redraw if window resized.
364
- $(window).resize(
365
- _.debounce(function () {
366
- _.each(HSPComponents, (comp) => {
367
- comp.draw();
368
- });
369
- }, 100)
370
- );
360
+ // $(window).resize(
361
+ // _.debounce(function () {
362
+ // _.each(HSPComponents, (comp) => {
363
+ // comp.draw();
364
+ // });
365
+ // }, 100)
366
+ // );
@@ -1,6 +1,5 @@
1
1
  import $ from 'jquery';
2
2
  import '../packages/jquery-ui@1.13.3';
3
- import 'bootstrap';
4
3
 
5
4
  global.$ = $;
6
5
  /**
@@ -44,22 +43,32 @@ global.$ = $;
44
43
  return this.prop('checked', false);
45
44
  };
46
45
 
47
-
48
46
  /**
49
- * Initialise Bootstrap tooltip on an element with presets. Takes title.
47
+ * Tooltip
50
48
  */
51
- $.fn._tooltip = $.fn.tooltip;
52
- $.fn.tooltip = function (options) {
53
- return this
54
- ._tooltip('destroy')
55
- ._tooltip($.extend({
56
- container: 'body',
57
- placement: 'bottom',
58
- delay: {
59
- show: 1000
60
- }
61
- }, options));
62
- };
49
+ $(document).tooltip({
50
+ position: {
51
+ my: 'center bottom-20',
52
+ at: 'center top',
53
+ using: function( position, feedback ) {
54
+ $(this).css(position);
55
+ $('<div>')
56
+ .addClass('arrow')
57
+ .addClass(feedback.vertical)
58
+ .addClass(feedback.horizontal)
59
+ .appendTo(this);
60
+ }
61
+ },
62
+ items: 'rect, .tooltip-item',
63
+ show: false,
64
+ hide: false,
65
+ content: function() {
66
+ var title = $(this).attr('title');
67
+ if (!title) return false;
68
+ var parsedHTML = $.parseHTML(title);
69
+ return parsedHTML;
70
+ }
71
+ });
63
72
 
64
73
  /**
65
74
  * Returns true / false if any modal is active.
@@ -1,4 +1,4 @@
1
- import d3 from 'd3';
1
+ import * as d3 from 'd3';
2
2
  import _ from 'underscore';
3
3
  import Grapher from 'grapher';
4
4
  import * as Helpers from './visualisation_helpers';
@@ -35,13 +35,13 @@ class Graph {
35
35
  }
36
36
 
37
37
  static dataName(props) {
38
- return 'Kablammo-'+props.query.id+'-'+props.hit.id;
38
+ return `Kablammo_query-${props.query.number}_${props.query.id}_${props.hit.id}`;
39
39
  }
40
40
 
41
41
  constructor($svgContainer, props) {
42
42
  this._zoom_scale_by = 1.4;
43
43
  this._padding_x = 12;
44
- this._padding_y = 50;
44
+ this._padding_y = 55;
45
45
 
46
46
  this._canvas_height = $svgContainer.height();
47
47
  this._canvas_width = $svgContainer.width();
@@ -84,7 +84,7 @@ class Graph {
84
84
  this.svgContainer_d3.insert('svg', ':first-child')
85
85
  .attr('height', this._canvas_height)
86
86
  .attr('width', this._canvas_width);
87
- this._svg.raw = this._svg.d3[0][0];
87
+ this._svg.raw = this._svg.d3._groups[0][0];
88
88
  this._render_graph();
89
89
  }
90
90
 
@@ -105,13 +105,17 @@ class Graph {
105
105
  _create_axis(scale, orientation, height, text_anchor, dx, dy, seq_type) {
106
106
  var formatter = Helpers.tick_formatter(scale, seq_type);
107
107
  var tvalues = scale.ticks();
108
+ var axis;
108
109
  tvalues.pop();
109
- var axis = d3.svg.axis()
110
- .ticks(this._axis_ticks)
111
- .scale(scale)
110
+ if (orientation === 'top') {
111
+ axis = d3.axisTop(scale)
112
+ } else {
113
+ axis = d3.axisBottom(scale)
114
+ }
115
+
116
+ axis.ticks(this._axis_ticks)
112
117
  .tickValues(tvalues.concat(scale.domain()))
113
118
  .tickFormat(formatter)
114
- .orient(orientation);
115
119
 
116
120
  var container = this._svg.d3.append('g')
117
121
  .attr('class', 'axis')
@@ -307,10 +311,10 @@ class Graph {
307
311
  subject_range.reverse();
308
312
  }
309
313
 
310
- var query_scale = d3.scale.linear()
314
+ var query_scale = d3.scaleLinear()
311
315
  .domain([1, this._query_length])
312
316
  .range(query_range);
313
- var subject_scale = d3.scale.linear()
317
+ var subject_scale = d3.scaleLinear()
314
318
  .domain([1, this._subject_length])
315
319
  .range(subject_range);
316
320
  query_scale.original_domain = query_scale.domain();