Skip to content

Commit 6ce57f0

Browse files
committed
fix: Certain diagrams not rendering + assertion issue
1 parent d1d2294 commit 6ce57f0

1 file changed

Lines changed: 37 additions & 10 deletions

File tree

projects/pathway-browser/src/app/services/diagram.service.ts

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ const squaredDist = (pos1: Position, pos2: Position) => {
5151

5252
const dist = (pos1: Position, pos2: Position) => Math.sqrt(squaredDist(pos1, pos2))
5353

54+
const isFinitePoint = (point: Position | undefined | null): point is Position =>
55+
!!point && Number.isFinite(point.x) && Number.isFinite(point.y);
56+
5457
const closestToAverage = (positions: Position[]): Position => {
5558
const average = avg(positions);
5659
let closest = positions[0];
@@ -582,7 +585,7 @@ export class DiagramService {
582585
if (equal(from, reactionP) || equal(to, reactionP)) d -= REACTION_RADIUS;
583586
if (classes.includes('positive-regulation') || classes.includes('catalysis') || classes.includes('production')) d -= ARROW_MULT * T;
584587
// console.assert(d > MIN_DIST, `The edge between reaction: R-HSA-${reaction.reactomeId} and entity: R-HSA-${node.reactomeId} in pathway ${id} has a visible length of ${d} which is shorter than ${MIN_DIST}`)
585-
console.assert(d > MIN_DIST, `${id}\t${diagram.displayName}\t${hasFadeOut}\tR-HSA-${reaction.reactomeId}\tR-HSA-${node.reactomeId}\thttps://release.reactome.org/PathwayBrowser/#/${id}&SEL=R-HSA-${reaction.reactomeId}&FLG=R-HSA-${node.reactomeId}\thttps://reactome-pwp.github.io/PathwayBrowser/${id}?select=${reaction.reactomeId}&flag=${node.reactomeId}`)
588+
console.assert(Math.abs(d) >= MIN_DIST, `${id}\t${diagram.displayName}\t${hasFadeOut}\tR-HSA-${reaction.reactomeId}\tR-HSA-${node.reactomeId}\thttps://release.reactome.org/PathwayBrowser/#/${id}&SEL=R-HSA-${reaction.reactomeId}&FLG=R-HSA-${node.reactomeId}\thttps://reactome-pwp.github.io/PathwayBrowser/${id}?select=${reaction.reactomeId}&flag=${node.reactomeId}`)
586589

587590
let replacement, replacedBy;
588591
if (connector.isFadeOut) {
@@ -595,23 +598,27 @@ export class DiagramService {
595598
}
596599
if (!connector.isFadeOut) {
597600
// First case: same node is used both special and normal context
598-
replacement = node.connectors.find(otherConnector => otherConnector !== connector && otherConnector.isFadeOut && samePoint(idToEdges.get(otherConnector.edgeId)!.position, reaction.position))?.edgeId;
601+
replacement = node.connectors.find(otherConnector => {
602+
if (otherConnector === connector || !otherConnector.isFadeOut) return false;
603+
const otherEdge = idToEdges.get(otherConnector.edgeId);
604+
return samePoint(otherEdge?.position, reaction.position);
605+
})?.edgeId;
599606
// console.log("Reaction edge", replacement)
600607

601608
// Second case: different nodes are used between special and normal context
602609
replacement = replacement || (posToNormalNode.get(pointToStr(node.position)) && posToNormalEdge.get(pointToStr(reaction.position)))?.id;
603610
// console.log("Reaction edge", replacement)
604611

605612
}
613+
const relativeSegments = this.getRelativeSegmentsData(relatives);
606614
const edge: cytoscape.EdgeDefinition = {
607615
data: {
608616
id: this.getEdgeId(source, connector, target, edgeIds),
609617
graph: dbIdToGraphEdge.get(reaction.reactomeId),
610618
source: source.id + '',
611619
target: target.id + '',
612620
stoichiometry: connector.stoichiometry.value,
613-
weights: relatives.weights.join(" "),
614-
distances: relatives.distances.join(" "),
621+
...relativeSegments,
615622
sourceEndpoint: this.endpoint(sourceP, from),
616623
targetEndpoint: this.endpoint(targetP, to),
617624
pathway: eventIdToSubPathwayId.get(reaction.reactomeId),
@@ -648,6 +655,7 @@ export class DiagramService {
648655

649656
// points = addRoundness(from, to, points);
650657
const relatives = this.absoluteToRelative(from, to, points);
658+
const relativeSegments = this.getRelativeSegmentsData(relatives);
651659

652660
const classes = [...this.linkClassMap.get(link.renderableClass)!];
653661
if (link.isDisease) classes.push('disease');
@@ -660,8 +668,7 @@ export class DiagramService {
660668
id: link.id + '',
661669
source: link.inputs[0].id + '',
662670
target: link.outputs[0].id + '',
663-
weights: relatives.weights.join(" "),
664-
distances: relatives.distances.join(" "),
671+
...relativeSegments,
665672
sourceEndpoint: this.endpoint(sourceP, from),
666673
targetEndpoint: this.endpoint(targetP, to),
667674
isFadeOut: link.isFadeOut,
@@ -746,6 +753,18 @@ export class DiagramService {
746753
return `${point.x - source.x} ${point.y - source.y}`
747754
}
748755

756+
private getRelativeSegmentsData(relatives: RelativePosition): Partial<{weights: string, distances: string}> {
757+
const weights = relatives.weights.filter(value => Number.isFinite(value));
758+
const distances = relatives.distances.filter(value => Number.isFinite(value));
759+
if (weights.length === 0 || distances.length === 0 || weights.length !== distances.length) {
760+
return {};
761+
}
762+
return {
763+
weights: weights.join(" "),
764+
distances: distances.join(" "),
765+
};
766+
}
767+
749768

750769
/**
751770
* Use Matrix power to convert points from an absolute coordinate system to an edge relative system
@@ -761,19 +780,26 @@ export class DiagramService {
761780
const relatives: RelativePosition = {distances: [], weights: []};
762781
if (toConvert.length === 0) return relatives;
763782

783+
if (!isFinitePoint(source) || !isFinitePoint(target) || equal(source, target)) return relatives;
784+
764785
const mainVector = array([target.x - source.x, target.y - source.y]); // Edge vector
786+
if (mainVector.x === 0 && mainVector.y === 0) return relatives;
765787
const orthoVector = array([-mainVector.y, mainVector.x]) // Perpendicular vector
766788
.normalize(); //Normalized to have the distance expressed in pixels https://math.stackexchange.com/a/413235/683621
767-
let transform = array([
789+
const transform = array([
768790
[mainVector.x, mainVector.y],
769791
[orthoVector.x, orthoVector.y],
770792
]).inv(); // Should always be invertible if the ortho vector is indeed perpendicular
771793

772794
for (let coord of toConvert) {
795+
if (!isFinitePoint(coord)) continue;
773796
const absolute = array([[coord.x - source.x, coord.y - source.y]]);
774797
const relative = absolute.multiply(transform);
775-
relatives.weights.push(relative.get(0, 0))
776-
relatives.distances.push(relative.get(0, 1))
798+
const weight = relative.get(0, 0);
799+
const distance = relative.get(0, 1);
800+
if (!Number.isFinite(weight) || !Number.isFinite(distance)) continue;
801+
relatives.weights.push(weight)
802+
relatives.distances.push(distance)
777803
}
778804
return relatives;
779805
}
@@ -869,7 +895,8 @@ export class DiagramService {
869895
}
870896
}
871897

872-
function samePoint(p1: Position, p2: Position) {
898+
function samePoint(p1?: Position | null, p2?: Position | null) {
899+
if (!p1 || !p2) return false;
873900
return p1.x === p2.x && p1.y === p2.y
874901
}
875902

0 commit comments

Comments
 (0)