diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..dd9819f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+.DS_Store
+node_modules/
+docker/data/
\ No newline at end of file
diff --git a/README.md b/README.md
index 269748f..4111301 100644
--- a/README.md
+++ b/README.md
@@ -92,11 +92,10 @@ Example Track:
```
[tracks.GDC_Genes]
storeClass=gdc-viewer/Store/SeqFeature/Genes
-type=JBrowse/View/Track/CanvasVariants
+type=JBrowse/View/Track/GeneTrack
key=GDC Genes
metadata.datatype=Gene
unsafePopup=true
-fmtDetailValue_projects=function(value) { return "
Loading...
";}
```
You can apply filters to the track too, in the same format as GDC. The below example only shows Genes whose biotype is not 'protein_coding'.
@@ -115,11 +114,10 @@ Example Track:
```
[tracks.GDC_SSM]
storeClass=gdc-viewer/Store/SeqFeature/SimpleSomaticMutations
-type=gdc-viewer/View/Track/CanvasVariants
+type=gdc-viewer/View/Track/SSMVariants
key=GDC SSM
metadata.datatype=SSM
unsafePopup=true
-fmtDetailValue_projects=function(value) { return "Loading...
";}
```
You can apply filters to the track too, in the same format as GDC. The below example only shows SSMs whose reference allele is 'G'.
diff --git a/data/tracks.conf b/data/tracks.conf
index fd195ef..fd1c2f3 100644
--- a/data/tracks.conf
+++ b/data/tracks.conf
@@ -1,18 +1,16 @@
[tracks.GDC_SSM]
storeClass=gdc-viewer/Store/SeqFeature/SimpleSomaticMutations
-type=gdc-viewer/View/Track/CanvasVariants
+type=gdc-viewer/View/Track/SSMTrack
key=GDC SSM
metadata.datatype=SSM
unsafePopup=true
-fmtDetailValue_projects=function(value) { return "Loading...
";}
[tracks.GDC_Genes]
storeClass=gdc-viewer/Store/SeqFeature/Genes
-type=gdc-viewer/View/Track/CanvasVariants
+type=gdc-viewer/View/Track/GeneTrack
key=GDC Genes
metadata.datatype=Gene
unsafePopup=true
-fmtDetailValue_projects=function(value) { return "Loading...
";}
[tracks.GDC_CNV]
storeClass=gdc-viewer/Store/SeqFeature/CNVs
diff --git a/docker/Dockerfile b/docker/Dockerfile
new file mode 100644
index 0000000..1da64f6
--- /dev/null
+++ b/docker/Dockerfile
@@ -0,0 +1,35 @@
+FROM node:latest
+
+LABEL maintainer="andrew.duncan@oicr.on.ca"
+
+ENV JBROWSE_VERSION 1.16.6
+
+# Install dependencies
+RUN apt-get -qq update --fix-missing
+RUN apt-get --no-install-recommends -y install git build-essential zlib1g-dev libxml2-dev libexpat-dev postgresql-client libpq-dev ca-certificates curl
+
+# Download JBrowse
+RUN mkdir -p /jbrowse/ && \
+ git clone --recursive https://github.com/gmod/jbrowse /jbrowse/ && \
+ cd /jbrowse/ && \
+ git checkout ${JBROWSE_VERSION}-release
+
+WORKDIR /jbrowse/
+
+# Download GDC Viewer
+RUN git clone https://github.com/agduncan94/gdc-viewer /gdc-viewer/ && \
+ cd /gdc-viewer/ && \
+ git checkout 0.1.1 && \
+ cp -r gdc-viewer /jbrowse/plugins/gdc-viewer && \
+ cat ./data/jbrowse.conf > /jbrowse/jbrowse.conf
+
+# Setup JBrowse
+RUN ./setup.sh && \
+ ./bin/cpanm --force JSON Hash::Merge PerlIO::gzip Devel::Size \
+ Heap::Simple Heap::Simple::XS List::MoreUtils Exception::Class Test::Warn Bio::Perl \
+ Bio::DB::SeqFeature::Store File::Next Bio::DB::Das::Chado && \
+ rm -rf /root/.cpan/
+
+
+# Expose port 3000
+EXPOSE 3000
\ No newline at end of file
diff --git a/docker/README.md b/docker/README.md
new file mode 100644
index 0000000..c660332
--- /dev/null
+++ b/docker/README.md
@@ -0,0 +1,56 @@
+# Running JBrowse with GDC Plugin in Docker
+This will get JBrowse with the GDC Viewer Plugin running with Express on port 3000.
+
+Based on [enuggetry/docker-jbrowse](https://github.com/enuggetry/docker-jbrowse)
+
+## Build and Run from Dockerfile
+### Setup data
+*Important*: Place your track data in `./data`. This maps to `/jbrowse/data` in the container, which is where JBrowse stores reference data and track information.
+
+### Build the docker image
+`docker build . -t jbrowse-with-gdc`
+
+### Run the docker image
+`docker run -p 3000:3000 -v {pwd}/data:/jbrowse/data jbrowse-with-gdc utils/jb_run.js -p 3000`
+
+Note: You can run in the background using the detach mode (-d)
+
+`docker run -d -p 3000:3000 -v {pwd}/data:/jbrowse/data jbrowse-with-gdc utils/jb_run.js -p 3000`
+
+## Build and Run from Docker Compose
+You can also use Docker Compose to build the image. Ensure you are working in the same directory as the `docker-compose.yml`.
+
+### Build docker-compose
+`docker-compose build`
+
+### Run the docker-compose
+`docker-compose up`
+
+Note: You can run in the background using the detach mode (-d)
+
+`docker-compose up -d`
+
+## Load refseq and tracks
+If you already have your `tracks.conf` and `seq/`, etc., you can simply put these files into your `./data` directory.
+
+You will have to put the RefSeq data into the `./data` directory. Download the GRCh38 `.fa` and `.fa.fai` files online (ex. http://bioinfo.hpc.cam.ac.uk/downloads/datasets/fasta/grch38/). Then put the following in `./data/tracks.conf` (note files may be named something else).
+
+```
+refSeqs=GRCh38.genome.fa.fai
+
+[tracks.refseqs]
+urlTemplate=GRCh38.genome.fa
+```
+
+Now go to `localhost:3000` and you should see JBrowse with your refdata and tracks!
+
+### Enter the Docker Container
+You can enter the container by doing the following:
+
+```
+# Get container ID
+docker ps
+
+# Enter container
+docker exec -it /bin/bash
+```
\ No newline at end of file
diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml
new file mode 100644
index 0000000..66ad339
--- /dev/null
+++ b/docker/docker-compose.yml
@@ -0,0 +1,10 @@
+version: '3'
+services:
+ jbrowse:
+ build: .
+ command: utils/jb_run.js -p 3000
+ ports:
+ - "3000:3000"
+ volumes:
+ - ./data:/jbrowse/data
+
\ No newline at end of file
diff --git a/gdc-viewer/js/Model/GeneFeature.js b/gdc-viewer/js/Model/GeneFeature.js
index d526daf..aba995a 100644
--- a/gdc-viewer/js/Model/GeneFeature.js
+++ b/gdc-viewer/js/Model/GeneFeature.js
@@ -85,9 +85,9 @@ get: function(name) {
}).then(function(response) {
return(response.json());
}).then(function(response) {
- document.getElementById('projects-gdc-' + geneId).innerHTML = thisB.createProjectTable(response);
+ document.getElementsByClassName('value projects')[0].innerHTML = thisB.createProjectTable(response);
}).catch(function(err) {
- document.getElementById('projects-gdc-' + geneId).innerHTML = 'Error creating projects table';
+ document.getElementsByClassName('value projects')[0].innerHTML = 'Error creating projects table';
});
return geneId;
} else {
diff --git a/gdc-viewer/js/Model/SSMFeature.js b/gdc-viewer/js/Model/SSMFeature.js
index 3a175cd..26539e3 100644
--- a/gdc-viewer/js/Model/SSMFeature.js
+++ b/gdc-viewer/js/Model/SSMFeature.js
@@ -79,9 +79,9 @@ get: function(name) {
}).then(function(response) {
return(response.json());
}).then(function(response) {
- document.getElementById('projects-gdc-' + mutationId).innerHTML = thisB.createProjectTable(response);
+ document.getElementsByClassName('value projects')[0].innerHTML = thisB.createProjectTable(response);
}).catch(function(err) {
- document.getElementById('projects-gdc-' + mutationId).innerHTML = 'Error creating projects table';
+ document.getElementsByClassName('value projects')[0].innerHTML = 'Error creating projects table';
});
return mutationId;
} else {
diff --git a/gdc-viewer/js/Store/SeqFeature/CNVs.js b/gdc-viewer/js/Store/SeqFeature/CNVs.js
index 93f3538..6b3972a 100644
--- a/gdc-viewer/js/Store/SeqFeature/CNVs.js
+++ b/gdc-viewer/js/Store/SeqFeature/CNVs.js
@@ -78,7 +78,7 @@ function(
var bodyVal = JSON.stringify(thisB.createQuery(ref, start, end));
// Fetch CNVs and create features
- fetch(thisB.graphQLUrl, {
+ fetch(thisB.graphQLUrl + '/CNVsTable', {
method: 'post',
headers: { 'X-Requested-With': null },
body: bodyVal
diff --git a/gdc-viewer/js/View/Export/TrackConfig.js b/gdc-viewer/js/View/Export/TrackConfig.js
index 1d5f453..a83e483 100644
--- a/gdc-viewer/js/View/Export/TrackConfig.js
+++ b/gdc-viewer/js/View/Export/TrackConfig.js
@@ -16,22 +16,26 @@ return declare( ExportBase,
},
_printHeader: function() {
- var storeArray = (this.store.config.storeClass).split('/')
+ var storeArray = (this.store.config.type).split('/')
var trackArray = [
- '[tracks.' + this.store.config.label + ']',
- 'storeClass=' + this.store.config.storeClass,
+ '[tracks.' + this.track.labelHTML + ']',
+ 'storeClass=' + this.store.config.type,
'type=' + this.track.config.type,
- 'key=' + this.store.config.key,
+ 'key=' + this.track.key,
'metadata.datatype=' + storeArray[storeArray.length - 1],
- 'unsafePopup=true',
+ 'unsafePopup=true'
]
- if (this.store.config.storeClass === 'gdc-viewer/Store/SeqFeature/SimpleSomaticMutations' || this.store.config.storeClass === 'gdc-viewer/Store/SeqFeature/Genes') {
- trackArray.push('fmtDetailValue_projects=function(value) { return "Loading...
";}');
+ if (this.store.case) {
+ trackArray.push('case=' + this.store.case)
}
- if (this.store.config.storeClass === 'gdc-viewer/Store/SeqFeature/CNVs') {
+ if (this.store.size) {
+ trackArray.push('size=' + this.store.size)
+ }
+
+ if (this.store.config.type === 'gdc-viewer/Store/SeqFeature/CNVs') {
trackArray.push("autoscale=local");
trackArray.push("bicolor_pivot=0");
}
diff --git a/gdc-viewer/js/View/Export/TrackConfigJson.js b/gdc-viewer/js/View/Export/TrackConfigJson.js
index cf2e573..fc47086 100644
--- a/gdc-viewer/js/View/Export/TrackConfigJson.js
+++ b/gdc-viewer/js/View/Export/TrackConfigJson.js
@@ -16,24 +16,22 @@ return declare( ExportBase,
},
_printHeader: function() {
- var storeArray = (this.store.config.storeClass).split('/')
+ var storeArray = (this.store.config.type).split('/')
var trackObject = {
- 'label': this.store.config.label,
- 'storeClass': this.store.config.storeClass,
+ 'label': this.track.labelHTML,
+ 'storeClass': this.store.config.type,
'type': this.track.config.type,
- 'key': this.store.config.key,
+ 'key': this.track.key,
'metadata': {
'datatype': storeArray[storeArray.length - 1]
},
- 'unsafePopup': true
+ 'unsafePopup': true,
+ 'case': this.store.case,
+ 'size': this.store.size
}
- if (this.store.config.storeClass === 'gdc-viewer/Store/SeqFeature/SimpleSomaticMutations' || this.store.config.storeClass === 'gdc-viewer/Store/SeqFeature/Genes') {
- trackObject['fmtDetailValue_projects'] = 'function(value) { return "Loading...
";}';
- }
-
- if (this.store.config.storeClass === 'gdc-viewer/Store/SeqFeature/CNVs') {
+ if (this.store.config.type === 'gdc-viewer/Store/SeqFeature/CNVs') {
trackObject['autoscale'] = 'local';
trackObject['bicolor_pivot'] = 0;
}
diff --git a/gdc-viewer/js/View/GDCDialog.js b/gdc-viewer/js/View/GDCDialog.js
index 96677c3..d98fcbd 100644
--- a/gdc-viewer/js/View/GDCDialog.js
+++ b/gdc-viewer/js/View/GDCDialog.js
@@ -234,7 +234,7 @@ function (
var geneLoading = thisB.createLoadingIcon(thisB.geneFacetTab.containerNode);
// Update the accordions with results from the GDC
- fetch(thisB.baseGraphQLUrl, {
+ fetch(thisB.baseGraphQLUrl + '/facets', {
method: 'post',
headers: { 'X-Requested-With': null },
body: JSON.stringify(bodyVal)
@@ -1055,7 +1055,7 @@ function (
},
/**
- * Creates pagination buttons for search results in the given 'holder' using the 'pagination' object from the ICGC response
+ * Creates pagination buttons for search results in the given 'holder' using the 'pagination' object from the GDC response
* @param {object} holder DOM location to place pagination buttons
* @param {number} totalPages the total number of pages for the given query results
* @param {string} type the type of results to create pagination button for
@@ -1367,7 +1367,6 @@ function (
trackConf.autoscale = 'local';
trackConf.bicolor_pivot = 0;
} else if (storeClass === 'Genes') {
- trackConf.fmtDetailValue_projects = function(value) { return "Loading...
Loading...Loading...Loading...Loading...Loading...Use the following link to share the selected track at the current location.';
+ var helpElement = domConstruct.toDom(helpString);
+ domConstruct.place(helpElement, details);
+
+ // Create text area with shareable link
+ var textArea = domConstruct.create(
+ 'textarea',{
+ rows: 10,
+ value: shareableLink,
+ style: "width: 80%",
+ readOnly: true
+ }, details );
+
+ // Create a DOM element for the link
+ var linkString = 'Open in New Tab';
+ var linkElement = domConstruct.toDom(linkString);
+ domConstruct.place(linkElement, details);
+
+ return details;
+ }
});
}
);
\ No newline at end of file
diff --git a/gdc-viewer/js/View/Track/SSMTrack.js b/gdc-viewer/js/View/Track/SSMTrack.js
index c3c5041..451726c 100644
--- a/gdc-viewer/js/View/Track/SSMTrack.js
+++ b/gdc-viewer/js/View/Track/SSMTrack.js
@@ -1,24 +1,24 @@
define(
[
"dojo/_base/declare",
- "JBrowse/View/Track/CanvasFeatures",
+ "JBrowse/View/Track/HTMLFeatures",
'JBrowse/View/Track/_ExportMixin',
'dojo/dom-construct'
],
function(
declare,
- CanvasFeatures,
+ HTMLFeatures,
ExportMixin,
domConstruct) {
- return declare([ CanvasFeatures, ExportMixin ], {
+ return declare([ HTMLFeatures, ExportMixin ], {
_exportFormats: function() {
return [
{name: 'gdc-viewer/View/Export/GFF3', label: 'GFF3', fileExt: 'gff3'},
{name: 'gdc-viewer/View/Export/BED', label: 'BED', fileExt: 'bed'},
{name: 'gdc-viewer/View/Export/CSV', label: 'CSV', fileExt: 'csv'},
- {name: 'icgc-viewer/View/Export/SequinTable', label: 'Sequin Table', fileExt: 'sqn'},
- {name: 'gdc-viewer/View/Export/TrackConfig', label: 'Track Config INI', fileExt: 'conf'},
+ {name: 'gdc-viewer/View/Export/SequinTable', label: 'Sequin Table', fileExt: 'sqn'},
+ {name: 'gdc-viewer/View/Export/TrackConfig', label: 'Track Config', fileExt: 'conf'},
{name: 'gdc-viewer/View/Export/TrackConfigJson', label: 'Track Config JSON', fileExt: 'json'}];
},
@@ -47,6 +47,64 @@ define(
var projectSection = dojo.create('div', { style: 'flex-grow:1; flex-basis: 0' }, thirdRow)
this.renderDetailField( projectSection, 'projects', f.get('projects'), f, undefined, track.store.getTagMetadata('projects'))
},
+
+ _trackMenuOptions: function () {
+ var track = this;
+ var options = this.inherited(arguments);
+ options.push({
+ label: 'Share Track as URL',
+ action: "contentDialog",
+ title: 'Share Track as URL',
+ content: dojo.hitch(this,'_shareableLinkContent')
+ });
+ return options;
+ },
+
+ _shareableLinkContent: function() {
+ var track = this;
+ var details = domConstruct.create('div', { className: 'detail', style: 'display: flex; flex-direction: column; align-items: center; justify-content: center;' });
+
+ // Create addTracks value
+ var addTracksArray = [];
+ var addTrackConf = {};
+ addTrackConf.label = track.config.label;
+ addTrackConf.storeClass = track.store.config.type;
+ addTrackConf.type = track.config.type;
+ addTrackConf.key = track.config.key;
+ addTrackConf.metadata = track.config.metadata;
+ addTrackConf.unsafePopup = true;
+ addTrackConf.filters = track.store.config.filters;
+ addTrackConf.case = track.store.config.case;
+ addTrackConf.size = track.config.size;
+ addTracksArray.push(addTrackConf);
+ addTracksArray = JSON.stringify(addTracksArray);
+
+ // Create a shareable URL
+ var params = new URLSearchParams(window.location.search);
+ params.set("addTracks", addTracksArray);
+ var shareableLink = window.location.protocol + "//" + window.location.host + window.location.pathname + '?' + params.toString();
+
+ // Create help text
+ var helpString = 'Use the following link to share the selected track at the current location.
';
+ var helpElement = domConstruct.toDom(helpString);
+ domConstruct.place(helpElement, details);
+
+ // Create text area with shareable link
+ var textArea = domConstruct.create(
+ 'textarea',{
+ rows: 10,
+ value: shareableLink,
+ style: "width: 80%",
+ readOnly: true
+ }, details );
+
+ // Create a DOM element for the link
+ var linkString = 'Open in New Tab';
+ var linkElement = domConstruct.toDom(linkString);
+ domConstruct.place(linkElement, details);
+
+ return details;
+ }
});
}
);
\ No newline at end of file