Skip to content

Commit

Permalink
Merge pull request #24 from theosanderson/seq-search
Browse files Browse the repository at this point in the history
Display antisense strand
  • Loading branch information
theosanderson authored Jul 28, 2023
2 parents 1d0d00e + 5ab198f commit a81fad3
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 9 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@headlessui/react": "^1.7.16",
"@tanstack/react-virtual": "^3.0.0-beta.48",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
Expand Down
65 changes: 60 additions & 5 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import React, {
} from "react";
import "rc-slider/assets/index.css";
import "./App.css";
import { Dialog } from "@headlessui/react";

import ClipLoader from "react-spinners/ClipLoader";
import { genbankToJson } from "bio-parsers";
Expand All @@ -17,6 +18,8 @@ import { DebounceInput } from "react-debounce-input";
import { useWindowVirtualizer } from "@tanstack/react-virtual";
import Slider, { Range } from "rc-slider";
import { AiOutlineZoomIn, AiOutlineZoomOut } from "react-icons/ai";
// settings icon
import { MdSettings } from "react-icons/md";
import { GiDna1 } from "react-icons/gi";
import {BsArrowRightCircleFill, BsArrowLeftCircleFill} from "react-icons/bs";
import { ToastContainer, toast } from "react-toastify";
Expand Down Expand Up @@ -156,10 +159,13 @@ function SearchPanel({
);
}

