diff --git a/lib/www/client/source/src/views/MapLayersMixin.vue b/lib/www/client/source/src/views/MapLayersMixin.vue index c61f735..02a3e82 100644 --- a/lib/www/client/source/src/views/MapLayersMixin.vue +++ b/lib/www/client/source/src/views/MapLayersMixin.vue @@ -437,17 +437,146 @@ export default { }); }, + heatmapLayer(options = {}) { + const { positions, values } = this.sequenceBinaryData; + if (!positions?.length || !values?.length) { + console.warn('No valid data for heatmapLayer'); + + return new HeatmapLayer({ + id: 'seqrh', + data: [], ...options }); } + + let weights, offset = 0, scaler = 1; + let colorDomain = null; + + switch (this.heatmapValue) { + case "total_error": + weights = Float32Array.from(values[3], (ei, i) => { + const ej = values[4][i]; + return Math.sqrt(ei * ei + ej * ej) / 10; // Euclidean distance in meters + }); + colorDomain = [2, 20]; + break; + case "delta_j": + weights = values[3]; + scaler = 0.1; + colorDomain = [2, 20]; + break; + case "delta_i": + weights = values[4]; + scaler = 0.1; + colorDomain = [0.5, 5]; + break; + case "delta_μ": + weights = values[5]; + scaler = 0.1; + break; + case "delta_σ": + weights = values[6]; + scaler = 0.1; + colorDomain = [ 0.1, 1.5 ]; + break; + case "delta_R": + weights = values[7]; + scaler = 0.1; + colorDomain = [ 0.1, 1.0 ]; + break; + case "press_μ": + weights = values[8]; + offset = -2000; + colorDomain = [ 5, 50 ]; + break; + case "press_σ": + weights = values[9]; + colorDomain = [ 1, 19 ]; + break; + case "press_R": + weights = values[10]; + colorDomain = [ 3, 50 ]; + break; + case "depth_μ": + weights = values[11]; + offset = -6; + scaler = 0.1; + colorDomain = [ 0.1, 1 ]; + break; + case "depth_σ": + weights = values[12]; + scaler = 0.1; + break; + case "depth_R": + weights = values[13]; + scaler = 0.1; + break; + case "fill_μ": + weights = values[14]; + break; + case "fill_σ": + weights = values[15]; + break; + case "fill_R": + weights = values[16]; + case "delay_μ": + weights = values[17]; + offset = -150; + scaler = 0.1; + colorDomain = [ 2, 50 ]; + break; + case "delay_σ": + weights = values[18]; + scaler = 0.1; + break; + case "delay_R": + weights = values[19]; + scaler = 0.1; + break; + } + + const stats = { + min: d3a.min(weights), + mode: d3a.mode(weights), + mean: d3a.mean(weights), + max: d3a.max(weights), + sd: d3a.deviation(weights), }; + const sr0 = [ stats.mean - 2.1*stats.sd, stats.mean + 2.1*stats.sd ]; + const sr1 = [ stats.mode - 2.1*stats.sd, stats.mode + 2.1*stats.sd ]; + console.log('Positions sample:', positions.slice(0, 10)); + console.log('Weights sample:', weights.slice(0, 10)); + console.log("Mode:", this.heatmapValue); + console.log('Weight stats:', stats); + console.log("Suggested ranges"); + console.log(sr0); + console.log(sr1); + console.log("Actual ranges"); + console.log(colorDomain); + return new HeatmapLayer({ + id: 'seqrh', data: { + length: weights.length, + positions, + weights + /* + attributes: { + getPosition: { value: positions, type: 'float32', size: 2 }, + getWeight: { value: weights, type: 'float32', size: 1 } + } + */ }, + getPosition: (d, {index, data}) => [ data.positions[index*2], data.positions[index*2+1] ], + getWeight: (d, {index, data}) => Math.abs(data.weights[index] * scaler + offset), + colorDomain, + radiusPixels: 25, + aggregation: 'MEAN', + pickable: false, ...options }); }, @@ -469,14 +598,6 @@ export default { return Math.sqrt(ei * ei + ej * ej) / 10; // Euclidean distance in meters }); - console.log('Positions sample:', positions.slice(0, 10)); - console.log('Weights sample:', weights.slice(0, 10)); - console.log('Weight stats:', { - min: Math.min(...weights), - max: Math.max(...weights), - mean: weights.reduce((sum, v) => sum + v, 0) / weights.length - }); - return new HeatmapLayer({ id: 'seqrh', data: {