Skip to content

Commit

Permalink
Merge branch 'release/0.3.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
abought committed Dec 16, 2021
2 parents 14494e2 + 6c8af9e commit 1c8e843
Show file tree
Hide file tree
Showing 8 changed files with 1,840 additions and 1,572 deletions.
15 changes: 7 additions & 8 deletions assets/js/pages/gwas_region.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import Vue from 'vue';
import 'bootstrap-vue/dist/bootstrap-vue.css';

import App from '../../vue/gwas_region.vue';

import { paramsFromUrl } from 'locuszoom/esm/ext/lz-dynamic-urls';

import { stateUrlMapping, getBasicSources, createStudyLayout, getBasicLayout } from 'localzoom/src/util/lz-helpers';
import count_region_view from 'localzoom/src/util/metrics';
import { stateUrlMapping, getBasicSources, createStudyLayouts, getBasicLayout } from 'localzoom/src/util/lz-helpers';
import { count_region_view } from 'localzoom/src/util/metrics';
import { createStudyAssocSources } from '../util/lz-helpers';

function makePlot(template_vars) {
Expand All @@ -16,19 +18,16 @@ function makePlot(template_vars) {
state
);
const assoc_sources = createStudyAssocSources(template_vars.label, template_vars.assoc_base_url);
const panels = createStudyLayout(template_vars.label, {
credible_sets: true,
gwas_catalog: true
}, template_vars.build);
const panels = createStudyLayouts('gwas', template_vars.label, template_vars.label);
const app_params = Object.assign(
{
lz_sources: getBasicSources(assoc_sources),
lz_layout: getBasicLayout(state, panels, { responsive_resize: true }),
study_names: [template_vars.label],
init_tracks: [{ data_type: 'gwas', filename: template_vars.label, display_name: template_vars.label}],
top_hits_url: template_vars.top_hits_url,
}, template_vars,
{
genome_build: template_vars.build,
genome_build: template_vars.genome_build,
chr: state.chr,
start: +state.start ,
end: +state.end
Expand Down
8 changes: 4 additions & 4 deletions assets/js/pages/gwas_upload.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import pako from 'pako';

import App from '../../vue/gwas_upload.vue';

import { isHeader } from 'localzoom/src/gwas/sniffers';
import { makeParser } from 'localzoom/src/gwas/parsers';
import { _isHeader } from 'locuszoom/esm/ext/lz-parsers/gwas/sniffers';
import { makeGWASParser } from 'locuszoom/esm/ext/lz-parsers';

const PREVIEW_BYTES = 5000; // enough for 50-100 lines
const MAX_UPLOAD_SIZE = 1048576 * 1000; // 1000 MiB # FIXME: Currently upload limit is only implemented in the frontend
Expand Down Expand Up @@ -157,9 +157,9 @@ modal.$on('has_options', function (parser_options) { // Close with options selec
fileField.setCustomValidity('');

// Once we know how to parse the file, do some quick validation to decide if the rows are sorted
const parser = makeParser(parser_options);
const parser = makeGWASParser(parser_options);
modal.file_reader.getRows().then((rows) => {
const first_data_index = rows.findIndex(text => !isHeader(text));
const first_data_index = rows.findIndex(text => !_isHeader(text));

let is_valid;
try {
Expand Down
17 changes: 9 additions & 8 deletions assets/js/util/lz-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ import {AssociationLZ} from 'locuszoom/esm/data/adapters';


class AssociationApi extends AssociationLZ {
getURL(state, chain,fields) {
const base = new URL(this.url, window.location.origin);
base.searchParams.set('chrom', state.chr);
base.searchParams.set('start', state.start);
base.searchParams.set('end', state.end);
_getURL(request_options) {
const { chr, start, end } = request_options;
const base = new URL(this._url, window.location.origin);
base.searchParams.set('chrom', chr);
base.searchParams.set('start', start);
base.searchParams.set('end', end);
return base;
}

Expand All @@ -40,11 +41,11 @@ LocusZoom.Adapters.add('AssociationApi', AssociationApi);
function createStudyAssocSources(label, url) {
const name = sourceName(label);
return [
[`assoc_${name}`, ['AssociationApi', { url, params: { id_field: 'variant' } }]],
[`assoc_gwas_${name}`, ['AssociationApi', { url }]],
[
`credset_${name}`, [
`credset_gwas_${name}`, [
'CredibleSetLZ',
{ params: { fields: { log_pvalue: `assoc_${name}:log_pvalue` }, threshold: 0.95 } },
{ threshold: 0.95 },
],
],
];
Expand Down
103 changes: 51 additions & 52 deletions assets/vue/gwas_region.vue
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
<script>
// Custom interactivity attached to the "GWAS Region/LocusZoom plot" page
import BatchSpec from 'localzoom/src/components/BatchSpec.vue';
import BatchScroller from 'localzoom/src/components/BatchScroller.vue';
import GwasToolbar from 'localzoom/src/components/GwasToolbar.vue';
import PlotPanes from 'localzoom/src/components/PlotPanes.vue';
import RegionPicker from 'localzoom/src/components/RegionPicker.vue';
import { DATA_TYPES } from 'localzoom/src/util/constants';
import { activateUserLD } from 'localzoom/src/util/lz-helpers';
import {setup_feature_metrics} from 'localzoom/src/util/metrics';
const MAX_REGION_SIZE = 1000000;
export default {
name: 'gwas_region',
props: [
'build', 'chr', 'start', 'end',
'genome_build', 'chr', 'start', 'end',
'lz_layout',
'lz_sources',
'study_names',
'init_tracks',
'top_hits_url'
],
data() {
Expand All @@ -28,6 +32,7 @@
c_chr: this.chr,
c_start: this.start,
c_end: this.end,
known_tracks: [...this.init_tracks],
// Controls for "batch view" mode
batch_mode_active: false,
Expand All @@ -39,25 +44,15 @@
// After plot is created, initiate metrics capture
// TODO: This is a mite finicky; consider further refactoring in the future?
this.$refs.plotWidget.$refs.assoc_plot.callPlot(setup_feature_metrics);
// FIXME: In tabbed UI, Bootstrap-vue has an issue where the tab panel is not fully initialized when
// content area is rendered. The result is that the plot width is slightly incorrect. Redrawing
// after a small delay helps to ensure that the plot is not truncated off the edge of the screen.
// This can be removed if we move away from the "tab/sidebar" UI design.
setTimeout(() => this.$refs.plotWidget.$refs.assoc_plot.callPlot((plot) => plot.rescaleSVG()));
},
activateBatchMode(regions) {
this.batch_mode_active = true;
this.batch_mode_regions = regions;
},
showMessage(message, style = 'text-danger') {
this.message = message;
this.message_class = style;
},
updateRegion(region) {
updateRegion({ chr, start, end }) {
// Receive new region config from toolbar
this.c_chr = region.chr;
this.c_start = region.start;
this.c_end = region.end;
if (!chr || !start || !end) {
return;
}
this.c_chr = chr;
this.c_start = start;
this.c_end = end;
},
fetchTopHits() {
// Used for batch mode "get top hits" button
Expand All @@ -78,53 +73,57 @@
end: +variant.pos + 250000
}));
});
}
},
receiveTrackOptions(data_type, filename, display_name, source_configs, panel_configs, extra_plot_state) {
if (!this.known_tracks.length) {
// If this is the first track added, allow the new track to suggest a region of interest and navigate there if relevant (mostly just GWAS)
this.updateRegion(extra_plot_state);
this.base_sources = getBasicSources(source_configs);
this.base_layout = getBasicLayout(extra_plot_state, panel_configs);
// Collect metrics for first plot loaded
count_region_view();
} else {
// TODO: We presently ignore extra plot state (like region) when adding new tracks. Revisit for future data types.
this.$refs.plotWidget.addStudy(panel_configs, source_configs);
if (data_type === DATA_TYPES.PLINK_LD) {
this.$refs.plotWidget.$refs.assoc_plot.callPlot((plot) => {
activateUserLD(plot, display_name);
});
}
}
},
},
components: { BatchSpec, BatchScroller, PlotPanes, RegionPicker }
components: { BatchSpec, BatchScroller, GwasToolbar, PlotPanes, RegionPicker }
}
</script>

<template>
<div>
<div class="row" v-if="!batch_mode_active">
<div class="col-md-4"></div>
<div class="col-md-8">
<div class="d-flex justify-content-end">
<region-picker
@ready="updateRegion"
@fail="showMessage"
class="float-right"
:build="build"
:max_range="max_region_size"
search_url="https://portaldev.sph.umich.edu/api/v1/annotation/omnisearch/"/>
<batch-spec class="ml-1"
:max_range="max_region_size"
@ready="activateBatchMode">
<template #preset-button="{updateRegions}">
<button class="btn btn-warning" @click="updateRegions(fetchTopHits())">Get top hits</button>
</template>
</batch-spec>
</div>
</div>
</div>
<div class="row" v-else>
<div class="row">
<div class="col-md-12">
<batch-scroller :regions="batch_mode_regions"
@navigate="updateRegion"
@cancel="batch_mode_active = false"/>
<gwas-toolbar
:batch_region_getter="fetchTopHits"
:genome_build.sync="genome_build"
:max_studies="6"
:known_tracks="known_tracks"
@add-tabix-track="receiveTrackOptions"
@select-range="updateRegion"/>
</div>
</div>
<div class="row" v-if="message">
<div class="col-sm-12"><span :class="[message_class]">{{message}}</span></div>
</div>

<div class="row">
<div class="col-md-12">
<plot-panes
ref="plotWidget"
:dynamic_urls="true"
:assoc_layout="lz_layout" :assoc_sources="lz_sources"
:study_names="study_names" :has_credible_sets="true"
:build="build"
:base_layout="lz_layout"
:base_sources="lz_sources"
:known_tracks="known_tracks"
:genome_build="genome_build"
:chr="c_chr" :start="c_start" :end="c_end"
@plot-created="activateMetrics"
/>
Expand Down
8 changes: 4 additions & 4 deletions assets/vue/gwas_upload.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script>
// Custom interactivity associated with the "Upload your own GWAS" page.
// This enhances just one part of the upload form.
import AdderWizard from 'localzoom/src/components/AdderWizard.vue';
import GwasParserOptions from 'localzoom/src/components/GwasParserOptions.vue';
export default {
name: 'gwas_upload',
Expand All @@ -17,16 +17,16 @@
this.$root.$emit('has_options', parser_options);
}
},
components: { AdderWizard },
components: { GwasParserOptions },
}
</script>

<template>
<div>
<adder-wizard v-if="show_modal"
<gwas-parser-options v-if="show_modal"
:file_reader="file_reader"
@ready="sendConfig"
@close="closeModal"></adder-wizard>
@close="closeModal"></gwas-parser-options>
</div>
</template>

Expand Down
22 changes: 21 additions & 1 deletion locuszoom_plotting_service/templates/pages/about.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ <h2 class="mt-3">What is this for?</h2>
</p>

<h2>Frequently asked questions</h2>
<div><ul id="auto-toc"></ul><!-- Generated automatically via JS --></div>
<div><ul id="auto-toc"></ul><!-- Generated automatically via JS (based on headings with class=faq) --></div>

<h3 class="faq" id="cite">How should I cite this?</h3>
<p>
Expand Down Expand Up @@ -104,6 +104,20 @@ <h3 class="faq" id="prepare-data">How should I prepare my data for uploading?</h
</li>
</ul>

<h3 class="faq" id="tabix-data-formats">How should I prepare local (tabix) files to add to the plot?</h3>
<p>
When viewing any LocusZoom plot on this site, you will be offered the option to "add [a] tabix-indexed datafile" to the plot.
This allows you to compare the plot in front of you with other information of interest, without having to share
sensitive or private information. Several types of track can be added. Inspired by <a href="https://statgen.github.io/localzoom" target="_blank">LocalZoom</a>,
the files will remain on your local computer (they will not be uploaded, and will vanish when the page is refreshed). Remote files (such as an S3 bucket) are also supported, so long as they follow the format instructions.
</p>
<p>
The use of Tabix allows region queries for files of any size, but it does require that the files be prepared
carefully before use. Some files (especially PLINK 1.9 LD) can be finicky to generate or require additional processing. We have gathered
detailed <a target="_blank" href="https://statgen.github.io/localzoom#instructions">instructions</a>
for how to run each step of the required programs, along with other format information. These instructions also cover how to configure cloud storage providers (Google Cloud or S3), so that you can host your own files at a remote URL without needing to manually configure an entire web server.
</p>

<h3 class="faq" id="missing-ld">Why is LD information not being shown for my data?</h3>
<p>
Sometimes, a region plot will be missing Linkage Disequilibrium (LD) information, and all points will be
Expand Down Expand Up @@ -136,6 +150,12 @@ <h3 class="faq" id="missing-ld">Why is LD information not being shown for my dat
Although we are exploring the possibility of additional LD reference panels, this is non-trivial due to
restrictions on public sharing of data.
</p>
<p>
Alternatively, the "add tabix file" feature allows you to generate your own LD and add it to the plot.
Because LD is sometimes considered sensitive information, we explicitly do not support uploading LD data to our server;
each person you are sharing the plot with will need to add their own LD from a local file (or remote URL). We welcome
suggestions for how to make this more reusable in the future.
</p>

<h3 class="faq" id="private-sharing">How do I share my results with only collaborators?</h3>
<p>
Expand Down
Loading

0 comments on commit 1c8e843

Please sign in to comment.