Skip to content

Commit

Permalink
Merge pull request #54 from agduncan94/develop
Browse files Browse the repository at this point in the history
Release 0.1.8
  • Loading branch information
agduncan94 authored Nov 18, 2019
2 parents c012b59 + c7651c9 commit ada6318
Show file tree
Hide file tree
Showing 9 changed files with 262 additions and 166 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
.DS_Store
node_modules/
docker/data/
cypress/data/
cypress/screenshots/
cypress/videos/
13 changes: 8 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,16 @@ before_install:
- cd docker/data
- curl -o Homo_sapiens.GRCh37.75.dna.chromosome.1.fa.gz http://ftp.ensembl.org/pub/release-75/fasta/homo_sapiens/dna/Homo_sapiens.GRCh37.75.dna.chromosome.1.fa.gz
- gzip -d Homo_sapiens.GRCh37.75.dna.chromosome.1.fa.gz
- cd ../
- docker-compose build
- docker-compose up -d
- cd ../
- cd ../../

install:
- npm ci
- cd docker
- 'if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then docker-compose build --build-arg plugin_version=${TRAVIS_PULL_REQUEST_BRANCH}; fi'
- 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then docker-compose build --build-arg plugin_version=${TRAVIS_BRANCH}; fi'
- docker-compose up -d
- cd ../

