Skip to content

Commit

Permalink
Add the GTExViewer component.
Browse files Browse the repository at this point in the history
  • Loading branch information
yjcyxky committed Apr 5, 2024
1 parent 2d3fd27 commit d588534
Show file tree
Hide file tree
Showing 18 changed files with 2,175 additions and 1,433 deletions.
2 changes: 2 additions & 0 deletions studio/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,5 +98,7 @@ export default defineConfig({
}
],
mfsu: {},
// https://github.com/umijs/umi/issues/8442
// https://umijs.org/docs/api/plugin-api#addhtmlheadscripts
scripts: []
});
10 changes: 8 additions & 2 deletions studio/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,11 @@
"biominer-components": "0.3.20",
"biomsa": "^0.3.3",
"classnames": "^2.3.0",
"file-saver": "^2.0.5",
"gtex-d3": "yjcyxky/gtex-viz#58b6493a",
"handlebars": "^4.7.7",
"handsontable": "^12.1.3",
"jwt-decode": "^4.0.0",
"jwt-decode": "^3.1.2",
"lodash": "^4.17.0",
"molstar": "^3.27.0",
"molstar-react": "^0.5.2",
Expand Down Expand Up @@ -87,7 +89,8 @@
"@types/react": "^18.0.0",
"@types/react-dom": "^18.0.0",
"@umijs/plugins": "^4.1.2",
"compression-webpack-plugin": "^11.1.0",
"commander": "11.1.0",
"compression-webpack-plugin": "^10.0.0",
"cross-env": "^7.0.3",
"husky": "^8.0.3",
"lint-staged": "^13.2.0",
Expand All @@ -110,6 +113,9 @@
"util": false,
"assert": false
},
"resolutions": {
"**/mockjs/commander": "11.1.0"
},
"browserslist": [
"> 1%",
"last 2 versions",
Expand Down
31 changes: 31 additions & 0 deletions studio/plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { IApi } from 'umi'

export default (api: IApi) => {
// For GTEx Components
api.addHTMLLinks(() => {
return [
{
rel: "stylesheet",
href: "https://gtexportal.org/external/bootstrap/3.3.7/bootstrap.min.css"
},
{
rel: "stylesheet",
href: "https://gtexportal.org/external/jquery-ui-1.11.4.custom/jquery-ui.css"
},
{
rel: "stylesheet",
href: "https://use.fontawesome.com/releases/v5.5.0/css/all.css"
}
]
})

// For GTEx Components
api.addHTMLHeadScripts(() => {
return [
"https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js",
"https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js",
"https://gtexportal.org/external/jquery-ui-1.11.4.custom/jquery-ui.min.js",
"https://gtexportal.org/external/bootstrap/3.3.7/bootstrap.min.js"
]
})
};
44 changes: 0 additions & 44 deletions studio/src/NodeInfoPanel/Components/ExpressionAtlas/index.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
.gtex-gene-violin-viewer {
position: relative;
width: 100%;
height: 100%;
// NOTE: Keep it same with the gtex-d3 library to avoid wrong height calculation.
max-height: 1200px;

#gtex-gene-violin-viewer-svg {
width: 100%;
}

.btn-group ~ div {
display: flex;

div {
margin-right: 5px;
}

.btn {
margin-right: 2px;
}

.btn:hover {
cursor: pointer;
}
}
}

