Skip to content

Commit

Permalink
Add Asxl1 for testing multiple gene lists
Browse files Browse the repository at this point in the history
  • Loading branch information
akikuno committed Mar 1, 2025
1 parent d008a77 commit 825861d
Show file tree
Hide file tree
Showing 14 changed files with 719 additions and 33 deletions.
16 changes: 16 additions & 0 deletions TSUMUGI/app/js/components.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export function calculateConnectedComponents(cy) {
const visibleElements = cy.elements(':visible');
const connectedComponents = visibleElements.components();

return connectedComponents.map(component => {
let componentObject = {};
component.nodes().forEach(node => {
const nodeLabel = node.data('label');
const nodeAnnotations = Array.isArray(node.data('annotation'))
? node.data('annotation')
: [node.data('annotation')];
componentObject[nodeLabel] = nodeAnnotations;
});
return componentObject;
});
}
12 changes: 7 additions & 5 deletions TSUMUGI/app/js/exporter.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import { calculateConnectedComponents } from './components.js';

// --------------------------------------------------------
// PNG Exporter
// --------------------------------------------------------

function exportGraphAsPNG() {
export function exportGraphAsPNG(cy, file_name) {
const pngContent = cy.png({
scale: 6.25, // Scale to achieve 600 DPI
full: true // Set to true to include the entire graph, even the offscreen parts
});

const a = document.createElement('a');
a.href = pngContent;
a.download = 'TSUMUGI_XXX_genesymbol.png';
a.download = `${file_name}.png`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
Expand All @@ -21,9 +23,9 @@ function exportGraphAsPNG() {
// CSV Exporter
// --------------------------------------------------------

function exportGraphAsCSV() {
export function exportGraphAsCSV(cy, file_name) {
// calculateConnectedComponentsを利用して連結成分を取得
const connected_component = calculateConnectedComponents();
const connected_component = calculateConnectedComponents(cy);

// CSVのヘッダー行
let csvContent = "cluster,gene,phenotypes\n";
Expand All @@ -45,7 +47,7 @@ function exportGraphAsCSV() {
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'TSUMUGI_XXX_genesymbol.csv';
a.download = `${file_name}.csv`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
Expand Down
96 changes: 96 additions & 0 deletions TSUMUGI/app/js/tooltips.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// ############################################################
// Tooltip Handling Functions
// ############################################################

// Function to remove all existing tooltips
export function removeTooltips() {
document.querySelectorAll('.cy-tooltip').forEach(el => el.remove());
}

// Function to create tooltip content for nodes and edges
function createTooltip(event, cy, map_symbol_to_id) {
const data = event.target.data();
let tooltipText = '';
let pos;

if (event.target.isNode()) {
const annotations = Array.isArray(data.annotation)
? data.annotation.map(anno => '・ ' + anno).join('<br>')
: '・ ' + data.annotation;

const geneID = map_symbol_to_id[data.label] || "UNKNOWN"; // undefined の場合に備える
const url_impc = `https://www.mousephenotype.org/data/genes/${geneID}`;
tooltipText = `<b>Phenotypes of <a href="${url_impc}" target="_blank">${data.label} KO mice</a></b><br>` + annotations;

pos = event.target.renderedPosition();
} else if (event.target.isEdge()) {
const sourceNode = cy.getElementById(data.source).data('label');
const targetNode = cy.getElementById(data.target).data('label');
const annotations = Array.isArray(data.annotation)
? data.annotation.map(anno => '・ ' + anno).join('<br>')
: '・ ' + data.annotation;

tooltipText = `<b>Shared phenotypes of ${sourceNode} and ${targetNode} KOs</b><br>` + annotations;

const sourcePos = cy.getElementById(data.source).renderedPosition();
const targetPos = cy.getElementById(data.target).renderedPosition();
pos = { x: (sourcePos.x + targetPos.x) / 2, y: (sourcePos.y + targetPos.y) / 2 };
}

return { tooltipText, pos };
}

// Function to show tooltip
export function showTooltip(event, cy, map_symbol_to_id) {
removeTooltips(); // Remove existing tooltips

const { tooltipText, pos } = createTooltip(event, cy, map_symbol_to_id);

const tooltip = document.createElement('div');
tooltip.classList.add('cy-tooltip');
tooltip.innerHTML = tooltipText;
Object.assign(tooltip.style, {
position: 'absolute',
left: `${pos.x + 10}px`,
top: `${pos.y + 10}px`,
padding: '5px',
background: 'white',
border: '1px solid #ccc',
borderRadius: '5px',
boxShadow: '0 2px 10px rgba(0,0,0,0.2)',
zIndex: '1000',
cursor: 'move',
userSelect: 'text'
});

document.querySelector('.cy').appendChild(tooltip);
enableTooltipDrag(tooltip);
}

// Function to enable dragging for tooltips
function enableTooltipDrag(tooltip) {
let isDragging = false;
let offset = { x: 0, y: 0 };

tooltip.addEventListener('mousedown', function (e) {
e.stopPropagation();
isDragging = true;
const rect = tooltip.getBoundingClientRect();
offset.x = e.clientX - rect.left;
offset.y = e.clientY - rect.top;
tooltip.style.cursor = 'grabbing';
});

document.addEventListener('mousemove', function (e) {
if (isDragging) {
const containerRect = document.querySelector('.cy').getBoundingClientRect();
tooltip.style.left = `${e.clientX - offset.x - containerRect.left}px`;
tooltip.style.top = `${e.clientY - offset.y - containerRect.top}px`;
}
});

document.addEventListener('mouseup', function () {
isDragging = false;
tooltip.style.cursor = 'move';
});
}
28 changes: 28 additions & 0 deletions TSUMUGI/app/js/value_scaler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@

export function scaleToOriginalRange(value, minValue, maxValue) {
// Scales a value from the range [1, 10] to a new range [minValue, maxValue].
return minValue + (value - 1) * (maxValue - minValue) / 9;
}

export function scaleValue(value, minValue, maxValue, minScale, maxScale) {
// スケールをminScaleとmaxScaleの範囲に変換
if (minValue == maxValue) {
return (maxScale + minScale) / 2;
}
return minScale + (value - minValue) * (maxScale - minScale) / (maxValue - minValue);
}

export function getColorForValue(value) {
// value を1-10の範囲から0-1の範囲に変換
const ratio = (value - 1) / (10 - 1);

// Light Yellow から Orange へのグラデーション
const r1 = 248, g1 = 229, b1 = 140; // Light Yellow
const r2 = 255, g2 = 140, b2 = 0; // Orange

const r = Math.round(r1 + (r2 - r1) * ratio);
const g = Math.round(g1 + (g2 - g1) * ratio);
const b = Math.round(b1 + (b2 - b1) * ratio);

return `rgb(${r}, ${g}, ${b})`;
}
Loading

0 comments on commit 825861d

Please sign in to comment.