Skip to content

Commit 05f2b44

Browse files
committed
Working MultiDataRectPlot and updated MultiDataTrackPlot. Fixed hidden SVG getBBox bug.
1 parent 9916782 commit 05f2b44

File tree

8 files changed

+209
-197
lines changed

8 files changed

+209
-197
lines changed

documentation.yml

+24-19
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,41 @@
11
toc:
2-
- name: Vue Components
2+
- name: Plot Components
3+
- mixin
34
- BarPlot
4-
- ScatterPlot
5-
- StackedBarPlot
65
- BoxPlot
7-
- MultiBoxPlot
8-
- TrackPlot
9-
- RectPlot
10-
- MultiTrackPlot
11-
- MultiDataTrackPlot
12-
- HierarchicalMultiTrackPlot
13-
- GenomeScatterPlot
14-
- GenomeTrackPlot
6+
- CountBarPlot
7+
- DoubleStratifiedBoxPlot
8+
- DoubleStratifiedScatterPlot
9+
- DoubleStratifiedSinaPlot
1510
- GenomeMultiTrackPlot
11+
- GenomeScatterPlot
1612
- GenomeStackedBarPlot
13+
- GenomeTrackPlot
14+
- HierarchicalMultiTrackPlot
15+
- MultiBoxPlot
16+
- MultiDataRectPlot
17+
- MultiDataTrackPlot
18+
- MultiTrackPlot
19+
- RectPlot
20+
- ScatterPlot
21+
- StackedBarPlot
1722
- StratifiedBoxPlot
18-
- DoubleStratifiedBoxPlot
19-
- StratifiedSinaPlot
20-
- DoubleStratifiedSinaPlot
21-
- StratifiedScatterPlot
22-
- DoubleStratifiedScatterPlot
2323
- StratifiedKaplanMeierPlot
24-
- CountBarPlot
25-
- mixin
24+
- StratifiedScatterPlot
25+
- StratifiedSinaPlot
26+
- TrackPlot
27+
- name: Axis Components
2628
- Axis
2729
- GenomeAxis
2830
- DendrogramAxis
31+
- name: Container Components
2932
- PlotContainer
30-
- SortOptions
33+
- name: Legend Components
3134
- CategoricalLegend
3235
- ContinuousLegend
3336
- Legend
37+
- name: Other Components
38+
- SortOptions
3439
- name: Data
3540
- DataContainer
3641
- name: History

examples-src/App.vue

+40-2
Original file line numberDiff line numberDiff line change
@@ -909,9 +909,9 @@
909909
<h3>&lt;MultiDataRectPlot/&gt; with value labels</h3>
910910
<PlotContainer
911911
:pWidth="200"
912-
:pHeight="80"
912+
:pHeight="60"
913913
:pMarginTop="5"
914-
:pMarginLeft="140"
914+
:pMarginLeft="100"
915915
:pMarginRight="40"
916916
:pMarginBottom="50"
917917
:showDownloadButton="true"
@@ -942,6 +942,44 @@
942942
/>
943943
</PlotContainer>
944944

945+
<h3>&lt;MultiDataTrackPlot/&gt;</h3>
946+
<PlotContainer
947+
:pWidth="700"
948+
:pHeight="60"
949+
:pMarginTop="10"
950+
:pMarginLeft="100"
951+
:pMarginRight="10"
952+
:pMarginBottom="180"
953+
:showDownloadButton="true"
954+
>
955+
<Axis
956+
slot="axisLeft"
957+
variable="multi_rect_plot_scale"
958+
side="left"
959+
:disableBrushing="true"
960+
:tickRotation="0"
961+
:getScale="getScale"
962+
:getStack="getStack"
963+
/>
964+
<MultiDataTrackPlot
965+
slot="plot"
966+
:dataArray="['clinical_data', 'clinical_data']"
967+
:cArray="['age', 'sex']"
968+
x="sample_id"
969+
:getData="getData"
970+
:getScale="getScale"
971+
:clickHandler="exampleClickHandler"
972+
/>
973+
<Axis
974+
slot="axisBottom"
975+
variable="sample_id"
976+
side="bottom"
977+
:tickRotation="-65"
978+
:getScale="getScale"
979+
:getStack="getStack"
980+
/>
981+
</PlotContainer>
982+
945983
<h3>&lt;StratifiedKaplanMeierPlot/&gt;</h3>
946984
<PlotContainer
947985
:pWidth="500"

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "vueplotlib",
3-
"version": "1.10.4",
3+
"version": "1.11.0",
44
"private": false,
55
"scripts": {
66
"serve": "vue-cli-service serve --open ./examples-src/index.js",

src/components/axes/Axis.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ export default {
410410
}
411411
412412
ticksZoomedIn.selectAll("text")
413-
.style("text-anchor", tickTextAnchor)
413+
.attr("text-anchor", tickTextAnchor)
414414
.attr("transform", tickTransformFunction);
415415
416416

src/components/plots/MultiDataRectPlot.vue

+41-92
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@
2020
'left': (this.pMarginLeft) + 'px'
2121
}"
2222
></canvas>
23-
<div v-show="this.highlightXY !== null"
23+
<div v-show="this.highlightY !== null"
2424
:style="{
2525
'height': (this.highlightHeight - 0.5) + 'px',
2626
'width': (this.highlightWidth - 0.5) + 'px',
27-
'top': (this.pMarginTop - 0.5) + 'px',
27+
'top': (this.pMarginTop + this.highlightY - 0.5) + 'px',
2828
'left': (this.pMarginLeft - 0.5) + 'px'
2929
}"
3030
class="vdp-plot-highlight-rect"
@@ -46,9 +46,11 @@
4646

