提交 ad01d3f6 authored 作者: 祖铭松's avatar 祖铭松

feat: 相关性分析

上级 02b21257
......@@ -451,6 +451,7 @@ const setTips = (rect) => {
.style('width', '80px')
.style('text-align', 'center')
.style('height', '20px')
.style('line-height', '20px')
.style('padding', '5px');
rect.on('mouseover', (event, d) => {
......
......@@ -27,7 +27,6 @@ import {
setSilhouetteHeatmap,
setSilhouetteLegend
} from '../utils/index';
import { config } from 'plotly.js-dist';
const chartRef = ref(null);
......
import hcluster from './hcluster';
import hcluster from '../../../utils/hcluster';
import * as d3 from 'https://cdn.jsdelivr.net/npm/d3@7/+esm';
// root config
......@@ -107,6 +107,7 @@ export const setTips = (rect) => {
.style('width', '200px')
.style('text-align', 'center')
.style('height', '20px')
.style('line-height', '20px')
.style('padding', '5px');
rect.on('mouseover', (event, d) => {
......
import distance from 'distancejs';
import extend from 'extend';
/**
* hcluster
* @returns
*/
export default function () {
var data,
clusters,
clustersGivenK,
treeRoot,
posKey = 'position',
distanceName = 'angular',
distanceFn = distance.angular,
linkage = 'avg',
verbose = false;
//
// simple constructor
function clust() { }
//
// getters, setters a la D3
// return data or set data and build tree
clust.data = function (value) {
if (!arguments.length) return data;
// dataset will be mutated
data = value;
clust._buildTree();
return clust;
};
clust.posKey = function (value) {
if (!arguments.length) return posKey;
posKey = value;
return clust;
};
clust.linkage = function (value) {
if (!arguments.length) return linkage;
linkage = value;
return clust;
};
clust.verbose = function (value) {
if (!arguments.length) return verbose;
verbose = value;
return clust;
};
clust.distance = function (value) {
if (!arguments.length) return distanceName;
distanceName = value;
distanceFn = {
angular: distance.angular,
euclidean: distance.euclidean
}[value] || distance.angular;
return clust;
}
//
// get tree properties
clust.orderedNodes = function () {
if (!treeRoot) throw new Error('Need to passin data and build tree first.');
return treeRoot.indexes.map(function (ndx) {
return data[ndx];
});
};
clust.tree = function () {
if (!treeRoot) throw new Error('Need to passin data and build tree first.');
return treeRoot;
};
clust.getClusters = function (n) {
if (!treeRoot) throw new Error('Need to passin data and build tree first.');
if (n > data.length) throw new Error('n must be less than the size of the dataset');
return clustersGivenK[data.length - n]
.map(function (indexes) {
return indexes.map(function (ndx) { return data[ndx]; });
});
};
//
// math, matrix utility fn's
// return unique pairs of indexes on n x n matrix above the diagonal
clust._squareMatrixPairs = function (n) {
var pairs = [];
for (var row = 0; row < n; row++) {
for (var col = row + 1; col < n; col++) {
pairs.push([row, col]);
}
}
return pairs;
};
// average distance between set of cluster indexes
clust._avgDistance = function (setA, setB) {
var distance = 0;
for (var ndxA = 0; ndxA < setA.length; ndxA++) {
for (var ndxB = 0; ndxB < setB.length; ndxB++) {
distance += data[setA[ndxA]]._distances[setB[ndxB]];
}
}
return distance / setA.length / setB.length;
};
// min distance between set of cluster indexes
clust._minDistance = function (setA, setB) {
var distances = [];
for (var ndxA = 0; ndxA < setA.length; ndxA++) {
for (var ndxB = 0; ndxB < setB.length; ndxB++) {
distances.push(data[setA[ndxA]]._distances[setB[ndxB]]);
}
}
return distances.sort()[0];
};
// max distance between set of cluster indexes
clust._maxDistance = function (setA, setB) {
var distances = [];
for (var ndxA = 0; ndxA < setA.length; ndxA++) {
for (var ndxB = 0; ndxB < setB.length; ndxB++) {
distances.push(data[setA[ndxA]]._distances[setB[ndxB]]);
}
}
return distances.sort()[distances.length - 1];
};
//
// tree construction
//
clust._buildTree = function () {
if (!data || !data.length) throw new Error('Need `data` to build tree');
//
var node, clusterPairs, nearestPair, newCluster;
clusters = [];
clustersGivenK = [];
treeRoot = {};
// calculate distances and build single datum clusters
data.forEach(function (d, ndx) {
d._distances = data.map(function (compareTo) {
return distanceFn(d[posKey], compareTo[posKey]);
});
clusters.push(extend(d, {
height: 0,
indexes: [ndx]
}));
});
// for tree of n leafs, n-1 linkages
for (var iter = 0; iter < data.length - 1; iter++) {
verbose && console.log(iter + ': ' +
clusters.map(function (c) { return c.indexes; }).join('|'));
// find closest pair of clusters, pair[2] is distance
clusterPairs = clust._squareMatrixPairs(clusters.length);
clusterPairs.forEach(function (pair) {
pair[2] = clust['_' + linkage + 'Distance'](
clusters[pair[0]].indexes,
clusters[pair[1]].indexes);
});
nearestPair = clusterPairs
.reduce(function (pairA, pairB) { return pairA[2] <= pairB[2] ? pairA : pairB; },
[0, 0, Infinity]);
newCluster = {
name: 'Node ' + iter,
height: nearestPair[2],
indexes: clusters[nearestPair[0]].indexes.concat(clusters[nearestPair[1]].indexes),
children: [clusters[nearestPair[0]], clusters[nearestPair[1]]],
};
verbose && console.log(newCluster);
clustersGivenK.push(clusters.map(function (c) { return c.indexes; }));
// remove merged nodes and push new node
clusters.splice(Math.max(nearestPair[0], nearestPair[1]), 1);
clusters.splice(Math.min(nearestPair[0], nearestPair[1]), 1);
clusters.push(newCluster);
}
treeRoot = clusters[0];
// clust._rebalanceTree(treeRoot);
};
// TODO: better rebalancing algo? ... this is just for presentation
// rebalance after tree is built (b/c it is top down operation)
// clust._rebalanceTree = function(node) {
// if(node.parent && node.parent.children && node.parent.children.length &&
// node.children && node.children.length) {
// var rightDistance = clust['_'+linkage+'Distance'](
// node.parent.children[1].indexes,
// node.children[0].indexes);
// var leftDistance = clust['_'+linkage+'Distance'](
// node.parent.children[1].indexes,
// node.children[1].indexes);
// // switch order of node.children
// if(leftDistance > rightDistance) {
// node.children = [ node.children[1], node.children[0] ];
// node.indexes = node.children[0].indexes.concat(node.children[1].indexes);
// }
// }
// if(node.children) {
// clust._rebalanceTree(node.children[0]);
// clust._rebalanceTree(node.children[1]);
// }
// };
return clust;
}
\ No newline at end of file
import hcluster from './hcluster';
import hcluster from '../../../utils/hcluster';
import * as d3 from 'https://cdn.jsdelivr.net/npm/d3@7/+esm';
// root config
......@@ -107,6 +107,7 @@ export const setTips = (rect) => {
.style('width', '200px')
.style('text-align', 'center')
.style('height', '20px')
.style('line-height', '20px')
.style('padding', '5px');
rect.on('mouseover', (event, d) => {
......
<template>
<div ref="chartRef"></div>
<div ref="chartRef" class="chart-box">
<div class="tip"></div>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import { chartData } from '../mock';
import { chartMockData } from '../mock.js';
import * as d3 from 'https://cdn.jsdelivr.net/npm/d3@7/+esm';
import PubSub from 'pubsub-js';
import Plotly from 'plotly.js-dist';
import {
setTips,
setMaxMinNumber,
setLegend,
setScale,
setAxis,
setRect,
setTopLeftColor,
getRootConfig,
setTree,
setLabel
} from '../utils/index';
// 根节点实例
const chartRef = ref(null);
// 配置项数据
const options = ref({});
// 图表实例
const svgInstance = ref(null);
// pubsub实例
const pubSubInstance = ref(null);
// const mackData = [
// {
// z: [
// [1, null, 30, 50, 1],
// [20, 1, 60, 80, 30],
// [30, 60, 1, -10, 20]
// ],
// x: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'],
// y: ['Morning', 'Afternoon', 'Evening'],
// type: 'heatmap',
// hoverongaps: false
// }
// ];
// 配色
const generateColorConfig = (color) => {
if (!color) return false;
let colors = [];
if (Array.isArray(color)) {
colors = color;
} else {
colors = color.split(',');
}
return colors;
};
// 生成图表
const generateChart = (data) => {
const ret = options.value;
// 生成数据
const generateData = () => {
let z = [],
x = [],
y = [];
let width = Number(ret.chart_width) || 1000;
let height = Number(ret.chart_height) || 700;
let marginTop = Number(ret.margin_top) || 120;
let marginRight = Number(ret.margin_Right) || 120;
let marginBottom = Number(ret.margin_Bottom) || 60;
let marginLeft = Number(ret.margin_Left) || 120;
let legendPosition = ret.legend_position?.split(',') || [0, 0];
let legendData = [0.8, 0.85, 0.9, 0.95, 1];
let dendWidth = 100;
let heatWidth = width - marginLeft - marginRight;
let colorList = [
['#3DD378', '#EC0B88', '#444444', '#5E35B1', '#F9791E', '#C6C6C6', '#F7DC05', '#3D98D3'],
['#017A4A', '#FFCE4E', '#3D98D3', '#FF363C', '#794924', '#8CDB5E', '#D6D6D6', '#FB8C00']
];
chartData.forEach((r) => {
z.push([r.CD4N_1, r.CD4N_2, r.CD4N_3, r.CD4P_1, r.CD4P_2, r.CD4P_3]);
});
const titleConfig = {
label: !!ret.title ? ret.title : null,
color: ret.title_font_color || '#333333',
fontSize: ret.title_font_size || 20,
fontStyle: ret.title_font_style ? 'oblique' : 'normal',
fontFamily: ret.title_font_family || 'Arial',
fontWeight: ret.title_font_weight ? 'bold' : 'normal'
};
x = Object.keys(chartData[0]);
y = Object.keys(chartData[0]);
return [
{
z,
x,
y,
type: 'heatmap',
hoverongaps: false
}
];
const svg = d3.create('svg').attr('width', width).attr('height', height);
let configObj = {
...ret,
svg,
width,
height,
marginTop,
marginRight,
marginBottom,
marginLeft,
dendWidth,
titleConfig,
legendData,
colorList,
heatWidth,
legendPosition
};
setChart(configObj, data);
svgInstance.value = svg.node();
// Append the SVG element.
chartRef.value.appendChild(svgInstance.value);
};
// 生成图表
const generateChart = (data) => {
const ret = options.value;
//图例位置数组
const legend_position = ret.legend_position?.split(',') || '0,0';
const color_ls = generateColorConfig(ret.data_color_list);
const layout = {
width: ret.chart_width,
height: ret.chart_height,
showlegend: ret.show_legend,
legend: {
x: Number(legend_position[0]), // 设置图例水平位置,范围从0到1,0表示左侧,1表示右侧,0.5表示水平居中
y: Number(legend_position[1]), // 设置图例垂直位置,范围从0到1,0表示底部,1表示顶部,0.5表示垂直居中
font: {
family: 'Arial, sans-serif', // 设置图例字体样式
size: 16, // 设置图例字体大小(以像素为单位)
color: 'green' // 设置图例字体颜色
}
},
title: {
text: ret.title,
font: {
family: ret.title_font_family, // 设置字体家族
size: ret.title_font_size, // 设置字体大小(以像素为单位)
color: ret.title_font_color, // 设置字体颜色
weight: ret.title_font_weight //字体粗细
},
// xanchor: 'center', // 设置标题在水平中央
// yanchor: 'center' // 设置标题在垂直顶部
x: 0.5, // 设置水平位置,0表示左侧,0.5表示居中,1表示右侧
y: 0.99 // 设置垂直位置,0表示底部,0.5表示居中,1表示顶部
},
margin: {
t: Number(ret.margin_top),
b: Number(ret.margin_bottom),
l: Number(ret.margin_left),
r: Number(ret.margin_right)
},
xaxis: {
visible: ret.show_x_axis,
title: {
text: ret.show_x_title ? ret.x_title : '',
font: {
family: ret.xtitle_font_family, // 设置字体家族
size: Number(ret.xtitle_font_size), // 设置字体大小(以像素为单位)
color: ret.xtitle_font_color, // 设置字体颜色
weight: 'bold' //字体粗细
},
// xanchor: 'left', // 设置标题在水平中央
// yanchor: 'center', // 设置标题在垂直顶部
x: 0.1
},
showgrid: ret.show_x_gridLine, // 显示 x 轴网格线
showline: ret.show_x_line, // 显示 x 轴线
showticklabels: true,
ticks: ret.show_x_tickMarks ? 'outside' : '' // 将刻度线朝外显示\inside 向内
},
yaxis: {
visible: ret.show_y_axis,
title: {
text: ret.show_y_title ? ret.y_title : '',
font: {
family: ret.ytitle_font_family, // 设置字体家族
size: Number(ret.ytitle_font_size), // 设置字体大小(以像素为单位)
color: ret.ytitle_font_color, // 设置字体颜色
weight: ret.ytitle_font_weight //字体粗细
},
xanchor: 'center', // 设置标题在水平中央
yanchor: 'center' // 设置标题在垂直顶部
},
showgrid: ret.show_y_gridLine, // 隐藏 y 轴网格线
showline: ret.show_y_line, // 隐藏 y 轴线
showticklabels: true, // 显示 x 轴上的刻度标签
ticks: ret.show_y_tickMarks ? 'outside' : '' // 将刻度线朝外显示/inside 向内
}
const setChart = (config, data) => {
const { maxNumber, minNumber } = setMaxMinNumber(data);
const color = d3.scaleSequential([minNumber, maxNumber], d3.interpolateMagma);
const categories = data.map((d) => d.index);
const { x, y } = setScale(config, categories);
const newArr = data.map((d) => Object.keys(d).map((e) => d[e])).map((item) => ({ index: item[0], values: item.slice(1) }));
const { root } = getRootConfig(config, newArr);
let configObj = {
...config,
root,
categories,
color,
x,
y
};
Plotly.newPlot(chartRef.value, data, layout, { displayModeBar: false, showSendToCloud: true });
// rects
const rects = setRect(configObj, data);
// tips
setTips(rects);
// axis
setAxis(configObj);
// topLeftColor
setTopLeftColor(configObj, data);
// legend
config.show_legend && setLegend(configObj);
// tree
setTree(configObj);
// label
setLabel(configObj);
};
onMounted(() => {
const mackData = generateData(chartData);
const chartData = chartMockData;
pubSubInstance.value = PubSub.subscribe('options', (m, data) => {
options.value = data;
generateChart(mackData);
chartRef.value.removeChild(svgInstance.value);
generateChart(chartData);
});
generateChart(mackData);
generateChart(chartData);
});
onUnmounted(() => {
......@@ -164,4 +144,8 @@ onUnmounted(() => {
});
</script>
<style scoped></style>
<style scoped>
.chart-box {
position: relative;
}
</style>
......@@ -26,6 +26,10 @@
<input type="text" v-model="dynamic_parameter.margin_left" />
</div>
<h3 class="type content">文本</h3>
<div class="form-item">
<span>标题:</span>
<input type="text" v-model="dynamic_parameter.title" />
</div>
<div class="form-item">
<span>字体:</span>
<input type="text" v-model="dynamic_parameter.title_font_family" />
......@@ -55,14 +59,6 @@
<span>显示刻度线:</span>
<input type="checkbox" v-model="dynamic_parameter.show_x_tickMarks" />
</div>
<div class="form-item">
<span>显示网格:</span>
<input type="checkbox" v-model="dynamic_parameter.show_x_gridLine" />
</div>
<div class="form-item">
<span>刻度线颜色:</span>
<input type="text" v-model="dynamic_parameter.x_tickMarks_color" />
</div>
<div class="form-item">
<span>刻度线长度:</span>
<input type="text" v-model="dynamic_parameter.x_tickMarks_length" />
......@@ -87,10 +83,6 @@
<span>斜体:</span>
<input type="checkbox" v-model="dynamic_parameter.xtitle_font_style" />
</div>
<div class="form-item">
<span>x轴标题:</span>
<input type="text" v-model="dynamic_parameter.x_title" />
</div>
<h3 class="type content">Y轴配置</h3>
<div class="form-item">
<span>显示坐标轴:</span>
......@@ -100,14 +92,6 @@
<span>显示刻度线:</span>
<input type="checkbox" v-model="dynamic_parameter.show_y_tickMarks" />
</div>
<div class="form-item">
<span>显示网格:</span>
<input type="checkbox" v-model="dynamic_parameter.show_y_gridLine" />
</div>
<div class="form-item">
<span>刻度线颜色:</span>
<input type="text" v-model="dynamic_parameter.y_tickMarks_color" />
</div>
<div class="form-item">
<span>刻度线长度:</span>
<input type="text" v-model="dynamic_parameter.y_tickMarks_length" />
......@@ -132,10 +116,6 @@
<span>斜体:</span>
<input type="checkbox" v-model="dynamic_parameter.ytitle_font_style" />
</div>
<div class="form-item">
<span>x轴标题:</span>
<input type="text" v-model="dynamic_parameter.y_title" />
</div>
<h3 class="type content">图例</h3>
<div class="form-item">
<span>显示图例:</span>
......@@ -158,30 +138,30 @@ import PubSub from 'pubsub-js';
//动态图参数,固定参数
const dynamic_parameter = reactive({
//长宽间距
chart_width: 800,
chart_height: 600,
margin_top: 60,
margin_right: 60,
chart_width: 1000,
chart_height: 700,
margin_top: 180,
margin_right: 120,
margin_bottom: 60,
margin_left: 60,
margin_left: 120,
//标题配置
title: '',
title: '相关性分析',
title_font_family: 'Arial',
title_font_weight: true,
title_font_size: 20,
title_font_color: '#333333',
title_font_style: true,
title_font_style: false,
//横轴标题
xtitle_font_family: 'Arial',
xtitle_font_weight: false,
xtitle_font_style: false,
xtitle_font_size: 16,
xtitle_font_size: 11,
xtitle_font_color: '#333333',
//纵轴标题
ytitle_font_family: 'Arial',
ytitle_font_weight: false,
ytitle_font_style: false,
ytitle_font_size: 16,
ytitle_font_size: 11,
ytitle_font_color: '#333333',
//颜色设置
......
This source diff could not be displayed because it is too large. You can view the blob instead.
import * as d3 from 'https://cdn.jsdelivr.net/npm/d3@7/+esm';
import hcluster from '../../../utils/hcluster';
// max min
export const setMaxMinNumber = (data) => {
const newArr = data.map((d) => Object.keys(d).map((e) => d[e])).map((f) => f.slice(1))
let maxNumArr = [],
minNumArr = [],
maxNumber = 0,
minNumber = 0;
for (let i = 0; i < newArr.length; i++) {
maxNumArr.push(d3.max(newArr[i]));
minNumArr.push(d3.min(newArr[i]));
}
// 最大值 最小值
maxNumber = d3.max(maxNumArr);
minNumber = d3.min(minNumArr);
return {
maxNumber,
minNumber
}
}
// scale
export const coordinateScale = (config, data) => {
const x = d3
.scaleLinear()
.domain([config.paddedMin, config.paddedMax])
.range([config.marginLeft, config.width - config.marginRight]);
const y = d3
.scaleLinear()
.domain(d3.extent(data, (d) => d.y))
.range([config.rectHeight, config.marginTop + 30]);
return {
x, y
}
}
// tips
export const setTips = (rect) => {
const tips = d3
.select('.tip')
.style('visibility', 'hidden')
.style('position', 'relative')
.style('background-color', 'rgba(0, 0, 0, .8)')
.style('color', '#fff')
.style('border-radius', '5px')
.style('width', '80px')
.style('height', '25px')
.style('line-height', '25px')
.style('text-align', 'center')
.style('padding', '5px')
rect.on('mouseover', (event, d) => {
tips.style('visibility', 'visible');
})
.on('mousemove', function (event, d) {
tips.style('visibility', 'visible')
.style('left', event.offsetX + 15 + 'px')
.style('top', event.offsetY + 55 + 'px')
.html(`${d.count}`);
})
.on('mouseleave', function () {
tips.style('visibility', 'hidden');
});
};
// legend
export const setLegend = (config) => {
config.svg.append('g')
.attr('transform', `translate(${(config.width - 100) * config.legendPosition[0]}, ${(config.height - 100) * config.legendPosition[1]})`)
.selectAll()
.data(config.legendData)
.join('g')
.attr('transform', (d, i, nodes) => `translate(0, ${(nodes.length - i) * 20 - 20})`)
.call((g) => g.append('rect').attr('width', 40).attr('height', 20).attr('fill', d => config.color(d)))
.call((g) =>
g
.append('text')
.attr('x', 45)
.attr('y', 11)
.attr('dy', '0.3em')
.style('font', '13px sans-serif')
.text((d) => d)
);
};
// topLeft Color
export const setTopLeftColor = (config, data) => {
config.svg
.append('g')
.attr('transform', `translate(${config.marginLeft}, ${config.marginTop - 20})`)
.selectAll()
.data(data)
.join('g')
.append('rect')
.attr('x', (d, i) => config.x.bandwidth() * i)
.attr('y', 0)
.attr('width', config.x.bandwidth())
.attr('height', 20)
.style('fill', (d, i) => config.colorList[0][i]);
config.svg
.append('g')
.attr('transform', `translate(${config.marginLeft - 20}, ${config.marginTop})`)
.selectAll()
.data(data)
.join('g')
.append('rect')
.attr('x', (d, i) => 0)
.attr('y', (d, i) => config.y.bandwidth() * i)
.attr('width', 20)
.attr('height', config.y.bandwidth())
.style('fill', (d, i) => config.colorList[1][i]);
}
// scale
export const setScale = (config, categories) => {
const x = d3
.scaleBand()
.domain(categories)
.range([config.marginLeft, config.width - config.marginRight]);
const y = d3
.scaleBand()
.domain([...categories].reverse())
.range([config.height - config.marginBottom, config.marginTop]);
return { x, y }
}
// axis
export const setAxis = (config) => {
const xAxis = (g) =>
g
.attr('transform', `translate(0, ${config.height - config.marginBottom})`)
.style('font', `${config.xtitle_font_size}px ${config.xtitle_font_family}`)
.style('color', `${config.xtitle_font_color}`)
.style('font-weight', `${config.xtitle_font_weight ? 'bold' : 'normal'}`)
.style('font-style', `${config.xtitle_font_style ? 'oblique' : 'normal'}`)
.call(d3.axisBottom(config.x).tickSize(Number(config.show_x_tickMarks ? config.x_tickMarks_length : 0)))
.call((g) => g.selectAll('.domain').remove())
.selectAll('text')
.style('text-anchor', 'middle');
const yAxis = (g) =>
g
.attr('transform', `translate(${config.width - config.marginRight}, 0)`)
.style('font', `${config.ytitle_font_size}px ${config.ytitle_font_family}`)
.style('color', `${config.ytitle_font_color}`)
.style('font-weight', `${config.ytitle_font_weight ? 'bold' : 'normal'}`)
.style('font-style', `${config.ytitle_font_style ? 'oblique' : 'normal'}`)
.call(d3.axisRight(config.y).tickSize(Number(config.show_y_tickMarks ? config.y_tickMarks_length : 0)))
.call((g) => g.selectAll('.domain').remove())
.selectAll('text')
.style('text-anchor', 'start')
config.show_x_axis && config.svg.append('g').call(xAxis);
config.show_y_axis && config.svg.append('g').call(yAxis);
}
// rect
export const setRect = (config, data) => {
const rects = config.svg
.append('g')
.selectAll('g')
.data(data)
.enter()
.append('g')
.attr('class', (d, i) => `${i} bar`)
.selectAll('g')
.data((d) =>
config.categories.map((e) => {
return { xval: d.index, yval: e, count: d[e] };
})
)
.enter()
.append('g');
rects
.append('rect')
.attr('x', (d) => config.x(d.xval))
.attr('y', (d) => config.y(d.yval))
.attr('width', config.x.bandwidth())
.attr('height', config.y.bandwidth())
.style('fill', (d) => config.color(d.count));
return rects
}
// root config
export const getRootConfig = (config, chartData) => {
const normalizedData = () => {
let minmaxes = d3
.range(chartData[0].values.length)
.map((d) => [d3.min(chartData.map((el) => el.values[d])), d3.max(chartData.map((el) => el.values[d]))]);
return chartData.map((el) => ({
...el,
normalized: el.values.map((n, i) => (n - minmaxes[i][0]) / (minmaxes[i][1] - minmaxes[i][0]))
}));
};
const clustering = hcluster().distance('angular').linkage('avg').posKey('normalized').data(normalizedData());
const tree = (data) => {
const root = d3.hierarchy(data).sort((a, b) => d3.ascending(a.height, b.height));
root.dx = 0;
root.dy = config.dendWidth / (root.height + 1);
return d3
.cluster()
.size([config.heatWidth, config.dendWidth])
.separation(() => 2)(root);
};
const root = tree(clustering.tree());
return {
root,
}
}
// tree
export const setTree = (config) => {
// top tree
config.svg.append('g')
.attr('fill', 'none')
.attr('stroke', '#555')
.attr('stroke-width', 1)
.attr('transform', `translate(${config.dendWidth + 20}, ${60})`)
.selectAll('path')
.data(config.root.links())
.join('path')
.attr(
'd',
(d) => `
M${d.target.x},${d.target.y}
L${d.target.x},${d.source.y}
${d.source.x},${d.source.y}
${d.source.x},${d.source.y}
`
);
};
// title
export const setLabel = (config) => {
config.svg.append('text')
.attr('x', config.width / 2)
.attr('y', 30)
.attr('fill', config.titleConfig.color)
.attr('font-size', `${config.titleConfig.fontSize}px`)
.attr('font-family', `${config.titleConfig.fontFamily}`)
.attr('font-style', `${config.titleConfig.fontStyle}`)
.attr('font-weight', `${config.titleConfig.fontWeight}`)
.style('text-anchor', 'middle')
.text(`${config.titleConfig.label}`);
};
......@@ -26,6 +26,10 @@
<input type="text" v-model="dynamic_parameter.margin_left" />
</div>
<h3 class="type content">文本</h3>
<div class="form-item">
<span>标题:</span>
<input type="text" v-model="dynamic_parameter.title" />
</div>
<div class="form-item">
<span>字体:</span>
<input type="text" v-model="dynamic_parameter.title_font_family" />
......@@ -76,7 +80,7 @@ const dynamic_parameter = reactive({
margin_bottom: 60,
margin_left: 60,
//标题配置
title: '',
title: 'group',
title_font_family: 'Arial',
title_font_weight: true,
title_font_size: 30,
......
......@@ -8,7 +8,7 @@
import { ref, onMounted } from 'vue';
import { chartMockData } from './mock.js';
import * as d3 from 'https://cdn.jsdelivr.net/npm/d3@7/+esm';
import { setTips, setMaxMinNumber, coordinateScale, setColor, setCluster, setLegend, setLabel } from './utils';
import { setTips, setMaxMinNumber, setLegend, setScale, setAxis, setRect, setTopLeftColor, getRootConfig, setTree } from './utils';
const chartRef = ref(null);
......@@ -19,20 +19,20 @@ const options = ref({});
const generateChart = (data) => {
const ret = options.value;
let width = 500;
let height = 1200;
let marginTop = 30;
let marginRight = 30;
let marginBottom = 30;
let marginLeft = 30;
let rectHeight = 300;
let width = 1000;
let height = 700;
let marginTop = 120;
let marginRight = 120;
let marginBottom = 60;
let marginLeft = 120;
let dendWidth = 100;
let legendData = [0.8, 0.85, 0.9, 0.95, 1];
let colorList = [
['#E53935', '#1E88E5'],
['#AA40FC', '#FFBB78'],
['#17BECF', '#E377C2']
['#3DD378', '#EC0B88', '#444444', '#5E35B1', '#F9791E', '#C6C6C6', '#F7DC05', '#3D98D3'],
['#017A4A', '#FFCE4E', '#3D98D3', '#FF363C', '#794924', '#8CDB5E', '#D6D6D6', '#FB8C00']
];
let titles = ['UMAP1', 'UMAP2'];
let labels = ['main_cluster_id_0.4', 'celltype', 'sample_id'];
let legendPosition = [0, 0];
let heatWidth = width - marginLeft - marginRight;
const titleConfig = {
label: !!ret.title ? ret.title : null,
......@@ -53,59 +53,60 @@ const generateChart = (data) => {
marginRight,
marginBottom,
marginLeft,
rectHeight,
dendWidth,
titleConfig,
titles,
labels,
colorList
legendData,
colorList,
heatWidth,
legendPosition
};
for (let i = 0; i < 3; i++) {
setChart(configObj, data, i);
}
setChart(configObj, data);
// setEl
chartRef.value.append(svg.node());
};
const setChart = (config, data, index) => {
let position = {
rect: [config.marginLeft, (config.rectHeight + 80) * index + config.marginTop],
cluster: [0, (config.rectHeight + 80) * index],
titleTop: [config.width / 2, (config.rectHeight + 80) * index + 20],
titleBottom: [config.width / 2, (config.rectHeight + 80) * index + config.rectHeight + 50],
titleLeft: [-config.rectHeight / 2 - (config.rectHeight + 80) * index, 20]
};
config.svg
.append('rect')
.attr('x', position.rect[0])
.attr('y', position.rect[1])
.attr('width', config.width - config.marginTop - config.marginRight)
.attr('height', config.rectHeight)
.attr('stroke', '#111111')
.attr('fill', 'white');
const setChart = (config, data) => {
const categories = data.map((d) => d.index);
const newArr = data.map((d) => Object.keys(d).map((e) => d[e])).map((item) => ({ index: item[0], values: item.slice(1) }));
const { maxNumber, minNumber } = setMaxMinNumber(data);
const { paddedMin, paddedMax } = setMaxMinNumber(data);
const color = d3.scaleSequential([minNumber, maxNumber], d3.interpolateMagma);
let configObj = {
...config,
categories,
color
};
let label = config.labels[index];
const { x, y } = setScale(config, categories);
let colors = config.colorList[index];
const { root } = getRootConfig(config, newArr);
let configObj = { ...config, paddedMin, paddedMax, position, label, colors };
configObj = {
...configObj,
root,
x,
y
};
const { x, y } = coordinateScale(configObj, data);
// rects
const rects = setRect(configObj, data);
const color = setColor(configObj);
// tips
setTips(rects);
configObj = { ...configObj, x, y, color };
// axis
setAxis(configObj);
const cluster = setCluster(configObj, data);
// topLeftColor
setTopLeftColor(configObj, data);
setTips(cluster);
// legend
setLegend(configObj);
// label
setLabel(configObj);
// tree
setTree(configObj);
};
onMounted(() => {
......
export const chartMockData = [
{
"x": -2.16937518759992,
"y": -3.73799262382173,
"group": "Cancer"
},
{
"x": 1.20950072955589,
"y": 0.235181672666528,
"group": "Non-cance"
},
{
"x": 1.17532258965045,
"y": -1.23876055963028,
"group": "Cancer"
},
{
"x": 2.05243302259336,
"y": 0.297813778924238,
"group": "Cancer"
},
{
"x": 0.112639689436034,
"y": 0.435463095441167,
"group": "Non-cance"
},
{
"x": -3.62498165924368,
"y": -1.59560845891834,
"group": "Cancer"
},
{
"x": 1.0996192165776,
"y": 0.923996346407357,
"group": "Cancer"
},
{
"x": -1.8768810343446,
"y": 2.17747795564948,
"group": "Non-cance"
},
{
"x": -1.7608357638922,
"y": 1.19219562555815,
"group": "Non-cance"
},
{
"x": 2.13661513280316,
"y": 0.236468233567813,
"group": "Cancer"
},
{
"x": 0.613390061404473,
"y": 1.06042824456935,
"group": "Cancer"
},
{
"x": -5.21101815005855,
"y": 4.47591384361132,
"group": "Non-cance"
},
{
"x": 0.838158581383053,
"y": 0.362694045925332,
"group": "Non-cance"
},
{
"x": 0.612258952193114,
"y": -4.42257726021997,
"group": "Cancer"
},
{
"x": -1.2483602499926,
"y": -1.04344671953559,
"group": "Cancer"
},
{
"x": -0.889932930105449,
"y": 0.139110165472675,
"group": "Non-cance"
},
{
"x": -0.652758913828004,
"y": -1.13699192023002,
"group": "Cancer"
},
{
"x": 2.01533998216389,
"y": -0.014201289497884,
"group": "Cancer"
},
{
"x": -1.61318598249345,
"y": -0.744621956952308,
"group": "Cancer"
},
{
"x": 1.79748846510557,
"y": 0.335421073128267,
"group": "Cancer"
},
{
"x": 1.98265006670833,
"y": 0.242059849140413,
"group": "Cancer"
},
{
"x": 1.74275870721343,
"y": -1.52365837545892,
"group": "Cancer"
},
{
"x": 2.24323378427512,
"y": 0.00389642300436324,
"group": "Cancer"
},
{
"x": 1.10449732384952,
"y": -1.01975213854357,
"group": "Cancer"
},
{
"x": -1.69859264301144,
"y": 0.089585892198542,
"group": "Cancer"
},
{
"x": -1.29498445169158,
"y": 0.961097872202235,
"group": "Non-cance"
},
{
"x": 0.941693121661991,
"y": 0.0697464661652063,
"group": "Non-cance"
},
{
"x": 0.380311878890109,
"y": 1.27181361823985,
"group": "Non-cance"
},
{
"x": 1.19675381021704,
"y": -0.0249606669348487,
"group": "Non-cance"
},
{
"x": 1.04730211011537,
"y": 0.257952879123077,
"group": "Non-cance"
},
{
"x": 1.97930020865197,
"y": 0.133251762343105,
"group": "Cancer"
},
{
"x": -2.30596410067018,
"y": 0.64052870652969,
"group": "Non-cance"
},
{
"x": 1.00468927382856,
"y": 0.0264098398469375,
"group": "Non-cance"
},
{
"x": 0.362984518249555,
"y": 1.17291796812492,
"group": "Cancer"
},
{
"x": 2.27061958358967,
"y": -0.0377523018270191,
"group": "Cancer"
},
{
"x": 0.533702401961174,
"y": 1.20419375043522,
"group": "Cancer"
},
{
"x": 0.422238882113262,
"y": 0.669103851659734,
"group": "Non-cance"
},
{
"x": -1.62960061656625,
"y": 2.00121849599749,
"group": "Non-cance"
},
{
"x": -1.84797214340467,
"y": -1.0064142585385,
"group": "Non-cance"
},
{
"x": -0.231230937825765,
"y": 1.65064494927466,
"group": "Cancer"
},
{
"x": -1.48959800499883,
"y": 1.544344966215,
"group": "Non-cance"
},
{
"x": 0.91466887077799,
"y": -1.17193730003533,
"group": "Cancer"
},
{
"x": 0.0802769950165894,
"y": 0.951359911188878,
"group": "Cancer"
},
{
"x": -3.45248159663703,
"y": -4.83853337224045,
"group": "Cancer"
},
{
"x": -0.249272576536832,
"y": -3.69336033643003,
"group": "Cancer"
},
{
"x": 0.730722447058803,
"y": -4.56548864832501,
"group": "Cancer"
},
{
"x": -1.14945241815085,
"y": -0.619031602490801,
"group": "Cancer"
},
{
"x": -0.350815735716144,
"y": 0.0690803064598962,
"group": "Non-cance"
},
{
"x": -0.226820671570678,
"y": 0.503108891754201,
"group": "Non-cance"
},
{
"x": 2.0418424964837,
"y": 0.118890298732828,
"group": "Cancer"
},
{
"x": -0.40814140287172,
"y": 0.692285685415223,
"group": "Non-cance"
},
{
"x": -2.19118080049179,
"y": 0.770719830246453,
"group": "Non-cance"
},
{
"x": 1.87027493999536,
"y": 0.344423685489549,
"group": "Cancer"
},
{
"x": -1.82687037479416,
"y": 1.63495547244402,
"group": "Non-cance"
},
{
"x": 0.188243344917409,
"y": 0.00125613183878562,
"group": "Cancer"
},
{
"x": -1.75675908301825,
"y": -0.296801362965225,
"group": "Cancer"
},
{
"x": 1.14479926018198,
"y": 0.239783463926525,
"group": "Non-cance"
},
{
"x": 0.97173818015304,
"y": 0.0682184939534245,
"group": "Non-cance"
},
{
"x": -3.4128347190817,
"y": 0.377327078404862,
"group": "Non-cance"
},
{
"x": 0.867741994433366,
"y": 0.603019772248489,
"group": "Non-cance"
},
{
"x": -1.79447732016727,
"y": 0.346351806914762,
"group": "Non-cance"
},
{
"x": -0.134667106777083,
"y": 1.20486709146323,
"group": "Non-cance"
},
{
"x": 1.8601968426472,
"y": 0.358407704376102,
"group": "Cancer"
},
{
"x": -1.58633134759729,
"y": 1.26922519385697,
"group": "Non-cance"
},
{
"x": 0.56730425074976,
"y": -4.58196806145978,
"group": "Cancer"
},
{
"x": -2.23507705126784,
"y": -3.07995896507561,
"group": "Cancer"
},
{
"x": -0.665634514005979,
"y": 0.283563048182783,
"group": "Non-cance"
},
{
"x": -0.500010559240671,
"y": -0.828708317430092,
"group": "Cancer"
},
{
"x": 0.634498729232388,
"y": 0.158233060578302,
"group": "Non-cance"
},
{
"x": 2.18518163881916,
"y": 0.0478305235106689,
"group": "Cancer"
},
{
"x": 0.313321252623918,
"y": 1.30833304963688,
"group": "Non-cance"
},
{
"x": -2.18954958054675,
"y": 0.649101485984047,
"group": "Non-cance"
},
{
"x": 0.73020709104066,
"y": 0.420834475342582,
"group": "Non-cance"
},
{
"x": 1.25697922487258,
"y": -1.04939159334455,
"group": "Cancer"
},
{
"x": -0.943750920088064,
"y": -0.506840811726623,
"group": "Cancer"
},
{
"x": 0.850439366474301,
"y": -1.27459706063345,
"group": "Cancer"
},
{
"x": 1.22901303357559,
"y": -2.61754170322427,
"group": "Cancer"
},
{
"x": 1.20036350674605,
"y": -1.29896112583748,
"group": "Cancer"
},
{
"x": 1.63008215686071,
"y": -1.3776698670706,
"group": "Cancer"
},
{
"x": 0.695046192686288,
"y": 0.323071647373476,
"group": "Cancer"
},
{
"x": -0.554947461042057,
"y": -1.20792983320948,
"group": "Cancer"
},
{
"x": 2.08117074859847,
"y": 0.0120282355293085,
"group": "Cancer"
},
{
"x": -1.40225572786423,
"y": -1.13459193110574,
"group": "Cancer"
},
{
"x": 0.408744822243002,
"y": 1.10216954523748,
"group": "Cancer"
},
{
"x": -0.427168371052439,
"y": 2.11673403996121,
"group": "Cancer"
},
{
"x": 2.10515695434221,
"y": 0.305854966269975,
"group": "Cancer"
},
{
"x": 1.22395793961888,
"y": -1.03166449128486,
"group": "Cancer"
},
{
"x": 2.14188766837062,
"y": 0.0761124283022032,
"group": "Cancer"
},
{
"x": -1.0644894444319,
"y": -2.93137138193128,
"group": "Cancer"
},
{
"x": 0.56970484184483,
"y": 1.80335932716454,
"group": "Non-cance"
},
{
"x": 2.32006422395923,
"y": -0.0382048088223572,
"group": "Cancer"
},
{
"x": -0.80050914734797,
"y": 1.17508682717831,
"group": "Non-cance"
},
{
"x": -0.692075605555399,
"y": -3.71511471981744,
"group": "Cancer"
},
{
"x": -0.974137168188438,
"y": -4.02733063300371,
"group": "Cancer"
},
{
"x": 1.93793120860812,
"y": 0.30314725578678,
"group": "Cancer"
},
{
"x": -2.43433283619866,
"y": 2.15482195100833,
"group": "Non-cance"
},
{
"x": -3.61354392178395,
"y": 1.90231830715836,
"group": "Non-cance"
},
{
"x": -3.80805248260896,
"y": 1.45012002007096,
"group": "Non-cance"
},
{
"x": 0.00860896616614883,
"y": 1.89431685784015,
"group": "Non-cance"
},
{
"x": 0.435107900568662,
"y": 1.32000841983658,
"group": "Cancer"
},
{
"x": 0.415339173114644,
"y": 0.614774087260173,
"group": "Non-cance"
},
{
"x": 0.603762518978029,
"y": 1.0341859826543,
"group": "Cancer"
},
{
"x": -0.450823174907223,
"y": -3.18275383552603,
"group": "Cancer"
},
{
"x": 0.572322349513285,
"y": -4.62134462349837,
"group": "Cancer"
},
{
"x": 0.216989922019603,
"y": -4.61156167914732,
"group": "Cancer"
},
{
"x": -2.70437300662563,
"y": -0.678645965609044,
"group": "Cancer"
},
{
"x": -1.30861794645249,
"y": -0.926162659409892,
"group": "Cancer"
},
{
"x": 0.540524157466341,
"y": 0.442745225063374,
"group": "Non-cance"
},
{
"x": -4.96601051502206,
"y": -0.871057387565659,
"group": "Non-cance"
},
{
"x": 2.02980106778328,
"y": 0.232574938774401,
"group": "Cancer"
},
{
"x": -0.981469971602537,
"y": 1.97922784306295,
"group": "Non-cance"
},
{
"x": -2.85262443458106,
"y": -1.43305485877584,
"group": "Non-cance"
},
{
"x": -0.541862562117694,
"y": 0.726146783268867,
"group": "Non-cance"
},
{
"x": -4.7644416750483,
"y": -2.73270741758483,
"group": "Cancer"
},
{
"x": 1.04015121205773,
"y": 0.307707498546097,
"group": "Non-cance"
},
{
"x": 1.23322642941554,
"y": -1.27437372060629,
"group": "Cancer"
},
{
"x": 1.66535965472428,
"y": 0.167971271865978,
"group": "Cancer"
},
{
"x": 0.782454323268248,
"y": 0.0463756119242875,
"group": "Non-cance"
},
{
"x": -0.364701533027158,
"y": -0.881819132426865,
"group": "Cancer"
},
{
"x": 0.388032817032171,
"y": -0.278318520729361,
"group": "Cancer"
},
{
"x": -2.51106622478013,
"y": 1.2324766317997,
"group": "Non-cance"
},
{
"x": -0.270410032766559,
"y": 0.277245461086781,
"group": "Non-cance"
},
{
"x": -4.72256993868376,
"y": 1.07480719840077,
"group": "Non-cance"
},
{
"x": 2.06607179890427,
"y": 0.809442023463668,
"group": "Cancer"
},
{
"x": -1.92418259680104,
"y": 1.58767022243255,
"group": "Non-cance"
},
{
"x": 2.26222112635974,
"y": 0.235929945022946,
"group": "Cancer"
},
{
"x": 0.848753660808607,
"y": 0.264221864579908,
"group": "Non-cance"
},
{
"x": -0.207413948991137,
"y": -0.945597365352881,
"group": "Cancer"
},
{
"x": -0.0529159955788029,
"y": 0.875996556794465,
"group": "Cancer"
},
{
"x": -1.49615485591266,
"y": -0.815205338249317,
"group": "Cancer"
},
{
"x": 1.31916914269479,
"y": 0.740012419698714,
"group": "Cancer"
},
{
"x": -1.70017201084313,
"y": -3.51484217716458,
"group": "Cancer"
},
{
"x": 0.940340802014965,
"y": 0.056330945375435,
"group": "Non-cance"
},
{
"x": 2.03335219377401,
"y": 0.27532597096311,
"group": "Cancer"
},
{
"x": 1.21812565793635,
"y": -0.604199667199764,
"group": "Cancer"
},
{
"x": -1.37814578804792,
"y": 0.37238933358514,
"group": "Non-cance"
},
{
"x": 0.926539816898182,
"y": 1.50561679829205,
"group": "Cancer"
},
{
"x": 0.212084582932134,
"y": -1.29757901801696,
"group": "Cancer"
},
{
"x": -1.90314732724116,
"y": -4.22887368818333,
"group": "Cancer"
},
{
"x": 0.879937093687778,
"y": 0.714045206883997,
"group": "Cancer"
},
{
"x": -2.57997578689605,
"y": 2.697677463906,
"group": "Non-cance"
},
{
"x": -1.77471196116864,
"y": -1.15529629598283,
"group": "Cancer"
},
{
"x": -0.951483818594621,
"y": -1.15089500487587,
"group": "Cancer"
},
{
"x": 0.141649277985723,
"y": 0.840158299366154,
"group": "Non-cance"
},
{
"x": -1.19422035629745,
"y": -3.26963253111098,
"group": "Cancer"
},
{
"x": -0.340302772450477,
"y": -1.23526510939176,
"group": "Cancer"
},
{
"x": 0.801018180990244,
"y": 0.0940044353282817,
"group": "Non-cance"
},
{
"x": 2.09034583061342,
"y": 0.0681637155365988,
"group": "Cancer"
},
{
"x": -2.34943005540015,
"y": -4.30531925055979,
"group": "Cancer"
},
{
"x": 1.73598123686276,
"y": 1.01876088070005,
"group": "Cancer"
},
{
"x": -1.26271277829623,
"y": 0.888985894733774,
"group": "Non-cance"
},
{
"x": -1.27229729673794,
"y": -1.12153197514487,
"group": "Cancer"
},
{
"x": -1.8407229165559,
"y": 1.79646511946251,
"group": "Non-cance"
},
{
"x": -0.648187668549265,
"y": 1.6457160271611,
"group": "Non-cance"
},
{
"x": 0.759473066729202,
"y": 1.58471702042419,
"group": "Cancer"
},
{
"x": 0.954613893871845,
"y": 1.22299099207626,
"group": "Cancer"
},
{
"x": -2.58861426803473,
"y": 1.81582778696349,
"group": "Non-cance"
},
{
"x": 0.944174388121608,
"y": -1.16601648162636,
"group": "Cancer"
},
{
"x": 2.32446948531729,
"y": -0.0406125083628081,
"group": "Cancer"
},
{
"x": -0.682859615251316,
"y": -0.581665302204599,
"group": "Cancer"
},
{
"x": 1.27973059422852,
"y": 0.995848267810618,
"group": "Cancer"
},
{
"x": 1.00703777987144,
"y": 0.0527817453992481,
"group": "Non-cance"
},
{
"x": 0.598802844649231,
"y": 1.07161575829885,
"group": "Cancer"
},
{
"x": 0.647673199585262,
"y": 0.124769388459546,
"group": "Non-cance"
},
{
"x": 1.21047334837894,
"y": 0.123879035060295,
"group": "Cancer"
},
{
"x": -1.11622444705792,
"y": 0.185991166486966,
"group": "Non-cance"
},
{
"x": 0.299468307255519,
"y": 1.424223283634,
"group": "Cancer"
},
{
"x": -0.419730289589368,
"y": 1.64745944621495,
"group": "Non-cance"
},
{
"x": -0.601681598297447,
"y": 1.63834335406696,
"group": "Non-cance"
},
{
"x": -3.1974780569428,
"y": -0.0504434930500891,
"group": "Cancer"
},
{
"x": 1.95617609895766,
"y": 0.107210238481263,
"group": "Cancer"
},
{
"x": 0.0209610405013348,
"y": 0.490616699666852,
"group": "Cancer"
},
{
"x": 1.78072021145476,
"y": -1.7195938194267,
"group": "Cancer"
},
{
"x": -1.23682946774351,
"y": 0.34804742998495,
"group": "Non-cance"
},
{
"x": 0.718626678838738,
"y": 0.124572600381486,
"group": "Non-cance"
},
{
"x": -1.95387069181506,
"y": 1.75233715525921,
"group": "Non-cance"
},
{
"x": 0.102426682726904,
"y": -0.576205282823572,
"group": "Cancer"
},
{
"x": 0.477160534481465,
"y": -1.24331480972779,
"group": "Cancer"
},
{
"x": 0.448001155524939,
"y": 1.12741418178943,
"group": "Cancer"
},
{
"x": -0.304398492094618,
"y": 0.242982773517717,
"group": "Non-cance"
},
{
"x": -2.89114219666187,
"y": 1.06656075131227,
"group": "Non-cance"
},
{
"x": 1.05900714494474,
"y": 0.53118111256512,
"group": "Non-cance"
},
{
"x": 1.94886700260168,
"y": 0.1388605152737,
"group": "Cancer"
},
{
"x": -1.15466395719433,
"y": 0.187560249642174,
"group": "Non-cance"
},
{
"x": -0.613028900275737,
"y": 1.7205750299586,
"group": "Non-cance"
},
{
"x": -3.77709212962353,
"y": 0.9876037183981,
"group": "Non-cance"
},
{
"x": 2.05539829203553,
"y": 0.0936940387403885,
"group": "Cancer"
},
{
"x": 2.02724628939209,
"y": 0.35744026007998,
"group": "Cancer"
},
{
"x": 0.401183071648358,
"y": 1.16832602605382,
"group": "Cancer"
},
{
"x": 1.78444035271073,
"y": 0.0984916470620601,
"group": "Cancer"
},
{
"x": -0.784564601317049,
"y": -0.216062718076483,
"group": "Cancer"
},
{
"x": 2.22786054693358,
"y": 0.0257995309704855,
"group": "Cancer"
},
{
"x": -0.451334933603293,
"y": 0.408125684363557,
"group": "Cancer"
},
{
"x": 1.82632263013556,
"y": 0.347713516358913,
"group": "Cancer"
},
{
"x": 0.440892444323358,
"y": -4.36482907884103,
"group": "Cancer"
},
{
"x": 1.02100344742884,
"y": 1.6081354292289,
"group": "Cancer"
},
{
"x": 2.03561904564828,
"y": -0.0401903702580246,
"group": "Cancer"
},
{
"x": -1.93851028584365,
"y": -3.0708513598222,
"group": "Cancer"
},
{
"x": -0.0871967072604459,
"y": -1.23062647088601,
"group": "Cancer"
},
{
"x": 1.87394145219173,
"y": 0.0663341389962665,
"group": "Cancer"
},
{
"x": -0.0477509857898044,
"y": 0.171848990040622,
"group": "Non-cance"
},
{
"x": 0.116585059434006,
"y": 0.742503866760543,
"group": "Non-cance"
},
{
"x": 1.43541075623904,
"y": 0.313630050443752,
"group": "Cancer"
},
{
"x": 0.868754292089192,
"y": 0.0428018519206832,
"group": "Non-cance"
},
{
"x": 0.964086753067101,
"y": 0.700763093177106,
"group": "Cancer"
},
{
"x": -0.970908883386746,
"y": -0.831203127779086,
"group": "Cancer"
},
{
"x": 1.81711314485598,
"y": 0.277442207182767,
"group": "Cancer"
},
{
"x": -1.23079131928395,
"y": 2.61362013392397,
"group": "Cancer"
},
{
"x": -0.530975485493529,
"y": -3.66987641898797,
"group": "Cancer"
},
{
"x": -0.240965619876677,
"y": 1.25049171744959,
"group": "Non-cance"
},
{
"x": 0.873689140279353,
"y": 0.138214641252442,
"group": "Non-cance"
},
{
"x": 0.0203060702224715,
"y": -1.01022949196579,
"group": "Cancer"
},
{
"x": 0.655458664826964,
"y": -4.35582980334672,
"group": "Cancer"
},
{
"x": -4.42831310785028,
"y": 1.69508105606565,
"group": "Non-cance"
},
{
"x": -0.304975592380851,
"y": 0.0438464406038675,
"group": "Non-cance"
},
{
"x": 0.167199774261687,
"y": 0.625575887379237,
"group": "Non-cance"
},
{
"x": 1.24322499437795,
"y": 0.648967288924275,
"group": "Cancer"
},
{
"x": 2.14758300621859,
"y": 0.0357967077962112,
"group": "Cancer"
},
{
"x": -0.706681619938241,
"y": 2.40252856070429,
"group": "Non-cance"
},
{
"x": 0.722579140783639,
"y": 1.07513955345056,
"group": "Cancer"
},
{
"x": -0.718377836340344,
"y": -0.324025886014972,
"group": "Cancer"
},
{
"x": 0.830480487773538,
"y": 0.156902470574637,
"group": "Non-cance"
},
{
"x": 0.319994233380379,
"y": 1.39686730527636,
"group": "Cancer"
},
{
"x": 1.99877222491453,
"y": 0.0257241740456704,
"group": "Cancer"
},
{
"x": 1.86701491912469,
"y": 0.321346988389356,
"group": "Cancer"
},
{
"x": 1.79617946251546,
"y": 0.626459994800626,
"group": "Cancer"
},
{
"x": 2.17461254549052,
"y": 0.233711625223321,
"group": "Cancer"
},
{
"x": -1.89170880181067,
"y": 0.111311187638334,
"group": "Non-cance"
},
{
"x": 0.0319163924283049,
"y": 1.31242888563328,
"group": "Non-cance"
},
{
"x": 1.03066091472108,
"y": 0.24112523576781,
"group": "Non-cance"
},
{
"x": -0.373536895031899,
"y": 1.53528892745146,
"group": "Cancer"
},
{
"x": -0.750464113507272,
"y": 0.45283709200199,
"group": "Non-cance"
},
{
"x": -0.846121353942867,
"y": 0.935945196012798,
"group": "Non-cance"
},
{
"x": -1.10402140268156,
"y": 2.06311745159163,
"group": "Non-cance"
},
{
"x": -2.9987670429794,
"y": -0.275328891573563,
"group": "Cancer"
},
{
"x": -0.862523023874412,
"y": 0.849648753565752,
"group": "Non-cance"
},
{
"x": 1.87999467154731,
"y": 0.139987500822862,
"group": "Cancer"
},
{
"x": 1.4390812225086,
"y": 0.938912982284872,
"group": "Cancer"
},
{
"x": -2.80986370971676,
"y": 0.613292482716283,
"group": "Non-cance"
},
{
"x": 2.01300004623551,
"y": 0.0773726747695536,
"group": "Cancer"
},
{
"x": 0.608551133536396,
"y": 0.122461870557329,
"group": "Non-cance"
},
{
"x": 2.28277357677969,
"y": 0.236214953421352,
"group": "Cancer"
},
{
"x": 0.453193539776809,
"y": 0.141269705074493,
"group": "Cancer"
},
{
"x": 1.26503613450708,
"y": 0.334485883528882,
"group": "Cancer"
},
{
"x": -3.46214896312579,
"y": 1.53714269278059,
"group": "Non-cance"
},
{
"x": -1.71380253363954,
"y": 1.05349120586351,
"group": "Non-cance"
},
{
"x": -0.475631462129027,
"y": 0.345918885791653,
"group": "Non-cance"
},
{
"x": -1.8500430522431,
"y": 2.99991088672401,
"group": "Cancer"
},
{
"x": 0.0226310624312658,
"y": -1.05289967627683,
"group": "Cancer"
},
{
"x": -3.66981064360042,
"y": -1.07820853756733,
"group": "Non-cance"
},
{
"x": 0.13004288880889,
"y": 0.730394091413725,
"group": "Non-cance"
},
{
"x": 0.021314607814896,
"y": 0.282592939375094,
"group": "Non-cance"
},
{
"x": 0.970997432909836,
"y": 0.298444833164395,
"group": "Non-cance"
},
{
"x": 0.432124211529602,
"y": 0.626658442993877,
"group": "Non-cance"
},
{
"x": 1.17076802394756,
"y": 0.809231635229459,
"group": "Cancer"
},
{
"x": -5.27887504788985,
"y": -0.402094883253519,
"group": "Non-cance"
},
{
"x": 0.937681911463538,
"y": 0.0673316092588679,
"group": "Non-cance"
},
{
"x": 1.07448509032561,
"y": -1.01502724949889,
"group": "Cancer"
},
{
"x": 1.02278173046408,
"y": 0.239592448946923,
"group": "Non-cance"
},
{
"x": 0.647815354164399,
"y": 0.345940688812712,
"group": "Cancer"
},
{
"x": 0.0887227522122356,
"y": -1.20848641282023,
"group": "Cancer"
},
{
"x": 1.695181720339,
"y": 0.15874313182976,
"group": "Cancer"
},
{
"x": 0.923457756655145,
"y": -1.21789720844516,
"group": "Cancer"
},
{
"x": -1.49707013508938,
"y": 1.52591866457669,
"group": "Cancer"
},
{
"x": -5.79194741817854,
"y": 2.12967846601336,
"group": "Non-cance"
},
{
"x": -3.5540236981016,
"y": -4.33383179480796,
"group": "Cancer"
},
{
"x": 1.77418035065036,
"y": 0.0306802543481402,
"group": "Cancer"
},
{
"x": 1.39308751023048,
"y": 1.13449625483816,
"group": "Cancer"
},
{
"x": -0.655242041259883,
"y": -0.997352220542483,
"group": "Cancer"
},
{
"x": -0.384700363537256,
"y": 0.323310869788651,
"group": "Non-cance"
},
{
"x": -2.57209265411714,
"y": -1.17535935594136,
"group": "Non-cance"
},
{
"x": 2.28654276173057,
"y": -0.095926934333892,
"group": "Cancer"
},
{
"x": 1.16822055856764,
"y": 0.230678456119326,
"group": "Non-cance"
},
{
"x": 1.90024377764878,
"y": 0.0368855035851561,
"group": "Cancer"
},
{
"x": 2.1590392769068,
"y": 0.304702440187337,
"group": "Cancer"
},
{
"x": 0.77577792207889,
"y": 0.292358087618884,
"group": "Non-cance"
},
{
"x": 1.85976485764551,
"y": 0.119692716293928,
"group": "Cancer"
},
{
"x": 2.08684451485357,
"y": 0.276112000632023,
"group": "Cancer"
},
{
"x": -0.747111893921671,
"y": -0.685428770903068,
"group": "Cancer"
},
{
"x": -1.84423733062336,
"y": -1.32614688917891,
"group": "Cancer"
},
{
"x": -4.00169540299989,
"y": 0.673205018122871,
"group": "Non-cance"
},
{
"x": 1.07498486281758,
"y": -1.18734696727664,
"group": "Cancer"
},
{
"x": -1.31169058076253,
"y": -0.230683997714911,
"group": "Cancer"
},
{
"x": -0.21992437369863,
"y": 1.38669463214628,
"group": "Non-cance"
},
{
"x": 1.90533569925003,
"y": 0.318831481423468,
"group": "Cancer"
},
{
"x": 1.54162499210516,
"y": -0.593772826796098,
"group": "Cancer"
},
{
"x": -0.483944105223758,
"y": 0.439716324887303,
"group": "Non-cance"
},
{
"x": 0.536359213928963,
"y": 0.695447745034254,
"group": "Non-cance"
},
{
"x": -3.11173959258511,
"y": 1.67142337138606,
"group": "Non-cance"
},
{
"x": -0.938562059912305,
"y": 1.05310280334826,
"group": "Non-cance"
},
{
"x": 0.203320204446677,
"y": 0.515788738768065,
"group": "Non-cance"
},
{
"x": -3.95827703348375,
"y": 3.18745282071095,
"group": "Non-cance"
},
{
"x": 0.746076393896232,
"y": 1.05395223193444,
"group": "Cancer"
},
{
"x": 0.0737851853672342,
"y": 0.797312096290768,
"group": "Non-cance"
},
{
"x": -1.45935758032728,
"y": 0.545257704468836,
"group": "Non-cance"
},
{
"x": 0.80783669181901,
"y": 0.416655777060071,
"group": "Non-cance"
},
{
"x": -0.485780840243109,
"y": -4.39903724275969,
"group": "Cancer"
},
{
"x": -0.985762106701204,
"y": -0.900803531212219,
"group": "Non-cance"
},
{
"x": -0.574808678034063,
"y": 0.39023078324811,
"group": "Non-cance"
},
{
"x": -0.417008694714375,
"y": 0.39397639067805,
"group": "Non-cance"
},
{
"x": -0.612303339315886,
"y": 0.102442934895947,
"group": "Non-cance"
},
{
"x": -1.75644912960494,
"y": 1.32191963839822,
"group": "Non-cance"
},
{
"x": 1.12825171395369,
"y": -0.635440834757169,
"group": "Cancer"
},
{
"x": 2.18188405011041,
"y": 0.0367857532179026,
"group": "Cancer"
},
{
"x": -1.43964816297122,
"y": 1.38434909653063,
"group": "Non-cance"
},
{
"x": 1.99323948231864,
"y": 0.129822589128215,
"group": "Cancer"
},
{
"x": 1.55173825001233,
"y": 0.518443178198605,
"group": "Cancer"
},
{
"x": -2.33061802518435,
"y": -4.15287104388452,
"group": "Cancer"
},
{
"x": 0.0737358971946831,
"y": 1.29495908662751,
"group": "Cancer"
},
{
"x": -1.53000386783713,
"y": -0.272674319162456,
"group": "Cancer"
},
{
"x": 2.00952358888033,
"y": 0.0691470971534185,
"group": "Cancer"
},
{
"x": -0.450791106623714,
"y": 0.0743628030441722,
"group": "Non-cance"
},
{
"x": 0.345675115645683,
"y": 1.26879538107995,
"group": "Cancer"
},
{
"x": -2.3004143108553,
"y": 0.519673086470863,
"group": "Non-cance"
},
{
"x": 1.99157240311337,
"y": 0.0741907908939875,
"group": "Cancer"
},
{
"x": 0.16699553588816,
"y": -3.76459376417826,
"group": "Cancer"
},
{
"x": 0.788638612562172,
"y": 0.590634477255124,
"group": "Non-cance"
},
{
"x": 1.89282156471999,
"y": 0.361148621272098,
"group": "Cancer"
},
{
"x": 0.910521678084575,
"y": 0.0620219093148729,
"group": "Non-cance"
},
{
"x": 1.07257817051642,
"y": -0.00479250709267795,
"group": "Non-cance"
},
{
"x": 0.31119657702912,
"y": 0.463431864741871,
"group": "Cancer"
},
{
"x": 2.07899085334771,
"y": 0.313084935568856,
"group": "Cancer"
},
{
"x": 1.10075568696803,
"y": 0.0077832406576244,
"group": "Non-cance"
},
{
"x": -0.293583725485335,
"y": -1.20040022519867,
"group": "Cancer"
},
{
"x": 0.264812070230152,
"y": 1.9131052009748,
"group": "Non-cance"
},
{
"x": 0.397593673629468,
"y": -0.802560707327924,
"group": "Non-cance"
},
{
"x": 1.11365733825192,
"y": 1.00114684425788,
"group": "Cancer"
},
{
"x": 0.787209235909883,
"y": 0.330802196086261,
"group": "Non-cance"
},
{
"x": 1.96831116848826,
"y": 0.0893049603995789,
"group": "Cancer"
},
{
"x": -1.46317904426873,
"y": 1.40759304193146,
"group": "Non-cance"
},
{
"x": 2.02267479025293,
"y": 0.300181017813627,
"group": "Cancer"
},
{
"x": -2.6608300356131,
"y": 1.08718686102204,
"group": "Non-cance"
},
{
"x": 0.0485002883432515,
"y": -0.527995286818386,
"group": "Non-cance"
},
{
"x": 2.24980664793003,
"y": -0.00142138160330194,
"group": "Cancer"
},
{
"x": 1.03816207606816,
"y": 0.0812767731770992,
"group": "Non-cance"
},
{
"x": 0.579340543940069,
"y": 0.297536958401714,
"group": "Cancer"
},
{
"x": -0.744862798195347,
"y": -0.551976530431195,
"group": "Non-cance"
},
{
"x": 0.913361530129574,
"y": 1.29490256481253,
"group": "Cancer"
},
{
"x": -0.341578529966019,
"y": -4.54787344772947,
"group": "Cancer"
},
{
"x": -0.878758797051621,
"y": 0.296792596612596,
"group": "Non-cance"
},
{
"x": 2.18322285891686,
"y": 0.00164811676778268,
"group": "Cancer"
},
{
"x": 0.518327907596202,
"y": 0.363333214906798,
"group": "Cancer"
},
{
"x": -0.287669731990206,
"y": -2.58860986374843,
"group": "Cancer"
},
{
"x": 0.802738286250557,
"y": 1.20465035218834,
"group": "Cancer"
},
{
"x": -1.45553171183474,
"y": 1.25188387391856,
"group": "Non-cance"
},
{
"x": 0.648169586376555,
"y": -0.00696521152411675,
"group": "Cancer"
},
{
"x": -0.722663932353358,
"y": 0.201969873883074,
"group": "Non-cance"
},
{
"x": 0.554997179137438,
"y": 0.448073899354283,
"group": "Non-cance"
},
{
"x": 0.766147418530411,
"y": 0.0730754931061437,
"group": "Non-cance"
},
{
"x": -1.6637629559818,
"y": 1.38507400100381,
"group": "Non-cance"
},
{
"x": -1.12105864589293,
"y": 2.39052227086082,
"group": "Non-cance"
},
{
"x": 0.495970449718372,
"y": 0.0420324260441031,
"group": "Cancer"
},
{
"x": 2.29681564945321,
"y": 0.231004195226574,
"group": "Cancer"
},
{
"x": -2.47834114260863,
"y": 0.190860694735743,
"group": "Cancer"
},
{
"x": -0.598876474824143,
"y": 0.144810946849699,
"group": "Non-cance"
},
{
"x": -0.44466189620123,
"y": -0.587342332853095,
"group": "Cancer"
},
{
"x": 1.70144277982201,
"y": -0.617135723058092,
"group": "Cancer"
},
{
"x": -5.41181144576582,
"y": 0.12717230104913,
"group": "Non-cance"
},
{
"x": 2.25651865930603,
"y": 0.269423548989115,
"group": "Cancer"
},
{
"x": 2.1142697452619,
"y": 0.289920227393179,
"group": "Cancer"
},
{
"x": -2.8512440241074,
"y": -0.825609168164621,
"group": "Cancer"
},
{
"x": 0.763651942479493,
"y": -0.478705698434409,
"group": "Cancer"
},
{
"x": 1.29469651107903,
"y": 1.11273650384557,
"group": "Cancer"
},
{
"x": -0.241083804702669,
"y": -0.986362322111779,
"group": "Cancer"
},
{
"x": 1.61363658306347,
"y": 0.258968095947149,
"group": "Cancer"
},
{
"x": -0.157103895671682,
"y": 1.48601354229983,
"group": "Non-cance"
},
{
"x": 1.02022682782059,
"y": 1.3397566578807,
"group": "Cancer"
},
{
"x": 0.848726378004263,
"y": 0.118203060179299,
"group": "Non-cance"
},
{
"x": 2.02550069542197,
"y": 0.37394127841611,
"group": "Cancer"
},
{
"x": 2.17056036444145,
"y": 0.275357283276692,
"group": "Cancer"
},
{
"x": 0.777742604518927,
"y": 0.104261773292967,
"group": "Non-cance"
},
{
"x": -4.58477281751526,
"y": -0.711183045564223,
"group": "Non-cance"
},
{
"x": 2.23910947114045,
"y": 0.262973755842211,
"group": "Cancer"
},
{
"x": 0.502159025447041,
"y": -4.3504343419155,
"group": "Cancer"
},
{
"x": -3.49757515485927,
"y": 1.55228884799679,
"group": "Non-cance"
},
{
"x": 1.60853621044436,
"y": 0.297014314935539,
"group": "Cancer"
},
{
"x": -1.35582321528752,
"y": 1.00877382692954,
"group": "Non-cance"
},
{
"x": -6.45930469889209,
"y": 0.541444616776251,
"group": "Non-cance"
},
{
"x": -2.61199757075851,
"y": -3.92524538936491,
"group": "Cancer"
},
{
"x": 0.971684304929901,
"y": 0.0378710240138574,
"group": "Non-cance"
},
{
"x": -0.21050570427323,
"y": 0.694708118533453,
"group": "Non-cance"
},
{
"x": 2.12500089254747,
"y": 0.217303761579659,
"group": "Cancer"
},
{
"x": 1.68172070029425,
"y": 0.388432772757681,
"group": "Cancer"
},
{
"x": 0.596273138247733,
"y": -1.44785818835398,
"group": "Cancer"
},
{
"x": 0.994307592190093,
"y": 0.0433568022059004,
"group": "Non-cance"
},
{
"x": -0.808288168419703,
"y": 0.087055392997485,
"group": "Cancer"
},
{
"x": 0.333830126193129,
"y": 1.30016660272971,
"group": "Cancer"
},
{
"x": -0.866540925780797,
"y": 1.31698289195771,
"group": "Non-cance"
},
{
"x": -0.108008337373563,
"y": -0.301543961109353,
"group": "Cancer"
},
{
"x": 1.38387027864752,
"y": 0.946096070822146,
"group": "Cancer"
},
{
"x": 1.75897004923862,
"y": 0.264047398431522,
"group": "Cancer"
},
{
"x": 1.94673254032124,
"y": 0.0545967074442076,
"group": "Cancer"
},
{
"x": 1.55065294209414,
"y": -3.86163512888018,
"group": "Cancer"
},
{
"x": 1.51581410305577,
"y": -0.796146849567481,
"group": "Cancer"
},
{
"x": -1.21672412236107,
"y": -2.32289928134483,
"group": "Cancer"
},
{
"x": 0.848402219214822,
"y": 0.0630692621893946,
"group": "Non-cance"
},
{
"x": -3.91577066447767,
"y": 2.4232642187356,
"group": "Non-cance"
},
{
"x": 1.85984763902208,
"y": 0.145159717459658,
"group": "Cancer"
},
{
"x": 1.94154519627851,
"y": 0.288978738208818,
"group": "Cancer"
},
{
"x": -0.433580493246295,
"y": 1.50221468746683,
"group": "Non-cance"
},
{
"x": 2.21654986478101,
"y": 0.0219457031650472,
"group": "Cancer"
},
{
"x": -4.74627421550312,
"y": 0.068952620387012,
"group": "Non-cance"
},
{
"x": -0.847927777140955,
"y": 0.896649605653024,
"group": "Non-cance"
},
{
"x": -1.97686627331088,
"y": 0.565830861800317,
"group": "Non-cance"
},
{
"x": 1.75800875286778,
"y": 0.0771396222450081,
"group": "Cancer"
},
{
"x": 2.12350468645243,
"y": -0.0184503944456242,
"group": "Cancer"
},
{
"x": 1.93585350686051,
"y": 0.0601391746663197,
"group": "Cancer"
},
{
"x": -2.7229137590684,
"y": 4.3408024041123,
"group": "Non-cance"
},
{
"x": -0.44339949373828,
"y": 1.29752058164537,
"group": "Non-cance"
},
{
"x": 2.10908855655517,
"y": 0.0000478182476982003,
"group": "Cancer"
},
{
"x": -0.838359079758306,
"y": 0.738633630080747,
"group": "Non-cance"
},
{
"x": -2.92927462031164,
"y": 2.90229111468834,
"group": "Non-cance"
},
{
"x": 1.79693670989593,
"y": 0.156019558557384,
"group": "Cancer"
},
{
"x": -1.27815225968438,
"y": 0.300183217895613,
"group": "Non-cance"
},
{
"x": -3.50297534089218,
"y": 3.04415972653821,
"group": "Non-cance"
},
{
"x": -0.576482143994799,
"y": 0.703062705299996,
"group": "Non-cance"
},
{
"x": 2.09559761634736,
"y": 0.0479238576883496,
"group": "Cancer"
},
{
"x": 2.2432172039302,
"y": 0.00689675855927899,
"group": "Cancer"
},
{
"x": 2.26638748192196,
"y": 0.00399169200159546,
"group": "Cancer"
},
{
"x": -1.5117930852015,
"y": -1.01722381336728,
"group": "Cancer"
},
{
"x": 1.12272088884876,
"y": 0.224528003924177,
"group": "Non-cance"
},
{
"x": -1.75882539882068,
"y": 1.49689099846843,
"group": "Non-cance"
},
{
"x": 1.09979423577477,
"y": -1.20519302874896,
"group": "Cancer"
},
{
"x": 1.09849912122874,
"y": 0.0416970778906649,
"group": "Non-cance"
},
{
"x": 2.09555011681734,
"y": 0.329546700690826,
"group": "Cancer"
},
{
"x": -2.27902957399003,
"y": 0.779792251881904,
"group": "Non-cance"
},
{
"x": -3.18473474899784,
"y": -0.532847987819189,
"group": "Cancer"
},
{
"x": 0.0123140002369803,
"y": -0.982954753343489,
"group": "Cancer"
},
{
"x": -2.13425440417168,
"y": 0.103990666922371,
"group": "Non-cance"
},
{
"x": -2.70895953422846,
"y": 0.848300839360461,
"group": "Non-cance"
},
{
"x": -1.23719659675828,
"y": -3.57121606210069,
"group": "Cancer"
},
{
"x": 2.16115233220577,
"y": 0.237532748532047,
"group": "Cancer"
},
{
"x": -1.69066796374744,
"y": -0.253534876561411,
"group": "Cancer"
},
{
"x": 0.336353391405282,
"y": 1.60870814971536,
"group": "Cancer"
},
{
"x": -2.1169727170744,
"y": -1.9391297279219,
"group": "Cancer"
},
{
"x": 2.25493070245791,
"y": 0.185096990959329,
"group": "Cancer"
},
{
"x": -2.46333866978245,
"y": -4.0344379082894,
"group": "Cancer"
},
{
"x": -3.33191894115671,
"y": 4.73669899040226,
"group": "Non-cance"
},
{
"x": -2.87286354473424,
"y": 0.246543019838962,
"group": "Non-cance"
},
{
"x": 2.17843153805402,
"y": 0.237303157966219,
"group": "Cancer"
},
{
"x": 0.709901270101137,
"y": 0.17552284087788,
"group": "Non-cance"
},
{
"x": 0.85716055611973,
"y": -0.974376262708492,
"group": "Cancer"
},
{
"x": 0.818394453298107,
"y": 0.698321467193181,
"group": "Non-cance"
},
{
"x": -1.63323373819168,
"y": 0.305622513523895,
"group": "Non-cance"
},
{
"x": 0.2387168696503,
"y": 0.87508896003161,
"group": "Cancer"
},
{
"x": 0.822555914101854,
"y": 0.311386310292182,
"group": "Non-cance"
},
{
"x": 0.208650893810009,
"y": 0.931090662934692,
"group": "Non-cance"
},
{
"x": -1.98204238332366,
"y": 1.38425264763724,
"group": "Non-cance"
},
{
"x": 2.23619032609003,
"y": 0.269632036432314,
"group": "Cancer"
},
{
"x": 0.705790944448384,
"y": 0.0450859632913446,
"group": "Non-cance"
},
{
"x": -0.0371632365012833,
"y": 0.519293492476561,
"group": "Non-cance"
},
{
"x": -0.369448094522874,
"y": -0.801342711402777,
"group": "Cancer"
},
{
"x": -0.163869517679154,
"y": 1.46733009178252,
"group": "Non-cance"
},
{
"x": -2.03156240254143,
"y": -1.43465505900213,
"group": "Non-cance"
},
{
"x": -1.14447048673749,
"y": 0.731287864197706,
"group": "Non-cance"
},
{
"x": 1.8404615291782,
"y": 0.0408591611967349,
"group": "Cancer"
},
{
"x": 1.82285745771227,
"y": 0.761759267517167,
"group": "Cancer"
},
{
"x": -3.55754365136791,
"y": -4.63666568959427,
"group": "Cancer"
},
{
"x": 0.0792661736459622,
"y": 0.65830483911383,
"group": "Non-cance"
},
{
"x": 1.15806338317813,
"y": 0.2147466178306,
"group": "Non-cance"
},
{
"x": -2.88024092095457,
"y": 2.35365336812957,
"group": "Non-cance"
},
{
"x": -2.43085611797218,
"y": 1.15427665435285,
"group": "Non-cance"
},
{
"x": -0.57833705870197,
"y": 0.047727700397464,
"group": "Non-cance"
},
{
"x": 1.04996306183006,
"y": 1.07984888807477,
"group": "Cancer"
},
{
"x": 0.43113447275592,
"y": 0.221373477907162,
"group": "Non-cance"
},
{
"x": -0.00463450706515584,
"y": -3.33357856684749,
"group": "Cancer"
},
{
"x": 2.29796791650403,
"y": -0.0140195309491713,
"group": "Cancer"
},
{
"x": 1.51370970162265,
"y": -0.783799429466536,
"group": "Cancer"
},
{
"x": 0.00048160457355053,
"y": 1.11864706085494,
"group": "Non-cance"
},
{
"x": 1.94301574912765,
"y": 0.0618135040579851,
"group": "Cancer"
},
{
"x": -3.22509665934639,
"y": -0.0452116887402084,
"group": "Non-cance"
},
{
"x": -0.403861506783196,
"y": 0.35871746156536,
"group": "Non-cance"
},
{
"x": 0.850586629486341,
"y": 0.237457505790471,
"group": "Non-cance"
},
{
"x": 1.91028380502572,
"y": 0.0798758919424118,
"group": "Cancer"
},
{
"x": 1.9606166969203,
"y": 0.1431425414439,
"group": "Cancer"
},
{
"x": 0.387273004024063,
"y": 1.40098252619623,
"group": "Cancer"
},
{
"x": 2.19335373550089,
"y": -0.0387126703414857,
"group": "Cancer"
},
{
"x": -0.375942190957179,
"y": 1.44633972104517,
"group": "Non-cance"
},
{
"x": 0.179724865202405,
"y": 1.55634104707304,
"group": "Cancer"
},
{
"x": -0.989504039302104,
"y": 0.206083922683253,
"group": "Non-cance"
},
{
"x": 0.850413900094021,
"y": 0.356085110069058,
"group": "Non-cance"
},
{
"x": 2.0514770981624,
"y": 0.029168590399578,
"group": "Cancer"
},
{
"x": -0.986567217696896,
"y": -1.18833930712429,
"group": "Non-cance"
},
{
"x": 0.785563710786714,
"y": 1.4259771772168,
"group": "Cancer"
},
{
"x": -2.13150645891057,
"y": -1.06553367596079,
"group": "Cancer"
},
{
"x": 1.85002773614612,
"y": -1.74761811231409,
"group": "Cancer"
},
{
"x": 1.48110178566877,
"y": 0.378143172268176,
"group": "Cancer"
},
{
"x": -1.12224917272359,
"y": 2.44154366419417,
"group": "Non-cance"
},
{
"x": -0.604925403820906,
"y": -4.57343513444193,
"group": "Cancer"
},
{
"x": 0.798011091702643,
"y": 0.419054960700513,
"group": "Non-cance"
},
{
"x": 1.72738386288825,
"y": 0.354248796444663,
"group": "Cancer"
},
{
"x": -1.07241803218074,
"y": 1.96594945371887,
"group": "Non-cance"
},
{
"x": 2.17256265148714,
"y": 0.282738757253991,
"group": "Cancer"
},
{
"x": 1.90675675802382,
"y": 0.290559672328954,
"group": "Cancer"
},
{
"x": 2.2326748203812,
"y": 0.0231682855061875,
"group": "Cancer"
},
{
"x": 0.554021250323335,
"y": 0.517583919627158,
"group": "Non-cance"
},
{
"x": 0.645710141933467,
"y": 0.27119916727941,
"group": "Cancer"
},
{
"x": -0.31340716618483,
"y": -0.811079232043347,
"group": "Cancer"
},
{
"x": 0.43573841624461,
"y": 0.164841888967416,
"group": "Cancer"
},
{
"x": 0.543271675245391,
"y": 0.995225431495561,
"group": "Cancer"
},
{
"x": -1.24962968685202,
"y": 0.842002168339176,
"group": "Non-cance"
},
{
"x": 0.731227903078727,
"y": 0.274248222585399,
"group": "Non-cance"
},
{
"x": 0.841788790775115,
"y": -2.50974298966646,
"group": "Cancer"
},
{
"x": 0.845589647779306,
"y": 0.191691762179116,
"group": "Cancer"
},
{
"x": 0.453363463473448,
"y": 0.420122783373017,
"group": "Non-cance"
},
{
"x": -1.11295883204984,
"y": 1.25815939666927,
"group": "Non-cance"
},
{
"x": -1.96551114109669,
"y": -1.48490851672821,
"group": "Cancer"
},
{
"x": 1.09381772850423,
"y": 0.237207321920042,
"group": "Non-cance"
},
{
"x": 1.27245655100831,
"y": 1.05003425699063,
"group": "Cancer"
},
{
"x": 0.718672715157027,
"y": 0.551696243000391,
"group": "Non-cance"
},
{
"x": 1.72006686074047,
"y": 0.181594156414106,
"group": "Cancer"
},
{
"x": 0.819420137371799,
"y": 0.306600048923468,
"group": "Non-cance"
},
{
"x": -2.73261875615964,
"y": -0.794718801210809,
"group": "Cancer"
},
{
"x": -0.282974184170587,
"y": -1.07574350612006,
"group": "Cancer"
},
{
"x": 0.881132145791996,
"y": 0.406896852579719,
"group": "Non-cance"
},
{
"x": 0.751366860134604,
"y": 0.05399176239142,
"group": "Non-cance"
},
{
"x": -0.856772786086455,
"y": 0.221310040576244,
"group": "Non-cance"
},
{
"x": 0.0245663771437544,
"y": -2.35199818296407,
"group": "Cancer"
},
{
"x": 1.75405014497992,
"y": 0.0732065582412485,
"group": "Cancer"
},
{
"x": 0.581430580627477,
"y": 0.393869875160245,
"group": "Non-cance"
},
{
"x": -1.25483453599141,
"y": 0.896204444106171,
"group": "Non-cance"
},
{
"x": 0.352953621851234,
"y": 0.688146724657673,
"group": "Non-cance"
},
{
"x": 0.626691361025788,
"y": 0.39404706789608,
"group": "Non-cance"
},
{
"x": -2.91331217219505,
"y": 0.231325985734653,
"group": "Non-cance"
},
{
"x": 0.325217002961721,
"y": 0.592125216105134,
"group": "Cancer"
},
{
"x": -0.988822842202209,
"y": -0.551723646026553,
"group": "Cancer"
},
{
"x": 0.523279723066128,
"y": 0.473828153089561,
"group": "Non-cance"
},
{
"x": -1.58514565577211,
"y": -3.7105708131746,
"group": "Cancer"
},
{
"x": 0.572592068798086,
"y": 1.0704770862156,
"group": "Cancer"
},
{
"x": -0.406738847883459,
"y": 0.0922532858961852,
"group": "Non-cance"
},
{
"x": 0.898102268401188,
"y": 0.303495902031343,
"group": "Non-cance"
},
{
"x": 0.410035017966802,
"y": -4.44024653891624,
"group": "Cancer"
},
{
"x": 1.25765880701631,
"y": -0.484744466898515,
"group": "Cancer"
},
{
"x": 0.937816681579775,
"y": -1.22245982612136,
"group": "Cancer"
},
{
"x": -2.76408215802373,
"y": 0.946290005575687,
"group": "Non-cance"
},
{
"x": 2.14464639880938,
"y": 0.320808763523397,
"group": "Cancer"
},
{
"x": -0.521681237982154,
"y": 1.19787773023717,
"group": "Non-cance"
},
{
"x": 2.16523893295976,
"y": 0.278098180993126,
"group": "Cancer"
},
{
"x": -1.82561476029441,
"y": 0.37066919761129,
"group": "Cancer"
},
{
"x": 1.96411572736956,
"y": 0.404385916541981,
"group": "Cancer"
},
{
"x": -2.78571805675463,
"y": 1.68897172609427,
"group": "Non-cance"
},
{
"x": -2.4588331264621,
"y": 0.688749127721328,
"group": "Cancer"
},
{
"x": 2.21622717012847,
"y": -0.00906897973348395,
"group": "Cancer"
},
{
"x": 1.79862519466813,
"y": 0.0292485297398488,
"group": "Cancer"
},
{
"x": 1.99241104334071,
"y": 0.0678932692937919,
"group": "Cancer"
},
{
"x": -2.38804566423841,
"y": 0.0296485222425242,
"group": "Cancer"
},
{
"x": 1.00991619357648,
"y": -0.964734393530452,
"group": "Cancer"
},
{
"x": 0.794340604287388,
"y": 0.139464186792679,
"group": "Non-cance"
},
{
"x": -1.81674061873047,
"y": -3.72310594897467,
"group": "Cancer"
},
{
"x": 2.15531064376668,
"y": 0.301061521420671,
"group": "Cancer"
},
{
"x": 1.99097492778331,
"y": 0.290677617898933,
"group": "Cancer"
},
{
"x": 1.05101635601788,
"y": 0.070960810261687,
"group": "Non-cance"
},
{
"x": 0.788101250218855,
"y": 0.327350110234589,
"group": "Non-cance"
},
{
"x": -1.30356405752714,
"y": -4.36684907714314,
"group": "Cancer"
},
{
"x": 0.410615350841205,
"y": 1.5416309804312,
"group": "Cancer"
},
{
"x": 0.315982210964215,
"y": 1.93741985949092,
"group": "Non-cance"
},
{
"x": 1.27250977839801,
"y": 1.10359073268906,
"group": "Cancer"
},
{
"x": -2.53406258317069,
"y": -0.842768028636238,
"group": "Cancer"
},
{
"x": 1.78537488921855,
"y": 0.12917192724664,
"group": "Cancer"
},
{
"x": -2.45383037856368,
"y": -0.0840278460777458,
"group": "Non-cance"
},
{
"x": 1.56050132166935,
"y": 0.409546261834881,
"group": "Cancer"
},
{
"x": -1.29741611475275,
"y": -0.657771644136354,
"group": "Cancer"
},
{
"x": -0.0414672619929929,
"y": 2.02208285407862,
"group": "Cancer"
},
{
"x": 1.96829898306835,
"y": 0.31946617349967,
"group": "Cancer"
},
{
"x": 0.65433174365747,
"y": 0.308133596485693,
"group": "Cancer"
},
{
"x": 2.28632055795646,
"y": -0.00443879935591382,
"group": "Cancer"
},
{
"x": 1.04440037870415,
"y": -4.48481847925363,
"group": "Cancer"
},
{
"x": 2.10680358004846,
"y": 0.277299517882273,
"group": "Cancer"
},
{
"x": 0.884738507699768,
"y": 0.258779354841291,
"group": "Non-cance"
},
{
"x": -1.87014038006741,
"y": 0.38228937526935,
"group": "Non-cance"
},
{
"x": -0.39262115027806,
"y": 1.22505619029361,
"group": "Non-cance"
},
{
"x": -1.3976508982624,
"y": 1.26311843944009,
"group": "Non-cance"
},
{
"x": 1.08134362869545,
"y": -4.78283521656358,
"group": "Cancer"
},
{
"x": 1.31280008442501,
"y": -0.546996656068227,
"group": "Cancer"
},
{
"x": -3.25059892439231,
"y": -0.769241430403467,
"group": "Non-cance"
},
{
"x": -1.35526939345756,
"y": 0.361722156101695,
"group": "Cancer"
},
{
"x": 2.05959150111169,
"y": 0.338593209358361,
"group": "Cancer"
},
{
"x": 2.22597207775835,
"y": 0.00131943008823113,
"group": "Cancer"
},
{
"x": 1.01767085949684,
"y": 0.00918910407705245,
"group": "Non-cance"
},
{
"x": 1.86378813756916,
"y": 0.170716331942402,
"group": "Cancer"
},
{
"x": 0.0913899637602279,
"y": 0.696082338994632,
"group": "Non-cance"
},
{
"x": 1.64621726654184,
"y": 0.0768780051558296,
"group": "Cancer"
},
{
"x": 0.765894411616808,
"y": -4.63122634759582,
"group": "Cancer"
},
{
"x": -1.63834287863236,
"y": 1.31020809147337,
"group": "Non-cance"
},
{
"x": -0.75501889619481,
"y": 0.162136074536712,
"group": "Non-cance"
},
{
"x": -2.38634477853108,
"y": 2.1619383121611,
"group": "Non-cance"
},
{
"x": -0.410096105640341,
"y": 0.112689662382171,
"group": "Non-cance"
},
{
"x": -0.00116659886505916,
"y": -1.2399746677555,
"group": "Cancer"
},
{
"x": 0.721402419135543,
"y": 1.99436077863642,
"group": "Cancer"
},
{
"x": -0.139340815526139,
"y": -1.02504311052851,
"group": "Cancer"
},
{
"x": 0.797873372182585,
"y": -3.00778066875461,
"group": "Cancer"
},
{
"x": -2.05042140889777,
"y": -0.432250405436247,
"group": "Cancer"
},
{
"x": 2.12245143712393,
"y": 0.309485664405176,
"group": "Cancer"
},
{
"x": 2.25706608760194,
"y": 0.248873074569709,
"group": "Cancer"
},
{
"x": 0.771376717441417,
"y": -0.083205269442605,
"group": "Cancer"
},
{
"x": 2.00985515791088,
"y": 0.286775966872753,
"group": "Cancer"
},
{
"x": 1.08921565804195,
"y": 0.0251273559308325,
"group": "Non-cance"
},
{
"x": 1.64240312949211,
"y": 0.0533604325433401,
"group": "Cancer"
},
{
"x": -5.67092186818055,
"y": 0.723345150806403,
"group": "Non-cance"
},
{
"x": 0.736379142400422,
"y": 1.00963478020972,
"group": "Cancer"
},
{
"x": 2.14982902897078,
"y": 0.00822122036545639,
"group": "Cancer"
},
{
"x": -0.245134193965563,
"y": 0.429906589300685,
"group": "Non-cance"
},
{
"x": -0.0515010251089383,
"y": 0.788089629797581,
"group": "Cancer"
},
{
"x": -1.07999290104626,
"y": 0.219344788213661,
"group": "Non-cance"
},
{
"x": -0.8199246685981,
"y": -4.58721086058925,
"group": "Cancer"
},
{
"x": -0.644294973488715,
"y": -0.647307084738364,
"group": "Cancer"
},
{
"x": 1.29080334562579,
"y": 0.125878942024665,
"group": "Cancer"
},
{
"x": 2.02519785503217,
"y": 0.0510328680794432,
"group": "Cancer"
},
{
"x": -3.05466782790202,
"y": -0.0558399623881638,
"group": "Non-cance"
},
{
"x": -3.43163989800511,
"y": 0.404188200948507,
"group": "Non-cance"
},
{
"x": -2.4891324584457,
"y": 0.925590923135083,
"group": "Non-cance"
},
{
"x": -0.119882423784981,
"y": 1.41084458570908,
"group": "Non-cance"
},
{
"x": -3.01269360281346,
"y": -3.84551108612398,
"group": "Cancer"
},
{
"x": 0.0300041564838832,
"y": 1.46629919928737,
"group": "Non-cance"
},
{
"x": 1.84294709635771,
"y": 0.684506975477439,
"group": "Cancer"
},
{
"x": 0.847865125223378,
"y": 0.00022979934413983,
"group": "Non-cance"
},
{
"x": -0.920813676996997,
"y": -0.165171444245175,
"group": "Cancer"
},
{
"x": -1.52141784366632,
"y": -0.911686694194898,
"group": "Cancer"
},
{
"x": 0.644670050235408,
"y": 0.665906900859917,
"group": "Non-cance"
},
{
"x": 1.27021209983415,
"y": 0.168889112483464,
"group": "Non-cance"
},
{
"x": 0.432773599514627,
"y": 0.385702616795673,
"group": "Non-cance"
},
{
"x": -0.892610707630411,
"y": -2.46705028591853,
"group": "Cancer"
},
{
"x": 0.404084593347261,
"y": 2.28094434371199,
"group": "Cancer"
},
{
"x": -0.369605652656395,
"y": 0.394554952932983,
"group": "Non-cance"
},
{
"x": -3.53262684868487,
"y": 0.346252374863351,
"group": "Cancer"
},
{
"x": -1.69874434490633,
"y": 1.64258754651874,
"group": "Non-cance"
},
{
"x": 1.48351256384312,
"y": 0.190541593029074,
"group": "Cancer"
},
{
"x": -1.04667247269134,
"y": -0.244878940499415,
"group": "Cancer"
},
{
"x": 2.38628878357829,
"y": -0.0332559252656721,
"group": "Cancer"
},
{
"x": 0.31359733987676,
"y": 1.77046771072785,
"group": "Cancer"
},
{
"x": -1.15125200174753,
"y": 1.17772276874434,
"group": "Non-cance"
},
{
"x": -2.52419003207152,
"y": 0.495699128300088,
"group": "Non-cance"
},
{
"x": 0.27971586280845,
"y": 0.498129820514466,
"group": "Non-cance"
},
{
"x": 1.42279600850853,
"y": 0.161524071286406,
"group": "Cancer"
},
{
"x": 1.96902307712919,
"y": 0.230745872762215,
"group": "Cancer"
},
{
"x": -0.867453415754027,
"y": -0.171406032850651,
"group": "Cancer"
},
{
"x": 2.21198643013116,
"y": 0.239117851471884,
"group": "Cancer"
},
{
"x": 1.95870702562042,
"y": 0.311368170587973,
"group": "Cancer"
},
{
"x": 0.559512383532093,
"y": 0.171401540710694,
"group": "Cancer"
},
{
"x": 0.422123750823622,
"y": 1.05193775111228,
"group": "Cancer"
},
{
"x": 0.590796161784814,
"y": 0.393279979958892,
"group": "Non-cance"
},
{
"x": -1.8041940081004,
"y": 0.432157793164541,
"group": "Non-cance"
},
{
"x": -2.01866920690204,
"y": -1.09324162401808,
"group": "Cancer"
},
{
"x": 0.538255214870276,
"y": 0.416979163587204,
"group": "Non-cance"
},
{
"x": -0.764616975779211,
"y": 2.15108768768024,
"group": "Cancer"
},
{
"x": -1.32618794672541,
"y": 1.33570761272916,
"group": "Non-cance"
},
{
"x": -2.87021270968338,
"y": -3.55388890917782,
"group": "Cancer"
},
{
"x": 1.02361509207064,
"y": -1.02564675046242,
"group": "Cancer"
},
{
"x": 0.108643105951982,
"y": -3.74686588248107,
"group": "Cancer"
},
{
"x": 0.53528539506144,
"y": 0.325188885247784,
"group": "Non-cance"
},
{
"x": -0.982832493965038,
"y": -4.60670254346272,
"group": "Cancer"
},
{
"x": 1.00332755388412,
"y": 0.262987448798649,
"group": "Non-cance"
},
{
"x": -3.53821954834133,
"y": 4.96817626446861,
"group": "Non-cance"
},
{
"x": -2.58411943781556,
"y": -3.23430891391471,
"group": "Cancer"
},
{
"x": 0.672563728748851,
"y": 0.432518426811699,
"group": "Non-cance"
},
{
"x": 2.1946755574872,
"y": 0.285546110089931,
"group": "Cancer"
},
{
"x": 2.06032622074577,
"y": 0.656019441754223,
"group": "Cancer"
},
{
"x": -0.395100734657474,
"y": 0.38432858708183,
"group": "Non-cance"
},
{
"x": -1.95971242133964,
"y": -3.39171515915456,
"group": "Cancer"
},
{
"x": 0.774408345177871,
"y": 0.716202240977428,
"group": "Non-cance"
},
{
"x": -3.67970173989135,
"y": -3.56160407937597,
"group": "Cancer"
},
{
"x": -0.0273644330149317,
"y": 2.16967411057935,
"group": "Non-cance"
},
{
"x": -3.11571532883282,
"y": -3.68837994678254,
"group": "Cancer"
},
{
"x": 0.327107040016566,
"y": 1.21476099572567,
"group": "Cancer"
},
{
"x": 1.69993611965234,
"y": 0.120667082213178,
"group": "Cancer"
},
{
"x": -0.556002579092688,
"y": -1.2862515162888,
"group": "Cancer"
},
{
"x": -1.8578798766153,
"y": 0.492049482693538,
"group": "Non-cance"
},
{
"x": 0.689632403891856,
"y": 0.310002064794149,
"group": "Non-cance"
},
{
"x": -0.551264809392112,
"y": 0.272385034440608,
"group": "Non-cance"
},
{
"x": 1.84265816029738,
"y": 0.377958769934223,
"group": "Cancer"
},
{
"x": 0.85066222363722,
"y": 0.362846537551314,
"group": "Non-cance"
},
{
"x": -1.48790080602781,
"y": -0.610146390458143,
"group": "Cancer"
},
{
"x": -1.31382758489495,
"y": 1.26738089135706,
"group": "Non-cance"
},
{
"x": -1.5295308635417,
"y": -0.256495295792684,
"group": "Cancer"
},
{
"x": 0.818831641134171,
"y": 1.38873786516446,
"group": "Cancer"
},
{
"x": -0.741758014183331,
"y": 0.664167906024238,
"group": "Non-cance"
},
{
"x": -0.948428993800742,
"y": -0.831888795692768,
"group": "Cancer"
},
{
"x": -0.512514082188688,
"y": 0.694379488428468,
"group": "Non-cance"
},
{
"x": 1.12455763269765,
"y": 0.0430017374986552,
"group": "Non-cance"
},
{
"x": -1.16852475041312,
"y": 1.44363627331541,
"group": "Non-cance"
},
{
"x": 0.993274573956558,
"y": 1.37441800239316,
"group": "Cancer"
},
{
"x": -2.14005259566534,
"y": 0.796424459597077,
"group": "Non-cance"
},
{
"x": -0.882615844473813,
"y": 0.3494938202086,
"group": "Non-cance"
},
{
"x": 2.16377046808294,
"y": 0.255281461901645,
"group": "Cancer"
},
{
"x": 0.901079293187635,
"y": 0.131387284399895,
"group": "Non-cance"
},
{
"x": -0.921310461443545,
"y": 0.0401845500949057,
"group": "Non-cance"
},
{
"x": -0.145953794916256,
"y": 1.95780343370745,
"group": "Non-cance"
},
{
"x": -0.444133285308427,
"y": 0.45573362864333,
"group": "Non-cance"
},
{
"x": 1.53291299387321,
"y": -3.78559147489734,
"group": "Cancer"
},
{
"x": 0.836602252346351,
"y": 0.643998786006336,
"group": "Non-cance"
},
{
"x": 0.822750592740604,
"y": 0.3652833138252,
"group": "Non-cance"
},
{
"x": -2.70287483920483,
"y": 0.0462171469054271,
"group": "Cancer"
},
{
"x": 0.727165749108358,
"y": 0.0475462827803257,
"group": "Cancer"
},
{
"x": -0.8645944406068,
"y": 0.232836003955521,
"group": "Non-cance"
},
{
"x": 1.43265162581448,
"y": 0.18966991416211,
"group": "Cancer"
},
{
"x": -5.81019828187951,
"y": 1.20632103713362,
"group": "Non-cance"
},
{
"x": -1.3065691675054,
"y": 0.948195228268149,
"group": "Non-cance"
},
{
"x": 0.253206353195792,
"y": -0.450626504603086,
"group": "Cancer"
},
{
"x": -0.495977618597782,
"y": -4.29090023749876,
"group": "Cancer"
},
{
"x": -1.90410302354997,
"y": -2.7341257657014,
"group": "Cancer"
},
{
"x": -2.38495044166141,
"y": 1.27842308000582,
"group": "Non-cance"
},
{
"x": -6.24560440198458,
"y": 1.29885746998912,
"group": "Non-cance"
},
{
"x": -0.393101813269389,
"y": 0.468065863405132,
"group": "Non-cance"
},
{
"x": -0.5332432142475,
"y": 1.04822931993254,
"group": "Non-cance"
},
{
"x": 0.913637330607835,
"y": 0.607957940820885,
"group": "Non-cance"
},
{
"x": 2.282189170967,
"y": -0.015681637426232,
"group": "Cancer"
},
{
"x": 2.13408859047752,
"y": 0.259825794623225,
"group": "Cancer"
},
{
"x": 1.10554427905579,
"y": -0.0178822648371295,
"group": "Non-cance"
},
{
"x": -1.52402437943605,
"y": 0.228521541148207,
"group": "Non-cance"
},
{
"x": -0.430504097238405,
"y": 0.0960836812354002,
"group": "Non-cance"
},
{
"x": -0.741555946309826,
"y": 0.147845566247175,
"group": "Non-cance"
},
{
"x": 0.781100534241145,
"y": -1.13914857939598,
"group": "Cancer"
"index": "AD1",
"AD1": "1",
"AD2": "0.84",
"AD3": "0.83",
"AD4": "0.9",
"Non_AD_5": "0.95",
"Non_AD_6": "0.81",
"Non_AD_7": "0.98",
"Non_AD_8": "1.0",
},
{
"index": "AD2",
"AD1": "0.8",
"AD2": "0.9",
"AD3": "0.85",
"AD4": "0.95",
"Non_AD_5": "1",
"Non_AD_6": "0.92",
"Non_AD_7": "0.91",
"Non_AD_8": "0.81",
},
{
"index": "AD3",
"AD1": "1",
"AD2": "0.99",
"AD3": "0.91",
"AD4": "0.98",
"Non_AD_5": "0.95",
"Non_AD_6": "0.93",
"Non_AD_7": "0.94",
"Non_AD_8": "1.0",
},
{
"index": "AD4",
"AD1": "0.99",
"AD2": "0.81",
"AD3": "0.82",
"AD4": "0.93",
"Non_AD_5": "0.99",
"Non_AD_6": "0.98",
"Non_AD_7": "0.91",
"Non_AD_8": "0.97",
},
{
"index": "Non_AD_5",
"AD1": "0.99",
"AD2": "0.98",
"AD3": "0.97",
"AD4": "0.95",
"Non_AD_5": "0.91",
"Non_AD_6": "0.99",
"Non_AD_7": "0.98",
"Non_AD_8": "0.95",
},
{
"index": "Non_AD_6",
"AD1": "0.98",
"AD2": "0.97",
"AD3": "0.92",
"AD4": "0.9",
"Non_AD_5": "0.95",
"Non_AD_6": "0.99",
"Non_AD_7": "0.89",
"Non_AD_8": "0.87",
},
{
"index": "Non_AD_7",
"AD1": "0.99",
"AD2": "0.98",
"AD3": "0.89",
"AD4": "0.91",
"Non_AD_5": "0.92",
"Non_AD_6": "0.89",
"Non_AD_7": "0.92",
"Non_AD_8": "1",
},
{
"index": "Non_AD_8",
"AD1": "0.96",
"AD2": "0.99",
"AD3": "0.97",
"AD4": "0.94",
"Non_AD_5": "0.94",
"Non_AD_6": "0.89",
"Non_AD_7": "0.91",
"Non_AD_8": "1",
}
]
import * as d3 from 'https://cdn.jsdelivr.net/npm/d3@7/+esm';
import hcluster from '../../utils/hcluster';
// color config
export const setColor = (config) => {
let colors = ['#E53935', '#1E88E5'];
if (Array.isArray(config.colors)) {
colors = !!config.colors.length ? config.colors : colors;
} else if (!!config.colors) {
colors = config.colors.split(',');
}
return d3.scaleOrdinal(colors).domain(config.legendData || []);
};
// paddedMin paddedMax
// max min
export const setMaxMinNumber = (data) => {
const paddedMin = d3.min(data, (d) => d.x) - d3.min(data, (d) => d.y) * -0.1;
const paddedMax = d3.max(data, (d) => d.x) + d3.max(data, (d) => d.y) * 0.1;
const newArr = data.map((d) => Object.keys(d).map((e) => d[e])).map((f) => f.slice(1))
let maxNumArr = [],
minNumArr = [],
maxNumber = 0,
minNumber = 0;
return {
paddedMin,
paddedMax
for (let i = 0; i < newArr.length; i++) {
maxNumArr.push(d3.max(newArr[i]));
minNumArr.push(d3.min(newArr[i]));
}
}
// cluster
export const setCluster = (config, data) => {
return config.svg
.append('g')
.attr('transform', `translate(${config.position.cluster[0]}, ${config.position.cluster[1]})`)
.style('isolation', 'isolate')
.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('class', 'points')
.attr('cx', (d) => config.x(d.x))
.attr('cy', (d) => config.y(d.y))
.attr('fill', (d) => config.color(d.group))
.attr('opacity', 0.7)
.attr('r', 4);
// 最大值 最小值
maxNumber = d3.max(maxNumArr);
minNumber = d3.min(minNumArr);
return {
maxNumber,
minNumber
}
}
// scale
......@@ -65,9 +48,10 @@ export const setTips = (rect) => {
.style('background-color', 'rgba(0, 0, 0, .8)')
.style('color', '#fff')
.style('border-radius', '5px')
.style('width', '200px')
.style('height', '45px')
.style('text-align', 'left')
.style('width', '80px')
.style('height', '25px')
.style('line-height', '25px')
.style('text-align', 'center')
.style('padding', '5px')
rect.on('mouseover', (event, d) => {
......@@ -76,10 +60,8 @@ export const setTips = (rect) => {
.on('mousemove', function (event, d) {
tips.style('visibility', 'visible')
.style('left', event.offsetX + 15 + 'px')
.style('top', event.offsetY + 90 + 'px')
.html(`
<div>x: ${d.x}</div>
<div>y: ${d.y}</div>`);
.style('top', event.offsetY + 55 + 'px')
.html(`${d.count}`);
})
.on('mouseleave', function () {
tips.style('visibility', 'hidden');
......@@ -90,54 +72,172 @@ export const setTips = (rect) => {
export const setLegend = (config) => {
config.svg.append('g')
.attr('transform', `translate(${config.width - config.marginLeft - 70}, ${100})`)
.attr('transform', `translate(${(config.width - 100) * config.legendPosition[0]}, ${(config.height - 100) * config.legendPosition[1]})`)
.selectAll()
.data(config.legendData)
.join('g')
.attr('transform', (d, i) => `translate(0, ${i * 20})`)
.call((g) => g.append('rect').attr('width', 15).attr('height', 15).attr('fill', d => config.color(d)))
.attr('transform', (d, i, nodes) => `translate(0, ${(nodes.length - i) * 20 - 20})`)
.call((g) => g.append('rect').attr('width', 40).attr('height', 20).attr('fill', d => config.color(d)))
.call((g) =>
g
.append('text')
.attr('x', 20)
.attr('y', 8)
.attr('x', 45)
.attr('y', 11)
.attr('dy', '0.3em')
.style('font', '13px sans-serif')
.text((d) => d)
);
};
// title
export const setLabel = (config) => {
config.svg.append('text')
.attr('x', config.position.titleTop[0])
.attr('y', config.position.titleTop[1])
.attr('fill', config.titleConfig.color)
.attr('font-size', `${config.titleConfig.fontSize}px`)
.attr('font-family', `${config.titleConfig.fontFamily}`)
.attr('font-style', `${config.titleConfig.fontStyle}`)
.attr('font-weight', `${config.titleConfig.fontWeight}`)
.style('text-anchor', 'middle')
.text(config.label);
config.svg.append('text')
.attr('x', config.position.titleBottom[0])
.attr('y', config.position.titleBottom[1])
.attr('fill', config.titleConfig.color)
.attr('font-size', `${config.titleConfig.fontSize}px`)
.attr('font-family', `${config.titleConfig.fontFamily}`)
.attr('font-style', `${config.titleConfig.fontStyle}`)
.attr('font-weight', `${config.titleConfig.fontWeight}`)
.style('text-anchor', 'middle')
.text(config.titles[0]);
config.svg.append('text')
.attr('x', config.position.titleLeft[0])
.attr('y', config.position.titleLeft[1])
.attr('fill', config.titleConfig.color)
.attr('font-size', `${config.titleConfig.fontSize}px`)
.attr('font-family', `${config.titleConfig.fontFamily}`)
.attr('font-style', `${config.titleConfig.fontStyle}`)
.attr('font-weight', `${config.titleConfig.fontWeight}`)
.style('text-anchor', 'middle')
.style('transform', 'rotate(-90deg)')
.text(config.titles[1]);
};
// topLeft Color
export const setTopLeftColor = (config, data) => {
config.svg
.append('g')
.attr('transform', `translate(${config.marginLeft}, ${config.marginTop - 20})`)
.selectAll()
.data(data)
.join('g')
.append('rect')
.attr('x', (d, i) => config.x.bandwidth() * i)
.attr('y', 0)
.attr('width', config.x.bandwidth())
.attr('height', 20)
.style('fill', (d, i) => config.colorList[0][i]);
config.svg
.append('g')
.attr('transform', `translate(${config.marginLeft - 20}, ${config.marginTop})`)
.selectAll()
.data(data)
.join('g')
.append('rect')
.attr('x', (d, i) => 0)
.attr('y', (d, i) => config.y.bandwidth() * i)
.attr('width', 20)
.attr('height', config.y.bandwidth())
.style('fill', (d, i) => config.colorList[1][i]);
}
// scale
export const setScale = (config, categories) => {
const x = d3
.scaleBand()
.domain(categories)
.range([config.marginLeft, config.width - config.marginRight]);
const y = d3
.scaleBand()
.domain([...categories].reverse())
.range([config.height - config.marginBottom, config.marginTop]);
return { x, y }
}
// axis
export const setAxis = (config) => {
const xAxis = (g) =>
g
.attr('transform', `translate(0, ${config.height - config.marginBottom})`)
// .style('font', '12px verdana')
.call(d3.axisBottom(config.x).tickSizeOuter(0))
.call((g) => g.selectAll('.domain').remove())
.selectAll('text')
.style('text-anchor', 'middle');
const yAxis = (g) =>
g
.attr('transform', `translate(${config.width - config.marginRight + 5}, 0)`)
// .style('font', '12px verdana')
.call(d3.axisLeft(config.y).ticks(null, 's'))
.call((g) => g.selectAll('.domain').remove())
.selectAll('text')
.style('text-anchor', 'start')
.attr('transform', `translate(10, 0)`);
config.svg.append('g').call(xAxis);
config.svg.append('g').call(yAxis);
}
// rect
export const setRect = (config, data) => {
const rects = config.svg
.append('g')
.selectAll('g')
.data(data)
.enter()
.append('g')
.attr('class', (d, i) => `${i} bar`)
.selectAll('g')
.data((d) =>
config.categories.map((e) => {
return { xval: d.index, yval: e, count: d[e] };
})
)
.enter()
.append('g');
rects
.append('rect')
.attr('x', (d) => config.x(d.xval))
.attr('y', (d) => config.y(d.yval))
.attr('width', config.x.bandwidth())
.attr('height', config.y.bandwidth())
.style('fill', (d) => config.color(d.count));
return rects
}
// root config
export const getRootConfig = (config, chartData) => {
const normalizedData = () => {
let minmaxes = d3
.range(chartData[0].values.length)
.map((d) => [d3.min(chartData.map((el) => el.values[d])), d3.max(chartData.map((el) => el.values[d]))]);
return chartData.map((el) => ({
...el,
normalized: el.values.map((n, i) => (n - minmaxes[i][0]) / (minmaxes[i][1] - minmaxes[i][0]))
}));
};
const clustering = hcluster().distance('angular').linkage('avg').posKey('normalized').data(normalizedData());
const tree = (data) => {
const root = d3.hierarchy(data).sort((a, b) => d3.ascending(a.height, b.height));
root.dx = 0;
root.dy = config.dendWidth / (root.height + 1);
return d3
.cluster()
.size([config.heatWidth, config.dendWidth])
.separation(() => 2)(root);
};
const root = tree(clustering.tree());
return {
root,
}
}
// tree
export const setTree = (config) => {
// top tree
config.svg.append('g')
.attr('fill', 'none')
.attr('stroke', '#555')
.attr('stroke-width', 1)
.attr('transform', `translate(${config.dendWidth + 20}, 0)`)
.selectAll('path')
.data(config.root.links())
.join('path')
.attr(
'd',
(d) => `
M${d.target.x},${d.target.y}
L${d.target.x},${d.source.y}
${d.source.x},${d.source.y}
${d.source.x},${d.source.y}
`
);
};
\ No newline at end of file
......@@ -21,7 +21,7 @@ import ClusterHeatmapSecond from '../../components/ClusterHeatmapSecond/index.vu
import CircularHeatmap from '../../components/CircularHeatmap/index.vue';
import Test from '../../components/Test/index.vue';
const chartCurrent = ref(4);
const chartCurrent = ref(6);
const chartList = shallowRef([
{ title: '线性拟合图', value: 1, comName: LinearFitting },
......
Markdown 格式
0% 或
您添加了 0 人 到此讨论。请谨慎行事。
请先完成此评论的编辑!
请 注册 或者 后发表评论