Skip to content

Commit

Permalink
Merge pull request #14 from scottcain/add_gene_panel
Browse files Browse the repository at this point in the history
Add gene panel
  • Loading branch information
scottcain authored May 24, 2023
2 parents 3befca9 + 621cc55 commit c316c22
Show file tree
Hide file tree
Showing 17 changed files with 1,161 additions and 647 deletions.
25 changes: 25 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint"],
"globals": { "console": true, "test": true, "global": true },
"settings": {
"react": {
"version": "detect"
}
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react/recommended",
"plugin:react/jsx-runtime",
"plugin:react-hooks/recommended"
],
"rules": {
"no-underscore-dangle": 0,
"curly": "error",
"@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/explicit-module-boundary-types": 0,
"@typescript-eslint/ban-ts-comment": 0,
"react/prop-types": 0
}
}
4 changes: 4 additions & 0 deletions .github/workflows/push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,7 @@ jobs:
uses: bahmutov/npm-install@v1
- name: Test codebase
run: yarn test
- name: Lint codebase
run: yarn Lint
- name: Typecheck codebase
run: yarn tsc
60 changes: 8 additions & 52 deletions app/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,59 +1,15 @@
import { FC, ReactElement, useState, useEffect } from "react";
import { GenericSeqPanel } from "generic-sequence-panel";
import { GenericGeneSeqPanel } from "generic-sequence-panel";

type UpdateSeqProps = {
trans: string,
mod: string,
}

const UpdateSeq: FC<UpdateSeqProps> = ( {trans, mod } ): ReactElement => {
useEffect(() => {
}, [trans, mod]);

return (
<GenericSeqPanel
refseq="X"
start={13201770}
end={13216729}
gene="WBGene00006749"
transcript={trans}
mode={mod}
export default function App() {
return (
<GenericGeneSeqPanel
refseq="II"
start={162374}
end={170631}
gene="WBGene00001340"
nclistbaseurl="https://s3.amazonaws.com/agrjbrowse/MOD-jbrowses/WormBase/WS288/c_elegans_PRJNA13758/"
urltemplate="tracks/Curated_Genes/{refseq}/trackData.jsonz"
fastaurl="https://s3.amazonaws.com/wormbase-modencode/fasta/current/c_elegans.PRJNA13758.WS284.genomic.fa.gz"
/>
);
}

function App() {
var transcript = "R12H7.1a.2";
var mode = "gene";

const [valueTranscript, setValueTranscript] = useState(transcript);
const [valueMode, setValueMode] = useState(mode);

return (
<div>
Transcript:<select onChange={(e) => {setValueTranscript(e.target.value)}}>
<option value="R12H7.1a.1">R12H7.1a.1</option>
<option value="R12H7.1a.2">R12H7.1a.2</option>
<option value="R12H7.1b.1">R12H7.1b.1</option>
</select>
Mode:<select onChange={(e) => {setValueMode(e.target.value)}}>
<option value="gene">gene</option>
<option value="cds">CDS</option>
<option value="cdna">cDNA</option>
<option value="protein">protein</option>
<option value="genomic">genomic</option>
<option value="genomic_sequence_updown">genomic +500bp up and down stream</option>
<option value="gene_collapsed_intron">gene with colapsed introns</option>
<option value="gene_updownstream">gene with 500bp up and down stream</option>
<option value="gene_updownstream_collapsed_intron">gene with 500bp up and down stream and colapsed introns</option>
</select>
<br />
<UpdateSeq trans={valueTranscript} mod={valueMode} />
</div>
);
}

export default App;
9 changes: 4 additions & 5 deletions app/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import React from "react";
// eslint-disable-next-line @typescript-eslint/no-unused-vars
//import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.tsx";
import App from "./App";
import { Buffer } from "buffer";

window.Buffer = Buffer;

ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
<React.StrictMode>
<App />
</React.StrictMode>,
<App />,
);
2 changes: 1 addition & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
preset: "ts-jest",
testPathIgnorePatterns: ["/dist/"],
testPathIgnorePatterns: ["/dist/", "/esm/"],
testEnvironment: "jsdom",
};
6 changes: 3 additions & 3 deletions lib/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
"repository": "scottcain/seqpanel",
"main": "dist/index.js",
"module": "esm/index.js",
"version": "1.0.2",
"keywords" : [
"version": "1.1.0",
"keywords": [
"bioinformatics",
"gene page",
"FASTA",
Expand Down Expand Up @@ -40,7 +40,7 @@
"dependencies": {
"@gmod/indexedfasta": "^2.0.4",
"@gmod/nclist": "^1.0.0",
"@jbrowse/core": "^2.4.1",
"@jbrowse/core": "2.4.2",
"generic-filehandle": "^3.0.1",
"mobx": "^6.8.0",
"mobx-state-tree": "^5.1.8",
Expand Down
32 changes: 32 additions & 0 deletions lib/src/accessFasta.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { RemoteFile } from "generic-filehandle";
import { BgzipIndexedFasta } from "@gmod/indexedfasta";

export async function accessFasta(
refseq: string,
start: number,
end: number,
fastaURL: string,
) {
const fastaFilehandle = new RemoteFile(fastaURL);
const faiFilehandle = new RemoteFile(fastaURL + ".fai");
const gziFilehandle = new RemoteFile(fastaURL + ".gzi");

const t = new BgzipIndexedFasta({
fasta: fastaFilehandle,
fai: faiFilehandle,
gzi: gziFilehandle,
chunkSizeLimit: 500000,
});

const upstreamstart = start - 499;
const downstreamend = end + 499;
const seq = await t.getSequence(refseq, start, end);
const upstream = await t.getSequence(refseq, upstreamstart, start);
const downstream = await t.getSequence(refseq, end, downstreamend);

return {
seq: seq || "",
upstream: upstream || "",
downstream: downstream || "",
};
}
28 changes: 28 additions & 0 deletions lib/src/assembleBundle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Feature } from "@jbrowse/core/util";
import NCListFeature from "./NCListFeature";
import { accessFasta } from "./accessFasta";

export async function assembleBundle(props: {
nclistbaseurl: string;
urltemplate: string;
fastaurl: string;
refseq: string;
gene: string;
transcript: Feature;
}) {
const { fastaurl, transcript, refseq } = props;
const sequence = await accessFasta(
refseq,
transcript.get("start"),
transcript.get("end"),
fastaurl,
);

const f = new NCListFeature(transcript);
return {
feature: f.toJSON(),
sequence,
mode: "protein", //this will probably be overridden by the SeqPanel component
intronBp: 10,
};
}
89 changes: 89 additions & 0 deletions lib/src/components/GenericGeneSeqPanel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import React, { useState, useEffect } from "react";
import GenericSeqPanel from "./GenericSeqPanel";
import transcriptList from "../fetchTranscripts";
import { Feature } from "@jbrowse/core/util";

export default function GenericGeneSeqPanel(props: {
nclistbaseurl: string;
fastaurl: string;
refseq: string;
start: number;
end: number;
gene: string;
urltemplate: string;
}) {
const { nclistbaseurl, fastaurl, refseq, start, end, gene, urltemplate } =
props;
const [result, setResult] = useState<Feature[]>();
const [error, setError] = useState<unknown>();
const [transcript, setTranscript] = useState<Feature>();
const [mode, setMode] = useState("gene");
const feature = transcript || result?.[0];
useEffect(() => {
(async () => {
try {
const res = await transcriptList({
nclistbaseurl,
fastaurl,
refseq,
start,
end,
gene,
urltemplate,
});
setResult(res);
} catch (e) {
console.error(e);
setError(e);
}
})();
}, [nclistbaseurl, fastaurl, refseq, start, end, gene, urltemplate]);

if (error) {
return <div style={{ color: "red" }}>{`${error}`}</div>;
} else if (!result) {
return <div>Loading...</div>;
} else {
return (
<div className="GenericGeneSeqPanel">
Transcript:
<select
onChange={e =>
setTranscript(result.find(r => r.id() === e.target.value))
}
>
{result.map(r => (
<option key={r.id()} value={r.id()}>
{r.get("name")}
</option>
))}
</select>
Mode:
<select onChange={e => setMode(e.target.value)}>
<option value="gene">gene</option>
<option value="cds">CDS</option>
<option value="cdna">cDNA</option>
<option value="protein">protein</option>
<option value="genomic">genomic</option>
<option value="genomic_sequence_updown">
genomic +500bp up and down stream
</option>
<option value="gene_collapsed_intron">
gene with colapsed introns
</option>
<option value="gene_updownstream">
gene with 500bp up and down stream
</option>
<option value="gene_updownstream_collapsed_intron">
gene with 500bp up and down stream and colapsed introns
</option>
</select>
<br />
{feature ? (
<GenericSeqPanel {...props} transcript={feature} mode={mode} />
) : null}
</div>
);
}
}
Loading

0 comments on commit c316c22

Please sign in to comment.