4747
<script>
4848
import Two from '../../two.js';
49+
import { scaleBand as d3_scaleBand } from 'd3-scale';
4950
import { select as d3_select, create as d3_create } from 'd3-selection';
5051
import { mouse as d3_mouse, event as d3_event } from 'd3';
5152
import debounce from 'lodash/debounce';
53+
import range from 'lodash/range';
5254
import { TOOLTIP_DEBOUNCE, BAR_WIDTH_MIN } from './../../constants.js';
5355
import { getRetinaRatio } from './../../helpers.js';
5456
@@ -58,19 +60,14 @@ import DataContainer from './../../data/DataContainer.js';
5860
import mixin from './mixin.js';
5961
import CategoricalScale from './../../scales/CategoricalScale.js';
6062
61-
const SIDES = Object.freeze({ "TOP": 1, "LEFT": 2, "RIGHT": 3, "BOTTOM": 4 });
62-
const ORIENTATIONS = Object.freeze({ "VERTICAL": 1, "HORIZONTAL": 2 }); // vertical = left/right, horizontal = top/bottom
63-
6463
let uuid = 0;
6564
/**
6665
* @prop {string} dataArray An array of data keys.
6766
* @prop {string} cArray An array of color-scale variable keys.
6867
* @prop {string} z The observation-scale variable key.
6968
* @prop {string} o The observation (observation-scale domain element of interest).
70-
* @prop {string} orientation One of {'vertical', 'horizontal'}. TODO: implement horizontal.
7169
* @prop {number} rectMargin The margin between each rect.
7270
* @prop {number} rectSize The size of rects (only used if text values are enabled).
73-
* @prop {string} textSide One of {'top', 'left', 'right', 'bottom'} (only used if text values are enabled). TODO: implement top, left, bottom.
7471
* @prop {boolean} disableText Whether to disable the rendering of text for each value.
7572
* @prop {boolean} disableTooltip Whether to disable tooltips. Default: false
7673
* @extends mixin
@@ -81,7 +78,6 @@ let uuid = 0;
8178
* :cArray="['mut_class', 'mut_class', 'mut_class']"
8279
* z="sample_id"
8380
* o="SA12345"
84-
* orientation="vertical"
8581
* :pWidth="500"
8682
* :pHeight="300"
8783
* :pMarginTop="10"
@@ -124,10 +120,6 @@ export default {
124120
type: String,
125121
default: "#000"
126122
},
127-
'textSide': {
128-
type: String,
129-
default: 'right'
130-
},
131123
'disableText': {
132124
type: Boolean,
133125
default: true
@@ -144,7 +136,8 @@ export default {
144136
c: '',
145137
i: 0,
146138
},
147-
highlightXY: null,
139+
highlightYScale: null,
140+
highlightY: null,
148141
highlightHeight: null,
149142
highlightWidth: null,
150143
}
@@ -154,14 +147,6 @@ export default {
154147
uuid += 1;
155148
},
156149
created() {
157-
const orientationString = this.orientation.toUpperCase();
158-
console.assert(Object.keys(ORIENTATIONS).includes(orientationString));
159-
this._orientation = ORIENTATIONS[orientationString];
160-
161-
const textSideString = this.textSide.toUpperCase();
162-
console.assert(Object.keys(SIDES).includes(textSideString));
163-
this._textSide = SIDES[textSideString];
164-
165150
console.assert(this.dataArray.length === this.cArray.length);
166151
167152
// Set data
@@ -232,7 +217,7 @@ export default {
232217
this.tooltipPosition.left = mouseX;
233218
this.tooltipPosition.top = mouseY;
234219
}
235-
220+
236221
// Dispatch highlights
237222
this._zScale.emitHighlight(z);
238223
this._cScales[i].emitHighlight(c);
@@ -259,12 +244,9 @@ export default {
259244
return;
260245
}
261246
262-
263247
const cScales = vm._cScales;
264248
265249
const point = vm._dataContainers.map((dc) => dc.dataCopy.find((el) => el[vm.z] === vm.o)); // the single data point
266-
267-
console.log(point);
268250
269251
/*
270252
* Scale up the canvas
@@ -335,61 +317,38 @@ export default {
335317
*/
336318
337319
// Compute sizes.
338-
const numRects = point.length;
339-
let rectHeight, rectWidth, rectMargin, textWidth, textHeight;
340320
341-
rectMargin = vm.rectMargin;
342-
343-
if(vm._orientation === ORIENTATIONS.HORIZONTAL) {
344-
rectHeight = vm.pHeight;
345-
rectWidth = vm.pWidth / numRects;
321+
const numRects = point.length;
346322
347-
if(rectWidth - rectMargin <= BAR_WIDTH_MIN) {
348-
rectMargin = 0;
349-
}
323+
const y = d3_scaleBand()
324+
.domain(range(numRects))
325+
.range([0, vm.pHeight]);
350326
351-
if(!vm.disableText && vm.rectSize > 0) {
352-
rectHeight = vm.rectSize;
353-
}
354-
textWidth = rectWidth;
355-
textHeight = vm.pHeight - rectHeight;
327+
let rectHeight, rectWidth, rectMargin, textWidth;
356328
357-
vm.highlightHeight = vm.pHeight;
358-
vm.highlightWidth = rectWidth;
359-
} else if(vm._orientation === ORIENTATIONS.VERTICAL) {
360-
rectHeight = vm.pHeight / numRects;
361-
rectWidth = vm.pWidth;
329+
rectMargin = vm.rectMargin;
330+
362331
363-
if(rectHeight - rectMargin <= BAR_WIDTH_MIN) {
364-
rectMargin = 0;
365-
}
332+
rectHeight = vm.pHeight / numRects;
333+
rectWidth = vm.pWidth;
366334
367-
if(!vm.disableText && vm.rectSize > 0) {
368-
rectWidth = vm.rectSize;
369-
}
370-
textHeight = rectHeight;
371-
textWidth = vm.pWidth - rectWidth;
335+
if(rectHeight - rectMargin <= BAR_WIDTH_MIN) {
336+
rectMargin = 0;
337+
}
372338
373-
vm.highlightHeight = rectHeight;
374-
vm.highlightWidth = vm.pWidth;
339+
if(!vm.disableText && vm.rectSize > 0) {
340+
rectWidth = vm.rectSize;
375341
}
342+
textWidth = vm.pWidth - rectWidth;
343+
344+
vm.highlightHeight = rectHeight;
345+
vm.highlightWidth = vm.pWidth;
376346
377347
// Compute offsets if text will be on one side.
378-
let rectOffsetX = 0;
379-
let rectOffsetY = 0;
380348
let textOffsetX = 0;
381-
let textOffsetY = 0;
382349
383350
if(!vm.disableText && vm.rectSize > 0) {
384-
if(vm._orientation === ORIENTATIONS.HORIZONTAL && vm._textSide === SIDES.TOP) {
385-
rectOffsetY = textHeight;
386-
} else if(vm._orientation === ORIENTATIONS.HORIZONTAL && vm._textSide === SIDES.BOTTOM) {
387-
textOffsetY = rectHeight;
388-
} else if(vm._orientation === ORIENTATIONS.VERTICAL && vm._textSide === SIDES.LEFT) {
389-
rectOffsetX = textWidth;
390-
} else if(vm._orientation === ORIENTATIONS.VERTICAL && vm._textSide === SIDES.RIGHT) {
391-
textOffsetX = rectWidth;
392-
}
351+
textOffsetX = rectWidth;
393352
}
394353
395354
point.forEach((pointValue, i) => {
@@ -399,31 +358,21 @@ export default {
399358
400359
const textValue = this._cScales[i].toHuman(point[i][vm.cArray[i]]);
401360
402-
let rect, text;
403-
if(vm._orientation === ORIENTATIONS.HORIZONTAL) {
404-
rect = two.makeRectangle(
405-
i*rectWidth + (rectWidth/2) + (rectMargin/2), rectOffsetY + (rectHeight/2),
406-
rectWidth - rectMargin, rectHeight
407-
);
408-
contextHidden.fillRect(i*rectWidth, 0, rectWidth, rectHeight);
409-
410-
text = two.makeText(
411-
i*textWidth + (textWidth/2), textOffsetY + (textHeight/2),
412-
textWidth, textHeight, textValue
413-
);
414-
} else if(vm._orientation === ORIENTATIONS.VERTICAL) {
415-
rect = two.makeRectangle(
416-
rectOffsetX + (rectWidth/2), i*rectHeight + (rectHeight/2) + (rectMargin/2),
417-
rectWidth, rectHeight - rectMargin
418-
);
419-
contextHidden.fillRect(0, i*rectHeight, rectWidth, rectHeight);
420-
421-
text = two.makeText(
422-
textOffsetX + 4, i*textHeight + (textHeight/2) + 7,
423-
textWidth, textHeight, textValue
424-
);
425-
text.textalign = "left";
426-
}
361+
const rect = two.makeRectangle(
362+
0.5 + rectWidth/2, y(i) + rectHeight/2,
363+
rectWidth, rectHeight - rectMargin
364+
);
365+
contextHidden.fillRect(
366+
0.5, y(i),
367+
rectWidth, rectHeight
368+
);
369+
370+
const text = two.makeText(
371+
textOffsetX + 4, y(i) + (rectHeight/2) + 7,
372+
textWidth, rectHeight, textValue
373+
);
374+
375+
text.textalign = "left";
427376
rect.fill = cScales[i].color(point[i][vm.cArray[i]]);
428377
rect.noStroke();
429378

0 commit comments

Comments
 (0)