Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Display all relations #54

Merged
merged 9 commits into from
Nov 22, 2024
14 changes: 14 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"cytoscape-dagre": "^2.4.0",
"graphlib": "^2.1.8",
"lodash": "^4.17.21",
"moment": "^2.30.1",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You probably already know that Moment has their own recommendations for alternatives: https://momentjs.com/docs/#/-project-status/recommendations/

Personally I've used date-fns and have had no issues with it. But I think that's something that can be addressed separately from this PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am having problems with date-fns and typescript, 'Intl' has no exported member named 'RelativeTimeFormatOptions'. Did you mean 'DateTimeFormatOptions'? so can I look into this later then I remove moment later. or moment has to be removed before PR. I had changed the date to use date-fns and working but that tpescript error

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without knowing what you tried doing, the error message in isolation isn't too informative. I'm not even really strongly advocating for date-fns. I was just pointing out that I've used it (yes, in TypeScript projects) and thought it was fine.

But more importantly, to quote myself 😂 :

I think that's something that can be addressed separately from this PR.

"uuid": "^8.3.2"
},
"devDependencies": {
Expand All @@ -46,6 +47,6 @@
"url": "https://github.com/geneontology/wc-gocam-viz/issues"
},
"homepage": "https://github.com/geneontology/wc-gocam-viz#readme",
"author": "Laurent-Philippe Albou",
"author": "The Gene Ontology Consortium",
"license": "BSD-3"
}
}
4 changes: 2 additions & 2 deletions src/components/gocam-legend/gocam-legend.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import positive_regulation from './assets/relation/positive_regulation.png';
import negative_regulation from './assets/relation/negative_regulation.png';
import provides_input_for from './assets/relation/provides_input_for.png';
import neutral from './assets/relation/neutral.png';
import has_input from './assets/relation/has_input.png';
import input_of from './assets/relation/input_of.png';
import has_output from './assets/relation/has_output.png';

// Stencil's Assets feature[1] makes client applications jump through a lot of hoops[2] in order
Expand All @@ -25,7 +25,7 @@ const IMAGE_DATA = {
negative_regulation,
provides_input_for,
neutral,
has_input,
input_of,
has_output
};

