diff --git a/lib/www/client/source/src/views/Map.vue b/lib/www/client/source/src/views/Map.vue index eac2313..58ba928 100644 --- a/lib/www/client/source/src/views/Map.vue +++ b/lib/www/client/source/src/views/Map.vue @@ -578,6 +578,7 @@ export default { layerSelection: [], layersAvailable: {}, sequenceDataElements: [], + sequenceBinaryData: { positions: new Float32Array(0), values: [], udv: 2 }, sequenceDataTStamp: null, loadingProgress: null, viewState: {}, @@ -613,99 +614,14 @@ export default { return this.sequenceDataElements?.map( el => el.data ); }, + /* sequenceBinaryData() { - const sequences = this.sequenceDataElements?.sort((a, b) => a.sequence - b.sequence) || []; - 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 }; + return this.getSequenceBinaryData(2); // Raw + gun data }, + }, + */ + heatmapTitle () { let title = this.heatmapValue; @@ -929,6 +845,7 @@ export default { } } await this.$root.sleep(300); + this.sequenceDataElements = []; this.getSequenceData(); }, @@ -1087,12 +1004,14 @@ export default { return [[λ0 - mλ, φ0 - mφ], [λ1 + mλ, φ1 + mφ]]; }, - async getSequenceData () { + async getSequenceData (sequenceNumbers, types = [2, 3]) { - const types = ["p", "R", "F"]; - 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 - const sequenceNumbers = sequenceList.map(i => i.sequence); + //const types = [2, 3]; // Bundle types: 2 → raw/gun data; 3 ‒ final data. See bundles.js + + if (!sequenceNumbers) { + const sequenceList = await this.api([`/project/${this.$route.params.project}/sequence`]); + sequenceNumbers = sequenceList?.map(i => i.sequence) ?? []; + } const sequenceCount = sequenceNumbers.length * types.length; let count = 0; @@ -1129,33 +1048,141 @@ export default { } for (const sequence of sequenceNumbers) { - try { - const url = `/project/${self.$route.params.project}/sequence/${sequence}?type=2`; + for (const type of types) { + try { + const url = `/project/${self.$route.params.project}/sequence/${sequence}?type=${type}`; - const sequenceData = await download(url); - if (sequenceData) { - yield { - id: `seq-${sequence}`, - sequence: sequence, - data: sequenceData.data - }; + const sequenceData = await download(url); + if (sequenceData) { + yield { + id: `seq-${sequence}-${type}`, + sequence: sequence, + 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()) { this.loadingProgress = ++count/sequenceCount*100; //console.log("PRG", count, sequenceCount, this.loadingProgress, ); this.sequenceDataElements.push(Object.freeze(value)); } + + transferData(); + this.loadingProgress = null; 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) { //console.log("SHOULD BE INITIALISING LAYERS HERE", gl); this.decodeURL();