const ConfigPanel = ({ zoomLevel, setZoomLevel }) => {
const ConfigPanel = ({ zoomLevel, setZoomLevel, configModalOpen, setConfigModalOpen }) => {
// zoom slider
return (
<>
<button className="inline-block mr-4 text-gray-400" onClick={() => setConfigModalOpen(true)}>
<MdSettings className="inline-block" />
</button>
<button
className="inline-block"
onClick={() => setZoomLevel((x) => x - 0.1)}
Expand All @@ -173,7 +179,7 @@ const ConfigPanel = ({ zoomLevel, setZoomLevel }) => {
max={1}
step={0.001}
style={{ width: 150 }}
className="inline-block mx-5"
className="inline-block mx-3"
/>
<button
className="inline-block"
Expand Down Expand Up @@ -378,6 +384,8 @@ function GensploreView({ genbankString, searchInput, setSearchInput }) {
}, [centeredNucleotide, zoomLevel]);

const [lastSearch, setLastSearch] = useState(null);
const [enableRC, setEnableRC] = useState(false);
const [configModalOpen, setConfigModalOpen] = useState(false);

useEffect(() => {
if (!intSearchInput) return;
Expand Down Expand Up @@ -470,7 +478,52 @@ function GensploreView({ genbankString, searchInput, setSearchInput }) {
);
}

return (
return (<>
<Dialog
open={configModalOpen}
onClose={() => setConfigModalOpen(false)}
className="fixed z-50 max-w-2xl px-4 py-6 bg-white rounded-lg shadow-xl sm:px-6 sm:py-8 sm:pb-4 sm:pt-6"
>

<Dialog.Panel
className="fixed inset-0 flex items-center justify-center bg-gray-500 bg-opacity-75 transition-opacity"
style={{ zIndex: 1000 }}
>
<div className="bg-white rounded-lg px-4 py-4 sm:px-6 sm:py-6 shadow-md max-w-md mx-auto">
<Dialog.Title
as="h3"
className="text-lg font-medium leading-6 text-gray-900 mb-4"
>
Settings
</Dialog.Title>

<Dialog.Description
className="text-base text-gray-600 mb-4"
>
Customize appearance
</Dialog.Description>

<p className="text-sm text-gray-500">
<label>
<input type="checkbox" checked={enableRC} onChange={(e) => setEnableRC(e.target.checked)} />
<span className="ml-2">Display antisense strand</span>
</label>
</p>

<div className="mt-4 flex justify-end">
<button
type="button"
className="inline-flex justify-center px-4 py-2 text-sm font-medium text-gray-700 bg-gray-100 border border-transparent rounded-md hover:bg-gray-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-blue-500"
onClick={() => setConfigModalOpen(false)}
>
Close
</button>
</div>
</div>
</Dialog.Panel>
</Dialog>


<div className="w-full p-5">
<ToastContainer />
{true && (
Expand All @@ -491,8 +544,8 @@ function GensploreView({ genbankString, searchInput, setSearchInput }) {
</div>
)}

<div className="fixed bottom-0 right-0 z-10 w-64 h-12 p-2 rounded shadow bg-white">
<ConfigPanel zoomLevel={zoomLevel} setZoomLevel={setZoomLevel} />
<div className="fixed bottom-0 right-0 z-10 w-72 h-12 p-2 rounded shadow bg-white">
<ConfigPanel zoomLevel={zoomLevel} setZoomLevel={setZoomLevel} configModalOpen={configModalOpen} setConfigModalOpen={setConfigModalOpen} />
</div>

<div className="w-full">
Expand Down Expand Up @@ -571,6 +624,7 @@ function GensploreView({ genbankString, searchInput, setSearchInput }) {
setWhereMouseCurrentlyIs={setWhereMouseCurrentlyIs}
sequenceHits={sequenceHits}
curSeqHitIndex={curSeqHitIndex}
enableRC={enableRC}
/>
</div>
);
Expand All @@ -582,6 +636,7 @@ function GensploreView({ genbankString, searchInput, setSearchInput }) {
)}
</div>
</div>
</>
);
}

Expand Down
47 changes: 43 additions & 4 deletions src/components/SingleRow.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,8 @@ const SingleRow = ({
whereMouseCurrentlyIs,
setWhereMouseCurrentlyIs,
sequenceHits,
curSeqHitIndex
curSeqHitIndex,
enableRC
}) => {
const zoomFactor = 2 ** zoomLevel;
const sep = 10 * zoomFactor;
Expand Down Expand Up @@ -386,6 +387,7 @@ const SingleRow = ({

// Generate sequence characters
let chars = null;
let chars2 = null;

if (zoomLevel > -1) {
chars = rowSequence.split("").map((char, i) => {
Expand All @@ -410,6 +412,34 @@ const SingleRow = ({
);
});
}
const rc = {"A": "T", "T": "A", "C": "G", "G": "C", "N": "N"};
if (//window.RC &&
zoomLevel > -1) {
// Generate reverse complement sequence characters
chars2 = rowSequence.split("").map((char, i) => {
const x = i * sep;
return (
<text
key={i}
x={x}
y={10}
textAnchor="middle"
fontSize={zoomLevel < -0.5 ? "10" : "12"}
fillOpacity={0.9}
onMouseEnter={() =>
setHoveredInfo({
label: `Nucleotide ${i + rowStart + 1}: ${char}`,
})
}
onMouseLeave={() => setHoveredInfo(null)}
>
{rc[char]}
</text>
);
});
}


const codonZoomThreshold = -2;

const featureBlocksSVG = featureBlocks.map((feature, i) => {
Expand Down Expand Up @@ -682,14 +712,16 @@ const SingleRow = ({
>
<svg
width={width + 40}
height={height - 20}
height={height - 20 + (enableRC ? 20 : 0)}
style={{ position: "absolute", top: 0, left: 0 }}
>
{selectionRect}
<g>
{sequenceHitRects}
</g>
<g fillOpacity={0.7}>
<g transform={enableRC ? `translate(0,20)` : ""}>

<g
transform={`translate(${extraPadding}, ${height - 40})`}
style={{ zIndex: -5 }}
Expand All @@ -704,16 +736,23 @@ const SingleRow = ({
{
// line above ticks
}
<line

</g>
</g>
<line
x1={0 + extraPadding}
y1={height - 40}
x2={width + extraPadding + 0}
y2={height - 40}
stroke="black"
/>
</g>

<g transform={`translate(${extraPadding}, ${height - 55})`}>{chars}</g>

{enableRC &&
<g transform={`translate(${extraPadding}, ${height - 55 + 19})`}>{chars2}</g>

}
<g transform={`translate(${extraPadding}, 5)`}>{featureBlocksSVG}</g>

</svg>
Expand Down
12 changes: 12 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1225,6 +1225,13 @@
dependencies:
stream-browserify "^3.0.0"

"@headlessui/react@^1.7.16":
version "1.7.16"
resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-1.7.16.tgz#9c458c9c4dbb708258c9e8da3fe5363f915f7b11"
integrity sha512-2MphIAZdSUacZBT6EXk8AJkj+EuvaaJbtCyHTJrPsz8inhzCl7qeNPI1uk1AUvCgWylVtdN8cVVmnhUDPxPy3g==
dependencies:
client-only "^0.0.1"

"@humanwhocodes/config-array@^0.11.8":
version "0.11.8"
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.8.tgz#03595ac2075a4dc0f191cc2131de14fbd7d410b9"
Expand Down Expand Up @@ -3145,6 +3152,11 @@ clean-css@^5.2.2:
dependencies:
source-map "~0.6.0"

client-only@^0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1"
integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==

cliui@^7.0.2:
version "7.0.4"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
Expand Down

1 comment on commit a81fad3

@vercel
Copy link

@vercel vercel bot commented on a81fad3 Jul 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.