Loading libs/graphics/src/primitives/continuous_tube.ts +0 −104 Original line number Original line Diff line number Diff line Loading @@ -302,29 +302,6 @@ export class ContinuousTube implements HighLevelStructure { return this._points.length - 1; return this._points.length - 1; } } public resetColorBorder(color: vec4): void { if (!this.buffer) return; this._colors.fill(color); this._colors2.fill(color); this._borderColors.fill(color); this._borderColors2.fill(color); const colorsArrayBuffer = new Uint8Array([ color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255, color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255, color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255, color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255 ]); const u8view = this.buffer.u8view; for (let i = 0; i < this._points.length - 1; i++) { u8view.set(colorsArrayBuffer, (this._roundedConesPosition + i) * LL_STRUCTURE_SIZE_BYTES + 64); } } public resetColor(color: vec4): void { public resetColor(color: vec4): void { this._colors.fill(color); this._colors.fill(color); Loading Loading @@ -419,66 +396,6 @@ export class ContinuousTube implements HighLevelStructure { this.buffer.setModifiedBytes({ start: this._roundedConesPosition * LL_STRUCTURE_SIZE_BYTES, end: (this._roundedConesPosition + this._colors.length - 1) * LL_STRUCTURE_SIZE_BYTES }); this.buffer.setModifiedBytes({ start: this._roundedConesPosition * LL_STRUCTURE_SIZE_BYTES, end: (this._roundedConesPosition + this._colors.length - 1) * LL_STRUCTURE_SIZE_BYTES }); } } public resetBorderColors(color: vec4): void { if (!this.buffer) return; this._borderColors.fill(color); this._borderColors2.fill(color); const colorsArrayBuffer = new Uint8Array([ color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255, color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255, ]); const u8view = this.buffer.u8view; for (let i = 0; i < this._points.length - 1; i++) { u8view.set(colorsArrayBuffer, (this._roundedConesPosition + i) * LL_STRUCTURE_SIZE_BYTES + 72); } } public setBorderColors(borderColors: Array<vec4>): void { this._borderColors = borderColors; if (!this.buffer) { return; } const u8view = this.buffer.u8view; for (let i = 0; i < this._points.length - 1; i++) { const color = this._borderColors[i]; const offset = (this._roundedConesPosition + i) * LL_STRUCTURE_SIZE_BYTES; u8view.set([color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255], offset + 72); } this.buffer.setModifiedBytes({ start: this._roundedConesPosition * LL_STRUCTURE_SIZE_BYTES, end: (this._roundedConesPosition + this._points.length) * LL_STRUCTURE_SIZE_BYTES }); } public setBorderColors2(borderColors2: Array<vec4>): void { this._borderColors2 = borderColors2; if (!this.buffer) { return; } const u8view = this.buffer.u8view; for (let i = 0; i < this._points.length - 1; i++) { const color = this._borderColors2[i]; const offset = (this._roundedConesPosition + i) * LL_STRUCTURE_SIZE_BYTES; u8view.set([color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255], offset + 76); } this.buffer.setModifiedBytes({ start: this._roundedConesPosition * LL_STRUCTURE_SIZE_BYTES, end: (this._roundedConesPosition + this._points.length) * LL_STRUCTURE_SIZE_BYTES }); } public resetBorderColors2(color: vec4): void { this._borderColors2.fill(color); this.setBorderColors2(this._borderColors2); } public setColorsCombined(colors: Array<vec4>): void { public setColorsCombined(colors: Array<vec4>): void { if (!this.buffer) { if (!this.buffer) { return; return; Loading @@ -502,27 +419,6 @@ export class ContinuousTube implements HighLevelStructure { this.buffer.setModifiedBytes({ start: this._roundedConesPosition * LL_STRUCTURE_SIZE_BYTES, end: (this._roundedConesPosition + this._points.length + 1) * LL_STRUCTURE_SIZE_BYTES }); this.buffer.setModifiedBytes({ start: this._roundedConesPosition * LL_STRUCTURE_SIZE_BYTES, end: (this._roundedConesPosition + this._points.length + 1) * LL_STRUCTURE_SIZE_BYTES }); } } public setBorderColorsCombined(colors: Array<vec4>): void { if (!this.buffer || colors.length * 2 < this._points.length) { return; } const u8view = this.buffer.u8view; for (let i = 0; i < this._points.length - 1; i++) { const color = colors[2 * i]; const color2 = colors[2 * i + 1]; const offsetBytes = (this._roundedConesPosition + i) * LL_STRUCTURE_SIZE_BYTES; this._borderColors[i] = color; this._borderColors2[i] = color2; u8view.set([color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255, color2[0] * 255, color2[1] * 255, color2[2] * 255, color2[3] * 255], offsetBytes + 72); } this.buffer.setModifiedBytes({ start: this._roundedConesPosition * LL_STRUCTURE_SIZE_BYTES, end: (this._roundedConesPosition + this._points.length + 1) * LL_STRUCTURE_SIZE_BYTES }); } public setSelectionIds(binIds: number[]): void { public setSelectionIds(binIds: number[]): void { if (!this.buffer) { if (!this.buffer) { return; return; Loading libs/graphics/src/primitives/spheres.ts +0 −24 Original line number Original line Diff line number Diff line Loading @@ -167,18 +167,6 @@ export class Spheres implements HighLevelStructure { this.buffer.setModifiedBytes({ start: (this._spheresPosition) * LL_STRUCTURE_SIZE_BYTES, end: (this._spheresPosition + this._colors.length) * LL_STRUCTURE_SIZE_BYTES }); this.buffer.setModifiedBytes({ start: (this._spheresPosition) * LL_STRUCTURE_SIZE_BYTES, end: (this._spheresPosition + this._colors.length) * LL_STRUCTURE_SIZE_BYTES }); } } public resetBorderColors(color: vec4): void { this._borderColors.fill(color); if (!this.buffer) return; for (let i = 0; i < this._borderColors.length; i++) { writeSphereToArrayBuffer(this.buffer, this._spheresPosition + i, { borderColor: this._borderColors[i] }); } this.buffer.setModifiedBytes({ start: (this._spheresPosition) * LL_STRUCTURE_SIZE_BYTES, end: (this._spheresPosition + this._borderColors.length) * LL_STRUCTURE_SIZE_BYTES }); } public setColor(i: number, color: vec4): void { public setColor(i: number, color: vec4): void { this._colors[i] = vec4.clone(color); this._colors[i] = vec4.clone(color); Loading @@ -201,18 +189,6 @@ export class Spheres implements HighLevelStructure { this.buffer.setModifiedBytes({ start: (this._spheresPosition) * LL_STRUCTURE_SIZE_BYTES, end: (this._spheresPosition + this._colors.length) * LL_STRUCTURE_SIZE_BYTES }); this.buffer.setModifiedBytes({ start: (this._spheresPosition) * LL_STRUCTURE_SIZE_BYTES, end: (this._spheresPosition + this._colors.length) * LL_STRUCTURE_SIZE_BYTES }); } } public setBorderColors(colors: Array<vec4>): void { this._borderColors = colors.map(v => vec4.clone(v)); if (!this.buffer) return; for (let i = 0; i < this._borderColors.length; i++) { writeSphereToArrayBuffer(this.buffer, this._spheresPosition + i, { borderColor: this._borderColors[i] }); } this.buffer.setModifiedBytes({ start: (this._spheresPosition) * LL_STRUCTURE_SIZE_BYTES, end: (this._spheresPosition + this._borderColors.length) * LL_STRUCTURE_SIZE_BYTES }); } public getColor(i: number): vec4 | Array<vec4> { public getColor(i: number): vec4 | Array<vec4> { return this._colors[i]; return this._colors[i]; } } Loading libs/graphics/src/viewports/chromatin_viewport.ts +13 −53 Original line number Original line Diff line number Diff line Loading @@ -4,10 +4,8 @@ import { Scene } from "../scene"; import { GraphicsLibrary } from ".."; import { GraphicsLibrary } from ".."; import { Viewport3D } from "."; import { Viewport3D } from "."; import { vec2, vec3, vec4, quat } from "gl-matrix"; import { vec2, vec3, vec4, quat } from "gl-matrix"; import { BoundingBox, BoundingBoxEmpty, BoundingBoxExtendByPoint, Hit, Ray } from "../shared"; import { Hit, Ray } from "../shared"; import { quantile } from 'simple-statistics' import { Spline } from "../primitives/spline"; import { Spline } from "../primitives/spline"; import { Plane, SectionCuts } from "../sectionCuts" const CHROMATIN_OBJECT_NAME = 'CHROMATIN'; const CHROMATIN_OBJECT_NAME = 'CHROMATIN'; Loading @@ -21,21 +19,23 @@ export type ChromatinRepresentationType = ContinuousTube | Spheres | Spline; export class ChromatinPart { export class ChromatinPart { private _chromatinViewport: ChromatinViewport; private _chromatinViewport: ChromatinViewport; private _name: string; private _name: string; private _structure: ChromatinRepresentationType; private _structure: ChromatinRepresentationType; private _highLevelID: number; private _highLevelID: number; private _dataId: number; private _dataId: number; private _chromosomeIndex: number; private _binsPositions: Array<vec3>; private _binsPositions: Array<vec3>; private _binsColor: Array<vec4>; private _binsColor: Array<vec4>; constructor(chromatinViewport: ChromatinViewport, name: string, structure: ChromatinRepresentationType, highLevelID: number, dataId: number, chromosomeIndex: number, binsPositions: Array<vec3>) { constructor(chromatinViewport: ChromatinViewport, name: string, structure: ChromatinRepresentationType, highLevelID: number, dataId: number, binsPositions: Array<vec3>) { this._name = name; this._name = name; this._chromatinViewport = chromatinViewport; this._chromatinViewport = chromatinViewport; this._structure = structure; this._structure = structure; this._highLevelID = highLevelID; this._highLevelID = highLevelID; this._dataId = dataId; this._dataId = dataId; this._chromosomeIndex = chromosomeIndex; this._binsPositions = binsPositions; this._binsPositions = binsPositions; this._binsColor = new Array<vec4>(this._binsPositions.length); this._binsColor = new Array<vec4>(this._binsPositions.length); } } Loading @@ -47,7 +47,6 @@ export class ChromatinPart { // Calculate Intersection // Calculate Intersection const intersection = vec3.add(vec3.create(), ray.origin, vec3.scale(vec3.create(), ray.direction, hit.distance)); const intersection = vec3.add(vec3.create(), ray.origin, vec3.scale(vec3.create(), ray.direction, hit.distance)); // Calculate normal // Calculate normal const i = this._structure.localOffsetOf(LowLevelStructure.RoundedCone, hit.lowLevelIndex); const i = this._structure.localOffsetOf(LowLevelStructure.RoundedCone, hit.lowLevelIndex); Loading @@ -70,18 +69,14 @@ export class ChromatinPart { const lengthOnIntersection = vec3.length(vec3.sub(vec3.create(), from, vec3.sub(vec3.create(), intersection, vec3.scale(vec3.create(), normal, radius)))); const lengthOnIntersection = vec3.length(vec3.sub(vec3.create(), from, vec3.sub(vec3.create(), intersection, vec3.scale(vec3.create(), normal, radius)))); const ratio = lengthOnIntersection / capsuleLength; const ratio = lengthOnIntersection / capsuleLength; if (i == 0) { return 0; } if (i >= this._binsPositions.length) { if (i >= this._binsPositions.length) { return this._binsPositions.length - 1; return this._binsPositions.length - 1; } } if (ratio < 0.5) { if (ratio < 0.5) { return i - 1; } else { return i; return i; } else { return i + 1; } } } else if (this._structure instanceof Spheres) { } else if (this._structure instanceof Spheres) { return this._structure.localOffsetOf(LowLevelStructure.Sphere, hit.lowLevelIndex); return this._structure.localOffsetOf(LowLevelStructure.Sphere, hit.lowLevelIndex); Loading @@ -94,11 +89,11 @@ export class ChromatinPart { public resetColor(color: GPUColorDict): void { public resetColor(color: GPUColorDict): void { if (this._structure instanceof ContinuousTube) { if (this._structure instanceof ContinuousTube) { this._structure.resetColorBorder(vec4.fromValues(color.r, color.g, color.b, color.a)); this._structure.resetColors(vec4.fromValues(color.r, color.g, color.b, color.a)); } else if (this._structure instanceof Spheres) { } else if (this._structure instanceof Spheres) { this._structure.resetColors(vec4.fromValues(color.r, color.g, color.b, color.a)); this._structure.resetColors(vec4.fromValues(color.r, color.g, color.b, color.a)); } else if (this._structure instanceof Spline) { } else if (this._structure instanceof Spline) { this._structure.resetColorBorder(vec4.fromValues(color.r, color.g, color.b, color.a)); this._structure.resetColors(vec4.fromValues(color.r, color.g, color.b, color.a)); } } } } Loading Loading @@ -196,10 +191,6 @@ export class ChromatinPart { public get highLevelID(): number { public get highLevelID(): number { return this._highLevelID; return this._highLevelID; } } public get chromosomeIndex(): number { return this._chromosomeIndex; } } } export type ChromatinIntersection = { export type ChromatinIntersection = { Loading @@ -216,24 +207,9 @@ export type ChromatinIntersection = { export class ChromatinViewport extends Viewport3D { export class ChromatinViewport extends Viewport3D { public _chromatin: Array<ChromatinPart> = []; public _chromatin: Array<ChromatinPart> = []; private maxId = 0; private maxId = 0; private binPositions: vec3[] = []; private binPositions: vec3[] = []; private debugRadius = 5.0; // private sectionCuts: { intersections: vec3[], planes: Plane[] } = { // intersections: [], // planes: [] // } private sectionCuts: SectionCuts = new SectionCuts(); // private box: BoundingBox = BoundingBoxEmpty(); // private yRange = 0; //#region protected debugDisplay = { showBins: true, showPlanes: true, showIntersections: true } //#endregion constructor( constructor( graphicsLibrary: GraphicsLibrary, graphicsLibrary: GraphicsLibrary, Loading @@ -241,7 +217,6 @@ export class ChromatinViewport extends Viewport3D { scene: Scene | null = null, scene: Scene | null = null, camera: OrbitCamera | SmoothCamera | null = null) { camera: OrbitCamera | SmoothCamera | null = null) { super(graphicsLibrary, canvas, scene, camera); super(graphicsLibrary, canvas, scene, camera); // this.calculateSectionCuts(); } } public clearChromatin(): void { public clearChromatin(): void { Loading @@ -252,6 +227,7 @@ export class ChromatinViewport extends Viewport3D { for (let i = 0; i < this._chromatin.length; i++) { for (let i = 0; i < this._chromatin.length; i++) { this._scene.removeStructureByID(this._chromatin[i].highLevelID); this._scene.removeStructureByID(this._chromatin[i].highLevelID); } } this._chromatin = []; this._chromatin = []; } } Loading @@ -271,12 +247,11 @@ export class ChromatinViewport extends Viewport3D { * Adds a part of chromatin to the viewport * Adds a part of chromatin to the viewport * * * @param bins - sequence of points that represent bins of a chromatin part * @param bins - sequence of points that represent bins of a chromatin part * @param center - whether the supplied data should be centered around point [0, 0, 0] * @param dataId - unique id of the supplied data * @param dataId - unique id of the supplied data * * * @returns created structure * @returns created structure */ */ public addPart(chromosomeName: string, bins: Array<{ x: number, y: number, z: number }>, center = false, dataId: number, chromosomeIndex: number, representation: ChromatinRepresentation, update = true): ChromatinPart { public addPart(chromosomeName: string, bins: Array<{ x: number, y: number, z: number }>, dataId: number, representation: ChromatinRepresentation, update = true): ChromatinPart { const pointsVec3 = bins.map(p => vec3.fromValues(p.x, p.y, p.z)); const pointsVec3 = bins.map(p => vec3.fromValues(p.x, p.y, p.z)); this.binPositions = pointsVec3.map(p => vec3.clone(p)); this.binPositions = pointsVec3.map(p => vec3.clone(p)); Loading Loading @@ -316,14 +291,11 @@ export class ChromatinViewport extends Viewport3D { structure, structure, highLevelID, highLevelID, dataId, dataId, chromosomeIndex, this.binPositions, this.binPositions, )); )); this.maxId++; this.maxId++; // this.calculateSectionCuts(); return this._chromatin[this._chromatin.length - 1]; return this._chromatin[this._chromatin.length - 1]; } } Loading @@ -343,37 +315,25 @@ export class ChromatinViewport extends Viewport3D { return this._chromatin; return this._chromatin; } } public getChromatinPartByChromosomeIndex(chromosomeIndex: number): ChromatinPart | null { const chromatinPartIndex = this._chromatin.findIndex(v => v.chromosomeIndex == chromosomeIndex); return this._chromatin[chromatinPartIndex]; } public closestIntersectionBin(screenSpacePosition: { x: number, y: number }): ChromatinIntersection | null { public closestIntersectionBin(screenSpacePosition: { x: number, y: number }): ChromatinIntersection | null { // console.time('ChromatinIntersection::closestIntersectionBin'); const closestIntersection = this.closestIntersection(vec2.fromValues(screenSpacePosition.x, screenSpacePosition.y)); const closestIntersection = this.closestIntersection(vec2.fromValues(screenSpacePosition.x, screenSpacePosition.y)); if (closestIntersection == null) { if (closestIntersection == null) { // console.timeEnd('ChromatinIntersection::closestIntersectionBin'); return null; return null; } } const chromatinPart = this._chromatin.find(chromatinPart => chromatinPart.highLevelID == closestIntersection.highLevelIndex); const chromatinPart = this._chromatin.find(chromatinPart => chromatinPart.highLevelID == closestIntersection.highLevelIndex); if (chromatinPart == undefined) { if (chromatinPart == undefined) { // console.timeEnd('ChromatinIntersection::closestIntersectionBin'); return null; return null; } } const binIndex = chromatinPart.lowLevelIndexToBinIndex(closestIntersection); const binIndex = chromatinPart.lowLevelIndexToBinIndex(closestIntersection); if (binIndex == null) { if (binIndex == null) { // console.timeEnd('ChromatinIntersection::closestIntersectionBin'); return null; return null; } } // console.timeEnd('ChromatinIntersection::closestIntersectionBin'); return { return { chromatinPart, chromatinPart, Loading Loading
libs/graphics/src/primitives/continuous_tube.ts +0 −104 Original line number Original line Diff line number Diff line Loading @@ -302,29 +302,6 @@ export class ContinuousTube implements HighLevelStructure { return this._points.length - 1; return this._points.length - 1; } } public resetColorBorder(color: vec4): void { if (!this.buffer) return; this._colors.fill(color); this._colors2.fill(color); this._borderColors.fill(color); this._borderColors2.fill(color); const colorsArrayBuffer = new Uint8Array([ color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255, color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255, color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255, color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255 ]); const u8view = this.buffer.u8view; for (let i = 0; i < this._points.length - 1; i++) { u8view.set(colorsArrayBuffer, (this._roundedConesPosition + i) * LL_STRUCTURE_SIZE_BYTES + 64); } } public resetColor(color: vec4): void { public resetColor(color: vec4): void { this._colors.fill(color); this._colors.fill(color); Loading Loading @@ -419,66 +396,6 @@ export class ContinuousTube implements HighLevelStructure { this.buffer.setModifiedBytes({ start: this._roundedConesPosition * LL_STRUCTURE_SIZE_BYTES, end: (this._roundedConesPosition + this._colors.length - 1) * LL_STRUCTURE_SIZE_BYTES }); this.buffer.setModifiedBytes({ start: this._roundedConesPosition * LL_STRUCTURE_SIZE_BYTES, end: (this._roundedConesPosition + this._colors.length - 1) * LL_STRUCTURE_SIZE_BYTES }); } } public resetBorderColors(color: vec4): void { if (!this.buffer) return; this._borderColors.fill(color); this._borderColors2.fill(color); const colorsArrayBuffer = new Uint8Array([ color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255, color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255, ]); const u8view = this.buffer.u8view; for (let i = 0; i < this._points.length - 1; i++) { u8view.set(colorsArrayBuffer, (this._roundedConesPosition + i) * LL_STRUCTURE_SIZE_BYTES + 72); } } public setBorderColors(borderColors: Array<vec4>): void { this._borderColors = borderColors; if (!this.buffer) { return; } const u8view = this.buffer.u8view; for (let i = 0; i < this._points.length - 1; i++) { const color = this._borderColors[i]; const offset = (this._roundedConesPosition + i) * LL_STRUCTURE_SIZE_BYTES; u8view.set([color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255], offset + 72); } this.buffer.setModifiedBytes({ start: this._roundedConesPosition * LL_STRUCTURE_SIZE_BYTES, end: (this._roundedConesPosition + this._points.length) * LL_STRUCTURE_SIZE_BYTES }); } public setBorderColors2(borderColors2: Array<vec4>): void { this._borderColors2 = borderColors2; if (!this.buffer) { return; } const u8view = this.buffer.u8view; for (let i = 0; i < this._points.length - 1; i++) { const color = this._borderColors2[i]; const offset = (this._roundedConesPosition + i) * LL_STRUCTURE_SIZE_BYTES; u8view.set([color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255], offset + 76); } this.buffer.setModifiedBytes({ start: this._roundedConesPosition * LL_STRUCTURE_SIZE_BYTES, end: (this._roundedConesPosition + this._points.length) * LL_STRUCTURE_SIZE_BYTES }); } public resetBorderColors2(color: vec4): void { this._borderColors2.fill(color); this.setBorderColors2(this._borderColors2); } public setColorsCombined(colors: Array<vec4>): void { public setColorsCombined(colors: Array<vec4>): void { if (!this.buffer) { if (!this.buffer) { return; return; Loading @@ -502,27 +419,6 @@ export class ContinuousTube implements HighLevelStructure { this.buffer.setModifiedBytes({ start: this._roundedConesPosition * LL_STRUCTURE_SIZE_BYTES, end: (this._roundedConesPosition + this._points.length + 1) * LL_STRUCTURE_SIZE_BYTES }); this.buffer.setModifiedBytes({ start: this._roundedConesPosition * LL_STRUCTURE_SIZE_BYTES, end: (this._roundedConesPosition + this._points.length + 1) * LL_STRUCTURE_SIZE_BYTES }); } } public setBorderColorsCombined(colors: Array<vec4>): void { if (!this.buffer || colors.length * 2 < this._points.length) { return; } const u8view = this.buffer.u8view; for (let i = 0; i < this._points.length - 1; i++) { const color = colors[2 * i]; const color2 = colors[2 * i + 1]; const offsetBytes = (this._roundedConesPosition + i) * LL_STRUCTURE_SIZE_BYTES; this._borderColors[i] = color; this._borderColors2[i] = color2; u8view.set([color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255, color2[0] * 255, color2[1] * 255, color2[2] * 255, color2[3] * 255], offsetBytes + 72); } this.buffer.setModifiedBytes({ start: this._roundedConesPosition * LL_STRUCTURE_SIZE_BYTES, end: (this._roundedConesPosition + this._points.length + 1) * LL_STRUCTURE_SIZE_BYTES }); } public setSelectionIds(binIds: number[]): void { public setSelectionIds(binIds: number[]): void { if (!this.buffer) { if (!this.buffer) { return; return; Loading
libs/graphics/src/primitives/spheres.ts +0 −24 Original line number Original line Diff line number Diff line Loading @@ -167,18 +167,6 @@ export class Spheres implements HighLevelStructure { this.buffer.setModifiedBytes({ start: (this._spheresPosition) * LL_STRUCTURE_SIZE_BYTES, end: (this._spheresPosition + this._colors.length) * LL_STRUCTURE_SIZE_BYTES }); this.buffer.setModifiedBytes({ start: (this._spheresPosition) * LL_STRUCTURE_SIZE_BYTES, end: (this._spheresPosition + this._colors.length) * LL_STRUCTURE_SIZE_BYTES }); } } public resetBorderColors(color: vec4): void { this._borderColors.fill(color); if (!this.buffer) return; for (let i = 0; i < this._borderColors.length; i++) { writeSphereToArrayBuffer(this.buffer, this._spheresPosition + i, { borderColor: this._borderColors[i] }); } this.buffer.setModifiedBytes({ start: (this._spheresPosition) * LL_STRUCTURE_SIZE_BYTES, end: (this._spheresPosition + this._borderColors.length) * LL_STRUCTURE_SIZE_BYTES }); } public setColor(i: number, color: vec4): void { public setColor(i: number, color: vec4): void { this._colors[i] = vec4.clone(color); this._colors[i] = vec4.clone(color); Loading @@ -201,18 +189,6 @@ export class Spheres implements HighLevelStructure { this.buffer.setModifiedBytes({ start: (this._spheresPosition) * LL_STRUCTURE_SIZE_BYTES, end: (this._spheresPosition + this._colors.length) * LL_STRUCTURE_SIZE_BYTES }); this.buffer.setModifiedBytes({ start: (this._spheresPosition) * LL_STRUCTURE_SIZE_BYTES, end: (this._spheresPosition + this._colors.length) * LL_STRUCTURE_SIZE_BYTES }); } } public setBorderColors(colors: Array<vec4>): void { this._borderColors = colors.map(v => vec4.clone(v)); if (!this.buffer) return; for (let i = 0; i < this._borderColors.length; i++) { writeSphereToArrayBuffer(this.buffer, this._spheresPosition + i, { borderColor: this._borderColors[i] }); } this.buffer.setModifiedBytes({ start: (this._spheresPosition) * LL_STRUCTURE_SIZE_BYTES, end: (this._spheresPosition + this._borderColors.length) * LL_STRUCTURE_SIZE_BYTES }); } public getColor(i: number): vec4 | Array<vec4> { public getColor(i: number): vec4 | Array<vec4> { return this._colors[i]; return this._colors[i]; } } Loading
libs/graphics/src/viewports/chromatin_viewport.ts +13 −53 Original line number Original line Diff line number Diff line Loading @@ -4,10 +4,8 @@ import { Scene } from "../scene"; import { GraphicsLibrary } from ".."; import { GraphicsLibrary } from ".."; import { Viewport3D } from "."; import { Viewport3D } from "."; import { vec2, vec3, vec4, quat } from "gl-matrix"; import { vec2, vec3, vec4, quat } from "gl-matrix"; import { BoundingBox, BoundingBoxEmpty, BoundingBoxExtendByPoint, Hit, Ray } from "../shared"; import { Hit, Ray } from "../shared"; import { quantile } from 'simple-statistics' import { Spline } from "../primitives/spline"; import { Spline } from "../primitives/spline"; import { Plane, SectionCuts } from "../sectionCuts" const CHROMATIN_OBJECT_NAME = 'CHROMATIN'; const CHROMATIN_OBJECT_NAME = 'CHROMATIN'; Loading @@ -21,21 +19,23 @@ export type ChromatinRepresentationType = ContinuousTube | Spheres | Spline; export class ChromatinPart { export class ChromatinPart { private _chromatinViewport: ChromatinViewport; private _chromatinViewport: ChromatinViewport; private _name: string; private _name: string; private _structure: ChromatinRepresentationType; private _structure: ChromatinRepresentationType; private _highLevelID: number; private _highLevelID: number; private _dataId: number; private _dataId: number; private _chromosomeIndex: number; private _binsPositions: Array<vec3>; private _binsPositions: Array<vec3>; private _binsColor: Array<vec4>; private _binsColor: Array<vec4>; constructor(chromatinViewport: ChromatinViewport, name: string, structure: ChromatinRepresentationType, highLevelID: number, dataId: number, chromosomeIndex: number, binsPositions: Array<vec3>) { constructor(chromatinViewport: ChromatinViewport, name: string, structure: ChromatinRepresentationType, highLevelID: number, dataId: number, binsPositions: Array<vec3>) { this._name = name; this._name = name; this._chromatinViewport = chromatinViewport; this._chromatinViewport = chromatinViewport; this._structure = structure; this._structure = structure; this._highLevelID = highLevelID; this._highLevelID = highLevelID; this._dataId = dataId; this._dataId = dataId; this._chromosomeIndex = chromosomeIndex; this._binsPositions = binsPositions; this._binsPositions = binsPositions; this._binsColor = new Array<vec4>(this._binsPositions.length); this._binsColor = new Array<vec4>(this._binsPositions.length); } } Loading @@ -47,7 +47,6 @@ export class ChromatinPart { // Calculate Intersection // Calculate Intersection const intersection = vec3.add(vec3.create(), ray.origin, vec3.scale(vec3.create(), ray.direction, hit.distance)); const intersection = vec3.add(vec3.create(), ray.origin, vec3.scale(vec3.create(), ray.direction, hit.distance)); // Calculate normal // Calculate normal const i = this._structure.localOffsetOf(LowLevelStructure.RoundedCone, hit.lowLevelIndex); const i = this._structure.localOffsetOf(LowLevelStructure.RoundedCone, hit.lowLevelIndex); Loading @@ -70,18 +69,14 @@ export class ChromatinPart { const lengthOnIntersection = vec3.length(vec3.sub(vec3.create(), from, vec3.sub(vec3.create(), intersection, vec3.scale(vec3.create(), normal, radius)))); const lengthOnIntersection = vec3.length(vec3.sub(vec3.create(), from, vec3.sub(vec3.create(), intersection, vec3.scale(vec3.create(), normal, radius)))); const ratio = lengthOnIntersection / capsuleLength; const ratio = lengthOnIntersection / capsuleLength; if (i == 0) { return 0; } if (i >= this._binsPositions.length) { if (i >= this._binsPositions.length) { return this._binsPositions.length - 1; return this._binsPositions.length - 1; } } if (ratio < 0.5) { if (ratio < 0.5) { return i - 1; } else { return i; return i; } else { return i + 1; } } } else if (this._structure instanceof Spheres) { } else if (this._structure instanceof Spheres) { return this._structure.localOffsetOf(LowLevelStructure.Sphere, hit.lowLevelIndex); return this._structure.localOffsetOf(LowLevelStructure.Sphere, hit.lowLevelIndex); Loading @@ -94,11 +89,11 @@ export class ChromatinPart { public resetColor(color: GPUColorDict): void { public resetColor(color: GPUColorDict): void { if (this._structure instanceof ContinuousTube) { if (this._structure instanceof ContinuousTube) { this._structure.resetColorBorder(vec4.fromValues(color.r, color.g, color.b, color.a)); this._structure.resetColors(vec4.fromValues(color.r, color.g, color.b, color.a)); } else if (this._structure instanceof Spheres) { } else if (this._structure instanceof Spheres) { this._structure.resetColors(vec4.fromValues(color.r, color.g, color.b, color.a)); this._structure.resetColors(vec4.fromValues(color.r, color.g, color.b, color.a)); } else if (this._structure instanceof Spline) { } else if (this._structure instanceof Spline) { this._structure.resetColorBorder(vec4.fromValues(color.r, color.g, color.b, color.a)); this._structure.resetColors(vec4.fromValues(color.r, color.g, color.b, color.a)); } } } } Loading Loading @@ -196,10 +191,6 @@ export class ChromatinPart { public get highLevelID(): number { public get highLevelID(): number { return this._highLevelID; return this._highLevelID; } } public get chromosomeIndex(): number { return this._chromosomeIndex; } } } export type ChromatinIntersection = { export type ChromatinIntersection = { Loading @@ -216,24 +207,9 @@ export type ChromatinIntersection = { export class ChromatinViewport extends Viewport3D { export class ChromatinViewport extends Viewport3D { public _chromatin: Array<ChromatinPart> = []; public _chromatin: Array<ChromatinPart> = []; private maxId = 0; private maxId = 0; private binPositions: vec3[] = []; private binPositions: vec3[] = []; private debugRadius = 5.0; // private sectionCuts: { intersections: vec3[], planes: Plane[] } = { // intersections: [], // planes: [] // } private sectionCuts: SectionCuts = new SectionCuts(); // private box: BoundingBox = BoundingBoxEmpty(); // private yRange = 0; //#region protected debugDisplay = { showBins: true, showPlanes: true, showIntersections: true } //#endregion constructor( constructor( graphicsLibrary: GraphicsLibrary, graphicsLibrary: GraphicsLibrary, Loading @@ -241,7 +217,6 @@ export class ChromatinViewport extends Viewport3D { scene: Scene | null = null, scene: Scene | null = null, camera: OrbitCamera | SmoothCamera | null = null) { camera: OrbitCamera | SmoothCamera | null = null) { super(graphicsLibrary, canvas, scene, camera); super(graphicsLibrary, canvas, scene, camera); // this.calculateSectionCuts(); } } public clearChromatin(): void { public clearChromatin(): void { Loading @@ -252,6 +227,7 @@ export class ChromatinViewport extends Viewport3D { for (let i = 0; i < this._chromatin.length; i++) { for (let i = 0; i < this._chromatin.length; i++) { this._scene.removeStructureByID(this._chromatin[i].highLevelID); this._scene.removeStructureByID(this._chromatin[i].highLevelID); } } this._chromatin = []; this._chromatin = []; } } Loading @@ -271,12 +247,11 @@ export class ChromatinViewport extends Viewport3D { * Adds a part of chromatin to the viewport * Adds a part of chromatin to the viewport * * * @param bins - sequence of points that represent bins of a chromatin part * @param bins - sequence of points that represent bins of a chromatin part * @param center - whether the supplied data should be centered around point [0, 0, 0] * @param dataId - unique id of the supplied data * @param dataId - unique id of the supplied data * * * @returns created structure * @returns created structure */ */ public addPart(chromosomeName: string, bins: Array<{ x: number, y: number, z: number }>, center = false, dataId: number, chromosomeIndex: number, representation: ChromatinRepresentation, update = true): ChromatinPart { public addPart(chromosomeName: string, bins: Array<{ x: number, y: number, z: number }>, dataId: number, representation: ChromatinRepresentation, update = true): ChromatinPart { const pointsVec3 = bins.map(p => vec3.fromValues(p.x, p.y, p.z)); const pointsVec3 = bins.map(p => vec3.fromValues(p.x, p.y, p.z)); this.binPositions = pointsVec3.map(p => vec3.clone(p)); this.binPositions = pointsVec3.map(p => vec3.clone(p)); Loading Loading @@ -316,14 +291,11 @@ export class ChromatinViewport extends Viewport3D { structure, structure, highLevelID, highLevelID, dataId, dataId, chromosomeIndex, this.binPositions, this.binPositions, )); )); this.maxId++; this.maxId++; // this.calculateSectionCuts(); return this._chromatin[this._chromatin.length - 1]; return this._chromatin[this._chromatin.length - 1]; } } Loading @@ -343,37 +315,25 @@ export class ChromatinViewport extends Viewport3D { return this._chromatin; return this._chromatin; } } public getChromatinPartByChromosomeIndex(chromosomeIndex: number): ChromatinPart | null { const chromatinPartIndex = this._chromatin.findIndex(v => v.chromosomeIndex == chromosomeIndex); return this._chromatin[chromatinPartIndex]; } public closestIntersectionBin(screenSpacePosition: { x: number, y: number }): ChromatinIntersection | null { public closestIntersectionBin(screenSpacePosition: { x: number, y: number }): ChromatinIntersection | null { // console.time('ChromatinIntersection::closestIntersectionBin'); const closestIntersection = this.closestIntersection(vec2.fromValues(screenSpacePosition.x, screenSpacePosition.y)); const closestIntersection = this.closestIntersection(vec2.fromValues(screenSpacePosition.x, screenSpacePosition.y)); if (closestIntersection == null) { if (closestIntersection == null) { // console.timeEnd('ChromatinIntersection::closestIntersectionBin'); return null; return null; } } const chromatinPart = this._chromatin.find(chromatinPart => chromatinPart.highLevelID == closestIntersection.highLevelIndex); const chromatinPart = this._chromatin.find(chromatinPart => chromatinPart.highLevelID == closestIntersection.highLevelIndex); if (chromatinPart == undefined) { if (chromatinPart == undefined) { // console.timeEnd('ChromatinIntersection::closestIntersectionBin'); return null; return null; } } const binIndex = chromatinPart.lowLevelIndexToBinIndex(closestIntersection); const binIndex = chromatinPart.lowLevelIndexToBinIndex(closestIntersection); if (binIndex == null) { if (binIndex == null) { // console.timeEnd('ChromatinIntersection::closestIntersectionBin'); return null; return null; } } // console.timeEnd('ChromatinIntersection::closestIntersectionBin'); return { return { chromatinPart, chromatinPart, Loading