.modal-backdrop {
display: none;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
title: GTexGeneViolinViewer
group:
path: /components/visualization-components
title: Visualization
---

## GTexGeneViolinViewer

```tsx
import React from 'react';
import { GTexGeneViolinViewer } from 'gtex-d3';

export default () => (
<GTexGeneViolinViewer
rootId="gtex-gene-violin-viewer"
title="GTex Gene Violin Viewer"
geneId="ENSG00000141510.16"
/>
);
```

<API></API>
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import React, { useRef, useEffect } from 'react';
// @ts-ignore
import { GeneExpressionViolinPlot } from 'gtex-d3';
// @ts-ignore
import jquery from 'jquery';
// @ts-ignore
import { parseGenes, getGtexUrls } from 'gtex-d3/src/modules/gtexDataParser';
import 'gtex-d3/css/geneExpViolin.css';

import './index.less';

type GeneViewerProps = {
/**
* @description Only support Hugo gene symbol or Ensembl gene ID. e.g. "TP53" or "ENSG00000141510"
*/
geneId: string;
/**
* @description Title of the plot.
*/
title?: string;
};

const host =
'https://gtexportal.org/api/v2/reference/geneSearch?geneId=';

const GTexGeneViolinViewer: React.FC<GeneViewerProps> = (props) => {
const ref = useRef(null);

const { geneId, title } = props;

const removeChildren = (tag: HTMLElement) => {
if (tag.children) {
tag.innerHTML = '';
}
};

const fetchGene = async (geneId: string) => {
const response = await fetch(`${host}${geneId}`);
const data = await response.json();
return data;
};

const launch = (element: HTMLElement, gencodeId: string) => {
// @ts-ignore
window.$ = jquery;

console.log("Launch violin plot: ", GeneExpressionViolinPlot);
const width = element.clientWidth - 100;
// (Re)render the plot
GeneExpressionViolinPlot.launchBulkTissueViolinPlot(
"gene-expr-vplot",
"gene-expr-vplot-tooltip",
gencodeId,
'', // title
getGtexUrls(), // urls
{
top: 50,
right: 75,
bottom: 150,
left: 60,
}, // margins
{
w: width,
h: 250,
}, // dimensions
);
}

const update = () => {
// Remove existing children from the container element
if (ref.current) {
const element = ref.current as HTMLElement;
removeChildren(element);

fetchGene(geneId)
.then((data) => {
const gene = parseGenes(data, true, geneId);
const gencodeId = gene.gencodeId;

launch(element, gencodeId);
})
.catch((error) => {
console.log(error);
});
}
};

useEffect(() => {
if (ref.current && geneId) {
if (/.*\.[0-9]+/.test(geneId)) {
launch(ref.current as HTMLElement, geneId);
} else {
update();
}
}
}, [geneId]);

return (
<div className="gtex-gene-violin-viewer">
{title && <h3>{title}</h3>}
<div id="gene-expr-vplot" style={{ width: '100%' }} ref={ref} />
<div className="modal fade" id="gene-expr-vplot-filter-modal" tabIndex={-1} role="dialog" aria-labelledby="Gene Expr Violin Plot Tissue Filter Modal" aria-hidden="true">
<div className="modal-dialog modal-lg" role="document">
<div className="modal-content">
<div className="modal-header">
<h5 className="modal-title">Tissue Filter</h5>
<button id="gene-expr-vplot-filter-modal-close" type="button" data-dismiss="modal"
aria-label="Close" className="close">
<span aria-hidden="true"><i className="far fa-times-circle"></i></span>
</button>
</div>
<div className="modal-body">
<div className="row" id="gene-expr-vplot-filter-modal-body"></div>
</div>
<div className="modal-footer">
<button id="gene-expr-vplot-filter-modal-button" type="button"
data-dismiss="modal" className="btn btm-sm btn-default"
style={{ fontSize: '11px' }}>
Apply
</button>
</div>
</div>
</div>
</div>
</div>
);
};

export default GTexGeneViolinViewer;
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.gtex-transcript-viewer {
position: relative;
width: 100%;
height: 100%;
// NOTE: Keep it same with the gtex-d3 library to avoid wrong height calculation.
max-height: 1200px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
title: GTexTranscriptViewer
group:
path: /components/visualization-components
title: Visualization
---

## GTexTranscriptViewer

### IsoformTransposed Type

```tsx
import React from 'react';
import { GTexTranscriptViewer } from 'gtex-d3';

export default () => (
<GTexTranscriptViewer
rootId="gtex-transcript-viewer-isoform-transposed"
title="GTex Transcript Viewer"
geneId="ENSG00000141510"
type="isoformTransposed"
/>
);
```

### Isoform Type

```tsx
import React from 'react';
import { GTexTranscriptViewer } from 'gtex-d3';

export default () => (
<GTexTranscriptViewer
rootId="gtex-transcript-viewer-isoform"
title="GTex Transcript Viewer"
geneId="ENSG00000141510"
type="exon"
/>
);
```

### Junction Type

```tsx
import React from 'react';
import { GTexTranscriptViewer } from 'gtex-d3';

export default () => (
<GTexTranscriptViewer
rootId="gtex-transcript-viewer-junction"
title="GTex Transcript Viewer"
geneId="ENSG00000141510"
type="junction"
/>
);
```

<API></API>
Loading

0 comments on commit d588534

Please sign in to comment.