From a49157f77335262ae8768614d012cfc52284e3bf Mon Sep 17 00:00:00 2001 From: Theo Sanderson Date: Fri, 28 Jul 2023 17:30:36 +0100 Subject: [PATCH 1/3] sequence search --- src/App.js | 100 +++++++++++++++++++++++++++++++++-- src/components/SingleRow.jsx | 41 ++++++++++++++ 2 files changed, 137 insertions(+), 4 deletions(-) diff --git a/src/App.js b/src/App.js index f4c93f1..0895141 100644 --- a/src/App.js +++ b/src/App.js @@ -18,7 +18,7 @@ import { useWindowVirtualizer } from "@tanstack/react-virtual"; import Slider, { Range } from "rc-slider"; import { AiOutlineZoomIn, AiOutlineZoomOut } from "react-icons/ai"; import { GiDna1 } from "react-icons/gi"; - +import {BsArrowRightCircleFill, BsArrowLeftCircleFill} from "react-icons/bs"; import { ToastContainer, toast } from "react-toastify"; import { useDebounce, useQueryState } from "./hooks"; import "react-toastify/dist/ReactToastify.css"; @@ -33,23 +33,37 @@ function SearchPanel({ setSearchInput, searchType, setSearchType, + curSeqHitIndex, + sequenceHits, + setCurSeqHitIndex }) { const handleInputChange = (event) => { + setCurSeqHitIndex(0); setSearchInput(event.target.value); + // if event.target.value has only ACGT characters, then set searchType to sequence // if event.target.value has non-numeric characters, then set searchType to annot - if (event.target.value.match(/[^0-9]/)) { + // if event.target.value has only numeric characters, then set searchType to nuc + if (/^[0-9]+$/.test(event.target.value)) { + setSearchType("nuc"); + } + else if (/^[ACGTacgt]+$/.test(event.target.value)) { + setSearchType("sequence"); + } + else if (/^[^0-9]+$/.test(event.target.value)) { setSearchType("annot"); - console.log("setting searchType to annot"); } + }; const searchOption = [ { value: "nuc", label: "nucleotide" }, { value: "annot", label: "annotation" }, + { value: "sequence", label: "sequence"} ]; return ( -
+
+
{searchPanelOpen ? ( <> { + + setIncludeRC(!includeRC); + setCurSeqHitIndex(0); + } + + }/> + + {sequenceHits.length > 0 && ( <> @@ -187,6 +200,7 @@ function GensploreView({ genbankString, searchInput, setSearchInput }) { const [genbankData, setGenbankData] = useState(null); const [sequenceHits, setSequenceHits] = useState([]); const [curSeqHitIndex, setCurSeqHitIndex] = useState(0); + const [includeRC, setIncludeRC] = useState(false); // safely convert searchInput to int const intSearchInput = searchType === "nuc" ? parseInt(searchInput) : null; @@ -423,8 +437,13 @@ function GensploreView({ genbankString, searchInput, setSearchInput }) { // we want to find all locations that match and store them with setSequenceHits as [start,end] const seqHits = []; let start = 0; + const rc = getReverseComplement(strippedSequenceInput); + console.log("rc", rc); while (true) { - const hit = fullSequence.indexOf(strippedSequenceInput, start); + const hit1 = fullSequence.indexOf(strippedSequenceInput, start); + const hit2 = includeRC ? fullSequence.indexOf(rc, start) : -1; + const hit = hit1 === -1 ? hit2 : (hit2 === -1 ? hit1 : Math.min(hit1, hit2)); + if (hit === -1) break; seqHits.push([hit, hit + strippedSequenceInput.length]); start = hit + 1; @@ -435,7 +454,7 @@ function GensploreView({ genbankString, searchInput, setSearchInput }) { console.log("row", row); rowVirtualizer.scrollToIndex(row + 1, { align: "center" }); setLastSearch(sequenceSearchInput); - }, [sequenceSearchInput, curSeqHitIndex]); + }, [sequenceSearchInput, curSeqHitIndex,includeRC]); //console.log("virtualItems", virtualItems); @@ -467,6 +486,8 @@ function GensploreView({ genbankString, searchInput, setSearchInput }) { curSeqHitIndex={curSeqHitIndex} setCurSeqHitIndex={setCurSeqHitIndex} sequenceHits={sequenceHits} + includeRC={includeRC} + setIncludeRC={setIncludeRC} />
)}