Commit c73a251b authored by Sascha Herzinger's avatar Sascha Herzinger
Browse files

volcanoplot centered table below selection

parent 21e840ca
Pipeline #5301 passed with stages
in 6 minutes and 5 seconds
...@@ -45,19 +45,41 @@ ...@@ -45,19 +45,41 @@
</control-panel> </control-panel>
<svg :height="height" :width="width"> <svg :height="height" :width="width">
<g :transform="`translate(${margin.left}, ${margin.top})`"> <g :transform="`translate(${margin.left}, ${margin.top})`">
<html2svg :left="brushCoords.x" :top="brushCoords.y"> <html2svg :left="selectionTable.left" :top="selectionTable.top">
<table> <table class="fjs-selection-table"
<tr v-for="d in selectedFeaturesTable"> ref="selectionTable"
:style="{'min-width': brushSelection.x1 - brushSelection.x0 + 'px'}"
v-show="Object.keys(brushSelection).length > 0">
<tr id="table-colnames">
<td>Feature</td>
<td>{{ xAxisStatistic }}</td>
<td>{{ yAxisStatistic }}</td>
</tr>
<tr @mouseover="highlightedFeature = d.feature"
@mouseout="highlightedFeature = ''"
v-for="d in selectedFeaturesTable">
<td>{{ d.feature }}</td> <td>{{ d.feature }}</td>
<td>{{ d.xStat }}</td> <td>{{ d.xStat }}</td>
<td>{{ d.yStat }}</td> <td>{{ d.yStat }}</td>
</tr> </tr>
</table> </table>
</html2svg> </html2svg>
<g class="fjs-corr-axis" ref="yAxis2" :transform="`translate(${padded.width}, 0)`"></g> <g class="fjs-axis" ref="yAxis2" :transform="`translate(${padded.width}, 0)`"></g>
<g class="fjs-corr-axis" ref="xAxis2"></g> <g class="fjs-axis" ref="xAxis2"></g>
<g class="fjs-corr-axis" ref="xAxis1" :transform="`translate(0, ${padded.height})`"></g> <g class="fjs-axis" ref="xAxis1" :transform="`translate(0, ${padded.height})`"></g>
<g class="fjs-corr-axis" ref="yAxis1"></g> <g class="fjs-axis" ref="yAxis1"></g>
<text class="fjs-axis-label" :transform="`translate(${padded.width / 2}, ${padded.height})`">
{{ `${xAxisTransform}(${xAxisStatistic})` }}
</text>
<text class="fjs-axis-label" :transform="`translate(${0}, ${padded.height / 2})rotate(-90)`">
{{ `${yAxisTransform}(${yAxisStatistic})` }}
</text>
<text class="fjs-axis-label" :transform="`translate(${padded.width / 2}, ${0})`">
{{ `${xAxisStatistic}` }}
</text>
<text class="fjs-axis-label" :transform="`translate(${padded.width}, ${padded.height / 2})rotate(90)`">
{{ `${yAxisStatistic}` }}
</text>
<crosshair :width="padded.width" :height="padded.height"/> <crosshair :width="padded.width" :height="padded.height"/>
<image :xlink:href="dataUrl" :width="padded.width" :height="padded.height"></image> <image :xlink:href="dataUrl" :width="padded.width" :height="padded.height"></image>
<g class="fjs-brush" ref="brush"></g> <g class="fjs-brush" ref="brush"></g>
...@@ -101,10 +123,12 @@ ...@@ -101,10 +123,12 @@
'-log10': d => -Math.log10(d), '-log10': d => -Math.log10(d),
'identity': d => d 'identity': d => d
}, },
brushCoords: { brushSelection: {},
x: 0, selectionTable: {
y: 0 left: 0,
top: 0
}, },
highlightedFeature: '',
params: { params: {
min_total_row_count: 10 min_total_row_count: 10
}, },
...@@ -129,10 +153,10 @@ ...@@ -129,10 +153,10 @@
return this.args.numerical_arrays.length > 0 return this.args.numerical_arrays.length > 0
}, },
margin () { margin () {
const left = this.width / 20 const left = this.width / 18
const top = this.height / 20 const top = this.height / 18
const right = this.width / 20 const right = this.width / 18
const bottom = this.height / 20 const bottom = this.height / 18
return {left, top, right, bottom} return {left, top, right, bottom}
}, },
padded () { padded () {
...@@ -161,6 +185,23 @@ ...@@ -161,6 +185,23 @@
}) })
return { xs, ys, features } return { xs, ys, features }
}, },
rawScales () {
const x = d3.scaleLinear()
.domain((() => {
const xExtent = d3.extent(this.results.stats[this.xAxisStatistic])
const xPadding = (xExtent[1] - xExtent[0]) / 10
return [xExtent[0] - xPadding, xExtent[1] + xPadding]
})())
.range([0, this.padded.width])
const y = d3.scaleLinear()
.domain((() => {
const yExtent = d3.extent(this.results.stats[this.yAxisStatistic])
const yPadding = (yExtent[1] - yExtent[0]) / 10
return [yExtent[0] - yPadding, yExtent[1] + yPadding]
})())
.range([0, this.padded.height])
return { x, y }
},
scales () { scales () {
const x = d3.scaleLinear() const x = d3.scaleLinear()
.domain((() => { .domain((() => {
...@@ -186,14 +227,12 @@ ...@@ -186,14 +227,12 @@
}) })
}, },
axis () { axis () {
const x1 = d3.axisTop(this.scales.x) const x1 = d3.axisBottom(this.scales.x)
const y1 = d3.axisRight(this.scales.y) const y1 = d3.axisLeft(this.scales.y)
const x2 = d3.axisBottom(this.scales.x) const x2 = d3.axisTop(this.rawScales.x)
.tickSizeInner(this.padded.height) .tickSizeOuter(-this.padded.height)
.tickFormat('') const y2 = d3.axisRight(this.rawScales.y)
const y2 = d3.axisLeft(this.scales.y) .tickSizeOuter(-this.padded.width)
.tickSizeInner(this.padded.width)
.tickFormat('')
return {x1, x2, y1, y2} return {x1, x2, y1, y2}
}, },
statistics () { statistics () {
...@@ -212,17 +251,21 @@ ...@@ -212,17 +251,21 @@
.extent([[0, 0], [this.padded.width, this.padded.height]]) .extent([[0, 0], [this.padded.width, this.padded.height]])
.on('brush', () => { .on('brush', () => {
if (!d3.event.sourceEvent) { return } if (!d3.event.sourceEvent) { return }
if (!d3.event.selection) { if (d3.event.selection) {
this.selectedFeatures = []
} else {
const [[x0, y0], [x1, y1]] = d3.event.selection const [[x0, y0], [x1, y1]] = d3.event.selection
this.brushCoords.x = x0 this.brushSelection = { x0, x1, y0, y1 }
this.brushCoords.y = y1
this.selectedFeatures = this.scaledPoints.filter(d => { this.selectedFeatures = this.scaledPoints.filter(d => {
return x0 <= d.x && d.x <= x1 && y0 <= d.y && d.y <= y1 return x0 <= d.x && d.x <= x1 && y0 <= d.y && d.y <= y1
}) })
} }
}) })
.on('end', () => {
if (!d3.event.selection) {
this.brushSelection = {}
this.selectedFeatures = []
this.highlightedFeature = ''
}
})
}, },
selectedFeaturesTable () { selectedFeaturesTable () {
return this.selectedFeatures.map(d => { return this.selectedFeatures.map(d => {
...@@ -255,16 +298,22 @@ ...@@ -255,16 +298,22 @@
const ctx = this.canvas.getContext('2d') const ctx = this.canvas.getContext('2d')
ctx.clearRect(0, 0, this.canvas.width, this.canvas.height) ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
points.forEach(d => { points.forEach(d => {
let pointSize = this.pointSize
ctx.beginPath() ctx.beginPath()
if (d.feature === this.highlightedFeature) {
ctx.fillStyle = '#F00'
pointSize *= 2
} else {
ctx.fillStyle = '#000' ctx.fillStyle = '#000'
ctx.fillRect(d.x - this.pointSize / 2, d.y - this.pointSize / 2, this.pointSize, this.pointSize) }
ctx.fillRect(d.x - pointSize / 2, d.y - pointSize / 2, pointSize, pointSize)
}) })
this.dataUrl = this.canvas.toDataURL('image/png') this.dataUrl = this.canvas.toDataURL('image/png')
} }
}, },
watch: { watch: {
'args': { 'args': {
handler: function (newArgs, oldArgs) { handler: function (newArgs) {
if (this.validArgs) { if (this.validArgs) {
this.runAnalysisWrapper(newArgs) this.runAnalysisWrapper(newArgs)
} }
...@@ -275,6 +324,11 @@ ...@@ -275,6 +324,11 @@
this.drawPoints(newPoints) this.drawPoints(newPoints)
} }
}, },
'highlightedFeature': {
handler: function () {
this.drawPoints(this.scaledPoints)
}
},
'statistics': { 'statistics': {
handler: function (newStats, oldStats) { handler: function (newStats, oldStats) {
if (!_.isEqual(newStats, oldStats)) { if (!_.isEqual(newStats, oldStats)) {
...@@ -301,6 +355,14 @@ ...@@ -301,6 +355,14 @@
d3.select(this.$refs.brush).call(newBrush) d3.select(this.$refs.brush).call(newBrush)
}) })
} }
},
'brushSelection': {
handler: function (newSelection) {
const tableWidth = this.$refs.selectionTable.getBoundingClientRect().width
const selectionWidth = newSelection.x1 - newSelection.x0
this.selectionTable.left = newSelection.x0 - (tableWidth / 2 - selectionWidth / 2)
this.selectionTable.top = newSelection.y1
}
} }
} }
} }
...@@ -313,6 +375,22 @@ ...@@ -313,6 +375,22 @@
.fjs-axis-params .fjs-axis-params
display: flex display: flex
flex-direction: column flex-direction: column
svg
.fjs-axis-label
text-anchor: middle
.fjs-selection-table
border-collapse: collapse
background: rgb(216, 217, 216)
color: #000
margin: 0
#table-colnames
border-top: 1px solid black
border-bottom: 1px solid black
td, tr
border: none
tr
&:hover:not(#table-colnames)
background: aqua
</style> </style>
<!--CSS for dynamically created components--> <!--CSS for dynamically created components-->
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment