Skip to content

Commit

Permalink
added snp search and coordinates suggestions
Browse files Browse the repository at this point in the history
  • Loading branch information
NishiPhalke committed Oct 9, 2020
1 parent b50d06d commit 2bfb976
Show file tree
Hide file tree
Showing 13 changed files with 120 additions and 49 deletions.
1 change: 1 addition & 0 deletions debug.log
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[1009/083544.836:ERROR:directory_reader_win.cc(43)] FindFirstFile: The system cannot find the path specified. (0x3)
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "gbwebapp",
"version": "2.0.11",
"version": "2.0.12",
"private": true,
"dependencies": {
"bigwig-reader": "^1.3.1",
Expand Down
5 changes: 1 addition & 4 deletions src/components/customtrack/addtrack.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import React, { useState } from 'react';
import {
AddTrackProps,
TrackType,
} from './types';
import { AddTrackProps, TrackType } from './types';
import { Button, Modal, Message, Input, Radio, Dropdown } from 'semantic-ui-react';
import ColorPicker from './colorpicker';
import { TEST_QUERY } from './queries';
Expand Down
14 changes: 14 additions & 0 deletions src/components/search/queries.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
export const SNP_AUTOCOMPLETE_QUERY = `
query suggestions($assembly: String!, $snpid: String!) {
snpAutocompleteQuery(assembly: $assembly, snpid: $snpid) {
rsId
coordinates {
chromosome
start
end
}
}
}`;

export const GENE_AUTOCOMPLETE_QUERY = `
query Genes(
$id: [String]
Expand All @@ -8,6 +20,7 @@ export const GENE_AUTOCOMPLETE_QUERY = `
$end: Int
$gene_type: String
$havana_id: String
$orderby: String
$name_prefix: String
$limit: Int
$assembly: String!
Expand All @@ -20,6 +33,7 @@ export const GENE_AUTOCOMPLETE_QUERY = `
start: $start
end: $end
gene_type: $gene_type
orderby: $orderby
havana_id: $havana_id
name_prefix: $name_prefix
limit: $limit
Expand Down
2 changes: 1 addition & 1 deletion src/components/search/refseqsearchbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const RefSeqSearchBox: React.FC<RefSeqSearchBoxProps> = (props) => {
<Form onSubmit={onSubmit}>
<Search
input={{ fluid: true }}
placeholder="enter gene name or locus"
placeholder="enter gene name"
onSearchChange={onSearchChange}
onResultSelect={onResultSelect}
results={results}
Expand Down
103 changes: 74 additions & 29 deletions src/components/search/searchbox.tsx
Original file line number Diff line number Diff line change
@@ -1,57 +1,102 @@
import React, { useState, useCallback } from 'react';
import { Form, Search } from 'semantic-ui-react';
import { GENE_AUTOCOMPLETE_QUERY } from './queries';
import { GENE_AUTOCOMPLETE_QUERY, SNP_AUTOCOMPLETE_QUERY } from './queries';
import { uniq, isCoordinate } from './utils';
import { SearchBoxProps, Result } from './types';

const SearchBox: React.FC<SearchBoxProps> = (props) => {
const [searchVal, setSearchVal] = useState<string | undefined>();
const [selectedsearchVal, setSelectedsearchVal] = useState<Result | undefined>();
const [selectedSearchVal, setSelectedsearchVal] = useState<Result | undefined>();
const [results, setResults] = useState<Result[]>();

const onSubmit = useCallback(() => {
if (searchVal && isCoordinate(searchVal)) {
props.onSearchSubmit && props.onSearchSubmit(searchVal);
return;
}
let gene = selectedsearchVal ? selectedsearchVal : results && results[0];
let gene = selectedSearchVal ? selectedSearchVal : results && results[0];

if (gene === undefined) return;
const coords = gene.description.split('\n');
props.onSearchSubmit &&
isCoordinate(gene.description.split('\n')[1]) &&
props.onSearchSubmit(gene.description.split('\n')[1]);
}, [searchVal, results, props, selectedsearchVal]);
isCoordinate(coords.length === 2 ? coords[1] : coords[0]) &&
props.onSearchSubmit(coords.length === 2 ? coords[1] : coords[0], gene.title, !(coords.length === 2));
}, [searchVal, results, props, selectedSearchVal]);
const onSearchChange = useCallback(
async (e, { value }) => {
let val: string = value.toLowerCase();
let rs: Result[] = [];
setSearchVal(value);
if (val.startsWith('rs') && props.assembly === 'GRCh38') {
const response = await fetch('https://snps.staging.wenglab.org/graphql', {
method: 'POST',
body: JSON.stringify({
query: SNP_AUTOCOMPLETE_QUERY,
variables: { snpid: value, assembly: 'hg38', limit: 3 },
}),
headers: { 'Content-Type': 'application/json' },
});
let rst = (await response.json()).data?.snpAutocompleteQuery
?.slice(0, 3)
.map(
(result: {
rsId: string;
coordinates: { chromosome: string; start: number; end: number };
}) => ({
title: result.rsId,
description:
result.coordinates.chromosome +
':' +
result.coordinates.start +
'-' +
result.coordinates.end,
})
);
rs = uniq(rst, value);
}
if (
value.toLowerCase().match(/^chr[0-9x-y]+$/g) &&
value.toLowerCase().match(/^chr[0-9x-y]+$/g).length === 1 &&
value.length <= 5
) {
rs = [
{ title: value + ':' + '1' + '-100000', description: '' + '\n' + value + ':' + '1' + '-100000' },
{ title: value + ':' + '1' + '-1000000', description: '' + '\n' + value + ':' + '1' + '-1000000' },
{
title: value + ':' + '1' + '-10000000',
description: '' + '\n' + value + ':' + '1' + '-10000000',
},
];
}
const response = await fetch('https://ga.staging.wenglab.org/graphql', {
method: 'POST',
body: JSON.stringify({
query: GENE_AUTOCOMPLETE_QUERY,
variables: { name_prefix: value, assembly: props.assembly, limit: 3 },
variables: { name_prefix: value, assembly: props.assembly, orderby: 'name', limit: 3 },
}),
headers: { 'Content-Type': 'application/json' },
});
setSearchVal(value);
let res: Result[] = uniq(
(await response.json()).data?.gene?.map(
(result: {
name: string;
id: string;
coordinates: { chromosome: string; start: number; end: number };
}) => ({
title: result.name,
description:
result.id +
'\n' +
result.coordinates.chromosome +
':' +
result.coordinates.start +
'-' +
result.coordinates.end,
})
),
value
let genesRes = (await response.json()).data?.gene?.map(
(result: {
name: string;
id: string;
coordinates: { chromosome: string; start: number; end: number };
}) => ({
title: result.name,
description:
result.id +
'\n' +
result.coordinates.chromosome +
':' +
result.coordinates.start +
'-' +
result.coordinates.end,
})
);
setResults(res);

let res: Result[] | undefined =
genesRes && genesRes.length === 0 && rs.length > 0 ? undefined : uniq(genesRes, value);
setResults(rs ? (res ? [...rs, ...res] : rs) : res);
},
[props.assembly]
);
Expand All @@ -64,7 +109,7 @@ const SearchBox: React.FC<SearchBoxProps> = (props) => {
<Form onSubmit={onSubmit}>
<Search
input={{ fluid: true }}
placeholder="enter gene name or locus"
placeholder="enter gene name,snp or locus"
onSearchChange={onSearchChange}
onResultSelect={onResultSelect}
results={results}
Expand Down
2 changes: 1 addition & 1 deletion src/components/search/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export type SearchBoxProps = {
assembly: string;
onSearchSubmit: (domain: string) => void;
onSearchSubmit: (domain: string, name?: string, isSnp?: boolean) => void;
};

export type RefSeqSearchBoxProps = {
Expand Down
1 change: 1 addition & 0 deletions src/components/search/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const uniq = (results: Result[], d: string): Result[] => {
});
if (!found) r.push(result);
});

return r.length ? r : [{ title: d, description: '' }];
};

Expand Down
8 changes: 4 additions & 4 deletions src/genomes/default/default.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ import { GenomicRange } from 'ts-bedkit';
const BamTrack_Limit = 50000;
const transcriptPack_Limit = 3000000;
const transcript_Limit = 10000000;
const bigbed_Limit = 10000000
const bigbed_Limit = 10000000;

const DefaultBrowser: React.FC<DefaultProps> = (props) => {
let defaultTracksModes: Record<string, string> = {};

console.log('props.domain',props.domain)
defaultTracksModes['refseqgenes_transcript_track'] = '';
defaultTracksModes['refseqxeno_transcript_track'] = '';

Expand Down Expand Up @@ -373,7 +373,7 @@ const DefaultBrowser: React.FC<DefaultProps> = (props) => {
id={peak.title}
/>
</WrappedTrack>
) : props.domain.end - props.domain.start > bigbed_Limit && !peak.displayMode ? (
) : props.domain.end - props.domain.start > bigbed_Limit && !peak.displayMode ? (
<WrappedSquishBigBed
title={peak.title}
width={2000}
Expand All @@ -387,7 +387,7 @@ const DefaultBrowser: React.FC<DefaultProps> = (props) => {
titleSize={12}
trackMargin={12}
/>
): (
) : (
<WrappedDenseBigBed
title={peak.title}
width={2000}
Expand Down
4 changes: 2 additions & 2 deletions src/genomes/hg19/browser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ const tracks = (range: Domain) => [
const BamTrack_Limit = 50000;
const transcriptPack_Limit = 3000000;
const transcript_Limit = 10000000;
const bigbed_Limit = 10000000
const bigbed_Limit = 10000000;

const Hg19Browser: React.FC<Hg19BrowserProps> = (props) => {
let defaultTracksModes: Record<string, string> = {};
Expand Down Expand Up @@ -369,7 +369,7 @@ const Hg19Browser: React.FC<Hg19BrowserProps> = (props) => {
titleSize={12}
trackMargin={12}
/>
): (
) : (
<WrappedDenseBigBed
title={peak.title}
width={2000}
Expand Down
10 changes: 5 additions & 5 deletions src/genomes/hg38/browser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const ldTrack_Limit = 5000000;
const BamTrack_Limit = 50000;
const transcriptPack_Limit = 3000000;
const transcript_Limit = 10000000;
const bigbed_Limit = 10000000;
const bigbed_Limit = 10000000;

const Hg38Browser: React.FC<Hg38BrowserProps> = (props) => {
let defaultTracksModes: Record<string, string> = {};
Expand All @@ -65,12 +65,12 @@ const Hg38Browser: React.FC<Hg38BrowserProps> = (props) => {
defaultTracksModes['AFR_LdTrack'] = 'dense';
defaultTracksModes['EUR_LdTrack'] = 'dense';
defaultTracksModes['AMR_LdTrack'] = 'dense';

let noOfRows = +(+Math.round((tracks(props.domain).length + 5) / 5)).toFixed() + 1;
const [defaultTracks, setDefaultTracks] = useState<Record<string, string>>(defaultTracksModes);
const customTracks = props.customTracks && Object.values(props.customTracks).filter((ct) => !ct.track.baiUrl);
const bamCustomTracks = props.customTracks && Object.values(props.customTracks).filter((ct) => ct.track.baiUrl);

let pks: Record<
string,
{ peaks: { chr: string; start: number; end: number }[] | []; title: string; displayMode?: string }
Expand Down Expand Up @@ -130,8 +130,8 @@ const Hg38Browser: React.FC<Hg38BrowserProps> = (props) => {
}
}}
>
<WrappedTrack width={2000} height={70} title="scale" id="ruler" titleSize={12} trackMargin={12}>
<RulerTrack width={2000} height={70} domain={props.domain} />
<WrappedTrack width={2000} height={60} title="scale" id="ruler" titleSize={12} trackMargin={12}>
<RulerTrack width={2000} height={60} domain={props.domain} />
</WrappedTrack>
{defaultTracks['transcript'] === 'hide' ? (
<WrappedTrack width={2000} height={0} id={'transcript'}>
Expand Down
2 changes: 1 addition & 1 deletion src/genomes/mm10/browser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ const Mm10Browser: React.FC<Mm10BrowserProps> = (props) => {
titleSize={12}
trackMargin={12}
/>
): (
) : (
<WrappedDenseBigBed
title={peak.title}
width={2000}
Expand Down
15 changes: 14 additions & 1 deletion src/genomes/page/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ const GenomeBrowserPage: React.FC<GenomeBrowserPageProps> = (props) => {
}
}, [props.assembly]);
useEffect(() => {
console.log(chromLength,domain?.chromosome)
if ((!genomeConfig[props.assembly] || !genomeConfig[props.assembly].domain) && chromLength) {
if (transcriptCoordinates) {
let genelength = transcriptCoordinates.coordinates.end - transcriptCoordinates.coordinates.start;
Expand Down Expand Up @@ -354,7 +355,19 @@ const GenomeBrowserPage: React.FC<GenomeBrowserPageProps> = (props) => {
<br />
<div style={{ width: '75%', margin: '0 auto' }}>
<SearchBoxComponent
onSearchSubmit={(domain: string) => onDomainChanged(parseDomain(domain))}
onSearchSubmit={(domain: string, name?: string, isSnp?: boolean) => {
let d: Domain = parseDomain(domain);
console.log(d, 'd');
if (isSnp) {
d = {
...d,
start: d.start - 10000,
end: d.end + 10000,
};
setAnchor(name);
}
onDomainChanged(d);
}}
assembly={props.assembly === 'hg38' ? 'GRCh38' : props.assembly}
/>
</div>
Expand Down

0 comments on commit 2bfb976

Please sign in to comment.