Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Metagenomics
metagenedb
Commits
6a851eb1
Commit
6a851eb1
authored
May 13, 2020
by
Kenzo-Hugo Hillion
♻
Browse files
add gene length computation for different gene source and update front
parent
8ac32cc0
Changes
7
Hide whitespace changes
Inline
Side-by-side
README.md
View file @
6a851eb1
...
...
@@ -93,6 +93,11 @@ DATABASE_PORT=5432
port is redirected to `
5433
` on the `
localhost
`. This is done in order to not interfere with your local
postgres if you have one. This means you need to change `
DATABASE_HOST
` to `
localhost
` and `
DATABASE_POS
### Pre-computed statistics
Some statistics about genes are pre-computed and can be accessed through the
`/api/catalog/v1/statistics`
endpoint.
The ID is constructed with the following format:
`<statisctics-type>-<gene_source>-<method>-<options>`
.
----
## Run the application
...
...
backend/metagenedb/apps/catalog/management/commands/compute_stats.py
View file @
6a851eb1
...
...
@@ -39,15 +39,19 @@ class ComputeCounts(ComputeStatistics):
FUNCTION_SOURCES
=
[
'kegg'
,
'eggnog'
]
GENE_SOURCES
=
[
'all'
,
'igc'
,
'virgo'
]
def
compute_count
(
self
,
method
,
filters
=
None
,
**
kwargs
):
def
compute_count
(
self
,
method
,
gene_source
,
filters
=
None
,
**
kwargs
):
if
filters
is
None
:
filters
=
{}
gene_stats
=
GeneStatistics
(
filters
=
filters
)
print_kwargs
=
'_'
.
join
([
str
(
k
)
+
'-'
+
str
(
v
)
for
k
,
v
in
kwargs
.
items
()
if
v
])
print_filters
=
'_'
.
join
([
str
(
k
)
+
'-'
+
str
(
v
)
for
k
,
v
in
filters
.
items
()
if
v
])
logger
.
info
(
"Call GeneStatistics(%s).%s(%s)"
,
print_filters
,
method
,
print_kwargs
)
print_kwargs
=
'-'
.
join
([
str
(
k
)
+
'-'
+
str
(
v
)
for
k
,
v
in
kwargs
.
items
()
if
v
])
print_filters
=
'-'
.
join
([
str
(
k
)
+
'-'
+
str
(
v
)
for
k
,
v
in
filters
.
items
()
if
v
])
stats_id
=
slugify
(
f
"GeneStatistics(
{
gene_source
}
).
{
method
}
(
{
print_kwargs
}
)"
)
logger
.
info
(
"Call GeneStatistics(%s).%s(%s) and saving under id <%s>"
,
print_filters
,
method
,
print_kwargs
,
stats_id
)
payload
=
{
'stats_id'
:
s
lugify
(
f
"GeneStatistics(
{
print_filters
}
).
{
method
}
(
{
print_kwargs
}
)"
)
,
'stats_id'
:
s
tats_id
,
'body'
:
{
'count'
:
getattr
(
gene_stats
,
method
)(
**
kwargs
)
}
...
...
@@ -61,9 +65,9 @@ class ComputeCounts(ComputeStatistics):
else
:
filters
=
{
'source'
:
gene_source
}
for
method
in
self
.
METHODS
:
self
.
compute_count
(
method
,
filters
=
filters
)
self
.
compute_count
(
method
,
gene_source
,
filters
=
filters
)
for
source
in
self
.
FUNCTION_SOURCES
:
self
.
compute_count
(
'count_has_function'
,
filters
=
filters
,
source
=
source
)
self
.
compute_count
(
'count_has_function'
,
gene_source
,
filters
=
filters
,
source
=
source
)
class
ComputeGeneLength
(
ComputeStatistics
):
...
...
@@ -82,20 +86,34 @@ class ComputeGeneLength(ComputeStatistics):
'functions__isnull'
:
False
},
}
GENE_SOURCES
=
[
'all'
,
'igc'
,
'virgo'
]
def
_compute_gene_length
(
self
,
filters
,
category
,
gene_source
):
gene_stats
=
GeneLengthDistribution
(
window_size
=
self
.
MIN_WINDOW_SIZE
,
stop_at
=
self
.
MAX_STOP_AT
,
filters
=
filters
)
for
window_size
in
self
.
WINDOW_SIZES
:
for
stop_at
in
self
.
STOP_ATS
:
stats_id
=
slugify
(
f
"GeneStatistics(
{
gene_source
}
).gene-length-
{
window_size
}
-
{
stop_at
}
-
{
category
}
"
)
logger
.
info
(
"Call GeneStatistics.gene_length(%s, %s) for %s and saving under id <%s>"
,
window_size
,
stop_at
,
category
,
stats_id
)
payload
=
{
'stats_id'
:
stats_id
,
'body'
:
gene_stats
.
get_distribution
(
window_size
=
window_size
,
stop_at
=
stop_at
)
}
self
.
_save_to_db
(
payload
)
def
all
(
self
):
for
category
,
filters
in
self
.
CATEGORIES
.
items
():
gene_stats
=
GeneLengthDistribution
(
window_size
=
self
.
MIN_WINDOW_SIZE
,
stop_at
=
self
.
MAX_STOP_AT
,
filters
=
filters
)
for
window_size
in
self
.
WINDOW_SIZES
:
for
stop_at
in
self
.
STOP_ATS
:
logger
.
info
(
"Call GeneStatistics.gene_length(%s, %s) for %s"
,
window_size
,
stop_at
,
category
)
payload
=
{
'stats_id'
:
slugify
(
f
"GeneStatistics.gene_length-
{
window_size
}
-
{
stop_at
}
-
{
category
}
"
),
'body'
:
gene_stats
.
get_distribution
(
window_size
=
window_size
,
stop_at
=
stop_at
)
}
self
.
_save_to_db
(
payload
)
for
gene_source
in
self
.
GENE_SOURCES
:
if
gene_source
==
'all'
:
filters
=
{}
else
:
filters
=
{
'source'
:
gene_source
}
for
category
,
cat_filters
in
self
.
CATEGORIES
.
items
():
if
cat_filters
is
not
None
:
filters
.
update
(
**
cat_filters
)
self
.
_compute_gene_length
(
filters
,
category
,
gene_source
)
class
ComputeTaxonomyRepartition
(
ComputeStatistics
):
...
...
frontend/src/router.js
View file @
6a851eb1
...
...
@@ -4,7 +4,7 @@ import Router from 'vue-router';
import
Home
from
'
@/views/Home.vue
'
;
import
GeneDetail
from
'
@/views/GeneDetail.vue
'
;
import
Genes
from
'
@/views/genes/genes.vue
'
;
import
Catalogstats
from
'
@/views/
S
tats.vue
'
;
import
Catalogstats
from
'
@/views/
stats/s
tats.vue
'
;
Vue
.
use
(
Router
);
...
...
frontend/src/views/Stats.vue
deleted
100644 → 0
View file @
8ac32cc0
<
template
>
<div
class=
"stats"
>
<v-flex>
<v-toolbar
class=
"secondary darken-1 white--text"
dense
>
<v-icon
class=
"white--text"
>
far fa-chart-bar
</v-icon>
<v-toolbar-title>
Catalog Statistics
</v-toolbar-title>
</v-toolbar>
<v-card>
<v-container
fluid
grid-list-md
>
<v-layout
row
wrap
>
<countcard
:count=
"geneCountAll"
></countcard>
<countcard
:count=
"geneCountFunctions"
></countcard>
<countcard
:count=
"geneCountEggnogs"
></countcard>
<countcard
:count=
"geneCountKeggs"
></countcard>
<countcard
:count=
"geneCountTaxo"
></countcard>
<countcard
:count=
"geneCountFull"
></countcard>
</v-layout>
<v-layout
row
wrap
class=
"mt-2"
>
<!-- Histogram -->
<v-flex
md12
xl6
>
<v-toolbar
class=
"primary lighten-1"
dark
dense
>
<v-icon
class=
"white--text"
>
far fa-chart-bar
</v-icon>
<v-toolbar-title>
Gene length distribution
</v-toolbar-title>
<v-spacer></v-spacer>
<v-flex
xs4
md2
xl3
class=
"mt-3"
>
<v-slider
v-model=
"geneLengthWindowSize"
@
change=
"getAllGeneLength"
thumb-label
color=
"secondary lighten-2"
thumb-color=
"secondary lighten-1"
step=
"100"
min=
"100"
max=
200
always-dirty
label=
"Window size (bp):"
></v-slider>
</v-flex>
<v-flex
xs4
md2
xl3
class=
"mt-3 ml-4"
>
<v-slider
v-model=
"stopAt"
@
change=
"getAllGeneLength"
thumb-label
color=
"secondary lighten-2"
thumb-color=
"secondary lighten-1"
step=
"1000"
min=
"1000"
max=
5000
ticks
always-dirty
label=
"Stop at (bp):"
></v-slider>
</v-flex>
</v-toolbar>
<histogram
:histoData=
"geneLengthData"
:requestStatus=
"geneLengthRequestDone"
chartId=
"histo_gene_length"
></histogram>
</v-flex>
<!-- Doughnut -->
<v-flex
md12
xl6
>
<v-toolbar
class=
"taxonomy"
dark
dense
>
<v-icon
class=
"white--text"
>
fa-sitemap
</v-icon>
<v-toolbar-title>
Taxonomical annotation
</v-toolbar-title>
<v-spacer></v-spacer>
<v-flex
xs3
md2
>
<v-select
:items=
"selectLevel"
v-model=
"taxLevel"
color=
"taxonomy ligthen-1"
@
change=
"getTaxoCounts"
></v-select>
</v-flex>
</v-toolbar>
<doughnut
:doughnutData=
"taxoCounts"
chartId=
"taxo_annotation"
></doughnut>
</v-flex>
</v-layout>
</v-container>
</v-card>
</v-flex>
</div>
</
template
>
<
script
>
import
axios
from
'
axios
'
;
import
Histogram
from
'
@/components/Histogram.vue
'
;
import
CountCard
from
'
@/components/CountCard.vue
'
;
import
Doughnut
from
'
@/components/Doughnut.vue
'
;
export
default
{
name
:
'
home
'
,
data
()
{
return
{
// Gene length data
geneLengthRequestDone
:
false
,
geneLengthLabels
:
[],
geneLengthAll
:
{},
geneLengthFunctions
:
{},
geneLengthKegg
:
{},
geneLengthEggnog
:
{},
geneLengthTaxonomy
:
{},
geneLengthFull
:
{},
geneLengthWindowSize
:
200
,
stopAt
:
4000
,
// Gene counts data
geneCountAll
:
{},
geneCountFunctions
:
{},
geneCountKeggs
:
{},
geneCountEggnogs
:
{},
geneCountTaxo
:
{},
geneCountFull
:
{},
// Taxonomy repartition
taxoCounts
:
{},
taxLevel
:
'
phylum
'
,
};
},
computed
:
{
selectLevel
()
{
return
[
'
kingdom
'
,
'
superkingdom
'
,
'
phylum
'
,
'
class
'
,
'
order
'
,
'
family
'
,
'
genus
'
];
},
geneLengthData
()
{
return
{
labels
:
this
.
geneLengthLabels
,
datasets
:
[
this
.
geneLengthAll
,
this
.
geneLengthFunctions
,
this
.
geneLengthEggnog
,
this
.
geneLengthKegg
,
this
.
geneLengthTaxonomy
,
this
.
geneLengthFull
,
],
};
},
},
mounted
()
{
this
.
getAllGeneLength
();
this
.
getGeneCountsAll
();
this
.
getGeneCountsFunctions
();
this
.
getGeneCountsKeggs
();
this
.
getGeneCountsEggnogs
();
this
.
getGeneCountsTaxo
();
this
.
getGeneCountsFull
();
this
.
getTaxoCounts
();
},
methods
:
{
getGeneLength
()
{
axios
.
get
(
`/api/catalog/v1/statistics/genestatistics-gene-length-
${
this
.
geneLengthWindowSize
}
-
${
this
.
stopAt
}
-all`
,
{
headers
:
{
Accept
:
'
application/json
'
,
},
})
.
then
((
response
)
=>
{
this
.
geneLengthLabels
=
response
.
data
.
body
.
labels
;
this
.
geneLengthAll
=
{
data
:
response
.
data
.
body
.
counts
,
label
:
'
All
'
,
backgroundColor
:
this
.
$vuetify
.
theme
.
primary
,
};
this
.
geneLengthRequestDone
=
true
;
})
.
catch
((
error
)
=>
{
this
.
geneLengthLabels
=
[];
this
.
geneLengthAll
=
{};
console
.
error
(
error
);
this
.
geneLengthRequestDone
=
true
;
});
},
getGeneLengthWithFunctions
()
{
axios
.
get
(
`/api/catalog/v1/statistics/genestatistics-gene-length-
${
this
.
geneLengthWindowSize
}
-
${
this
.
stopAt
}
-with-functions`
,
{
headers
:
{
Accept
:
'
application/json
'
,
},
})
.
then
((
response
)
=>
{
this
.
geneLengthLabels
=
response
.
data
.
body
.
labels
;
this
.
geneLengthFunctions
=
{
data
:
response
.
data
.
body
.
counts
,
label
:
'
Functions
'
,
backgroundColor
:
this
.
$vuetify
.
theme
.
function
,
};
})
.
catch
((
error
)
=>
{
console
.
error
(
error
);
});
},
getGeneLengthWithKEGG
()
{
axios
.
get
(
`/api/catalog/v1/statistics/genestatistics-gene-length-
${
this
.
geneLengthWindowSize
}
-
${
this
.
stopAt
}
-with-kegg`
,
{
headers
:
{
Accept
:
'
application/json
'
,
},
})
.
then
((
response
)
=>
{
this
.
geneLengthLabels
=
response
.
data
.
body
.
labels
;
this
.
geneLengthKegg
=
{
data
:
response
.
data
.
body
.
counts
,
label
:
'
KEGG
'
,
backgroundColor
:
this
.
$vuetify
.
theme
.
kegg
,
};
})
.
catch
((
error
)
=>
{
console
.
error
(
error
);
});
},
getGeneLengthWithEggNOG
()
{
axios
.
get
(
`/api/catalog/v1/statistics/genestatistics-gene-length-
${
this
.
geneLengthWindowSize
}
-
${
this
.
stopAt
}
-with-eggnog`
,
{
headers
:
{
Accept
:
'
application/json
'
,
},
})
.
then
((
response
)
=>
{
this
.
geneLengthLabels
=
response
.
data
.
body
.
labels
;
this
.
geneLengthEggnog
=
{
data
:
response
.
data
.
body
.
counts
,
label
:
'
EggNOG
'
,
backgroundColor
:
this
.
$vuetify
.
theme
.
eggnog
,
};
})
.
catch
((
error
)
=>
{
console
.
error
(
error
);
});
},
getGeneLengthWithTaxonomy
()
{
axios
.
get
(
`/api/catalog/v1/statistics/genestatistics-gene-length-
${
this
.
geneLengthWindowSize
}
-
${
this
.
stopAt
}
-with-taxonomy`
,
{
headers
:
{
Accept
:
'
application/json
'
,
},
})
.
then
((
response
)
=>
{
this
.
geneLengthLabels
=
response
.
data
.
body
.
labels
;
this
.
geneLengthTaxonomy
=
{
data
:
response
.
data
.
body
.
counts
,
label
:
'
Taxonomy
'
,
backgroundColor
:
this
.
$vuetify
.
theme
.
taxonomy
,
};
})
.
catch
((
error
)
=>
{
console
.
error
(
error
);
});
},
getGeneLengthWithFunctionsAndTaxonomy
()
{
axios
.
get
(
`/api/catalog/v1/statistics/genestatistics-gene-length-
${
this
.
geneLengthWindowSize
}
-
${
this
.
stopAt
}
-with-function-tax`
,
{
headers
:
{
Accept
:
'
application/json
'
,
},
})
.
then
((
response
)
=>
{
this
.
geneLengthLabels
=
response
.
data
.
body
.
labels
;
this
.
geneLengthFull
=
{
data
:
response
.
data
.
body
.
counts
,
label
:
'
Full
'
,
backgroundColor
:
this
.
$vuetify
.
theme
.
tertiary
,
};
})
.
catch
((
error
)
=>
{
console
.
error
(
error
);
});
},
getAllGeneLength
()
{
this
.
geneLengthDatasets
=
{};
this
.
getGeneLength
();
this
.
getGeneLengthWithFunctions
();
this
.
getGeneLengthWithKEGG
();
this
.
getGeneLengthWithEggNOG
();
this
.
getGeneLengthWithTaxonomy
();
this
.
getGeneLengthWithFunctionsAndTaxonomy
();
},
getGeneCountsAll
()
{
axios
.
get
(
'
/api/catalog/v1/statistics/genestatistics-count-all
'
,
{
headers
:
{
Accept
:
'
application/json
'
,
},
})
.
then
((
response
)
=>
{
this
.
geneCountAll
=
{
class
:
'
primary
'
,
icon
:
'
bar_chart
'
,
text
:
response
.
data
.
body
.
count
,
title
:
'
Genes
'
,
};
})
.
catch
((
error
)
=>
{
console
.
error
(
error
);
});
},
getGeneCountsFunctions
()
{
axios
.
get
(
'
/api/catalog/v1/statistics/genestatistics-count-has-function
'
,
{
headers
:
{
Accept
:
'
application/json
'
,
},
})
.
then
((
response
)
=>
{
this
.
geneCountFunctions
=
{
class
:
'
function darken-1
'
,
icon
:
'
bar_chart
'
,
text
:
response
.
data
.
body
.
count
,
title
:
'
Functions
'
,
};
})
.
catch
((
error
)
=>
{
console
.
error
(
error
);
});
},
getGeneCountsKeggs
()
{
axios
.
get
(
'
/api/catalog/v1/statistics/genestatistics-count-has-function-source-kegg
'
,
{
headers
:
{
Accept
:
'
application/json
'
,
},
})
.
then
((
response
)
=>
{
this
.
geneCountKeggs
=
{
class
:
'
kegg
'
,
icon
:
'
bar_chart
'
,
text
:
response
.
data
.
body
.
count
,
title
:
'
KEGG
'
,
};
})
.
catch
((
error
)
=>
{
console
.
error
(
error
);
});
},
getGeneCountsEggnogs
()
{
axios
.
get
(
'
/api/catalog/v1/statistics/genestatistics-count-has-function-source-eggnog
'
,
{
headers
:
{
Accept
:
'
application/json
'
,
},
})
.
then
((
response
)
=>
{
this
.
geneCountEggnogs
=
{
class
:
'
eggnog darken-1
'
,
icon
:
'
bar_chart
'
,
text
:
response
.
data
.
body
.
count
,
title
:
'
EggNOG
'
,
};
})
.
catch
((
error
)
=>
{
console
.
error
(
error
);
});
},
getGeneCountsTaxo
()
{
axios
.
get
(
'
/api/catalog/v1/statistics/genestatistics-count-has-taxonomy
'
,
{
headers
:
{
Accept
:
'
application/json
'
,
},
})
.
then
((
response
)
=>
{
this
.
geneCountTaxo
=
{
class
:
'
taxonomy darken-1
'
,
icon
:
'
bar_chart
'
,
text
:
response
.
data
.
body
.
count
,
title
:
'
Taxonomy
'
,
};
})
.
catch
((
error
)
=>
{
console
.
error
(
error
);
});
},
getGeneCountsFull
()
{
axios
.
get
(
'
/api/catalog/v1/statistics/genestatistics-count-has-function-has-taxonomy
'
,
{
headers
:
{
Accept
:
'
application/json
'
,
},
})
.
then
((
response
)
=>
{
this
.
geneCountFull
=
{
class
:
'
tertiary
'
,
icon
:
'
bar_chart
'
,
text
:
response
.
data
.
body
.
count
,
title
:
'
Full
'
,
};
})
.
catch
((
error
)
=>
{
console
.
error
(
error
);
});
},
getTaxoCounts
()
{
axios
.
get
(
`/api/catalog/v1/statistics/genestatistics-taxonomy-repartition-
${
this
.
taxLevel
}
`
,
{
headers
:
{
Accept
:
'
application/json
'
,
},
})
.
then
((
response
)
=>
{
const
chartId
=
`taxo_distri_
${
this
.
taxLevel
}
`
;
this
.
taxoCounts
=
{
data
:
response
.
data
.
body
.
counts
,
labels
:
response
.
data
.
body
.
labels
,
colors
:
response
.
data
.
body
.
colors
,
level
:
this
.
taxLevel
,
chartId
,
};
})
.
catch
((
error
)
=>
{
console
.
error
(
error
);
});
},
},
components
:
{
histogram
:
Histogram
,
countcard
:
CountCard
,
doughnut
:
Doughnut
,
},
};
</
script
>
frontend/src/views/stats/stats.html
0 → 100644
View file @
6a851eb1
<div
class=
"stats"
>
<v-flex>
<v-toolbar
class=
"secondary darken-1 white--text"
dense
>
<v-icon
class=
"white--text"
>
far fa-chart-bar
</v-icon>
<v-toolbar-title>
Catalog Statistics
</v-toolbar-title>
<v-spacer/>
<v-flex
xs12
sm6
md4
lg2
d-flex
>
<v-select
dark
:items=
"geneSources"
v-model=
"geneSource"
@
change=
"getAllStats"
></v-select>
</v-flex>
</v-toolbar>
<v-card>
<v-container
fluid
grid-list-md
>
<v-layout
row
wrap
>
<countcard
:count=
"geneCountAll"
></countcard>
<countcard
:count=
"geneCountFunctions"
></countcard>
<countcard
:count=
"geneCountEggnogs"
></countcard>
<countcard
:count=
"geneCountKeggs"
></countcard>
<countcard
:count=
"geneCountTaxo"
></countcard>
<countcard
:count=
"geneCountFull"
></countcard>
</v-layout>
<v-layout
row
wrap
class=
"mt-2"
>
<!-- Histogram -->
<v-flex
md12
xl6
>
<v-toolbar
class=
"primary lighten-1"
dark
dense
>
<v-icon
class=
"white--text"
>
far fa-chart-bar
</v-icon>
<v-toolbar-title>
Gene length distribution
</v-toolbar-title>
<v-spacer></v-spacer>
<v-flex
xs4
md2
xl3
class=
"mt-3"
>
<v-slider
v-model=
"geneLengthWindowSize"
@
change=
"getAllGeneLength"
thumb-label
color=
"secondary lighten-2"
thumb-color=
"secondary lighten-1"
step=
"100"
min=
"100"
max=
200
always-dirty
label=
"Window size (bp):"
></v-slider>
</v-flex>
<v-flex
xs4
md2
xl3
class=
"mt-3 ml-4"
>
<v-slider
v-model=
"stopAt"
@
change=
"getAllGeneLength"
thumb-label
color=
"secondary lighten-2"
thumb-color=
"secondary lighten-1"
step=
"1000"
min=
"1000"
max=
5000
ticks
always-dirty
label=
"Stop at (bp):"
></v-slider>
</v-flex>
</v-toolbar>
<histogram
:histoData=
"geneLengthData"
:requestStatus=
"geneLengthRequestDone"
chartId=
"histo_gene_length"
></histogram>
</v-flex>
<!-- Doughnut -->
<v-flex
md12
xl6
>
<v-toolbar
class=
"taxonomy"
dark
dense
>
<v-icon
class=
"white--text"
>
fa-sitemap
</v-icon>
<v-toolbar-title>
Taxonomical annotation
</v-toolbar-title>
<v-spacer></v-spacer>
<v-flex
xs3
md2
>
<v-select
:items=
"selectLevel"