mirror of
https://github.com/haniffalab/scRNA-seq_analysis.git
synced 2024-10-23 08:29:24 -07:00
scRNA-seq_analysis
This commit is contained in:
commit
82cc2d191e
188 changed files with 146184 additions and 0 deletions
33694
pipelines/90_web_portal/genes.tsv
Executable file
33694
pipelines/90_web_portal/genes.tsv
Executable file
File diff suppressed because it is too large
Load diff
42653
pipelines/90_web_portal/hgnc.csv
Executable file
42653
pipelines/90_web_portal/hgnc.csv
Executable file
File diff suppressed because it is too large
Load diff
4
pipelines/90_web_portal/options_files/dummydata_options.txt
Executable file
4
pipelines/90_web_portal/options_files/dummydata_options.txt
Executable file
|
|
@ -0,0 +1,4 @@
|
|||
file_name: ../../data/dummydata.RDS
|
||||
output_folder: ../../output/dummydata_web_portal
|
||||
dr_coordonates: UMAP->umap; tSNE->tsne; FDG->fdg;
|
||||
Cell Labels->Annotation_5->null;
|
||||
4
pipelines/90_web_portal/options_files/liver_web_portal_options.txt
Executable file
4
pipelines/90_web_portal/options_files/liver_web_portal_options.txt
Executable file
|
|
@ -0,0 +1,4 @@
|
|||
file_name: ../../data/liver_all.RDS
|
||||
output_folder: ../../output/liver_web_portal
|
||||
dr_coordonates: UMAP->umap; tSNE->tsne; FDG->fdg;
|
||||
Cell Labels->cell.labels->../../resources/liver_cell_type_colours.csv;Cell Subsets->cell.labels->null;Flow gate->sort.ids->null;Sample->sample.ids->null;Gender->gender->null;
|
||||
4
pipelines/90_web_portal/options_files/thymus_web_portal_options.txt
Executable file
4
pipelines/90_web_portal/options_files/thymus_web_portal_options.txt
Executable file
|
|
@ -0,0 +1,4 @@
|
|||
file_name: ../../data/thymus.h5ad
|
||||
output_folder: ../../output/thymus_web_portal
|
||||
dr_coordonates: UMAP->X_umap; tSNE->X_tsne; FDG->X_draw_graph_fa;
|
||||
Cell Labels->Annotation->null;Flow gate->sort->null;Sample->sample->null;Gender->gender->null;
|
||||
94
pipelines/90_web_portal/scanpy_to_seurat.py
Executable file
94
pipelines/90_web_portal/scanpy_to_seurat.py
Executable file
|
|
@ -0,0 +1,94 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Thu Dec 20 12:00:47 2018
|
||||
|
||||
@author: doru
|
||||
"""
|
||||
|
||||
# gene expression should be at data.X
|
||||
# gene symbols should be at data.var.GeneName
|
||||
# DRs should be at data.obsm
|
||||
# categoeis should be columns at data.obs
|
||||
|
||||
import sys
|
||||
option_files = sys.argv[1]
|
||||
|
||||
#option_files = "thymus_web_portal_options.txt"
|
||||
|
||||
import matplotlib; matplotlib.use('Agg');
|
||||
import scanpy.api as sc
|
||||
from os.path import join
|
||||
from scipy.io import mmwrite
|
||||
from scipy.sparse import hstack
|
||||
import numpy as np
|
||||
import random
|
||||
import pandas as pd
|
||||
|
||||
# extract options
|
||||
options_fobj = open(option_files, 'r')
|
||||
options = options_fobj.readlines()
|
||||
options_fobj.close()
|
||||
options = [op.strip() for op in options]
|
||||
# make file_name variable
|
||||
file_name = options[0].split(':')[1].strip()
|
||||
# make output_folder variable
|
||||
output_folder = options[1].split(':')[1].strip()
|
||||
# make dr_coordinates
|
||||
dr_coordinates = options[2].split(':')[1].strip()
|
||||
dr_coordinates = dr_coordinates.split(";")
|
||||
dr_coordinates = [dr.split('->')[1] for dr in dr_coordinates if dr != '']
|
||||
# extract categories
|
||||
categories = options[3].split(';')
|
||||
categories = [cat.split('->') for cat in categories if cat != '']
|
||||
|
||||
data = sc.read(file_name)
|
||||
|
||||
# save expression data
|
||||
expression_data_filename = join(output_folder, 'expression')
|
||||
nUMI = np.array(data.obs.n_UMIs)
|
||||
nUMI = nUMI.reshape((nUMI.shape[0], 1))
|
||||
nGene = np.array(data.obs.n_genes)
|
||||
nGene = nUMI.reshape((nGene.shape[0], 1))
|
||||
gene_expression = hstack([data.X, nUMI, nGene])
|
||||
mmwrite(expression_data_filename, gene_expression)
|
||||
|
||||
# save gene names
|
||||
gene_names = [g for g in data.var.GeneName]
|
||||
gene_names.append('nUMI')
|
||||
gene_names.append('nGene')
|
||||
gene_names = '\n'.join(gene_names)
|
||||
gene_names_fobj = open(join(output_folder, 'gene_names.txt'), 'w')
|
||||
gene_names_fobj.write(gene_names)
|
||||
gene_names_fobj.close()
|
||||
|
||||
# get DR coordinates
|
||||
for index, dr_coor in enumerate(dr_coordinates):
|
||||
if index == 0:
|
||||
dr_data = data.obsm[dr_coor]
|
||||
else:
|
||||
dr_data = np.concatenate([dr_data, data.obsm[dr_coor]], axis = 1)
|
||||
np.savetxt(join(output_folder, "dr.csv"), dr_data, delimiter=",")
|
||||
|
||||
# get categories
|
||||
for index, category in enumerate(categories):
|
||||
slot = category[1]
|
||||
category_col = category[2]
|
||||
category_data = data.obs[slot]
|
||||
if category_col == 'null':
|
||||
category_unique = category_data.values.categories
|
||||
r = lambda: random.randint(0,255)
|
||||
category_col = {}
|
||||
for unique in category_unique:
|
||||
category_col[unique] = '#%02X%02X%02X' % (r(),r(),r())
|
||||
category_col = category_data.map(category_col)
|
||||
else:
|
||||
category_col = pd.read.csv('when colour keys are ready continue script here')
|
||||
categories_data = pd.concat([category_data, category_col], axis = 1)
|
||||
categories_data.columns = [category[0], '{c}_Colour'.format(c = category[0])]
|
||||
if index == 0:
|
||||
csv_data = categories_data
|
||||
else:
|
||||
csv_data = pd.concat([csv_data, categories_data], axis = 1)
|
||||
categories_fname = join(output_folder, 'categories.csv')
|
||||
csv_data.to_csv(categories_fname)
|
||||
37
pipelines/90_web_portal/templates_no_password_protection/fetch_category.php
Executable file
37
pipelines/90_web_portal/templates_no_password_protection/fetch_category.php
Executable file
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
$mot_de_pass = $_GET['mot_de_pass'];
|
||||
$password = "clear_to_go";
|
||||
if ($mot_de_pass != $password){
|
||||
exit('Password not correct');
|
||||
}
|
||||
|
||||
$category_name = $_GET["category"];
|
||||
$color_key_file = $category_name . "_color_key.csv";
|
||||
$color_key_file = "./categories/" . $color_key_file;
|
||||
$color_key_file = fopen($color_key_file, "r");
|
||||
$line = fgets($color_key_file );
|
||||
$data_string = "";
|
||||
while (($line = fgets($color_key_file)) !== false){
|
||||
$col_key = explode(",", $line);
|
||||
$cell_name = $col_key[0];
|
||||
$cell_col = $col_key[1];
|
||||
$button_html = str_replace('cell_name', str_replace('"', "", $cell_name), "<div style='background-color: cell_color;'><input type = 'checkbox' onchange='toggleCategoryAction()' name = 'cellTypeBtn' id='cell_name' checked /><label for = 'cell_name'> cell_name</label></div>");
|
||||
$button_html = str_replace('cell_color', str_replace('"', "", $cell_col), $button_html);
|
||||
$data_string = $data_string . $button_html;
|
||||
}
|
||||
fclose($color_key_file);
|
||||
|
||||
$categories_colors_file = "./categories/" . $category_name . "_colors";
|
||||
$categories_colors_file = fopen($categories_colors_file, "r");
|
||||
$categories_colors = fgets($categories_colors_file);
|
||||
fclose($categories_colors_file);
|
||||
$data_string = $data_string . "&&" . $categories_colors;
|
||||
|
||||
$categories_indices_file = "./categories/" . $category_name . "_indices";
|
||||
$categories_indices_file = fopen($categories_indices_file, "r");
|
||||
$categories_indices = fgets($categories_indices_file);
|
||||
fclose($categories_indices_file);
|
||||
$data_string = $data_string . "&&" . $categories_indices;
|
||||
|
||||
echo $data_string;
|
||||
?>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
$dr_fname = "./dr/" . $_GET["dr_name"] . "_coordinates";
|
||||
$dr_file = fopen($dr_fname, 'r');
|
||||
$dr_array = fgets($dr_file);
|
||||
fclose($dr_file);
|
||||
echo $dr_array;
|
||||
?>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
$gene_name = $_GET["gene_name"];
|
||||
$gene_expression_file = './genes/' . $gene_name;
|
||||
$gene_expression_file = fopen($gene_expression_file, 'r');
|
||||
$gene_expression = fgets($gene_expression_file);
|
||||
echo $gene_expression;
|
||||
?>
|
||||
753
pipelines/90_web_portal/templates_no_password_protection/index.php
Executable file
753
pipelines/90_web_portal/templates_no_password_protection/index.php
Executable file
|
|
@ -0,0 +1,753 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Gene expression web portal</title>
|
||||
<meta name="description" content="Gene expression web portal for single cell RNA sequencing data made for the Human Cell Atlas at Newcastle University">
|
||||
<meta name="author" content="Dorin-Mirel Popescu">
|
||||
<style>
|
||||
body {
|
||||
font-family: Avenir, Arial, sans-serif;
|
||||
}
|
||||
#div_left {
|
||||
float: left;
|
||||
}
|
||||
|
||||
#canvasdiv {
|
||||
overflow-x: scroll;
|
||||
overflow-y: scroll;
|
||||
max-height: 90vh;
|
||||
}
|
||||
|
||||
#typesControlPanel {
|
||||
height: 25em;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
#cursorText{
|
||||
position:absolute;
|
||||
background-color: black;
|
||||
color : white;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<?php
|
||||
$password = 'clear_to_go';
|
||||
|
||||
echo "<script type = 'text/javascript'>";
|
||||
echo "var password = 'clear_to_go'";
|
||||
echo "</script>";
|
||||
?>
|
||||
|
||||
<div id = "div_left">
|
||||
<form>
|
||||
<fieldset>
|
||||
<legend><b>Visualisation options</b></legend>
|
||||
<label for = 'particleSizeBar'>Particle size: </label>
|
||||
<input type='range' name = 'particleSizeBar' min = .3 max = 7 step=0.1 oninput='setParticleSize(value)' value = 2 /><br/>
|
||||
|
||||
<label for = 'alphaInput'>Transparency: </label>
|
||||
<input type='range' name = 'alphaInput' min = 0 max = 1000 oninput='setAlpha(value)' value = 1000 /><br/>
|
||||
|
||||
<label for = 'canvasSizeInput'>Canvas size: </label>
|
||||
<input type='range' name = 'canvasSizeInput' min = 200 max = 2000 oninput='setCanvasSize(value)' value = 500 /><br/>
|
||||
</fieldset>
|
||||
</form>
|
||||
<form>
|
||||
<fieldset>
|
||||
<legend><b>Cell types</b></legend>
|
||||
<div>
|
||||
<div>
|
||||
Select category: <select id='categorySelectMenu' onchange = 'updateCategories(value)'>
|
||||
<?php
|
||||
$categories_file = fopen("./categories/categories_key", "r");
|
||||
$categories_content = fgets($categories_file);
|
||||
fclose($categories_file);
|
||||
$categories = explode(";", $categories_content);
|
||||
foreach($categories as $category){
|
||||
$category_fields = explode("->", $category);
|
||||
$category_name = $category_fields[0];
|
||||
$category_value = $category_fields[1];
|
||||
echo "<option value='" . $category_value . "'>" . $category_name . "</option>";
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<label for='toggleRadio'><input type='checkbox' name = 'toggleRadio' id='toggleRadio' onchange='toggleAllTypes()' checked />Show all</label>
|
||||
<div id='typesControlPanel'>
|
||||
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id = "div_right">
|
||||
<div>
|
||||
<b>Colour by:</b>
|
||||
<label for='colourType_t'><input type='radio' name='colourType' id='colourType_t' onchange='setColourBy(value)' value='cell_type' checked />Cell type</label>
|
||||
<label for='colourType_g'><input type='radio' name='colourType' id='colourType_g' onchange='setColourBy(value)' value='gene_expression' />Gene expression</label>
|
||||
</div>
|
||||
<table id = "geneSelectorTable">
|
||||
<tr>
|
||||
<td>
|
||||
<label for='geneFamilySelector'>Gene family:</label>
|
||||
</td>
|
||||
<td>
|
||||
<select name='geneFamilySelector' id='geneFamilySelector' onchange='selectFamily(value)'>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for='geneSymbolSelector'>Gene symbol:</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type = 'text' id='genelist_input' name = 'geneSymbolSelector_datalist' list='geneSymbolSelector_datalist' onchange='getGeneExpression(this)'>
|
||||
<datalist id = 'geneSymbolSelector_datalist'>
|
||||
<select onchange = 'getGeneExpression(this)' id ='geneSymbolSelector'></select>
|
||||
</datalist>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<label for = 'bgColorRadio_white'><input id = 'bgColorRadio_white' name = "bgColorRadio" type = "radio" value = 'white' onchange='setBackground(value)' checked/>White background </label>
|
||||
<label for = 'bgColorRadio_dark'><input id = 'bgColorRadio_dark' name = "bgColorRadio" type = "radio" value = 'dark' onchange='setBackground(value)' />Dark background </label>
|
||||
<br/><span id='expression_scale'></span>
|
||||
<div>
|
||||
Choose coordinates: <select onchange = 'getCoordinates(value)'>
|
||||
<?php
|
||||
$dr_file = fopen("./dr/dr_key", "r");
|
||||
$dr_content = fgets($dr_file);
|
||||
fclose($dr_file);
|
||||
$dr_cats = explode(";", $dr_content);
|
||||
foreach($dr_cats as $dr_cat){
|
||||
echo 1;
|
||||
$dr_fields = explode("->", $dr_cat);
|
||||
$dr_name = $dr_fields[0];
|
||||
echo "<option value='" . $dr_name . "'>" . $dr_name . "</option>";
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
<div id='canvasdiv'><canvas id='canvas' width=500 height=500></canvas></div>
|
||||
</div>
|
||||
|
||||
<script id='vertex-shader' type='x-shader/x-fragment'>
|
||||
attribute vec4 a_Position;
|
||||
attribute vec3 a_Color;
|
||||
uniform float u_basePointSize;
|
||||
uniform float u_Alpha;
|
||||
uniform int u_PaintFeatureScale;
|
||||
varying vec4 v_Color;
|
||||
void main() {
|
||||
gl_Position = a_Position;
|
||||
gl_PointSize = u_basePointSize;
|
||||
if (u_PaintFeatureScale == 0){
|
||||
v_Color = vec4(a_Color, u_Alpha);
|
||||
}
|
||||
else{
|
||||
float r = 0.0;
|
||||
float g = 0.0;
|
||||
float b = 0.0;
|
||||
r = max(0.0, 2.0 * a_Color.r - 1.0);
|
||||
b = max(0.0, 2.0 * (1.0 - a_Color.r) - 1.0);
|
||||
g = 1.0 - 2.0 * abs(a_Color.r - 0.5);
|
||||
v_Color = vec4(r, g, b, u_Alpha);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script id ='fragment-shader' type='x-shader/x-fragment'>
|
||||
precision mediump float;
|
||||
varying vec4 v_Color;
|
||||
void main() {
|
||||
float r = 0.0;
|
||||
vec2 cxy = 2.0 * gl_PointCoord - 1.0;
|
||||
r = dot(cxy, cxy);
|
||||
if (r > 1.0){
|
||||
discard;
|
||||
}
|
||||
gl_FragColor = v_Color;
|
||||
}
|
||||
</script>
|
||||
|
||||
<?php
|
||||
echo "<script type = 'text/javascript'>";
|
||||
$gene_families_file = fopen("./genes/gene_lists", "r");
|
||||
$gene_families_content = fgets($gene_families_file);
|
||||
fclose($gene_families_file);
|
||||
echo $gene_families_content;
|
||||
|
||||
$dr_file = fopen("./dr/dr_key", "r");
|
||||
$dr_content = fgets($dr_file);
|
||||
fclose($dr_file);
|
||||
$dr_cats = explode(";", $dr_content);
|
||||
$first_dr = explode('->', $dr_cats[0])[0];
|
||||
echo "first_dr = '" . $first_dr . "'";
|
||||
echo "</script>";
|
||||
?>
|
||||
|
||||
<script type = 'text/javascript'>
|
||||
|
||||
var Matrix4 = function(opt_src) {
|
||||
var i, s, d;
|
||||
if (opt_src && typeof opt_src === 'object' && opt_src.hasOwnProperty('elements')) {
|
||||
s = opt_src.elements;
|
||||
d = new Float32Array(16);
|
||||
for (i = 0; i < 16; ++i) {
|
||||
d[i] = s[i];
|
||||
}
|
||||
this.elements = d;
|
||||
} else {
|
||||
this.elements = new Float32Array([1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1]);
|
||||
}
|
||||
};
|
||||
|
||||
Matrix4.prototype.setTranslate = function(x, y, z) {
|
||||
var e = this.elements;
|
||||
e[0] = 1; e[4] = 0; e[8] = 0; e[12] = x;
|
||||
e[1] = 0; e[5] = 1; e[9] = 0; e[13] = y;
|
||||
e[2] = 0; e[6] = 0; e[10] = 1; e[14] = z;
|
||||
e[3] = 0; e[7] = 0; e[11] = 0; e[15] = 1;
|
||||
return this;
|
||||
};
|
||||
|
||||
Matrix4.prototype.setLookAt = function(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ) {
|
||||
var e, fx, fy, fz, rlf, sx, sy, sz, rls, ux, uy, uz;
|
||||
|
||||
fx = centerX - eyeX;
|
||||
fy = centerY - eyeY;
|
||||
fz = centerZ - eyeZ;
|
||||
|
||||
// Normalize f.
|
||||
rlf = 1 / Math.sqrt(fx*fx + fy*fy + fz*fz);
|
||||
fx *= rlf;
|
||||
fy *= rlf;
|
||||
fz *= rlf;
|
||||
|
||||
// Calculate cross product of f and up.
|
||||
sx = fy * upZ - fz * upY;
|
||||
sy = fz * upX - fx * upZ;
|
||||
sz = fx * upY - fy * upX;
|
||||
|
||||
// Normalize s.
|
||||
rls = 1 / Math.sqrt(sx*sx + sy*sy + sz*sz);
|
||||
sx *= rls;
|
||||
sy *= rls;
|
||||
sz *= rls;
|
||||
|
||||
// Calculate cross product of s and f.
|
||||
ux = sy * fz - sz * fy;
|
||||
uy = sz * fx - sx * fz;
|
||||
uz = sx * fy - sy * fx;
|
||||
|
||||
// Set to this.
|
||||
e = this.elements;
|
||||
e[0] = sx;
|
||||
e[1] = ux;
|
||||
e[2] = -fx;
|
||||
e[3] = 0;
|
||||
|
||||
e[4] = sy;
|
||||
e[5] = uy;
|
||||
e[6] = -fy;
|
||||
e[7] = 0;
|
||||
|
||||
e[8] = sz;
|
||||
e[9] = uz;
|
||||
e[10] = -fz;
|
||||
e[11] = 0;
|
||||
|
||||
e[12] = 0;
|
||||
e[13] = 0;
|
||||
e[14] = 0;
|
||||
e[15] = 1;
|
||||
|
||||
// Translate.
|
||||
return this.translate(-eyeX, -eyeY, -eyeZ);
|
||||
};
|
||||
|
||||
Matrix4.prototype.translate = function(x, y, z) {
|
||||
var e = this.elements;
|
||||
e[12] += e[0] * x + e[4] * y + e[8] * z;
|
||||
e[13] += e[1] * x + e[5] * y + e[9] * z;
|
||||
e[14] += e[2] * x + e[6] * y + e[10] * z;
|
||||
e[15] += e[3] * x + e[7] * y + e[11] * z;
|
||||
return this;
|
||||
};
|
||||
|
||||
Matrix4.prototype.setPerspective = function(fovy, aspect, near, far) {
|
||||
var e, rd, s, ct;
|
||||
|
||||
if (near === far || aspect === 0) {
|
||||
throw 'null frustum';
|
||||
}
|
||||
if (near <= 0) {
|
||||
throw 'near <= 0';
|
||||
}
|
||||
if (far <= 0) {
|
||||
throw 'far <= 0';
|
||||
}
|
||||
|
||||
fovy = Math.PI * fovy / 180 / 2;
|
||||
s = Math.sin(fovy);
|
||||
if (s === 0) {
|
||||
throw 'null frustum';
|
||||
}
|
||||
|
||||
rd = 1 / (far - near);
|
||||
ct = Math.cos(fovy) / s;
|
||||
|
||||
e = this.elements;
|
||||
|
||||
e[0] = ct / aspect;
|
||||
e[1] = 0;
|
||||
e[2] = 0;
|
||||
e[3] = 0;
|
||||
|
||||
e[4] = 0;
|
||||
e[5] = ct;
|
||||
e[6] = 0;
|
||||
e[7] = 0;
|
||||
|
||||
e[8] = 0;
|
||||
e[9] = 0;
|
||||
e[10] = -(far + near) * rd;
|
||||
e[11] = -1;
|
||||
|
||||
e[12] = 0;
|
||||
e[13] = 0;
|
||||
e[14] = -2 * near * far * rd;
|
||||
e[15] = 0;
|
||||
|
||||
return this;
|
||||
};
|
||||
</script>
|
||||
|
||||
<script type = 'text/javascript'>
|
||||
function initContext(gl){
|
||||
n = buffer_data_array.length / 5
|
||||
var vertexColourBuffer = gl.createBuffer()
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, vertexColourBuffer)
|
||||
|
||||
var FSIZE = buffer_data_array.BYTES_PER_ELEMENT;
|
||||
|
||||
var a_Position = gl.getAttribLocation(gl.program, 'a_Position')
|
||||
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 5, 0)
|
||||
gl.enableVertexAttribArray(a_Position)
|
||||
|
||||
var a_Color = gl.getAttribLocation(gl.program, 'a_Color')
|
||||
gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 5, 2 * FSIZE)
|
||||
gl.enableVertexAttribArray(a_Color)
|
||||
|
||||
u_basePointSize = gl.getUniformLocation(gl.program, 'u_basePointSize')
|
||||
gl.uniform1f(u_basePointSize, particleSize)
|
||||
|
||||
u_Alpha = gl.getUniformLocation(gl.program, "u_Alpha")
|
||||
gl.uniform1f(u_Alpha, alphaValue)
|
||||
|
||||
u_PaintFeatureScale = gl.getUniformLocation(gl.program, 'u_PaintFeatureScale')
|
||||
gl.uniform1i(u_PaintFeatureScale, PaintFeatureScale)
|
||||
|
||||
gl.clearColor(1, 1, 1, 1);
|
||||
if(bg_color == "dark"){
|
||||
gl.clearColor(0, 0, 0, 1)
|
||||
}
|
||||
|
||||
gl.disable(gl.DEPTH_TEST)
|
||||
gl.enable(gl.BLEND)
|
||||
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
|
||||
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
return gl
|
||||
}
|
||||
|
||||
function getContext(canvasWidget){
|
||||
var names = ['webgl', 'experimental-webgl', 'webkit-3d', 'moz-webgl'];
|
||||
for(var i=0; i<names.length; i++){
|
||||
try{
|
||||
var gl = canvasWidget.getContext(names[i])
|
||||
}catch(e){}
|
||||
if(gl){i=names.length}
|
||||
}
|
||||
|
||||
var vshader = shadersFromScriptElement(gl, 'vertex-shader', gl.VERTEX_SHADER),
|
||||
fshader = shadersFromScriptElement(gl, 'fragment-shader', gl.FRAGMENT_SHADER)
|
||||
program = gl.createProgram();
|
||||
gl.attachShader(program, vshader)
|
||||
gl.attachShader(program, fshader)
|
||||
gl.linkProgram(program)
|
||||
gl.useProgram(program)
|
||||
gl.program = program
|
||||
return gl
|
||||
}
|
||||
|
||||
function shadersFromScriptElement(gl, ID, type){
|
||||
shaderScript = document.getElementById(ID)
|
||||
var str = ''
|
||||
var k = shaderScript.firstChild;
|
||||
while(k){
|
||||
if (k.nodeType == 3){
|
||||
str += k.textContent;
|
||||
}
|
||||
k = k.nextSibling
|
||||
}
|
||||
var shader = gl.createShader(type)
|
||||
gl.shaderSource(shader, str)
|
||||
gl.compileShader(shader)
|
||||
return shader
|
||||
}
|
||||
|
||||
function toggleAllTypes(){
|
||||
for (i=0;i<typesControlPanel.childElementCount;i++){
|
||||
typesControlPanel.children[i].children[0].checked = toggleRadio.checked;
|
||||
}
|
||||
updateBuffer()
|
||||
draw()
|
||||
}
|
||||
|
||||
function updateBuffer(){
|
||||
var buffer_data = [];
|
||||
// first update indices to be used - for this read the category control panel radio buttons
|
||||
current_indices = []
|
||||
for(i=0;i<typesControlPanel.childElementCount;i++){
|
||||
if(typesControlPanel.children[i].children[0].checked){
|
||||
radio_type = typesControlPanel.children[i].children[0].id
|
||||
current_indices = current_indices.concat(type_indices[radio_type])
|
||||
}
|
||||
}
|
||||
// now just populate the buffer_data
|
||||
if(colour_by == 'gene_expression'){
|
||||
current_indices.forEach(function(index, i){
|
||||
buffer_data.push(dr_coordinates[2 * index])
|
||||
buffer_data.push(dr_coordinates[2 * index + 1])
|
||||
buffer_data.push(gene_expression[index])
|
||||
buffer_data.push(gene_expression[index])
|
||||
buffer_data.push(gene_expression[index])
|
||||
})
|
||||
}else{
|
||||
current_indices.forEach(function(index){
|
||||
buffer_data.push(dr_coordinates[2 * index])
|
||||
buffer_data.push(dr_coordinates[2 * index + 1])
|
||||
buffer_data.push(category_type_colors[3 * index])
|
||||
buffer_data.push(category_type_colors[3 * index + 1])
|
||||
buffer_data.push(category_type_colors[3 * index + 2])
|
||||
})
|
||||
}
|
||||
buffer_data_array = new Float32Array(buffer_data)
|
||||
n = buffer_data_array.length / 5
|
||||
}
|
||||
|
||||
function draw(){
|
||||
if(bg_color == "white"){
|
||||
gl_context.clearColor(1, 1, 1, 1)
|
||||
}else{
|
||||
gl_context.clearColor(0, 0, 0, 1)
|
||||
}
|
||||
gl_context.clear(gl_context.COLOR_BUFFER_BIT);
|
||||
if(n > 0){
|
||||
gl_context.bufferData(gl_context.ARRAY_BUFFER, buffer_data_array, gl_context.STATIC_DRAW)
|
||||
gl_context.drawArrays(gl_context.POINTS, 0, n)
|
||||
}
|
||||
}
|
||||
|
||||
function setParticleSize(value){
|
||||
particleSize = parseInt(value)
|
||||
gl_context.uniform1f(u_basePointSize, particleSize)
|
||||
updateBuffer()
|
||||
draw()
|
||||
}
|
||||
|
||||
function setAlpha(value){
|
||||
alphaValue = parseInt(value) / 1000
|
||||
gl_context.uniform1f(u_Alpha, alphaValue)
|
||||
updateBuffer()
|
||||
draw()
|
||||
}
|
||||
|
||||
function setCanvasSize(value){
|
||||
value = parseInt(value)
|
||||
canvas.width = value
|
||||
canvas.height = value
|
||||
gl_context = getContext(canvas)
|
||||
gl_context = initContext(gl_context)
|
||||
gl_context.viewport(0, 0, canvas.width, canvas.height)
|
||||
updateBuffer()
|
||||
draw()
|
||||
}
|
||||
|
||||
function setBackground(value){
|
||||
bg_color = value;
|
||||
draw()
|
||||
}
|
||||
|
||||
function toggleCategoryAction(){
|
||||
updateBuffer()
|
||||
draw()
|
||||
}
|
||||
|
||||
function updateCategories(value){
|
||||
var request;
|
||||
try {
|
||||
request = new XMLHttpRequest();
|
||||
}catch(e){
|
||||
try{
|
||||
request = new ActiveXObject("Msxml2.XMLHTTP");
|
||||
}catch(e){
|
||||
try{
|
||||
request = new ActiveXObject("Microsoft.XMLHTTP");
|
||||
}catch(e){
|
||||
alert('Your browser is too old. Update your browser!')
|
||||
}
|
||||
}
|
||||
}
|
||||
request.onreadystatechange = function(){
|
||||
if (request.readyState == 4){
|
||||
response = request.responseText
|
||||
if(response == 'Password not correct'){document.body.innerHTML = "<h1>Wrong password. Refresh page an try again</h1>"}
|
||||
response = response.split('&&');
|
||||
typesControlPanel.innerHTML = response[0]
|
||||
toggleRadio.checked = true;
|
||||
reponse_colors = response[1].split(',');
|
||||
reponse_indices = response[2].split(';');
|
||||
category_type_colors = []
|
||||
type_indices = [];
|
||||
reponse_colors.forEach(function(val){
|
||||
category_type_colors.push(parseFloat(val));
|
||||
})
|
||||
reponse_indices.forEach(function(indices){
|
||||
try{
|
||||
indices = indices.split('->');
|
||||
var indices_name = indices[0],
|
||||
indices_values = indices[1].split(',');
|
||||
indices_array = [];
|
||||
indices_values.forEach(function(val){
|
||||
indices_array.push(parseInt(val))
|
||||
})
|
||||
type_indices[indices_name] = indices_array;
|
||||
}catch(e){}
|
||||
})
|
||||
toggleCategoryAction()
|
||||
}
|
||||
}
|
||||
queryString = "?category=" + value;
|
||||
queryString = queryString + "&mot_de_pass=" + password;
|
||||
request.open("GET", "fetch_category.php" + queryString, true)
|
||||
request.send(null)
|
||||
}
|
||||
|
||||
function getGeneExpression(caller){
|
||||
value = caller.value;
|
||||
caller_id = caller.id
|
||||
if (caller.id == 'geneSymbolSelector'){
|
||||
genelist_input.value = value
|
||||
}else{
|
||||
geneSymbolSelector.value = value
|
||||
}
|
||||
gene_expression = []
|
||||
try {
|
||||
request = new XMLHttpRequest();
|
||||
}catch(e){
|
||||
try{
|
||||
request = new ActiveXObject("Msxml2.XMLHTTP");
|
||||
}catch(e){
|
||||
try{
|
||||
request = new ActiveXObject("Microsoft.XMLHTTP");
|
||||
}catch(e){
|
||||
alert('Your browser is too old. Update your browser!')
|
||||
}
|
||||
}
|
||||
}
|
||||
request.onreadystatechange = function(){
|
||||
if (request.readyState == 4){
|
||||
response = request.responseText.split(',');
|
||||
gene_expression_scale = parseFloat(response[0]);
|
||||
var r = response.shift();
|
||||
response.forEach(function(val){
|
||||
gene_expression.push(parseFloat(val))
|
||||
})
|
||||
if(colour_by == 'gene_expression'){
|
||||
gl_context = getContext(canvas),
|
||||
gl_context = initContext(gl_context);
|
||||
toggleCategoryAction()
|
||||
if(!isNaN(gene_expression_scale)){
|
||||
expression_scale.innerHTML = "<canvas id ='scale_canvas' width = 200 height = 30></canvas><i>" + genelist_input.value + '</i>'
|
||||
var scale_canvas = document.getElementById('scale_canvas'),
|
||||
scale_context = scale_canvas.getContext('2d');
|
||||
scale_gradient = scale_context.createLinearGradient(0, 0, 200, 0);
|
||||
scale_gradient.addColorStop(0, 'blue');
|
||||
scale_gradient.addColorStop(0.5, 'green');
|
||||
scale_gradient.addColorStop(1, 'red');
|
||||
scale_context.fillStyle = scale_gradient;
|
||||
scale_context.fillRect(0, 20, scale_canvas.width, scale_canvas.height)
|
||||
scale_context.fillStyle = 'black'
|
||||
scale_context.fillText('0', 10, 10)
|
||||
scale_context.fillText(parseInt(10 * gene_expression_scale) / 10, 180, 10)
|
||||
}else{expression_scale.innerHTML = ""}
|
||||
if (geneFamilySelector.value != 'All'){
|
||||
if(gene_families[geneFamilySelector.value].indexOf(genelist_input.value) == -1){
|
||||
expression_scale.innerHTML = 'Gene entered is not part of selected gene family!'
|
||||
}
|
||||
}
|
||||
if (gene_list.indexOf(genelist_input.value) == -1){
|
||||
expression_scale.innerHTML = 'Gene name mistyped or does not exist!'
|
||||
}
|
||||
if (genelist_input.value == ''){
|
||||
expression_scale.innerHTML = "Choose a gene"
|
||||
}
|
||||
geneSymbolSelector_datalist.value = genelist_input.value
|
||||
}
|
||||
}
|
||||
}
|
||||
value = value.replace('/', "___")
|
||||
queryString = "?gene_name=" + value;
|
||||
request.open("GET", "fetch_gene_expression.php" + queryString, true)
|
||||
request.send(null)
|
||||
}
|
||||
|
||||
function setColourBy(val){
|
||||
colour_by = val;
|
||||
PaintFeatureScale = 1
|
||||
if (colour_by == "cell_type"){
|
||||
PaintFeatureScale = 0
|
||||
}
|
||||
if(colour_by == "gene_expression"){
|
||||
getGeneExpression(genelist_input)
|
||||
}else{
|
||||
gl_context = getContext(canvas),
|
||||
gl_context = initContext(gl_context);
|
||||
toggleCategoryAction()
|
||||
expression_scale.innerHTML = '';
|
||||
}
|
||||
}
|
||||
|
||||
function getCoordinates(value){
|
||||
dr_coordinates = []
|
||||
try {
|
||||
request = new XMLHttpRequest();
|
||||
}catch(e){
|
||||
try{
|
||||
request = new ActiveXObject("Msxml2.XMLHTTP");
|
||||
}catch(e){
|
||||
try{
|
||||
request = new ActiveXObject("Microsoft.XMLHTTP");
|
||||
}catch(e){
|
||||
alert('Your browser is too old. Update your browser!')
|
||||
}
|
||||
}
|
||||
}
|
||||
request.onreadystatechange = function(){
|
||||
if (request.readyState == 4){
|
||||
response = request.responseText.split(",")
|
||||
response.forEach(function(val){dr_coordinates.push(parseFloat(val))})
|
||||
if(canvas_init){
|
||||
updateBuffer()
|
||||
draw()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
queryString = "?dr_name=" + value;
|
||||
request.open("GET", "fetch_dr_coordinates.php" + queryString, true)
|
||||
request.send(null)
|
||||
}
|
||||
|
||||
function selectFamily(value){
|
||||
geneSymbolSelector_innerHTML = "<select onchange = 'getGeneExpression(this)' id ='geneSymbolSelector'>"
|
||||
if (value == 'All'){
|
||||
gene_list.forEach(function(gene_name, i){
|
||||
geneSymbolSelector_innerHTML = geneSymbolSelector_innerHTML + "<option value = '" + gene_name + "'>" + gene_name + "</option>"
|
||||
})
|
||||
}else{
|
||||
family_genes = gene_families[value]
|
||||
family_genes.forEach(function(gene_name, i){
|
||||
geneSymbolSelector_innerHTML = geneSymbolSelector_innerHTML + "<option value = '" + gene_name + "'>" + gene_name + "</option>"
|
||||
})
|
||||
}
|
||||
geneSymbolSelector_innerHTML = geneSymbolSelector_innerHTML + '</select>'
|
||||
geneSymbolSelector.innerHTML = geneSymbolSelector_innerHTML
|
||||
if (canvas_init){getGeneExpression(genelist_input)}
|
||||
}
|
||||
|
||||
var category_type_colors = [],
|
||||
type_indices = [],
|
||||
gene_expression = [],
|
||||
dr_coordinates = [],
|
||||
categorySelectMenu = document.getElementById('categorySelectMenu'),
|
||||
genelist_input = document.getElementById('genelist_input'),
|
||||
expression_scale = document.getElementById('expression_scale'),
|
||||
canvas = document.getElementById('canvas'),
|
||||
typesControlPanel = document.getElementById('typesControlPanel'),
|
||||
toggleRadio = document.getElementById('toggleRadio'),
|
||||
geneFamilySelector = document.getElementById('geneFamilySelector'),
|
||||
geneSymbolSelector = document.getElementById('geneSymbolSelector'),
|
||||
particleSize = 5,
|
||||
alphaValue = 1.0,
|
||||
bg_color = "white",
|
||||
n = 0,
|
||||
particleSize = 2,
|
||||
PaintFeatureScale = 0,
|
||||
currentMaxExpression = 0,
|
||||
buffer_data_array = null,
|
||||
colour_by = "cell_types",
|
||||
gene_expression_scale = 0,
|
||||
canvas_init = false;
|
||||
|
||||
// population gene families
|
||||
geneFamilySelector_innerHTML = "<option value = 'All'>All</option>"
|
||||
for(var gene_family_name in gene_families){
|
||||
geneFamilySelector_innerHTML = geneFamilySelector_innerHTML + "<option value = '" + gene_family_name + "'>" + gene_family_name + "</option>"
|
||||
}
|
||||
geneFamilySelector.innerHTML = geneFamilySelector_innerHTML
|
||||
|
||||
selectFamily('All')
|
||||
|
||||
getCoordinates(first_dr)
|
||||
updateCategories(categorySelectMenu.value)
|
||||
updateBuffer()
|
||||
|
||||
// create the renderer
|
||||
var gl_context = getContext(canvas),
|
||||
gl_context = initContext(gl_context);
|
||||
|
||||
draw()
|
||||
|
||||
canvas_init = true;
|
||||
|
||||
// safari does not support datalist
|
||||
// see at https://www.w3schools.com/tags/tryit.asp?filename=tryhtml5_datalist
|
||||
|
||||
var curTxt=document.createElement('div');
|
||||
curTxt.id="cursorText";
|
||||
document.body.appendChild(curTxt);
|
||||
canvas.addEventListener('mousemove', function(event){
|
||||
var canvasRect = canvas.getBoundingClientRect();
|
||||
var selectedIndex = false;
|
||||
Xc = 2*(event.clientX - canvasRect.x) / canvas.width - 1;
|
||||
Yc = -2*(event.clientY - canvasRect.y) / canvas.height + 1;
|
||||
for(var k=0; k<dr_coordinates.length/2;k++){
|
||||
dd = Math.abs(Xc - dr_coordinates[2*k]) + Math.abs(Yc - dr_coordinates[2*k + 1])
|
||||
if (dd < .003){
|
||||
selectedIndex = k
|
||||
break;
|
||||
}
|
||||
}
|
||||
var selectedCellType = ""
|
||||
for (var xy_cell_type in type_indices){
|
||||
if (type_indices[xy_cell_type].includes(selectedIndex)){
|
||||
selectedCellType = xy_cell_type
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
curTxt.innerHTML = selectedCellType
|
||||
curTxt.style.left = event.pageX + 5 + "px"
|
||||
curTxt.style.top = event.pageY - curTxt.offsetHeight + "px"
|
||||
})
|
||||
|
||||
</script>
|
||||
<div style="float: clear;""><hr><span style="font-size:0.8em;">This data portal was created using the web_portal tool (<a href="https://github.com/DoruMP/Fast-data-portals-for-scRNAseq-data">github link</a>) developed by Dorin-Mirel Popescu</span><hr></div>
|
||||
</body>
|
||||
</html>
|
||||
37
pipelines/90_web_portal/templates_password_protection/fetch_category.php
Executable file
37
pipelines/90_web_portal/templates_password_protection/fetch_category.php
Executable file
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
$mot_de_pass = $_GET['mot_de_pass'];
|
||||
$password = "b3mZ5GVYeRZEvk8ctsEk";
|
||||
if ($mot_de_pass != $password){
|
||||
exit('Password not correct');
|
||||
}
|
||||
|
||||
$category_name = $_GET["category"];
|
||||
$color_key_file = $category_name . "_color_key.csv";
|
||||
$color_key_file = "./categories/" . $color_key_file;
|
||||
$color_key_file = fopen($color_key_file, "r");
|
||||
$line = fgets($color_key_file );
|
||||
$data_string = "";
|
||||
while (($line = fgets($color_key_file)) !== false){
|
||||
$col_key = explode(",", $line);
|
||||
$cell_name = $col_key[0];
|
||||
$cell_col = $col_key[1];
|
||||
$button_html = str_replace('cell_name', str_replace('"', "", $cell_name), "<div style='background-color: cell_color;'><input type = 'checkbox' onchange='toggleCategoryAction()' name = 'cellTypeBtn' id='cell_name' checked /><label for = 'cell_name'> cell_name</label></div>");
|
||||
$button_html = str_replace('cell_color', str_replace('"', "", $cell_col), $button_html);
|
||||
$data_string = $data_string . $button_html;
|
||||
}
|
||||
fclose($color_key_file);
|
||||
|
||||
$categories_colors_file = "./categories/" . $category_name . "_colors";
|
||||
$categories_colors_file = fopen($categories_colors_file, "r");
|
||||
$categories_colors = fgets($categories_colors_file);
|
||||
fclose($categories_colors_file);
|
||||
$data_string = $data_string . "&&" . $categories_colors;
|
||||
|
||||
$categories_indices_file = "./categories/" . $category_name . "_indices";
|
||||
$categories_indices_file = fopen($categories_indices_file, "r");
|
||||
$categories_indices = fgets($categories_indices_file);
|
||||
fclose($categories_indices_file);
|
||||
$data_string = $data_string . "&&" . $categories_indices;
|
||||
|
||||
echo $data_string;
|
||||
?>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
$dr_fname = "./dr/" . $_GET["dr_name"] . "_coordinates";
|
||||
$dr_file = fopen($dr_fname, 'r');
|
||||
$dr_array = fgets($dr_file);
|
||||
fclose($dr_file);
|
||||
echo $dr_array;
|
||||
?>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
$gene_name = $_GET["gene_name"];
|
||||
$gene_expression_file = './genes/' . $gene_name;
|
||||
$gene_expression_file = fopen($gene_expression_file, 'r');
|
||||
$gene_expression = fgets($gene_expression_file);
|
||||
echo $gene_expression;
|
||||
?>
|
||||
12
pipelines/90_web_portal/templates_password_protection/generate_password.py
Executable file
12
pipelines/90_web_portal/templates_password_protection/generate_password.py
Executable file
|
|
@ -0,0 +1,12 @@
|
|||
f = open("fetch_category.php", "r")
|
||||
content = f.readlines()
|
||||
f.close()
|
||||
import string
|
||||
import random
|
||||
material = string.ascii_lowercase+string.ascii_uppercase+"123456789"
|
||||
pswd = "".join([random.choice(material) for k in range(20)])
|
||||
with open("password.txt", "w") as pswd_file: pswd_file.write(pswd);
|
||||
pswd = '\t$password = "{pswd}";\n'.format(pswd = pswd)
|
||||
content[2] = pswd
|
||||
content = "".join(content)
|
||||
with open("fetch_category.php", "w") as new_fetch:new_fetch.write(content);
|
||||
752
pipelines/90_web_portal/templates_password_protection/index.php
Executable file
752
pipelines/90_web_portal/templates_password_protection/index.php
Executable file
|
|
@ -0,0 +1,752 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Gene expression web portal</title>
|
||||
<meta name="description" content="Gene expression web portal for single cell RNA sequencing data made for the Human Cell Atlas at Newcastle University">
|
||||
<meta name="author" content="Dorin-Mirel Popescu">
|
||||
<style>
|
||||
body {
|
||||
font-family: Avenir, Arial, sans-serif;
|
||||
}
|
||||
#div_left {
|
||||
float: left;
|
||||
}
|
||||
|
||||
#canvasdiv {
|
||||
overflow-x: scroll;
|
||||
overflow-y: scroll;
|
||||
max-height: 90vh;
|
||||
}
|
||||
#typesControlPanel {
|
||||
height: 25em;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
#cursorText{
|
||||
position:absolute;
|
||||
background-color: black;
|
||||
color : white;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<?php
|
||||
$password = 'cucurucu';
|
||||
|
||||
echo "<script type = 'text/javascript'>";
|
||||
echo "var password = prompt('Introduce password:')";
|
||||
echo "</script>";
|
||||
?>
|
||||
|
||||
<div id = "div_left">
|
||||
<form>
|
||||
<fieldset>
|
||||
<legend><b>Visualisation options</b></legend>
|
||||
<label for = 'particleSizeBar'>Particle size: </label>
|
||||
<input type='range' name = 'particleSizeBar' min = .3 max = 7 step=0.1 oninput='setParticleSize(value)' value = 2 /><br/>
|
||||
|
||||
<label for = 'alphaInput'>Transparency: </label>
|
||||
<input type='range' name = 'alphaInput' min = 0 max = 1000 oninput='setAlpha(value)' value = 1000 /><br/>
|
||||
|
||||
<label for = 'canvasSizeInput'>Canvas size: </label>
|
||||
<input type='range' name = 'canvasSizeInput' min = 200 max = 2000 oninput='setCanvasSize(value)' value = 500 /><br/>
|
||||
</fieldset>
|
||||
</form>
|
||||
<form>
|
||||
<fieldset>
|
||||
<legend><b>Cell types</b></legend>
|
||||
<div>
|
||||
<div>
|
||||
Select category: <select id='categorySelectMenu' onchange = 'updateCategories(value)'>
|
||||
<?php
|
||||
$categories_file = fopen("./categories/categories_key", "r");
|
||||
$categories_content = fgets($categories_file);
|
||||
fclose($categories_file);
|
||||
$categories = explode(";", $categories_content);
|
||||
foreach($categories as $category){
|
||||
$category_fields = explode("->", $category);
|
||||
$category_name = $category_fields[0];
|
||||
$category_value = $category_fields[1];
|
||||
echo "<option value='" . $category_value . "'>" . $category_name . "</option>";
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<label for='toggleRadio'><input type='checkbox' name = 'toggleRadio' id='toggleRadio' onchange='toggleAllTypes()' checked />Show all</label>
|
||||
<div id='typesControlPanel'>
|
||||
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id = "div_right">
|
||||
<div>
|
||||
<b>Colour by:</b>
|
||||
<label for='colourType_t'><input type='radio' name='colourType' id='colourType_t' onchange='setColourBy(value)' value='cell_type' checked />Cell type</label>
|
||||
<label for='colourType_g'><input type='radio' name='colourType' id='colourType_g' onchange='setColourBy(value)' value='gene_expression' />Gene expression</label>
|
||||
</div>
|
||||
<table id = "geneSelectorTable">
|
||||
<tr>
|
||||
<td>
|
||||
<label for='geneFamilySelector'>Gene family:</label>
|
||||
</td>
|
||||
<td>
|
||||
<select name='geneFamilySelector' id='geneFamilySelector' onchange='selectFamily(value)'>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for='geneSymbolSelector'>Gene symbol:</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type = 'text' id='genelist_input' name = 'geneSymbolSelector_datalist' list='geneSymbolSelector_datalist' onchange='getGeneExpression(this)'>
|
||||
<datalist id = 'geneSymbolSelector_datalist'>
|
||||
<select onchange = 'getGeneExpression(this)' id ='geneSymbolSelector'></select>
|
||||
</datalist>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<label for = 'bgColorRadio_white'><input id = 'bgColorRadio_white' name = "bgColorRadio" type = "radio" value = 'white' onchange='setBackground(value)' checked/>White background </label>
|
||||
<label for = 'bgColorRadio_dark'><input id = 'bgColorRadio_dark' name = "bgColorRadio" type = "radio" value = 'dark' onchange='setBackground(value)' />Dark background </label>
|
||||
<br/><span id='expression_scale'></span>
|
||||
<div>
|
||||
Choose coordinates: <select onchange = 'getCoordinates(value)'>
|
||||
<?php
|
||||
$dr_file = fopen("./dr/dr_key", "r");
|
||||
$dr_content = fgets($dr_file);
|
||||
fclose($dr_file);
|
||||
$dr_cats = explode(";", $dr_content);
|
||||
foreach($dr_cats as $dr_cat){
|
||||
echo 1;
|
||||
$dr_fields = explode("->", $dr_cat);
|
||||
$dr_name = $dr_fields[0];
|
||||
echo "<option value='" . $dr_name . "'>" . $dr_name . "</option>";
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
<div id='canvasdiv'><canvas id='canvas' width=500 height=500></canvas></div>
|
||||
</div>
|
||||
|
||||
<script id='vertex-shader' type='x-shader/x-fragment'>
|
||||
attribute vec4 a_Position;
|
||||
attribute vec3 a_Color;
|
||||
uniform float u_basePointSize;
|
||||
uniform float u_Alpha;
|
||||
uniform int u_PaintFeatureScale;
|
||||
varying vec4 v_Color;
|
||||
void main() {
|
||||
gl_Position = a_Position;
|
||||
gl_PointSize = u_basePointSize;
|
||||
if (u_PaintFeatureScale == 0){
|
||||
v_Color = vec4(a_Color, u_Alpha);
|
||||
}
|
||||
else{
|
||||
float r = 0.0;
|
||||
float g = 0.0;
|
||||
float b = 0.0;
|
||||
r = max(0.0, 2.0 * a_Color.r - 1.0);
|
||||
b = max(0.0, 2.0 * (1.0 - a_Color.r) - 1.0);
|
||||
g = 1.0 - 2.0 * abs(a_Color.r - 0.5);
|
||||
v_Color = vec4(r, g, b, u_Alpha);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script id ='fragment-shader' type='x-shader/x-fragment'>
|
||||
precision mediump float;
|
||||
varying vec4 v_Color;
|
||||
void main() {
|
||||
float r = 0.0;
|
||||
vec2 cxy = 2.0 * gl_PointCoord - 1.0;
|
||||
r = dot(cxy, cxy);
|
||||
if (r > 1.0){
|
||||
discard;
|
||||
}
|
||||
gl_FragColor = v_Color;
|
||||
}
|
||||
</script>
|
||||
|
||||
<?php
|
||||
echo "<script type = 'text/javascript'>";
|
||||
$gene_families_file = fopen("./genes/gene_lists", "r");
|
||||
$gene_families_content = fgets($gene_families_file);
|
||||
fclose($gene_families_file);
|
||||
echo $gene_families_content;
|
||||
|
||||
$dr_file = fopen("./dr/dr_key", "r");
|
||||
$dr_content = fgets($dr_file);
|
||||
fclose($dr_file);
|
||||
$dr_cats = explode(";", $dr_content);
|
||||
$first_dr = explode('->', $dr_cats[0])[0];
|
||||
echo "first_dr = '" . $first_dr . "'";
|
||||
echo "</script>";
|
||||
?>
|
||||
|
||||
<script type = 'text/javascript'>
|
||||
|
||||
var Matrix4 = function(opt_src) {
|
||||
var i, s, d;
|
||||
if (opt_src && typeof opt_src === 'object' && opt_src.hasOwnProperty('elements')) {
|
||||
s = opt_src.elements;
|
||||
d = new Float32Array(16);
|
||||
for (i = 0; i < 16; ++i) {
|
||||
d[i] = s[i];
|
||||
}
|
||||
this.elements = d;
|
||||
} else {
|
||||
this.elements = new Float32Array([1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1]);
|
||||
}
|
||||
};
|
||||
|
||||
Matrix4.prototype.setTranslate = function(x, y, z) {
|
||||
var e = this.elements;
|
||||
e[0] = 1; e[4] = 0; e[8] = 0; e[12] = x;
|
||||
e[1] = 0; e[5] = 1; e[9] = 0; e[13] = y;
|
||||
e[2] = 0; e[6] = 0; e[10] = 1; e[14] = z;
|
||||
e[3] = 0; e[7] = 0; e[11] = 0; e[15] = 1;
|
||||
return this;
|
||||
};
|
||||
|
||||
Matrix4.prototype.setLookAt = function(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ) {
|
||||
var e, fx, fy, fz, rlf, sx, sy, sz, rls, ux, uy, uz;
|
||||
|
||||
fx = centerX - eyeX;
|
||||
fy = centerY - eyeY;
|
||||
fz = centerZ - eyeZ;
|
||||
|
||||
// Normalize f.
|
||||
rlf = 1 / Math.sqrt(fx*fx + fy*fy + fz*fz);
|
||||
fx *= rlf;
|
||||
fy *= rlf;
|
||||
fz *= rlf;
|
||||
|
||||
// Calculate cross product of f and up.
|
||||
sx = fy * upZ - fz * upY;
|
||||
sy = fz * upX - fx * upZ;
|
||||
sz = fx * upY - fy * upX;
|
||||
|
||||
// Normalize s.
|
||||
rls = 1 / Math.sqrt(sx*sx + sy*sy + sz*sz);
|
||||
sx *= rls;
|
||||
sy *= rls;
|
||||
sz *= rls;
|
||||
|
||||
// Calculate cross product of s and f.
|
||||
ux = sy * fz - sz * fy;
|
||||
uy = sz * fx - sx * fz;
|
||||
uz = sx * fy - sy * fx;
|
||||
|
||||
// Set to this.
|
||||
e = this.elements;
|
||||
e[0] = sx;
|
||||
e[1] = ux;
|
||||
e[2] = -fx;
|
||||
e[3] = 0;
|
||||
|
||||
e[4] = sy;
|
||||
e[5] = uy;
|
||||
e[6] = -fy;
|
||||
e[7] = 0;
|
||||
|
||||
e[8] = sz;
|
||||
e[9] = uz;
|
||||
e[10] = -fz;
|
||||
e[11] = 0;
|
||||
|
||||
e[12] = 0;
|
||||
e[13] = 0;
|
||||
e[14] = 0;
|
||||
e[15] = 1;
|
||||
|
||||
// Translate.
|
||||
return this.translate(-eyeX, -eyeY, -eyeZ);
|
||||
};
|
||||
|
||||
Matrix4.prototype.translate = function(x, y, z) {
|
||||
var e = this.elements;
|
||||
e[12] += e[0] * x + e[4] * y + e[8] * z;
|
||||
e[13] += e[1] * x + e[5] * y + e[9] * z;
|
||||
e[14] += e[2] * x + e[6] * y + e[10] * z;
|
||||
e[15] += e[3] * x + e[7] * y + e[11] * z;
|
||||
return this;
|
||||
};
|
||||
|
||||
Matrix4.prototype.setPerspective = function(fovy, aspect, near, far) {
|
||||
var e, rd, s, ct;
|
||||
|
||||
if (near === far || aspect === 0) {
|
||||
throw 'null frustum';
|
||||
}
|
||||
if (near <= 0) {
|
||||
throw 'near <= 0';
|
||||
}
|
||||
if (far <= 0) {
|
||||
throw 'far <= 0';
|
||||
}
|
||||
|
||||
fovy = Math.PI * fovy / 180 / 2;
|
||||
s = Math.sin(fovy);
|
||||
if (s === 0) {
|
||||
throw 'null frustum';
|
||||
}
|
||||
|
||||
rd = 1 / (far - near);
|
||||
ct = Math.cos(fovy) / s;
|
||||
|
||||
e = this.elements;
|
||||
|
||||
e[0] = ct / aspect;
|
||||
e[1] = 0;
|
||||
e[2] = 0;
|
||||
e[3] = 0;
|
||||
|
||||
e[4] = 0;
|
||||
e[5] = ct;
|
||||
e[6] = 0;
|
||||
e[7] = 0;
|
||||
|
||||
e[8] = 0;
|
||||
e[9] = 0;
|
||||
e[10] = -(far + near) * rd;
|
||||
e[11] = -1;
|
||||
|
||||
e[12] = 0;
|
||||
e[13] = 0;
|
||||
e[14] = -2 * near * far * rd;
|
||||
e[15] = 0;
|
||||
|
||||
return this;
|
||||
};
|
||||
</script>
|
||||
|
||||
<script type = 'text/javascript'>
|
||||
function initContext(gl){
|
||||
n = buffer_data_array.length / 5
|
||||
var vertexColourBuffer = gl.createBuffer()
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, vertexColourBuffer)
|
||||
|
||||
var FSIZE = buffer_data_array.BYTES_PER_ELEMENT;
|
||||
|
||||
var a_Position = gl.getAttribLocation(gl.program, 'a_Position')
|
||||
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 5, 0)
|
||||
gl.enableVertexAttribArray(a_Position)
|
||||
|
||||
var a_Color = gl.getAttribLocation(gl.program, 'a_Color')
|
||||
gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 5, 2 * FSIZE)
|
||||
gl.enableVertexAttribArray(a_Color)
|
||||
|
||||
u_basePointSize = gl.getUniformLocation(gl.program, 'u_basePointSize')
|
||||
gl.uniform1f(u_basePointSize, particleSize)
|
||||
|
||||
u_Alpha = gl.getUniformLocation(gl.program, "u_Alpha")
|
||||
gl.uniform1f(u_Alpha, alphaValue)
|
||||
|
||||
u_PaintFeatureScale = gl.getUniformLocation(gl.program, 'u_PaintFeatureScale')
|
||||
gl.uniform1i(u_PaintFeatureScale, PaintFeatureScale)
|
||||
|
||||
gl.clearColor(1, 1, 1, 1);
|
||||
if(bg_color == "dark"){
|
||||
gl.clearColor(0, 0, 0, 1)
|
||||
}
|
||||
|
||||
gl.disable(gl.DEPTH_TEST)
|
||||
gl.enable(gl.BLEND)
|
||||
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
|
||||
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
return gl
|
||||
}
|
||||
|
||||
function getContext(canvasWidget){
|
||||
var names = ['webgl', 'experimental-webgl', 'webkit-3d', 'moz-webgl'];
|
||||
for(var i=0; i<names.length; i++){
|
||||
try{
|
||||
var gl = canvasWidget.getContext(names[i])
|
||||
}catch(e){}
|
||||
if(gl){i=names.length}
|
||||
}
|
||||
|
||||
var vshader = shadersFromScriptElement(gl, 'vertex-shader', gl.VERTEX_SHADER),
|
||||
fshader = shadersFromScriptElement(gl, 'fragment-shader', gl.FRAGMENT_SHADER)
|
||||
program = gl.createProgram();
|
||||
gl.attachShader(program, vshader)
|
||||
gl.attachShader(program, fshader)
|
||||
gl.linkProgram(program)
|
||||
gl.useProgram(program)
|
||||
gl.program = program
|
||||
return gl
|
||||
}
|
||||
|
||||
function shadersFromScriptElement(gl, ID, type){
|
||||
shaderScript = document.getElementById(ID)
|
||||
var str = ''
|
||||
var k = shaderScript.firstChild;
|
||||
while(k){
|
||||
if (k.nodeType == 3){
|
||||
str += k.textContent;
|
||||
}
|
||||
k = k.nextSibling
|
||||
}
|
||||
var shader = gl.createShader(type)
|
||||
gl.shaderSource(shader, str)
|
||||
gl.compileShader(shader)
|
||||
return shader
|
||||
}
|
||||
|
||||
function toggleAllTypes(){
|
||||
for (i=0;i<typesControlPanel.childElementCount;i++){
|
||||
typesControlPanel.children[i].children[0].checked = toggleRadio.checked;
|
||||
}
|
||||
updateBuffer()
|
||||
draw()
|
||||
}
|
||||
|
||||
function updateBuffer(){
|
||||
var buffer_data = [];
|
||||
// first update indices to be used - for this read the category control panel radio buttons
|
||||
current_indices = []
|
||||
for(i=0;i<typesControlPanel.childElementCount;i++){
|
||||
if(typesControlPanel.children[i].children[0].checked){
|
||||
radio_type = typesControlPanel.children[i].children[0].id
|
||||
current_indices = current_indices.concat(type_indices[radio_type])
|
||||
}
|
||||
}
|
||||
// now just populate the buffer_data
|
||||
if(colour_by == 'gene_expression'){
|
||||
current_indices.forEach(function(index, i){
|
||||
buffer_data.push(dr_coordinates[2 * index])
|
||||
buffer_data.push(dr_coordinates[2 * index + 1])
|
||||
buffer_data.push(gene_expression[index])
|
||||
buffer_data.push(gene_expression[index])
|
||||
buffer_data.push(gene_expression[index])
|
||||
})
|
||||
}else{
|
||||
current_indices.forEach(function(index){
|
||||
buffer_data.push(dr_coordinates[2 * index])
|
||||
buffer_data.push(dr_coordinates[2 * index + 1])
|
||||
buffer_data.push(category_type_colors[3 * index])
|
||||
buffer_data.push(category_type_colors[3 * index + 1])
|
||||
buffer_data.push(category_type_colors[3 * index + 2])
|
||||
})
|
||||
}
|
||||
buffer_data_array = new Float32Array(buffer_data)
|
||||
n = buffer_data_array.length / 5
|
||||
}
|
||||
|
||||
function draw(){
|
||||
if(bg_color == "white"){
|
||||
gl_context.clearColor(1, 1, 1, 1)
|
||||
}else{
|
||||
gl_context.clearColor(0, 0, 0, 1)
|
||||
}
|
||||
gl_context.clear(gl_context.COLOR_BUFFER_BIT);
|
||||
if(n > 0){
|
||||
gl_context.bufferData(gl_context.ARRAY_BUFFER, buffer_data_array, gl_context.STATIC_DRAW)
|
||||
gl_context.drawArrays(gl_context.POINTS, 0, n)
|
||||
}
|
||||
}
|
||||
|
||||
function setParticleSize(value){
|
||||
particleSize = parseInt(value)
|
||||
gl_context.uniform1f(u_basePointSize, particleSize)
|
||||
updateBuffer()
|
||||
draw()
|
||||
}
|
||||
|
||||
function setAlpha(value){
|
||||
alphaValue = parseInt(value) / 1000
|
||||
gl_context.uniform1f(u_Alpha, alphaValue)
|
||||
updateBuffer()
|
||||
draw()
|
||||
}
|
||||
|
||||
function setCanvasSize(value){
|
||||
value = parseInt(value)
|
||||
canvas.width = value
|
||||
canvas.height = value
|
||||
gl_context = getContext(canvas)
|
||||
gl_context = initContext(gl_context)
|
||||
gl_context.viewport(0, 0, canvas.width, canvas.height)
|
||||
updateBuffer()
|
||||
draw()
|
||||
}
|
||||
|
||||
function setBackground(value){
|
||||
bg_color = value;
|
||||
draw()
|
||||
}
|
||||
|
||||
function toggleCategoryAction(){
|
||||
updateBuffer()
|
||||
draw()
|
||||
}
|
||||
|
||||
function updateCategories(value){
|
||||
var request;
|
||||
try {
|
||||
request = new XMLHttpRequest();
|
||||
}catch(e){
|
||||
try{
|
||||
request = new ActiveXObject("Msxml2.XMLHTTP");
|
||||
}catch(e){
|
||||
try{
|
||||
request = new ActiveXObject("Microsoft.XMLHTTP");
|
||||
}catch(e){
|
||||
alert('Your browser is too old. Update your browser!')
|
||||
}
|
||||
}
|
||||
}
|
||||
request.onreadystatechange = function(){
|
||||
if (request.readyState == 4){
|
||||
response = request.responseText
|
||||
if(response == 'Password not correct'){document.body.innerHTML = "<h1>Wrong password. Refresh page an try again</h1>"}
|
||||
response = response.split('&&');
|
||||
typesControlPanel.innerHTML = response[0]
|
||||
toggleRadio.checked = true;
|
||||
reponse_colors = response[1].split(',');
|
||||
reponse_indices = response[2].split(';');
|
||||
category_type_colors = []
|
||||
type_indices = [];
|
||||
reponse_colors.forEach(function(val){
|
||||
category_type_colors.push(parseFloat(val));
|
||||
})
|
||||
reponse_indices.forEach(function(indices){
|
||||
try{
|
||||
indices = indices.split('->');
|
||||
var indices_name = indices[0],
|
||||
indices_values = indices[1].split(',');
|
||||
indices_array = [];
|
||||
indices_values.forEach(function(val){
|
||||
indices_array.push(parseInt(val))
|
||||
})
|
||||
type_indices[indices_name] = indices_array;
|
||||
}catch(e){}
|
||||
})
|
||||
toggleCategoryAction()
|
||||
}
|
||||
}
|
||||
queryString = "?category=" + value;
|
||||
queryString = queryString + "&mot_de_pass=" + password;
|
||||
request.open("GET", "fetch_category.php" + queryString, true)
|
||||
request.send(null)
|
||||
}
|
||||
|
||||
function getGeneExpression(caller){
|
||||
value = caller.value;
|
||||
caller_id = caller.id
|
||||
if (caller.id == 'geneSymbolSelector'){
|
||||
genelist_input.value = value
|
||||
}else{
|
||||
geneSymbolSelector.value = value
|
||||
}
|
||||
gene_expression = []
|
||||
try {
|
||||
request = new XMLHttpRequest();
|
||||
}catch(e){
|
||||
try{
|
||||
request = new ActiveXObject("Msxml2.XMLHTTP");
|
||||
}catch(e){
|
||||
try{
|
||||
request = new ActiveXObject("Microsoft.XMLHTTP");
|
||||
}catch(e){
|
||||
alert('Your browser is too old. Update your browser!')
|
||||
}
|
||||
}
|
||||
}
|
||||
request.onreadystatechange = function(){
|
||||
if (request.readyState == 4){
|
||||
response = request.responseText.split(',');
|
||||
gene_expression_scale = parseFloat(response[0]);
|
||||
var r = response.shift();
|
||||
response.forEach(function(val){
|
||||
gene_expression.push(parseFloat(val))
|
||||
})
|
||||
if(colour_by == 'gene_expression'){
|
||||
gl_context = getContext(canvas),
|
||||
gl_context = initContext(gl_context);
|
||||
toggleCategoryAction()
|
||||
if(!isNaN(gene_expression_scale)){
|
||||
expression_scale.innerHTML = "<canvas id ='scale_canvas' width = 200 height = 30></canvas><i>" + genelist_input.value + '</i>'
|
||||
var scale_canvas = document.getElementById('scale_canvas'),
|
||||
scale_context = scale_canvas.getContext('2d');
|
||||
scale_gradient = scale_context.createLinearGradient(0, 0, 200, 0);
|
||||
scale_gradient.addColorStop(0, 'blue');
|
||||
scale_gradient.addColorStop(0.5, 'green');
|
||||
scale_gradient.addColorStop(1, 'red');
|
||||
scale_context.fillStyle = scale_gradient;
|
||||
scale_context.fillRect(0, 20, scale_canvas.width, scale_canvas.height)
|
||||
scale_context.fillStyle = 'black'
|
||||
scale_context.fillText('0', 10, 10)
|
||||
scale_context.fillText(parseInt(10 * gene_expression_scale) / 10, 180, 10)
|
||||
}else{expression_scale.innerHTML = ""}
|
||||
if (geneFamilySelector.value != 'All'){
|
||||
if(gene_families[geneFamilySelector.value].indexOf(genelist_input.value) == -1){
|
||||
expression_scale.innerHTML = 'Gene entered is not part of selected gene family!'
|
||||
}
|
||||
}
|
||||
if (gene_list.indexOf(genelist_input.value) == -1){
|
||||
expression_scale.innerHTML = 'Gene name mistyped or does not exist!'
|
||||
}
|
||||
if (genelist_input.value == ''){
|
||||
expression_scale.innerHTML = "Choose a gene"
|
||||
}
|
||||
geneSymbolSelector_datalist.value = genelist_input.value
|
||||
}
|
||||
}
|
||||
}
|
||||
value = value.replace('/', "___")
|
||||
queryString = "?gene_name=" + value;
|
||||
request.open("GET", "fetch_gene_expression.php" + queryString, true)
|
||||
request.send(null)
|
||||
}
|
||||
|
||||
function setColourBy(val){
|
||||
colour_by = val;
|
||||
PaintFeatureScale = 1
|
||||
if (colour_by == "cell_type"){
|
||||
PaintFeatureScale = 0
|
||||
}
|
||||
if(colour_by == "gene_expression"){
|
||||
getGeneExpression(genelist_input)
|
||||
}else{
|
||||
gl_context = getContext(canvas),
|
||||
gl_context = initContext(gl_context);
|
||||
toggleCategoryAction()
|
||||
expression_scale.innerHTML = '';
|
||||
}
|
||||
}
|
||||
|
||||
function getCoordinates(value){
|
||||
dr_coordinates = []
|
||||
try {
|
||||
request = new XMLHttpRequest();
|
||||
}catch(e){
|
||||
try{
|
||||
request = new ActiveXObject("Msxml2.XMLHTTP");
|
||||
}catch(e){
|
||||
try{
|
||||
request = new ActiveXObject("Microsoft.XMLHTTP");
|
||||
}catch(e){
|
||||
alert('Your browser is too old. Update your browser!')
|
||||
}
|
||||
}
|
||||
}
|
||||
request.onreadystatechange = function(){
|
||||
if (request.readyState == 4){
|
||||
response = request.responseText.split(",")
|
||||
response.forEach(function(val){dr_coordinates.push(parseFloat(val))})
|
||||
if(canvas_init){
|
||||
updateBuffer()
|
||||
draw()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
queryString = "?dr_name=" + value;
|
||||
request.open("GET", "fetch_dr_coordinates.php" + queryString, true)
|
||||
request.send(null)
|
||||
}
|
||||
|
||||
function selectFamily(value){
|
||||
geneSymbolSelector_innerHTML = "<select onchange = 'getGeneExpression(this)' id ='geneSymbolSelector'>"
|
||||
if (value == 'All'){
|
||||
gene_list.forEach(function(gene_name, i){
|
||||
geneSymbolSelector_innerHTML = geneSymbolSelector_innerHTML + "<option value = '" + gene_name + "'>" + gene_name + "</option>"
|
||||
})
|
||||
}else{
|
||||
family_genes = gene_families[value]
|
||||
family_genes.forEach(function(gene_name, i){
|
||||
geneSymbolSelector_innerHTML = geneSymbolSelector_innerHTML + "<option value = '" + gene_name + "'>" + gene_name + "</option>"
|
||||
})
|
||||
}
|
||||
geneSymbolSelector_innerHTML = geneSymbolSelector_innerHTML + '</select>'
|
||||
geneSymbolSelector.innerHTML = geneSymbolSelector_innerHTML
|
||||
if (canvas_init){getGeneExpression(genelist_input)}
|
||||
}
|
||||
|
||||
var category_type_colors = [],
|
||||
type_indices = [],
|
||||
gene_expression = [],
|
||||
dr_coordinates = [],
|
||||
categorySelectMenu = document.getElementById('categorySelectMenu'),
|
||||
genelist_input = document.getElementById('genelist_input'),
|
||||
expression_scale = document.getElementById('expression_scale'),
|
||||
canvas = document.getElementById('canvas'),
|
||||
typesControlPanel = document.getElementById('typesControlPanel'),
|
||||
toggleRadio = document.getElementById('toggleRadio'),
|
||||
geneFamilySelector = document.getElementById('geneFamilySelector'),
|
||||
geneSymbolSelector = document.getElementById('geneSymbolSelector'),
|
||||
particleSize = 5,
|
||||
alphaValue = 1.0,
|
||||
bg_color = "white",
|
||||
n = 0,
|
||||
particleSize = 2,
|
||||
PaintFeatureScale = 0,
|
||||
currentMaxExpression = 0,
|
||||
buffer_data_array = null,
|
||||
colour_by = "cell_types",
|
||||
gene_expression_scale = 0,
|
||||
canvas_init = false;
|
||||
|
||||
// population gene families
|
||||
geneFamilySelector_innerHTML = "<option value = 'All'>All</option>"
|
||||
for(var gene_family_name in gene_families){
|
||||
geneFamilySelector_innerHTML = geneFamilySelector_innerHTML + "<option value = '" + gene_family_name + "'>" + gene_family_name + "</option>"
|
||||
}
|
||||
geneFamilySelector.innerHTML = geneFamilySelector_innerHTML
|
||||
|
||||
selectFamily('All')
|
||||
|
||||
getCoordinates(first_dr)
|
||||
updateCategories(categorySelectMenu.value)
|
||||
updateBuffer()
|
||||
|
||||
// create the renderer
|
||||
var gl_context = getContext(canvas),
|
||||
gl_context = initContext(gl_context);
|
||||
|
||||
draw()
|
||||
|
||||
canvas_init = true;
|
||||
|
||||
var curTxt=document.createElement('div');
|
||||
curTxt.id="cursorText";
|
||||
document.body.appendChild(curTxt);
|
||||
canvas.addEventListener('mousemove', function(event){
|
||||
var canvasRect = canvas.getBoundingClientRect();
|
||||
var selectedIndex = false;
|
||||
Xc = 2*(event.clientX - canvasRect.x) / canvas.width - 1;
|
||||
Yc = -2*(event.clientY - canvasRect.y) / canvas.height + 1;
|
||||
for(var k=0; k<dr_coordinates.length/2;k++){
|
||||
dd = Math.abs(Xc - dr_coordinates[2*k]) + Math.abs(Yc - dr_coordinates[2*k + 1])
|
||||
if (dd < .003){
|
||||
selectedIndex = k
|
||||
break;
|
||||
}
|
||||
}
|
||||
var selectedCellType = ""
|
||||
for (var xy_cell_type in type_indices){
|
||||
if (type_indices[xy_cell_type].includes(selectedIndex)){
|
||||
selectedCellType = xy_cell_type
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
curTxt.innerHTML = selectedCellType
|
||||
curTxt.style.left = event.pageX + 5 + "px"
|
||||
curTxt.style.top = event.pageY - curTxt.offsetHeight + "px"
|
||||
})
|
||||
|
||||
// safari does not support datalist
|
||||
// see at https://www.w3schools.com/tags/tryit.asp?filename=tryhtml5_datalist
|
||||
|
||||
</script>
|
||||
<div style="float: clear;""><hr><span style="font-size:0.8em;">This data portal was created using the web_portal tool (<a href="https://github.com/DoruMP/Fast-data-portals-for-scRNAseq-data">github link</a>) developed by Dorin-Mirel Popescu</span><hr></div>
|
||||
</body>
|
||||
</html>
|
||||
1
pipelines/90_web_portal/templates_password_protection/password.txt
Executable file
1
pipelines/90_web_portal/templates_password_protection/password.txt
Executable file
|
|
@ -0,0 +1 @@
|
|||
b3mZ5GVYeRZEvk8ctsEk
|
||||
348
pipelines/90_web_portal/web_portal.R
Executable file
348
pipelines/90_web_portal/web_portal.R
Executable file
|
|
@ -0,0 +1,348 @@
|
|||
args = commandArgs(trailingOnly=T)
|
||||
|
||||
python.addr = 'python'
|
||||
|
||||
# load the required libraries
|
||||
library(Seurat)
|
||||
library(plyr)
|
||||
library(dplyr)
|
||||
library(RColorBrewer)
|
||||
library(methods)
|
||||
|
||||
options_file = args[1]
|
||||
|
||||
##########################################################################################
|
||||
##########################################################################################
|
||||
##########################################################################################
|
||||
# FUNCTIONS
|
||||
|
||||
# a function to convert hex colours to subunit rgb values - that are red by WebGL
|
||||
hex_to_floats= function(hex_str){
|
||||
red = round(strtoi(paste("0x", substr(x=hex_str, start=2, stop=3), sep = "")) / 255, digits=2)
|
||||
green = round(strtoi(paste("0x", substr(x=hex_str, start=4, stop=5), sep = "")) / 255, digits=2)
|
||||
blue = round(strtoi(paste("0x", substr(x=hex_str, start=6, stop=7), sep = "")) / 255, digits=2)
|
||||
paste(c(red, green, blue), collapse = ",")
|
||||
}
|
||||
|
||||
##########################################################################################
|
||||
##########################################################################################
|
||||
##########################################################################################
|
||||
|
||||
# extract options
|
||||
options_fobj = file(options_file)
|
||||
options_val = readLines(options_fobj)
|
||||
close(options_fobj)
|
||||
# make file_name variable
|
||||
file_name = gsub(" ", "", unlist(strsplit(options_val[1], ':'))[2])
|
||||
# make output_folder variable
|
||||
output_folder = gsub(" ", "", unlist(strsplit(options_val[2], ':'))[2])
|
||||
# make dr coordinates pointers
|
||||
dr_coordinates = gsub(" ", "", unlist(strsplit(options_val[3], ':'))[2])
|
||||
dr_coordinates = unlist(lapply(unlist(strsplit(dr_coordinates, ';')), strsplit, "->"))
|
||||
dr_names = dr_coordinates[seq(1, length(dr_coordinates), 2)]
|
||||
dr_slots = dr_coordinates[seq(2, length(dr_coordinates), 2)]
|
||||
# make categories pointers
|
||||
categories = unlist(lapply(unlist(strsplit(options_val[4], ';')), strsplit, '->'))
|
||||
categories_names = categories[seq(1, length(categories), 3)]
|
||||
categories_slot = categories[seq(2, length(categories), 3)]
|
||||
categories_cols = categories[seq(3, length(categories), 3)]
|
||||
|
||||
# make the output folder and the other folders
|
||||
dir.create(output_folder)
|
||||
gene_output_folder = file.path(output_folder, "genes")
|
||||
categories_output_folder = file.path(output_folder, "categories")
|
||||
dr_output_folder = file.path(output_folder, "dr")
|
||||
dir.create(gene_output_folder)
|
||||
dir.create(categories_output_folder)
|
||||
dir.create(dr_output_folder)
|
||||
|
||||
# check file_mame extension
|
||||
# if is RDS assume this is a Seurat object and go on
|
||||
# if is h5ad then assume it is a scanpy object and get help form Python to extract the required data
|
||||
file_name_extension = unlist(strsplit(file_name, "\\."))
|
||||
file_name_extension = file_name_extension[length(file_name_extension)]
|
||||
if (file_name_extension == 'h5ad'){ # handle a scanpy object
|
||||
print('Handling a Scanpy object')
|
||||
command = sprintf("%s scanpy_to_seurat.py %s", python.addr, options_file)
|
||||
system(command, wait = T)
|
||||
# read expression matrix - should include nUMI and nGene
|
||||
expression_matrix = readMM(file.path(output_folder, 'expression.mtx'))
|
||||
# read the gene names
|
||||
gene_name_fobj = file(file.path(output_folder, 'gene_names.txt'))
|
||||
gene_names = readLines(gene_name_fobj)
|
||||
close(gene_name_fobj)
|
||||
# add gene names as colnames to gene_expression
|
||||
colnames(expression_matrix) = gene_names
|
||||
# transpose the expression matrix
|
||||
expression_matrix = t(expression_matrix)
|
||||
# read dr data
|
||||
dr_matrix = read.csv(file.path(output_folder, 'dr.csv'), header = F)
|
||||
# read the categories
|
||||
categories_matrix = read.csv(file.path(output_folder, 'categories.csv'), row.names = 1, check.names=FALSE)
|
||||
# remove the files
|
||||
file.remove(file.path(output_folder, 'expression.mtx'))
|
||||
file.remove(file.path(output_folder, 'gene_names.txt'))
|
||||
file.remove(file.path(output_folder, 'dr.csv'))
|
||||
file.remove(file.path(output_folder, 'categories.csv'))
|
||||
# extract nUMI and nGENE
|
||||
nUMI = expression_matrix['nUMI', ]
|
||||
nGene = expression_matrix['nGene', ]
|
||||
# remove nUMI and nGene rows from the expression matrix
|
||||
indices = which(rownames(expression_matrix) %in% c('nUMI', 'nGene'))
|
||||
expression_matrix = expression_matrix[-c(indices), ]
|
||||
}else{ # handle a seurat object
|
||||
print('Handling a Seurat object')
|
||||
print('Loading data ...')
|
||||
seurat.obj = readRDS(file_name)
|
||||
print('Data loaded')
|
||||
# extract expression_matrix
|
||||
expression_matrix = seurat.obj@data
|
||||
# make the dr matrix
|
||||
for(i in 1:length(dr_slots)){
|
||||
dr_slot = dr_slots[i]
|
||||
command = paste("dr_slot_data = seurat.obj@dr$", dr_slot, "@cell.embeddings", sep = "")
|
||||
eval(parse(text = command))
|
||||
if (i == 1){
|
||||
dr_matrix = dr_slot_data
|
||||
}else{
|
||||
dr_matrix = cbind(dr_matrix, dr_slot_data)
|
||||
}
|
||||
}
|
||||
# make the categories_matrix
|
||||
for (i in 1:length(categories_slot)){
|
||||
cat_slot = categories_slot[i]
|
||||
command = paste("category_data = seurat.obj@meta.data$", cat_slot, sep = "")
|
||||
eval(parse(text = command))
|
||||
category_data = as.vector(category_data)
|
||||
if(categories_cols[i] == "null"){
|
||||
# randomly generate the colors
|
||||
unique_cats = sort(as.vector(unique(category_data)))
|
||||
cat_colours = sample(colorRampPalette(brewer.pal(12, "Paired"))(length(unique_cats)))
|
||||
}else{
|
||||
type.to.colour = read.csv(categories_cols[i])
|
||||
unique_cats = as.vector(type.to.colour$CellTypes)
|
||||
cat_colours = as.vector(type.to.colour$Colours)
|
||||
}
|
||||
cat_colours = mapvalues(x=category_data, from=unique_cats, to=cat_colours)
|
||||
cat_data = data.frame(Labels = category_data, Colours = cat_colours)
|
||||
colnames(cat_data) = c(categories_names[i], paste(categories_names[i], "_Colour", sep = ""))
|
||||
if ( i == 1 ){
|
||||
categories_matrix = cat_data
|
||||
}else{
|
||||
categories_matrix = cbind(categories_matrix, cat_data)
|
||||
}
|
||||
}
|
||||
# extract nUMI and nGENE
|
||||
nGene = seurat.obj@meta.data$nGene
|
||||
nUMI = seurat.obj@meta.data$nUMI
|
||||
}
|
||||
|
||||
# save color key for each category
|
||||
# categories_names
|
||||
# categories_slot
|
||||
# categories_cols
|
||||
for (i in 1:length(categories_names)){
|
||||
category_name = categories_names[i]
|
||||
category_col = paste(category_name, 'Colour', sep = '_')
|
||||
category_slot = categories_slot[i]
|
||||
category_tags = as.vector(categories_matrix[, category_name])
|
||||
category_cols = as.vector(categories_matrix[, category_col])
|
||||
category_unique = unique(category_tags)
|
||||
cols_unique = mapvalues(x=category_unique, from = category_tags, to = category_cols, warn_missing=F)
|
||||
# caol keys
|
||||
color.key = data.frame(Categories = category_unique, Colours = cols_unique)
|
||||
color_key_fname = paste(category_slot, "_color_key.csv", sep = '')
|
||||
write.csv(color.key, file.path(categories_output_folder, color_key_fname), row.names=FALSE)
|
||||
# color floats webgl-readable
|
||||
float_colors = unlist(lapply(category_cols, hex_to_floats))
|
||||
float_colors = paste(float_colors, collapse = ",")
|
||||
float_colors_file = paste(category_slot, 'colors', sep = '_')
|
||||
float_colors_file = file(file.path(categories_output_folder, float_colors_file), 'w')
|
||||
writeLines(float_colors, float_colors_file)
|
||||
close(float_colors_file)
|
||||
# save category indices
|
||||
cell.types.indices = ""
|
||||
for(i in 1:length(category_unique)){
|
||||
cell.label = category_unique[i]
|
||||
cell.label.indices = which(category_tags %in% c(cell.label)) - 1
|
||||
cell.label.indices = paste(cell.label.indices, collapse = ",")
|
||||
assignment = paste(cell.label, cell.label.indices, sep = "->")
|
||||
cell.types.indices = c(cell.types.indices, assignment)
|
||||
}
|
||||
cell.types.indices = paste(cell.types.indices, collapse = ";")
|
||||
type_fname = paste(category_slot, 'indices', sep = '_')
|
||||
cell.types.indices.file = file.path(categories_output_folder, type_fname)
|
||||
cell.types.indices.file = file(cell.types.indices.file, "w")
|
||||
writeLines(cell.types.indices, cell.types.indices.file)
|
||||
close(cell.types.indices.file)
|
||||
}
|
||||
|
||||
# save categories types key
|
||||
# categories_names
|
||||
# categories_slot
|
||||
categories.menu.content = ""
|
||||
for(i in 1:length(categories_names)){
|
||||
category_name = categories_names[i]
|
||||
category_slot = categories_slot[i]
|
||||
category_arrow = paste(category_name, "->", category_slot, ";", sep = '')
|
||||
categories.menu.content = paste(categories.menu.content, category_arrow, sep = "")
|
||||
}
|
||||
categories.menu.file = file.path(categories_output_folder, "categories_key")
|
||||
categories.menu.file = file(categories.menu.file, "w")
|
||||
writeLines(categories.menu.content, categories.menu.file)
|
||||
close(categories.menu.file)
|
||||
|
||||
# save key to dr
|
||||
#dr_names
|
||||
#dr_slots
|
||||
dr.menu.content = ""
|
||||
for(i in 1:length(dr_names)){
|
||||
dr_name = dr_names[i]
|
||||
dr_slot = dr_slots[i]
|
||||
dr_arrow = paste(dr_name, "->", dr_slot, ";", sep = "")
|
||||
dr.menu.content = paste(dr.menu.content, dr_arrow, sep = "")
|
||||
}
|
||||
dr.menu.file = file.path(dr_output_folder, "dr_key")
|
||||
dr.menu.file = file(dr.menu.file, "w")
|
||||
writeLines(dr.menu.content, dr.menu.file)
|
||||
close(dr.menu.file)
|
||||
|
||||
# save dr coordinates
|
||||
#dr_names
|
||||
#dr_slots
|
||||
#dr_matrix
|
||||
for(i in 0:(length(dr_names) - 1)){
|
||||
dr_name = dr_names[i + 1]
|
||||
start_ = 2*i + 1
|
||||
end_ = 2*i + 2
|
||||
coordinates = dr_matrix[, c(start_, end_)]
|
||||
coordinates.x.q = mean(quantile(coordinates[, 1], c(.01, .99)))
|
||||
coordinates.y.q = mean(quantile(coordinates[, 2], c(.01, .99)))
|
||||
coordinates[, 1] = coordinates[, 1] - coordinates.x.q
|
||||
coordinates[, 2] = coordinates[, 2] - coordinates.y.q
|
||||
divide.x.at = quantile(coordinates[, 1], c(.99)) * 1.2
|
||||
divide.y.at = quantile(coordinates[, 2], c(.99)) * 1.2
|
||||
coordinates[, 1] = coordinates[, 1] / divide.x.at
|
||||
coordinates[, 2] = coordinates[, 2] / divide.y.at
|
||||
coordinates_ = c()
|
||||
for(i in 1:dim(coordinates)[1]){
|
||||
varx = round(coordinates[i, 1], digits = 3)
|
||||
vary = round(coordinates[i, 2], digits = 3)
|
||||
coordinates_ = c(coordinates_ ,paste(varx, vary, sep = ","))
|
||||
}
|
||||
coordinates = paste(coordinates_, collapse = ",")
|
||||
coordinates.file = paste(dr_name, "coordinates", sep = "_")
|
||||
coordinates.file = file.path(dr_output_folder, coordinates.file)
|
||||
coordinates.file = file(coordinates.file, "w")
|
||||
writeLines(coordinates, coordinates.file)
|
||||
close(coordinates.file)
|
||||
}
|
||||
|
||||
# save gene expression
|
||||
# get all genes names in alphabetical order
|
||||
gene_names = read.csv("genes.tsv", sep = "\t", header = F)
|
||||
gene_names = as.vector(unique(gene_names$V2))
|
||||
gene_names = sort(gene_names)
|
||||
# read the hgnc data frame and keep just the columns relevant for gene symbol and gene family
|
||||
hgnc = read.csv("./hgnc.csv", sep = '\t', row.names =NULL)
|
||||
hgnc = hgnc[, c("symbol", "gene_family")]
|
||||
# filter out any rows where the gene symbol is not found in the seurat genes or where the gene symbol is not part of any family
|
||||
hgnc = hgnc[hgnc$symbol %in% gene_names, ]
|
||||
hgnc = hgnc[!(hgnc$gene_family == ""), ]
|
||||
# extract all gene families and arrange them in alphabetical order
|
||||
gene.families = sort(unique(unlist(strsplit(as.vector(hgnc$gene_family), split="\\|"))))
|
||||
gene.families.contents = rep("", length(gene.families))
|
||||
names(gene.families.contents) = gene.families
|
||||
# population an empty vector which has names set to gene families, with all the genes part of that family
|
||||
for(j in 1:dim(hgnc)[1]){
|
||||
gene.fam.concat =unlist(strsplit( as.vector(hgnc$gene_family)[j], split = "\\|"))
|
||||
quoted.gene.symbol = as.vector(hgnc$symbol)[j]
|
||||
for (k in 1:length(gene.fam.concat)){
|
||||
gene.fam = gene.fam.concat[k]
|
||||
if(gene.families.contents[gene.fam] != ""){
|
||||
gene.families.contents[gene.fam] = paste(gene.families.contents[gene.fam], paste("'", quoted.gene.symbol, "'", sep = ""), sep = ",")
|
||||
}else{
|
||||
gene.families.contents[gene.fam] = as.character(paste("'", quoted.gene.symbol, "'", sep = ""))
|
||||
}
|
||||
}
|
||||
}
|
||||
# insert each gene family into double quotes - for js compatibility
|
||||
gene.families = unlist(lapply(gene.families, function(gene.fam){paste('\"', gene.fam, '\"', sep = "")}))
|
||||
# insert each gene name in single quotes - for js compatibility
|
||||
gene_names = unlist(lapply(gene_names, function(gene.n){paste("'", gene.n, "'", sep = "")}))
|
||||
gene_names = paste(gene_names, collapse = ",")
|
||||
# create a javacript point to gene_list and populate it with all gene names
|
||||
gene.list = sprintf("gene_list = [%s];", gene_names)
|
||||
# create the javacript named array gene_familie and populate it with indices for all genes for each gene family
|
||||
gene.list = paste(gene.list, "gene_families = [];", sep = "")
|
||||
# loop over each gene family name and insert its gene indices in gene.list
|
||||
for(k in 1:length(gene.families)){
|
||||
gene.fam = gene.families[k]
|
||||
gene.indices = as.vector(gene.families.contents[k])
|
||||
gene.list = paste(gene.list, sprintf("gene_families[%s] = [%s];", gene.fam, gene.indices), sep = "")
|
||||
}
|
||||
gene.list.file = file.path(gene_output_folder, "gene_lists")
|
||||
gene.list.file = file(gene.list.file, "w")
|
||||
writeLines(gene.list, gene.list.file)
|
||||
close(gene.list.file)
|
||||
|
||||
####### save gene expression files
|
||||
gene_names = read.csv("genes.tsv", sep = "\t", header = F)
|
||||
gene_names = as.vector(unique(gene_names$V2))
|
||||
gene_names = sort(gene_names)
|
||||
gene.expression.scale.limit = 1;
|
||||
# loop though each gene name, get its expression and convert it to a color scale
|
||||
# if gene name does not exists in the seurat object (has not passed filtering) save its expression as zeros
|
||||
expression_matrix = as(expression_matrix, 'dgCMatrix')
|
||||
for (i in 1:length(gene_names)){
|
||||
gene_name = gene_names[i]
|
||||
if (gene_name %in% rownames(expression_matrix)){
|
||||
gene_expression = expression_matrix[gene_name, ]
|
||||
}else{
|
||||
gene_expression = rep(0, ncol(expression_matrix))
|
||||
}
|
||||
gene_expression.upper.limit = max(max(gene_expression), gene.expression.scale.limit)
|
||||
gene_expression = gene_expression / gene_expression.upper.limit
|
||||
gene_expression = lapply(gene_expression, function(val){round(val, digits = 2)})
|
||||
gene_expression = unlist(gene_expression)
|
||||
gene_expression = c(round(gene_expression.upper.limit, digits=1), gene_expression)
|
||||
gene_expression = paste(gene_expression, collapse = ",")
|
||||
gene_expression.fname = file.path(gene_output_folder, gsub(pattern="/", replacement="__", x=gene_name));
|
||||
gene_expression.file = file(gene_expression.fname)
|
||||
writeLines(gene_expression, gene_expression.file)
|
||||
close(gene_expression.file)
|
||||
print(sprintf("%s - %s", gene_name, i))
|
||||
}
|
||||
|
||||
# add the nUMI and nGene
|
||||
for (j in 1:2){
|
||||
gene_name = c('nGene', 'nUMI')[j]
|
||||
if (j == 'nGene'){
|
||||
gene_expression = nGene
|
||||
}else{
|
||||
gene_expression = nUMI
|
||||
}
|
||||
gene_expression.upper.limit = max(gene_expression)
|
||||
gene_expression = gene_expression / gene_expression.upper.limit
|
||||
gene_expression = lapply(gene_expression, function(val){round(val, digits = 2)})
|
||||
gene_expression = unlist(gene_expression)
|
||||
gene_expression = c(round(gene_expression.upper.limit, digits=1), gene_expression)
|
||||
gene_expression = paste(gene_expression, collapse = ",")
|
||||
gene_expression.fname = file.path(gene_output_folder, gsub(pattern="/", replacement="__", x=gene_name));
|
||||
gene_expression.file = file(gene_expression.fname)
|
||||
writeLines(gene_expression, gene_expression.file)
|
||||
close(gene_expression.file)
|
||||
print(sprintf("%s - %s", gene_name, j))
|
||||
}
|
||||
|
||||
# tar zip the output so it will be faster to download/upload between servers
|
||||
print("Tar-zipping the output so it will be much faster for downloading/uploading operations between servers ...")
|
||||
output_folder.arh = paste(output_folder, ".tar.gz", sep = "")
|
||||
tar(output_folder.arh, files = output_folder, compression = 'gzip')
|
||||
print("(The output is the tar.zip file which is much faster to download/upload than a folder with tens of thousands of files.)")
|
||||
|
||||
# remove the out folder
|
||||
print("Deleting the output folder ...")
|
||||
unlink(x=output_folder, recursive=T, force=T)
|
||||
|
||||
print("Ended beautifully ... ")
|
||||
16
pipelines/90_web_portal/web_portal.sh
Executable file
16
pipelines/90_web_portal/web_portal.sh
Executable file
|
|
@ -0,0 +1,16 @@
|
|||
#!/bin/bash
|
||||
|
||||
#$ -cwd
|
||||
#$ -N web_portal
|
||||
#$ -V
|
||||
#$ -l h_rt=23:59:59
|
||||
#$ -l h_vmem=100G
|
||||
|
||||
if [ "$#" -ne 1 ]; then
|
||||
echo "Illegal number of parameters"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
Rscript web_portal.R $1
|
||||
|
||||
echo "End on `date`"
|
||||
Loading…
Add table
Add a link
Reference in a new issue