UNPKG

molstar

Version:

A comprehensive macromolecular library.

364 lines 14.8 kB
/** * Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author David Sehnal <david.sehnal@gmail.com> * @author Alexander Rose <alexander.rose@weirdbyte.de> */ import { arrayPickIndices, cantorPairing } from '../../mol-data/util'; import { LinkedIndex, SortedArray } from '../../mol-data/int'; export var IntAdjacencyGraph; (function (IntAdjacencyGraph) { function areEqual(a, b) { if (a === b) return true; if (a.vertexCount !== b.vertexCount || a.edgeCount !== b.edgeCount) return false; var aa = a.a, ab = a.b, ao = a.offset; var ba = b.a, bb = b.b, bo = b.offset; for (var i = 0, _i = a.a.length; i < _i; i++) { if (aa[i] !== ba[i]) return false; } for (var i = 0, _i = a.b.length; i < _i; i++) { if (ab[i] !== bb[i]) return false; } for (var i = 0, _i = a.offset.length; i < _i; i++) { if (ao[i] !== bo[i]) return false; } for (var _a = 0, _b = Object.keys(a.edgeProps); _a < _b.length; _a++) { var k = _b[_a]; var pa = a.edgeProps[k], pb = b.edgeProps[k]; if (!pb) return false; for (var i = 0, _i = pa.length; i < _i; i++) { if (pa[i] !== pb[i]) return false; } } return true; } IntAdjacencyGraph.areEqual = areEqual; var IntGraphImpl = /** @class */ (function () { function IntGraphImpl(offset, a, b, edgeCount, edgeProps, props) { this.offset = offset; this.a = a; this.b = b; this.edgeCount = edgeCount; this.props = props; this.vertexCount = offset.length - 1; this.edgeProps = (edgeProps || {}); } IntGraphImpl.prototype.getEdgeIndex = function (i, j) { var a, b; if (i < j) { a = i; b = j; } else { a = j; b = i; } for (var t = this.offset[a], _t = this.offset[a + 1]; t < _t; t++) { if (this.b[t] === b) return t; } return -1; }; IntGraphImpl.prototype.getDirectedEdgeIndex = function (i, j) { for (var t = this.offset[i], _t = this.offset[i + 1]; t < _t; t++) { if (this.b[t] === j) return t; } return -1; }; IntGraphImpl.prototype.getVertexEdgeCount = function (i) { return this.offset[i + 1] - this.offset[i]; }; return IntGraphImpl; }()); function create(offset, a, b, edgeCount, edgeProps, props) { return new IntGraphImpl(offset, a, b, edgeCount, edgeProps, props); } IntAdjacencyGraph.create = create; var EdgeBuilder = /** @class */ (function () { function EdgeBuilder(vertexCount, xs, ys) { this.vertexCount = vertexCount; this.xs = xs; this.ys = ys; this.current = 0; this.curA = 0; this.curB = 0; this.edgeCount = xs.length; this.offsets = new Int32Array(this.vertexCount + 1); this.bucketFill = new Int32Array(this.vertexCount); var bucketSizes = new Int32Array(this.vertexCount); for (var i = 0, _i = this.xs.length; i < _i; i++) bucketSizes[this.xs[i]]++; for (var i = 0, _i = this.ys.length; i < _i; i++) bucketSizes[this.ys[i]]++; var offset = 0; for (var i = 0; i < this.vertexCount; i++) { this.offsets[i] = offset; offset += bucketSizes[i]; } this.offsets[this.vertexCount] = offset; this.slotCount = offset; this.a = new Int32Array(offset); this.b = new Int32Array(offset); } EdgeBuilder.prototype.createGraph = function (edgeProps, props) { return create(this.offsets, this.a, this.b, this.edgeCount, edgeProps, props); }; /** * @example * const property = new Int32Array(builder.slotCount); * for (let i = 0; i < builder.edgeCount; i++) { * builder.addNextEdge(); * builder.assignProperty(property, srcProp[i]); * } * return builder.createGraph({ property }); */ EdgeBuilder.prototype.addNextEdge = function () { var a = this.xs[this.current], b = this.ys[this.current]; var oa = this.offsets[a] + this.bucketFill[a]; var ob = this.offsets[b] + this.bucketFill[b]; this.a[oa] = a; this.b[oa] = b; this.bucketFill[a]++; this.a[ob] = b; this.b[ob] = a; this.bucketFill[b]++; this.current++; this.curA = oa; this.curB = ob; }; /** Builds property-less graph */ EdgeBuilder.prototype.addAllEdges = function () { for (var i = 0; i < this.edgeCount; i++) { this.addNextEdge(); } }; EdgeBuilder.prototype.assignProperty = function (prop, value) { prop[this.curA] = value; prop[this.curB] = value; }; return EdgeBuilder; }()); IntAdjacencyGraph.EdgeBuilder = EdgeBuilder; var DirectedEdgeBuilder = /** @class */ (function () { function DirectedEdgeBuilder(vertexCount, xs, ys) { this.vertexCount = vertexCount; this.xs = xs; this.ys = ys; this.current = 0; this.curA = 0; this.edgeCount = xs.length; this.offsets = new Int32Array(this.vertexCount + 1); this.bucketFill = new Int32Array(this.vertexCount); var bucketSizes = new Int32Array(this.vertexCount); for (var i = 0, _i = this.xs.length; i < _i; i++) bucketSizes[this.xs[i]]++; var offset = 0; for (var i = 0; i < this.vertexCount; i++) { this.offsets[i] = offset; offset += bucketSizes[i]; } this.offsets[this.vertexCount] = offset; this.slotCount = offset; this.a = new Int32Array(offset); this.b = new Int32Array(offset); } DirectedEdgeBuilder.prototype.createGraph = function (edgeProps) { return create(this.offsets, this.a, this.b, this.edgeCount, edgeProps); }; /** * @example * const property = new Int32Array(builder.slotCount); * for (let i = 0; i < builder.edgeCount; i++) { * builder.addNextEdge(); * builder.assignProperty(property, srcProp[i]); * } * return builder.createGraph({ property }); */ DirectedEdgeBuilder.prototype.addNextEdge = function () { var a = this.xs[this.current], b = this.ys[this.current]; var oa = this.offsets[a] + this.bucketFill[a]; this.a[oa] = a; this.b[oa] = b; this.bucketFill[a]++; this.current++; this.curA = oa; }; /** Builds property-less graph */ DirectedEdgeBuilder.prototype.addAllEdges = function () { for (var i = 0; i < this.edgeCount; i++) { this.addNextEdge(); } }; DirectedEdgeBuilder.prototype.assignProperty = function (prop, value) { prop[this.curA] = value; }; return DirectedEdgeBuilder; }()); IntAdjacencyGraph.DirectedEdgeBuilder = DirectedEdgeBuilder; var UniqueEdgeBuilder = /** @class */ (function () { function UniqueEdgeBuilder(vertexCount) { this.vertexCount = vertexCount; this.xs = []; this.ys = []; this.included = new Set(); } UniqueEdgeBuilder.prototype.addEdge = function (i, j) { var u = i, v = j; if (i > j) { u = j; v = i; } var id = cantorPairing(u, v); if (this.included.has(id)) return false; this.included.add(id); this.xs[this.xs.length] = u; this.ys[this.ys.length] = v; return true; }; UniqueEdgeBuilder.prototype.getGraph = function () { return fromVertexPairs(this.vertexCount, this.xs, this.ys); }; // if we cant to add custom props as well UniqueEdgeBuilder.prototype.getEdgeBuiler = function () { return new EdgeBuilder(this.vertexCount, this.xs, this.ys); }; return UniqueEdgeBuilder; }()); IntAdjacencyGraph.UniqueEdgeBuilder = UniqueEdgeBuilder; function fromVertexPairs(vertexCount, xs, ys) { var graphBuilder = new IntAdjacencyGraph.EdgeBuilder(vertexCount, xs, ys); graphBuilder.addAllEdges(); return graphBuilder.createGraph({}); } IntAdjacencyGraph.fromVertexPairs = fromVertexPairs; function induceByVertices(graph, vertexIndices) { var b = graph.b, offset = graph.offset, vertexCount = graph.vertexCount, edgeProps = graph.edgeProps; var vertexMap = new Int32Array(vertexCount); for (var i = 0, _i = vertexIndices.length; i < _i; i++) vertexMap[vertexIndices[i]] = i + 1; var newEdgeCount = 0; for (var i = 0; i < vertexCount; i++) { if (vertexMap[i] === 0) continue; for (var j = offset[i], _j = offset[i + 1]; j < _j; j++) { if (b[j] > i && vertexMap[b[j]] !== 0) newEdgeCount++; } } var newOffsets = new Int32Array(vertexIndices.length + 1); var edgeIndices = new Int32Array(2 * newEdgeCount); var newA = new Int32Array(2 * newEdgeCount); var newB = new Int32Array(2 * newEdgeCount); var eo = 0, vo = 0; for (var i = 0; i < vertexCount; i++) { if (vertexMap[i] === 0) continue; var aa = vertexMap[i] - 1; for (var j = offset[i], _j = offset[i + 1]; j < _j; j++) { var bb = vertexMap[b[j]]; if (bb === 0) continue; newA[eo] = aa; newB[eo] = bb - 1; edgeIndices[eo] = j; eo++; } newOffsets[++vo] = eo; } var newEdgeProps = {}; for (var _a = 0, _b = Object.keys(edgeProps); _a < _b.length; _a++) { var key = _b[_a]; newEdgeProps[key] = arrayPickIndices(edgeProps[key], edgeIndices); } return create(newOffsets, newA, newB, newEdgeCount, newEdgeProps); } IntAdjacencyGraph.induceByVertices = induceByVertices; function connectedComponents(graph) { var vCount = graph.vertexCount; if (vCount === 0) return { componentCount: 0, componentIndex: new Int32Array(0) }; if (graph.edgeCount === 0) { var componentIndex_1 = new Int32Array(vCount); for (var i = 0, _i = vCount; i < _i; i++) { componentIndex_1[i] = i; } return { componentCount: vCount, componentIndex: componentIndex_1 }; } var componentIndex = new Int32Array(vCount); for (var i = 0, _i = vCount; i < _i; i++) componentIndex[i] = -1; var currentComponent = 0; componentIndex[0] = currentComponent; var offset = graph.offset, neighbor = graph.b; var stack = [0]; var list = LinkedIndex(vCount); list.remove(0); while (stack.length > 0) { var v = stack.pop(); var cIdx = componentIndex[v]; for (var eI = offset[v], _eI = offset[v + 1]; eI < _eI; eI++) { var n = neighbor[eI]; if (!list.has(n)) continue; list.remove(n); stack.push(n); componentIndex[n] = cIdx; } // check if we visited all vertices. // If not, create a new component and continue. if (stack.length === 0 && list.head >= 0) { stack.push(list.head); componentIndex[list.head] = ++currentComponent; list.remove(list.head); } } return { componentCount: vCount, componentIndex: componentIndex }; } IntAdjacencyGraph.connectedComponents = connectedComponents; /** * Check if any vertex in `verticesA` is connected to any vertex in `verticesB` * via at most `maxDistance` edges. * * Returns true if verticesA and verticesB are intersecting. */ function areVertexSetsConnected(graph, verticesA, verticesB, maxDistance) { // check if A and B are intersecting, this handles maxDistance = 0 if (SortedArray.areIntersecting(verticesA, verticesB)) return true; if (maxDistance < 1) return false; var visited = new Set(); for (var i = 0, il = verticesA.length; i < il; ++i) { visited.add(verticesA[i]); } return areVertexSetsConnectedImpl(graph, verticesA, verticesB, maxDistance, visited); } IntAdjacencyGraph.areVertexSetsConnected = areVertexSetsConnected; })(IntAdjacencyGraph || (IntAdjacencyGraph = {})); function areVertexSetsConnectedImpl(graph, frontier, target, distance, visited) { var neighbor = graph.b, offset = graph.offset; var newFrontier = []; for (var i = 0, il = frontier.length; i < il; ++i) { var src = frontier[i]; for (var j = offset[src], jl = offset[src + 1]; j < jl; ++j) { var other = neighbor[j]; if (visited.has(other)) continue; if (SortedArray.has(target, other)) return true; visited.add(other); newFrontier[newFrontier.length] = other; } } return distance > 1 ? areVertexSetsConnectedImpl(graph, newFrontier, target, distance - 1, visited) : false; } //# sourceMappingURL=int-adjacency-graph.js.map