script:
- $(npm bin)/cypress run --record
# - $(npm bin)/cypress run --record
- $(npm bin)/cypress run
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
[![Build Status](https://travis-ci.org/agduncan94/icgc-viewer.svg?branch=develop)](https://travis-ci.org/agduncan94/icgc-viewer)
# ICGC JBrowse Plugin
A plugin for [JBrowse](https://jbrowse.org/) for viewing [ICGC](https://icgc.org/) data. For any bugs, issues, or feature recommendations please create an issue through GitHub.

Expand Down Expand Up @@ -25,7 +26,7 @@ urlTemplate=GRCh37.genome.fa
```

## 4. Adding new tracks
We have some basic example tracks in `data/tracks.conf`. You can also add new tracks by using the ICGC Dialog accessible within JBrowse. These are present in the menu under `ICGC`. See [Dynamic Track Generation](#dynamic-track-generation) for more details
We have some basic example tracks in `data/tracks.conf`. You can also add new tracks by using the ICGC Dialog accessible within JBrowse. These are present in the menu under `ICGC`. See [Dynamic Track Generation](#dynamic-track-generation) for more details.

## 5. Run JBrowse
You'll have to run the following commands:
Expand Down Expand Up @@ -55,6 +56,8 @@ displayColumns =
## A note on filters
All SeqFeatures support filters as they are used in the ICGC API Documentation.

You can view/edit the filters associated with a track by clicking the down arrow for the track menu and selecting `View Applied Filters`. Be careful, there are currently no checks to see if the filters are valid before applying them.

## Genes
A simple view of all genes returned by the ICGC portal for a given range of the chromosome you are looking at.

Expand Down Expand Up @@ -95,7 +98,7 @@ filters={"gene":{"type":{"is":["protein_coding"]}}}
![ICGC Genes](images/ICGC-Genes-protein-coding.png)

### Extra notes
You can also set the `size` attribute (defaults to 1000). This is the theoretical maximum number of genes displayed at a time in JBrowse. The smaller the value, the faster JBrowse will be.
You can also set the `size` attribute (defaults to 1000). This is the theoretical maximum number of genes displayed at a time in JBrowse (per panel). The smaller the value, the faster JBrowse will be.

## SimpleSomaticMutations
A simple view of all the simple somatic mutations across all donors in the ICGC portal.
Expand Down Expand Up @@ -137,7 +140,7 @@ filters={"mutation":{"functionalImpact":{"is":["High"]}}}
![ICGC SSMs](images/ICGC-SSM-high-impact.png)

### Extra notes
You can also set the `size` attribute (defaults to 500). This is the theoretical maximum number of mutations displayed at a time in JBrowse. The smaller the value, the faster JBrowse will be.
You can also set the `size` attribute (defaults to 500). This is the theoretical maximum number of mutations displayed at a time in JBrowse(per panel). The smaller the value, the faster JBrowse will be.

# Dynamic track generation
## Explore donors, genes and mutations
Expand Down Expand Up @@ -169,6 +172,6 @@ Cypress.io is used for testing this plugin. The following steps show how to run
2. Download Chr 1 fasta from `http://ftp.ensembl.org/pub/release-75/fasta/homo_sapiens/dna/Homo_sapiens.GRCh37.75.dna.chromosome.1.fa.gz`. There should be the fasta index file in `cypress/data/Homo_sapiens.GRCh37.75.dna.chromosome.1.fa.fai`. Put these files into `jbrowse/data/`.
3. Install Cypress.io with `npm install`.
4. Place `cypress/data/tracks.conf` into your `jbrowse/data/` directory. Make sure no other tracks are present.
5. Run `./node_modules/cypress/bin/cypress open` or `./node_modules/cypress/bin/cypress run`
5. Run `npx cypress open` or `npx cypress run` or `npm run e2e`

**Note** while some tests have mocked endpoints, not all endpoints are mocked. This could lead to breakage of tests in the future.
4 changes: 3 additions & 1 deletion docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ FROM node:latest

LABEL maintainer="[email protected]"

ARG plugin_version=master

ENV JBROWSE_VERSION 1.16.6
ENV PLUGIN_VERSION=0.1.7
ENV PLUGIN_VERSION=$plugin_version

# Install dependencies
RUN apt-get -qq update --fix-missing
Expand Down
206 changes: 206 additions & 0 deletions icgc-viewer/js/View/Track/BaseTrack.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
define(
[
"dojo/_base/declare",
"JBrowse/View/Track/HTMLFeatures",
'JBrowse/View/Track/_ExportMixin',
'dojo/dom-construct',
'dijit/form/Button',
'dijit/form/NumberSpinner',
'dijit/form/ValidationTextBox',
'./ValidationTextArea'
],
function(
declare,
HTMLFeatures,
ExportMixin,
domConstruct,
Button,
NumberSpinner,
ValidationTextBox,
ValidationTextArea) {
return declare([ HTMLFeatures, ExportMixin ], {

_exportFormats: function() {
return [
{name: 'icgc-viewer/View/Export/GFF3', label: 'GFF3', fileExt: 'gff3'},
{name: 'icgc-viewer/View/Export/BED', label: 'BED', fileExt: 'bed'},
{name: 'icgc-viewer/View/Export/CSV', label: 'CSV', fileExt: 'csv'},
{name: 'icgc-viewer/View/Export/SequinTable', label: 'Sequin Table', fileExt: 'sqn'},
{name: 'icgc-viewer/View/Export/TrackConfig', label: 'Track Config', fileExt: 'conf'},
{name: 'icgc-viewer/View/Export/TrackConfigJson', label: 'Track Config JSON', fileExt: 'json'}
];
},

_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')
});
options.push({
label: 'View Applied Filters',
action: "contentDialog",
title: 'View Applied Filters',
content: dojo.hitch(this,'_appliedFilters')
});
return options;
},

/**
* Create dialog showing applied filters for the given track.
* User can apply new filters here too.
*/
_appliedFilters: function() {
var track = this;
var details = domConstruct.create('div', { className: 'detail', style: 'display: flex; flex-direction: column; align-items: center; justify-content: center;' });

var headerString = '<h1 style="width: 80%">Track Filters</h1>';
var headerElement = domConstruct.toDom(headerString);
domConstruct.place(headerElement, details);

// Create help text
var helpString = '<span style="width: 80%">The following filters have been applied to the track. You can update the filters here, though no validation is done on the input.</span>';
var helpElement = domConstruct.toDom(helpString);
domConstruct.place(helpElement, details);

var filterString = '<div style="width: 80%"><h3>Filters</h3></div>';
var filterElement = domConstruct.toDom(filterString);
domConstruct.place(filterElement, details);

// Get filtered text
var filteredText = JSON.stringify(track.store.filters, null, 2)

var textArea = new ValidationTextArea({
rows: 20,
value: filteredText,
style: "width: 80%",
readOnly: false,
id: "filterTextArea",
invalidMessage: "Invalid JSON filter - must be a valid JSON",
isValid: function() {
var value = this.attr('value')
try {
JSON.parse(value)
} catch (e) {
return false;
}
return true;
}
}).placeAt(details);

var donorString = '<div style="width: 80%"><h3>Donor UUID</h3></div>';
var donorElement = domConstruct.toDom(donorString);
domConstruct.place(donorElement, details);

var donorIdTextBox = new ValidationTextBox({
value: track.store.config.donor,
style: "width: 80%",
id: "donorTextBox",
regExp: "^DO[0-9]+$",
invalidMessage: "Invalid Donor ID - Must be of the form DOxxxx, where xxxx is some number greater than 0.",
trim: true
}).placeAt(details);

var sizeHeader = '<div style="width: 80%"><h3>Size</h3></div>';
var sizeElement = domConstruct.toDom(sizeHeader);
domConstruct.place(sizeElement, details);

var sizeTextBox = new NumberSpinner({
value: track.store.size,
style: "width: 80%",
id: "sizeTextBox",
constraints: { min: 1, max: 1000, places: 0 },
smallDelta: 10
}).placeAt(details);

var updateTrackButton = new Button({
label: 'Apply New Filters',
iconClass: 'dijitIconSave',
onClick: function() {
const trackString = document.getElementById("filterTextArea").value;
const donorString = document.getElementById("donorTextBox").value;
const sizeString = document.getElementById("sizeTextBox").value;
var storeConf = {
browser: track.browser,
refSeq: track.browser.refSeq,
type: track.store.config.type,
donor: donorString,
size: sizeString,
filters: trackString
};
var storeName = track.browser.addStoreConfig(null, storeConf);
track.config.store = storeName;
track.browser.publish( '/jbrowse/v1/v/tracks/replace', [track.config] );
}
}).placeAt(details);

donorIdTextBox.on('change', function(e) {
updateTrackButton.set('disabled', !donorIdTextBox.validate() || !sizeTextBox.validate() || !textArea.validate())
});

sizeTextBox.on('change', function(e) {
updateTrackButton.set('disabled', !donorIdTextBox.validate() || !sizeTextBox.validate() || !textArea.validate())
});

textArea.on('change', function(e) {
updateTrackButton.set('disabled', !donorIdTextBox.validate() || !sizeTextBox.validate() || !textArea.validate())
});

return details;
},

_shareableLinkContent: function() {
var track = this;
var details = domConstruct.create('div', { className: 'detail', style: 'display: flex; flex-direction: column; align-items: center; justify-content: center;' });

var headerString = '<h1 style="width: 80%">Shareable Link</h1>';
var headerElement = domConstruct.toDom(headerString);
domConstruct.place(headerElement, details);

// 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.donor = track.store.config.donor;
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 = '<span style="width: 80%">Use the following link to share the selected track at the current location.</span>';
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 = '<a target="_blank" href="' + shareableLink + '">Open in New Tab</a>';
var linkElement = domConstruct.toDom(linkString);
domConstruct.place(linkElement, details);

return details;
}
});
}
);
Loading

0 comments on commit ada6318

Please sign in to comment.