Skip to content

Commit

Permalink
Implement first network visualization
Browse files Browse the repository at this point in the history
  • Loading branch information
Nico Trummer committed Apr 2, 2024
1 parent 7d491ec commit 33ee950
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 28 deletions.

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions modules/local/report/create/app/templates/macros.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
<li class="tab-item {{ 'active' if active=='tg'}}">
<a href="target_genes.html">Target genes</a>
</li>
<li class="tab-item {{ 'active' if active=='net'}}">
<a href="network.html">Network</a>
</li>
<li class="tab-item {{ 'active' if active=='snp'}}">
<a href="snps.html">SNPs</a>
</li>
Expand Down
56 changes: 56 additions & 0 deletions modules/local/report/create/app/templates/network.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{% extends "base.html" %} {% block tabs %} {% from 'macros.html' import tabs %} {{ tabs(active="net") }} {% endblock %}
{% block content %}
<div id="3d-graph"></div>
{% endblock %} {% block scripts %}
<script src="ranking.js"></script>
<script src="dependencies/3d-force-graph.js"></script>
<script>
const tf_tg_ranking = {{ tf_tg_ranking | tojson }};
const assays = {{ assays | tojson }};
const secondary_ranking = getSecondaryRanking(assays, tf_tg_ranking);
const top_k_tgs = 20;

const filtered_ranking = Object.entries(secondary_ranking)
.reduce(function (acc, [tf, tg_rank]) {
return {
...acc, [tf]: Object.entries(tg_rank)
.filter(([tg, rank]) => rank < top_k_tgs)
.reduce(function (acc, [tg, rank]) {
return { ...acc, [tg]: rank }
}, {})
}
}, {})

let tfs = Object.keys(filtered_ranking);
let tgs = [...new Set(Object.values(filtered_ranking)
.map(tg_rank => Object.entries(tg_rank))
.flat()
.map(([tg, rank]) => tg))];

let autoRegulating = tfs.filter(tf => tgs.includes(tf))
tfs = tfs.filter(tf => !autoRegulating.includes(tf)).map(tf => ({ id: tf, color: 'red' }));
tgs = tgs.filter(tg => !autoRegulating.includes(tg)).map(tg => ({ id: tg, color: 'blue' }));
autoRegulating = autoRegulating.map(tf => ({ id: tf, color: 'green' }));

const nodes = tfs.concat(tgs).concat(autoRegulating);
const links = Object.entries(filtered_ranking)
.map(([tf, tgs]) => Object.keys(tgs)
.map(tg => ({ source: tf, target: tg, curvature: tf == tg ? 0.5 : 0 })))
.flat();

const gData = {
nodes: nodes,
links: links
};

const Graph = ForceGraph3D()
(document.getElementById('3d-graph'))
.graphData(gData)
.linkCurvature('curvature')
.linkDirectionalArrowLength(3)
.linkDirectionalParticles(1)
.linkDirectionalParticleSpeed(0.005)
.linkDirectionalParticleWidth(2)
.d3Force('charge').strength(-120);
</script>
{% endblock %}
59 changes: 32 additions & 27 deletions modules/local/report/create/app/templates/ranking.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,36 @@
const initRanking = async function (primary_ranking, secondary_ranking) {
const assayChips = Array.from(document.querySelectorAll('[id^="assay-"]'));
const getRanking = function (inputDcgs, assays) {
const scores = Object.entries(inputDcgs).reduce(function (acc, [value, dcgs]) {
if (assays.some((assay) => Object.keys(dcgs).includes(assay))) {
acc[value] =
assays.reduce(function (acc, assay) {
return acc + (dcgs[assay] || 0);
}, 0) / assays.length;
} else {
acc[value] = -1;
}
return acc;
}, {});

const getRanking = function (inputDcgs, assays) {
const scores = Object.entries(inputDcgs).reduce(function (acc, [value, dcgs]) {
if (assays.some((assay) => Object.keys(dcgs).includes(assay))) {
acc[value] =
assays.reduce(function (acc, assay) {
return acc + (dcgs[assay] || 0);
}, 0) / assays.length;
} else {
acc[value] = -1;
}
return acc;
}, {});
const order = Object.keys(scores).sort(function (a, b) {
return scores[b] - scores[a];
});

const order = Object.keys(scores).sort(function (a, b) {
return scores[b] - scores[a];
});
const ranks = order.reduce(function (acc, primary, index) {
acc[primary] = index;
return acc;
}, {});

const ranks = order.reduce(function (acc, primary, index) {
acc[primary] = index;
return acc;
}, {});
return ranks;
};

return ranks;
};
const getSecondaryRanking = function (activeAssays, secondary_ranking) {
return Object.entries(secondary_ranking).reduce(function (acc, [primary, currentRanking]) {
return {...acc, [primary]: getRanking(currentRanking, activeAssays)};
}, {});
}

const initRanking = async function (primary_ranking, secondary_ranking) {
const assayChips = Array.from(document.querySelectorAll('[id^="assay-"]'));

const updatePrimaryRanking = async function (activeAssays) {
const primaryRank = getRanking(primary_ranking, activeAssays);
Expand All @@ -36,10 +42,9 @@ const initRanking = async function (primary_ranking, secondary_ranking) {
};

const updateSecondaryRanking = async function (activeAssays) {
for (const primary in secondary_ranking) {
const currentRanking = secondary_ranking[primary];
const tgRank = getRanking(currentRanking, activeAssays);

const ranking = getSecondaryRanking(activeAssays, secondary_ranking);
for (const primary in ranking) {
const tgRank = ranking[primary];
const showedSecondaries = [];

Object.entries(tgRank).forEach(function ([secondary, rank]) {
Expand Down
11 changes: 10 additions & 1 deletion modules/local/report/create/templates/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
# Copy app_dir to current directory
shutil.copytree(module_app, os.path.join(os.getcwd(), app_dir), dirs_exist_ok=True)

# Copy dependencies to report
shutil.copytree(os.path.join(app_dir, "dependencies"), os.path.join(out_dir, "dependencies"), dirs_exist_ok=True)

params = json.loads(r'$params_string')
schema_path = "$schema"
with open(schema_path) as f:
Expand All @@ -42,7 +45,7 @@
for tf, ranks in df_ranking.to_dict(orient="index").items()
}

assays = df_ranking.columns
assays = df_ranking.columns.tolist()
sorted(assays, reverse=True)

raw_tf_tg_ranking = {
Expand Down Expand Up @@ -89,6 +92,7 @@

tf = env.get_template("tf.html")
tg = env.get_template("tg.html")
network = env.get_template("network.html")
snp = env.get_template("snp.html")
configuration = env.get_template("configuration.html")
styles = env.get_template("styles.css")
Expand All @@ -109,6 +113,11 @@
differential=differential,
pairings=pairings))

with open(os.path.join(out_dir, "network.html"), "w") as f:
f.write(network.render(tf_tg_ranking=tf_tg_ranking,
assays=assays,
))

with open(os.path.join(out_dir, "snps.html"), "w") as f:
f.write(snp.render())

Expand Down

0 comments on commit 33ee950

Please sign in to comment.