Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • statistical-genetics/jass
  • statistical-genetics/jass-server
2 results
Show changes
Commits on Source (62)
Showing
with 588 additions and 129864 deletions
......@@ -8,6 +8,9 @@ test-python:
image: python:$PYTHON_VERSION
needs: []
stage: test
retry:
max: 2
when: runner_system_failure
script:
- apt-get update && apt install -y libblas-dev liblapack-dev python3-dev
- pip install -r requirements.txt
......@@ -16,8 +19,8 @@ test-python:
matrix:
- PYTHON_VERSION: [
'3.7',
'3.8',
'3.9',
# '3.8',
# '3.9',
'3.10',
]
......@@ -27,7 +30,12 @@ test-docker-compose:
services:
- registry-gitlab.pasteur.fr/dsi-tools/docker-images/docker:dind
needs: []
when: delayed
start_in: 3 minutes
stage: test
retry:
max: 2
when: runner_system_failure
script:
- apk update && apk upgrade && apk add jq bash curl
- ./test_docker_compose.sh
......@@ -77,6 +85,9 @@ pages:
.build:
stage: build
image: registry-gitlab.pasteur.fr/dsi-tools/docker-images/docker:latest
retry:
max: 2
when: runner_system_failure
services:
- registry-gitlab.pasteur.fr/dsi-tools/docker-images/docker:dind
script:
......@@ -153,6 +164,9 @@ build-client-prod:
- test-python
# - test-backend-image
image: harbor.pasteur.fr/kube-system/helm-kubectl:3.4.0
retry:
max: 2
when: runner_system_failure
script:
# create if missing the shared pvc to save data
- kubectl apply -n $NAMESPACE -f chart/pvc-shared-data.yaml
......@@ -224,6 +238,9 @@ delete-dev-deployment:
environment:
name: "k8sdev-01/jass-dev/${CI_COMMIT_REF_SLUG}"
action: stop
retry:
max: 2
when: runner_system_failure
script:
- echo "Removing $CI_COMMIT_REF_SLUG"
- helm delete -n ${NAMESPACE} ${CI_COMMIT_REF_SLUG}
......
apiVersion: v1
kind: Service
metadata:
name: {{ printf "%s-%s" .Release.Name "celery-worker-svc" }}
labels:
{{- include "chart.labels" . | nindent 4 }}
app: celery-worker-svc
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
{{- include "chart.labels" . | nindent 4 }}
app: celery-worker
---
apiVersion: apps/v1
kind: Deployment
kind: StatefulSet
metadata:
name: {{ printf "%s-%s" .Release.Name "celery" }}
labels:
......@@ -10,8 +26,12 @@ spec:
matchLabels:
{{- include "chart.selectorLabels" . | nindent 6 }}
app: celery-worker
strategy:
type: Recreate
serviceName: {{ printf "%s-%s" .Release.Name "celery-worker-svc" }}
{{- if .Values.celery.replicas }}
replicas: {{ .Values.celery.replicas }}
{{- end }}
updateStrategy:
type: RollingUpdate
template:
metadata:
{{- with .Values.podAnnotations }}
......@@ -45,6 +65,10 @@ spec:
value: {{ printf "%s-rabbitmq" .Release.Name }}
- name: RABBITMQ_PORT
value: '5672'
{{- if .Values.projects.minSizeToKeepFree }}
- name: MIN_SIZE_TO_KEEP_IN_PROJECTS_DIR_IN_MB
value: '{{ .Values.projects.minSizeToKeepFree }}'
{{- end }}
command:
- "celery"
- "-A"
......
projects:
size: 34Gi # quota - 15Gi from pvc-shared-data.yaml - 1Gi for rabbitMQ
size: 84Gi # quota - 15Gi from pvc-shared-data.yaml - 1Gi for rabbitMQ
minSizeToKeepFree: 16384 # size is in MB,
celery:
resources:
......
......@@ -7,7 +7,7 @@
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'BrandonGrotesqueBld';
src: local('BrandonGrotesqueBld'),
......@@ -25,8 +25,8 @@
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'PlayfairDisplayBld';
src: local('PlayfairDisplayBld'),
......@@ -46,7 +46,7 @@
}
/* FONT DETAILS */
* {
font-family: 'BrandonGrotesqueReg';
font-size: 18px;
......@@ -57,7 +57,7 @@
text-transform: capitalize;
font-size: 30px;
}
h2 {
font-family: 'PlayfairDisplayBld';
font-size: 24px;
......@@ -99,9 +99,10 @@
}
.main_intro {
width: 75%;
margin: 0 auto;
padding: 30px 0px 30px 0px;
text-align: justify;
font-family: 'BrandonGrotesqueReg';
font-size: 18px;
line-height: 1.5;
}
.card-title {
......@@ -109,18 +110,6 @@
font-size: 25px;
}
.left-card {
text-align: left;
width: 60%;
margin: 20px auto;
}
.right-card {
text-align: right;
width: 60%;
margin: 20px auto;
}
button,input,select,textarea {
font-size:100%;
margin:0;
......@@ -233,4 +222,4 @@ button:active,input[type="submit"]:active,input[type="button"]:active,input[type
.footer-text {
font-size: 12px;
}
\ No newline at end of file
}
<template>
<v-card :elevation=0 :class="myClass">
<v-container>
<v-card-title class="card-title"> {{title}} </v-card-title>
<v-col
cols="12"
sm="8"
offset-sm="2"
lg="6"
offset-lg="3">
<v-card-title class="card-title"> {{title}} </v-card-title>
<v-row>
<v-col
cols="5"
md="3">
cols="12"
sm="5"
md="4">
<v-img
class="mx-auto"
height="200"
width="200"
:src='myImg'
></v-img>
</v-col>
<v-col
cols="12"
sm="7"
md="9">
<v-card-text style="font-size:18px; color:black;">
{{description}}
</v-card-text>
</v-col
>
</v-row>
<v-card-actions style="width: 50%; margin: 0 auto; background: white; border-radius: 3px; padding: 20px; box-shadow: 1px 1px 5px #aeaeae;">
md="8">
<v-card-text style="font-size:18px; color:black;text-align: justify;">
{{description}}
</v-card-text>
</v-col>
<v-col
cols="12"
md="8"
offset-md="2">
<v-card-actions style="margin: 0 auto; background: white; border-radius: 3px; padding: 20px; box-shadow: 1px 1px 5px #aeaeae;">
<v-card-text style="font-size:18px; text-align:center;"> {{short_btn}}</v-card-text>
<v-btn :to ="link" :style="myStyle" style="color:#fff; text-transform:none; margin:0 auto;">
{{short_desc}}
</v-btn>
</v-card-actions>
</v-container>
</v-col>
</v-row>
</v-col>
</v-card>
</template>
......@@ -37,3 +49,10 @@
props: ['title', "description", "short_btn", "short_desc","link","myStyle","myClass","myImg"]
}
</script>
<style>
.card-title {
word-break:unset;
}
</style>
<template>
<div>
<v-speed-dial v-model="dialShare" absolute right bottom direction="left" open-on-hover>
<v-speed-dial v-model="dialShare" absolute top right direction="left" open-on-hover>
<template v-slot:activator>
<v-btn fab bottom small color="primary">
<v-icon v-if="dialShare">mdi-close</v-icon>
......@@ -16,12 +15,13 @@
<v-btn dark fab bottom color="green" small :href="`https://wa.me/?text=Checkout%20this%20page.%20${pageUrl}`" target="_blank">
<v-icon>mdi-whatsapp</v-icon>
</v-btn>
<v-btn dark fab bottom color="tertiary" small :href="`mailto:?subject=Awesomeness!&amp;body=Checkout this page!<a href='${pageUrl}'>${pageUrl}</a>`" target="_blank">
<v-btn dark fab bottom color="primary" small :href="`mailto:?subject=JASS analysis&amp;body=Here is an analysis computed in JASS: ${pageUrl}`" target="_blank" title="Send by mail">
<v-icon>mdi-email</v-icon>
</v-btn>
<v-btn dark fab bottom color="primary" small v-on:click="copySign()" title="Copy to clipboard">
<v-icon>mdi-clipboard</v-icon>
</v-btn>
</v-speed-dial>
</div>
</template>
<script>
......@@ -31,8 +31,13 @@
return {
dialShare: false
}
},
methods: {
copySign() {
navigator.clipboard.writeText(this.pageUrl);
}
}
}
</script>
\ No newline at end of file
</script>
......@@ -20,10 +20,25 @@
></v-img>
</v-app-bar>
<v-tabs fixed-tabs dark>
<span class="hidden-xs-only" style="width:280px"></span>
<v-tab v-for="(item, i) in items"
:key="i"
:to="item.to" v-text="item.title">
</v-tab>
<v-tab to="/workload" style="max-width:280px;margin-right: inherit;margin-left: auto;">
Workload
<v-progress-linear
:value="this.activeTask/(this.activeTask+this.pendingTask)*100"
:background-color="(this.activeTask==0)&&(this.pendingTask==0)?'#fffb':undefined"
:buffer-value="this.activeTask === null ? 0 : 100"
height="20"
:stream="this.activeTask === null"
:striped="this.activeTask !== null"
color="rgb(45, 150, 250)"
:title="'Task: '+this.activeTask +' running and ' +this.pendingTask+' pending.'"
class="hidden-xs-only ml-2"
><small>{{textProgressBar}}</small></v-progress-linear>
</v-tab>
</v-tabs>
<v-main>
<v-container>
......@@ -38,6 +53,8 @@
export default {
data () {
return {
activeTask: null,
pendingTask: null,
clipped: false,
drawer: false,
fixed: false,
......@@ -125,6 +142,36 @@ export default {
],
},
}
},
created(){
this.getQueueStatus();
},
methods:{
async getQueueStatus(){
if (this.isready)
return;
await this.$axios.$get('/queue_status').then((function (resultStatus) {
console.log(resultStatus);
this.activeTask = resultStatus.active;
this.pendingTask = resultStatus.reserved;
setTimeout(this.getQueueStatus, 5000);
}).bind(this)).catch((function () {
setTimeout(this.getQueueStatus, 10000);
}).bind(this));
},
},
computed:{
textProgressBar(){
if (this.activeTask === null)
return ''
if (this.pendingTask === 0){
if (this.activeTask ===0 ){
return 'no load';
}
return this.activeTask + " running";
}
return this.activeTask + " + " + this.pendingTask;
},
}
}
</script>
......
......@@ -2,47 +2,44 @@
<div>
<h1 class="main_title"> Welcome to JASS v2.1</h1>
<h3>a web interface for the Joint Analysis of GWAS Summary Statistics</h3>
<p class="main_intro">
<v-row><v-col cols="12" sm="10" offset-sm="1">
<v-card-text style="text-align: justify;" class="main_intro">
The JASS web interface efficiently compute multi-trait genome-wide association study (GWAS) and enable user to interactively explore results.
Multi-trait GWAS can increase statistical power by leveraging pleiotropy, but also can deepen our understanding of SNPs functional effect (for a detailed explanation see the citation box below).
Currently this website host <b>{{initmeta.nb_phenotypes}}</b> traits available for analysis with the Omnibus test.
All GWAS have been pre-processed using the <a href="https://gitlab.pasteur.fr/statistical-genetics/jass_suite_pipeline">JASS pre-processing pipeline</a> and imputation of missing statistics has been conducted using the <a href="https://gitlab.pasteur.fr/statistical-genetics/raiss">RAISS software</a>, resulting in a total of <b>{{initmeta.nb_snps}}</b> SNPs available for analysis.
To analyze data in your own facility and/or access supplementary joint analysis tests, please download and install the <a href="https://statistical-genetics.pages.pasteur.fr/jass/">JASS python package.</a>
</p>
</v-card-text>
</v-col></v-row>
<v-container fluid>
<v-row dense>
<AnalysisCard v-for="analysis in analysis" :key="analysis.title" :title="analysis.title" :description="analysis.description" :short_btn="analysis.short_btn" :short_desc="analysis.short_desc" :link="analysis.link" :myStyle="analysis.myStyle" :myClass="analysis.myClass" :myImg="analysis.myImg" />
</v-row>
</v-container>
<div style="text-align: center; background-color: #fbfbfb; padding: 20px; width: 80%; margin: 30px auto;">
<v-row><v-col cols="10" offset="1" md="8" offset-md="2" style="text-align: center; background-color: #f8f8f8;margin:1em auto" id="citations">
<h2> Citations </h2>
<p style="text-align:center; padding:20px;">
<h4>When referring to theoretical basis of JASS tests, cite :</h4>
<b><i class="fas fa-quote-left"> Julienne, H., Laville, V., McCaw, Z.R., He, Z., Guillemot, V., Lasry, C., Ziyatdinov, A., Nerin, C., Vaysse, A., Lechat, P., Ménager, H and Aschard, H. </i>Multitrait GWAS to connect disease variants and biological mechanisms</b> <i>PLOS Genetics</i> Aug 30;17(8):e1009713. https://doi.org/10.1371/journal.pgen.1009713<a href="https://academic.oup.com/nargab/article/2/1/lqaa003/5715214" target="_blank">https://journals.plos.org/plosgenetics/article?id=10.1371/journal.pgen.1009713</a><br>
<b><i class="fas fa-quote-left"> Julienne, H., Laville, V., McCaw, Z.R., He, Z., Guillemot, V., Lasry, C., Ziyatdinov, A., Nerin, C., Vaysse, A., Lechat, P., Ménager, H and Aschard, H. </i>Multitrait GWAS to connect disease variants and biological mechanisms</b> <i>PLOS Genetics</i> Aug 30;17(8):e1009713. doi: 10.1371/journal.pgen.1009713 <br/><a href="https://academic.oup.com/nargab/article/2/1/lqaa003/5715214" target="_blank">https://journals.plos.org/plosgenetics/article?id=10.1371/journal.pgen.1009713</a><br>
<br>
<h4>When using JASS software in publication, cite :</h4>
<b><i class="fas fa-quote-left">Julienne, H., Lechat, P., Guillemot, V., Lasry, C., Yao, C., Araud, R., Laville, V., Vilhjalmsson, B., Ménager, H. and Aschard, H. </i>JASS: command line and web interface for the joint analysis of GWAS results.</b> <i>NAR Genom Bioinform</i> 2020 Mar;2(1):lqaa003.
doi: 10.1093/nargab/lqaa003. Epub 2020 Jan 24. <a href="https://academic.oup.com/nargab/article/2/1/lqaa003/5715214" target="_blank">https://academic.oup.com/nargab/article/2/1/lqaa003/5715214</a><br>
doi: 10.1093/nargab/lqaa003. Epub 2020 Jan 24. <br/><a href="https://academic.oup.com/nargab/article/2/1/lqaa003/5715214" target="_blank">https://academic.oup.com/nargab/article/2/1/lqaa003/5715214</a><br>
<br>
<h4>When refereeing to the imputation of summary statistics, cite :</h4>
<b><i class="fas fa-quote-left">Julienne, H., Shi, H., Pasaniuc, B. and Aschard, H. </i>RAISS: robust and accurate imputation from summary statistics.</b> <i>Bioinformatics</i> 2019 Nov 1;35(22):4837-4839.
doi: 10.1093/bioinformatics/btz466. <a href="https://academic.oup.com/bioinformatics/article/35/22/4837/5512360" target="_blank">https://academic.oup.com/bioinformatics/article/35/22/4837/5512360</a><br>
doi: 10.1093/bioinformatics/btz466. <br/><a href="https://academic.oup.com/bioinformatics/article/35/22/4837/5512360" target="_blank">https://academic.oup.com/bioinformatics/article/35/22/4837/5512360</a><br>
<br>
</p>
</div>
<v-row>
<v-col cols="12">
<div style="text-align: center; background-color: #fbfbfb; padding: 20px; width: 80%; margin: 30px auto;">
</v-col>
<v-col cols="10" offset="1" md="8" offset-md="2" style="text-align: center; background-color: #f8f8f8;margin:1em auto">
<h2> Team </h2>
<p>
Jass is developed at Institut Pasteur by the <a href="https://research.pasteur.fr/en/team/statistical-genetics/">Statistical Genetics group</a> and the <a href="https://research.pasteur.fr/en/team/bioinformatics-and-biostatistics-hub/">Biostatistic and Bioinformatic HUB</a>
<p>
<a href="https://research.pasteur.fr/en/team/statistical-genetics/"> The Statistical Genetics group</a>, lead by Hugues Aschard, is interested in developping new methods to analyze GWAS data. In particular, in JASS, we leverage publicly available GWAS results to discover new signals and understand pleiotropy. While our team focus mainly on developping the theory behind the tools, we also aim to make our software widely available and to follow high quality software development standards. Hence, our close collaboration with the hub and more specifically with its WINTER group dedicated to web developement. <a href="https://research.pasteur.fr/en/team/hub-winter/">The WINTER group</a> is a software development team focusing mainly on Web technologies for publishing and sharing scientific tools, analysis, data and workflows. We work hand in hand to develop JASS website.
<a href="https://research.pasteur.fr/en/team/statistical-genetics/"> The Statistical Genetics unit</a>, lead by Hugues Aschard, is interested in developping new methods to analyze GWAS data. In particular, in JASS, we leverage publicly available GWAS results to discover new signals and understand pleiotropy. While our team focus mainly on developping the theory behind the tools, we also aim to make our software widely available and to follow high quality software development standards. Hence, our close collaboration with the hub and more specifically with its WINTER group dedicated to web developement. <a href="https://research.pasteur.fr/en/team/hub-winter/">The WINTER group</a> is a software development team focusing mainly on Web technologies for publishing and sharing scientific tools, analysis, data and workflows. We work hand in hand to develop JASS website.
</p>
</div>
</v-col>
</v-row>
......@@ -85,7 +82,6 @@ export default {
myStyle:{
backgroundColor:'#2D96FA',
},
myClass:'left-card',
myImg:'/jass19Avrilsmall.png',
},
......@@ -107,3 +103,9 @@ export default {
}
}
</script>
<style>
#citations a[target="_blank"] {
word-break:break-all;
}
</style>
......@@ -7,7 +7,7 @@
Please select the traits you want to analyze jointly with the Omnibus test. A research box bellow allows you to query our current database. The maximum number of trait that can be analyzed jointly is 64 traits. Computation time for a large number of trait can take up to half an hour.
</p>
</div>
<h2>Select the GWAS to be analyzed jointly:</h2>
<h2>Select at least two GWASs to be analyzed jointly:</h2>
<div id="app">
<v-app>
<v-data-table
......@@ -33,7 +33,7 @@ Please select the traits you want to analyze jointly with the Omnibus test. A re
</template>
</v-data-table>
<div align="left" justify="start">
<v-btn depressed color="primary" v-on:click="runAnalysis()">
<v-btn depressed color="primary" v-on:click="runAnalysis()" :disabled="selectedRows.length <=1">
Launch analysis
</v-btn>
</div>
......
......@@ -10,7 +10,7 @@
class="text-subtitle-1 text-center"
cols="12"
>
<h2>Creating the worktable ! It might take a few minutes</h2>
<h2>Creating the worktable ! It might take a few minutes </h2>
</v-col>
<v-col
class="text-subtitle-1 text-center"
......@@ -18,13 +18,13 @@
>
<PhenotypeCard v-for="pheno in phenotypesDict" :key="pheno.id" :phe="pheno"/>
</v-col>
<v-col cols="6">
<v-col cols="12" md="8" lg="6">
<v-progress-linear
color="#298e49"
striped
rounded
height="20"
v-model="progress"
:value="progress"
>
<strong style="color:white; text-transform:capitalize;">{{progress}} %</strong>
</v-progress-linear>
......@@ -34,14 +34,13 @@
<v-col cols="12">
<v-card >
<ShareLink :pageUrl="sharedUrl"/>
</v-card>
<v-card>
<ShareLink :pageUrl="sharedUrl" style="top:-1em"/>
<div class="row" style="text-align:left;padding:12px;margin:0;">
<h1 style="text-transform:none;">Results for :</h1>
<PhenotypeCard v-for="pheno in phenotypesDict" :key="pheno.id" :phe="pheno"/>
</div>
</v-card>
<v-card style="margin-top:10px; margin-bottom:10px;" outlined tile no-gutter>
<v-card-title class="text-h5">
<v-row justify="start" no-gutters>
......@@ -57,10 +56,14 @@
<b>Test performed:</b>Omnibus
</v-col>
<v-col >
<v-card>
<v-card style="padding:16px">
Genetic covariance derived with <a href="https://www.nature.com/articles/ng.3406">the LDScore</a>
The value on the diagonal correspond to the heritability of the trait.
<div id="divCorrelationHeat" ref="divCorrelationHeat"><!-- Plotly chart will be drawn inside this DIV --></div>
<div v-if="this.gencov && 'error' in this.gencov">
<v-icon style="margin-top: -8px;" color="error">mdi-alert-octagon</v-icon>
Computation failure: <v-card-text style="white-space: pre;">{{gencov.error}}</v-card-text>
</div>
<div v-else id="divCorrelationHeat" ref="divCorrelationHeat"><!-- Plotly chart will be drawn inside this DIV --></div>
</v-card>
</v-col>
</v-row>
......@@ -81,7 +84,7 @@
</v-col>
<v-col >
<vue-json-to-csv :json-data="Regions">
<vue-json-to-csv :json-data="Regions" :csv-title="'LD-independent lead SNPs - '+ this.project.id">
<v-btn small color="#298e49" style="color:#fff; text-transform:capitalize;" v-on:click="processExportAllJASSPVAL()" >
Export LD-independent lead SNPs
</v-btn>
......@@ -129,6 +132,19 @@
indeterminate
></v-progress-circular>
</v-btn>
<v-btn
:disabled="status.qq_plot != 'READY'"
small color="#298e49" style="color:#fff;text-transform:capitalize;"
v-on:click="qqPlot()">
QQ plot
<v-progress-circular
v-if="status.qq_plot != 'READY'"
:size="15"
:width="2"
style="margin-left:5px"
indeterminate
></v-progress-circular>
</v-btn>
<p>Tips : You can share the link of this page with your collaborators. They will have access to the same results.</p>
</v-col>
</v-row>
......@@ -162,7 +178,7 @@
:items-per-page="5"
class="elevation-1"
></v-data-table>
<vue-json-to-csv :json-data="significantsRegions">
<vue-json-to-csv :json-data="significantsRegions" :csv-title="'Significants regions - '+ this.project.id">
<v-btn small color="#298e49" style="color:#fff;">export csv</v-btn>
<!-- <button>
<b>export csv</b>
......@@ -493,6 +509,11 @@ methods:{
console.log("quadrant "+desiredLink);
window.open(desiredLink,'_blank');
},
qqPlot(){
const desiredLink = process.env.API_URL+"/projects/"+this.project.id+"/qqplot";
console.log("qq "+desiredLink);
window.open(desiredLink,'_blank');
},
manhattanPlot(){
const desiredLink = process.env.API_URL+"/projects/"+this.project.id+"/globalmanhattan";
console.log("globalmanhattan "+desiredLink);
......@@ -553,7 +574,7 @@ methods:{
this.sharedUrl = "http://"+window.location.host + "/projects/" + this.project.id;
console.log(this.project.id);
this.status=result.status;
if(result.status.worktable ==="READY"){
if(result.status.metadata ==="READY" && ! this.isready){
await this.$axios.$get('/projects/'+this.project.id+"/gencov").then((async function (result2) {
this.gencov = result2;
......@@ -574,16 +595,26 @@ methods:{
await this.$axios.$get('/projects/'+this.project.id+"/metadata").then((function (result4) {
this.metadata = result4;
}).bind(this));
}).bind(this));
}).bind(this)).catch(error => {
console.error(error.response.data.detail);
this.gencov = {'error': error.response.data.detail}
this.isready=true;
});
}
let keepFetching=true;
for (const step in result.status){
if (result.status[step] !=="READY"){
setTimeout(this.getStatus, 10000);
keepFetching=true
break;
}else{
keepFetching=false;
}
}
if (keepFetching){
setTimeout(this.getStatus, 5000);
}
}).bind(this)).catch((function () {
setTimeout(this.getStatus, 10000);
}).bind(this));
......
<template>
<v-row>
<v-col cols=12 style="text-align:center">
<h1>Server workload</h1>
</v-col>
<v-col cols=12 >
<v-row>
<v-col cols=6 style="text-align:right">
<h4>Compute node:</h4>
</v-col>
<v-col cols=6 >
<h4>{{this.worker}}</h4>
</v-col>
</v-row>
</v-col>
<v-col cols=12 >
<v-row>
<v-col cols=6 style="text-align:right">
<h4>Tasks being processed:</h4>
</v-col>
<v-col cols=6 >
<h4>{{this.activeTask}}</h4>
</v-col>
</v-row>
</v-col>
<v-col cols=12 >
<v-row>
<v-col cols=6 style="text-align:right">
<h4>Pending tasks to be computed</h4>
</v-col>
<v-col cols=6 >
<h4>{{this.pendingTask}}</h4>
</v-col>
</v-row>
</v-col>
<v-col
v-if="activeTask===0"
style="text-align:center"
cols=12>
Your analysis would start right away.
</v-col>
<v-col
v-else-if="activeTask>0"
style="text-align:center"
cols=12>
Your analysis would be queued, and processed as soon as possible.
</v-col>
<v-col
v-else
cols=12>
&nbsp;
</v-col>
</v-row>
</template>
<script>
export default {
data () {
return {
activeTask: '_',
pendingTask: '_',
worker: '_',
}
},
created(){
this.getQueueStatus();
},
methods:{
async getQueueStatus(){
await this.$axios.$get('/queue_status').then((function (resultStatus) {
console.log(resultStatus);
this.activeTask = resultStatus.active;
this.worker = resultStatus.worker;
this.pendingTask = resultStatus.reserved;
setTimeout(this.getQueueStatus, 5000);
}).bind(this)).catch((function () {
setTimeout(this.getQueueStatus, 10000);
}).bind(this));
},
}
}
</script>
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
This diff is collapsed.
File deleted
Installation
============
You can use JASS locally either using the command line interface in a terminal, or by running a web server. Deployment in a public server is also later discussed in this document.
You need **python3** to install and use JASS. As of April 2022, JASS runs on python from 3.6 to 3.10.
Installation with pip (recommended)
-----------------------------------
We advise users to install jass in a virtual environment
.. code-block:: shell
python3 -m venv $PATH_NEW_ENVIRONMENT
source $PATH_NEW_ENVIRONMENT/bin/activate
pip3 install git+https://gitlab.pasteur.fr/statistical-genetics/jass.git
pip3 install -r https://gitlab.pasteur.fr/statistical-genetics/jass/-/raw/master/requirements.txt
Installation with conda
-----------------------
Installation with pip (recommended)
-----------------------------------
We advise users to install jass in a virtual environment
.. code-block:: shell
python3 -m venv $PATH_NEW_ENVIRONMENT
source $PATH_NEW_ENVIRONMENT/bin/activate
pip3 install git+https://gitlab.pasteur.fr/statistical-genetics/jass.git
pip3 install -r https://gitlab.pasteur.fr/statistical-genetics/jass/-/raw/master/requirements.txt
Installation with conda
-----------------------
A procedure for the correct installation of JASS in Anaconda environment for development purpose is developed in detail below.
**1. Create a specific directory and load the code on your laptop (only the first time)**
For example, the directory $HOME/DEVELOP_JASS has been created.
In a TERMINAL window, type the following instructions:
.. code-block:: shell
cd $HOME/DEVELOP_JASS
git clone https://gitlab.pasteur.fr/statistical-genetics/jass
**2. Change directory to the JASS main directory**
.. code-block:: shell
cd $HOME/DEVELOP_JASS/jass
**3. Create a specific virtual ANACONDA environment for JASS:**
.. note::
You have to check that you are in the **base** environment of Anaconda before creating the new virtual environment:
(for example, Dev_Jass_Pyt36 with python 3.6)
.. code-block:: shell
conda create --name Dev_Jass_Pyt36 python=3.6
**4. Activation of the new environment**
.. code-block:: shell
conda activate Dev_Jass_Pyt36
**5. Installing JASS dependencies**
.. code-block:: shell
pip install -r requirements.txt
**6. Installing JASS for development purpose**
.. code-block:: shell
pip install -e .
**7. Installation verification**
.. code-block:: shell
pip freeze
Installing it this way will automatically import and setup all of the dependencies required to run JASS.
This is pretty much all you need to do to use JASS on the command line, or to run a local personal web server. To deploy JASS on a public web server, please refer to the "Public server deployment" section.
Additional software installation on Linux
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Some python packages require additional non-python software that you might need to install, e.g. on Ubuntu, with:
.. code-block:: shell
sudo apt install libfreetype6-dev #(required by matplotlib)
sudo apt install libhdf5-dev #(required by tables)
sudo apt install rabbitmq-server #(required by celery)
Additional software installation on Windows
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. tip:: For Windows, an easy option is to install the free software package manager called chocolatey.
In order to have a correct installation of RabbitMQ on windows, we recommend to install chocolatey by running the following command as Administrator in a powershell:
.. code-block:: shell
Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
Then, you can install RabbitMQ with the "choco install" command:
.. code-block:: shell
Choco install rabbitmq
Run JASS as a web application (optional)
----------------------------------------
To run locally JASS as a web application, it is recommended to use the docker-compose as it handles all dependencies in one command.
If using docker-compose is not an option, you need to launch two servers in two different processes, the `celery` task management server and the web server. The web server handles the HTTP requests, and sends all computation requests to the task management server.
Launching with docker compose (recommended)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Once docker and docker-compose installed, just run
.. code-block:: shell
# build the application
docker-compose build
# launch the whole application
docker-compose up
# then visit http://0.0.0.0:3000/
launching the two servers on Linux
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The command lines below show how to launch the two servers. Please note that you should of course not use this for any use beyond tests and personnal use, we provide further instructions below to deploy JASS on shared/public servers.
.. code-block:: shell
# launch celery to process tasks
celery -A jass worker
## and in ANOTHER TERMINAL
# launch the web server
jass serve
By default, the Jass server will listen to requests on the port 8080 of your machine. You can control the host and port that the JASS standalone webserver listens to through two environment variables, ``JASS_HOST`` and ``JASS_PORT``, that you just have to set before to launch the web server.
Launching the celery server on Windows
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In order to launch the celery server on windows, it is necessary to use the following command in a terminal:
.. code-block:: shell
celery -A jass worker --pool=solo
.. warning::
The command recommended for Linux crashes when it is used on windows due to incorrect recognition of the prefork option on windows by the billiard library.
The part “--pool=solo” is necessary on windows because this is the only option of celery that works on windows.
Launching the web server on Windows
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The web server is launched in another terminal (the same as on Linux):
.. code-block:: shell
jass serve
Public server deployment (optional)
-----------------------------------
Helm charts are available in the `chart folder of the source repository <https://gitlab.pasteur.fr/statistical-genetics/jass/tree/master/chart>`_. These charts automate the installation and update of the application in a kubernetes cluster.
In this specific deployment, the JASS web application is hosted by an NGINX server, served by the uvicorn library. It communicates with a celery container that handles the user-launched tasks. Many other deployment options are of course possible, use whichever suits your infrastructure!
Installation
============
You can use JASS locally either using the command line interface in a terminal, or by running a web server. Deployment in a public server is also later discussed in this document.
You need **python3** to install and use JASS. As of April 2022, JASS runs on python from 3.6 to 3.10.
Installation with pip (recommended)
-----------------------------------
We advise users to install jass in a virtual environment
.. code-block:: shell
python3 -m venv $PATH_NEW_ENVIRONMENT
source $PATH_NEW_ENVIRONMENT/bin/activate
pip3 install git+https://gitlab.pasteur.fr/statistical-genetics/jass.git
pip3 install -r https://gitlab.pasteur.fr/statistical-genetics/jass/-/raw/master/requirements.txt
Installation with conda
-----------------------
A procedure for the correct installation of JASS in Anaconda environment for development purpose is developed in detail below.
**1. Create a specific directory and load the code on your laptop (only the first time)**
For example, the directory $HOME/DEVELOP_JASS has been created.
In a TERMINAL window, type the following instructions:
.. code-block:: shell
cd $HOME/DEVELOP_JASS
git clone https://gitlab.pasteur.fr/statistical-genetics/jass
**2. Change directory to the JASS main directory**
.. code-block:: shell
cd $HOME/DEVELOP_JASS/jass
**3. Create a specific virtual ANACONDA environment for JASS:**
.. note::
You have to check that you are in the **base** environment of Anaconda before creating the new virtual environment:
(for example, Dev_Jass_Pyt36 with python 3.6)
.. code-block:: shell
conda create --name Dev_Jass_Pyt36 python=3.6
**4. Activation of the new environment**
.. code-block:: shell
conda activate Dev_Jass_Pyt36
**5. Installing JASS dependencies**
.. code-block:: shell
pip install -r requirements.txt
**6. Installing JASS for development purpose**
.. code-block:: shell
pip install -e .
**7. Installation verification**
.. code-block:: shell
pip freeze
Installing it this way will automatically import and setup all of the dependencies required to run JASS.
This is pretty much all you need to do to use JASS on the command line, or to run a local personal web server. To deploy JASS on a public web server, please refer to the "Public server deployment" section.
Additional software installation on Linux
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Some python packages require additional non-python software that you might need to install, e.g. on Ubuntu, with:
.. code-block:: shell
sudo apt install libfreetype6-dev #(required by matplotlib)
sudo apt install libhdf5-dev #(required by tables)
sudo apt install rabbitmq-server #(required by celery)
Additional software installation on Windows
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. tip:: For Windows, an easy option is to install the free software package manager called chocolatey.
In order to have a correct installation of RabbitMQ on windows, we recommend to install chocolatey by running the following command as Administrator in a powershell:
.. code-block:: shell
Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
Then, you can install RabbitMQ with the "choco install" command:
.. code-block:: shell
Choco install rabbitmq
Run JASS as a web application (optional)
----------------------------------------
To run locally JASS as a web application, it is recommended to use the docker-compose as it handles all dependencies in one command.
If using docker-compose is not an option, you need to launch two servers in two different processes, the `celery` task management server and the web server. The web server handles the HTTP requests, and sends all computation requests to the task management server.
Launching with docker compose (recommended)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Once docker and docker-compose installed, just run
.. code-block:: shell
# build the application
docker-compose build
# launch the whole application
docker-compose up
# then visit http://0.0.0.0:3000/
launching the two servers on Linux
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The command lines below show how to launch the two servers. Please note that you should of course not use this for any use beyond tests and personnal use, we provide further instructions below to deploy JASS on shared/public servers.
.. code-block:: shell
# launch celery to process tasks
celery -A jass worker
## and in ANOTHER TERMINAL
# launch the web server
jass serve
By default, the Jass server will listen to requests on the port 8080 of your machine. You can control the host and port that the JASS standalone webserver listens to through two environment variables, ``JASS_HOST`` and ``JASS_PORT``, that you just have to set before to launch the web server.
Launching the celery server on Windows
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In order to launch the celery server on windows, it is necessary to use the following command in a terminal:
.. code-block:: shell
celery -A jass worker --pool=solo
.. warning::
The command recommended for Linux crashes when it is used on windows due to incorrect recognition of the prefork option on windows by the billiard library.
The part “--pool=solo” is necessary on windows because this is the only option of celery that works on windows.
Launching the web server on Windows
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The web server is launched in another terminal (the same as on Linux):
.. code-block:: shell
jass serve
Public server deployment (optional)
-----------------------------------
Helm charts are available in the `chart folder of the source repository <https://gitlab.pasteur.fr/statistical-genetics/jass/tree/master/chart>`_. These charts automate the installation and update of the application in a kubernetes cluster.
In this specific deployment, the JASS web application is hosted by an NGINX server, served by the uvicorn library. It communicates with a celery container that handles the user-launched tasks. Many other deployment options are of course possible, use whichever suits your infrastructure!
......@@ -2,9 +2,11 @@
# -*- coding: utf-8 -*-
import os
import shutil
import sys
import argparse
from datetime import timedelta, datetime
from json import JSONDecodeError
import uvicorn
......@@ -171,10 +173,14 @@ def w_clean_project_data(args):
for proj in get_projects_last_access():
print(f"Project {proj['project_id']} was last accessed on {proj['last_access']}, ", end='')
if proj['last_access'] + shift < datetime.now():
if load_project(project_id=proj['project_id'], flag_as_visited=False).delete_large_files():
print("removing its large files")
else:
print("large files already removed")
try:
if load_project(project_id=proj['project_id'], flag_as_visited=False).delete_large_files():
print("removing its large files")
else:
print("large files already removed")
except JSONDecodeError as e:
print("removing as meta.json is corrupted (" + str(e) + ")")
shutil.rmtree(proj['path'])
else:
print("keeping it")
......
......@@ -15,7 +15,7 @@ matplotlib.use("AGG")
import matplotlib.pyplot as plt
from matplotlib import colors
import matplotlib.patches as mpatches
from scipy.stats import norm
from scipy.stats import norm, chi2
import os
from pandas import DataFrame, read_hdf
......@@ -82,7 +82,6 @@ def create_global_plot(work_file_path: str, global_plot_path: str):
ax.set_xticks(lab_pos)
ax.set_xticklabels(label, rotation =90)
ax.set_xlabel("", fontsize=16)
ax.set_ylabel("-log10(p-value)", fontsize=16)
# add line for significant SNPs
......@@ -106,23 +105,14 @@ def create_local_plot(work_file_path: str, local_plot_path: str):
colors = ['blue', 'red']
df = read_hdf(work_file_path, "SumStatTab")
chr = int(df["CHR"].iloc[0])
Num_color = chr % 2
df['JASS_PVAL'] = replaceZeroes(df['JASS_PVAL'])
df["-log10(Joint p-value)"] = -np.log10(df.JASS_PVAL)
Columns_to_keep = ["position", "-log10(Joint p-value)"]
Columns_to_delete = []
for col in df.columns:
if col not in Columns_to_keep:
Columns_to_delete.append(col)
df.drop(Columns_to_delete, axis=1, inplace=True)
df = df[Columns_to_keep]
df.sort_values(by="position", inplace=True)
Nb_values = df.shape[0]
......@@ -261,28 +251,31 @@ def create_quadrant_plot(work_file_path: str,
def create_qq_plot(work_file_path: str, qq_plot_path: str):
df = read_hdf(work_file_path, "SumStatTab")
df = read_hdf(work_file_path, "SumStatTab", columns=['JASS_PVAL', 'UNIVARIATE_MIN_PVAL'])
df[['JASS_PVAL', 'UNIVARIATE_MIN_PVAL']] = replaceZeroes(
df[['JASS_PVAL', 'UNIVARIATE_MIN_PVAL']])
pvalue = -np.log10(df.JASS_PVAL)
# Cast values between 0 and 1, 0 and 1 excluded
x = -np.log10(np.arange(1, pvalue.shape[0] + 1) / (pvalue.shape[0] + 2))
y = pvalue.sort_values()
plt.scatter(x[::-1], y, s=5)
pval_median = np.nanmedian(y)
lambda_value = pval_median / np.median(x)
x_1 = np.linspace(0, 6)
y_1 = lambda_value * x_1
x_2 = np.linspace(0, 6)
plt.plot(x_1, y_1, c="red")
plt.plot(x_2, x_2)
plt.title("median p-val = {:.3f}".format(pval_median))
plt.xlabel("expected quantile of -log10(P)")
plt.ylabel("observed quantile of -log10(P)")
plt.savefig(qq_plot_path, dpi=600)
pvalue_univ = -np.log10(df.UNIVARIATE_MIN_PVAL)
# compute_expected pvalue
QQ_pval = pd.DataFrame(index =-np.log10(np.arange(1, pvalue.shape[0] + 1) / (pvalue.shape[0] + 2)),
{"JASS pvalue" : pvalue.sort_values(),
"UNIV pvalue" : pvalue_univ.sort_values()})
pval_median = df.JASS_PVAL.median()
pval_median_univ = df.UNIVARIATE_MIN_PVAL.median()
print("median pval")
print(pval_median)
lambda_value_jass = chi.sf(pval_median) / chi.sf(0.5)
lambda_value_univ = chi.sf(pval_median_univ) / chi.sf(0.5)
p = sns.lineplot(data=QQ_pval)
p.set("QQ plot")
p.set_xlabel("Expected p-values", fontsize = 20)
p.set_ylabel("Observed p-values", fontsize = 20)
plt.savefig(qq_plot_path)
print("------ QQ plot -----")
def create_qq_plot_by_GWAS(init_file_path: str, qq_plot_folder: str):
......
......@@ -6,6 +6,7 @@ from __future__ import absolute_import
import abc
import shutil
from datetime import datetime
from json import JSONDecodeError
from pathlib import Path
from celery import states
import json
......@@ -123,8 +124,13 @@ class Project(BaseModel, abc.ABC):
if fail_if_exists:
raise e
if os.path.exists(self.get_meta_file_path()):
return False
# The directory exists, but not meta.json, we clean up the directory, in case of.
try:
load_project(self.id)
return False
except JSONDecodeError as e:
print(f"Project {self.id} corrupted ({str(e)}). Removing it, before trying to re-create it.")
pass
# The directory exists, but meta.json don't or is corrupted, we clean up the directory, in case of.
shutil.rmtree(self.get_folder_path())
return self.create(fail_if_exists=fail_if_exists)
......@@ -159,7 +165,7 @@ class Project(BaseModel, abc.ABC):
def update_progress(self, progress):
self.progress = progress
self.save()
print("PROGRESS {0}".format(self.progress))
print(f"PROGRESS for {self.id}: {self.progress}")
def get_folder_path(self):
"""
......@@ -212,6 +218,12 @@ class Project(BaseModel, abc.ABC):
def get_project_summary_statistics(self):
return get_worktable_summary(self.get_worktable_path())
def get_metadata_file_path(self):
"""
Get the path of the metadata json file
"""
return os.path.join(self.get_folder_path(), "metadata.json")
def get_project_nsnps(self):
return get_inittable_meta(self.get_worktable_path())
......@@ -250,11 +262,7 @@ class Project(BaseModel, abc.ABC):
os.remove(project_hdf_path)
# as a consequence, its creation will have to be redone, so set progress to 0 and remove is status.
self.progress = 0
try:
del self.status['worktable']
except KeyError:
# worktable not in status
pass
self.status.clear()
self.save()
if self.delayed_gen_csv_file:
......@@ -264,6 +272,15 @@ class Project(BaseModel, abc.ABC):
if os.path.exists(csv_path):
have_removed_file = True
os.remove(csv_path)
for filename in os.listdir(self.get_folder_path()):
if filename.endswith(".png"):
os.remove(os.path.join(self.get_folder_path(), filename))
have_removed_file = True
try:
os.remove(self.get_metadata_file_path())
have_removed_file = True
except FileNotFoundError:
pass
return have_removed_file
@call_with_tb('global_manhattan')
......@@ -290,6 +307,12 @@ class Project(BaseModel, abc.ABC):
def create_csv_file(self):
return create_genome_full_csv(self.get_worktable_path(), self.get_csv_path())
@call_with_tb('metadata')
def create_project_metadata_file(self):
with open(self.get_metadata_file_path(), 'w') as f:
f.write(json.dumps(self.get_project_nsnps()))
print("------ metadata -----")
class GlobalProject(Project):
@call_with_tb('worktable')
......@@ -408,5 +431,10 @@ def ensure_space_in_project_dir(*, except_project_id=None):
f'({free} MB<{config["MIN_SIZE_TO_KEEP_IN_PROJECTS_DIR_IN_MB"]} MB), '
f'removing data from old projects')
show_space_message = False
if load_project(proj['project_id'], flag_as_visited=False).delete_large_files():
print(f"Project {proj['project_id']} was last accessed on {proj['last_access']}, data removed.")
try:
if load_project(proj['project_id'], flag_as_visited=False).delete_large_files():
print(f"Project {proj['project_id']} was last accessed on {proj['last_access']}, data removed.")
except JSONDecodeError as e:
print(f"Project {proj['project_id']} has a corrupted meta.json ({str(e)}), removing it.")
shutil.rmtree(proj['path'])
......@@ -865,11 +865,18 @@ def get_worktable_gencov(project_hdf_path: str):
for i in range(gencov.shape[0]):
for j in range(i, gencov.shape[0]):
lines.append({
"phenotypeID_A": sorted_trait.iloc[i],
"phenotypeID_B": sorted_trait.iloc[j],
"gencov":gencov.loc[sorted_trait.index[i], sorted_trait.index[j]]
})
if np.isnan(gencov.loc[sorted_trait.index[i], sorted_trait.index[j]]):
lines.append({
"phenotypeID_A": sorted_trait.iloc[i],
"phenotypeID_B": sorted_trait.iloc[j],
"gencov":"null"
})
else:
lines.append({
"phenotypeID_A": sorted_trait.iloc[i],
"phenotypeID_B": sorted_trait.iloc[j],
"gencov":gencov.loc[sorted_trait.index[i], sorted_trait.index[j]]
})
print(lines)
return lines
......@@ -1062,4 +1069,4 @@ def create_genome_full_csv_lock_file(project_hdf_path):
the_lock = "The lock is set on : workTable.csv is not yet available"
file_lock = open(the_lock_path, "w")
file_lock.write(the_lock)
file_lock.close()
\ No newline at end of file
file_lock.close()
#!/usr/bin/env python3
import logging
import os
import shutil
from json import JSONDecodeError
from pathlib import Path
from typing import List
from starlette.responses import RedirectResponse
from starlette.responses import RedirectResponse, JSONResponse
from tables import HDF5ExtError
from jass import util
from jass.config import config
from jass.models.phenotype import Phenotype, get_available_phenotypes, PhenotypeIdList
from jass.models.inittable import get_inittable_meta
from jass.models.project import GlobalProject, load_project as project__load_project
from jass.tasks import create_project, run_project_analysis_if_needed
from jass.tasks import create_project, run_project_analysis_if_needed, get_queue_status
from fastapi import FastAPI, HTTPException
from fastapi.responses import Response, FileResponse
......@@ -32,11 +35,15 @@ else:
logging.info("/webui cannot be served as client/dist is missing, please build the client.")
def load_project(project_id):
def load_project(project_id, *args, **kargs):
try:
return project__load_project(project_id=project_id)
return project__load_project(project_id=project_id, *args, **kargs)
except FileNotFoundError:
raise HTTPException(status_code=404, detail="Project not found")
except JSONDecodeError as e:
print(f"Project {project_id} has a corrupted meta.json ({str(e)}), removing it.")
shutil.rmtree(GlobalProject.get_folder_path_from_id(project_id))
raise HTTPException(status_code=404, detail="Project invalid, and removed")
@app.get("/")
......@@ -75,6 +82,11 @@ def project_detail(project_id: str):
return load_project(project_id=project_id).progress
@app.get("/api/projects/{project_id}/unload", response_model=bool)
def project_detail(project_id: str):
return load_project(project_id=project_id, flag_as_visited=False).delete_large_files()
@app.get("/api/projects/{project_id}/summary")
def project_detail(project_id: str):
return load_project(project_id=project_id).get_project_summary_statistics()
......@@ -82,12 +94,19 @@ def project_detail(project_id: str):
@app.get("/api/projects/{project_id}/gencov")
def project_gencov_view(project_id: str):
return load_project(project_id=project_id).get_project_gencov()
try:
return JSONResponse(load_project(project_id=project_id).get_project_gencov())
except ValueError as e: # NaN in values
raise HTTPException(status_code=500, detail=str(e))
except HDF5ExtError as e: # file corrupted
raise HTTPException(status_code=500, detail=str(e))
except Exception as e: # anything else
raise HTTPException(status_code=500, detail=str(e))
@app.get("/api/projects/{project_id}/metadata")
def project_metadata(project_id: str):
return load_project(project_id=project_id).get_project_nsnps()
return FileResponse(load_project(project_id=project_id).get_metadata_file_path())
@app.get("/api/projects/{project_id}/globalmanhattan")
......@@ -106,6 +125,14 @@ def project_get_quadrant(project_id: str):
)
@app.get("/api/projects/{project_id}/qqplot")
def project_get_qq_plot(project_id: str):
return FileResponse(
load_project(project_id=project_id).get_qq_plot_path(),
media_type="image/png",
)
@app.get("/api/projects/{project_id}/genome_full")
def get_full_sumstat(project_id: str):
project = load_project(project_id=project_id)
......@@ -115,6 +142,7 @@ def get_full_sumstat(project_id: str):
print("CREATED CSV FILE")
return FileResponse(
project.get_csv_path(),
filename=f"genome_full_{project_id}.csv",
media_type="text/csv",
)
......@@ -124,6 +152,7 @@ def get_data_manhattan(project_id: str):
return Response(
content=load_project(project_id=project_id).get_project_genomedata(),
media_type="text/csv",
headers={"content-disposition": f"attachment; filename=genome_{project_id}.csv"},
)
......@@ -153,6 +182,11 @@ def get_manhattan(project_id: str, selected_chr: str, selected_region: str):
)
@app.get("/api/queue_status")
def queue_status():
return JSONResponse(get_queue_status())
# @blp_inittable.route("")
......