Expand Down
142 changes: 14 additions & 128 deletions src/components/gocam-viz/gocam-viz.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Component, Host, Prop, Element, Event, EventEmitter, Watch, h } from '@
import { Listen, Method, State } from '@stencil/core';
import cytoscape from 'cytoscape';
import dagre from 'cytoscape-dagre';
import { glyph, _node_labels, annotate, _folded_stack_gather } from '../../globals/utils';
import { glyph } from '../../globals/utils';
import * as dbxrefs from "@geneontology/dbxrefs";
import {
Activity, ActivityType, Cam,
Expand Down Expand Up @@ -320,7 +320,7 @@ export class GoCamViz {
let el
if (activity.activityType === ActivityType.molecule) {
el = self.createMolecule(activity);
} if (activity.activityType === ActivityType.proteinComplex) {
} else if (activity.activityType === ActivityType.proteinComplex) {
el = self.createComplex(activity, expandComplex);
} else {
el = self.createNode(activity);
Expand All @@ -330,7 +330,7 @@ export class GoCamViz {
});

cam.causalRelations.forEach((triple: Triple<Activity>) => {
if (triple.predicate.visible && triple.isTripleComplete()) {
if (triple.predicate.visible && triple.isTripleComplete() && this.configService.isAllowedEdge(triple.predicate.edge.id)) {
const source = triple.predicate.isReverseLink ? triple.object : triple.subject;
const target = triple.predicate.isReverseLink ? triple.subject : triple.object;
let rglyph = glyph(triple.predicate.edge.id);
Expand Down Expand Up @@ -437,7 +437,7 @@ export class GoCamViz {
createMolecule(activity: Activity) {
const moleculeNode = activity.rootNode;
const label = moleculeNode?.term.label || activity.label || '';
const geneShorthand = this.configService.getGeneShorthand(label)
const geneShorthand = this.configService.getGeneShorthand(label) ?? label

const el = {
group: "nodes",
Expand Down Expand Up @@ -554,120 +554,6 @@ export class GoCamViz {
}
}

/**
* If desired, this can render a pop up with information about the gene & its activity
* @param evt
*/
showPopup(evt) {
if (evt && evt.target && evt.target.id) {
this.highlight(evt.target.id());
// evt.target.style("background-color", "#ebebeb")
// evt.target.style("border-width", "2px")
// evt.target.style("border-color", "black")
this.selectedNode = evt.target;
this.selectedEvent = evt;
let entity_id = evt.target.id();

const activity = this.cam.findActivityById(entity_id);
// console.log("graph handler: " , activity);

//this.cam.enrichActivity(activity);

if (entity_id.startsWith(GOMODEL_PREFIX)) {
let data = evt.target.data();
let node = this.currentGraph.get_node(entity_id);
let labels = [];
for (let ann of node.annotations()) {
if (ann.key() == "rdfs:label") {
labels.push(ann.value());
}
}

// this concern the activity itself
let standardTypes = node.types();
let inferredTypes = node.get_unique_inferred_types();

// this will detect the associated biological context
let subgraph = node.subgraph();
let biocontext = {};
let hook_list = []
if (subgraph) {
// Do it both ways--upstream and downstream.
_folded_stack_gather(node, this.currentGraph, subgraph, 'standard', hook_list, biocontext, dbxrefs);
_folded_stack_gather(node, this.currentGraph, subgraph, 'reverse', hook_list, biocontext, dbxrefs);
// convert to array
for (let key of Object.keys(biocontext)) {
biocontext[key] = Array.from(biocontext[key]);
}
}

let annotations = node.annotations();
let annotationMap = {};
for (let ann of annotations) {
if (ann.key() == "evidence") {
let cs = new Set();
if (ann.key() in annotationMap) {
cs = annotationMap[ann.key()]
} else {
annotationMap[ann.key()] = cs;
}
cs.add(ann.value());
} else if (ann.key() == "rdfs:label") {
let cs = new Set();
if (ann.key() in annotationMap) {
cs = annotationMap[ann.key()]
} else {
annotationMap[ann.key()] = cs;
}
cs.add(ann.value());
} else if (ann.key() == "contributor") {
let cs = new Set();
if (ann.key() in annotationMap) {
cs = annotationMap[ann.key()]
} else {
annotationMap[ann.key()] = cs;
}
cs.add(ann.value());
} else if (ann.key() == "providedBy") {
let cs = new Set();
if (ann.key() in annotationMap) {
cs = annotationMap[ann.key()]
} else {
annotationMap[ann.key()] = cs;
}
cs.add(ann.value());
}
}
// convert to array
for (let key of Object.keys(annotationMap)) {
annotationMap[key] = Array.from(annotationMap[key]);
}
// console.log("node annotations: ", annotationMap);

let id = data.link && data.link._class_id ? data.link.class_id() : undefined
let meta = annotate(id, dbxrefs);
meta.then(metaData => {
let payload = {
entityId: entity_id,
id: id,
uri: id ? "https://www.alliancegenome.org/gene/" + id : undefined,
annotation: annotationMap,
biocontext: biocontext,
meta: metaData,
label: data.label,
data: data.link,
standardTypes: standardTypes,
inferredTypes: inferredTypes,
x: evt.renderedPosition.x,
y: evt.renderedPosition.y
}
this.nodeOver.emit(payload);
})
}
}
}


/**
* Center the cytoscape graph to fit the whole graph
*/
Expand Down Expand Up @@ -843,10 +729,10 @@ export class GoCamViz {
let element: Node = this.gocamviz;
const invalidateCoordsCache = () => this.cy?.renderer().invalidateContainerClientCoordsCache();
while (element != null) {
element.addEventListener('transitionend', invalidateCoordsCache);
element.addEventListener('animationend', invalidateCoordsCache);
element.addEventListener('scroll', invalidateCoordsCache);
element = element.parentNode;
element.addEventListener('transitionend', invalidateCoordsCache);
element.addEventListener('animationend', invalidateCoordsCache);
element.addEventListener('scroll', invalidateCoordsCache);
element = element.parentNode;
}
}

Expand All @@ -873,9 +759,9 @@ export class GoCamViz {
</div>
<div class="panel-body">
<div class="gocam-graph" part="gocam-graph" ref={(el) => this.graphDiv = el}>
{ this.loading &&
<go-loading-spinner message={`Loading GO-CAM ${this.gocamId}`}></go-loading-spinner>
}
{this.loading &&
<go-loading-spinner message={`Loading GO-CAM ${this.gocamId}`}></go-loading-spinner>
}
</div>
{this.showLegend && (
<wc-gocam-legend exportparts="header : legend-header, section : legend-section" />
Expand All @@ -889,9 +775,9 @@ export class GoCamViz {
</div>
<div class="panel-body">
<wc-genes-panel
cam={this.cam}
exportparts="process, activity, gene-product, function-label"
ref={el => this.genesPanel = el}
cam={this.cam}
exportparts="process, activity, gene-product, function-label"
ref={el => this.genesPanel = el}
>
</wc-genes-panel>
</div>
Expand Down
Loading
Loading