diff --git a/src/content/app/genome-browser/components/zmenu/zmenus/VariantZmenu.tsx b/src/content/app/genome-browser/components/zmenu/zmenus/VariantZmenu.tsx index 5b680434fb..7a95803976 100644 --- a/src/content/app/genome-browser/components/zmenu/zmenus/VariantZmenu.tsx +++ b/src/content/app/genome-browser/components/zmenu/zmenus/VariantZmenu.tsx @@ -17,6 +17,7 @@ import React from 'react'; import * as urlFor from 'src/shared/helpers/urlHelper'; +import { getChrLocationStr } from 'src/content/app/genome-browser/helpers/browserHelper'; import { buildFocusVariantId } from 'src/shared/helpers/focusObjectHelpers'; import { isEnvironment, Environment } from 'src/shared/helpers/environment'; @@ -56,9 +57,16 @@ const VariantZmenu = (props: Props) => { variantName: variantMetadata.id }); + const locationForVariant = calculateLocation( + variantMetadata.region_name, + variantMetadata.start, + variantMetadata.end + ); + const linkToVariantInGenomeBrowser = urlFor.browser({ genomeId: genomeIdForUrl, - focus: variantId + focus: variantId, + location: locationForVariant }); return ( @@ -82,4 +90,40 @@ const VariantZmenu = (props: Props) => { ); }; +/** + * Consider that the genome browser shows the detailed zoomed-in view for variants + * at scales between 2**1 and 2**6 base pairs. 2**6 is 64; and when the genome browser zooms out to this point, + * it switches to the zoomed-out view. + */ +const VARIANT_DETAILS_MAX_NUCLEOTIDES = 2 ** 6 - 1; // variant details program of the genome browser shows up to 63 nucleotides +const MAX_NUCLEOTIDES_PER_VIEWPORT = VARIANT_DETAILS_MAX_NUCLEOTIDES - 2; // to leave at least one nucleotide on either side +const MIN_NUCLEOTIDES_PER_VIEWPORT = 32; // genome browser doesn't zoom past 32 nucleotides in viewport + +const calculateLocation = ( + regionName: string, + variantStart: number, + variantEnd: number +) => { + const variantLength = variantEnd - variantStart; + const variantMidpoint = variantStart + Math.ceil(variantLength / 2); + + let start: number; + let end: number; + + if (variantLength < MIN_NUCLEOTIDES_PER_VIEWPORT) { + start = variantMidpoint - MIN_NUCLEOTIDES_PER_VIEWPORT / 2; + end = variantMidpoint + MIN_NUCLEOTIDES_PER_VIEWPORT / 2; + } else if (variantLength <= MAX_NUCLEOTIDES_PER_VIEWPORT) { + start = variantMidpoint - MAX_NUCLEOTIDES_PER_VIEWPORT / 2; + end = variantMidpoint + MAX_NUCLEOTIDES_PER_VIEWPORT / 2; + } else { + const viewportSize = variantLength / 0.7; // variant should take 70% of the viewport + const halfViewportSize = Math.ceil(viewportSize / 2); + start = Math.max(variantMidpoint - halfViewportSize, 0); + end = variantMidpoint + halfViewportSize; // hopefully, this won't exceed region length; might be a problem for circular chromosomes + } + + return getChrLocationStr([regionName, start, end]); +}; + export default VariantZmenu; diff --git a/src/content/app/genome-browser/services/genome-browser-service/genomeBrowserCommands.ts b/src/content/app/genome-browser/services/genome-browser-service/genomeBrowserCommands.ts index 10959fdcaa..df7a28dfb0 100644 --- a/src/content/app/genome-browser/services/genome-browser-service/genomeBrowserCommands.ts +++ b/src/content/app/genome-browser/services/genome-browser-service/genomeBrowserCommands.ts @@ -45,6 +45,9 @@ export const setBrowserLocation = (payload: { const { genomeBrowser, regionName, start, end, genomeId, focus } = payload; genomeBrowser.set_stick(`${genomeId}:${regionName}`); + genomeBrowser.goto(start, end); + genomeBrowser.wait(); + if (focus) { setFocus({ genomeBrowser, @@ -53,8 +56,6 @@ export const setBrowserLocation = (payload: { focusType: focus.type }); } - - genomeBrowser.goto(start, end); }; export const toggleTrack = (payload: { diff --git a/src/content/app/genome-browser/services/genome-browser-service/types/zmenu.ts b/src/content/app/genome-browser/services/genome-browser-service/types/zmenu.ts index e146244642..d474714335 100644 --- a/src/content/app/genome-browser/services/genome-browser-service/types/zmenu.ts +++ b/src/content/app/genome-browser/services/genome-browser-service/types/zmenu.ts @@ -68,6 +68,7 @@ export type ZmenuContentVariantMetadata = { id: string; // just the rsID; will have to be combined with region name and start coordinate for full id region_name: string; // needed to generate full variant id start: number; // needed to generate full variant id + end: number; // needed to correctly size the viewport when focusing on a variant position: string; // formatted as "region:start-end". NOTE: start and end coordinates have commas in them variety: string; // e.g. SNV, INS... Do we have a full list of such varieties? type: ZmenuFeatureType.VARIANT;