Files
dougal-software/lib/www/client/source/src/components/graph-arrays-ij-scatter.vue
D. Berge 7d2fb5558a Hide switches to enable additional graphs.
All violin plots as well as position scatter plots and histograms
are shown by default. This is due to #338.

For some reason, having them enabled from the get go does not
cause any problems.
2025-08-15 18:09:51 +02:00

384 lines
8.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<v-card style="min-height:400px;" outlined>
<v-card-title class="headline">
Array inline / crossline error
<v-spacer></v-spacer>
<!--
<v-switch v-model="scatterplot" label="Scatterplot"></v-switch>
<v-switch class="ml-4" v-model="histogram" label="Histogram"></v-switch>
-->
</v-card-title>
<v-container fluid fill-height>
<v-row>
<v-col>
<div class="graph-container" ref="graph0"></div>
</v-col>
</v-row>
<v-row v-show="scatterplot">
<v-col>
<div class="graph-container" ref="graph1"></div>
</v-col>
</v-row>
<v-row v-show="histogram">
<v-col>
<div class="graph-container" ref="graph2"></div>
</v-col>
</v-row>
</v-container>
<v-overlay :value="busy" absolute z-index="1">
<v-progress-circular indeterminate></v-progress-circular>
</v-overlay>
</v-card>
</template>
<style scoped>
.graph-container {
width: 100%;
height: 100%;
}
</style>
<script>
import Plotly from 'plotly.js-dist';
import { mapActions, mapGetters } from 'vuex';
import unpack from '@/lib/unpack.js';
export default {
name: 'DougalGraphArraysIJScatter',
props: [ "data", "settings" ],
data () {
return {
graph: [],
busy: false,
resizeObserver: null,
scatterplot: true,
histogram: true
};
},
computed: {
//...mapGetters(['apiUrl'])
},
watch: {
data (newVal, oldVal) {
if (newVal === null) {
this.busy = true;
} else {
this.busy = false;
this.plot();
}
},
settings () {
for (const key in this.settings) {
this[key] = this.settings[key];
}
},
histogram () {
this.plot();
this.$emit("update:settings", {[`${this.$options.name}.histogram`]: this.histogram});
},
scatterplot () {
this.plot();
this.$emit("update:settings", {[`${this.$options.name}.scatterplot`]: this.scatterplot});
},
"$vuetify.theme.isDark" () {
this.plot();
}
},
methods: {
plot () {
this.plotSeries();
if (this.histogram) {
this.plotHistogram();
}
if (this.scatterplot) {
this.plotScatter();
}
},
plotSeries () {
if (!this.data) {
return;
}
function transform (d, idx=0, otherParams={}) {
const errortype = d.errorfinal ? "errorfinal" : "errorraw";
const coords = unpack(unpack(d, errortype), "coordinates");
const x = unpack(d, "point");
const y = unpack(coords, idx);
const data = {
type: "scatter",
mode: "lines",
x,
y,
transforms: [{
type: "groupby",
groups: unpack(unpack(d, "meta"), "src_number"),
styles: [
{target: 1, value: {line: {color: "green"}}},
{target: 2, value: {line: {color: "red"}}}
]
}],
...otherParams
};
return data;
}
const data = [
transform(this.data.items, 1, {
xaxis: 'x',
yaxis: 'y',
name: 'Crossline'
}),
transform(this.data.items, 0, {
xaxis: 'x',
yaxis: 'y2',
name: 'Inline'
})
];
this.busy = false;
const layout = {
//autosize: true,
title: {text: "Inline / crossline error sequence %{meta.sequence}"},
autocolorscale: true,
// colorscale: "sequential",
yaxis2: {
title: "Crossline (m)",
anchor: "y2",
domain: [ 0.55, 1 ]
},
yaxis: {
title: "Inline (m)",
anchor: "y1",
domain: [ 0, 0.45 ]
},
xaxis: {
title: "Shotpoint",
anchor: "x1"
},
font: {
color: this.$vuetify.theme.isDark ? "#fff" : undefined
},
plot_bgcolor:"rgba(0,0,0,0)",
paper_bgcolor:"rgba(0,0,0,0)",
meta: this.data.meta
};
const config = {
editable: false,
displaylogo: false
};
this.graph[0] = Plotly.newPlot(this.$refs.graph0, data, layout, config);
},
plotScatter () {
console.log("plot");
if (!this.data) {
console.log("missing data");
return;
}
console.log("Will plot sequence", this.data.meta.project, this.data.meta.sequence);
function transform (d) {
const errortype = d.errorfinal ? "errorfinal" : "errorraw";
const coords = unpack(unpack(d, errortype), "coordinates");
const x = unpack(coords, 0);
const y = unpack(coords, 1);
const data = [{
type: "scatter",
mode: "markers",
x,
y,
transforms: [{
type: "groupby",
groups: unpack(unpack(d, "meta"), "src_number"),
styles: [
{target: 1, value: {line: {color: "green"}}},
{target: 2, value: {line: {color: "red"}}}
]
}]
}];
return data;
}
const data = transform(this.data.items);
this.busy = false;
const layout = {
//autosize: true,
//title: {text: "Inline / crossline error sequence %{meta.sequence}"},
autocolorscale: true,
// colorscale: "sequential",
yaxis: {
title: "Inline (m)",
//zeroline: false
},
xaxis: {
title: "Crossline (m)"
},
font: {
color: this.$vuetify.theme.isDark ? "#fff" : undefined
},
plot_bgcolor:"rgba(0,0,0,0)",
paper_bgcolor:"rgba(0,0,0,0)",
meta: this.data.meta
};
const config = {
editable: false,
displaylogo: false
};
this.graph[1] = Plotly.newPlot(this.$refs.graph1, data, layout, config);
},
plotHistogram () {
if (!this.data) {
console.log("missing data");
return;
}
function transform (d, idx=0, otherParams={}) {
const errortype = d.errorfinal ? "errorfinal" : "errorraw";
const coords = unpack(unpack(d, errortype), "coordinates");
const x = unpack(coords, idx);
const data = {
type: "histogram",
histnorm: 'probability',
x,
transforms: [{
type: "groupby",
groups: unpack(unpack(d, "meta"), "src_number"),
styles: [
{target: 1, value: {marker: {color: "rgba(129, 199, 132, 0.9)"}}},
{target: 2, value: {marker: {color: "rgba(229, 115, 115, 0.9)"}}}
]
}],
...otherParams
};
return data;
}
const data = [
transform(this.data.items, 0, {
xaxis: 'x',
yaxis: 'y',
name: 'Crossline'
}),
transform(this.data.items, 1, {
xaxis: 'x2',
yaxis: 'y',
name: 'Inline'
})
];
const layout = {
//autosize: true,
//title: {text: "Inline / crossline error sequence %{meta.sequence}"},
legend: {
title: { text: "Array" }
},
xaxis: {
title: "Crossline distance (m)",
domain: [ 0, 0.45 ],
anchor: 'x1'
},
yaxis: {
title: "Frequency (01)",
domain: [ 0, 1 ],
anchor: 'y1'
},
xaxis2: {
title: "Inline distance (m)",
domain: [ 0.55, 1 ],
anchor: 'x2'
},
font: {
color: this.$vuetify.theme.isDark ? "#fff" : undefined
},
plot_bgcolor:"rgba(0,0,0,0)",
paper_bgcolor:"rgba(0,0,0,0)",
meta: this.data.meta
};
const config = {
editable: false,
displaylogo: false
};
this.busy = false;
console.log(data);
console.log(layout);
this.graph[2] = Plotly.newPlot(this.$refs.graph2, data, layout, config);
},
replot () {
if (!this.graph.length) {
return;
}
console.log("Replotting");
this.graph.forEach( (graph, idx) => {
const ref = this.$refs["graph"+idx];
Plotly.relayout(ref, {
width: ref.clientWidth,
height: ref.clientHeight
});
});
},
},
async mounted () {
if (this.data) {
this.plot();
} else {
this.busy = true;
}
this.resizeObserver = new ResizeObserver(this.replot)
this.resizeObserver.observe(this.$refs.graph0);
this.resizeObserver.observe(this.$refs.graph1);
this.resizeObserver.observe(this.$refs.graph2);
},
beforeDestroy () {
if (this.resizeObserver) {
this.resizeObserver.unobserve(this.$refs.graph2);
this.resizeObserver.unobserve(this.$refs.graph1);
this.resizeObserver.unobserve(this.$refs.graph0);
}
}
};
</script>