Loading app/src/components/RightPanel/ChromatinViewportConfigurationPanel.tsx +2 −2 Original line number Diff line number Diff line Loading @@ -602,13 +602,13 @@ export function ChromatinViewportConfigurationPanel(props: { options={data3DOptions} onChange={onChangeSecondaryData} />)} <PrimaryButton text='Add Data' style={{ marginTop: '8px' }} disabled={!enableAddDataButton} onClick={addData} /> <DefaultButton text='Add Data' style={{ marginTop: '8px' }} disabled={!enableAddDataButton} onClick={addData} /> <div style={{ display: 'block', width: '100%', marginTop: '16px' }}></div> {configuration.data.map((datum, index) => (<div className={"treeViewListItem " + (configuration.selectedDatum == index ? 'selected' : '')} key={index} onClick={() => setSelectedDatum(index)}> <span style={{ display: 'block', width: '4px' }}></span> <Text className="text" nowrap>{datum.id}</Text> <Text className="text" nowrap>{data.data.find(d => d.id == datum.id)?.name || 'No Name (BUG)'}</Text> <Delete16Regular primaryFill={'white'} className='icon iconHoverRed' onClick={(e) => { e.stopPropagation(); removeData3D(index); }}></Delete16Regular> </div>) )} Loading app/src/components/RightPanel/SelectionsPart.tsx +9 −8 Original line number Diff line number Diff line Loading @@ -49,7 +49,6 @@ export function SelectionsPart<T extends ConfigurationsWithSelections>(props: Pr const dataSize = data.data.find(d => d.id == selectedDataPartID)?.values?.length; if (dataSize) { console.log('adding selection'); globalSelectionsDispatch({ type: SelectionActionKind.ADD, dataID: selectedDataPartID as DataID, dataSize }); } } Loading @@ -67,8 +66,6 @@ export function SelectionsPart<T extends ConfigurationsWithSelections>(props: Pr ...configuration, data: newData }); console.log(configuration); } else { updateConfiguration({ ...configuration, Loading @@ -93,16 +90,20 @@ export function SelectionsPart<T extends ConfigurationsWithSelections>(props: Pr } const setSelectionVisiblity = (selectionID: SelectionID, visible: boolean, dataIndex = 0) => { if (!configuration.data || (Array.isArray(configuration.data) && configuration.data.length === 0)) return; if (!configuration.data || ((Array.isArray(configuration.data) && configuration.data.length == 0))) { return; } if (Array.isArray(configuration.data)) { const associatedSelectionIndex = configuration.data[dataIndex].selections.findIndex(s => s.selectionID == selectionID); const newData = { ...configuration.data, const associatedSelectionIndex = configuration.data[props.selectedDataIndex].selections.findIndex(s => s.selectionID == selectionID); const newData = [...configuration.data]; newData[props.selectedDataIndex] = { ...newData[props.selectedDataIndex], selections: configuration.data[dataIndex].selections.map((s: ViewportSelectionOptions) => { return { selectionID: s.selectionID, visible: s.visible } }), }; newData.selections[associatedSelectionIndex].visible = visible; newData[props.selectedDataIndex].selections[associatedSelectionIndex].visible = visible; updateConfiguration({ ...configuration, Loading app/src/components/viewports/ChromatinViewport.tsx +54 −102 Original line number Diff line number Diff line Loading @@ -99,7 +99,7 @@ export function ChromatinViewport(props: { const render = async (frametime: number) => { await newViewport.render(frametime); //~ label rendered scene. setLabels(await layoutGenerator.getLabelPositions()); // setLabels(await layoutGenerator.getLabelPositions()); requestAnimationFrame(render); } Loading @@ -117,22 +117,22 @@ export function ChromatinViewport(props: { }, [layoutGenerator, viewport, viewport.width, viewport.height]); // Camera Update useDeepCompareEffect(() => { viewport.cameraConfiguration = configuration.camera; }, [configuration.camera]); // useDeepCompareEffect(() => { // viewport.cameraConfiguration = configuration.camera; // }, [configuration.camera]); useDeepCompareEffect(() => { if (!viewport.camera || !viewport.canvas) return; // useDeepCompareEffect(() => { // if (!viewport.camera || !viewport.canvas) return; const timer = setTimeout(() => { updateConfiguration({ ...configuration, camera: viewport.cameraConfiguration }); }, 500) // const timer = setTimeout(() => { // updateConfiguration({ // ...configuration, // camera: viewport.cameraConfiguration // }); // }, 500) return () => clearTimeout(timer); }, [viewport.cameraConfiguration]); // return () => clearTimeout(timer); // }, [viewport.cameraConfiguration]); // Disable camera if control is pressed useEffect(() => { Loading @@ -154,6 +154,7 @@ export function ChromatinViewport(props: { useEffect(() => { if (!viewport.canvas) return; console.log('ChromatinViewport::Rebuild'); viewport.clearChromatin(); for (const [configurationDatumIndex, configurationDatum] of configuration.data.entries()) { Loading Loading @@ -245,7 +246,31 @@ export function ChromatinViewport(props: { 1.0 ))); } else if (configurationDatum.colorMappingMode == "selections") { newColors[configurationDatumIndex] = data3D.cacheColorArray(new Array(binsAmount).fill(vec4.fromValues(1.0, 1.0, 1.0, 1.0))); const selections = globalSelections.selections.filter(s => s.dataID == configurationDatum.id); const colors: Array<vec4> = [vec4.fromValues(1.0, 1.0, 1.0, 1.0)]; const finalColorIndices = new Uint16Array(binsAmount); for (let selectionIndex = 0; selectionIndex < selections.length; selectionIndex++) { const selection = selections[selectionIndex]; const associatedData = configurationDatum.selections.find(s => s.selectionID == selection.id) ?? getDefaultViewportSelectionOptions(selection.id); if (!associatedData.visible) { continue; } colors.push(vec4.fromValues(selection.color.r, selection.color.g, selection.color.b, selection.color.a)); const colorIndex = colors.length - 1; for (let i = 0; i < binsAmount; i++) { finalColorIndices[i] = selection.bins[i] * colorIndex + (1 - selection.bins[i]) * finalColorIndices[i]; } } const finalColors: Array<vec4> = new Array(binsAmount); for (let i = 0; i < binsAmount; i++) { finalColors[i] = colors[finalColorIndices[i]]; } newColors[configurationDatumIndex] = data3D.cacheColorArray(finalColors); } } Loading Loading @@ -476,80 +501,12 @@ export function ChromatinViewport(props: { const colorScale = chroma.scale(['white', 'red']); setInnerColors(() => mapScaleToChromatin(densities, colorScale)); } */ setColors(newColors); }, [viewport, globalSelections.selections, configuration.data, configuration.sasa, data.data, configuration.chromosomes, configuration.density]); // Calculate/Cache border colors (selections) // useEffect(() => { // if (!viewport || !configuration.data) return; // const datum = configuration.data; // const binPositions = data.data.filter(d => d.id == datum.id)[0] as BinPositionsData; // const chromosomeSlices = binPositions.chromosomes; // const selections = globalSelections.selections.filter(s => s.dataID == datum.id); // if (selections.length <= 0) { // return; // } // // Reset colors // // Color by mapping & selection // // console.time('colorBins::selections'); // const allBorderColors: Array<Array<vec4>> = new Array(binPositions.chromosomes.length).fill([]); // const allBinIds: number[][] = new Array(binPositions.chromosomes.length).fill([]); //~ TODO: actually fill below... // for (let chromosomeIndex = 0; chromosomeIndex < configuration.chromosomes.length; chromosomeIndex++) { // const chromatinPart = viewport.getChromatinPartByChromosomeIndex(chromosomeIndex); // if (!chromatinPart) { // continue; // } // const colors: Array<vec4> = [vec4.fromValues(1.0, 1.0, 1.0, 1.0)]; // const binsLength = chromatinPart.getBinsPositions().length; // const finalColorIndices = new Uint16Array(binsLength); // const binIdsThisChromosome = new Array(binsLength).fill(-1); // for (let selectionIndex = 0; selectionIndex < selections.length; selectionIndex++) { // const selection = selections[selectionIndex]; // const associatedData = datum.selections.find(s => s.selectionID == selection.id) ?? getDefaultViewportSelectionOptions(selection.id); // if (!associatedData.visible) { // continue; // } // colors.push(vec4.fromValues(selection.color.r, selection.color.g, selection.color.b, selection.color.a)); // const colorIndex = colors.length - 1; // for (let i = 0; i < binsLength; i++) { // const j = chromosomeSlices[chromosomeIndex].from + i; // finalColorIndices[i] = selection.bins[j] * colorIndex + (1 - selection.bins[j]) * finalColorIndices[i]; // //~ selection IDs // //~ TODO: check this later for cases where selections overlap... // const binInSelection = selection.bins[i]; // if (binInSelection == 1) { // binIdsThisChromosome[i] = selection.bins[i] * isoSelectionID.unwrap(selection.id); //~ (0 or 1) * selection.id // } //~ otherwise, just leave what's there before // } // } // const finalColors: Array<vec4> = new Array(binsLength); // for (let i = 0; i < binsLength; i++) { // finalColors[i] = colors[finalColorIndices[i]]; // } // allBorderColors[chromosomeIndex] = chromatinPart.cacheColorArray(finalColors); // allBinIds[chromosomeIndex] = binIdsThisChromosome; // } // setBorderColors(allBorderColors); // setBinIds(allBinIds); // // console.timeEnd('colorBins::selections'); // }, [viewport, globalSelections.selections, configuration.representation, configuration.data, data.data, configuration.chromosomes]); //~ Propagate selections to labelLayoutGenerator useEffect(() => { layoutGenerator.selections = globalSelections.selections; Loading Loading @@ -579,10 +536,10 @@ export function ChromatinViewport(props: { const data3D = viewport.getChromatinPartByDataId(configurationDatumIndex); if (data3D && colors.length > configurationDatumIndex && colors[configurationDatumIndex]) { data3D.structure.setColors(colors[configurationDatumIndex]); if (data3D.structure instanceof ContinuousTube) { data3D.structure.setColors2(colors[configurationDatumIndex]); data3D.structure.setColorsCombined(colors[configurationDatumIndex]); } else { data3D.structure.setColors(colors[configurationDatumIndex]); } } } Loading Loading @@ -802,24 +759,19 @@ export function ChromatinViewport(props: { if (tool.type == ChromatinViewportToolType.PointSelection) { newBins[closestIntersection.binIndex] = isSecondaryModPressed ? 0 : 1; } else if (tool.type == ChromatinViewportToolType.SphereSelection) { // const sphereCenter = vec3.add(vec3.create(), closestIntersection.ray.origin, vec3.scale(vec3.create(), closestIntersection.ray.direction, closestIntersection.distance)); // const sphereRadius = tool.radius; // const value = isSecondaryModPressed ? 0 : 1; const sphereCenter = vec3.add(vec3.create(), closestIntersection.ray.origin, vec3.scale(vec3.create(), closestIntersection.ray.direction, closestIntersection.distance)); const sphereRadius = tool.radius; const value = isSecondaryModPressed ? 0 : 1; // for (let chromosomeIndex = 0; chromosomeIndex < configuration.chromosomes.length; chromosomeIndex++) { // const chromatinPart = viewport.getChromatinPartByChromosomeIndex(chromosomeIndex); // if (!chromatinPart || !configuration.chromosomes[chromosomeIndex]) continue; const binsPositions = selectedChromatinPart.getBinsPositions(); // const binsPositions = chromatinPart.getBinsPositions(); // const offset = binPositions.chromosomes[chromosomeIndex].from; // for (let binIndex = 0; binIndex < binsPositions.length; binIndex++) { // const binPosition = binsPositions[binIndex]; for (let binIndex = 0; binIndex < binsPositions.length; binIndex++) { const binPosition = binsPositions[binIndex]; // if (vec3.distance(binPosition, sphereCenter) < sphereRadius) { // newBins[offset + binIndex] = value; // } // } // } if (vec3.distance(binPosition, sphereCenter) < sphereRadius) { newBins[binIndex] = value; } } } else if (tool.type == ChromatinViewportToolType.JoinSelection) { // if (tool.from == null) { // updateConfiguration({ Loading app/src/modules/storage/state.ts +1 −1 Original line number Diff line number Diff line Loading @@ -5,7 +5,7 @@ import { WorkspaceStorage } from "./models/workspace"; // increment when the current application // can no longer correctly load previously created application states export const APPLICATION_STATE_VERSION = 4; export const APPLICATION_STATE_VERSION = 5; export interface ApplicationState { data?: DataState; Loading libs/graphics/src/primitives/continuous_tube.ts +4 −0 Original line number Diff line number Diff line Loading @@ -401,6 +401,10 @@ export class ContinuousTube implements HighLevelStructure { return; } if (colors.length != 2 * (this._points.length - 1)) { throw new Error(`Number of colors must be '2 * (points - 1)'. Number of colors provided is ${colors.length}, expected ${(this._points.length - 1) * 2}`); } const u8view = this.buffer.u8view; for (let i = 0; i < this._points.length - 1; i++) { const color = colors[2 * i]; Loading Loading
app/src/components/RightPanel/ChromatinViewportConfigurationPanel.tsx +2 −2 Original line number Diff line number Diff line Loading @@ -602,13 +602,13 @@ export function ChromatinViewportConfigurationPanel(props: { options={data3DOptions} onChange={onChangeSecondaryData} />)} <PrimaryButton text='Add Data' style={{ marginTop: '8px' }} disabled={!enableAddDataButton} onClick={addData} /> <DefaultButton text='Add Data' style={{ marginTop: '8px' }} disabled={!enableAddDataButton} onClick={addData} /> <div style={{ display: 'block', width: '100%', marginTop: '16px' }}></div> {configuration.data.map((datum, index) => (<div className={"treeViewListItem " + (configuration.selectedDatum == index ? 'selected' : '')} key={index} onClick={() => setSelectedDatum(index)}> <span style={{ display: 'block', width: '4px' }}></span> <Text className="text" nowrap>{datum.id}</Text> <Text className="text" nowrap>{data.data.find(d => d.id == datum.id)?.name || 'No Name (BUG)'}</Text> <Delete16Regular primaryFill={'white'} className='icon iconHoverRed' onClick={(e) => { e.stopPropagation(); removeData3D(index); }}></Delete16Regular> </div>) )} Loading
app/src/components/RightPanel/SelectionsPart.tsx +9 −8 Original line number Diff line number Diff line Loading @@ -49,7 +49,6 @@ export function SelectionsPart<T extends ConfigurationsWithSelections>(props: Pr const dataSize = data.data.find(d => d.id == selectedDataPartID)?.values?.length; if (dataSize) { console.log('adding selection'); globalSelectionsDispatch({ type: SelectionActionKind.ADD, dataID: selectedDataPartID as DataID, dataSize }); } } Loading @@ -67,8 +66,6 @@ export function SelectionsPart<T extends ConfigurationsWithSelections>(props: Pr ...configuration, data: newData }); console.log(configuration); } else { updateConfiguration({ ...configuration, Loading @@ -93,16 +90,20 @@ export function SelectionsPart<T extends ConfigurationsWithSelections>(props: Pr } const setSelectionVisiblity = (selectionID: SelectionID, visible: boolean, dataIndex = 0) => { if (!configuration.data || (Array.isArray(configuration.data) && configuration.data.length === 0)) return; if (!configuration.data || ((Array.isArray(configuration.data) && configuration.data.length == 0))) { return; } if (Array.isArray(configuration.data)) { const associatedSelectionIndex = configuration.data[dataIndex].selections.findIndex(s => s.selectionID == selectionID); const newData = { ...configuration.data, const associatedSelectionIndex = configuration.data[props.selectedDataIndex].selections.findIndex(s => s.selectionID == selectionID); const newData = [...configuration.data]; newData[props.selectedDataIndex] = { ...newData[props.selectedDataIndex], selections: configuration.data[dataIndex].selections.map((s: ViewportSelectionOptions) => { return { selectionID: s.selectionID, visible: s.visible } }), }; newData.selections[associatedSelectionIndex].visible = visible; newData[props.selectedDataIndex].selections[associatedSelectionIndex].visible = visible; updateConfiguration({ ...configuration, Loading
app/src/components/viewports/ChromatinViewport.tsx +54 −102 Original line number Diff line number Diff line Loading @@ -99,7 +99,7 @@ export function ChromatinViewport(props: { const render = async (frametime: number) => { await newViewport.render(frametime); //~ label rendered scene. setLabels(await layoutGenerator.getLabelPositions()); // setLabels(await layoutGenerator.getLabelPositions()); requestAnimationFrame(render); } Loading @@ -117,22 +117,22 @@ export function ChromatinViewport(props: { }, [layoutGenerator, viewport, viewport.width, viewport.height]); // Camera Update useDeepCompareEffect(() => { viewport.cameraConfiguration = configuration.camera; }, [configuration.camera]); // useDeepCompareEffect(() => { // viewport.cameraConfiguration = configuration.camera; // }, [configuration.camera]); useDeepCompareEffect(() => { if (!viewport.camera || !viewport.canvas) return; // useDeepCompareEffect(() => { // if (!viewport.camera || !viewport.canvas) return; const timer = setTimeout(() => { updateConfiguration({ ...configuration, camera: viewport.cameraConfiguration }); }, 500) // const timer = setTimeout(() => { // updateConfiguration({ // ...configuration, // camera: viewport.cameraConfiguration // }); // }, 500) return () => clearTimeout(timer); }, [viewport.cameraConfiguration]); // return () => clearTimeout(timer); // }, [viewport.cameraConfiguration]); // Disable camera if control is pressed useEffect(() => { Loading @@ -154,6 +154,7 @@ export function ChromatinViewport(props: { useEffect(() => { if (!viewport.canvas) return; console.log('ChromatinViewport::Rebuild'); viewport.clearChromatin(); for (const [configurationDatumIndex, configurationDatum] of configuration.data.entries()) { Loading Loading @@ -245,7 +246,31 @@ export function ChromatinViewport(props: { 1.0 ))); } else if (configurationDatum.colorMappingMode == "selections") { newColors[configurationDatumIndex] = data3D.cacheColorArray(new Array(binsAmount).fill(vec4.fromValues(1.0, 1.0, 1.0, 1.0))); const selections = globalSelections.selections.filter(s => s.dataID == configurationDatum.id); const colors: Array<vec4> = [vec4.fromValues(1.0, 1.0, 1.0, 1.0)]; const finalColorIndices = new Uint16Array(binsAmount); for (let selectionIndex = 0; selectionIndex < selections.length; selectionIndex++) { const selection = selections[selectionIndex]; const associatedData = configurationDatum.selections.find(s => s.selectionID == selection.id) ?? getDefaultViewportSelectionOptions(selection.id); if (!associatedData.visible) { continue; } colors.push(vec4.fromValues(selection.color.r, selection.color.g, selection.color.b, selection.color.a)); const colorIndex = colors.length - 1; for (let i = 0; i < binsAmount; i++) { finalColorIndices[i] = selection.bins[i] * colorIndex + (1 - selection.bins[i]) * finalColorIndices[i]; } } const finalColors: Array<vec4> = new Array(binsAmount); for (let i = 0; i < binsAmount; i++) { finalColors[i] = colors[finalColorIndices[i]]; } newColors[configurationDatumIndex] = data3D.cacheColorArray(finalColors); } } Loading Loading @@ -476,80 +501,12 @@ export function ChromatinViewport(props: { const colorScale = chroma.scale(['white', 'red']); setInnerColors(() => mapScaleToChromatin(densities, colorScale)); } */ setColors(newColors); }, [viewport, globalSelections.selections, configuration.data, configuration.sasa, data.data, configuration.chromosomes, configuration.density]); // Calculate/Cache border colors (selections) // useEffect(() => { // if (!viewport || !configuration.data) return; // const datum = configuration.data; // const binPositions = data.data.filter(d => d.id == datum.id)[0] as BinPositionsData; // const chromosomeSlices = binPositions.chromosomes; // const selections = globalSelections.selections.filter(s => s.dataID == datum.id); // if (selections.length <= 0) { // return; // } // // Reset colors // // Color by mapping & selection // // console.time('colorBins::selections'); // const allBorderColors: Array<Array<vec4>> = new Array(binPositions.chromosomes.length).fill([]); // const allBinIds: number[][] = new Array(binPositions.chromosomes.length).fill([]); //~ TODO: actually fill below... // for (let chromosomeIndex = 0; chromosomeIndex < configuration.chromosomes.length; chromosomeIndex++) { // const chromatinPart = viewport.getChromatinPartByChromosomeIndex(chromosomeIndex); // if (!chromatinPart) { // continue; // } // const colors: Array<vec4> = [vec4.fromValues(1.0, 1.0, 1.0, 1.0)]; // const binsLength = chromatinPart.getBinsPositions().length; // const finalColorIndices = new Uint16Array(binsLength); // const binIdsThisChromosome = new Array(binsLength).fill(-1); // for (let selectionIndex = 0; selectionIndex < selections.length; selectionIndex++) { // const selection = selections[selectionIndex]; // const associatedData = datum.selections.find(s => s.selectionID == selection.id) ?? getDefaultViewportSelectionOptions(selection.id); // if (!associatedData.visible) { // continue; // } // colors.push(vec4.fromValues(selection.color.r, selection.color.g, selection.color.b, selection.color.a)); // const colorIndex = colors.length - 1; // for (let i = 0; i < binsLength; i++) { // const j = chromosomeSlices[chromosomeIndex].from + i; // finalColorIndices[i] = selection.bins[j] * colorIndex + (1 - selection.bins[j]) * finalColorIndices[i]; // //~ selection IDs // //~ TODO: check this later for cases where selections overlap... // const binInSelection = selection.bins[i]; // if (binInSelection == 1) { // binIdsThisChromosome[i] = selection.bins[i] * isoSelectionID.unwrap(selection.id); //~ (0 or 1) * selection.id // } //~ otherwise, just leave what's there before // } // } // const finalColors: Array<vec4> = new Array(binsLength); // for (let i = 0; i < binsLength; i++) { // finalColors[i] = colors[finalColorIndices[i]]; // } // allBorderColors[chromosomeIndex] = chromatinPart.cacheColorArray(finalColors); // allBinIds[chromosomeIndex] = binIdsThisChromosome; // } // setBorderColors(allBorderColors); // setBinIds(allBinIds); // // console.timeEnd('colorBins::selections'); // }, [viewport, globalSelections.selections, configuration.representation, configuration.data, data.data, configuration.chromosomes]); //~ Propagate selections to labelLayoutGenerator useEffect(() => { layoutGenerator.selections = globalSelections.selections; Loading Loading @@ -579,10 +536,10 @@ export function ChromatinViewport(props: { const data3D = viewport.getChromatinPartByDataId(configurationDatumIndex); if (data3D && colors.length > configurationDatumIndex && colors[configurationDatumIndex]) { data3D.structure.setColors(colors[configurationDatumIndex]); if (data3D.structure instanceof ContinuousTube) { data3D.structure.setColors2(colors[configurationDatumIndex]); data3D.structure.setColorsCombined(colors[configurationDatumIndex]); } else { data3D.structure.setColors(colors[configurationDatumIndex]); } } } Loading Loading @@ -802,24 +759,19 @@ export function ChromatinViewport(props: { if (tool.type == ChromatinViewportToolType.PointSelection) { newBins[closestIntersection.binIndex] = isSecondaryModPressed ? 0 : 1; } else if (tool.type == ChromatinViewportToolType.SphereSelection) { // const sphereCenter = vec3.add(vec3.create(), closestIntersection.ray.origin, vec3.scale(vec3.create(), closestIntersection.ray.direction, closestIntersection.distance)); // const sphereRadius = tool.radius; // const value = isSecondaryModPressed ? 0 : 1; const sphereCenter = vec3.add(vec3.create(), closestIntersection.ray.origin, vec3.scale(vec3.create(), closestIntersection.ray.direction, closestIntersection.distance)); const sphereRadius = tool.radius; const value = isSecondaryModPressed ? 0 : 1; // for (let chromosomeIndex = 0; chromosomeIndex < configuration.chromosomes.length; chromosomeIndex++) { // const chromatinPart = viewport.getChromatinPartByChromosomeIndex(chromosomeIndex); // if (!chromatinPart || !configuration.chromosomes[chromosomeIndex]) continue; const binsPositions = selectedChromatinPart.getBinsPositions(); // const binsPositions = chromatinPart.getBinsPositions(); // const offset = binPositions.chromosomes[chromosomeIndex].from; // for (let binIndex = 0; binIndex < binsPositions.length; binIndex++) { // const binPosition = binsPositions[binIndex]; for (let binIndex = 0; binIndex < binsPositions.length; binIndex++) { const binPosition = binsPositions[binIndex]; // if (vec3.distance(binPosition, sphereCenter) < sphereRadius) { // newBins[offset + binIndex] = value; // } // } // } if (vec3.distance(binPosition, sphereCenter) < sphereRadius) { newBins[binIndex] = value; } } } else if (tool.type == ChromatinViewportToolType.JoinSelection) { // if (tool.from == null) { // updateConfiguration({ Loading
app/src/modules/storage/state.ts +1 −1 Original line number Diff line number Diff line Loading @@ -5,7 +5,7 @@ import { WorkspaceStorage } from "./models/workspace"; // increment when the current application // can no longer correctly load previously created application states export const APPLICATION_STATE_VERSION = 4; export const APPLICATION_STATE_VERSION = 5; export interface ApplicationState { data?: DataState; Loading
libs/graphics/src/primitives/continuous_tube.ts +4 −0 Original line number Diff line number Diff line Loading @@ -401,6 +401,10 @@ export class ContinuousTube implements HighLevelStructure { return; } if (colors.length != 2 * (this._points.length - 1)) { throw new Error(`Number of colors must be '2 * (points - 1)'. Number of colors provided is ${colors.length}, expected ${(this._points.length - 1) * 2}`); } const u8view = this.buffer.u8view; for (let i = 0; i < this._points.length - 1; i++) { const color = colors[2 * i]; Loading