Refactor sequenceBinaryData.

It is no longer a computed property but actual data. It gets
recalculated on demand via getSequenceBinaryData().
This commit is contained in:
D. Berge
2025-08-08 12:40:23 +02:00
parent 5a19c81ed1
commit 4957142fb1

View File

@@ -578,6 +578,7 @@ export default {
layerSelection: [], layerSelection: [],
layersAvailable: {}, layersAvailable: {},
sequenceDataElements: [], sequenceDataElements: [],
sequenceBinaryData: { positions: new Float32Array(0), values: [], udv: 2 },
sequenceDataTStamp: null, sequenceDataTStamp: null,
loadingProgress: null, loadingProgress: null,
viewState: {}, viewState: {},
@@ -613,99 +614,14 @@ export default {
return this.sequenceDataElements?.map( el => el.data ); return this.sequenceDataElements?.map( el => el.data );
}, },
/*
sequenceBinaryData() { sequenceBinaryData() {
const sequences = this.sequenceDataElements?.sort((a, b) => a.sequence - b.sequence) || []; return this.getSequenceBinaryData(2); // Raw + gun data
if (!sequences.length) {
console.warn('No sequence data available');
return { positions: new Float32Array(0), values: [], udv: 2 };
}
// Validate first sequence to get array sizes
let firstBundle;
try {
firstBundle = DougalBinaryBundle.clone(sequences[0].data);
if (!firstBundle.chunks || typeof firstBundle.chunks !== 'function') {
throw new Error('Invalid DougalBinaryBundle: chunks method missing');
}
if (!firstBundle.chunks().length) {
throw new Error('Invalid DougalBinaryBundle: bundle has no chunks');
}
} catch (e) {
console.error('Failed to process first sequence:', e);
return { positions: new Float32Array(0), values: [], udv: 2 };
}
const totalCount = sequences.reduce((acc, { data }) => {
try {
const bundle = DougalBinaryBundle.clone(data);
return acc + bundle.chunks().reduce((sum, chunk) => sum + chunk.jCount, 0);
} catch (e) {
console.warn('Skipping invalid sequence data:', e);
return acc;
}
}, 0);
if (totalCount === 0) {
console.warn('No valid points found in sequences');
return { positions: new Float32Array(0), values: [], udv: 2 };
}
const ΔelemCount = firstBundle.chunks()[0].ΔelemCount;
const elemCount = firstBundle.chunks()[0].elemCount;
const positions = new Float32Array(totalCount * 2);
const values = new Array(ΔelemCount + elemCount + 2);
for (let k = 0; k < values.length; k++) {
values[k] = new (k === 0 ? Uint16Array : k === 1 ? Uint32Array : k === 2 ? BigUint64Array : Float32Array)(totalCount);
}
let offset = 0;
let udv = 2;
sequences.forEach(({ data, sequence }) => {
try {
const bundle = DougalBinaryBundle.clone(data);
const chunks = bundle.chunks();
if (!chunks.length) {
console.warn(`No chunks in sequence ${sequence}`);
return;
}
udv = chunks[0].udv;
let chunkOffset = offset;
for (const chunk of chunks) {
const λarray = chunk.elem(0);
const φarray = chunk.elem(1);
for (let i = 0; i < λarray.length; i++) {
positions[chunkOffset * 2 + i * 2] = λarray[i];
positions[chunkOffset * 2 + i * 2 + 1] = φarray[i];
}
values[0].set(new Uint16Array(chunk.jCount).fill(chunk.i), chunkOffset);
values[1].set(Uint32Array.from({ length: chunk.jCount }, (_, i) => chunk.j0 + i * chunk.Δj), chunkOffset);
for (let j = 0; j < chunk.ΔelemCount; j++) {
values[2 + j].set(chunk.Δelem(j), chunkOffset);
}
for (let j = 2; j < chunk.elemCount; j++) {
values[2 + chunk.ΔelemCount + j - 2].set(chunk.elem(j), chunkOffset);
}
chunkOffset += chunk.jCount;
}
offset += chunkOffset - offset;
} catch (e) {
console.warn(`Error processing sequence ${sequence}:`, e);
}
});
if (offset !== totalCount) {
console.warn(`Offset mismatch: ${offset}${totalCount}`);
}
console.log(`Concatenated ${totalCount} points, ${values.length} value arrays`);
return { positions, values, udv };
}, },
},
*/
heatmapTitle () { heatmapTitle () {
let title = this.heatmapValue; let title = this.heatmapValue;
@@ -929,6 +845,7 @@ export default {
} }
} }
await this.$root.sleep(300); await this.$root.sleep(300);
this.sequenceDataElements = [];
this.getSequenceData(); this.getSequenceData();
}, },
@@ -1087,12 +1004,14 @@ export default {
return [[λ0 - , φ0 - ], [λ1 + , φ1 + ]]; return [[λ0 - , φ0 - ], [λ1 + , φ1 + ]];
}, },
async getSequenceData () { async getSequenceData (sequenceNumbers, types = [2, 3]) {
const types = ["p", "R", "F"]; //const types = [2, 3]; // Bundle types: 2 → raw/gun data; 3 final data. See bundles.js
const sequenceList = await this.api([`/project/${this.$route.params.project}/sequence`]);
// FIXME if sequenceList is undefined the API call failed. It should error and maybe retry if (!sequenceNumbers) {
const sequenceNumbers = sequenceList.map(i => i.sequence); const sequenceList = await this.api([`/project/${this.$route.params.project}/sequence`]);
sequenceNumbers = sequenceList?.map(i => i.sequence) ?? [];
}
const sequenceCount = sequenceNumbers.length * types.length; const sequenceCount = sequenceNumbers.length * types.length;
let count = 0; let count = 0;
@@ -1129,33 +1048,141 @@ export default {
} }
for (const sequence of sequenceNumbers) { for (const sequence of sequenceNumbers) {
try { for (const type of types) {
const url = `/project/${self.$route.params.project}/sequence/${sequence}?type=2`; try {
const url = `/project/${self.$route.params.project}/sequence/${sequence}?type=${type}`;
const sequenceData = await download(url); const sequenceData = await download(url);
if (sequenceData) { if (sequenceData) {
yield { yield {
id: `seq-${sequence}`, id: `seq-${sequence}-${type}`,
sequence: sequence, sequence: sequence,
data: sequenceData.data type: type,
}; data: sequenceData.data
};
}
} catch (err) {
console.error(`Error downloading sequence ${sequence}`);
console.error(err);
} }
} catch (err) {
console.error(`Error downloading sequence ${sequence}`);
console.error(err);
} }
} }
}; };
const transferData = () => {
this.sequenceBinaryData = this.getSequenceBinaryData(2);
this.sequenceBinaryDataFinal = this.getSequenceBinaryData(3);
};
for await (const value of iterator()) { for await (const value of iterator()) {
this.loadingProgress = ++count/sequenceCount*100; this.loadingProgress = ++count/sequenceCount*100;
//console.log("PRG", count, sequenceCount, this.loadingProgress, ); //console.log("PRG", count, sequenceCount, this.loadingProgress, );
this.sequenceDataElements.push(Object.freeze(value)); this.sequenceDataElements.push(Object.freeze(value));
} }
transferData();
this.loadingProgress = null; this.loadingProgress = null;
console.log("passed for await", deck); console.log("passed for await", deck);
}, },
getSequenceBinaryData (type) {
const sequences = this.sequenceDataElements?.filter( el => el.type == type)?.sort((a, b) => a.sequence - b.sequence) || [];
if (!sequences.length) {
console.warn('No sequence data available');
return { positions: new Float32Array(0), values: [], udv: type };
}
// Validate first sequence to get array sizes
let firstBundle;
try {
firstBundle = DougalBinaryBundle.clone(sequences[0].data);
if (!firstBundle.chunks || typeof firstBundle.chunks !== 'function') {
throw new Error('Invalid DougalBinaryBundle: chunks method missing');
}
if (!firstBundle.chunks().length) {
throw new Error('Invalid DougalBinaryBundle: bundle has no chunks');
}
} catch (e) {
console.error('Failed to process first sequence:', e);
return { positions: new Float32Array(0), values: [], udv: type };
}
const totalCount = sequences.reduce((acc, { data }) => {
try {
const bundle = DougalBinaryBundle.clone(data);
return acc + bundle.chunks().reduce((sum, chunk) => sum + chunk.jCount, 0);
} catch (e) {
console.warn('Skipping invalid sequence data:', e);
return acc;
}
}, 0);
if (totalCount === 0) {
console.warn('No valid points found in sequences');
return { positions: new Float32Array(0), values: [], udv: type };
}
const ΔelemCount = firstBundle.chunks()[0].ΔelemCount;
const elemCount = firstBundle.chunks()[0].elemCount;
const positions = new Float32Array(totalCount * 2);
const values = new Array(ΔelemCount + elemCount + 2);
for (let k = 0; k < values.length; k++) {
values[k] = new (k === 0 ? Uint16Array : k === 1 ? Uint32Array : k === 2 ? BigUint64Array : Float32Array)(totalCount);
}
let offset = 0;
let udv = 2;
sequences.forEach(({ data, sequence }) => {
try {
const bundle = DougalBinaryBundle.clone(data);
const chunks = bundle.chunks();
if (!chunks.length) {
console.warn(`No chunks in sequence ${sequence}`);
return;
}
udv = chunks[0].udv;
if (udv != type) {
console.warn(`Found bundle with udv = ${udv} but I'm only expecting udv = ${type}`);
}
let chunkOffset = offset;
for (const chunk of chunks) {
const λarray = chunk.elem(0);
const φarray = chunk.elem(1);
for (let i = 0; i < λarray.length; i++) {
positions[chunkOffset * 2 + i * 2] = λarray[i];
positions[chunkOffset * 2 + i * 2 + 1] = φarray[i];
}
values[0].set(new Uint16Array(chunk.jCount).fill(chunk.i), chunkOffset);
values[1].set(Uint32Array.from({ length: chunk.jCount }, (_, i) => chunk.j0 + i * chunk.Δj), chunkOffset);
for (let j = 0; j < chunk.ΔelemCount; j++) {
values[2 + j].set(chunk.Δelem(j), chunkOffset);
}
for (let j = 2; j < chunk.elemCount; j++) {
values[2 + chunk.ΔelemCount + j - 2].set(chunk.elem(j), chunkOffset);
}
chunkOffset += chunk.jCount;
}
offset += chunkOffset - offset;
} catch (e) {
console.warn(`Error processing sequence ${sequence}:`, e);
}
});
if (offset !== totalCount) {
console.warn(`Offset mismatch: ${offset}${totalCount}`);
}
console.log(`Concatenated ${totalCount} points, ${values.length} value arrays`);
return { positions, values, udv };
},
async initLayers (gl) { async initLayers (gl) {
//console.log("SHOULD BE INITIALISING LAYERS HERE", gl); //console.log("SHOULD BE INITIALISING LAYERS HERE", gl);
this.decodeURL(); this.decodeURL();