Commit 1bcbca8c authored by Kenzo-Hugo Hillion's avatar Kenzo-Hugo Hillion
Browse files

add filtering to gene list

parent 1c69e764
Pipeline #21543 passed with stages
in 2 minutes and 42 seconds
from django_filters import rest_framework as filters
from metagenedb.apps.catalog.models import Gene
from metagenedb.apps.catalog.models import Gene, Taxonomy
class GeneFilter(filters.FilterSet):
no_taxonomy = filters.BooleanFilter(field_name='taxonomy', lookup_expr="isnull")
no_functions = filters.BooleanFilter(field_name='functions', lookup_expr="isnull")
has_taxonomy = filters.BooleanFilter(
field_name='taxonomy', lookup_expr="isnull", exclude=True
)
has_functions = filters.BooleanFilter(
field_name='functions', lookup_expr="isnull", distinct=True, exclude=True
)
taxonomy_rank = filters.ChoiceFilter(
choices=Taxonomy.RANK_CHOICES, field_name='taxonomy__rank'
)
name = filters.CharFilter(
field_name='name', lookup_expr='icontains'
)
length__gt = filters.NumberFilter(
field_name='length', lookup_expr='gt'
)
length__lt = filters.NumberFilter(
field_name='length', lookup_expr='lt'
)
class Meta:
model = Gene
fields = ['taxonomy', 'functions']
fields = ['taxonomy', 'functions', 'length', 'name']
......@@ -4,5 +4,10 @@ from metagenedb.common.django_default.qparams_validators import PaginatedQueryPa
class GeneQueryParams(PaginatedQueryParams):
no_taxonomy = fields.Boolean()
no_functions = fields.Boolean()
has_taxonomy = fields.Boolean()
has_functions = fields.Boolean()
length = fields.Integer()
length__gt = fields.Integer()
length__lt = fields.Integer()
name = fields.String()
taxonomy_rank = fields.String()
......@@ -12,9 +12,3 @@ class GeneViewSet(BulkViewSet):
filterset_class = GeneFilter
query_params_parser = GeneQueryParams
lookup_field = 'gene_id'
GENE_LENGTH_COL = 'length'
DEFAULT_WINDOW_SIZE = 1000
DEFAULT_STOP_AT = 10000
DEFAULT_LEVEL = 'phylum'
......@@ -9,7 +9,7 @@ class SimpleTaxonomySerializer(serializers.ModelSerializer):
class Meta:
model = Taxonomy
fields = ('tax_id', 'name')
fields = ('tax_id', 'name', 'rank')
class TaxonomyHierarchySerializer(serializers.ModelSerializer):
......
......@@ -10,11 +10,88 @@
<v-icon class="white--text">format_list_bulleted</v-icon>
<v-toolbar-title>Catalog content</v-toolbar-title>
</v-toolbar>
<v-list>
<v-subheader>
<p><span class="badge badge-secondary"> {{ count }} </span> genes in the calalog.</p>
</v-subheader>
<!-- Filters -->
<v-expansion-panel>
<v-expansion-panel-content class="grey lighten-2">
<template v-slot:header>
<div>Show Filters</div>
</template>
<v-card class="grey lighten-3">
<v-card-text class="ma-0">
<v-layout wrap align-center>
<v-flex xs12 sm6 md4 lg2 d-flex>
<v-select
:items="taxonomy_ranks"
v-model="taxonomy_rank"
label="Taxonomy rank"
></v-select>
</v-flex>
<v-flex class="ml-4">
<v-switch
v-model="filterGeneLength"
label="Filter on gene length"
></v-switch>
</v-flex>
<v-flex
shrink
style="width: 60px"
v-if="filterGeneLength"
>
<v-text-field
v-model="geneLengthFilterRange[0]"
class="mt-0"
hide-details
single-line
type="number"
></v-text-field>
</v-flex>
<v-flex class="mx-4" v-if="filterGeneLength">
<v-range-slider
v-model="geneLengthFilterRange"
:max="maxGeneLength"
:min="minGeneLength"
></v-range-slider>
</v-flex>
<v-flex
shrink
style="width: 60px"
v-if="filterGeneLength"
>
<v-text-field
v-model="geneLengthFilterRange[1]"
class="mt-0"
hide-details
single-line
type="number"
></v-text-field>
</v-flex>
<v-spacer></v-spacer>
<v-btn
color="deep-orange lighten-1 white--text"
@click="emptyFilters"
>
Clear<v-icon right>far fa-window-close</v-icon>
</v-btn>
<v-btn
color="secondary lighten-1"
@click="applyFilters"
>
Apply<v-icon right>far fa-check-square</v-icon>
</v-btn>
</v-layout>
</v-card-text>
</v-card>
</v-expansion-panel-content>
</v-expansion-panel>
<!-- Table -->
<v-card class="text-xs-center" v-if="!requestDone">
<v-progress-circular
indeterminate
color="secondary"
class="ma-2"
></v-progress-circular>
</v-card>
<v-list v-else>
<v-data-table
:rows-per-page-items="rowsPerPageItems"
:pagination.sync="pagination"
......@@ -24,12 +101,7 @@
>
<template v-slot:items="props">
<td>
{{ props.item.gene_id }}
<v-btn :to="/gene-detail/ + props.item.gene_id" icon flat small target="_blank" class="primary--text mt-1 ml-0">
<v-icon small>
open_in_new
</v-icon>
</v-btn>
<router-link :to="/gene-detail/ + props.item.gene_id">{{ props.item.gene_id }}</router-link>
</td>
<td>{{ props.item.name }}</td>
<td class="text-xs">{{ props.item.length }}</td>
......@@ -53,6 +125,9 @@
</template>
</v-data-table>
</v-list>
<v-card class="white" flat>
<v-subheader class="text-right">{{count}} genes found</v-subheader>
</v-card>
</v-flex>
</v-layout>
</v-container>
......@@ -69,33 +144,52 @@ export default {
genes: [],
count: 0,
page: 1,
rowsPerPageItems: [25],
page_size: 20,
pagination: {
rowsPerPage: 25
rowsPerPage: 20
},
taxonomy_rank: null,
requestDone: false,
filterGeneLength: false,
geneLengthFilterRange:[0, 2000]
};
},
computed: {
headers() {
return [
{
text: 'Gene ID',
align: 'left',
sortable: false,
value: 'name',
},
{
text: 'Gene name',
align: 'left',
sortable: false,
value: 'name',
},
{ text: 'Length', value: 'length' },
{ text: 'Gene ID', align: 'left', sortable: false, value: 'name'},
{ text: 'Gene name', align: 'left', sortable: false, value: 'name'},
{ text: 'Length', value: 'length', sortable: false},
{ text: 'Taxonomy', value: 'taxonomy', sortable: false },
{ text: 'KEGG', value: 'kegg', sortable: false },
{ text: 'EggNOG', value: 'eggnog', sortable: false },
];
},
taxonomy_ranks() {
return [
'Phylum', 'Genus'
];
},
rowsPerPageItems() {
return [this.page_size];
},
qParams() {
var qParams = {page_size: this.page_size}
if (this.taxonomy_rank) {
qParams.taxonomy_rank = this.taxonomy_rank.toLowerCase()
}
if (this.filterGeneLength) {
qParams.length__gt = this.geneLengthFilterRange[0];
qParams.length__lt = this.geneLengthFilterRange[1];
}
return qParams;
},
maxGeneLength() {
return 5000;
},
minGeneLength() {
return 0;
}
},
mounted() {
this.getGenes();
......@@ -103,9 +197,7 @@ export default {
methods: {
getGenes() {
axios.get('/api/catalog/v1/genes', {
params: {
page_size: 25
},
params: this.qParams,
headers: {
Accept: 'application/json',
},
......@@ -117,7 +209,7 @@ export default {
genes.forEach(function (item, index) {
if (item.taxonomy) {
item.tax_url = ncbi_tax_url + item.taxonomy.name;
item.taxonomy = item.taxonomy.name;
item.taxonomy = item.taxonomy.name + " (" + item.taxonomy.rank + ')';
};
if (item.functions) {
var functions = item.functions;
......@@ -134,10 +226,20 @@ export default {
});
this.genes = genes;
this.count = response.data.count;
this.requestDone = true;
})
.catch((error) => {
console.log(error);
});
},
emptyFilters(){
this.taxonomy_rank = null;
this.filterGeneLength = false;
this.geneLengthFilterRange = [0, 2000];
},
applyFilters(){
this.requestDone = false;
this.getGenes();
}
},
};
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment