Skip to content

Commit

Permalink
fix bugs and add INSDC bioproject management/annotations retrieval
Browse files Browse the repository at this point in the history
  • Loading branch information
emiliorighi committed May 18, 2022
1 parent 3ec435d commit 665d9bf
Show file tree
Hide file tree
Showing 31 changed files with 354 additions and 299 deletions.
21 changes: 9 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,17 @@ This project aims to provide an easy way to show biodiversity within a geographi

Species are created from samples representing the physical or genetic entity of the species.

The samples can be inserted locally via excel (following the format of the ERGA manifest) or via form.¡
The samples can be inserted locally via excel (following the format of the ERGA manifest) or via form.

This project offers additional services for sequencing projects:
This project offers additional services for sequencing projects (under the Earth Biogenome scope):

* cronjob to collect public information related to the project (genomic data)
* cronjob to collect INSDC data related to the project (genomic data): assemblies, reads, samples metadata and taxonomy.
* export of an excel file containing locally inserted samples to submit to COPO(https://copo-project.org/)


IMPORTANT:
This project uses the metadata of the ERGA manifesto (https://github.com/ERGA-consortium/COPO-manifest) and is mainly intended to retrieve data from BioSamples(https://www.ebi.ac.uk/biosamples) for samples metadata and ENA (https://www.ebi.ac.uk/ena/browser/home) for reads and assemblies. For specific project needs you can open an issue.
This project uses the metadata of the ERGA manifest (https://github.com/ERGA-consortium/COPO-manifest) and is mainly intended to retrieve data from BioSamples(https://www.ebi.ac.uk/biosamples) for samples metadata and ENA (https://www.ebi.ac.uk/ena/browser/home) for reads and assemblies. For specific project needs you can open an issue.

Use the `BLANK_README.md` to get started.

<p align="right">(<a href="#top">back to top</a>)</p>

Expand Down Expand Up @@ -97,18 +96,16 @@ The .env file contains many parts that have to be configured depending on the ne
RESTKEY=secretPassword #change this in production!! --> password that will be inserted to access the admin area

The CRONJOB part:
Configure this part if you want to retrieve public data from ENA/BioSamples and/or NCBI (the sample metadata format must be compliant with the ENA checklist)
the cronjob will automatically check for read data in ENA if PROJECTS and/or PROJECT_ACCESSION are present
Configure this part if you want to retrieve public data from ENA/BioSamples and/or NCBI (the sample metadata format must be compliant with the ENA checklist).
The cronjob will automatically check for read data in ENA if PROJECTS and/or PROJECT_ACCESSION are present
PROJECTS= --> list of projects (comma separated) wich name figures in the sample metadata submitted to the ENA/BioSamples
PROJECT_ACCESSION --> bioproject accession to retrieve data from NCBI
EXEC_TIME=600 --> how often, in seconds, the job should be performed

The DATA PORTAL part:
This part have some default values that can be modified

RANKS=--> ordered, descending list of taxonomic ranks you want to display. Note that is a rank is not present in the species' lineage it will be skipped, for instance you may find phylum nodes that has as a children class nodes.
MAX_NODES=90 --> number of max leaves to display in the tree of life page (numbers greaters than 150 may affect performance and visualization)

ROOT_NODE=the INSDC bioproject acccession which will be used as the root project of the application


To add a custom logo and an icon follow this steps:
Expand Down Expand Up @@ -154,7 +151,7 @@ Here is a list of the APIs consumed:


## Sequencing Project
For sequencing projects with the aim to sequence species within a geographical context, it is strongly recommended to submit public samples to the ENA via the [COPO web service](https://copo-project.org/), this service ensure that all the submitted samples share the same format before submission to ENA. It will, then, be responsibility of the single project to upload assemblies and reads to ENA/NCBI and associate them with the sample accession submitted through COPO.
For sequencing projects, it is strongly recommended to submit public samples to the ENA via the [COPO web service](https://copo-project.org/), this service ensure that all the submitted samples share the same format before submission to ENA(INSDC). It will, then, be responsibility of the single project to upload assemblies and reads to ENA/NCBI and associate them with the sample accession submitted through COPO.
To facilitate the sample submission to COPO this project provides the possibility to download the samples inserted locally in an excel compliant with the [ERGA submission manifest](https://github.com/ERGA-consortium/COPO-manifest). The generated excel will be then submitted to COPO. Once the samples will be pubblicly available in BioSamples the data portal will link the accession to the sample unique name and will start checking for new assemlies and/or reads every time the cronjob will be executed (the EXEC_TIME env variable).
IMPORTANT: the ERGA manifest will change during time, this portal will try to keep it up to date.

Expand All @@ -179,7 +176,7 @@ The import function uses the BioSamples API to retrieve samples metadata via the

- [ ] Add Changelog
- [ ] Add JSON schema (OAS docs)
- [ ] Add local names management
- [X] Add local names management
- [X] Add organism photo management
- [X] Add sample accession import feature
- [ ] Add custom fields management
Expand Down
1 change: 0 additions & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
"bootstrap-vue": "^2.21.2",
"d3": "^7.0.0",
"ol": "^6.10.0",
"swagger-ui": "^4.4.1",
"vue": "^2.6.14",
"vue-router": "^3.1.3",
"vuex": "^3.6.2",
Expand Down
8 changes: 2 additions & 6 deletions client/src/components/base/LastPublishedBanner.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
<template>
<div v-if="assembly.assembly_name">
<b-button @click="show = !show" pill variant="outline-success">See last imported assembly</b-button>
<b-collapse :visible="show" id="collapse-1" class="mt-2">
<b-card :title="assembly.assembly_name">
<b-card-text>
Created: {{recordDate}}
Expand All @@ -12,17 +10,15 @@
<b-card-text>
Sample Accession: <b-link :to="{name: 'sample-details', params:{accession:assembly.sample_accession}}">{{assembly.sample_accession}}</b-link>
</b-card-text>

</b-card>
</b-collapse>
</div>
</template>
<script>
import {BLink,BCard,BButton,BCollapse,BCardText} from 'bootstrap-vue'
import {BLink,BCard,BCardText} from 'bootstrap-vue'
import portalService from '../../services/DataPortalService'
export default {
components:{BLink,BCard,BButton,BCollapse,BCardText},
components:{BLink,BCard,BCardText},
data(){
return{
assembly:{},
Expand Down
34 changes: 34 additions & 0 deletions client/src/components/data/AnnotationsComponent.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<template>
<div ref="annotationsTable">
<table-component stacked :sticky-header="stickyHeader" :items="annotations">
<template #cell(pageURL)="data">
<b-link class="no-underline" target="_blank" :href="data.value">Genome browser</b-link>
</template>
<template #cell(gffGzLocation)="data">
<b-link class="no-underline" target="_blank" :href="data.value">GFF3</b-link>
</template>
<template #cell(tabIndexLocation)="data">
<b-link class="no-underline" target="_blank" :href="data.value">GFF3 (Tabix)</b-link>
</template>
<template #cell(targetGenome)="data">
<b-link class="no-underline" target="_blank" :href="'https://www.ebi.ac.uk/ena/browser/view/' + data.value">{{data.value}}</b-link>
</template>
<template #cell(annotationSource)="data">
<b-link class="no-underline" target="_blank" :href="data.value">{{data.value}}</b-link>
</template>
</table-component>
</div>
</template>

<script>
import {BLink} from 'bootstrap-vue'
import TableComponent from '../base/TableComponent.vue'
export default{
components: { TableComponent,BLink },
props: ['annotations'],
}
</script>
<style>
</style>
4 changes: 3 additions & 1 deletion client/src/components/modal/DataModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,18 @@
<experiments-component v-if="model === 'experiments'" :experiments="data"/>
<assemblies-component v-if="model === 'assemblies'" :assemblies="data"/>
<sample-component v-if="model === 'insdc_samples' || model === 'local_samples'" :samples="data" :name="organism"/>
<annotations-component v-if="model === 'annotations'" :annotations="data"/>
</b-modal>
</template>
<script>
import AnnotationsComponent from '../data/AnnotationsComponent.vue'
import AssembliesComponent from '../data/AssembliesComponent.vue'
import ExperimentsComponent from '../data/ExperimentsComponent.vue'
import SampleComponent from '../sample/SampleComponent.vue'
export default {
props: ['organism', 'model', 'data'],
components: {AssembliesComponent,ExperimentsComponent, SampleComponent},
components: {AssembliesComponent,ExperimentsComponent, SampleComponent, AnnotationsComponent},
computed: {
size(){
if (this.model === 'experiments'){
Expand Down
55 changes: 14 additions & 41 deletions client/src/components/organism/OrganismDetailsComponent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,31 @@
<b-col>
<b-tabs
content-class="mt-3" fill
v-model="tabIndex"
>
<b-tab :title-link-class="linkClass(0)" active class="tab-element" lazy>
<b-tab active class="tab-element" lazy>
<template #title>
<strong>Samples </strong><b-badge :variant="linkVariant(0)" pill>{{samples.length}}</b-badge>
<strong>Samples </strong><b-badge pill variant="primary">{{samples.length}}</b-badge>
</template>
<sample-component :name="organism.organism" :samples="samples"/>
</b-tab>
<b-tab :title-link-class="linkClass(1)" class="tab-element" v-if="organism.assemblies && organism.assemblies.length" lazy>
<b-tab class="tab-element" v-if="organism.assemblies && organism.assemblies.length" lazy>
<template #title>
<strong>Assemblies </strong><b-badge :variant="linkVariant(1)" pill>{{organism.assemblies.length}}</b-badge>
<strong>Assemblies </strong><b-badge pill variant="primary">{{organism.assemblies.length}}</b-badge>
</template>
<assemblies-component :assemblies="organism.assemblies"/>
</b-tab>
<b-tab :title-link-class="linkClass(expIndex)" class="tab-element" v-if="organism.experiments && organism.experiments.length" lazy>
<b-tab class="tab-element" v-if="organism.experiments && organism.experiments.length" lazy>
<template #title>
<strong>Experiments </strong><b-badge :variant="linkVariant(expIndex)" pill>{{organism.experiments.length}}</b-badge>
<strong>Experiments </strong><b-badge pill variant="primary">{{organism.experiments.length}}</b-badge>
</template>
<experiments-component :experiments="organism.experiments"/>
</b-tab>
<b-tab class="tab-element" v-if="organism.annotations && organism.annotations.length" lazy>
<template #title>
<strong>Annotations </strong><b-badge pill variant="primary">{{organism.annotations.length}}</b-badge>
</template>
<annotations-component :annotations="organism.annotations"/>
</b-tab>
</b-tabs>
</b-col>
</b-row>
Expand All @@ -33,46 +38,14 @@ import {BTabs,BTab,BBadge} from 'bootstrap-vue'
import ExperimentsComponent from '../data/ExperimentsComponent.vue'
import AssembliesComponent from '../data/AssembliesComponent.vue'
import SampleComponent from '../sample/SampleComponent.vue'
import AnnotationsComponent from '../data/AnnotationsComponent.vue'
export default {
components: {BTabs,ExperimentsComponent,BTab, BBadge, AssembliesComponent, SampleComponent},
components: {BTabs,ExperimentsComponent,BTab, BBadge, AssembliesComponent, SampleComponent, AnnotationsComponent},
props:['organism'],
computed:{
expIndex(){
if(this.haveItems(this.organism.assemblies)){
return 2
}
return 1
},
samples(){
return [...this.organism.insdc_samples, ...this.organism.local_samples]
}
},
data(){
return {
tabIndex:0,
mapKey: 0
}
},
methods: {
haveItems(arr){
return arr && arr.length > 0
},
linkClass(idx) {
if (this.tabIndex === idx) {
return ['bg-success', 'text-light']
}
else {
return ['bg-light', 'text-success']
}
},
linkVariant(idx){
if (this.tabIndex === idx) {
return 'light'
}
else {
return 'success'
}
}
}
}
Expand Down
10 changes: 6 additions & 4 deletions client/src/components/organism/OrganismFilterComponent.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<b-row>
<b-col lg="7">
<multi-select-component/>
<multi-select-component v-if="projectAccession"/>
</b-col>
<b-col lg="5">
<filter-component :options="options" :prependSelect="true"/>
Expand All @@ -21,7 +21,7 @@
Retrieve only selected data ex: retrieve <stong>only</stong> organisms with 'Submitted Samples' or <stong>only</stong> 'Submitted Samples' and 'Submitted Assemblies'
</b-tooltip>
<b-form-checkbox-group :options="checkboxOptions" v-model="selectedCheckboxes"/>
<b-icon-arrow-clockwise @mouseenter="animation='spin-pulse'" @mouseleave="animation=''" :animation="animation" font-scale="2" id="refresh-action" @click="resetFilters()"/>
<b-icon-arrow-clockwise variant="primary" @mouseenter="animation='spin-pulse'" @mouseleave="animation=''" :animation="animation" font-scale="2" id="refresh-action" @click="resetFilters()"/>
<b-tooltip target="refresh-action">
Refresh filters
</b-tooltip>
Expand All @@ -47,9 +47,11 @@ export default {
{text: 'Submitted samples', value: 'insdc_samples'},
{text: 'Submitted reads', value: 'experiments'},
{text: 'Submitted assemblies', value: 'assemblies'},
{text: 'Annotations', value: 'annotations'}
],
selectedCheckboxes:[],
animation:''
animation:'',
projectAccession: PROJECT_ACCESSION
}
},
computed: {
Expand Down Expand Up @@ -88,7 +90,7 @@ export default {
.then(response => {
const bioprojects = response.data.map(bp => { return {text: bp.title, value:bp.accession}})
//create append all to root_project
const root_project = bioprojects.find(el => el.value === PROJECT_ACCESSION)
const root_project = bioprojects.find(el => el.value === this.projectAccession)
const groupedChildren = {label: 'Children projects', options:bioprojects.filter(bp => bp.value !== root_project.value)}
if(groupedChildren){
this.bioprojects = [root_project, groupedChildren]
Expand Down
18 changes: 16 additions & 2 deletions client/src/components/organism/OrganismsComponent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,12 @@
<div class="badge-wrapper">
<b-badge href="#" pill style="cursor:pointer" v-if="data['item'].assemblies.length" @click.stop="getData(data['item'], 'assemblies')" variant="primary">{{data['item'].assemblies.length}}</b-badge>
</div>
</template>outline-success
</template>
<template #cell(annotations)="data">
<div class="badge-wrapper">
<b-badge href="#" pill style="cursor:pointer" v-if="data['item'].annotations.length" @click.stop="getData(data['item'], 'annotations')" variant="secondary">{{data['item'].annotations.length}}</b-badge>
</div>
</template>
<template #cell(experiments)="data">
<div class="badge-wrapper">
<b-badge href="#" v-if="data['item'].experiments.length" @click.stop="getData(data['item'], 'experiments')" pill variant="warning">{{data['item'].experiments.length}}</b-badge>
Expand Down Expand Up @@ -100,7 +105,7 @@ export default {
'option','taxName',
'totalRows','currentPage',
'insdc_samples','local_samples',
'experiments','assemblies'],
'experiments','assemblies','annotations'],
module: 'portal',
mutation: 'portal/setField'
}),
Expand Down Expand Up @@ -131,6 +136,7 @@ export default {
{key: 'insdc_samples', label: 'Submitted BioSamples'},
{key: 'experiments', label: 'Submitted Reads'},
{key: 'assemblies', label: 'Submitted Assemblies'},
{key: 'annotations', label: 'Annotations'}
],
selectedOrganisms:[],
Expand Down Expand Up @@ -169,6 +175,13 @@ export default {
this.fields.filter(f => f.key === 'experiments').forEach(f => f.variant = "")
}
},
annotations(value){
if (value){
this.fields.filter(f => f.key === 'annotations').forEach(f => f.variant = "secondary")
}else{
this.fields.filter(f => f.key === 'annotations').forEach(f => f.variant = "")
}
},
option(){
this.filter=''
}
Expand Down Expand Up @@ -239,6 +252,7 @@ export default {
local_samples: this.local_samples,
assemblies: this.assemblies,
experiments: this.experiments,
annotations: this.annotations,
option: this.option,
onlySelectedData: this.onlySelectedData,
bioproject:this.selectedBioproject
Expand Down
6 changes: 6 additions & 0 deletions client/src/components/sample/SampleComponent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
<template #cell(tube_or_well_id)="data">
<b-link v-if="data.value" :to="{name: 'sample-details', params: {accession: data.value}}">{{data.value}}</b-link>
</template>
<template #cell(bioprojects)="data">
<b-link target="_blank" v-for="bioproject in data.item.bioprojects" :key="bioproject" :href="'https://www.ebi.ac.uk/ena/browser/view/'+bioproject">
{{bioproject}}
</b-link>
</template>
<template #cell(organism_part)="data">
{{data.value? data.value : ''}}
</template>
Expand Down Expand Up @@ -51,6 +56,7 @@ export default {
{key: 'organism_part', label: 'Organism part'},
{key: 'sex', label: 'Sex'},
{key: 'GAL', label: 'GAL'},
],
stickyHeader: '60vh',
selectedSamples:[]
Expand Down
Loading

0 comments on commit 665d9bf

Please sign in to comment.