- nPeaks && navigate(`/dataset/explore/locus/${chrom}/${position}/${assay}`, {replace: true})}
+ nPeaks && navigate(
+ `/datasets/${urlEncodedNode}/explore/locus/${chrom}/${position}/${assay}`,
+ {replace: true})}
disabled={!nPeaks}
aria-disabled={true}
>
diff --git a/client/src/components/pages/DatasetPage.js b/client/src/components/pages/DatasetPage.js
new file mode 100644
index 00000000..ef1dc190
--- /dev/null
+++ b/client/src/components/pages/DatasetPage.js
@@ -0,0 +1,29 @@
+import {useEffect} from "react";
+import {useDispatch} from "react-redux";
+import {Outlet, useOutletContext, useParams} from "react-router-dom";
+
+import {setNode} from "../../actions";
+import {EPIVAR_NODES} from "../../config";
+import {useNode} from "../../hooks";
+
+const DatasetPage = () => {
+ const dispatch = useDispatch();
+ const {node: urlNode} = useParams();
+ const node = useNode();
+
+ useEffect(() => {
+ const decodedNode = decodeURIComponent(urlNode);
+ if (!EPIVAR_NODES.find((n) => n === decodedNode)) return; // Node doesn't exist in our list
+ if (node === urlNode) return; // Node is already set in the Redux store
+ console.info("setting node based on URL:", decodedNode);
+ dispatch(setNode(decodedNode));
+ }, [dispatch, urlNode]);
+
+ const existingOutletContext = useOutletContext();
+
+ return
+
+
;
+};
+
+export default DatasetPage;
diff --git a/client/src/components/pages/OverviewPage.js b/client/src/components/pages/OverviewPage.js
index 30cb3b41..515c77ec 100644
--- a/client/src/components/pages/OverviewPage.js
+++ b/client/src/components/pages/OverviewPage.js
@@ -15,7 +15,7 @@ import {
setOverviewChrom,
setOverviewAssay,
} from '../../actions.js'
-import {useCurrentDataset} from "../../hooks";
+import {useCurrentDataset, useUrlEncodedNode} from "../../hooks";
const SNP_PROP = "snp_nat_id";
@@ -33,7 +33,8 @@ const OverviewPage = () => {
const {width} = useWindowDimensions();
- const {chromosomeSizes} = useCurrentDataset();
+ const urlEncodedNode = useUrlEncodedNode();
+ const {chromosomeSizes} = useCurrentDataset() ?? {};
const {
isLoading: configIsLoading,
@@ -81,11 +82,11 @@ const OverviewPage = () => {
const onPointClick = useCallback((peak) => {
console.info("onPointClick triggered on peak:", peak);
const snp = peak[SNP_PROP];
- navigate(`/dataset/explore/locus/rsID/${snp}/${assay}`);
+ navigate(`/datasets/${urlEncodedNode}/explore/locus/rsID/${snp}/${assay}`);
dispatch(setChrom("rsID"));
dispatch(setPosition(snp));
dispatch(doSearch());
- }, [dispatch, navigate]);
+ }, [dispatch, assay, navigate, urlEncodedNode]);
// noinspection JSValidateTypes
return
diff --git a/client/src/components/pages/ProtectedPageContainer.js b/client/src/components/pages/ProtectedPageContainer.js
index 8e8ecd62..e8f304e2 100644
--- a/client/src/components/pages/ProtectedPageContainer.js
+++ b/client/src/components/pages/ProtectedPageContainer.js
@@ -22,22 +22,29 @@ const ProtectedPageContainer = React.memo(({children}) => {
const {data: userData, isLoaded} = useSelector(state => state.user);
const triggerLogIn = useCallback(() => {
- window.location.href = `${node}/api/auth/login?redirect=${window.location.pathname}`;
+ if (!node) {
+ console.warn("no node selected; cannot trigger log in");
+ return;
+ }
+ window.location.href = `${node}/api/auth/login?redirect=${encodeURIComponent(window.location.href)}`;
}, [node]);
useEffect(() => {
+ if (!node) return;
if (isLoaded && userData) {
- setHasLoggedIn();
+ setHasLoggedIn(node);
} else if (isLoaded && !userData) {
- if (getHasLoggedIn()) {
+ if (getHasLoggedIn(node)) {
+ console.info("triggering log-in (has logged in before)");
triggerLogIn();
}
}
- }, [userData, isLoaded]);
+ }, [node, isLoaded, userData]);
const onAccess = useCallback(() => {
if (!userData) {
// Redirect to sign in, so we can capture some information about their identity (IP address).
+ console.info("triggering log-in (onAccess)");
triggerLogIn();
} else {
// Signed in but terms not accepted yet; show the modal.
diff --git a/client/src/helpers/localStorage.js b/client/src/helpers/localStorage.js
index c459ce90..3f4eb7fc 100644
--- a/client/src/helpers/localStorage.js
+++ b/client/src/helpers/localStorage.js
@@ -1,9 +1,10 @@
-const LS_HAS_LOGGED_IN_BEFORE = 'EPIVAR_HAS_LOGGED_IN_BEFORE';
+const LS_HAS_LOGGED_IN_BEFORE = "EPIVAR_HAS_LOGGED_IN_BEFORE";
-export const setHasLoggedIn = () => {
- localStorage.setItem(LS_HAS_LOGGED_IN_BEFORE, "1");
-}
+const getLoggedInObject = () => JSON.parse(localStorage.getItem(LS_HAS_LOGGED_IN_BEFORE) || "{}");
-export const getHasLoggedIn = () => {
- return localStorage.getItem(LS_HAS_LOGGED_IN_BEFORE) === "1";
+export const setHasLoggedIn = (node) => {
+ const existing = getLoggedInObject();
+ localStorage.setItem(LS_HAS_LOGGED_IN_BEFORE, JSON.stringify({...existing, [node]: true}));
}
+
+export const getHasLoggedIn = (node) => (getLoggedInObject()[node]) ?? false;
diff --git a/client/src/helpers/reducers.js b/client/src/helpers/reducers.js
index 3803f0c8..e3fcda12 100644
--- a/client/src/helpers/reducers.js
+++ b/client/src/helpers/reducers.js
@@ -1,3 +1,5 @@
+import * as k from "../constants/ActionTypes"
+
export const makeDefaultListState = (defaultList = undefined) => ({
isLoading: false,
isLoaded: false,
@@ -12,25 +14,11 @@ export const makeListReducer = (types, defaultState) => (state = defaultState, a
return {...state, isLoading: false, isLoaded: true, list: action.payload};
case types.ERROR:
return {...state, isLoading: false};
- default:
- return state;
- }
-};
-export const makeDefaultDataState = (defaultData = undefined) => ({
- isLoading: false,
- isLoaded: false,
- data: defaultData,
-});
+ // TODO: this can create a race condition with fetching
+ case k.SET_NODE:
+ return defaultState;
-export const makeDataReducer = (types, defaultState) => (state = defaultState, action) => {
- switch (action.type) {
- case types.REQUEST:
- return {...state, isLoading: true};
- case types.RECEIVE:
- return {...state, isLoading: false, isLoaded: true, data: action.payload};
- case types.ERROR:
- return {...state, isLoading: false};
default:
return state;
}
diff --git a/client/src/hooks.js b/client/src/hooks.js
index 1058df7b..62186a73 100644
--- a/client/src/hooks.js
+++ b/client/src/hooks.js
@@ -3,6 +3,11 @@ import {useSelector} from "react-redux";
export const useDevMode = () => useSelector((state) => state.ui.devMode);
export const useNode = () => useSelector((state) => state.ui.node);
+export const useUrlEncodedNode = () => {
+ const node = useNode();
+ return encodeURIComponent(node ?? "");
+}
+
export const useDatasetsByNode = () => useSelector((state) => state.datasets.datasetsByNode);
export const useCurrentDataset = () => {
diff --git a/client/src/index.js b/client/src/index.js
index 6b453529..78ad7eed 100644
--- a/client/src/index.js
+++ b/client/src/index.js
@@ -14,14 +14,6 @@ import { composeWithDevToolsLogOnlyInProduction } from '@redux-devtools/extensio
import './styles.css';
import { rootReducer } from './reducers';
import App from './components/App';
-import {
- fetchAssays,
- fetchDatasets,
- fetchMessages,
- fetchUser, setNode
-} from './actions.js'
-import {EPIVAR_NODES} from "./config";
-
const initialState = {};
@@ -48,20 +40,6 @@ render(
document.querySelector('#root')
);
-store.dispatch(fetchDatasets()).then(() => {
- const { datasetsByNode } = store.getState().datasets;
- const firstNode = EPIVAR_NODES[0];
- if (firstNode && datasetsByNode[firstNode]) {
- store.dispatch(setNode(firstNode));
- store.dispatch(fetchUser());
- store.dispatch(fetchMessages()); // Server-side messages, e.g. auth errors
- store.dispatch(fetchAssays());
- } else {
- // TODO: report error to users
- console.error("Either no nodes are configured, or dataset information was not fetched successfully")
- }
-});
-
/*
Re-enable to bring back server-fetched genomic chromosomes. For now, this instead just holds rsID + gene.
- David L, 2023-05-25
diff --git a/client/src/reducers.js b/client/src/reducers.js
index 0b5c89c6..97d27aa9 100644
--- a/client/src/reducers.js
+++ b/client/src/reducers.js
@@ -2,7 +2,7 @@ import { combineReducers } from "redux"
import {EPIVAR_NODES} from "./config";
import * as k from "./constants/ActionTypes"
-import {makeDataReducer, makeDefaultDataState, makeDefaultListState, makeListReducer} from "./helpers/reducers";
+import {makeDefaultListState, makeListReducer} from "./helpers/reducers";
const defaultChrom = 'rsID';
@@ -26,7 +26,8 @@ const defaultUI = {
function uiReducer(state = defaultUI, action) {
switch (action.type) {
case k.SET_NODE: {
- return { ...state, node: action.payload };
+ // Reset other state too when node changes
+ return { ...state, node: action.payload, chrom: defaultChrom, position: '', overview: defaultUI.overview };
}
case k.SET_CHROM: {
return { ...state, chrom: action.payload };
@@ -62,7 +63,7 @@ const defaultSamples = {
end: undefined,
ref: undefined,
}
-}
+};
function samplesReducer(state = defaultSamples, action) {
switch (action.type) {
case k.SAMPLES.REQUEST: {
@@ -74,6 +75,12 @@ function samplesReducer(state = defaultSamples, action) {
case k.SAMPLES.ERROR: {
return { ...state, isLoading: false }
}
+
+ // TODO: this can create a race condition with samples fetching
+ case k.SET_NODE: {
+ return defaultSamples;
+ }
+
default:
return state;
}
@@ -114,7 +121,7 @@ const defaultPositions = {
isLoaded: false,
lastRequestDispatched: 0,
list: [],
-}
+};
function positionsReducer(state = defaultPositions, action) {
switch (action.type) {
case k.POSITIONS.REQUEST: {
@@ -132,6 +139,12 @@ function positionsReducer(state = defaultPositions, action) {
// TODO: Should this use cancel token?
return {...state, isLoading: action.meta.dispatchedAt >= state.lastRequestDispatched ? false : state.isLoading}
}
+
+ // TODO: this can create a race condition with positions fetching
+ case k.SET_NODE: {
+ return defaultPositions;
+ }
+
default:
return state;
}
@@ -234,6 +247,12 @@ const overviewReducer = (state = defaultOverview, action) => {
case k.OVERVIEW_CONFIG.ERROR: {
return {...state, isLoading: false};
}
+
+ // TODO: this can create a race condition with overview config loading
+ case k.SET_NODE: {
+ return defaultOverview;
+ }
+
default:
return state;
}
@@ -289,13 +308,40 @@ const manhattanReducer = (state = defaultManhattan, action) => {
};
}
+ // TODO: this can create a race condition with manhattan data loading
+ case k.SET_NODE: {
+ return defaultManhattan;
+ }
+
+ default:
+ return state;
+ }
+};
+
+const defaultUser = {
+ isLoading: false,
+ isLoaded: false,
+ data: null,
+};
+const userReducer = (state = defaultUser, action) => {
+ switch (action.type) {
+ case k.USER.REQUEST:
+ return {...state, isLoading: true};
+ case k.USER.RECEIVE:
+ return {...state, isLoading: false, isLoaded: true, data: action.payload};
+ case k.USER.ERROR:
+ return {...state, isLoading: false};
+
+ // TODO: this can create a race condition with user fetching
+ case k.SET_NODE: {
+ return defaultUser;
+ }
+
default:
return state;
}
};
-const defaultUser = makeDefaultDataState();
-const userReducer = makeDataReducer(k.USER, defaultUser);
const defaultMessages = makeDefaultListState();
const messagesReducer = makeListReducer(k.MESSAGES, defaultMessages);
diff --git a/epivar-prod/docker-compose.yml b/epivar-prod/docker-compose.yml
index f42876d8..e5a7cbb3 100644
--- a/epivar-prod/docker-compose.yml
+++ b/epivar-prod/docker-compose.yml
@@ -2,7 +2,7 @@ services:
# Common -------------------------------------------------------------------------------------------------------------
epivar-portal:
- image: ghcr.io/c3g/epivar-portal:edge
+ image: ghcr.io/c3g/epivar-portal:pr-15
ports:
- 80:80
depends_on:
@@ -18,8 +18,7 @@ services:
# Node 1: hg19 data --------------------------------------------------------------------------------------------------
epivar-node-1-server:
- # user: $EPIVAR_UID:$EPIVAR_UID
- image: ghcr.io/c3g/epivar-server:edge
+ image: ghcr.io/c3g/epivar-server:pr-15
networks:
- epivar-node-1-server-net
- epivar-node-1-redis-net
@@ -36,8 +35,6 @@ services:
- EPIVAR_IMPORT_MAX_P_VAL=0.05
- EPIVAR_LOW_COUNT_THRESHOLD=5
volumes:
- # user information
-# - /etc/passwd:/etc/passwd:ro
# dataset configuration: about Markdown file, EpiVar config.js
- ./node1/about.md:/app/data/about.md
- ./node1/config.js:/app/config.js:ro
@@ -82,8 +79,7 @@ services:
# Node 2: hg38 data (lifted over) ------------------------------------------------------------------------------------
epivar-node-2-server:
- # user: $USER:$USER
- image: ghcr.io/c3g/epivar-server:edge
+ image: ghcr.io/c3g/epivar-server:pr-15
networks:
- epivar-node-2-server-net
- epivar-node-2-redis-net
@@ -100,8 +96,6 @@ services:
- EPIVAR_IMPORT_MAX_P_VAL=0.05
- EPIVAR_LOW_COUNT_THRESHOLD=5
volumes:
- # user information
-# - /etc/passwd:/etc/passwd:ro
# dataset configuration: about Markdown file, EpiVar config.js, tracks metadata.json
- ./node2/about.md:/app/data/about.md
- ./node2/config.js:/app/config.js:ro
diff --git a/epivar-prod/node1/about.md b/epivar-prod/node1/about.md
index 993ed41a..96118f23 100644
--- a/epivar-prod/node1/about.md
+++ b/epivar-prod/node1/about.md
@@ -24,7 +24,7 @@ All the datasets that have been generated as part of this project are summarized
[made available here](#datasets). Access to some of the raw datasets require a formal data access request but all
resources are available freely. Please cite the appropriate paper(s) if you use the data.
-We have also built a [browser tool](https://flu-infection.vhost38.genap.ca/dataset/overview) that allows navigation of
+We have also built a [browser tool](https://flu-infection.vhost38.genap.ca/about) that allows navigation of
these rich datasets by condition, ancestry and, importantly, haplotype. This allows an in-depth exploration of the
quantitative trait loci and other key results reported in the studies above. Using this tool requires a terms-of-use
agreement to ensure data privacy conditions are respected.
@@ -113,7 +113,7 @@ access number [GSE225708](https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE
Genomic tracks by condition and ancestry are available [here](https://flu-infection.vhost38.genap.ca/explore).
-We constructed [a versatile QTL browser](https://flu-infection.vhost38.genap.ca/dataset/overview), which allows users to
+We constructed [a versatile QTL browser](https://flu-infection.vhost38.genap.ca/about), which allows users to
explore and visualize mapped QTLs for gene expression, chromatin accessibility, histone modifications and DNA
methylation.
diff --git a/epivar-prod/node1/ucsc.other-tracks.txt b/epivar-prod/node1/ucsc.other-tracks.txt
index f55ffddc..3dcda52d 100644
--- a/epivar-prod/node1/ucsc.other-tracks.txt
+++ b/epivar-prod/node1/ucsc.other-tracks.txt
@@ -1,13 +1,13 @@
track ATACseq
superTrack on show
shortLabel ATACseq
-longLabel
+longLabel
track ATACseq_EU_NI
parent ATACseq
container multiWig
shortLabel ATACseq_EU_NI
- longLabel
+ longLabel
type bigWig
visibility full
aggregate transparentOverlay
@@ -26,7 +26,7 @@ longLabel
type bigWig
parent ATACseq_EU_NI
shortLabel ATACseq_EU_NI_avg
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/ATACseq_EU_NI_avg.bw
color 135,168,232
@@ -34,7 +34,7 @@ longLabel
type bigWig
parent ATACseq_EU_NI
shortLabel ATACseq_EU_NI_stddev
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/ATACseq_EU_NI_stdev.bw
color 53,89,161
@@ -43,7 +43,7 @@ longLabel
parent ATACseq
container multiWig
shortLabel ATACseq_EU_Flu
- longLabel
+ longLabel
type bigWig
visibility full
aggregate transparentOverlay
@@ -62,7 +62,7 @@ longLabel
type bigWig
parent ATACseq_EU_Flu
shortLabel ATACseq_EU_Flu_avg
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/ATACseq_EU_Flu_avg.bw
color 232,135,168
@@ -70,7 +70,7 @@ longLabel
type bigWig
parent ATACseq_EU_Flu
shortLabel ATACseq_EU_Flu_stddev
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/ATACseq_EU_Flu_stdev.bw
color 204,0,0
@@ -79,7 +79,7 @@ longLabel
parent ATACseq
container multiWig
shortLabel ATACseq_AF_NI
- longLabel
+ longLabel
type bigWig
visibility full
aggregate transparentOverlay
@@ -98,7 +98,7 @@ longLabel
type bigWig
parent ATACseq_AF_NI
shortLabel ATACseq_AF_NI_avg
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/ATACseq_AF_NI_avg.bw
color 135,168,232
@@ -106,7 +106,7 @@ longLabel
type bigWig
parent ATACseq_AF_NI
shortLabel ATACseq_AF_NI_stddev
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/ATACseq_AF_NI_stdev.bw
color 53,89,161
@@ -115,7 +115,7 @@ longLabel
parent ATACseq
container multiWig
shortLabel ATACseq_AF_Flu
- longLabel
+ longLabel
type bigWig
visibility full
aggregate transparentOverlay
@@ -134,7 +134,7 @@ longLabel
type bigWig
parent ATACseq_AF_Flu
shortLabel ATACseq_AF_Flu_avg
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/ATACseq_AF_Flu_avg.bw
color 232,135,168
@@ -142,7 +142,7 @@ longLabel
type bigWig
parent ATACseq_AF_Flu
shortLabel ATACseq_AF_Flu_stddev
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/ATACseq_AF_Flu_stdev.bw
color 204,0,0
@@ -150,7 +150,7 @@ track NA1
type bigWig
visibility full
shortLabel NA1
-longLabel
+longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K27me3_AF_NI_avg.bw
viewLimits 0:500
alwaysZero on
@@ -162,13 +162,13 @@ color 255,255,255
track H3K27ac
superTrack on show
shortLabel H3K27ac
-longLabel
+longLabel
track H3K27ac_EU_NI
parent H3K27ac
container multiWig
shortLabel H3K27ac_EU_NI
- longLabel
+ longLabel
type bigWig
visibility full
aggregate transparentOverlay
@@ -187,7 +187,7 @@ longLabel
type bigWig
parent H3K27ac_EU_NI
shortLabel H3K27ac_EU_NI_avg
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K27ac_EU_NI_avg.bw
color 135,168,232
@@ -195,7 +195,7 @@ longLabel
type bigWig
parent H3K27ac_EU_NI
shortLabel H3K27ac_EU_NI_stddev
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K27ac_EU_NI_stdev.bw
color 53,89,161
@@ -204,7 +204,7 @@ longLabel
parent H3K27ac
container multiWig
shortLabel H3K27ac_EU_Flu
- longLabel
+ longLabel
type bigWig
visibility full
aggregate transparentOverlay
@@ -223,7 +223,7 @@ longLabel
type bigWig
parent H3K27ac_EU_Flu
shortLabel H3K27ac_EU_Flu_avg
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K27ac_EU_Flu_avg.bw
color 232,135,168
@@ -231,7 +231,7 @@ longLabel
type bigWig
parent H3K27ac_EU_Flu
shortLabel H3K27ac_EU_Flu_stddev
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K27ac_EU_Flu_stdev.bw
color 204,0,0
@@ -240,7 +240,7 @@ longLabel
parent H3K27ac
container multiWig
shortLabel H3K27ac_AF_NI
- longLabel
+ longLabel
type bigWig
visibility full
aggregate transparentOverlay
@@ -259,7 +259,7 @@ longLabel
type bigWig
parent H3K27ac_AF_NI
shortLabel H3K27ac_AF_NI_avg
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K27ac_AF_NI_avg.bw
color 135,168,232
@@ -267,7 +267,7 @@ longLabel
type bigWig
parent H3K27ac_AF_NI
shortLabel H3K27ac_AF_NI_stddev
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K27ac_AF_NI_stdev.bw
color 53,89,161
@@ -276,7 +276,7 @@ longLabel
parent H3K27ac
container multiWig
shortLabel H3K27ac_AF_Flu
- longLabel
+ longLabel
type bigWig
visibility full
aggregate transparentOverlay
@@ -295,7 +295,7 @@ longLabel
type bigWig
parent H3K27ac_AF_Flu
shortLabel H3K27ac_AF_Flu_avg
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K27ac_AF_Flu_avg.bw
color 232,135,168
@@ -303,7 +303,7 @@ longLabel
type bigWig
parent H3K27ac_AF_Flu
shortLabel H3K27ac_AF_Flu_stddev
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K27ac_AF_Flu_stdev.bw
color 204,0,0
@@ -311,7 +311,7 @@ track NA2
type bigWig
visibility full
shortLabel NA2
-longLabel
+longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K27me3_AF_NI_avg.bw
viewLimits 0:500
alwaysZero on
@@ -323,13 +323,13 @@ color 255,255,255
track H3K4me1
superTrack on show
shortLabel H3K4me1
-longLabel
+longLabel
track H3K4me1_EU_NI
parent H3K4me1
container multiWig
shortLabel H3K4me1_EU_NI
- longLabel
+ longLabel
type bigWig
visibility full
aggregate transparentOverlay
@@ -348,7 +348,7 @@ longLabel
type bigWig
parent H3K4me1_EU_NI
shortLabel H3K4me1_EU_NI_avg
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K4me1_EU_NI_avg.bw
color 135,168,232
@@ -356,7 +356,7 @@ longLabel
type bigWig
parent H3K4me1_EU_NI
shortLabel H3K4me1_EU_NI_stddev
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K4me1_EU_NI_stdev.bw
color 53,89,161
@@ -365,7 +365,7 @@ longLabel
parent H3K4me1
container multiWig
shortLabel H3K4me1_EU_Flu
- longLabel
+ longLabel
type bigWig
visibility full
aggregate transparentOverlay
@@ -384,7 +384,7 @@ longLabel
type bigWig
parent H3K4me1_EU_Flu
shortLabel H3K4me1_EU_Flu_avg
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K4me1_EU_Flu_avg.bw
color 232,135,168
@@ -392,7 +392,7 @@ longLabel
type bigWig
parent H3K4me1_EU_Flu
shortLabel H3K4me1_EU_Flu_stddev
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K4me1_EU_Flu_stdev.bw
color 204,0,0
@@ -401,7 +401,7 @@ longLabel
parent H3K4me1
container multiWig
shortLabel H3K4me1_AF_NI
- longLabel
+ longLabel
type bigWig
visibility full
aggregate transparentOverlay
@@ -420,7 +420,7 @@ longLabel
type bigWig
parent H3K4me1_AF_NI
shortLabel H3K4me1_AF_NI_avg
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K4me1_AF_NI_avg.bw
color 135,168,232
@@ -428,7 +428,7 @@ longLabel
type bigWig
parent H3K4me1_AF_NI
shortLabel H3K4me1_AF_NI_stddev
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K4me1_AF_NI_stdev.bw
color 53,89,161
@@ -437,7 +437,7 @@ longLabel
parent H3K4me1
container multiWig
shortLabel H3K4me1_AF_Flu
- longLabel
+ longLabel
type bigWig
visibility full
aggregate transparentOverlay
@@ -456,7 +456,7 @@ longLabel
type bigWig
parent H3K4me1_AF_Flu
shortLabel H3K4me1_AF_Flu_avg
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K4me1_AF_Flu_avg.bw
color 232,135,168
@@ -464,7 +464,7 @@ longLabel
type bigWig
parent H3K4me1_AF_Flu
shortLabel H3K4me1_AF_Flu_stddev
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K4me1_AF_Flu_stdev.bw
color 204,0,0
@@ -472,7 +472,7 @@ track NA3
type bigWig
visibility full
shortLabel NA3
-longLabel
+longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K27me3_AF_NI_avg.bw
viewLimits 0:500
alwaysZero on
@@ -484,13 +484,13 @@ color 255,255,255
track H3K4me3
superTrack on show
shortLabel H3K4me3
-longLabel
+longLabel
track H3K4me3_EU_NI
parent H3K4me3
container multiWig
shortLabel H3K4me3_EU_NI
- longLabel
+ longLabel
type bigWig
visibility full
aggregate transparentOverlay
@@ -509,7 +509,7 @@ longLabel
type bigWig
parent H3K4me3_EU_NI
shortLabel H3K4me3_EU_NI_avg
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K4me3_EU_NI_avg.bw
color 135,168,232
@@ -517,7 +517,7 @@ longLabel
type bigWig
parent H3K4me3_EU_NI
shortLabel H3K4me3_EU_NI_stddev
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K4me3_EU_NI_stdev.bw
color 53,89,161
@@ -526,7 +526,7 @@ longLabel
parent H3K4me3
container multiWig
shortLabel H3K4me3_EU_Flu
- longLabel
+ longLabel
type bigWig
visibility full
aggregate transparentOverlay
@@ -545,7 +545,7 @@ longLabel
type bigWig
parent H3K4me3_EU_Flu
shortLabel H3K4me3_EU_Flu_avg
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K4me3_EU_Flu_avg.bw
color 232,135,168
@@ -553,7 +553,7 @@ longLabel
type bigWig
parent H3K4me3_EU_Flu
shortLabel H3K4me3_EU_Flu_stddev
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K4me3_EU_Flu_stdev.bw
color 204,0,0
@@ -562,7 +562,7 @@ longLabel
parent H3K4me3
container multiWig
shortLabel H3K4me3_AF_NI
- longLabel
+ longLabel
type bigWig
visibility full
aggregate transparentOverlay
@@ -581,7 +581,7 @@ longLabel
type bigWig
parent H3K4me3_AF_NI
shortLabel H3K4me3_AF_NI_avg
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K4me3_AF_NI_avg.bw
color 135,168,232
@@ -589,7 +589,7 @@ longLabel
type bigWig
parent H3K4me3_AF_NI
shortLabel H3K4me3_AF_NI_stddev
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K4me3_AF_NI_stdev.bw
color 53,89,161
@@ -598,7 +598,7 @@ longLabel
parent H3K4me3
container multiWig
shortLabel H3K4me3_AF_Flu
- longLabel
+ longLabel
type bigWig
visibility full
aggregate transparentOverlay
@@ -617,7 +617,7 @@ longLabel
type bigWig
parent H3K4me3_AF_Flu
shortLabel H3K4me3_AF_Flu_avg
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K4me3_AF_Flu_avg.bw
color 232,135,168
@@ -625,7 +625,7 @@ longLabel
type bigWig
parent H3K4me3_AF_Flu
shortLabel H3K4me3_AF_Flu_stddev
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K4me3_AF_Flu_stdev.bw
color 204,0,0
@@ -633,7 +633,7 @@ track NA4
type bigWig
visibility full
shortLabel NA4
-longLabel
+longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K27me3_AF_NI_avg.bw
viewLimits 0:500
alwaysZero on
@@ -645,13 +645,13 @@ color 255,255,255
track H3K27me3
superTrack on show
shortLabel H3K27me3
-longLabel
+longLabel
track H3K27me3_EU_NI
parent H3K27me3
container multiWig
shortLabel H3K27me3_EU_NI
- longLabel
+ longLabel
type bigWig
visibility full
aggregate transparentOverlay
@@ -670,7 +670,7 @@ longLabel
type bigWig
parent H3K27me3_EU_NI
shortLabel H3K27me3_EU_NI_avg
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K27me3_EU_NI_avg.bw
color 135,168,232
@@ -678,7 +678,7 @@ longLabel
type bigWig
parent H3K27me3_EU_NI
shortLabel H3K27me3_EU_NI_stddev
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K27me3_EU_NI_stdev.bw
color 53,89,161
@@ -687,7 +687,7 @@ longLabel
parent H3K27me3
container multiWig
shortLabel H3K27me3_EU_Flu
- longLabel
+ longLabel
type bigWig
visibility full
aggregate transparentOverlay
@@ -706,7 +706,7 @@ longLabel
type bigWig
parent H3K27me3_EU_Flu
shortLabel H3K27me3_EU_Flu_avg
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K27me3_EU_Flu_avg.bw
color 232,135,168
@@ -714,7 +714,7 @@ longLabel
type bigWig
parent H3K27me3_EU_Flu
shortLabel H3K27me3_EU_Flu_stddev
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K27me3_EU_Flu_stdev.bw
color 204,0,0
@@ -723,7 +723,7 @@ longLabel
parent H3K27me3
container multiWig
shortLabel H3K27me3_AF_NI
- longLabel
+ longLabel
type bigWig
visibility full
aggregate transparentOverlay
@@ -742,7 +742,7 @@ longLabel
type bigWig
parent H3K27me3_AF_NI
shortLabel H3K27me3_AF_NI_avg
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K27me3_AF_NI_avg.bw
color 135,168,232
@@ -750,7 +750,7 @@ longLabel
type bigWig
parent H3K27me3_AF_NI
shortLabel H3K27me3_AF_NI_stddev
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K27me3_AF_NI_stdev.bw
color 53,89,161
@@ -759,7 +759,7 @@ longLabel
parent H3K27me3
container multiWig
shortLabel H3K27me3_AF_Flu
- longLabel
+ longLabel
type bigWig
visibility full
aggregate transparentOverlay
@@ -778,7 +778,7 @@ longLabel
type bigWig
parent H3K27me3_AF_Flu
shortLabel H3K27me3_AF_Flu_avg
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K27me3_AF_Flu_avg.bw
color 232,135,168
@@ -786,7 +786,7 @@ longLabel
type bigWig
parent H3K27me3_AF_Flu
shortLabel H3K27me3_AF_Flu_stddev
- longLabel
+ longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K27me3_AF_Flu_stdev.bw
color 204,0,0
@@ -794,7 +794,7 @@ track NA5
type bigWig
visibility full
shortLabel NA5
-longLabel
+longLabel
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/H3K27me3_AF_NI_avg.bw
viewLimits 0:500
alwaysZero on
@@ -813,13 +813,13 @@ genome hg19
track RNAseq
superTrack on show
shortLabel RNAseq
-longLabel
+longLabel
track RNAseq_EU_NI
parent RNAseq
container multiWig
shortLabel RNAseq_EU_NI
- longLabel
+ longLabel
type bigWig
visibility full
aggregate transparentOverlay
@@ -837,7 +837,7 @@ longLabel
priority 22
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/RNAseq_EU_NI_fwd_avg.bw
shortLabel RNAseq_EU_NI_fwd_avg
- longLabel
+ longLabel
parent RNAseq_EU_NI
color 135,168,232
viewLimits 0:500
@@ -847,7 +847,7 @@ longLabel
priority 23
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/RNAseq_EU_NI_fwd_stdev.bw
shortLabel RNAseq_EU_NI_fwd_stdev
- longLabel
+ longLabel
parent RNAseq_EU_NI
color 53,89,161
viewLimits 0:500
@@ -857,7 +857,7 @@ longLabel
priority 24
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/RNAseq_EU_NI_rev_avg.bw
shortLabel RNAseq_EU_NI_rev_avg
- longLabel
+ longLabel
parent RNAseq_EU_NI
color 148,208,220
viewLimits 0:500
@@ -867,7 +867,7 @@ longLabel
priority 25
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/RNAseq_EU_NI_rev_stdev.bw
shortLabel RNAseq_EU_NI_rev_stdev
- longLabel
+ longLabel
parent RNAseq_EU_NI
color 53,144,162
viewLimits 0:500
@@ -878,7 +878,7 @@ longLabel
parent RNAseq
container multiWig
shortLabel RNAseq_EU_Flu
- longLabel
+ longLabel
type bigWig
visibility full
aggregate transparentOverlay
@@ -896,7 +896,7 @@ longLabel
priority 27
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/RNAseq_EU_Flu_fwd_avg.bw
shortLabel RNAseq_EU_Flu_fwd_avg
- longLabel
+ longLabel
parent RNAseq_EU_Flu
color 232,135,168
viewLimits 0:500
@@ -906,7 +906,7 @@ longLabel
priority 28
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/RNAseq_EU_Flu_fwd_stdev.bw
shortLabel RNAseq_EU_Flu_fwd_stdev
- longLabel
+ longLabel
parent RNAseq_EU_Flu
color 204,0,01
viewLimits 0:500
@@ -916,7 +916,7 @@ longLabel
priority 29
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/RNAseq_EU_Flu_rev_avg.bw
shortLabel RNAseq_EU_Flu_rev_avg
- longLabel
+ longLabel
parent RNAseq_EU_Flu
color 237,213,162
viewLimits 0:500
@@ -926,7 +926,7 @@ longLabel
priority 30
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/RNAseq_EU_Flu_rev_stdev.bw
shortLabel RNAseq_EU_Flu_rev_stdev
- longLabel
+ longLabel
parent RNAseq_EU_Flu
color 207,153,40
viewLimits 0:500
@@ -936,7 +936,7 @@ longLabel
parent RNAseq
container multiWig
shortLabel RNAseq_AF_NI
- longLabel
+ longLabel
type bigWig
visibility full
aggregate transparentOverlay
@@ -954,7 +954,7 @@ longLabel
priority 32
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/RNAseq_AF_NI_fwd_avg.bw
shortLabel RNAseq_AF_NI_fwd_avg
- longLabel
+ longLabel
parent RNAseq_AF_NI
color 135,168,232
viewLimits 0:500
@@ -964,7 +964,7 @@ longLabel
priority 33
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/RNAseq_AF_NI_fwd_stdev.bw
shortLabel RNAseq_AF_NI_fwd_stdev
- longLabel
+ longLabel
parent RNAseq_AF_NI
color 53,89,161
viewLimits 0:500
@@ -974,7 +974,7 @@ longLabel
priority 34
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/RNAseq_AF_NI_rev_avg.bw
shortLabel RNAseq_AF_NI_rev_avg
- longLabel
+ longLabel
parent RNAseq_AF_NI
color 148,208,220
viewLimits 0:500
@@ -984,7 +984,7 @@ longLabel
priority 35
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/RNAseq_AF_NI_rev_stdev.bw
shortLabel RNAseq_AF_NI_rev_stdev
- longLabel
+ longLabel
parent RNAseq_AF_NI
color 53,144,162
viewLimits 0:500
@@ -995,7 +995,7 @@ longLabel
parent RNAseq
container multiWig
shortLabel RNAseq_AF_Flu
- longLabel
+ longLabel
type bigWig
visibility full
aggregate transparentOverlay
@@ -1013,7 +1013,7 @@ longLabel
priority 37
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/RNAseq_AF_Flu_fwd_avg.bw
shortLabel RNAseq_AF_Flu_fwd_avg
- longLabel
+ longLabel
parent RNAseq_AF_Flu
color 232,135,168
viewLimits 0:500
@@ -1023,7 +1023,7 @@ longLabel
priority 38
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/RNAseq_AF_Flu_fwd_stdev.bw
shortLabel RNAseq_AF_Flu_fwd_stdev
- longLabel
+ longLabel
parent RNAseq_AF_Flu
color 204,0,01
viewLimits 0:500
@@ -1033,7 +1033,7 @@ longLabel
priority 39
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/RNAseq_AF_Flu_rev_avg.bw
shortLabel RNAseq_AF_Flu_rev_avg
- longLabel
+ longLabel
parent RNAseq_AF_Flu
color 237,213,162
viewLimits 0:500
@@ -1043,7 +1043,7 @@ longLabel
priority 40
bigDataUrl https://emc.genome.mcgill.ca/hg19/barreiro/RNAseq_AF_Flu_rev_stdev.bw
shortLabel RNAseq_AF_Flu_rev_stdev
- longLabel
+ longLabel
parent RNAseq_AF_Flu
color 207,153,40
viewLimits 0:500
diff --git a/epivar-prod/node2/about.md b/epivar-prod/node2/about.md
index a6455077..27eecd4c 100644
--- a/epivar-prod/node2/about.md
+++ b/epivar-prod/node2/about.md
@@ -26,7 +26,7 @@ All the datasets that have been generated as part of this project are summarized
[made available here](#datasets). Access to some of the raw datasets require a formal data access request but all
resources are available freely. Please cite the appropriate paper(s) if you use the data.
-We have also built a [browser tool](https://flu-infection.vhost38.genap.ca/dataset/overview) that allows navigation of
+We have also built a [browser tool](https://flu-infection.vhost38.genap.ca/about) that allows navigation of
these rich datasets by condition, ancestry and, importantly, haplotype. This allows an in-depth exploration of the
quantitative trait loci and other key results reported in the studies above. Using this tool requires a terms-of-use
agreement to ensure data privacy conditions are respected.
@@ -115,7 +115,7 @@ access number [GSE225708](https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE
Genomic tracks by condition and ancestry are available [here](https://flu-infection.vhost38.genap.ca/explore).
-We constructed [a versatile QTL browser](https://flu-infection.vhost38.genap.ca/dataset/overview), which allows users to
+We constructed [a versatile QTL browser](https://flu-infection.vhost38.genap.ca/about), which allows users to
explore and visualize mapped QTLs for gene expression, chromatin accessibility, histone modifications and DNA
methylation.
diff --git a/epivar-prod/node2/config.js b/epivar-prod/node2/config.js
index 9488d5ff..775219df 100644
--- a/epivar-prod/node2/config.js
+++ b/epivar-prod/node2/config.js
@@ -38,8 +38,8 @@ module.exports = {
vcfSampleNameConverter: name => name.split('_')[1], // name => name
/*
- * VCF contigs have correct format, use identity function (default value)
+ * VCF contigs have chr prefix; ensure we prepend this without duplication.
*/
- // vcfChrTransform: (chr) => chr,
+ vcfChrTransform: (chr) => "chr" + chr.replace(/^chr/, ""),
},
};
diff --git a/epivar-prod/portal.env b/epivar-prod/portal.env
index 164b4a0f..8c26ad7b 100644
--- a/epivar-prod/portal.env
+++ b/epivar-prod/portal.env
@@ -1 +1 @@
-EPIVAR_NODES=https://flu-infection.vhost38.genap.ca/aracena-hg19
+EPIVAR_NODES=https://flu-infection.vhost38.genap.ca/aracena-hg19;https://flu-infection.vhost38.genap.ca/aracena-hg38
diff --git a/models/samples.mjs b/models/samples.mjs
index a13915d7..212bbe86 100644
--- a/models/samples.mjs
+++ b/models/samples.mjs
@@ -37,6 +37,7 @@ export async function vcfQuery(contig, start, end) {
const lines = [];
// tabix JS takes in 0-based half-open coordinates, which we convert from queryMap taking 1-based closed coordinates
await VCF_TABIX_FILE.getLines(contig, start - 1, end, line => lines.push(vcfParser.parseLine(line)));
+ console.info(`queried vcf: ${contig}:${start}-${end}; got ${lines.length} lines`);
return lines;
}
@@ -44,7 +45,10 @@ export async function vcfQuery(contig, start, end) {
export function normalizeSamplesMap(lines) {
const variant = lines.find(vcfFilterFn);
- if (!variant) return undefined;
+ if (!variant) {
+ console.error(`could not find any variants (got ${lines?.length ?? 'undefined'} lines)`);
+ return undefined;
+ }
const variantData = {
chrom: variant.CHROM,
diff --git a/routes/auth.mjs b/routes/auth.mjs
index 2c57b171..3d60b892 100644
--- a/routes/auth.mjs
+++ b/routes/auth.mjs
@@ -48,9 +48,11 @@ router.get("/login",
(req, res, next) => {
const returnTo = req.query.redirect;
if (returnTo) {
+ console.info(`/api/auth/login: redirecting to ${returnTo}`);
res.redirect(returnTo);
+ } else {
+ next();
}
- next();
});
// router.get("/callback", passport.authenticate("openidconnect", {