jbrowse-plugin-msaview 5.1.1 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/LaunchMsaView/components/PreLoadedMSA/PreLoadedMSADataPanel.js +0 -2
- package/dist/MsaViewPanel/model.d.ts +24 -22
- package/dist/chunks/{AboutDialog-YNPKL64P.js → AboutDialog-IRBPUPJK.js} +2 -2
- package/dist/chunks/{AboutDialog-YNPKL64P.js.map → AboutDialog-IRBPUPJK.js.map} +2 -2
- package/dist/chunks/{AnnotationFileDialog-NJGKHAVR.js → AnnotationFileDialog-FCYYZ4JN.js} +2 -2
- package/dist/chunks/{AnnotationFileDialog-NJGKHAVR.js.map → AnnotationFileDialog-FCYYZ4JN.js.map} +1 -1
- package/dist/chunks/ExportSVGDialog-TYYPI6VB.js +2 -0
- package/dist/chunks/ExportSVGDialog-TYYPI6VB.js.map +7 -0
- package/dist/chunks/{FeatureDialog-7XXL6XUK.js → FeatureDialog-ZBX3XQZ5.js} +1 -1
- package/dist/chunks/{FeatureDialog-7XXL6XUK.js.map → FeatureDialog-ZBX3XQZ5.js.map} +1 -1
- package/dist/chunks/{LaunchMsaViewDialog-C53VHT52.js → LaunchMsaViewDialog-GJAUPGFC.js} +3 -3
- package/dist/chunks/{LaunchMsaViewDialog-C53VHT52.js.map → LaunchMsaViewDialog-GJAUPGFC.js.map} +2 -2
- package/dist/chunks/{MetadataDialog-QCUWTDBU.js → MetadataDialog-KZWQFRF7.js} +2 -2
- package/dist/chunks/{MetadataDialog-QCUWTDBU.js.map → MetadataDialog-KZWQFRF7.js.map} +1 -1
- package/dist/chunks/{MsaViewPanel-DS4STM3W.js → MsaViewPanel-RUZAKFCB.js} +2 -2
- package/dist/chunks/{TrackInfoDialog-BVZWIDEU.js → TrackInfoDialog-IFIG77WO.js} +2 -2
- package/dist/chunks/{TrackInfoDialog-BVZWIDEU.js.map → TrackInfoDialog-IFIG77WO.js.map} +1 -1
- package/dist/chunks/{TreeNodeInfoDialog-LPLF6BA6.js → TreeNodeInfoDialog-VRCVIF26.js} +2 -2
- package/dist/chunks/{TreeNodeInfoDialog-LPLF6BA6.js.map → TreeNodeInfoDialog-VRCVIF26.js.map} +1 -1
- package/dist/chunks/{chunk-OF4AZJER.js → chunk-F3EC6OCO.js} +1 -1
- package/dist/chunks/{chunk-OF4AZJER.js.map → chunk-F3EC6OCO.js.map} +1 -1
- package/dist/chunks/{chunk-VWM6IHF2.js → chunk-GDFVLZYX.js} +2 -2
- package/dist/chunks/{chunk-VWM6IHF2.js.map → chunk-GDFVLZYX.js.map} +1 -1
- package/dist/chunks/{chunk-IP2BEEIU.js → chunk-GIHMPOCO.js} +1 -1
- package/dist/chunks/{chunk-IP2BEEIU.js.map → chunk-GIHMPOCO.js.map} +1 -1
- package/dist/chunks/{chunk-VJQWGQ4V.js → chunk-H6IQBAW7.js} +2 -2
- package/dist/chunks/{chunk-VJQWGQ4V.js.map → chunk-H6IQBAW7.js.map} +1 -1
- package/dist/chunks/chunk-NMYD2GWF.js +18 -0
- package/dist/chunks/chunk-NMYD2GWF.js.map +7 -0
- package/dist/chunks/{chunk-P7ZJCOIY.js → chunk-QQ5LZUIO.js} +1 -1
- package/dist/chunks/{chunk-P7ZJCOIY.js.map → chunk-QQ5LZUIO.js.map} +1 -1
- package/dist/chunks/chunk-QUWPHTZQ.js +2 -0
- package/dist/chunks/chunk-QUWPHTZQ.js.map +7 -0
- package/dist/chunks/{chunk-NSKY4K4T.js → chunk-YOTSFJMU.js} +1 -1
- package/dist/chunks/{chunk-NSKY4K4T.js.map → chunk-YOTSFJMU.js.map} +1 -1
- package/dist/chunks/{chunk-HOEVB65D.js → chunk-ZCT7RD24.js} +2 -2
- package/dist/chunks/{dist-UX5CKLQJ.js → dist-CMWKVHC7.js} +1 -1
- package/dist/chunks/{dist-UX5CKLQJ.js.map → dist-CMWKVHC7.js.map} +1 -1
- package/dist/chunks/{dist-6DG5HXEW.js → dist-R73J3CC3.js} +2 -2
- package/dist/chunks/{model-DXQOMSLC.js → model-VE7IYWNU.js} +2 -2
- package/dist/chunks/{renderToSvg-2LBAS6XS.js → renderToSvg-VDXAB7TT.js} +2 -2
- package/dist/jbrowse-plugin-msaview.esm.js +2 -2
- package/dist/jbrowse-plugin-msaview.esm.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -3
- package/src/LaunchMsaView/components/PreLoadedMSA/PreLoadedMSADataPanel.tsx +0 -2
- package/src/version.ts +1 -1
- package/dist/chunks/ExportSVGDialog-D5DKR6CZ.js +0 -2
- package/dist/chunks/ExportSVGDialog-D5DKR6CZ.js.map +0 -7
- package/dist/chunks/chunk-S2T7S4SB.js +0 -18
- package/dist/chunks/chunk-S2T7S4SB.js.map +0 -7
- package/dist/chunks/chunk-SKDGC3HW.js +0 -2
- package/dist/chunks/chunk-SKDGC3HW.js.map +0 -7
- /package/dist/chunks/{MsaViewPanel-DS4STM3W.js.map → MsaViewPanel-RUZAKFCB.js.map} +0 -0
- /package/dist/chunks/{chunk-HOEVB65D.js.map → chunk-ZCT7RD24.js.map} +0 -0
- /package/dist/chunks/{dist-6DG5HXEW.js.map → dist-R73J3CC3.js.map} +0 -0
- /package/dist/chunks/{model-DXQOMSLC.js.map → model-VE7IYWNU.js.map} +0 -0
- /package/dist/chunks/{renderToSvg-2LBAS6XS.js.map → renderToSvg-VDXAB7TT.js.map} +0 -0
package/dist/chunks/{LaunchMsaViewDialog-C53VHT52.js.map → LaunchMsaViewDialog-GJAUPGFC.js.map}
RENAMED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["global-externals:@jbrowse/core/data_adapters/dataAdapterCache", "../../src/LaunchMsaView/components/LaunchMsaViewDialog.tsx", "../../src/LaunchMsaView/components/BlastQuery/BlastPanel.tsx", "../../node_modules/.pnpm/@mui+icons-material@9.4.0_@mui+material@9.4.0_@emotion+react@11.14.0_@types+react@19.3._3766ec55733e6b150ee672ad270cc236/node_modules/@mui/icons-material/Settings.mjs", "../../src/LaunchMsaView/components/BlastQuery/BlastAutomaticPanel.tsx", "../../src/components/TextField2.tsx", "../../src/LaunchMsaView/components/LaunchPanelContent.tsx", "../../src/LaunchMsaView/components/SequenceStatus.tsx", "../../src/LaunchMsaView/components/SubmitCancelActions.tsx", "../../src/LaunchMsaView/components/launchPlacement.tsx", "../../src/LaunchMsaView/components/TranscriptSelector.tsx", "../../src/components/ReadOnlyTextField2.tsx", "../../src/LaunchMsaView/components/launchConnectedView.ts", "../../src/LaunchMsaView/components/useTranscriptSelection.ts", "../../src/LaunchMsaView/components/useFeatureSequence.ts", "../../src/utils/useFetch.ts", "../../src/LaunchMsaView/components/BlastQuery/CachedBlastResults.tsx", "../../node_modules/.pnpm/@mui+icons-material@9.4.0_@mui+material@9.4.0_@emotion+react@11.14.0_@types+react@19.3._3766ec55733e6b150ee672ad270cc236/node_modules/@mui/icons-material/Delete.mjs", "../../src/LaunchMsaView/components/BlastQuery/MsaAlgorithmSelect.tsx", "../../src/LaunchMsaView/components/BlastQuery/searchChoiceStorage.ts", "../../src/LaunchMsaView/components/BlastQuery/useCachedBlastResults.ts", "../../src/LaunchMsaView/components/BlastQuery/BlastManualPanel.tsx", "../../src/LaunchMsaView/useQueryRowName.ts", "../../src/LaunchMsaView/detectQueryRow.ts", "../../src/LaunchMsaView/components/QueryRowSelector.tsx", "../../src/LaunchMsaView/components/BlastQuery/BlastMethodSelector.tsx", "../../src/LaunchMsaView/components/BlastQuery/BlastSettingsDialog.tsx", "../../src/LaunchMsaView/components/HelpButton.tsx", "../../src/LaunchMsaView/components/ManualMSALoader/ManualMSALoader.tsx", "../../src/LaunchMsaView/components/OrthologQuery/OrthologPanel.tsx", "../../src/LaunchMsaView/components/OrthologQuery/OrthologSourceSelect.tsx", "../../src/LaunchMsaView/components/OrthologQuery/QuerySpeciesSelect.tsx", "../../src/utils/ncbiTaxonomy.ts", "../../src/LaunchMsaView/components/PreLoadedMSA/PreLoadedMSADataPanel.tsx", "../../src/LaunchMsaView/components/PreLoadedMSA/fetchMSAData.ts", "../../src/LaunchMsaView/components/PreLoadedMSA/types.ts", "../../src/LaunchMsaView/components/TabPanel.tsx"],
|
|
4
|
-
"sourcesContent": ["module.exports = JBrowseExports[\"@jbrowse/core/data_adapters/dataAdapterCache\"];", "import React, { useState } from 'react'\n\nimport { Dialog } from '@jbrowse/core/ui'\nimport { getSession } from '@jbrowse/core/util'\nimport { Tab, Tabs } from '@mui/material'\n\nimport BlastPanel from './BlastQuery/BlastPanel'\nimport HelpButton from './HelpButton'\nimport ManualMSALoader from './ManualMSALoader/ManualMSALoader'\nimport OrthologPanel from './OrthologQuery/OrthologPanel'\nimport PreLoadedMSA from './PreLoadedMSA/PreLoadedMSADataPanel'\nimport { readMsaDatasets } from './PreLoadedMSA/types'\nimport TabPanel from './TabPanel'\nimport { LaunchPlacementProvider } from './launchPlacement'\n\nimport type { AbstractTrackModel, Feature } from '@jbrowse/core/util'\n\nexport default function LaunchMsaViewDialog({\n handleClose,\n feature,\n model,\n preferredTranscriptId,\n}: {\n handleClose: () => void\n feature: Feature\n model: AbstractTrackModel\n /** the isoform the right-click landed on, when this opened on its gene */\n preferredTranscriptId?: string\n}) {\n const session = getSession(model)\n const datasets = readMsaDatasets(session.jbrowse)\n const hasPreloadedDatasets = !!datasets?.length\n\n // orthologs first, and the default: it answers the same question in ~10s\n // that BLAST takes 10+ minutes to answer worse (see utils/ncbiOrthologs.ts)\n const [value, setValue] = useState<\n 'orthologs' | 'ncbi_blast' | 'preloaded_msa' | 'manual_msa'\n >('orthologs')\n\n return (\n <Dialog maxWidth=\"xl\" title=\"Launch MSA view\" open onClose={handleClose}>\n {/* one placement answer for every tab: they all stay mounted once\n visited, so a per-panel one is a per-tab one */}\n <LaunchPlacementProvider>\n <div style={{ display: 'flex', alignItems: 'center' }}>\n <Tabs\n value={value}\n onChange={(_event, newValue) => {\n setValue(newValue)\n }}\n >\n <Tab label=\"Orthologs\" value=\"orthologs\" />\n {/* the tab value stays 'ncbi_blast' \u2014 it is only local state, and\n renaming it buys nothing */}\n <Tab label=\"BLAST query\" value=\"ncbi_blast\" />\n {hasPreloadedDatasets ? (\n <Tab label=\"Pre-loaded MSA datasets\" value=\"preloaded_msa\" />\n ) : null}\n <Tab label=\"Manual upload\" value=\"manual_msa\" />\n </Tabs>\n <HelpButton />\n </div>\n <TabPanel value={value} index=\"orthologs\">\n <OrthologPanel\n handleClose={handleClose}\n feature={feature}\n model={model}\n preferredTranscriptId={preferredTranscriptId}\n />\n </TabPanel>\n <TabPanel value={value} index=\"ncbi_blast\">\n <BlastPanel\n handleClose={handleClose}\n feature={feature}\n model={model}\n preferredTranscriptId={preferredTranscriptId}\n />\n </TabPanel>\n {hasPreloadedDatasets ? (\n <TabPanel value={value} index=\"preloaded_msa\">\n <PreLoadedMSA\n model={model}\n feature={feature}\n handleClose={handleClose}\n preferredTranscriptId={preferredTranscriptId}\n />\n </TabPanel>\n ) : null}\n <TabPanel value={value} index=\"manual_msa\">\n <ManualMSALoader\n model={model}\n feature={feature}\n handleClose={handleClose}\n preferredTranscriptId={preferredTranscriptId}\n />\n </TabPanel>\n </LaunchPlacementProvider>\n </Dialog>\n )\n}\n", "import React, { useState } from 'react'\n\nimport SettingsIcon from '@mui/icons-material/Settings'\nimport { IconButton, Tooltip } from '@mui/material'\nimport { makeStyles } from 'tss-react/mui'\n\nimport {\n DEFAULT_EBI_EMAIL,\n EBI_EMAIL_STORAGE_KEY,\n} from '../../../utils/ebiJobDispatcher'\nimport { useLocalStorage } from '../../../utils/useLocalStorage'\nimport BlastAutomaticPanel from './BlastAutomaticPanel'\nimport BlastManualPanel from './BlastManualPanel'\nimport BlastMethodSelector from './BlastMethodSelector'\nimport BlastSettingsDialog from './BlastSettingsDialog'\n\nimport type { AbstractTrackModel, Feature } from '@jbrowse/core/util'\n\nconst useStyles = makeStyles()({\n settingsButton: {\n float: 'right',\n },\n})\n\nconst panelMap = {\n automatic: BlastAutomaticPanel,\n manual: BlastManualPanel,\n} as const\n\nexport type BlastLookupMethod = keyof typeof panelMap\n\nexport default function BlastPanel({\n handleClose,\n model,\n feature,\n preferredTranscriptId,\n}: {\n handleClose: () => void\n model: AbstractTrackModel\n feature: Feature\n /** the isoform the user right-clicked, preselected in the picker */\n preferredTranscriptId?: string\n}) {\n const [lookupMethod, setLookupMethod] =\n useState<BlastLookupMethod>('automatic')\n const [ebiEmail, setEbiEmail] = useLocalStorage(\n EBI_EMAIL_STORAGE_KEY,\n DEFAULT_EBI_EMAIL,\n )\n const [settingsOpen, setSettingsOpen] = useState(false)\n const { classes } = useStyles()\n\n const Panel = panelMap[lookupMethod]\n\n return (\n <>\n {/* a bare gear said nothing about what it opened, and the address the\n job carries was invisible until you opened it */}\n <Tooltip\n title={`EBI settings \u2014 jobs are submitted with ${ebiEmail.trim() || DEFAULT_EBI_EMAIL}`}\n >\n <IconButton\n className={classes.settingsButton}\n aria-label=\"EBI settings\"\n size=\"small\"\n onClick={() => {\n setSettingsOpen(true)\n }}\n >\n <SettingsIcon />\n </IconButton>\n </Tooltip>\n\n <Panel\n model={model}\n feature={feature}\n handleClose={handleClose}\n preferredTranscriptId={preferredTranscriptId}\n >\n <BlastMethodSelector\n lookupMethod={lookupMethod}\n setLookupMethod={setLookupMethod}\n />\n </Panel>\n\n {settingsOpen ? (\n <BlastSettingsDialog\n ebiEmail={ebiEmail}\n handleClose={settings => {\n if (settings) {\n setEbiEmail(settings.ebiEmail)\n }\n setSettingsOpen(false)\n }}\n />\n ) : null}\n </>\n )\n}\n", "\"use client\";\n\nimport createSvgIcon from \"./utils/createSvgIcon.mjs\";\nimport { jsx as _jsx } from \"react/jsx-runtime\";\nexport default createSvgIcon(/*#__PURE__*/_jsx(\"path\", {\n d: \"M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.07.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6\"\n}), 'Settings');", "import React, { useMemo, useState } from 'react'\n\nimport ExpandMoreIcon from '@mui/icons-material/ExpandMore'\nimport {\n Accordion,\n AccordionDetails,\n AccordionSummary,\n MenuItem,\n Typography,\n} from '@mui/material'\nimport { observer } from 'mobx-react'\nimport { makeStyles } from 'tss-react/mui'\n\nimport TextField2 from '../../../components/TextField2'\nimport {\n getBlastViewTitle,\n getGeneIdentifiers,\n getLinearGenomeView,\n} from '../../util'\nimport LaunchPanelContent from '../LaunchPanelContent'\nimport SequenceStatusMessage from '../SequenceStatus'\nimport SubmitCancelActions from '../SubmitCancelActions'\nimport TranscriptSelector from '../TranscriptSelector'\nimport {\n builtAlignmentLook,\n launchConnectedView,\n useLaunchSubmit,\n} from '../launchConnectedView'\nimport { useTranscriptSelection } from '../useTranscriptSelection'\nimport CachedBlastResults from './CachedBlastResults'\nimport MsaAlgorithmSelect from './MsaAlgorithmSelect'\nimport {\n databaseLabel,\n databaseOptionsFor,\n defaultMaxHits,\n defaultSearchFor,\n searchProgramLabels,\n searchPrograms,\n} from './consts'\nimport {\n useStoredMsaAlgorithm,\n useStoredSearchChoice,\n} from './searchChoiceStorage'\nimport { useCachedBlastResults } from './useCachedBlastResults'\n\nimport type { BlastParams } from '../../../MsaViewPanel/model'\nimport type { SearchChoice, SearchProgram } from './consts'\nimport type { AbstractTrackModel, Feature } from '@jbrowse/core/util'\n\nconst useStyles = makeStyles()({\n selectField: {\n width: 150,\n },\n // wider than the rest because the collection names are what the user came to\n // read, and truncating them does not distinguish Swiss-Prot from TrEMBL\n databaseField: {\n width: 260,\n },\n cachedResultsAccordion: {\n marginTop: 20,\n },\n infoText: {\n marginTop: 20,\n },\n})\n\nconst BlastAutomaticPanel = observer(function ({\n handleClose,\n feature,\n model,\n children,\n preferredTranscriptId,\n}: {\n model: AbstractTrackModel\n feature: Feature\n handleClose: () => void\n children: React.ReactNode\n /** the isoform the user right-clicked, preselected in the picker */\n preferredTranscriptId?: string\n}) {\n const { classes } = useStyles()\n const view = getLinearGenomeView(model)\n const { launchError, submit } = useLaunchSubmit(handleClose)\n // one piece of state, not two: a program and a database that program does not\n // have is a 400 from EBI minutes after Submit, and holding them apart is what\n // would let them drift into that\n const [search, setSearch] = useStoredSearchChoice()\n const [selectedMsaAlgorithm, setSelectedMsaAlgorithm] =\n useStoredMsaAlgorithm()\n const [maxHits, setMaxHits] = useState(String(defaultMaxHits))\n const hitCount = Number(maxHits)\n const hitCountValid = Number.isInteger(hitCount) && hitCount >= 1\n const isPhmmer = search.program === 'phmmer'\n\n const geneIds = useMemo(() => getGeneIdentifiers(feature), [feature])\n const cached = useCachedBlastResults(geneIds)\n\n const transcriptSelection = useTranscriptSelection({\n feature,\n view,\n preferredTranscriptId,\n })\n const { selectedTranscript, proteinSequence, sequenceStatus } =\n transcriptSelection\n const e = transcriptSelection.error ?? launchError ?? cached.error\n return (\n <>\n <LaunchPanelContent error={e}>\n {children}\n <TextField2\n variant=\"outlined\"\n label=\"Search program\"\n className={classes.selectField}\n select\n value={search.program}\n onChange={event => {\n // the two services name their databases differently, so switching\n // program replaces the database rather than keeping a name the new\n // one has never heard of\n setSearch(defaultSearchFor(event.target.value as SearchProgram))\n }}\n >\n {searchPrograms.map(val => (\n <MenuItem value={val} key={val}>\n {searchProgramLabels[val]}\n </MenuItem>\n ))}\n </TextField2>\n\n <TextField2\n variant=\"outlined\"\n label=\"Database\"\n className={classes.databaseField}\n select\n value={search.database}\n onChange={event => {\n setSearch({\n program: search.program,\n database: event.target.value,\n } as SearchChoice)\n }}\n >\n {databaseOptionsFor(search.program).map(val => (\n <MenuItem value={val} key={val}>\n {databaseLabel(val)}\n </MenuItem>\n ))}\n </TextField2>\n\n {isPhmmer ? null : (\n <MsaAlgorithmSelect\n className={classes.selectField}\n value={selectedMsaAlgorithm}\n onChange={setSelectedMsaAlgorithm}\n />\n )}\n\n <TextField2\n variant=\"outlined\"\n label=\"Hits\"\n className={classes.selectField}\n type=\"number\"\n value={maxHits}\n onChange={event => {\n setMaxHits(event.target.value)\n }}\n error={!hitCountValid}\n helperText=\"best-scoring sequences to keep\"\n />\n\n <TranscriptSelector feature={feature} {...transcriptSelection} />\n\n {/* one line rather than eight; the rest is behind the Help button,\n where a reader who wants it can go and find it */}\n <Typography variant=\"body2\" className={classes.infoText}>\n {isPhmmer\n ? 'phmmer aligns the hits as it finds them, so nothing is realigned afterwards.'\n : 'The hits come back from EBI and are then run through the chosen aligner.'}{' '}\n The EBI queue is the wait, and it runs from seconds to many minutes.\n </Typography>\n\n {cached.results.length > 0 ? (\n <Accordion className={classes.cachedResultsAccordion}>\n <AccordionSummary expandIcon={<ExpandMoreIcon />}>\n <Typography>Previous BLAST Results</Typography>\n </AccordionSummary>\n <AccordionDetails>\n <CachedBlastResults\n model={model}\n handleClose={handleClose}\n feature={feature}\n cached={cached}\n />\n </AccordionDetails>\n </Accordion>\n ) : null}\n </LaunchPanelContent>\n <SubmitCancelActions\n model={model}\n hint={<SequenceStatusMessage status={sequenceStatus} />}\n submitDisabled={!proteinSequence || !hitCountValid}\n onSubmit={placement => {\n if (selectedTranscript) {\n const blastParams: BlastParams =\n search.program === 'phmmer'\n ? {\n searchProgram: 'phmmer',\n blastDatabase: search.database,\n maxHits: hitCount,\n selectedTranscript: selectedTranscript.toJSON(),\n proteinSequence,\n }\n : {\n searchProgram: 'blastp',\n blastDatabase: search.database,\n msaAlgorithm: selectedMsaAlgorithm,\n maxHits: hitCount,\n selectedTranscript: selectedTranscript.toJSON(),\n proteinSequence,\n }\n submit(() =>\n launchConnectedView({\n view,\n feature: selectedTranscript,\n placement,\n displayName: getBlastViewTitle(feature, selectedTranscript),\n ...builtAlignmentLook,\n blastParams,\n }),\n )\n }\n }}\n onCancel={handleClose}\n />\n </>\n )\n})\n\nexport default BlastAutomaticPanel\n", "import React from 'react'\n\nimport { TextField } from '@mui/material'\n\nimport type { TextFieldProps } from '@mui/material'\n\nfunction TextField2({ children, ...rest }: TextFieldProps) {\n return (\n <div>\n <TextField {...rest}>{children}</TextField>\n </div>\n )\n}\n\nexport default TextField2\n", "import React from 'react'\n\nimport { ErrorMessage } from '@jbrowse/core/ui'\nimport { DialogContent } from '@mui/material'\nimport { makeStyles } from 'tss-react/mui'\n\nconst useStyles = makeStyles()({\n dialogContent: {\n width: '80em',\n },\n})\n\nexport default function LaunchPanelContent({\n error,\n children,\n}: {\n error?: unknown\n children: React.ReactNode\n}) {\n const { classes } = useStyles()\n return (\n <DialogContent className={classes.dialogContent}>\n {error ? <ErrorMessage error={error} /> : null}\n {children}\n </DialogContent>\n )\n}\n", "import React from 'react'\n\nimport { LoadingEllipses } from '@jbrowse/core/ui'\nimport { Typography } from '@mui/material'\n\nexport type SequenceStatus = 'loading' | 'ready' | 'missing' | 'error'\n\n/**\n * Why Submit is grey. The query row is the selected transcript's translation,\n * and fetching and translating it takes a round trip to the sequence adapter,\n * so the button starts disabled on every panel \u2014 with nothing to distinguish\n * \"wait a moment\" from \"this gene has no protein and never will\".\n *\n * An error says so through the panel's own ErrorMessage, so this stays quiet\n * for that one rather than saying it twice.\n */\nexport default function SequenceStatusMessage({\n status,\n}: {\n status: SequenceStatus\n}) {\n return status === 'loading' ? (\n <LoadingEllipses message=\"Translating transcript\" />\n ) : status === 'missing' ? (\n <Typography color=\"textSecondary\" variant=\"body2\">\n no coding sequence to align\n </Typography>\n ) : null\n}\n", "import React from 'react'\n\nimport { getSession } from '@jbrowse/core/util'\nimport {\n Button,\n Checkbox,\n DialogActions,\n FormControlLabel,\n} from '@mui/material'\n\nimport {\n readLaunchPlacement,\n sessionSupportsPlacement,\n writeLaunchPlacement,\n} from '../../utils/workspaces'\nimport { useLaunchPlacement } from './launchPlacement'\n\nimport type { MsaViewPlacement } from '../../utils/workspaces'\nimport type { AbstractTrackModel } from '@jbrowse/core/util'\n\n/**\n * Where the launch puts the view, offered wherever a launch is submitted.\n *\n * A checkbox rather than a menu of the three placements: the choice a reader\n * has at this point is \"beside the genome view or under it\", and `newTab` is a\n * spec's to state, not a thing to pick before you have seen the alignment.\n *\n * Absent entirely on a host that cannot tile \u2014 an embedded session, or a\n * release that places views its own way \u2014 because the box would do nothing\n * there and every launch would quietly ignore it.\n */\nfunction PlacementToggle({\n checked,\n onChange,\n}: {\n checked: boolean\n onChange: (checked: boolean) => void\n}) {\n return (\n <FormControlLabel\n label=\"Open beside the genome view\"\n control={\n <Checkbox\n checked={checked}\n onChange={event => {\n onChange(event.target.checked)\n }}\n />\n }\n />\n )\n}\n\nexport default function SubmitCancelActions({\n onSubmit,\n onCancel,\n submitDisabled,\n hint,\n submitLabel = 'Submit',\n model,\n}: {\n /** handed the placement the box states, so no launch re-reads storage */\n onSubmit: (placement: MsaViewPlacement) => void\n onCancel: () => void\n submitDisabled?: boolean\n /** why Submit is grey, shown beside it */\n hint?: React.ReactNode\n submitLabel?: string\n /** omitted by a panel that submits something other than a view launch */\n model?: AbstractTrackModel\n}) {\n const [sideBySide, setSideBySide] = useLaunchPlacement()\n // The stored value is what the next dialog opens on, so it is written on\n // submit rather than on the click: a dialog the user backed out of must not\n // move where every future launch lands.\n const offerPlacement = !!model && sessionSupportsPlacement(getSession(model))\n return (\n // The buttons are one child rather than two, so a dialog too narrow for\n // the whole row wraps them together underneath the option instead of\n // breaking Cancel away from Submit or shrinking both out of shape.\n <DialogActions sx={{ flexWrap: 'wrap', rowGap: 1 }}>\n {offerPlacement ? (\n <PlacementToggle checked={sideBySide} onChange={setSideBySide} />\n ) : null}\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n marginLeft: 'auto',\n }}\n >\n {hint}\n <Button\n sx={{ flexShrink: 0 }}\n color=\"primary\"\n variant=\"contained\"\n disabled={submitDisabled}\n onClick={() => {\n if (offerPlacement) {\n const placement = sideBySide ? 'splitRight' : 'stack'\n writeLaunchPlacement(placement)\n onSubmit(placement)\n } else {\n onSubmit(readLaunchPlacement())\n }\n }}\n >\n {submitLabel}\n </Button>\n <Button\n sx={{ flexShrink: 0 }}\n color=\"secondary\"\n variant=\"contained\"\n onClick={() => {\n onCancel()\n }}\n >\n Cancel\n </Button>\n </div>\n </DialogActions>\n )\n}\n", "import React, { createContext, useContext, useState } from 'react'\n\nimport { readLaunchPlacement } from '../../utils/workspaces'\n\ntype PlacementState = [boolean, React.Dispatch<React.SetStateAction<boolean>>]\n\n/**\n * Whether the launch opens beside the genome view \u2014 one answer for the whole\n * dialog, not one per tab.\n *\n * Every tab the user visits stays mounted, and the checkbox lives in each\n * panel's actions row, so a `useState` there gave each tab its own copy of the\n * answer: ticking the box on one tab and submitting from another wrote the\n * other tab's stale one.\n *\n * Context rather than a prop through all five panels, none of which has any\n * other business with placement.\n */\nconst LaunchPlacementContext = createContext<PlacementState | undefined>(\n undefined,\n)\n\nexport function LaunchPlacementProvider({\n children,\n}: {\n children: React.ReactNode\n}) {\n const state = useState(() => readLaunchPlacement() === 'splitRight')\n return (\n <LaunchPlacementContext.Provider value={state}>\n {children}\n </LaunchPlacementContext.Provider>\n )\n}\n\n/** the dialog's answer, or a private one for a panel rendered outside it */\nexport function useLaunchPlacement(): PlacementState {\n const shared = useContext(LaunchPlacementContext)\n const own = useState(() => readLaunchPlacement() === 'splitRight')\n return shared ?? own\n}\n", "import React, { useState } from 'react'\n\nimport { Button, MenuItem, TextField } from '@mui/material'\nimport { makeStyles } from 'tss-react/mui'\n\nimport ReadOnlyTextField2 from '../../components/ReadOnlyTextField2'\nimport {\n featureMatchesId,\n getGeneDisplayName,\n getId,\n getTranscriptDisplayName,\n getTranscriptLength,\n} from '../util'\n\nimport type { SequenceStatus } from './SequenceStatus'\nimport type { Feature } from '@jbrowse/core/util'\n\nconst useStyles = makeStyles()({\n flex: {\n display: 'flex',\n },\n minWidth: {\n minWidth: 300,\n },\n centered: {\n alignContent: 'center',\n marginLeft: 20,\n },\n})\n\nexport default function TranscriptSelector({\n feature,\n options,\n selectedId,\n selectedTranscript,\n setSelectedId,\n proteinSequence,\n sequenceStatus = 'ready',\n validIds,\n}: {\n feature: Feature\n options: Feature[]\n selectedId: string\n selectedTranscript: Feature | undefined\n setSelectedId: (transcriptId: string) => void\n proteinSequence: string | undefined\n sequenceStatus?: SequenceStatus\n validIds?: string[]\n}) {\n const { classes } = useStyles()\n const [showSequence, setShowSequence] = useState(false)\n\n return (\n <>\n <div className={classes.flex}>\n <TextField\n variant=\"outlined\"\n label={`Choose isoform of ${getGeneDisplayName(feature)}`}\n // The query row is this transcript rather than NCBI's representative\n // protein, which is what keeps the alignment linked to the genome view\n // at codon resolution. It used to be a paragraph under the panel; as\n // helper text it says the same thing where the choice is made and\n // costs no height of its own.\n helperText=\"the query row, so the alignment stays linked to the genome view\"\n select\n className={classes.minWidth}\n value={selectedId}\n onChange={event => {\n setSelectedId(event.target.value)\n }}\n >\n {options.map(val => {\n const inSet = validIds\n ? validIds.some(id => featureMatchesId(val, id))\n : true\n const { len, mod } = getTranscriptLength(val)\n return (\n <MenuItem value={getId(val)} key={val.id()} disabled={!inSet}>\n {getTranscriptDisplayName(val)} ({len} aa){' '}\n {mod ? ` (possible fragment)` : ''}\n {validIds ? (inSet ? ' (has data)' : ' (no data)') : ''}\n </MenuItem>\n )\n })}\n </TextField>\n <div className={classes.centered}>\n <Button\n variant=\"contained\"\n color=\"primary\"\n onClick={() => {\n setShowSequence(!showSequence)\n }}\n >\n {showSequence ? 'Hide sequence' : 'Show sequence'}\n </Button>\n </div>\n </div>\n\n {showSequence ? (\n <ReadOnlyTextField2\n value={\n proteinSequence\n ? `>${getTranscriptDisplayName(selectedTranscript)}\\n${proteinSequence}`\n : sequenceStatus === 'missing'\n ? 'This transcript has no coding sequence, so there is nothing to translate.'\n : sequenceStatus === 'error'\n ? 'The sequence could not be fetched.'\n : 'Loading...'\n }\n />\n ) : null}\n </>\n )\n}\n", "import React from 'react'\n\nimport { makeStyles } from 'tss-react/mui'\n\nimport TextField2 from './TextField2'\n\nconst useStyles = makeStyles()({\n textAreaFont: {\n fontFamily: 'Courier New',\n },\n})\n\nexport default function ReadOnlyTextField2({ value }: { value: string }) {\n const { classes } = useStyles()\n return (\n <TextField2\n variant=\"outlined\"\n multiline\n minRows={5}\n maxRows={10}\n fullWidth\n value={value}\n slotProps={{\n input: {\n readOnly: true,\n classes: {\n input: classes.textAreaFont,\n },\n },\n }}\n />\n )\n}\n", "import { useRef, useState } from 'react'\n\nimport { getSession } from '@jbrowse/core/util'\n\nimport { launchMsaView } from '../../utils/launchMsaView'\n\nimport type { MsaViewPlacement } from '../../utils/workspaces'\nimport type { Feature } from '@jbrowse/core/util'\nimport type { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'\n\n/** how a view whose alignment the plugin builds opens */\nexport const builtAlignmentLook = {\n drawNodeBubbles: true,\n colWidth: 10,\n rowHeight: 12,\n}\n\n/**\n * Every dialog launch: an MSA view tied to the genome view it came from, and\n * through `feature` to the transcript whose codons its query row is read by.\n */\nexport function launchConnectedView({\n view,\n feature,\n placement,\n ...snapshot\n}: {\n view: LinearGenomeViewModel\n feature?: Feature\n placement: MsaViewPlacement\n} & Record<string, unknown>) {\n return launchMsaView(getSession(view), {\n placement,\n connectedViewId: view.id,\n connectedFeature: feature?.toJSON(),\n ...snapshot,\n })\n}\n\n/** runs a panel's launch, closing the dialog on success and keeping the error */\nexport function useLaunchSubmit(handleClose: () => void) {\n const [launchError, setLaunchError] = useState<unknown>()\n // the first launch loads the view's chunk, which is long enough to click twice\n const launching = useRef(false)\n return {\n launchError,\n submit: (launch: () => Promise<unknown>) => {\n if (launching.current) {\n return\n }\n launching.current = true\n setLaunchError(undefined)\n launch().then(handleClose, (e: unknown) => {\n launching.current = false\n console.error(e)\n setLaunchError(e)\n })\n },\n }\n}\n", "import { useMemo, useState } from 'react'\n\nimport { featureMatchesId, getId, getSortedTranscriptFeatures } from '../util'\nimport { useFeatureSequence } from './useFeatureSequence'\n\nimport type { SequenceStatus } from './SequenceStatus'\nimport type { Feature } from '@jbrowse/core/util'\n\n// Keep the current selection if it's valid for the given validIds, otherwise\n// fall back to the first valid option (or the current id if none qualify). With\n// no validIds constraint the current selection always stands.\nfunction pickSelectedId(\n currentId: string,\n options: Feature[],\n validIds: string[] | undefined,\n): string {\n if (!validIds?.length) {\n return currentId\n }\n const isValid = (opt: Feature) =>\n validIds.some(id => featureMatchesId(opt, id))\n const current = options.find(opt => getId(opt) === currentId)\n if (current && isValid(current)) {\n return currentId\n }\n const firstValid = options.find(isValid)\n return firstValid ? getId(firstValid) : currentId\n}\n\n/**\n * Submit is disabled until the query sequence is in hand, and a grey button\n * reads the same whether the translation is on its way or was never going to\n * arrive. `missing` is the second case: the feature has no CDS to translate,\n * which the dialog never said.\n */\nfunction sequenceStatus({\n error,\n isLoading,\n proteinSequence,\n}: {\n error: unknown\n isLoading: boolean\n proteinSequence: string\n}): SequenceStatus {\n if (error) {\n return 'error'\n }\n if (isLoading) {\n return 'loading'\n }\n return proteinSequence ? 'ready' : 'missing'\n}\n\nexport function useTranscriptSelection({\n feature,\n view,\n validIds,\n preferredTranscriptId,\n}: {\n feature: Feature\n view: { assemblyNames?: string[] } | undefined\n validIds?: string[]\n /**\n * the isoform the user right-clicked, when the dialog opened on its gene.\n * Ignored when this gene does not carry it, so a stale id falls back to the\n * longest transcript rather than selecting nothing.\n */\n preferredTranscriptId?: string\n}) {\n const options = useMemo(() => getSortedTranscriptFeatures(feature), [feature])\n const [selectedId, setSelectedId] = useState(() =>\n getId(\n options.find(opt => featureMatchesId(opt, preferredTranscriptId ?? '')) ??\n options[0],\n ),\n )\n const validatedSelectedId = pickSelectedId(selectedId, options, validIds)\n const selectedTranscript = options.find(\n val => getId(val) === validatedSelectedId,\n )\n const { proteinSequence, error, isLoading } = useFeatureSequence({\n view,\n feature: selectedTranscript,\n })\n\n return {\n options,\n selectedId: validatedSelectedId,\n setSelectedId,\n selectedTranscript,\n proteinSequence,\n error,\n isLoading,\n sequenceStatus: sequenceStatus({ error, isLoading, proteinSequence }),\n validIds,\n }\n}\n", "import { useMemo } from 'react'\n\nimport { getSession } from '@jbrowse/core/util'\nimport { translateTranscript } from '@jbrowse/core/util/translateTranscript'\n\nimport { useFetch } from '../../utils/useFetch'\nimport { fetchSeq } from './fetchSeq'\n\nimport type { Feature } from '@jbrowse/core/util'\n\ninterface ViewLike {\n assemblyNames?: string[]\n}\n\nexport function useFeatureSequence({\n view,\n feature,\n}: {\n view: ViewLike | undefined\n feature?: Feature\n}) {\n const assemblyName = view?.assemblyNames?.[0]\n const {\n data: sequence,\n error,\n isLoading,\n } = useFetch(\n feature && assemblyName\n ? [feature.id(), assemblyName, 'feature-sequence']\n : null,\n async () => {\n const { start, end, refName } = feature!.toJSON() as {\n start: number\n end: number\n refName: string\n }\n return fetchSeq({\n start,\n end,\n refName,\n assemblyName: assemblyName!,\n session: getSession(view),\n })\n },\n )\n\n const proteinSequence = useMemo(\n () =>\n sequence && feature\n ? (translateTranscript({ transcript: feature, ...sequence })?.protein ??\n '')\n : '',\n [sequence, feature],\n )\n return {\n proteinSequence,\n sequence,\n error,\n isLoading,\n }\n}\n", "import { useCallback, useEffect, useRef, useState } from 'react'\n\n// A trimmed copy of jbrowse-components' `packages/core/src/util/useFetch.ts`,\n// vendored for the same reason `useLocalStorage` and `defaultCodonTable` are:\n// it does not exist in the @jbrowse/core this plugin builds against, and a\n// host-resolved import is exactly how published bundles have broken here\n// before. Our own copy takes this out of the whack-a-mole.\n//\n// Trimmed because this plugin has no RPC: the core version also carries stop\n// tokens, a throttled progress stream and a cross-component mutate registry,\n// and nothing here has ever wanted any of the three. What is left is the\n// {data, error, isLoading} the four call sites this replaced actually used --\n// they were on SWR, whose only feature we relied on was fetch-once-per-key with\n// background revalidation off, so dropping it also drops a dependency from the\n// bundle.\n\nexport type FetchKey = string | readonly unknown[] | null | undefined | false\n\nconst isNil = (k: unknown) => k === null || k === undefined || k === false\n\n// A null result means \"don't fetch\": no key, or an array key with a missing\n// piece. Note what that makes of a boolean IN a key -- `false` reads as a\n// missing piece and silently disables the fetch, so put a string there.\nexport function serializeKey(key: FetchKey): string | null {\n return isNil(key) || (Array.isArray(key) && key.some(isNil))\n ? null\n : JSON.stringify(key)\n}\n\ninterface Settled<Data> {\n /** the key AND the attempt, so a mutate() refetch is a different entry */\n attempt: string\n /** the key alone, which is the question the data answers */\n question: string\n data?: Data\n error?: unknown\n}\n\n/**\n * Fetch once per key, keeping loading and error state with the data instead of\n * spread across three `useState`s and a cancellation flag.\n *\n * Everything the caller reads is derived from the one settled result, which is\n * what keeps the states consistent: while a key change is in flight there is no\n * frame showing the previous key's data as though it were the new key's. A\n * `mutate()` refetch under the same key does leave its data up, because it is\n * the same question asked again and blanking it flashes an empty list.\n */\nexport function useFetch<Data>(\n key: FetchKey,\n fetcher: (signal: AbortSignal) => Promise<Data>,\n { onSuccess }: { onSuccess?: (data: Data) => void } = {},\n) {\n const serialized = serializeKey(key)\n const [nonce, setNonce] = useState(0)\n const [settled, setSettled] = useState<Settled<Data>>()\n\n const attempt = serialized === null ? null : `${nonce}\\u0000${serialized}`\n const current = settled?.attempt === attempt\n const answersThisKey = settled?.question === serialized\n\n // The fetcher and the success callback are inline closures at every call site,\n // so depending on their identity would refetch every render. This effect is\n // declared before the fetch effect and has no dependency list, so it has\n // already run with the current render's values by the time that one does.\n const latest = useRef({ fetcher, onSuccess })\n useEffect(() => {\n latest.current = { fetcher, onSuccess }\n })\n\n useEffect(() => {\n if (attempt === null || serialized === null) {\n return undefined\n }\n const controller = new AbortController()\n latest.current\n .fetcher(controller.signal)\n .then(data => {\n if (!controller.signal.aborted) {\n setSettled({ attempt, question: serialized, data })\n latest.current.onSuccess?.(data)\n }\n })\n .catch((error: unknown) => {\n if (!controller.signal.aborted) {\n setSettled({ attempt, question: serialized, error })\n }\n })\n return () => {\n controller.abort()\n }\n }, [attempt, serialized])\n\n return {\n data: answersThisKey ? settled.data : undefined,\n error: current ? settled.error : undefined,\n isLoading: attempt !== null && !current,\n mutate: useCallback(() => {\n setNonce(n => n + 1)\n }, []),\n }\n}\n\n/** `value`, but only after it has stopped changing for `ms`. */\nexport function useDebounced<T>(value: T, ms: number) {\n const [debounced, setDebounced] = useState(value)\n useEffect(() => {\n const timer = setTimeout(() => {\n setDebounced(value)\n }, ms)\n return () => {\n clearTimeout(timer)\n }\n }, [value, ms])\n return debounced\n}\n", "import React, { useState } from 'react'\n\nimport { ErrorMessage } from '@jbrowse/core/ui'\nimport DeleteIcon from '@mui/icons-material/Delete'\nimport {\n Button,\n IconButton,\n List,\n ListItem,\n ListItemButton,\n ListItemText,\n Typography,\n} from '@mui/material'\nimport { observer } from 'mobx-react'\nimport { makeStyles } from 'tss-react/mui'\n\nimport {\n featureMatchesId,\n getLinearGenomeView,\n getSortedTranscriptFeatures,\n} from '../../util'\nimport { builtAlignmentLook, launchConnectedView } from '../launchConnectedView'\nimport { useLaunchPlacement } from '../launchPlacement'\n\nimport type { CachedBlastResult } from '../../../utils/blastCache'\nimport type { useCachedBlastResults } from './useCachedBlastResults'\nimport type { AbstractTrackModel, Feature } from '@jbrowse/core/util'\n\nconst useStyles = makeStyles()({\n header: {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n marginBottom: 8,\n },\n resultList: {\n maxHeight: 300,\n overflow: 'auto',\n },\n})\n\nfunction getResultDisplayName(result: CachedBlastResult): string {\n const parts = [\n result.geneName,\n result.transcriptName !== result.geneName\n ? result.transcriptName\n : undefined,\n ].filter((p): p is string => !!p)\n return parts.length > 0\n ? parts.join(' - ')\n : (result.geneId ?? result.transcriptId ?? 'Unknown')\n}\n\n/**\n * How the row was produced: `uniprotkb_swissprot / blastp / clustalo`, or\n * `swissprot / phmmer` for a row phmmer aligned as it searched and that\n * therefore ran no aligner. Each part is dropped when absent rather than\n * printed empty \u2014 `msaAlgorithm` became optional when phmmer arrived, and a\n * phmmer row read `(undefined)` until this stopped assuming one.\n *\n * `blastProgram` is the older field, written only while the plugin still\n * queried NCBI directly and blastp/quick-blastp was a real choice.\n */\nexport function describeSearch(result: CachedBlastResult) {\n return [\n result.blastDatabase,\n result.searchProgram ?? result.blastProgram ?? 'blastp',\n result.msaAlgorithm,\n ]\n .filter(Boolean)\n .join(' / ')\n}\n\nconst CachedBlastResults = observer(function ({\n model,\n handleClose,\n feature,\n cached: { results, handleDelete, handleClearAll },\n}: {\n model: AbstractTrackModel\n handleClose: () => void\n feature: Feature\n /** the panel's own listing, so clearing it here empties it there too */\n cached: ReturnType<typeof useCachedBlastResults>\n}) {\n const { classes } = useStyles()\n const view = getLinearGenomeView(model)\n const [operationError, setOperationError] = useState<unknown>()\n const [sideBySide] = useLaunchPlacement()\n\n const handleUseCached = (cached: CachedBlastResult) => {\n // the cached query row is the plugin's default `QUERY`, translated from\n // the transcript stored as transcriptId, so that transcript relinks it\n const { transcriptId, msa, tree, treeMetadata } = cached\n launchConnectedView({\n view,\n feature: transcriptId\n ? getSortedTranscriptFeatures(feature).find(t =>\n featureMatchesId(t, transcriptId),\n )\n : undefined,\n placement: sideBySide ? 'splitRight' : 'stack',\n displayName: `BLAST - ${getResultDisplayName(cached)}`,\n ...builtAlignmentLook,\n data: { msa, tree, treeMetadata },\n }).then(handleClose, (e: unknown) => {\n console.error(e)\n setOperationError(e)\n })\n }\n\n return (\n <div>\n {operationError ? <ErrorMessage error={operationError} /> : null}\n <div className={classes.header}>\n <Typography variant=\"subtitle1\">\n Cached BLAST Results ({results.length})\n </Typography>\n <Button\n size=\"small\"\n color=\"error\"\n onClick={async () => {\n try {\n setOperationError(undefined)\n await handleClearAll()\n } catch (e) {\n setOperationError(e)\n }\n }}\n >\n Clear results for this gene\n </Button>\n </div>\n <List dense className={classes.resultList}>\n {results.map(result => (\n <ListItem\n key={result.id}\n disablePadding\n secondaryAction={\n <IconButton\n edge=\"end\"\n size=\"small\"\n onClick={async e => {\n e.stopPropagation()\n try {\n setOperationError(undefined)\n await handleDelete(result.id)\n } catch (err) {\n setOperationError(err)\n }\n }}\n >\n <DeleteIcon fontSize=\"small\" />\n </IconButton>\n }\n >\n <ListItemButton\n onClick={() => {\n handleUseCached(result)\n }}\n >\n <ListItemText\n primary={`${getResultDisplayName(result)} - ${describeSearch(result)}`}\n secondary={`${new Date(result.timestamp).toLocaleString()} - Seq: ${result.proteinSequence.slice(0, 30)}...`}\n />\n </ListItemButton>\n </ListItem>\n ))}\n </List>\n </div>\n )\n})\n\nexport default CachedBlastResults\n", "\"use client\";\n\nimport createSvgIcon from \"./utils/createSvgIcon.mjs\";\nimport { jsx as _jsx } from \"react/jsx-runtime\";\nexport default createSvgIcon(/*#__PURE__*/_jsx(\"path\", {\n d: \"M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6zM19 4h-3.5l-1-1h-5l-1 1H5v2h14z\"\n}), 'Delete');", "import React from 'react'\n\nimport { MenuItem } from '@mui/material'\n\nimport TextField2 from '../../../components/TextField2'\nimport { msaAlgorithmLabels, msaAlgorithms } from './consts'\n\nimport type { MsaAlgorithm } from './consts'\n\nexport default function MsaAlgorithmSelect({\n value,\n onChange,\n className,\n}: {\n value: MsaAlgorithm\n onChange: (val: MsaAlgorithm) => void\n className?: string\n}) {\n return (\n <TextField2\n variant=\"outlined\"\n label=\"MSA Algorithm\"\n className={className}\n select\n value={value}\n helperText={\n value === 'browser'\n ? 'no EBI job; rows aligned to the query'\n : undefined\n }\n onChange={event => {\n onChange(event.target.value as MsaAlgorithm)\n }}\n >\n {msaAlgorithms.map(val => (\n <MenuItem value={val} key={val}>\n {msaAlgorithmLabels[val]}\n </MenuItem>\n ))}\n </TextField2>\n )\n}\n", "import { useLocalStorage } from '../../../utils/useLocalStorage'\nimport {\n databaseOptionsFor,\n defaultSearchFor,\n msaAlgorithms,\n searchPrograms,\n} from './consts'\n\nimport type { MsaAlgorithm, SearchChoice } from './consts'\n\n// The panel reopens on the last search run rather than on the defaults, the way\n// the Orthologs tab remembers its source.\n//\n// The program and its database stay ONE stored value for the reason consts.ts\n// keeps them one state: neither service knows the other's database names. What\n// comes back is checked against the current options before it is used \u2014 an\n// option this plugin has since dropped would otherwise reach EBI and come back\n// a 400, minutes after the user pressed Submit.\nconst SEARCH_CHOICE_STORAGE_KEY = 'msaView-blastSearch'\nconst MSA_ALGORITHM_STORAGE_KEY = 'msaView-msaAlgorithm'\n\nconst defaultSearch = defaultSearchFor('blastp')\nconst defaultMsaAlgorithm: MsaAlgorithm = 'clustalo'\n\nexport function validSearchChoice(stored: unknown): SearchChoice {\n const { program, database } = (stored ?? {}) as {\n program?: string\n database?: string\n }\n const known = searchPrograms.find(p => p === program)\n return known && databaseOptionsFor(known).some(d => d === database)\n ? ({ program: known, database } as SearchChoice)\n : defaultSearch\n}\n\nexport function validMsaAlgorithm(stored: unknown): MsaAlgorithm {\n return msaAlgorithms.find(a => a === stored) ?? defaultMsaAlgorithm\n}\n\nexport function useStoredSearchChoice() {\n const [stored, setStored] = useLocalStorage<unknown>(\n SEARCH_CHOICE_STORAGE_KEY,\n defaultSearch,\n )\n return [\n validSearchChoice(stored),\n (choice: SearchChoice) => {\n setStored(choice)\n },\n ] as const\n}\n\nexport function useStoredMsaAlgorithm() {\n const [stored, setStored] = useLocalStorage<unknown>(\n MSA_ALGORITHM_STORAGE_KEY,\n defaultMsaAlgorithm,\n )\n return [\n validMsaAlgorithm(stored),\n (algorithm: MsaAlgorithm) => {\n setStored(algorithm)\n },\n ] as const\n}\n", "import {\n deleteCachedResult,\n getAllCachedResults,\n} from '../../../utils/blastCache'\nimport { useFetch } from '../../../utils/useFetch'\n\nexport function useCachedBlastResults(geneIds: string[]) {\n const {\n data: results,\n error,\n isLoading,\n mutate,\n } = useFetch(`cached-blast-${geneIds.join(',')}`, async () => {\n const cached = await getAllCachedResults()\n return cached.filter(r => r.geneId && geneIds.includes(r.geneId))\n })\n\n return {\n results: results ?? [],\n error,\n isLoading,\n handleDelete: async (id: string) => {\n await deleteCachedResult(id)\n mutate()\n },\n // deletes only what this hook listed, i.e. the results for these gene ids.\n // The list the user is looking at is gene-scoped, so a store-wide clear here\n // would silently throw away every other gene's cached alignments too\n handleClearAll: async () => {\n await Promise.all((results ?? []).map(r => deleteCachedResult(r.id)))\n mutate()\n },\n }\n}\n", "import React, { useState } from 'react'\n\nimport { shorten2 } from '@jbrowse/core/util'\nimport { Alert, Typography } from '@mui/material'\nimport { observer } from 'mobx-react'\nimport { makeStyles } from 'tss-react/mui'\n\nimport ExternalLink from '../../../components/ExternalLink'\nimport TextField2 from '../../../components/TextField2'\nimport { useQueryRowName } from '../../useQueryRowName'\nimport {\n cleanProteinSequence,\n getGeneDisplayName,\n getLinearGenomeView,\n} from '../../util'\nimport LaunchPanelContent from '../LaunchPanelContent'\nimport QueryRowSelector from '../QueryRowSelector'\nimport SubmitCancelActions from '../SubmitCancelActions'\nimport TranscriptSelector from '../TranscriptSelector'\nimport { launchConnectedView, useLaunchSubmit } from '../launchConnectedView'\nimport { useTranscriptSelection } from '../useTranscriptSelection'\nimport { BASE_BLAST_URL } from './consts'\n\nimport type { AbstractTrackModel, Feature } from '@jbrowse/core/util'\n\nconst useStyles = makeStyles()({\n ncbiLink: {\n wordBreak: 'break-all',\n },\n textAreaFont: {\n fontFamily: 'Courier New',\n },\n msaInput: {\n marginBottom: 20,\n },\n step: {\n marginTop: 20,\n },\n stepBody: {\n marginLeft: 20,\n marginTop: 8,\n },\n})\n\n/**\n * The route to NCBI's `nr`, which no plugin version can query directly: NCBI\n * stopped sending Access-Control-Allow-Origin to third-party origins, so the\n * browser cannot read Blast.cgi at all (see docs/blast.md).\n *\n * That makes the round trip through NCBI's own site the whole feature rather\n * than a fallback, so the panel walks it end to end. It used to hand the user a\n * link, tell them to \"paste the results into JBrowse\", and offer only a Close\n * button -- leaving them to find the Manual upload tab, re-pick the transcript\n * they had already chosen here, and hand-type the row name.\n */\nconst BlastManualPanel = observer(function ({\n handleClose,\n feature,\n model,\n children,\n preferredTranscriptId,\n}: {\n children: React.ReactNode\n model: AbstractTrackModel\n feature: Feature\n handleClose: () => void\n /** the isoform the user right-clicked, preselected in the picker */\n preferredTranscriptId?: string\n}) {\n const { classes } = useStyles()\n const view = getLinearGenomeView(model)\n const { launchError, submit } = useLaunchSubmit(handleClose)\n const [msaText, setMsaText] = useState('')\n const [treeText, setTreeText] = useState('')\n\n const transcriptSelection = useTranscriptSelection({\n feature,\n view,\n preferredTranscriptId,\n })\n const { proteinSequence, selectedTranscript, error } = transcriptSelection\n const queryRow = useQueryRowName(msaText, proteinSequence)\n\n const s2 = cleanProteinSequence(proteinSequence)\n // a link the user follows to NCBI's own site, not something we fetch \u2014 which\n // is exactly why this route still works when the automatic one cannot\n const link = `${BASE_BLAST_URL}?PAGE_TYPE=BlastSearch&PAGE=Proteins&PROGRAM=blastp&QUERY=${s2}`\n const link2 = `${BASE_BLAST_URL}?PAGE_TYPE=BlastSearch&PAGE=Proteins&PROGRAM=blastp&QUERY=${shorten2(s2, 10)}`\n\n return (\n <>\n <LaunchPanelContent error={launchError ?? error}>\n {children}\n\n <TranscriptSelector feature={feature} {...transcriptSelection} />\n\n <div className={classes.step}>\n <Typography variant=\"subtitle2\">1. Run the search at NCBI</Typography>\n <div className={classes.stepBody}>\n {proteinSequence ? (\n <div className={classes.ncbiLink}>\n <ExternalLink href={link}>{link2}</ExternalLink>\n </div>\n ) : (\n <Alert severity=\"info\">\n Pick a transcript above to get a link carrying its protein\n sequence.\n </Alert>\n )}\n </div>\n </div>\n\n <div className={classes.step}>\n <Typography variant=\"subtitle2\">2. Align the hits</Typography>\n <div className={classes.stepBody}>\n <Typography>\n On the results page click \"Multiple Alignment\" to run COBALT,\n NCBI's aligner. Download the alignment (.aln) and, if you want the\n tree drawn, the Newick tree (.nh).\n </Typography>\n </div>\n </div>\n\n <div className={classes.step}>\n <Typography variant=\"subtitle2\">\n 3. Paste the results back here\n </Typography>\n <div className={classes.stepBody}>\n <TextField2\n variant=\"outlined\"\n label=\"Alignment\"\n multiline\n minRows={5}\n maxRows={10}\n fullWidth\n className={classes.msaInput}\n slotProps={{ input: { className: classes.textAreaFont } }}\n placeholder=\"Paste the .aln contents here\"\n value={msaText}\n onChange={event => {\n setMsaText(event.target.value)\n }}\n />\n <TextField2\n variant=\"outlined\"\n label=\"Tree (optional)\"\n multiline\n minRows={3}\n maxRows={10}\n fullWidth\n slotProps={{ input: { className: classes.textAreaFont } }}\n placeholder=\"Paste the .nh Newick tree here\"\n value={treeText}\n onChange={event => {\n setTreeText(event.target.value)\n }}\n />\n\n <QueryRowSelector {...queryRow} />\n </div>\n </div>\n </LaunchPanelContent>\n\n <SubmitCancelActions\n model={model}\n submitDisabled={!selectedTranscript || !msaText.trim()}\n onSubmit={placement => {\n if (selectedTranscript) {\n submit(() =>\n launchConnectedView({\n view,\n feature: selectedTranscript,\n placement,\n displayName: getGeneDisplayName(selectedTranscript),\n querySeqName: queryRow.querySeqName,\n querySeqOffset: queryRow.querySeqOffset,\n data: { msa: msaText, tree: treeText },\n }),\n )\n }\n }}\n onCancel={handleClose}\n />\n </>\n )\n})\n\nexport default BlastManualPanel\n", "import { useMemo, useState } from 'react'\n\nimport { findQueryRow } from './detectQueryRow'\n\n/**\n * The MSA row name to launch with, found by sequence rather than typed.\n *\n * Only the user's override is state. The detected name is derived from the\n * pasted text during render, so pasting a new alignment re-detects without an\n * effect writing back into state, and an override survives later edits to the\n * alignment because it is the one thing actually stored.\n */\n/**\n * The row to launch with. Detection by residues is the answer wherever it has\n * one -- aligners rename the query on the way through, so a name proves\n * nothing -- but a caller with a naming convention of its own can offer it as a\n * fallback, and it is taken only when the alignment really carries that row.\n * An empty result means there is no query row, which a launch has to refuse:\n * the view opens, renders, and then never navigates.\n */\nexport function resolveQueryRowName(\n queryRow: { querySeqName: string; names: string[] },\n fallback: string,\n) {\n return (\n queryRow.querySeqName || (queryRow.names.includes(fallback) ? fallback : '')\n )\n}\n\nexport function useQueryRowName(msaText: string, proteinSequence: string) {\n const [override, setOverride] = useState<string>()\n\n // parsing runs on every keystroke in the paste box otherwise, and an\n // alignment of a few hundred rows is not free\n const { names, match } = useMemo(\n () => findQueryRow(msaText, proteinSequence),\n [msaText, proteinSequence],\n )\n\n // a row picked from one alignment says nothing about the next one pasted\n const picked =\n override !== undefined && (names.length === 0 || names.includes(override))\n ? override\n : undefined\n const querySeqName = picked ?? match?.name ?? ''\n return {\n detected: match,\n names,\n querySeqName,\n // only the detected row's offset is known; a row the user picked instead is\n // taken at face value, residue 1 to residue 1\n querySeqOffset: querySeqName === match?.name ? match.offset : 0,\n setQuerySeqName: setOverride,\n isAutoDetected: picked === undefined && !!match,\n }\n}\n", "import { getUngappedSequence, parseMSA } from 'msa-parsers'\n\nimport { cleanProteinSequence } from './util'\n\n/**\n * Which row of a pasted alignment is the gene the user launched from.\n *\n * The MsaView needs that row name to tie alignment columns back to genome\n * coordinates, and until now the user typed it. Nothing validates a typo: the\n * view opens, renders, and simply never navigates or highlights, which reads as\n * a broken feature rather than a wrong field. Meanwhile the plugin already\n * knows the protein sequence it sent to BLAST, so it can find the row by\n * sequence instead of asking.\n *\n * NCBI and EBI both rename the query on the way through -- COBALT emits\n * `Query_1`, EBI's aligners carry the accession -- so the name is no help. The\n * residues are, and they survive every rename.\n */\n\nexport type MatchQuality = 'exact' | 'partial' | 'similar'\n\nexport interface QueryRowMatch {\n name: string\n quality: MatchQuality\n /** identity over the compared region, 0-1 */\n identity: number\n /**\n * Transcript residues before the row's first residue, so transcript position\n * = row position + offset. BLAST reports the aligned region, so a row is\n * often the query with its termini trimmed, and mapping its first residue to\n * the transcript's first residue would put every navigation off by the\n * trimmed amount. Negative when the row is the longer of the two.\n *\n * Zero for a `similar` match, which is the one arm this cannot measure: the\n * row is not the query, so where it starts is a guess.\n */\n offset: number\n}\n\n/**\n * The translation as a search launch would have sent it, so a row that launch\n * built matches exactly; case means nothing on either side.\n */\nfunction normalize(seq: string) {\n return cleanProteinSequence(seq).toUpperCase()\n}\n\nfunction identityOverOverlap(a: string, b: string) {\n const len = Math.min(a.length, b.length)\n if (len === 0) {\n return 0\n }\n let same = 0\n for (let i = 0; i < len; i++) {\n if (a[i] === b[i]) {\n same++\n }\n }\n return same / len\n}\n\n/**\n * Below this, a \"best\" row is not a match at all -- an alignment of homologs is\n * full of rows in the 40-70% range, and picking the top one would silently wire\n * the view to a paralog from another species.\n */\nconst SIMILARITY_FLOOR = 0.9\n\n/**\n * How much of the query a contained row has to cover. A short fragment is a\n * substring of almost any protein, so without a floor the first few residues of\n * a half-pasted alignment match the query and the field fills in with a row the\n * user is still typing.\n */\nconst PARTIAL_COVERAGE_FLOOR = 0.5\n\nexport interface MsaQueryRow {\n /** every row name, in file order, for the picker to offer */\n names: string[]\n /** the row whose residues are the query's, if one of them is */\n match?: QueryRowMatch\n}\n\n/**\n * The picker's whole answer for a pasted alignment: its row names, and which of\n * them is the query.\n *\n * One function rather than two because there is one parse. Both answers were\n * wanted on every keystroke in the paste box, and asking separately parsed a\n * few-hundred-row alignment twice per character.\n */\nexport function findQueryRow(\n msaText: string,\n proteinSequence: string,\n): MsaQueryRow {\n if (!msaText.trim()) {\n return { names: [] }\n }\n\n let parsed\n try {\n parsed = parseMSA(msaText)\n } catch {\n // a half-pasted alignment throws here on every keystroke; the caller shows\n // the field rather than an error\n return { names: [] }\n }\n\n const names = parsed.getNames()\n const query = normalize(proteinSequence)\n return { names, match: query ? bestMatch(parsed, names, query) : undefined }\n}\n\nfunction bestMatch(\n parsed: { getRow: (name: string) => string },\n names: string[],\n query: string,\n): QueryRowMatch | undefined {\n const candidates: QueryRowMatch[] = []\n for (const name of names) {\n const row = normalize(getUngappedSequence(parsed.getRow(name)))\n if (!row) {\n continue\n }\n if (row === query) {\n // nothing beats an exact match, and a second one would be a duplicate row\n return { name, quality: 'exact', identity: 1, offset: 0 }\n }\n // BLAST reports the aligned region, so the row is often the query trimmed\n // at one or both ends rather than the whole protein\n const contained = query.indexOf(row)\n const containing = row.indexOf(query)\n if (contained !== -1 || containing !== -1) {\n const coverage =\n Math.min(row.length, query.length) / Math.max(row.length, query.length)\n if (coverage >= PARTIAL_COVERAGE_FLOOR) {\n candidates.push({\n name,\n quality: 'partial',\n identity: coverage,\n offset: contained === -1 ? -containing : contained,\n })\n }\n continue\n }\n const identity = identityOverOverlap(row, query)\n if (identity >= SIMILARITY_FLOOR) {\n candidates.push({ name, quality: 'similar', identity, offset: 0 })\n }\n }\n\n // an exact match returns above, so only these two can be here\n const order: MatchQuality[] = ['partial', 'similar']\n return candidates.sort(\n (a, b) =>\n order.indexOf(a.quality) - order.indexOf(b.quality) ||\n b.identity - a.identity,\n )[0]\n}\n", "import React from 'react'\n\nimport { Alert, MenuItem } from '@mui/material'\nimport { makeStyles } from 'tss-react/mui'\n\nimport TextField2 from '../../components/TextField2'\n\nimport type { QueryRowMatch } from '../detectQueryRow'\n\nconst useStyles = makeStyles()({\n field: {\n marginTop: 20,\n },\n alert: {\n marginTop: 10,\n },\n})\n\n/**\n * Where a trimmed row sits in the protein. The offset is what the view maps\n * through, so the alert says it rather than leaving the user to wonder why the\n * row is shorter than their transcript.\n */\nfunction partialCoverage({\n identity,\n offset,\n}: {\n identity: number\n offset: number\n}) {\n const covering = `, covering ${Math.round(identity * 100)}% of it`\n return offset > 0\n ? `${covering} from residue ${offset + 1}`\n : offset < 0\n ? `${covering} and running ${-offset} residues past its start`\n : covering\n}\n\n/**\n * Which MSA row corresponds to the selected transcript. Clicking and hovering in\n * the alignment reach the genome only through this name, and a wrong one fails\n * silently -- the view opens, renders, and never navigates -- so the field fills\n * itself in from the pasted alignment and offers that alignment's own row names\n * rather than a free text box the user can typo.\n */\nexport default function QueryRowSelector({\n names,\n detected,\n querySeqName,\n setQuerySeqName,\n isAutoDetected,\n}: {\n names: string[]\n detected?: QueryRowMatch\n querySeqName: string\n setQuerySeqName: (arg: string) => void\n isAutoDetected: boolean\n}) {\n const { classes } = useStyles()\n\n return (\n <>\n {names.length > 0 ? (\n <TextField2\n variant=\"outlined\"\n label=\"MSA row matching the selected transcript\"\n select\n fullWidth\n className={classes.field}\n value={names.includes(querySeqName) ? querySeqName : ''}\n onChange={event => {\n setQuerySeqName(event.target.value)\n }}\n >\n {names.map(name => (\n <MenuItem value={name} key={name}>\n {name}\n {detected?.name === name ? ' \u2014 matches your protein' : ''}\n </MenuItem>\n ))}\n </TextField2>\n ) : (\n <TextField2\n variant=\"outlined\"\n label=\"MSA row matching the selected transcript\"\n fullWidth\n className={classes.field}\n helperText=\"Paste an alignment above and this fills in on its own\"\n value={querySeqName}\n onChange={event => {\n setQuerySeqName(event.target.value)\n }}\n />\n )}\n\n {isAutoDetected && detected ? (\n detected.quality === 'similar' ? (\n <Alert severity=\"warning\" className={classes.alert}>\n <strong>{detected.name}</strong> is{' '}\n {Math.round(detected.identity * 100)}% identical to your protein but\n is not the same sequence. Clicking the alignment navigates the\n genome view, approximately: wherever the two differ by an insertion\n or a deletion, every residue after it lands one codon off.\n </Alert>\n ) : (\n <Alert severity=\"success\" className={classes.alert}>\n Matched <strong>{detected.name}</strong> to your protein sequence\n {detected.quality === 'exact' ? '' : partialCoverage(detected)}.\n Clicking the alignment will navigate the genome view.\n </Alert>\n )\n ) : names.length > 0 && !querySeqName ? (\n <Alert severity=\"warning\" className={classes.alert}>\n No row matched your protein sequence \u2014 pick the one for your gene\n above. Without it the alignment still renders, but clicking it will\n not navigate the genome view.\n </Alert>\n ) : null}\n </>\n )\n}\n", "import React from 'react'\n\nimport { FormControl, FormControlLabel, Radio, RadioGroup } from '@mui/material'\n\nimport type { BlastLookupMethod } from './BlastPanel'\n\nexport default function BlastMethodSelector({\n lookupMethod,\n setLookupMethod,\n}: {\n lookupMethod: BlastLookupMethod\n setLookupMethod: (method: BlastLookupMethod) => void\n}) {\n return (\n <FormControl component=\"fieldset\">\n <RadioGroup\n row\n value={lookupMethod}\n onChange={event => {\n setLookupMethod(event.target.value as BlastLookupMethod)\n }}\n >\n <FormControlLabel\n value=\"automatic\"\n control={<Radio />}\n label=\"Automatic\"\n />\n <FormControlLabel value=\"manual\" control={<Radio />} label=\"Manual\" />\n </RadioGroup>\n </FormControl>\n )\n}\n", "import React, { useState } from 'react'\n\nimport {\n Button,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n Typography,\n} from '@mui/material'\nimport { makeStyles } from 'tss-react/mui'\n\nimport TextField2 from '../../../components/TextField2'\nimport { DEFAULT_EBI_EMAIL } from '../../../utils/ebiJobDispatcher'\n\nconst useStyles = makeStyles()({\n field: {\n minWidth: 300,\n },\n help: {\n marginBottom: 8,\n },\n})\n\nexport interface BlastSettings {\n ebiEmail: string\n}\n\nexport default function BlastSettingsDialog({\n handleClose,\n ebiEmail,\n}: {\n handleClose: (arg?: BlastSettings) => void\n ebiEmail: string\n}) {\n const { classes } = useStyles()\n const [tempEbiEmail, setTempEbiEmail] = useState(ebiEmail)\n return (\n <Dialog\n open\n maxWidth=\"lg\"\n onClose={() => {\n handleClose()\n }}\n >\n <DialogTitle>EBI settings</DialogTitle>\n <DialogContent>\n <Typography variant=\"subtitle2\" className={classes.help}>\n Every search this tab runs is submitted to EBI with this address,\n which is how they reach whoever is generating the load. If your site\n sends real volume, use your own.\n </Typography>\n <TextField2\n autoFocus\n margin=\"dense\"\n label=\"EBI contact email\"\n fullWidth\n variant=\"outlined\"\n value={tempEbiEmail}\n className={classes.field}\n onChange={e => {\n setTempEbiEmail(e.target.value)\n }}\n />\n <Button\n variant=\"contained\"\n onClick={() => {\n setTempEbiEmail(DEFAULT_EBI_EMAIL)\n }}\n >\n Reset\n </Button>\n </DialogContent>\n <DialogActions>\n <Button\n variant=\"contained\"\n color=\"secondary\"\n onClick={() => {\n handleClose()\n }}\n >\n Cancel\n </Button>\n <Button\n color=\"primary\"\n variant=\"contained\"\n onClick={() => {\n handleClose({ ebiEmail: tempEbiEmail })\n }}\n >\n Save\n </Button>\n </DialogActions>\n </Dialog>\n )\n}\n", "import React, { Suspense, lazy, useState } from 'react'\n\nimport Help from '@mui/icons-material/Help'\nimport { IconButton, Tooltip } from '@mui/material'\n\nconst HelpDialog = lazy(() => import('./HelpDialog'))\n\nexport default function HelpButton() {\n const [show, setShow] = useState(false)\n return (\n <>\n <Tooltip title=\"What each tab does\">\n <IconButton\n aria-label=\"Help\"\n onClick={() => {\n setShow(true)\n }}\n >\n <Help />\n </IconButton>\n </Tooltip>\n {show ? (\n <Suspense fallback={null}>\n <HelpDialog\n handleClose={() => {\n setShow(false)\n }}\n />\n </Suspense>\n ) : null}\n </>\n )\n}\n", "import React, { useState } from 'react'\n\nimport { FileSelector } from '@jbrowse/core/ui'\nimport { openLocation } from '@jbrowse/core/util/io'\nimport { FormControl, FormControlLabel, Radio, RadioGroup } from '@mui/material'\nimport { observer } from 'mobx-react'\nimport { makeStyles } from 'tss-react/mui'\n\nimport TextField2 from '../../../components/TextField2'\nimport { useDebounced, useFetch } from '../../../utils/useFetch'\nimport { useQueryRowName } from '../../useQueryRowName'\nimport { getGeneDisplayName, getLinearGenomeView } from '../../util'\nimport LaunchPanelContent from '../LaunchPanelContent'\nimport QueryRowSelector from '../QueryRowSelector'\nimport SequenceStatusMessage from '../SequenceStatus'\nimport SubmitCancelActions from '../SubmitCancelActions'\nimport TranscriptSelector from '../TranscriptSelector'\nimport { launchConnectedView, useLaunchSubmit } from '../launchConnectedView'\nimport { useTranscriptSelection } from '../useTranscriptSelection'\n\nimport type {\n AbstractTrackModel,\n Feature,\n FileLocation,\n} from '@jbrowse/core/util'\n\n/**\n * The chosen file's text, so its query row is found by sequence the way a\n * pasted alignment's is; without it a file launch named no row and never\n * linked to the genome. Debounced because a URL arrives a keystroke at a time.\n */\nfunction useMsaFileText(location: FileLocation | undefined) {\n const debounced = useDebounced(location, 500)\n const { data, error, isLoading } = useFetch(\n debounced ? [JSON.stringify(debounced), 'msa-file-text'] : null,\n () => openLocation(debounced!).readFile('utf8'),\n )\n return {\n text: data ?? '',\n error,\n isLoading: isLoading || debounced !== location,\n }\n}\n\nconst useStyles = makeStyles()({\n inputContainer: {\n marginBottom: 30,\n },\n fileContainer: {\n maxWidth: 500,\n },\n msaInput: {\n marginBottom: 20,\n },\n})\n\nconst ManualMSALoader = observer(function PreLoadedMSA2({\n model,\n feature,\n handleClose,\n preferredTranscriptId,\n}: {\n model: AbstractTrackModel\n feature: Feature\n handleClose: () => void\n /** the isoform the user right-clicked, preselected in the picker */\n preferredTranscriptId?: string\n}) {\n const view = getLinearGenomeView(model)\n const { classes } = useStyles()\n const { launchError, submit } = useLaunchSubmit(handleClose)\n const [inputMethod, setInputMethod] = useState<'file' | 'text'>('file')\n const [msaText, setMsaText] = useState('')\n const [treeText, setTreeText] = useState('')\n const [msaFileLocation, setMsaFileLocation] = useState<FileLocation>()\n const [treeFileLocation, setTreeFileLocation] = useState<FileLocation>()\n const transcriptSelection = useTranscriptSelection({\n feature,\n view,\n preferredTranscriptId,\n })\n const { selectedTranscript, proteinSequence, error, sequenceStatus } =\n transcriptSelection\n const msaFile = useMsaFileText(\n inputMethod === 'file' ? msaFileLocation : undefined,\n )\n const queryRow = useQueryRowName(\n inputMethod === 'file' ? msaFile.text : msaText,\n proteinSequence,\n )\n\n const e = launchError ?? error ?? msaFile.error\n return (\n <>\n <LaunchPanelContent error={e}>\n <FormControl component=\"fieldset\">\n <RadioGroup\n row\n value={inputMethod}\n onChange={event => {\n setInputMethod(event.target.value as 'file' | 'text')\n }}\n >\n <FormControlLabel\n value=\"file\"\n control={<Radio />}\n label=\"Open files\"\n />\n <FormControlLabel\n value=\"text\"\n control={<Radio />}\n label=\"Paste text\"\n />\n </RadioGroup>\n </FormControl>\n\n <div className={classes.inputContainer}>\n {inputMethod === 'file' ? (\n <div className={classes.fileContainer}>\n <FileSelector\n name=\"MSA File .aln (Clustal), .fa/.mfa (aligned FASTA), .stock (Stockholm), etc)\"\n inline\n location={msaFileLocation}\n setLocation={setMsaFileLocation}\n />\n <FileSelector\n name=\"Tree file .nh (Newick) or .asn (NCBI COBALT ASN.1)\"\n inline\n location={treeFileLocation}\n setLocation={setTreeFileLocation}\n />\n </div>\n ) : (\n <>\n <TextField2\n variant=\"outlined\"\n name=\"MSA\"\n multiline\n minRows={5}\n className={classes.msaInput}\n maxRows={10}\n fullWidth\n placeholder=\"Paste MSA here\"\n value={msaText}\n onChange={event => {\n setMsaText(event.target.value)\n }}\n />\n <TextField2\n variant=\"outlined\"\n name=\"Tree\"\n multiline\n minRows={5}\n maxRows={10}\n fullWidth\n placeholder=\"Paste newick tree (optional)\"\n value={treeText}\n onChange={event => {\n setTreeText(event.target.value)\n }}\n />\n </>\n )}\n </div>\n\n <TranscriptSelector feature={feature} {...transcriptSelection} />\n\n <QueryRowSelector {...queryRow} />\n </LaunchPanelContent>\n\n <SubmitCancelActions\n model={model}\n hint={<SequenceStatusMessage status={sequenceStatus} />}\n submitDisabled={\n !selectedTranscript ||\n (inputMethod === 'file' && (!msaFileLocation || msaFile.isLoading)) ||\n (inputMethod === 'text' && !msaText.trim())\n }\n onSubmit={placement => {\n if (selectedTranscript) {\n submit(() =>\n launchConnectedView({\n view,\n feature: selectedTranscript,\n placement,\n displayName: getGeneDisplayName(selectedTranscript),\n querySeqName: queryRow.querySeqName,\n querySeqOffset: queryRow.querySeqOffset,\n ...(inputMethod === 'file'\n ? {\n msaFilehandle: msaFileLocation,\n treeFilehandle: treeFileLocation,\n }\n : { data: { msa: msaText, tree: treeText } }),\n }),\n )\n }\n }}\n onCancel={handleClose}\n />\n </>\n )\n})\n\nexport default ManualMSALoader\n", "import React, { useMemo, useState } from 'react'\n\nimport { Typography } from '@mui/material'\nimport { observer } from 'mobx-react'\nimport { makeStyles } from 'tss-react/mui'\n\nimport TextField2 from '../../../components/TextField2'\nimport { defaultMaxSpecies } from '../../../utils/ncbiOrthologs'\nimport {\n getGeneDisplayName,\n getGeneIdentifiers,\n getLinearGenomeView,\n getTranscriptDisplayName,\n} from '../../util'\nimport MsaAlgorithmSelect from '../BlastQuery/MsaAlgorithmSelect'\nimport { useStoredMsaAlgorithm } from '../BlastQuery/searchChoiceStorage'\nimport LaunchPanelContent from '../LaunchPanelContent'\nimport SequenceStatusMessage from '../SequenceStatus'\nimport SubmitCancelActions from '../SubmitCancelActions'\nimport TranscriptSelector from '../TranscriptSelector'\nimport {\n builtAlignmentLook,\n launchConnectedView,\n useLaunchSubmit,\n} from '../launchConnectedView'\nimport { useTranscriptSelection } from '../useTranscriptSelection'\nimport OrthologSourceSelect, {\n useStoredOrthologSource,\n} from './OrthologSourceSelect'\nimport QuerySpeciesSelect from './QuerySpeciesSelect'\n\nimport type { OrthologSource } from '../../../MsaViewPanel/model'\nimport type { AbstractTrackModel, Feature } from '@jbrowse/core/util'\n\nconst useStyles = makeStyles()({\n selectField: {\n width: 180,\n },\n})\n\n// the N was literal: the helper text said \"the closest N species\" whatever the\n// box held\nconst rowsHint: Record<OrthologSource, (rows: number) => string> = {\n ncbi: rows => `the ${rows} closest species NCBI has`,\n panther: rows => `the ${rows} closest species PANTHER has`,\n uniref: rows => `${rows} rows, one per species, reviewed entries first`,\n}\n\nconst OrthologPanel = observer(function ({\n handleClose,\n feature,\n model,\n preferredTranscriptId,\n}: {\n model: AbstractTrackModel\n feature: Feature\n handleClose: () => void\n /** the isoform the user right-clicked, preselected in the picker */\n preferredTranscriptId?: string\n}) {\n const { classes } = useStyles()\n const view = getLinearGenomeView(model)\n const { launchError, submit } = useLaunchSubmit(handleClose)\n const [taxId, setTaxId] = useState(9606)\n const [source, setSource] = useStoredOrthologSource()\n const [msaAlgorithm, setMsaAlgorithm] = useStoredMsaAlgorithm()\n const [maxSpecies, setMaxSpecies] = useState(String(defaultMaxSpecies))\n\n const geneCandidates = useMemo(() => getGeneIdentifiers(feature), [feature])\n const transcriptSelection = useTranscriptSelection({\n feature,\n view,\n preferredTranscriptId,\n })\n const { selectedTranscript, proteinSequence, sequenceStatus } =\n transcriptSelection\n const e = transcriptSelection.error ?? launchError\n\n const rowCount = Number(maxSpecies)\n const rowCountValid = Number.isInteger(rowCount) && rowCount >= 2\n\n return (\n <>\n <LaunchPanelContent error={e}>\n {/* One line rather than seven. What a reader needs here is which tab to\n pick; the rest (species labels, CDD overlay, the query row being the\n selected transcript) is visible in the result or documented, and as\n prose it was most of the dialog's height.\n\n The comparison stays but the number moved: the lookup is still\n instant, and it is now the aligner that costs the wait, about half a\n second per row. */}\n <Typography variant=\"body2\">\n Precomputed orthologs, one gene per species, looked up rather than\n searched for. No BLAST job to queue, and with the in-browser aligner\n no job at all.\n </Typography>\n\n <div>\n <OrthologSourceSelect\n className={classes.selectField}\n value={source}\n onChange={setSource}\n />\n\n <QuerySpeciesSelect\n className={classes.selectField}\n value={taxId}\n assemblyName={view.assemblyNames[0]}\n onChange={setTaxId}\n />\n\n <MsaAlgorithmSelect\n className={classes.selectField}\n value={msaAlgorithm}\n onChange={setMsaAlgorithm}\n />\n\n <TextField2\n variant=\"outlined\"\n label=\"Rows to align\"\n className={classes.selectField}\n type=\"number\"\n value={maxSpecies}\n onChange={event => {\n setMaxSpecies(event.target.value)\n }}\n error={!rowCountValid}\n helperText={\n rowCountValid\n ? rowsHint[source](rowCount)\n : 'a whole number, 2 or more'\n }\n />\n </div>\n\n <TranscriptSelector feature={feature} {...transcriptSelection} />\n </LaunchPanelContent>\n <SubmitCancelActions\n model={model}\n hint={<SequenceStatusMessage status={sequenceStatus} />}\n submitDisabled={!proteinSequence || !rowCountValid}\n onSubmit={placement => {\n if (selectedTranscript) {\n submit(() =>\n launchConnectedView({\n view,\n feature: selectedTranscript,\n placement,\n displayName: `Orthologs - ${getGeneDisplayName(feature)} - ${getTranscriptDisplayName(selectedTranscript)}`,\n ...builtAlignmentLook,\n orthologParams: {\n taxId,\n source,\n maxSpecies: rowCount,\n geneCandidates,\n msaAlgorithm,\n selectedTranscript: selectedTranscript.toJSON(),\n proteinSequence,\n },\n }),\n )\n }\n }}\n onCancel={handleClose}\n />\n </>\n )\n})\n\nexport default OrthologPanel\n", "import React from 'react'\n\nimport { MenuItem } from '@mui/material'\n\nimport TextField2 from '../../../components/TextField2'\nimport { useLocalStorage } from '../../../utils/useLocalStorage'\n\nimport type { OrthologSource } from '../../../MsaViewPanel/model'\n\nconst ORTHOLOG_SOURCE_STORAGE_KEY = 'msaview-ortholog-source'\n\nconst orthologSourceLabels: Record<OrthologSource, string> = {\n ncbi: 'NCBI orthologs',\n panther: 'PANTHER',\n uniref: 'UniRef cluster',\n}\n\nconst orthologSources = Object.keys(orthologSourceLabels) as OrthologSource[]\n\n// another plugin version on the same origin may have stored a source this one\n// lacks, and the tab indexes its hints by it\nexport function validOrthologSource(stored: unknown): OrthologSource {\n return orthologSources.find(s => s === stored) ?? 'ncbi'\n}\n\nexport function useStoredOrthologSource() {\n const [stored, setStored] = useLocalStorage<unknown>(\n ORTHOLOG_SOURCE_STORAGE_KEY,\n 'ncbi',\n )\n return [\n validOrthologSource(stored),\n (source: OrthologSource) => {\n setStored(source)\n },\n ] as const\n}\n\n// Which species a source can answer for, in the words a reader picking one\n// needs: NCBI's ortholog sets stop at vertebrates and insects, PANTHER's run\n// from human to yeast and Arabidopsis, and a UniRef cluster is every UniProtKB\n// entry within 50% identity of the query, whatever it came from.\nconst hints: Record<OrthologSource, string> = {\n ncbi: 'vertebrates and insects',\n panther: 'also yeast, worm, fly and plants',\n uniref: 'all of UniProtKB within 50% identity',\n}\n\nexport default function OrthologSourceSelect({\n value,\n onChange,\n className,\n}: {\n value: OrthologSource\n onChange: (val: OrthologSource) => void\n className?: string\n}) {\n return (\n <TextField2\n variant=\"outlined\"\n label=\"Source\"\n className={className}\n select\n value={value}\n helperText={hints[value]}\n onChange={event => {\n onChange(event.target.value as OrthologSource)\n }}\n >\n {orthologSources.map(val => (\n <MenuItem value={val} key={val}>\n {orthologSourceLabels[val]}\n </MenuItem>\n ))}\n </TextField2>\n )\n}\n", "import React, { useState } from 'react'\n\nimport TextField2 from '../../../components/TextField2'\nimport {\n resolveAssemblySpecies,\n resolveTaxId,\n} from '../../../utils/ncbiTaxonomy'\nimport { fetchTaxonomyInfo } from '../../../utils/taxonomyNames'\nimport { useDebounced, useFetch } from '../../../utils/useFetch'\n\nasync function describeTaxon(query: string, signal: AbortSignal) {\n const taxId = await resolveTaxId(query, signal)\n if (!taxId) {\n throw new Error(`No NCBI taxon matches \"${query}\"`)\n }\n const failures: unknown[] = []\n const info = (\n await fetchTaxonomyInfo([taxId], signal, e => {\n failures.push(e)\n })\n ).get(taxId)\n // a throttle would otherwise read as a taxon NCBI has no name for\n if (!info && failures.length > 0) {\n throw new Error(`NCBI did not answer for the name of taxon ${taxId}`, {\n cause: failures[0],\n })\n }\n const label = [info?.sciname, info?.commonName && `(${info.commonName})`]\n .filter(Boolean)\n .join(' ')\n return { taxId, label: label || `taxon ${taxId}` }\n}\n\n/**\n * The species the query gene came from, as free text resolved against NCBI's\n * taxonomy rather than picked from a fixed list.\n *\n * The resolved taxon is shown back as helper text, which is the whole point of\n * resolving on a debounce instead of on submit: a typo resolves to some other\n * organism rather than to nothing, and the only place that surfaces is the gene\n * lookup, as \"could not resolve NLRP1 in taxon 9986\".\n */\nexport default function QuerySpeciesSelect({\n value,\n assemblyName,\n onChange,\n className,\n}: {\n value: number\n assemblyName?: string\n onChange: (taxId: number) => void\n className?: string\n}) {\n // undefined until the user types, which is what makes the two lookups\n // exclusive rather than both firing on open\n const [typed, setTyped] = useState<string>()\n const debounced = useDebounced(typed, 400)\n\n // Opening on `human` for everyone is the same silent wrong answer the fixed\n // species list gave: on a mouse assembly the gene symbol resolves to the HUMAN\n // gene, and the excluded taxon is human too, so mouse appears twice. The\n // assembly being browsed is the one thing here that already knows the answer.\n //\n // db=assembly already returns the taxon id, so this is the whole lookup \u2014 the\n // taxonomy chain below would be two more requests for an answer we hold. That\n // is not just waste: eutils allows 3 requests a second and throttles by\n // answering without CORS headers, so all four fired on open and the browser\n // reported the throttle as \"blocked by CORS policy\" in the helper text.\n const { data: fromAssembly } = useFetch(\n assemblyName && typed === undefined\n ? [assemblyName, 'assembly-species']\n : null,\n signal => resolveAssemblySpecies(assemblyName!, signal),\n {\n onSuccess: found => {\n if (found) {\n onChange(found.taxId)\n }\n },\n },\n )\n\n const { data: fromText, error } = useFetch(\n debounced?.trim() ? [debounced.trim(), 'taxon'] : null,\n signal => describeTaxon(debounced!, signal),\n {\n onSuccess: ({ taxId }) => {\n onChange(taxId)\n },\n },\n )\n\n // derived, not seeded through an effect: whatever the user typed wins, and\n // until they type anything the assembly's species does, so a lookup that\n // lands while they are mid-word cannot overwrite the field\n const text = typed ?? fromAssembly?.speciesName ?? 'human'\n const resolved =\n typed === undefined ? fromAssembly?.speciesName : fromText?.label\n\n return (\n <TextField2\n variant=\"outlined\"\n label=\"Query species\"\n className={className}\n value={text}\n onChange={event => {\n setTyped(event.target.value)\n }}\n error={!!error}\n helperText={\n error\n ? `${error}`\n : (resolved ?? `the species this gene is from (taxon ${value})`)\n }\n />\n )\n}\n", "import { eutilsJson, eutilsUrl } from './eutils'\n\n/**\n * Free text -> NCBI taxon id. A bare number is taken as the id itself; anything\n * else is searched against db=taxonomy, which resolves a scientific name\n * (`Danio rerio`), a common name (`zebrafish`) and a genus alike.\n *\n * This replaces a fixed list of species the dialog used to offer. The query\n * taxon has to match the assembly the user is browsing -- `resolveGeneId`\n * searches `SYMBOL[Gene Name] AND <taxid>[taxid]` -- so a list that stops at 23\n * species silently resolves the wrong organism's gene for anyone outside it.\n */\nexport async function resolveTaxId(query: string, signal?: AbortSignal) {\n const term = query.trim()\n if (!term) {\n return undefined\n }\n if (/^\\d+$/.test(term)) {\n return Number(term)\n }\n const json = await eutilsJson<{ esearchresult?: { idlist?: string[] } }>(\n eutilsUrl('esearch', {\n db: 'taxonomy',\n term,\n retmax: '1',\n retmode: 'json',\n }),\n { signal },\n )\n const id = json.esearchresult?.idlist?.[0]\n return id ? Number(id) : undefined\n}\n\ninterface AssemblySummary {\n result?: Record<string, { speciestaxid?: string; speciesname?: string }>\n}\n\n/**\n * A JBrowse assembly name -> the species it is an assembly of.\n *\n * The dialog's query species used to open on `human` whoever was browsing, and\n * that is the same silent wrong answer the 23-species list gave: `resolveGeneId`\n * searches `SYMBOL[Gene Name] AND <taxid>[taxid]`, so a user right-clicking a\n * mouse gene got the HUMAN gene of that symbol, its orthologs, and mouse twice\n * \u2014 once as the query row and once as an ortholog, because the excluded taxon\n * was the wrong one. A symbol with no human counterpart failed outright.\n *\n * db=assembly indexes the names JBrowse configs actually carry: hg38, GRCh38,\n * mm39, danRer11, dm6 and sacCer3 all resolve, and so do RefSeq/GenBank\n * accessions. An assembly NCBI has never heard of resolves to nothing and the\n * caller keeps its own default, so this can only improve on guessing.\n */\nexport async function resolveAssemblySpecies(\n assemblyName: string,\n signal?: AbortSignal,\n) {\n const term = assemblyName.trim()\n if (!term) {\n return undefined\n }\n const search = await eutilsJson<{ esearchresult?: { idlist?: string[] } }>(\n eutilsUrl('esearch', {\n db: 'assembly',\n term,\n retmax: '1',\n retmode: 'json',\n }),\n { signal },\n )\n const uid = search.esearchresult?.idlist?.[0]\n if (!uid) {\n return undefined\n }\n const summary = await eutilsJson<AssemblySummary>(\n eutilsUrl('esummary', { db: 'assembly', id: uid, retmode: 'json' }),\n { signal },\n )\n const record = summary.result?.[uid]\n const taxId = Number(record?.speciestaxid)\n return record?.speciesname && taxId\n ? { taxId, speciesName: record.speciesname }\n : undefined\n}\n", "import React, { useMemo, useState } from 'react'\n\nimport { LoadingEllipses, SanitizedHTML } from '@jbrowse/core/ui'\nimport { getEnv, getSession } from '@jbrowse/core/util'\nimport { MenuItem, Typography } from '@mui/material'\nimport { observer } from 'mobx-react'\nimport { makeStyles } from 'tss-react/mui'\n\nimport TextField2 from '../../../components/TextField2'\nimport { useFetch } from '../../../utils/useFetch'\nimport { resolveQueryRowName, useQueryRowName } from '../../useQueryRowName'\nimport {\n featureMatchesId,\n getGeneDisplayName,\n getLinearGenomeView,\n getTranscriptDisplayName,\n} from '../../util'\nimport LaunchPanelContent from '../LaunchPanelContent'\nimport QueryRowSelector from '../QueryRowSelector'\nimport SequenceStatusMessage from '../SequenceStatus'\nimport SubmitCancelActions from '../SubmitCancelActions'\nimport TranscriptSelector from '../TranscriptSelector'\nimport { launchConnectedView, useLaunchSubmit } from '../launchConnectedView'\nimport { useTranscriptSelection } from '../useTranscriptSelection'\nimport { fetchMSA, fetchMSAList } from './fetchMSAData'\nimport { readMsaDatasets } from './types'\n\nimport type { AbstractTrackModel, Feature } from '@jbrowse/core/util'\n\nconst useStyles = makeStyles()({\n selectedContainer: {\n marginTop: 50,\n },\n})\n\nconst PreLoadedMSA = observer(function ({\n model,\n feature,\n handleClose,\n preferredTranscriptId,\n}: {\n model: AbstractTrackModel\n feature: Feature\n handleClose: () => void\n /** the isoform the user right-clicked, preselected in the picker */\n preferredTranscriptId?: string\n}) {\n const session = getSession(model)\n const view = getLinearGenomeView(model)\n const { classes } = useStyles()\n const { pluginManager } = getEnv(model)\n const { assemblyNames } = view\n const { launchError, submit } = useLaunchSubmit(handleClose)\n\n const datasets = readMsaDatasets(session.jbrowse)\n const [selectedDatasetId, setSelectedDatasetId] = useState(\n datasets?.[0]?.datasetId,\n )\n const selectedDataset = datasets?.find(d => d.datasetId === selectedDatasetId)\n const {\n data: msaList,\n isLoading: msaListLoading,\n error: msaListFetchError,\n } = useFetch(\n selectedDataset ? `${selectedDataset.datasetId}-msa-list` : null,\n () => fetchMSAList({ config: selectedDataset!.adapter, pluginManager }),\n )\n\n const transcriptSelection = useTranscriptSelection({\n feature,\n view,\n validIds: msaList,\n preferredTranscriptId,\n })\n const { selectedTranscript, proteinSequence, sequenceStatus } =\n transcriptSelection\n\n // the dataset's name for this transcript, which a track is free not to use\n // as the feature's own id\n const msaId = selectedTranscript\n ? msaList?.find(id => featureMatchesId(selectedTranscript, id))\n : undefined\n const {\n data: msaData,\n isLoading: msaDataLoading,\n error: msaDataFetchError,\n } = useFetch(\n msaId && selectedDataset\n ? `${selectedDataset.datasetId}-${msaId}-msa`\n : null,\n () =>\n fetchMSA({\n msaId: msaId!,\n config: selectedDataset!.adapter,\n pluginManager,\n }),\n )\n\n const msaText = useMemo(\n () =>\n msaData?.map(r => `>${r.get('refName')}\\n${r.get('seq')}`).join('\\n') ??\n '',\n [msaData],\n )\n\n // The dataset's row for this transcript used to be assumed -- the launch\n // named `<transcriptId>_<assembly>` and hoped the file agreed. Nothing\n // checked, and a name the alignment does not carry fails silently: the view\n // opens, renders, and never navigates. The row is found by sequence instead,\n // the same way the Manual tab finds it.\n const queryRow = useQueryRowName(msaText, proteinSequence)\n\n // The name this panel used to launch with unconditionally. A dataset built to\n // that convention does carry the row, so it is worth falling back to when the\n // residues do not match closely enough to find it -- but only when the\n // alignment really has it, which is the check the old code never made.\n const querySeqName = resolveQueryRowName(\n queryRow,\n `${msaId ?? ''}_${assemblyNames[0] ?? ''}`,\n )\n\n const e =\n msaListFetchError ??\n msaDataFetchError ??\n transcriptSelection.error ??\n launchError\n return (\n <>\n <LaunchPanelContent error={e}>\n <TextField2\n select\n label=\"Select MSA dataset\"\n value={selectedDatasetId}\n onChange={event => {\n setSelectedDatasetId(event.target.value)\n }}\n >\n {datasets?.map(d => (\n <MenuItem key={d.datasetId} value={d.datasetId}>\n {d.name}\n </MenuItem>\n ))}\n </TextField2>\n\n {selectedDataset ? (\n <div className={classes.selectedContainer}>\n {!msaListLoading && msaDataLoading ? (\n <LoadingEllipses\n variant=\"h6\"\n message={`Loading MSA for ${getTranscriptDisplayName(selectedTranscript) || msaId}`}\n />\n ) : null}\n {msaListLoading ? (\n <LoadingEllipses\n variant=\"h6\"\n message={`Loading available MSAs for (${selectedDataset.name})`}\n />\n ) : null}\n\n {msaList ? (\n <div>\n <SanitizedHTML html={selectedDataset.description} />\n <TranscriptSelector\n feature={feature}\n {...transcriptSelection}\n />\n {msaText ? (\n <QueryRowSelector {...queryRow} querySeqName={querySeqName} />\n ) : null}\n </div>\n ) : null}\n </div>\n ) : null}\n </LaunchPanelContent>\n\n <SubmitCancelActions\n model={model}\n hint={\n msaDataLoading ? (\n <LoadingEllipses message=\"Loading alignment\" />\n ) : !!msaData?.length && !querySeqName ? (\n <Typography color=\"textSecondary\" variant=\"body2\">\n no row matches this transcript\n </Typography>\n ) : (\n <SequenceStatusMessage status={sequenceStatus} />\n )\n }\n // launching without a query row opens a view that renders and then\n // never navigates, which reads as a broken feature rather than a\n // dataset that does not cover this gene\n submitDisabled={\n !selectedTranscript || !msaData?.length || !querySeqName\n }\n onSubmit={placement => {\n if (selectedTranscript && msaText) {\n submit(() =>\n launchConnectedView({\n view,\n feature: selectedTranscript,\n placement,\n displayName: getGeneDisplayName(selectedTranscript),\n treeAreaWidth: 200,\n treeWidth: 100,\n drawNodeBubbles: false,\n labelsAlignRight: true,\n showBranchLen: false,\n colWidth: 10,\n rowHeight: 12,\n colorSchemeName: 'percent_identity_dynamic',\n querySeqName,\n querySeqOffset: queryRow.querySeqOffset,\n data: { msa: msaText },\n }),\n )\n }\n }}\n onCancel={handleClose}\n />\n </>\n )\n})\n\nexport default PreLoadedMSA\n", "import { getAdapter } from '@jbrowse/core/data_adapters/dataAdapterCache'\n\nimport type PluginManager from '@jbrowse/core/PluginManager'\nimport type { AnyConfigurationModel } from '@jbrowse/core/configuration'\nimport type { Feature } from '@jbrowse/core/util'\n\ninterface MsaDataAdapter {\n getMSAList(): Promise<string[]>\n getMSA(msaId: string): Promise<Feature[]>\n}\n\nasync function getMsaAdapter(\n pluginManager: PluginManager,\n config: AnyConfigurationModel,\n) {\n const result = await getAdapter(pluginManager, 'msa', config)\n return result.dataAdapter as unknown as MsaDataAdapter\n}\n\nexport async function fetchMSAList({\n config,\n pluginManager,\n}: {\n config: AnyConfigurationModel\n pluginManager: PluginManager\n}): Promise<string[]> {\n const adapter = await getMsaAdapter(pluginManager, config)\n return adapter.getMSAList()\n}\n\nexport async function fetchMSA({\n config,\n pluginManager,\n msaId,\n}: {\n config: AnyConfigurationModel\n pluginManager: PluginManager\n msaId: string\n}): Promise<Feature[]> {\n const adapter = await getMsaAdapter(pluginManager, config)\n return adapter.getMSA(msaId)\n}\n", "import { readConfObject } from '@jbrowse/core/configuration'\n\nimport type { AnyConfigurationModel } from '@jbrowse/core/configuration'\n\nexport interface Dataset {\n datasetId: string\n name: string\n description?: string\n adapter: AnyConfigurationModel\n}\n\nexport function readMsaDatasets(jbrowse: AnyConfigurationModel) {\n return readConfObject(jbrowse, ['msa', 'datasets']) as Dataset[] | undefined\n}\n", "import React, { useState } from 'react'\n\n// Once visited, a panel stays mounted and is hidden with the `hidden` attribute.\n// Unmounting it discarded whatever the user had typed and re-ran every fetch the\n// panel makes on the way back, so switching tabs to compare two of them cost an\n// EBI round trip and the pasted alignment.\n//\n// Lazy on first visit rather than mounted up front, because a panel mounts\n// fetches of its own: rendering all four on open would query the MSA dataset\n// adapter and the BLAST cache for tabs nobody looked at.\nexport default function TabPanel({\n children,\n value,\n index,\n}: {\n children?: React.ReactNode\n index: number | string\n value: number | string\n}) {\n const active = value === index\n const [visited, setVisited] = useState(active)\n if (active && !visited) {\n setVisited(true)\n }\n return (\n <div role=\"tabpanel\" hidden={!active}>\n {visited || active ? children : null}\n </div>\n )\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["module.exports = JBrowseExports[\"@jbrowse/core/data_adapters/dataAdapterCache\"];", "import React, { useState } from 'react'\n\nimport { Dialog } from '@jbrowse/core/ui'\nimport { getSession } from '@jbrowse/core/util'\nimport { Tab, Tabs } from '@mui/material'\n\nimport BlastPanel from './BlastQuery/BlastPanel'\nimport HelpButton from './HelpButton'\nimport ManualMSALoader from './ManualMSALoader/ManualMSALoader'\nimport OrthologPanel from './OrthologQuery/OrthologPanel'\nimport PreLoadedMSA from './PreLoadedMSA/PreLoadedMSADataPanel'\nimport { readMsaDatasets } from './PreLoadedMSA/types'\nimport TabPanel from './TabPanel'\nimport { LaunchPlacementProvider } from './launchPlacement'\n\nimport type { AbstractTrackModel, Feature } from '@jbrowse/core/util'\n\nexport default function LaunchMsaViewDialog({\n handleClose,\n feature,\n model,\n preferredTranscriptId,\n}: {\n handleClose: () => void\n feature: Feature\n model: AbstractTrackModel\n /** the isoform the right-click landed on, when this opened on its gene */\n preferredTranscriptId?: string\n}) {\n const session = getSession(model)\n const datasets = readMsaDatasets(session.jbrowse)\n const hasPreloadedDatasets = !!datasets?.length\n\n // orthologs first, and the default: it answers the same question in ~10s\n // that BLAST takes 10+ minutes to answer worse (see utils/ncbiOrthologs.ts)\n const [value, setValue] = useState<\n 'orthologs' | 'ncbi_blast' | 'preloaded_msa' | 'manual_msa'\n >('orthologs')\n\n return (\n <Dialog maxWidth=\"xl\" title=\"Launch MSA view\" open onClose={handleClose}>\n {/* one placement answer for every tab: they all stay mounted once\n visited, so a per-panel one is a per-tab one */}\n <LaunchPlacementProvider>\n <div style={{ display: 'flex', alignItems: 'center' }}>\n <Tabs\n value={value}\n onChange={(_event, newValue) => {\n setValue(newValue)\n }}\n >\n <Tab label=\"Orthologs\" value=\"orthologs\" />\n {/* the tab value stays 'ncbi_blast' \u2014 it is only local state, and\n renaming it buys nothing */}\n <Tab label=\"BLAST query\" value=\"ncbi_blast\" />\n {hasPreloadedDatasets ? (\n <Tab label=\"Pre-loaded MSA datasets\" value=\"preloaded_msa\" />\n ) : null}\n <Tab label=\"Manual upload\" value=\"manual_msa\" />\n </Tabs>\n <HelpButton />\n </div>\n <TabPanel value={value} index=\"orthologs\">\n <OrthologPanel\n handleClose={handleClose}\n feature={feature}\n model={model}\n preferredTranscriptId={preferredTranscriptId}\n />\n </TabPanel>\n <TabPanel value={value} index=\"ncbi_blast\">\n <BlastPanel\n handleClose={handleClose}\n feature={feature}\n model={model}\n preferredTranscriptId={preferredTranscriptId}\n />\n </TabPanel>\n {hasPreloadedDatasets ? (\n <TabPanel value={value} index=\"preloaded_msa\">\n <PreLoadedMSA\n model={model}\n feature={feature}\n handleClose={handleClose}\n preferredTranscriptId={preferredTranscriptId}\n />\n </TabPanel>\n ) : null}\n <TabPanel value={value} index=\"manual_msa\">\n <ManualMSALoader\n model={model}\n feature={feature}\n handleClose={handleClose}\n preferredTranscriptId={preferredTranscriptId}\n />\n </TabPanel>\n </LaunchPlacementProvider>\n </Dialog>\n )\n}\n", "import React, { useState } from 'react'\n\nimport SettingsIcon from '@mui/icons-material/Settings'\nimport { IconButton, Tooltip } from '@mui/material'\nimport { makeStyles } from 'tss-react/mui'\n\nimport {\n DEFAULT_EBI_EMAIL,\n EBI_EMAIL_STORAGE_KEY,\n} from '../../../utils/ebiJobDispatcher'\nimport { useLocalStorage } from '../../../utils/useLocalStorage'\nimport BlastAutomaticPanel from './BlastAutomaticPanel'\nimport BlastManualPanel from './BlastManualPanel'\nimport BlastMethodSelector from './BlastMethodSelector'\nimport BlastSettingsDialog from './BlastSettingsDialog'\n\nimport type { AbstractTrackModel, Feature } from '@jbrowse/core/util'\n\nconst useStyles = makeStyles()({\n settingsButton: {\n float: 'right',\n },\n})\n\nconst panelMap = {\n automatic: BlastAutomaticPanel,\n manual: BlastManualPanel,\n} as const\n\nexport type BlastLookupMethod = keyof typeof panelMap\n\nexport default function BlastPanel({\n handleClose,\n model,\n feature,\n preferredTranscriptId,\n}: {\n handleClose: () => void\n model: AbstractTrackModel\n feature: Feature\n /** the isoform the user right-clicked, preselected in the picker */\n preferredTranscriptId?: string\n}) {\n const [lookupMethod, setLookupMethod] =\n useState<BlastLookupMethod>('automatic')\n const [ebiEmail, setEbiEmail] = useLocalStorage(\n EBI_EMAIL_STORAGE_KEY,\n DEFAULT_EBI_EMAIL,\n )\n const [settingsOpen, setSettingsOpen] = useState(false)\n const { classes } = useStyles()\n\n const Panel = panelMap[lookupMethod]\n\n return (\n <>\n {/* a bare gear said nothing about what it opened, and the address the\n job carries was invisible until you opened it */}\n <Tooltip\n title={`EBI settings \u2014 jobs are submitted with ${ebiEmail.trim() || DEFAULT_EBI_EMAIL}`}\n >\n <IconButton\n className={classes.settingsButton}\n aria-label=\"EBI settings\"\n size=\"small\"\n onClick={() => {\n setSettingsOpen(true)\n }}\n >\n <SettingsIcon />\n </IconButton>\n </Tooltip>\n\n <Panel\n model={model}\n feature={feature}\n handleClose={handleClose}\n preferredTranscriptId={preferredTranscriptId}\n >\n <BlastMethodSelector\n lookupMethod={lookupMethod}\n setLookupMethod={setLookupMethod}\n />\n </Panel>\n\n {settingsOpen ? (\n <BlastSettingsDialog\n ebiEmail={ebiEmail}\n handleClose={settings => {\n if (settings) {\n setEbiEmail(settings.ebiEmail)\n }\n setSettingsOpen(false)\n }}\n />\n ) : null}\n </>\n )\n}\n", "\"use client\";\n\nimport createSvgIcon from \"./utils/createSvgIcon.mjs\";\nimport { jsx as _jsx } from \"react/jsx-runtime\";\nexport default createSvgIcon(/*#__PURE__*/_jsx(\"path\", {\n d: \"M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.07.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6\"\n}), 'Settings');", "import React, { useMemo, useState } from 'react'\n\nimport ExpandMoreIcon from '@mui/icons-material/ExpandMore'\nimport {\n Accordion,\n AccordionDetails,\n AccordionSummary,\n MenuItem,\n Typography,\n} from '@mui/material'\nimport { observer } from 'mobx-react'\nimport { makeStyles } from 'tss-react/mui'\n\nimport TextField2 from '../../../components/TextField2'\nimport {\n getBlastViewTitle,\n getGeneIdentifiers,\n getLinearGenomeView,\n} from '../../util'\nimport LaunchPanelContent from '../LaunchPanelContent'\nimport SequenceStatusMessage from '../SequenceStatus'\nimport SubmitCancelActions from '../SubmitCancelActions'\nimport TranscriptSelector from '../TranscriptSelector'\nimport {\n builtAlignmentLook,\n launchConnectedView,\n useLaunchSubmit,\n} from '../launchConnectedView'\nimport { useTranscriptSelection } from '../useTranscriptSelection'\nimport CachedBlastResults from './CachedBlastResults'\nimport MsaAlgorithmSelect from './MsaAlgorithmSelect'\nimport {\n databaseLabel,\n databaseOptionsFor,\n defaultMaxHits,\n defaultSearchFor,\n searchProgramLabels,\n searchPrograms,\n} from './consts'\nimport {\n useStoredMsaAlgorithm,\n useStoredSearchChoice,\n} from './searchChoiceStorage'\nimport { useCachedBlastResults } from './useCachedBlastResults'\n\nimport type { BlastParams } from '../../../MsaViewPanel/model'\nimport type { SearchChoice, SearchProgram } from './consts'\nimport type { AbstractTrackModel, Feature } from '@jbrowse/core/util'\n\nconst useStyles = makeStyles()({\n selectField: {\n width: 150,\n },\n // wider than the rest because the collection names are what the user came to\n // read, and truncating them does not distinguish Swiss-Prot from TrEMBL\n databaseField: {\n width: 260,\n },\n cachedResultsAccordion: {\n marginTop: 20,\n },\n infoText: {\n marginTop: 20,\n },\n})\n\nconst BlastAutomaticPanel = observer(function ({\n handleClose,\n feature,\n model,\n children,\n preferredTranscriptId,\n}: {\n model: AbstractTrackModel\n feature: Feature\n handleClose: () => void\n children: React.ReactNode\n /** the isoform the user right-clicked, preselected in the picker */\n preferredTranscriptId?: string\n}) {\n const { classes } = useStyles()\n const view = getLinearGenomeView(model)\n const { launchError, submit } = useLaunchSubmit(handleClose)\n // one piece of state, not two: a program and a database that program does not\n // have is a 400 from EBI minutes after Submit, and holding them apart is what\n // would let them drift into that\n const [search, setSearch] = useStoredSearchChoice()\n const [selectedMsaAlgorithm, setSelectedMsaAlgorithm] =\n useStoredMsaAlgorithm()\n const [maxHits, setMaxHits] = useState(String(defaultMaxHits))\n const hitCount = Number(maxHits)\n const hitCountValid = Number.isInteger(hitCount) && hitCount >= 1\n const isPhmmer = search.program === 'phmmer'\n\n const geneIds = useMemo(() => getGeneIdentifiers(feature), [feature])\n const cached = useCachedBlastResults(geneIds)\n\n const transcriptSelection = useTranscriptSelection({\n feature,\n view,\n preferredTranscriptId,\n })\n const { selectedTranscript, proteinSequence, sequenceStatus } =\n transcriptSelection\n const e = transcriptSelection.error ?? launchError ?? cached.error\n return (\n <>\n <LaunchPanelContent error={e}>\n {children}\n <TextField2\n variant=\"outlined\"\n label=\"Search program\"\n className={classes.selectField}\n select\n value={search.program}\n onChange={event => {\n // the two services name their databases differently, so switching\n // program replaces the database rather than keeping a name the new\n // one has never heard of\n setSearch(defaultSearchFor(event.target.value as SearchProgram))\n }}\n >\n {searchPrograms.map(val => (\n <MenuItem value={val} key={val}>\n {searchProgramLabels[val]}\n </MenuItem>\n ))}\n </TextField2>\n\n <TextField2\n variant=\"outlined\"\n label=\"Database\"\n className={classes.databaseField}\n select\n value={search.database}\n onChange={event => {\n setSearch({\n program: search.program,\n database: event.target.value,\n } as SearchChoice)\n }}\n >\n {databaseOptionsFor(search.program).map(val => (\n <MenuItem value={val} key={val}>\n {databaseLabel(val)}\n </MenuItem>\n ))}\n </TextField2>\n\n {isPhmmer ? null : (\n <MsaAlgorithmSelect\n className={classes.selectField}\n value={selectedMsaAlgorithm}\n onChange={setSelectedMsaAlgorithm}\n />\n )}\n\n <TextField2\n variant=\"outlined\"\n label=\"Hits\"\n className={classes.selectField}\n type=\"number\"\n value={maxHits}\n onChange={event => {\n setMaxHits(event.target.value)\n }}\n error={!hitCountValid}\n helperText=\"best-scoring sequences to keep\"\n />\n\n <TranscriptSelector feature={feature} {...transcriptSelection} />\n\n {/* one line rather than eight; the rest is behind the Help button,\n where a reader who wants it can go and find it */}\n <Typography variant=\"body2\" className={classes.infoText}>\n {isPhmmer\n ? 'phmmer aligns the hits as it finds them, so nothing is realigned afterwards.'\n : 'The hits come back from EBI and are then run through the chosen aligner.'}{' '}\n The EBI queue is the wait, and it runs from seconds to many minutes.\n </Typography>\n\n {cached.results.length > 0 ? (\n <Accordion className={classes.cachedResultsAccordion}>\n <AccordionSummary expandIcon={<ExpandMoreIcon />}>\n <Typography>Previous BLAST Results</Typography>\n </AccordionSummary>\n <AccordionDetails>\n <CachedBlastResults\n model={model}\n handleClose={handleClose}\n feature={feature}\n cached={cached}\n />\n </AccordionDetails>\n </Accordion>\n ) : null}\n </LaunchPanelContent>\n <SubmitCancelActions\n model={model}\n hint={<SequenceStatusMessage status={sequenceStatus} />}\n submitDisabled={!proteinSequence || !hitCountValid}\n onSubmit={placement => {\n if (selectedTranscript) {\n const blastParams: BlastParams =\n search.program === 'phmmer'\n ? {\n searchProgram: 'phmmer',\n blastDatabase: search.database,\n maxHits: hitCount,\n selectedTranscript: selectedTranscript.toJSON(),\n proteinSequence,\n }\n : {\n searchProgram: 'blastp',\n blastDatabase: search.database,\n msaAlgorithm: selectedMsaAlgorithm,\n maxHits: hitCount,\n selectedTranscript: selectedTranscript.toJSON(),\n proteinSequence,\n }\n submit(() =>\n launchConnectedView({\n view,\n feature: selectedTranscript,\n placement,\n displayName: getBlastViewTitle(feature, selectedTranscript),\n ...builtAlignmentLook,\n blastParams,\n }),\n )\n }\n }}\n onCancel={handleClose}\n />\n </>\n )\n})\n\nexport default BlastAutomaticPanel\n", "import React from 'react'\n\nimport { TextField } from '@mui/material'\n\nimport type { TextFieldProps } from '@mui/material'\n\nfunction TextField2({ children, ...rest }: TextFieldProps) {\n return (\n <div>\n <TextField {...rest}>{children}</TextField>\n </div>\n )\n}\n\nexport default TextField2\n", "import React from 'react'\n\nimport { ErrorMessage } from '@jbrowse/core/ui'\nimport { DialogContent } from '@mui/material'\nimport { makeStyles } from 'tss-react/mui'\n\nconst useStyles = makeStyles()({\n dialogContent: {\n width: '80em',\n },\n})\n\nexport default function LaunchPanelContent({\n error,\n children,\n}: {\n error?: unknown\n children: React.ReactNode\n}) {\n const { classes } = useStyles()\n return (\n <DialogContent className={classes.dialogContent}>\n {error ? <ErrorMessage error={error} /> : null}\n {children}\n </DialogContent>\n )\n}\n", "import React from 'react'\n\nimport { LoadingEllipses } from '@jbrowse/core/ui'\nimport { Typography } from '@mui/material'\n\nexport type SequenceStatus = 'loading' | 'ready' | 'missing' | 'error'\n\n/**\n * Why Submit is grey. The query row is the selected transcript's translation,\n * and fetching and translating it takes a round trip to the sequence adapter,\n * so the button starts disabled on every panel \u2014 with nothing to distinguish\n * \"wait a moment\" from \"this gene has no protein and never will\".\n *\n * An error says so through the panel's own ErrorMessage, so this stays quiet\n * for that one rather than saying it twice.\n */\nexport default function SequenceStatusMessage({\n status,\n}: {\n status: SequenceStatus\n}) {\n return status === 'loading' ? (\n <LoadingEllipses message=\"Translating transcript\" />\n ) : status === 'missing' ? (\n <Typography color=\"textSecondary\" variant=\"body2\">\n no coding sequence to align\n </Typography>\n ) : null\n}\n", "import React from 'react'\n\nimport { getSession } from '@jbrowse/core/util'\nimport {\n Button,\n Checkbox,\n DialogActions,\n FormControlLabel,\n} from '@mui/material'\n\nimport {\n readLaunchPlacement,\n sessionSupportsPlacement,\n writeLaunchPlacement,\n} from '../../utils/workspaces'\nimport { useLaunchPlacement } from './launchPlacement'\n\nimport type { MsaViewPlacement } from '../../utils/workspaces'\nimport type { AbstractTrackModel } from '@jbrowse/core/util'\n\n/**\n * Where the launch puts the view, offered wherever a launch is submitted.\n *\n * A checkbox rather than a menu of the three placements: the choice a reader\n * has at this point is \"beside the genome view or under it\", and `newTab` is a\n * spec's to state, not a thing to pick before you have seen the alignment.\n *\n * Absent entirely on a host that cannot tile \u2014 an embedded session, or a\n * release that places views its own way \u2014 because the box would do nothing\n * there and every launch would quietly ignore it.\n */\nfunction PlacementToggle({\n checked,\n onChange,\n}: {\n checked: boolean\n onChange: (checked: boolean) => void\n}) {\n return (\n <FormControlLabel\n label=\"Open beside the genome view\"\n control={\n <Checkbox\n checked={checked}\n onChange={event => {\n onChange(event.target.checked)\n }}\n />\n }\n />\n )\n}\n\nexport default function SubmitCancelActions({\n onSubmit,\n onCancel,\n submitDisabled,\n hint,\n submitLabel = 'Submit',\n model,\n}: {\n /** handed the placement the box states, so no launch re-reads storage */\n onSubmit: (placement: MsaViewPlacement) => void\n onCancel: () => void\n submitDisabled?: boolean\n /** why Submit is grey, shown beside it */\n hint?: React.ReactNode\n submitLabel?: string\n /** omitted by a panel that submits something other than a view launch */\n model?: AbstractTrackModel\n}) {\n const [sideBySide, setSideBySide] = useLaunchPlacement()\n // The stored value is what the next dialog opens on, so it is written on\n // submit rather than on the click: a dialog the user backed out of must not\n // move where every future launch lands.\n const offerPlacement = !!model && sessionSupportsPlacement(getSession(model))\n return (\n // The buttons are one child rather than two, so a dialog too narrow for\n // the whole row wraps them together underneath the option instead of\n // breaking Cancel away from Submit or shrinking both out of shape.\n <DialogActions sx={{ flexWrap: 'wrap', rowGap: 1 }}>\n {offerPlacement ? (\n <PlacementToggle checked={sideBySide} onChange={setSideBySide} />\n ) : null}\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n marginLeft: 'auto',\n }}\n >\n {hint}\n <Button\n sx={{ flexShrink: 0 }}\n color=\"primary\"\n variant=\"contained\"\n disabled={submitDisabled}\n onClick={() => {\n if (offerPlacement) {\n const placement = sideBySide ? 'splitRight' : 'stack'\n writeLaunchPlacement(placement)\n onSubmit(placement)\n } else {\n onSubmit(readLaunchPlacement())\n }\n }}\n >\n {submitLabel}\n </Button>\n <Button\n sx={{ flexShrink: 0 }}\n color=\"secondary\"\n variant=\"contained\"\n onClick={() => {\n onCancel()\n }}\n >\n Cancel\n </Button>\n </div>\n </DialogActions>\n )\n}\n", "import React, { createContext, useContext, useState } from 'react'\n\nimport { readLaunchPlacement } from '../../utils/workspaces'\n\ntype PlacementState = [boolean, React.Dispatch<React.SetStateAction<boolean>>]\n\n/**\n * Whether the launch opens beside the genome view \u2014 one answer for the whole\n * dialog, not one per tab.\n *\n * Every tab the user visits stays mounted, and the checkbox lives in each\n * panel's actions row, so a `useState` there gave each tab its own copy of the\n * answer: ticking the box on one tab and submitting from another wrote the\n * other tab's stale one.\n *\n * Context rather than a prop through all five panels, none of which has any\n * other business with placement.\n */\nconst LaunchPlacementContext = createContext<PlacementState | undefined>(\n undefined,\n)\n\nexport function LaunchPlacementProvider({\n children,\n}: {\n children: React.ReactNode\n}) {\n const state = useState(() => readLaunchPlacement() === 'splitRight')\n return (\n <LaunchPlacementContext.Provider value={state}>\n {children}\n </LaunchPlacementContext.Provider>\n )\n}\n\n/** the dialog's answer, or a private one for a panel rendered outside it */\nexport function useLaunchPlacement(): PlacementState {\n const shared = useContext(LaunchPlacementContext)\n const own = useState(() => readLaunchPlacement() === 'splitRight')\n return shared ?? own\n}\n", "import React, { useState } from 'react'\n\nimport { Button, MenuItem, TextField } from '@mui/material'\nimport { makeStyles } from 'tss-react/mui'\n\nimport ReadOnlyTextField2 from '../../components/ReadOnlyTextField2'\nimport {\n featureMatchesId,\n getGeneDisplayName,\n getId,\n getTranscriptDisplayName,\n getTranscriptLength,\n} from '../util'\n\nimport type { SequenceStatus } from './SequenceStatus'\nimport type { Feature } from '@jbrowse/core/util'\n\nconst useStyles = makeStyles()({\n flex: {\n display: 'flex',\n },\n minWidth: {\n minWidth: 300,\n },\n centered: {\n alignContent: 'center',\n marginLeft: 20,\n },\n})\n\nexport default function TranscriptSelector({\n feature,\n options,\n selectedId,\n selectedTranscript,\n setSelectedId,\n proteinSequence,\n sequenceStatus = 'ready',\n validIds,\n}: {\n feature: Feature\n options: Feature[]\n selectedId: string\n selectedTranscript: Feature | undefined\n setSelectedId: (transcriptId: string) => void\n proteinSequence: string | undefined\n sequenceStatus?: SequenceStatus\n validIds?: string[]\n}) {\n const { classes } = useStyles()\n const [showSequence, setShowSequence] = useState(false)\n\n return (\n <>\n <div className={classes.flex}>\n <TextField\n variant=\"outlined\"\n label={`Choose isoform of ${getGeneDisplayName(feature)}`}\n // The query row is this transcript rather than NCBI's representative\n // protein, which is what keeps the alignment linked to the genome view\n // at codon resolution. It used to be a paragraph under the panel; as\n // helper text it says the same thing where the choice is made and\n // costs no height of its own.\n helperText=\"the query row, so the alignment stays linked to the genome view\"\n select\n className={classes.minWidth}\n value={selectedId}\n onChange={event => {\n setSelectedId(event.target.value)\n }}\n >\n {options.map(val => {\n const inSet = validIds\n ? validIds.some(id => featureMatchesId(val, id))\n : true\n const { len, mod } = getTranscriptLength(val)\n return (\n <MenuItem value={getId(val)} key={val.id()} disabled={!inSet}>\n {getTranscriptDisplayName(val)} ({len} aa){' '}\n {mod ? ` (possible fragment)` : ''}\n {validIds ? (inSet ? ' (has data)' : ' (no data)') : ''}\n </MenuItem>\n )\n })}\n </TextField>\n <div className={classes.centered}>\n <Button\n variant=\"contained\"\n color=\"primary\"\n onClick={() => {\n setShowSequence(!showSequence)\n }}\n >\n {showSequence ? 'Hide sequence' : 'Show sequence'}\n </Button>\n </div>\n </div>\n\n {showSequence ? (\n <ReadOnlyTextField2\n value={\n proteinSequence\n ? `>${getTranscriptDisplayName(selectedTranscript)}\\n${proteinSequence}`\n : sequenceStatus === 'missing'\n ? 'This transcript has no coding sequence, so there is nothing to translate.'\n : sequenceStatus === 'error'\n ? 'The sequence could not be fetched.'\n : 'Loading...'\n }\n />\n ) : null}\n </>\n )\n}\n", "import React from 'react'\n\nimport { makeStyles } from 'tss-react/mui'\n\nimport TextField2 from './TextField2'\n\nconst useStyles = makeStyles()({\n textAreaFont: {\n fontFamily: 'Courier New',\n },\n})\n\nexport default function ReadOnlyTextField2({ value }: { value: string }) {\n const { classes } = useStyles()\n return (\n <TextField2\n variant=\"outlined\"\n multiline\n minRows={5}\n maxRows={10}\n fullWidth\n value={value}\n slotProps={{\n input: {\n readOnly: true,\n classes: {\n input: classes.textAreaFont,\n },\n },\n }}\n />\n )\n}\n", "import { useRef, useState } from 'react'\n\nimport { getSession } from '@jbrowse/core/util'\n\nimport { launchMsaView } from '../../utils/launchMsaView'\n\nimport type { MsaViewPlacement } from '../../utils/workspaces'\nimport type { Feature } from '@jbrowse/core/util'\nimport type { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'\n\n/** how a view whose alignment the plugin builds opens */\nexport const builtAlignmentLook = {\n drawNodeBubbles: true,\n colWidth: 10,\n rowHeight: 12,\n}\n\n/**\n * Every dialog launch: an MSA view tied to the genome view it came from, and\n * through `feature` to the transcript whose codons its query row is read by.\n */\nexport function launchConnectedView({\n view,\n feature,\n placement,\n ...snapshot\n}: {\n view: LinearGenomeViewModel\n feature?: Feature\n placement: MsaViewPlacement\n} & Record<string, unknown>) {\n return launchMsaView(getSession(view), {\n placement,\n connectedViewId: view.id,\n connectedFeature: feature?.toJSON(),\n ...snapshot,\n })\n}\n\n/** runs a panel's launch, closing the dialog on success and keeping the error */\nexport function useLaunchSubmit(handleClose: () => void) {\n const [launchError, setLaunchError] = useState<unknown>()\n // the first launch loads the view's chunk, which is long enough to click twice\n const launching = useRef(false)\n return {\n launchError,\n submit: (launch: () => Promise<unknown>) => {\n if (launching.current) {\n return\n }\n launching.current = true\n setLaunchError(undefined)\n launch().then(handleClose, (e: unknown) => {\n launching.current = false\n console.error(e)\n setLaunchError(e)\n })\n },\n }\n}\n", "import { useMemo, useState } from 'react'\n\nimport { featureMatchesId, getId, getSortedTranscriptFeatures } from '../util'\nimport { useFeatureSequence } from './useFeatureSequence'\n\nimport type { SequenceStatus } from './SequenceStatus'\nimport type { Feature } from '@jbrowse/core/util'\n\n// Keep the current selection if it's valid for the given validIds, otherwise\n// fall back to the first valid option (or the current id if none qualify). With\n// no validIds constraint the current selection always stands.\nfunction pickSelectedId(\n currentId: string,\n options: Feature[],\n validIds: string[] | undefined,\n): string {\n if (!validIds?.length) {\n return currentId\n }\n const isValid = (opt: Feature) =>\n validIds.some(id => featureMatchesId(opt, id))\n const current = options.find(opt => getId(opt) === currentId)\n if (current && isValid(current)) {\n return currentId\n }\n const firstValid = options.find(isValid)\n return firstValid ? getId(firstValid) : currentId\n}\n\n/**\n * Submit is disabled until the query sequence is in hand, and a grey button\n * reads the same whether the translation is on its way or was never going to\n * arrive. `missing` is the second case: the feature has no CDS to translate,\n * which the dialog never said.\n */\nfunction sequenceStatus({\n error,\n isLoading,\n proteinSequence,\n}: {\n error: unknown\n isLoading: boolean\n proteinSequence: string\n}): SequenceStatus {\n if (error) {\n return 'error'\n }\n if (isLoading) {\n return 'loading'\n }\n return proteinSequence ? 'ready' : 'missing'\n}\n\nexport function useTranscriptSelection({\n feature,\n view,\n validIds,\n preferredTranscriptId,\n}: {\n feature: Feature\n view: { assemblyNames?: string[] } | undefined\n validIds?: string[]\n /**\n * the isoform the user right-clicked, when the dialog opened on its gene.\n * Ignored when this gene does not carry it, so a stale id falls back to the\n * longest transcript rather than selecting nothing.\n */\n preferredTranscriptId?: string\n}) {\n const options = useMemo(() => getSortedTranscriptFeatures(feature), [feature])\n const [selectedId, setSelectedId] = useState(() =>\n getId(\n options.find(opt => featureMatchesId(opt, preferredTranscriptId ?? '')) ??\n options[0],\n ),\n )\n const validatedSelectedId = pickSelectedId(selectedId, options, validIds)\n const selectedTranscript = options.find(\n val => getId(val) === validatedSelectedId,\n )\n const { proteinSequence, error, isLoading } = useFeatureSequence({\n view,\n feature: selectedTranscript,\n })\n\n return {\n options,\n selectedId: validatedSelectedId,\n setSelectedId,\n selectedTranscript,\n proteinSequence,\n error,\n isLoading,\n sequenceStatus: sequenceStatus({ error, isLoading, proteinSequence }),\n validIds,\n }\n}\n", "import { useMemo } from 'react'\n\nimport { getSession } from '@jbrowse/core/util'\nimport { translateTranscript } from '@jbrowse/core/util/translateTranscript'\n\nimport { useFetch } from '../../utils/useFetch'\nimport { fetchSeq } from './fetchSeq'\n\nimport type { Feature } from '@jbrowse/core/util'\n\ninterface ViewLike {\n assemblyNames?: string[]\n}\n\nexport function useFeatureSequence({\n view,\n feature,\n}: {\n view: ViewLike | undefined\n feature?: Feature\n}) {\n const assemblyName = view?.assemblyNames?.[0]\n const {\n data: sequence,\n error,\n isLoading,\n } = useFetch(\n feature && assemblyName\n ? [feature.id(), assemblyName, 'feature-sequence']\n : null,\n async () => {\n const { start, end, refName } = feature!.toJSON() as {\n start: number\n end: number\n refName: string\n }\n return fetchSeq({\n start,\n end,\n refName,\n assemblyName: assemblyName!,\n session: getSession(view),\n })\n },\n )\n\n const proteinSequence = useMemo(\n () =>\n sequence && feature\n ? (translateTranscript({ transcript: feature, ...sequence })?.protein ??\n '')\n : '',\n [sequence, feature],\n )\n return {\n proteinSequence,\n sequence,\n error,\n isLoading,\n }\n}\n", "import { useCallback, useEffect, useRef, useState } from 'react'\n\n// A trimmed copy of jbrowse-components' `packages/core/src/util/useFetch.ts`,\n// vendored for the same reason `useLocalStorage` and `defaultCodonTable` are:\n// it does not exist in the @jbrowse/core this plugin builds against, and a\n// host-resolved import is exactly how published bundles have broken here\n// before. Our own copy takes this out of the whack-a-mole.\n//\n// Trimmed because this plugin has no RPC: the core version also carries stop\n// tokens, a throttled progress stream and a cross-component mutate registry,\n// and nothing here has ever wanted any of the three. What is left is the\n// {data, error, isLoading} the four call sites this replaced actually used --\n// they were on SWR, whose only feature we relied on was fetch-once-per-key with\n// background revalidation off, so dropping it also drops a dependency from the\n// bundle.\n\nexport type FetchKey = string | readonly unknown[] | null | undefined | false\n\nconst isNil = (k: unknown) => k === null || k === undefined || k === false\n\n// A null result means \"don't fetch\": no key, or an array key with a missing\n// piece. Note what that makes of a boolean IN a key -- `false` reads as a\n// missing piece and silently disables the fetch, so put a string there.\nexport function serializeKey(key: FetchKey): string | null {\n return isNil(key) || (Array.isArray(key) && key.some(isNil))\n ? null\n : JSON.stringify(key)\n}\n\ninterface Settled<Data> {\n /** the key AND the attempt, so a mutate() refetch is a different entry */\n attempt: string\n /** the key alone, which is the question the data answers */\n question: string\n data?: Data\n error?: unknown\n}\n\n/**\n * Fetch once per key, keeping loading and error state with the data instead of\n * spread across three `useState`s and a cancellation flag.\n *\n * Everything the caller reads is derived from the one settled result, which is\n * what keeps the states consistent: while a key change is in flight there is no\n * frame showing the previous key's data as though it were the new key's. A\n * `mutate()` refetch under the same key does leave its data up, because it is\n * the same question asked again and blanking it flashes an empty list.\n */\nexport function useFetch<Data>(\n key: FetchKey,\n fetcher: (signal: AbortSignal) => Promise<Data>,\n { onSuccess }: { onSuccess?: (data: Data) => void } = {},\n) {\n const serialized = serializeKey(key)\n const [nonce, setNonce] = useState(0)\n const [settled, setSettled] = useState<Settled<Data>>()\n\n const attempt = serialized === null ? null : `${nonce}\\u0000${serialized}`\n const current = settled?.attempt === attempt\n const answersThisKey = settled?.question === serialized\n\n // The fetcher and the success callback are inline closures at every call site,\n // so depending on their identity would refetch every render. This effect is\n // declared before the fetch effect and has no dependency list, so it has\n // already run with the current render's values by the time that one does.\n const latest = useRef({ fetcher, onSuccess })\n useEffect(() => {\n latest.current = { fetcher, onSuccess }\n })\n\n useEffect(() => {\n if (attempt === null || serialized === null) {\n return undefined\n }\n const controller = new AbortController()\n latest.current\n .fetcher(controller.signal)\n .then(data => {\n if (!controller.signal.aborted) {\n setSettled({ attempt, question: serialized, data })\n latest.current.onSuccess?.(data)\n }\n })\n .catch((error: unknown) => {\n if (!controller.signal.aborted) {\n setSettled({ attempt, question: serialized, error })\n }\n })\n return () => {\n controller.abort()\n }\n }, [attempt, serialized])\n\n return {\n data: answersThisKey ? settled.data : undefined,\n error: current ? settled.error : undefined,\n isLoading: attempt !== null && !current,\n mutate: useCallback(() => {\n setNonce(n => n + 1)\n }, []),\n }\n}\n\n/** `value`, but only after it has stopped changing for `ms`. */\nexport function useDebounced<T>(value: T, ms: number) {\n const [debounced, setDebounced] = useState(value)\n useEffect(() => {\n const timer = setTimeout(() => {\n setDebounced(value)\n }, ms)\n return () => {\n clearTimeout(timer)\n }\n }, [value, ms])\n return debounced\n}\n", "import React, { useState } from 'react'\n\nimport { ErrorMessage } from '@jbrowse/core/ui'\nimport DeleteIcon from '@mui/icons-material/Delete'\nimport {\n Button,\n IconButton,\n List,\n ListItem,\n ListItemButton,\n ListItemText,\n Typography,\n} from '@mui/material'\nimport { observer } from 'mobx-react'\nimport { makeStyles } from 'tss-react/mui'\n\nimport {\n featureMatchesId,\n getLinearGenomeView,\n getSortedTranscriptFeatures,\n} from '../../util'\nimport { builtAlignmentLook, launchConnectedView } from '../launchConnectedView'\nimport { useLaunchPlacement } from '../launchPlacement'\n\nimport type { CachedBlastResult } from '../../../utils/blastCache'\nimport type { useCachedBlastResults } from './useCachedBlastResults'\nimport type { AbstractTrackModel, Feature } from '@jbrowse/core/util'\n\nconst useStyles = makeStyles()({\n header: {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n marginBottom: 8,\n },\n resultList: {\n maxHeight: 300,\n overflow: 'auto',\n },\n})\n\nfunction getResultDisplayName(result: CachedBlastResult): string {\n const parts = [\n result.geneName,\n result.transcriptName !== result.geneName\n ? result.transcriptName\n : undefined,\n ].filter((p): p is string => !!p)\n return parts.length > 0\n ? parts.join(' - ')\n : (result.geneId ?? result.transcriptId ?? 'Unknown')\n}\n\n/**\n * How the row was produced: `uniprotkb_swissprot / blastp / clustalo`, or\n * `swissprot / phmmer` for a row phmmer aligned as it searched and that\n * therefore ran no aligner. Each part is dropped when absent rather than\n * printed empty \u2014 `msaAlgorithm` became optional when phmmer arrived, and a\n * phmmer row read `(undefined)` until this stopped assuming one.\n *\n * `blastProgram` is the older field, written only while the plugin still\n * queried NCBI directly and blastp/quick-blastp was a real choice.\n */\nexport function describeSearch(result: CachedBlastResult) {\n return [\n result.blastDatabase,\n result.searchProgram ?? result.blastProgram ?? 'blastp',\n result.msaAlgorithm,\n ]\n .filter(Boolean)\n .join(' / ')\n}\n\nconst CachedBlastResults = observer(function ({\n model,\n handleClose,\n feature,\n cached: { results, handleDelete, handleClearAll },\n}: {\n model: AbstractTrackModel\n handleClose: () => void\n feature: Feature\n /** the panel's own listing, so clearing it here empties it there too */\n cached: ReturnType<typeof useCachedBlastResults>\n}) {\n const { classes } = useStyles()\n const view = getLinearGenomeView(model)\n const [operationError, setOperationError] = useState<unknown>()\n const [sideBySide] = useLaunchPlacement()\n\n const handleUseCached = (cached: CachedBlastResult) => {\n // the cached query row is the plugin's default `QUERY`, translated from\n // the transcript stored as transcriptId, so that transcript relinks it\n const { transcriptId, msa, tree, treeMetadata } = cached\n launchConnectedView({\n view,\n feature: transcriptId\n ? getSortedTranscriptFeatures(feature).find(t =>\n featureMatchesId(t, transcriptId),\n )\n : undefined,\n placement: sideBySide ? 'splitRight' : 'stack',\n displayName: `BLAST - ${getResultDisplayName(cached)}`,\n ...builtAlignmentLook,\n data: { msa, tree, treeMetadata },\n }).then(handleClose, (e: unknown) => {\n console.error(e)\n setOperationError(e)\n })\n }\n\n return (\n <div>\n {operationError ? <ErrorMessage error={operationError} /> : null}\n <div className={classes.header}>\n <Typography variant=\"subtitle1\">\n Cached BLAST Results ({results.length})\n </Typography>\n <Button\n size=\"small\"\n color=\"error\"\n onClick={async () => {\n try {\n setOperationError(undefined)\n await handleClearAll()\n } catch (e) {\n setOperationError(e)\n }\n }}\n >\n Clear results for this gene\n </Button>\n </div>\n <List dense className={classes.resultList}>\n {results.map(result => (\n <ListItem\n key={result.id}\n disablePadding\n secondaryAction={\n <IconButton\n edge=\"end\"\n size=\"small\"\n onClick={async e => {\n e.stopPropagation()\n try {\n setOperationError(undefined)\n await handleDelete(result.id)\n } catch (err) {\n setOperationError(err)\n }\n }}\n >\n <DeleteIcon fontSize=\"small\" />\n </IconButton>\n }\n >\n <ListItemButton\n onClick={() => {\n handleUseCached(result)\n }}\n >\n <ListItemText\n primary={`${getResultDisplayName(result)} - ${describeSearch(result)}`}\n secondary={`${new Date(result.timestamp).toLocaleString()} - Seq: ${result.proteinSequence.slice(0, 30)}...`}\n />\n </ListItemButton>\n </ListItem>\n ))}\n </List>\n </div>\n )\n})\n\nexport default CachedBlastResults\n", "\"use client\";\n\nimport createSvgIcon from \"./utils/createSvgIcon.mjs\";\nimport { jsx as _jsx } from \"react/jsx-runtime\";\nexport default createSvgIcon(/*#__PURE__*/_jsx(\"path\", {\n d: \"M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6zM19 4h-3.5l-1-1h-5l-1 1H5v2h14z\"\n}), 'Delete');", "import React from 'react'\n\nimport { MenuItem } from '@mui/material'\n\nimport TextField2 from '../../../components/TextField2'\nimport { msaAlgorithmLabels, msaAlgorithms } from './consts'\n\nimport type { MsaAlgorithm } from './consts'\n\nexport default function MsaAlgorithmSelect({\n value,\n onChange,\n className,\n}: {\n value: MsaAlgorithm\n onChange: (val: MsaAlgorithm) => void\n className?: string\n}) {\n return (\n <TextField2\n variant=\"outlined\"\n label=\"MSA Algorithm\"\n className={className}\n select\n value={value}\n helperText={\n value === 'browser'\n ? 'no EBI job; rows aligned to the query'\n : undefined\n }\n onChange={event => {\n onChange(event.target.value as MsaAlgorithm)\n }}\n >\n {msaAlgorithms.map(val => (\n <MenuItem value={val} key={val}>\n {msaAlgorithmLabels[val]}\n </MenuItem>\n ))}\n </TextField2>\n )\n}\n", "import { useLocalStorage } from '../../../utils/useLocalStorage'\nimport {\n databaseOptionsFor,\n defaultSearchFor,\n msaAlgorithms,\n searchPrograms,\n} from './consts'\n\nimport type { MsaAlgorithm, SearchChoice } from './consts'\n\n// The panel reopens on the last search run rather than on the defaults, the way\n// the Orthologs tab remembers its source.\n//\n// The program and its database stay ONE stored value for the reason consts.ts\n// keeps them one state: neither service knows the other's database names. What\n// comes back is checked against the current options before it is used \u2014 an\n// option this plugin has since dropped would otherwise reach EBI and come back\n// a 400, minutes after the user pressed Submit.\nconst SEARCH_CHOICE_STORAGE_KEY = 'msaView-blastSearch'\nconst MSA_ALGORITHM_STORAGE_KEY = 'msaView-msaAlgorithm'\n\nconst defaultSearch = defaultSearchFor('blastp')\nconst defaultMsaAlgorithm: MsaAlgorithm = 'clustalo'\n\nexport function validSearchChoice(stored: unknown): SearchChoice {\n const { program, database } = (stored ?? {}) as {\n program?: string\n database?: string\n }\n const known = searchPrograms.find(p => p === program)\n return known && databaseOptionsFor(known).some(d => d === database)\n ? ({ program: known, database } as SearchChoice)\n : defaultSearch\n}\n\nexport function validMsaAlgorithm(stored: unknown): MsaAlgorithm {\n return msaAlgorithms.find(a => a === stored) ?? defaultMsaAlgorithm\n}\n\nexport function useStoredSearchChoice() {\n const [stored, setStored] = useLocalStorage<unknown>(\n SEARCH_CHOICE_STORAGE_KEY,\n defaultSearch,\n )\n return [\n validSearchChoice(stored),\n (choice: SearchChoice) => {\n setStored(choice)\n },\n ] as const\n}\n\nexport function useStoredMsaAlgorithm() {\n const [stored, setStored] = useLocalStorage<unknown>(\n MSA_ALGORITHM_STORAGE_KEY,\n defaultMsaAlgorithm,\n )\n return [\n validMsaAlgorithm(stored),\n (algorithm: MsaAlgorithm) => {\n setStored(algorithm)\n },\n ] as const\n}\n", "import {\n deleteCachedResult,\n getAllCachedResults,\n} from '../../../utils/blastCache'\nimport { useFetch } from '../../../utils/useFetch'\n\nexport function useCachedBlastResults(geneIds: string[]) {\n const {\n data: results,\n error,\n isLoading,\n mutate,\n } = useFetch(`cached-blast-${geneIds.join(',')}`, async () => {\n const cached = await getAllCachedResults()\n return cached.filter(r => r.geneId && geneIds.includes(r.geneId))\n })\n\n return {\n results: results ?? [],\n error,\n isLoading,\n handleDelete: async (id: string) => {\n await deleteCachedResult(id)\n mutate()\n },\n // deletes only what this hook listed, i.e. the results for these gene ids.\n // The list the user is looking at is gene-scoped, so a store-wide clear here\n // would silently throw away every other gene's cached alignments too\n handleClearAll: async () => {\n await Promise.all((results ?? []).map(r => deleteCachedResult(r.id)))\n mutate()\n },\n }\n}\n", "import React, { useState } from 'react'\n\nimport { shorten2 } from '@jbrowse/core/util'\nimport { Alert, Typography } from '@mui/material'\nimport { observer } from 'mobx-react'\nimport { makeStyles } from 'tss-react/mui'\n\nimport ExternalLink from '../../../components/ExternalLink'\nimport TextField2 from '../../../components/TextField2'\nimport { useQueryRowName } from '../../useQueryRowName'\nimport {\n cleanProteinSequence,\n getGeneDisplayName,\n getLinearGenomeView,\n} from '../../util'\nimport LaunchPanelContent from '../LaunchPanelContent'\nimport QueryRowSelector from '../QueryRowSelector'\nimport SubmitCancelActions from '../SubmitCancelActions'\nimport TranscriptSelector from '../TranscriptSelector'\nimport { launchConnectedView, useLaunchSubmit } from '../launchConnectedView'\nimport { useTranscriptSelection } from '../useTranscriptSelection'\nimport { BASE_BLAST_URL } from './consts'\n\nimport type { AbstractTrackModel, Feature } from '@jbrowse/core/util'\n\nconst useStyles = makeStyles()({\n ncbiLink: {\n wordBreak: 'break-all',\n },\n textAreaFont: {\n fontFamily: 'Courier New',\n },\n msaInput: {\n marginBottom: 20,\n },\n step: {\n marginTop: 20,\n },\n stepBody: {\n marginLeft: 20,\n marginTop: 8,\n },\n})\n\n/**\n * The route to NCBI's `nr`, which no plugin version can query directly: NCBI\n * stopped sending Access-Control-Allow-Origin to third-party origins, so the\n * browser cannot read Blast.cgi at all (see docs/blast.md).\n *\n * That makes the round trip through NCBI's own site the whole feature rather\n * than a fallback, so the panel walks it end to end. It used to hand the user a\n * link, tell them to \"paste the results into JBrowse\", and offer only a Close\n * button -- leaving them to find the Manual upload tab, re-pick the transcript\n * they had already chosen here, and hand-type the row name.\n */\nconst BlastManualPanel = observer(function ({\n handleClose,\n feature,\n model,\n children,\n preferredTranscriptId,\n}: {\n children: React.ReactNode\n model: AbstractTrackModel\n feature: Feature\n handleClose: () => void\n /** the isoform the user right-clicked, preselected in the picker */\n preferredTranscriptId?: string\n}) {\n const { classes } = useStyles()\n const view = getLinearGenomeView(model)\n const { launchError, submit } = useLaunchSubmit(handleClose)\n const [msaText, setMsaText] = useState('')\n const [treeText, setTreeText] = useState('')\n\n const transcriptSelection = useTranscriptSelection({\n feature,\n view,\n preferredTranscriptId,\n })\n const { proteinSequence, selectedTranscript, error } = transcriptSelection\n const queryRow = useQueryRowName(msaText, proteinSequence)\n\n const s2 = cleanProteinSequence(proteinSequence)\n // a link the user follows to NCBI's own site, not something we fetch \u2014 which\n // is exactly why this route still works when the automatic one cannot\n const link = `${BASE_BLAST_URL}?PAGE_TYPE=BlastSearch&PAGE=Proteins&PROGRAM=blastp&QUERY=${s2}`\n const link2 = `${BASE_BLAST_URL}?PAGE_TYPE=BlastSearch&PAGE=Proteins&PROGRAM=blastp&QUERY=${shorten2(s2, 10)}`\n\n return (\n <>\n <LaunchPanelContent error={launchError ?? error}>\n {children}\n\n <TranscriptSelector feature={feature} {...transcriptSelection} />\n\n <div className={classes.step}>\n <Typography variant=\"subtitle2\">1. Run the search at NCBI</Typography>\n <div className={classes.stepBody}>\n {proteinSequence ? (\n <div className={classes.ncbiLink}>\n <ExternalLink href={link}>{link2}</ExternalLink>\n </div>\n ) : (\n <Alert severity=\"info\">\n Pick a transcript above to get a link carrying its protein\n sequence.\n </Alert>\n )}\n </div>\n </div>\n\n <div className={classes.step}>\n <Typography variant=\"subtitle2\">2. Align the hits</Typography>\n <div className={classes.stepBody}>\n <Typography>\n On the results page click \"Multiple Alignment\" to run COBALT,\n NCBI's aligner. Download the alignment (.aln) and, if you want the\n tree drawn, the Newick tree (.nh).\n </Typography>\n </div>\n </div>\n\n <div className={classes.step}>\n <Typography variant=\"subtitle2\">\n 3. Paste the results back here\n </Typography>\n <div className={classes.stepBody}>\n <TextField2\n variant=\"outlined\"\n label=\"Alignment\"\n multiline\n minRows={5}\n maxRows={10}\n fullWidth\n className={classes.msaInput}\n slotProps={{ input: { className: classes.textAreaFont } }}\n placeholder=\"Paste the .aln contents here\"\n value={msaText}\n onChange={event => {\n setMsaText(event.target.value)\n }}\n />\n <TextField2\n variant=\"outlined\"\n label=\"Tree (optional)\"\n multiline\n minRows={3}\n maxRows={10}\n fullWidth\n slotProps={{ input: { className: classes.textAreaFont } }}\n placeholder=\"Paste the .nh Newick tree here\"\n value={treeText}\n onChange={event => {\n setTreeText(event.target.value)\n }}\n />\n\n <QueryRowSelector {...queryRow} />\n </div>\n </div>\n </LaunchPanelContent>\n\n <SubmitCancelActions\n model={model}\n submitDisabled={!selectedTranscript || !msaText.trim()}\n onSubmit={placement => {\n if (selectedTranscript) {\n submit(() =>\n launchConnectedView({\n view,\n feature: selectedTranscript,\n placement,\n displayName: getGeneDisplayName(selectedTranscript),\n querySeqName: queryRow.querySeqName,\n querySeqOffset: queryRow.querySeqOffset,\n data: { msa: msaText, tree: treeText },\n }),\n )\n }\n }}\n onCancel={handleClose}\n />\n </>\n )\n})\n\nexport default BlastManualPanel\n", "import { useMemo, useState } from 'react'\n\nimport { findQueryRow } from './detectQueryRow'\n\n/**\n * The MSA row name to launch with, found by sequence rather than typed.\n *\n * Only the user's override is state. The detected name is derived from the\n * pasted text during render, so pasting a new alignment re-detects without an\n * effect writing back into state, and an override survives later edits to the\n * alignment because it is the one thing actually stored.\n */\n/**\n * The row to launch with. Detection by residues is the answer wherever it has\n * one -- aligners rename the query on the way through, so a name proves\n * nothing -- but a caller with a naming convention of its own can offer it as a\n * fallback, and it is taken only when the alignment really carries that row.\n * An empty result means there is no query row, which a launch has to refuse:\n * the view opens, renders, and then never navigates.\n */\nexport function resolveQueryRowName(\n queryRow: { querySeqName: string; names: string[] },\n fallback: string,\n) {\n return (\n queryRow.querySeqName || (queryRow.names.includes(fallback) ? fallback : '')\n )\n}\n\nexport function useQueryRowName(msaText: string, proteinSequence: string) {\n const [override, setOverride] = useState<string>()\n\n // parsing runs on every keystroke in the paste box otherwise, and an\n // alignment of a few hundred rows is not free\n const { names, match } = useMemo(\n () => findQueryRow(msaText, proteinSequence),\n [msaText, proteinSequence],\n )\n\n // a row picked from one alignment says nothing about the next one pasted\n const picked =\n override !== undefined && (names.length === 0 || names.includes(override))\n ? override\n : undefined\n const querySeqName = picked ?? match?.name ?? ''\n return {\n detected: match,\n names,\n querySeqName,\n // only the detected row's offset is known; a row the user picked instead is\n // taken at face value, residue 1 to residue 1\n querySeqOffset: querySeqName === match?.name ? match.offset : 0,\n setQuerySeqName: setOverride,\n isAutoDetected: picked === undefined && !!match,\n }\n}\n", "import { getUngappedSequence, parseMSA } from 'msa-parsers'\n\nimport { cleanProteinSequence } from './util'\n\n/**\n * Which row of a pasted alignment is the gene the user launched from.\n *\n * The MsaView needs that row name to tie alignment columns back to genome\n * coordinates, and until now the user typed it. Nothing validates a typo: the\n * view opens, renders, and simply never navigates or highlights, which reads as\n * a broken feature rather than a wrong field. Meanwhile the plugin already\n * knows the protein sequence it sent to BLAST, so it can find the row by\n * sequence instead of asking.\n *\n * NCBI and EBI both rename the query on the way through -- COBALT emits\n * `Query_1`, EBI's aligners carry the accession -- so the name is no help. The\n * residues are, and they survive every rename.\n */\n\nexport type MatchQuality = 'exact' | 'partial' | 'similar'\n\nexport interface QueryRowMatch {\n name: string\n quality: MatchQuality\n /** identity over the compared region, 0-1 */\n identity: number\n /**\n * Transcript residues before the row's first residue, so transcript position\n * = row position + offset. BLAST reports the aligned region, so a row is\n * often the query with its termini trimmed, and mapping its first residue to\n * the transcript's first residue would put every navigation off by the\n * trimmed amount. Negative when the row is the longer of the two.\n *\n * Zero for a `similar` match, which is the one arm this cannot measure: the\n * row is not the query, so where it starts is a guess.\n */\n offset: number\n}\n\n/**\n * The translation as a search launch would have sent it, so a row that launch\n * built matches exactly; case means nothing on either side.\n */\nfunction normalize(seq: string) {\n return cleanProteinSequence(seq).toUpperCase()\n}\n\nfunction identityOverOverlap(a: string, b: string) {\n const len = Math.min(a.length, b.length)\n if (len === 0) {\n return 0\n }\n let same = 0\n for (let i = 0; i < len; i++) {\n if (a[i] === b[i]) {\n same++\n }\n }\n return same / len\n}\n\n/**\n * Below this, a \"best\" row is not a match at all -- an alignment of homologs is\n * full of rows in the 40-70% range, and picking the top one would silently wire\n * the view to a paralog from another species.\n */\nconst SIMILARITY_FLOOR = 0.9\n\n/**\n * How much of the query a contained row has to cover. A short fragment is a\n * substring of almost any protein, so without a floor the first few residues of\n * a half-pasted alignment match the query and the field fills in with a row the\n * user is still typing.\n */\nconst PARTIAL_COVERAGE_FLOOR = 0.5\n\nexport interface MsaQueryRow {\n /** every row name, in file order, for the picker to offer */\n names: string[]\n /** the row whose residues are the query's, if one of them is */\n match?: QueryRowMatch\n}\n\n/**\n * The picker's whole answer for a pasted alignment: its row names, and which of\n * them is the query.\n *\n * One function rather than two because there is one parse. Both answers were\n * wanted on every keystroke in the paste box, and asking separately parsed a\n * few-hundred-row alignment twice per character.\n */\nexport function findQueryRow(\n msaText: string,\n proteinSequence: string,\n): MsaQueryRow {\n if (!msaText.trim()) {\n return { names: [] }\n }\n\n let parsed\n try {\n parsed = parseMSA(msaText)\n } catch {\n // a half-pasted alignment throws here on every keystroke; the caller shows\n // the field rather than an error\n return { names: [] }\n }\n\n const names = parsed.getNames()\n const query = normalize(proteinSequence)\n return { names, match: query ? bestMatch(parsed, names, query) : undefined }\n}\n\nfunction bestMatch(\n parsed: { getRow: (name: string) => string },\n names: string[],\n query: string,\n): QueryRowMatch | undefined {\n const candidates: QueryRowMatch[] = []\n for (const name of names) {\n const row = normalize(getUngappedSequence(parsed.getRow(name)))\n if (!row) {\n continue\n }\n if (row === query) {\n // nothing beats an exact match, and a second one would be a duplicate row\n return { name, quality: 'exact', identity: 1, offset: 0 }\n }\n // BLAST reports the aligned region, so the row is often the query trimmed\n // at one or both ends rather than the whole protein\n const contained = query.indexOf(row)\n const containing = row.indexOf(query)\n if (contained !== -1 || containing !== -1) {\n const coverage =\n Math.min(row.length, query.length) / Math.max(row.length, query.length)\n if (coverage >= PARTIAL_COVERAGE_FLOOR) {\n candidates.push({\n name,\n quality: 'partial',\n identity: coverage,\n offset: contained === -1 ? -containing : contained,\n })\n }\n continue\n }\n const identity = identityOverOverlap(row, query)\n if (identity >= SIMILARITY_FLOOR) {\n candidates.push({ name, quality: 'similar', identity, offset: 0 })\n }\n }\n\n // an exact match returns above, so only these two can be here\n const order: MatchQuality[] = ['partial', 'similar']\n return candidates.sort(\n (a, b) =>\n order.indexOf(a.quality) - order.indexOf(b.quality) ||\n b.identity - a.identity,\n )[0]\n}\n", "import React from 'react'\n\nimport { Alert, MenuItem } from '@mui/material'\nimport { makeStyles } from 'tss-react/mui'\n\nimport TextField2 from '../../components/TextField2'\n\nimport type { QueryRowMatch } from '../detectQueryRow'\n\nconst useStyles = makeStyles()({\n field: {\n marginTop: 20,\n },\n alert: {\n marginTop: 10,\n },\n})\n\n/**\n * Where a trimmed row sits in the protein. The offset is what the view maps\n * through, so the alert says it rather than leaving the user to wonder why the\n * row is shorter than their transcript.\n */\nfunction partialCoverage({\n identity,\n offset,\n}: {\n identity: number\n offset: number\n}) {\n const covering = `, covering ${Math.round(identity * 100)}% of it`\n return offset > 0\n ? `${covering} from residue ${offset + 1}`\n : offset < 0\n ? `${covering} and running ${-offset} residues past its start`\n : covering\n}\n\n/**\n * Which MSA row corresponds to the selected transcript. Clicking and hovering in\n * the alignment reach the genome only through this name, and a wrong one fails\n * silently -- the view opens, renders, and never navigates -- so the field fills\n * itself in from the pasted alignment and offers that alignment's own row names\n * rather than a free text box the user can typo.\n */\nexport default function QueryRowSelector({\n names,\n detected,\n querySeqName,\n setQuerySeqName,\n isAutoDetected,\n}: {\n names: string[]\n detected?: QueryRowMatch\n querySeqName: string\n setQuerySeqName: (arg: string) => void\n isAutoDetected: boolean\n}) {\n const { classes } = useStyles()\n\n return (\n <>\n {names.length > 0 ? (\n <TextField2\n variant=\"outlined\"\n label=\"MSA row matching the selected transcript\"\n select\n fullWidth\n className={classes.field}\n value={names.includes(querySeqName) ? querySeqName : ''}\n onChange={event => {\n setQuerySeqName(event.target.value)\n }}\n >\n {names.map(name => (\n <MenuItem value={name} key={name}>\n {name}\n {detected?.name === name ? ' \u2014 matches your protein' : ''}\n </MenuItem>\n ))}\n </TextField2>\n ) : (\n <TextField2\n variant=\"outlined\"\n label=\"MSA row matching the selected transcript\"\n fullWidth\n className={classes.field}\n helperText=\"Paste an alignment above and this fills in on its own\"\n value={querySeqName}\n onChange={event => {\n setQuerySeqName(event.target.value)\n }}\n />\n )}\n\n {isAutoDetected && detected ? (\n detected.quality === 'similar' ? (\n <Alert severity=\"warning\" className={classes.alert}>\n <strong>{detected.name}</strong> is{' '}\n {Math.round(detected.identity * 100)}% identical to your protein but\n is not the same sequence. Clicking the alignment navigates the\n genome view, approximately: wherever the two differ by an insertion\n or a deletion, every residue after it lands one codon off.\n </Alert>\n ) : (\n <Alert severity=\"success\" className={classes.alert}>\n Matched <strong>{detected.name}</strong> to your protein sequence\n {detected.quality === 'exact' ? '' : partialCoverage(detected)}.\n Clicking the alignment will navigate the genome view.\n </Alert>\n )\n ) : names.length > 0 && !querySeqName ? (\n <Alert severity=\"warning\" className={classes.alert}>\n No row matched your protein sequence \u2014 pick the one for your gene\n above. Without it the alignment still renders, but clicking it will\n not navigate the genome view.\n </Alert>\n ) : null}\n </>\n )\n}\n", "import React from 'react'\n\nimport { FormControl, FormControlLabel, Radio, RadioGroup } from '@mui/material'\n\nimport type { BlastLookupMethod } from './BlastPanel'\n\nexport default function BlastMethodSelector({\n lookupMethod,\n setLookupMethod,\n}: {\n lookupMethod: BlastLookupMethod\n setLookupMethod: (method: BlastLookupMethod) => void\n}) {\n return (\n <FormControl component=\"fieldset\">\n <RadioGroup\n row\n value={lookupMethod}\n onChange={event => {\n setLookupMethod(event.target.value as BlastLookupMethod)\n }}\n >\n <FormControlLabel\n value=\"automatic\"\n control={<Radio />}\n label=\"Automatic\"\n />\n <FormControlLabel value=\"manual\" control={<Radio />} label=\"Manual\" />\n </RadioGroup>\n </FormControl>\n )\n}\n", "import React, { useState } from 'react'\n\nimport {\n Button,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n Typography,\n} from '@mui/material'\nimport { makeStyles } from 'tss-react/mui'\n\nimport TextField2 from '../../../components/TextField2'\nimport { DEFAULT_EBI_EMAIL } from '../../../utils/ebiJobDispatcher'\n\nconst useStyles = makeStyles()({\n field: {\n minWidth: 300,\n },\n help: {\n marginBottom: 8,\n },\n})\n\nexport interface BlastSettings {\n ebiEmail: string\n}\n\nexport default function BlastSettingsDialog({\n handleClose,\n ebiEmail,\n}: {\n handleClose: (arg?: BlastSettings) => void\n ebiEmail: string\n}) {\n const { classes } = useStyles()\n const [tempEbiEmail, setTempEbiEmail] = useState(ebiEmail)\n return (\n <Dialog\n open\n maxWidth=\"lg\"\n onClose={() => {\n handleClose()\n }}\n >\n <DialogTitle>EBI settings</DialogTitle>\n <DialogContent>\n <Typography variant=\"subtitle2\" className={classes.help}>\n Every search this tab runs is submitted to EBI with this address,\n which is how they reach whoever is generating the load. If your site\n sends real volume, use your own.\n </Typography>\n <TextField2\n autoFocus\n margin=\"dense\"\n label=\"EBI contact email\"\n fullWidth\n variant=\"outlined\"\n value={tempEbiEmail}\n className={classes.field}\n onChange={e => {\n setTempEbiEmail(e.target.value)\n }}\n />\n <Button\n variant=\"contained\"\n onClick={() => {\n setTempEbiEmail(DEFAULT_EBI_EMAIL)\n }}\n >\n Reset\n </Button>\n </DialogContent>\n <DialogActions>\n <Button\n variant=\"contained\"\n color=\"secondary\"\n onClick={() => {\n handleClose()\n }}\n >\n Cancel\n </Button>\n <Button\n color=\"primary\"\n variant=\"contained\"\n onClick={() => {\n handleClose({ ebiEmail: tempEbiEmail })\n }}\n >\n Save\n </Button>\n </DialogActions>\n </Dialog>\n )\n}\n", "import React, { Suspense, lazy, useState } from 'react'\n\nimport Help from '@mui/icons-material/Help'\nimport { IconButton, Tooltip } from '@mui/material'\n\nconst HelpDialog = lazy(() => import('./HelpDialog'))\n\nexport default function HelpButton() {\n const [show, setShow] = useState(false)\n return (\n <>\n <Tooltip title=\"What each tab does\">\n <IconButton\n aria-label=\"Help\"\n onClick={() => {\n setShow(true)\n }}\n >\n <Help />\n </IconButton>\n </Tooltip>\n {show ? (\n <Suspense fallback={null}>\n <HelpDialog\n handleClose={() => {\n setShow(false)\n }}\n />\n </Suspense>\n ) : null}\n </>\n )\n}\n", "import React, { useState } from 'react'\n\nimport { FileSelector } from '@jbrowse/core/ui'\nimport { openLocation } from '@jbrowse/core/util/io'\nimport { FormControl, FormControlLabel, Radio, RadioGroup } from '@mui/material'\nimport { observer } from 'mobx-react'\nimport { makeStyles } from 'tss-react/mui'\n\nimport TextField2 from '../../../components/TextField2'\nimport { useDebounced, useFetch } from '../../../utils/useFetch'\nimport { useQueryRowName } from '../../useQueryRowName'\nimport { getGeneDisplayName, getLinearGenomeView } from '../../util'\nimport LaunchPanelContent from '../LaunchPanelContent'\nimport QueryRowSelector from '../QueryRowSelector'\nimport SequenceStatusMessage from '../SequenceStatus'\nimport SubmitCancelActions from '../SubmitCancelActions'\nimport TranscriptSelector from '../TranscriptSelector'\nimport { launchConnectedView, useLaunchSubmit } from '../launchConnectedView'\nimport { useTranscriptSelection } from '../useTranscriptSelection'\n\nimport type {\n AbstractTrackModel,\n Feature,\n FileLocation,\n} from '@jbrowse/core/util'\n\n/**\n * The chosen file's text, so its query row is found by sequence the way a\n * pasted alignment's is; without it a file launch named no row and never\n * linked to the genome. Debounced because a URL arrives a keystroke at a time.\n */\nfunction useMsaFileText(location: FileLocation | undefined) {\n const debounced = useDebounced(location, 500)\n const { data, error, isLoading } = useFetch(\n debounced ? [JSON.stringify(debounced), 'msa-file-text'] : null,\n () => openLocation(debounced!).readFile('utf8'),\n )\n return {\n text: data ?? '',\n error,\n isLoading: isLoading || debounced !== location,\n }\n}\n\nconst useStyles = makeStyles()({\n inputContainer: {\n marginBottom: 30,\n },\n fileContainer: {\n maxWidth: 500,\n },\n msaInput: {\n marginBottom: 20,\n },\n})\n\nconst ManualMSALoader = observer(function PreLoadedMSA2({\n model,\n feature,\n handleClose,\n preferredTranscriptId,\n}: {\n model: AbstractTrackModel\n feature: Feature\n handleClose: () => void\n /** the isoform the user right-clicked, preselected in the picker */\n preferredTranscriptId?: string\n}) {\n const view = getLinearGenomeView(model)\n const { classes } = useStyles()\n const { launchError, submit } = useLaunchSubmit(handleClose)\n const [inputMethod, setInputMethod] = useState<'file' | 'text'>('file')\n const [msaText, setMsaText] = useState('')\n const [treeText, setTreeText] = useState('')\n const [msaFileLocation, setMsaFileLocation] = useState<FileLocation>()\n const [treeFileLocation, setTreeFileLocation] = useState<FileLocation>()\n const transcriptSelection = useTranscriptSelection({\n feature,\n view,\n preferredTranscriptId,\n })\n const { selectedTranscript, proteinSequence, error, sequenceStatus } =\n transcriptSelection\n const msaFile = useMsaFileText(\n inputMethod === 'file' ? msaFileLocation : undefined,\n )\n const queryRow = useQueryRowName(\n inputMethod === 'file' ? msaFile.text : msaText,\n proteinSequence,\n )\n\n const e = launchError ?? error ?? msaFile.error\n return (\n <>\n <LaunchPanelContent error={e}>\n <FormControl component=\"fieldset\">\n <RadioGroup\n row\n value={inputMethod}\n onChange={event => {\n setInputMethod(event.target.value as 'file' | 'text')\n }}\n >\n <FormControlLabel\n value=\"file\"\n control={<Radio />}\n label=\"Open files\"\n />\n <FormControlLabel\n value=\"text\"\n control={<Radio />}\n label=\"Paste text\"\n />\n </RadioGroup>\n </FormControl>\n\n <div className={classes.inputContainer}>\n {inputMethod === 'file' ? (\n <div className={classes.fileContainer}>\n <FileSelector\n name=\"MSA File .aln (Clustal), .fa/.mfa (aligned FASTA), .stock (Stockholm), etc)\"\n inline\n location={msaFileLocation}\n setLocation={setMsaFileLocation}\n />\n <FileSelector\n name=\"Tree file .nh (Newick) or .asn (NCBI COBALT ASN.1)\"\n inline\n location={treeFileLocation}\n setLocation={setTreeFileLocation}\n />\n </div>\n ) : (\n <>\n <TextField2\n variant=\"outlined\"\n name=\"MSA\"\n multiline\n minRows={5}\n className={classes.msaInput}\n maxRows={10}\n fullWidth\n placeholder=\"Paste MSA here\"\n value={msaText}\n onChange={event => {\n setMsaText(event.target.value)\n }}\n />\n <TextField2\n variant=\"outlined\"\n name=\"Tree\"\n multiline\n minRows={5}\n maxRows={10}\n fullWidth\n placeholder=\"Paste newick tree (optional)\"\n value={treeText}\n onChange={event => {\n setTreeText(event.target.value)\n }}\n />\n </>\n )}\n </div>\n\n <TranscriptSelector feature={feature} {...transcriptSelection} />\n\n <QueryRowSelector {...queryRow} />\n </LaunchPanelContent>\n\n <SubmitCancelActions\n model={model}\n hint={<SequenceStatusMessage status={sequenceStatus} />}\n submitDisabled={\n !selectedTranscript ||\n (inputMethod === 'file' && (!msaFileLocation || msaFile.isLoading)) ||\n (inputMethod === 'text' && !msaText.trim())\n }\n onSubmit={placement => {\n if (selectedTranscript) {\n submit(() =>\n launchConnectedView({\n view,\n feature: selectedTranscript,\n placement,\n displayName: getGeneDisplayName(selectedTranscript),\n querySeqName: queryRow.querySeqName,\n querySeqOffset: queryRow.querySeqOffset,\n ...(inputMethod === 'file'\n ? {\n msaFilehandle: msaFileLocation,\n treeFilehandle: treeFileLocation,\n }\n : { data: { msa: msaText, tree: treeText } }),\n }),\n )\n }\n }}\n onCancel={handleClose}\n />\n </>\n )\n})\n\nexport default ManualMSALoader\n", "import React, { useMemo, useState } from 'react'\n\nimport { Typography } from '@mui/material'\nimport { observer } from 'mobx-react'\nimport { makeStyles } from 'tss-react/mui'\n\nimport TextField2 from '../../../components/TextField2'\nimport { defaultMaxSpecies } from '../../../utils/ncbiOrthologs'\nimport {\n getGeneDisplayName,\n getGeneIdentifiers,\n getLinearGenomeView,\n getTranscriptDisplayName,\n} from '../../util'\nimport MsaAlgorithmSelect from '../BlastQuery/MsaAlgorithmSelect'\nimport { useStoredMsaAlgorithm } from '../BlastQuery/searchChoiceStorage'\nimport LaunchPanelContent from '../LaunchPanelContent'\nimport SequenceStatusMessage from '../SequenceStatus'\nimport SubmitCancelActions from '../SubmitCancelActions'\nimport TranscriptSelector from '../TranscriptSelector'\nimport {\n builtAlignmentLook,\n launchConnectedView,\n useLaunchSubmit,\n} from '../launchConnectedView'\nimport { useTranscriptSelection } from '../useTranscriptSelection'\nimport OrthologSourceSelect, {\n useStoredOrthologSource,\n} from './OrthologSourceSelect'\nimport QuerySpeciesSelect from './QuerySpeciesSelect'\n\nimport type { OrthologSource } from '../../../MsaViewPanel/model'\nimport type { AbstractTrackModel, Feature } from '@jbrowse/core/util'\n\nconst useStyles = makeStyles()({\n selectField: {\n width: 180,\n },\n})\n\n// the N was literal: the helper text said \"the closest N species\" whatever the\n// box held\nconst rowsHint: Record<OrthologSource, (rows: number) => string> = {\n ncbi: rows => `the ${rows} closest species NCBI has`,\n panther: rows => `the ${rows} closest species PANTHER has`,\n uniref: rows => `${rows} rows, one per species, reviewed entries first`,\n}\n\nconst OrthologPanel = observer(function ({\n handleClose,\n feature,\n model,\n preferredTranscriptId,\n}: {\n model: AbstractTrackModel\n feature: Feature\n handleClose: () => void\n /** the isoform the user right-clicked, preselected in the picker */\n preferredTranscriptId?: string\n}) {\n const { classes } = useStyles()\n const view = getLinearGenomeView(model)\n const { launchError, submit } = useLaunchSubmit(handleClose)\n const [taxId, setTaxId] = useState(9606)\n const [source, setSource] = useStoredOrthologSource()\n const [msaAlgorithm, setMsaAlgorithm] = useStoredMsaAlgorithm()\n const [maxSpecies, setMaxSpecies] = useState(String(defaultMaxSpecies))\n\n const geneCandidates = useMemo(() => getGeneIdentifiers(feature), [feature])\n const transcriptSelection = useTranscriptSelection({\n feature,\n view,\n preferredTranscriptId,\n })\n const { selectedTranscript, proteinSequence, sequenceStatus } =\n transcriptSelection\n const e = transcriptSelection.error ?? launchError\n\n const rowCount = Number(maxSpecies)\n const rowCountValid = Number.isInteger(rowCount) && rowCount >= 2\n\n return (\n <>\n <LaunchPanelContent error={e}>\n {/* One line rather than seven. What a reader needs here is which tab to\n pick; the rest (species labels, CDD overlay, the query row being the\n selected transcript) is visible in the result or documented, and as\n prose it was most of the dialog's height.\n\n The comparison stays but the number moved: the lookup is still\n instant, and it is now the aligner that costs the wait, about half a\n second per row. */}\n <Typography variant=\"body2\">\n Precomputed orthologs, one gene per species, looked up rather than\n searched for. No BLAST job to queue, and with the in-browser aligner\n no job at all.\n </Typography>\n\n <div>\n <OrthologSourceSelect\n className={classes.selectField}\n value={source}\n onChange={setSource}\n />\n\n <QuerySpeciesSelect\n className={classes.selectField}\n value={taxId}\n assemblyName={view.assemblyNames[0]}\n onChange={setTaxId}\n />\n\n <MsaAlgorithmSelect\n className={classes.selectField}\n value={msaAlgorithm}\n onChange={setMsaAlgorithm}\n />\n\n <TextField2\n variant=\"outlined\"\n label=\"Rows to align\"\n className={classes.selectField}\n type=\"number\"\n value={maxSpecies}\n onChange={event => {\n setMaxSpecies(event.target.value)\n }}\n error={!rowCountValid}\n helperText={\n rowCountValid\n ? rowsHint[source](rowCount)\n : 'a whole number, 2 or more'\n }\n />\n </div>\n\n <TranscriptSelector feature={feature} {...transcriptSelection} />\n </LaunchPanelContent>\n <SubmitCancelActions\n model={model}\n hint={<SequenceStatusMessage status={sequenceStatus} />}\n submitDisabled={!proteinSequence || !rowCountValid}\n onSubmit={placement => {\n if (selectedTranscript) {\n submit(() =>\n launchConnectedView({\n view,\n feature: selectedTranscript,\n placement,\n displayName: `Orthologs - ${getGeneDisplayName(feature)} - ${getTranscriptDisplayName(selectedTranscript)}`,\n ...builtAlignmentLook,\n orthologParams: {\n taxId,\n source,\n maxSpecies: rowCount,\n geneCandidates,\n msaAlgorithm,\n selectedTranscript: selectedTranscript.toJSON(),\n proteinSequence,\n },\n }),\n )\n }\n }}\n onCancel={handleClose}\n />\n </>\n )\n})\n\nexport default OrthologPanel\n", "import React from 'react'\n\nimport { MenuItem } from '@mui/material'\n\nimport TextField2 from '../../../components/TextField2'\nimport { useLocalStorage } from '../../../utils/useLocalStorage'\n\nimport type { OrthologSource } from '../../../MsaViewPanel/model'\n\nconst ORTHOLOG_SOURCE_STORAGE_KEY = 'msaview-ortholog-source'\n\nconst orthologSourceLabels: Record<OrthologSource, string> = {\n ncbi: 'NCBI orthologs',\n panther: 'PANTHER',\n uniref: 'UniRef cluster',\n}\n\nconst orthologSources = Object.keys(orthologSourceLabels) as OrthologSource[]\n\n// another plugin version on the same origin may have stored a source this one\n// lacks, and the tab indexes its hints by it\nexport function validOrthologSource(stored: unknown): OrthologSource {\n return orthologSources.find(s => s === stored) ?? 'ncbi'\n}\n\nexport function useStoredOrthologSource() {\n const [stored, setStored] = useLocalStorage<unknown>(\n ORTHOLOG_SOURCE_STORAGE_KEY,\n 'ncbi',\n )\n return [\n validOrthologSource(stored),\n (source: OrthologSource) => {\n setStored(source)\n },\n ] as const\n}\n\n// Which species a source can answer for, in the words a reader picking one\n// needs: NCBI's ortholog sets stop at vertebrates and insects, PANTHER's run\n// from human to yeast and Arabidopsis, and a UniRef cluster is every UniProtKB\n// entry within 50% identity of the query, whatever it came from.\nconst hints: Record<OrthologSource, string> = {\n ncbi: 'vertebrates and insects',\n panther: 'also yeast, worm, fly and plants',\n uniref: 'all of UniProtKB within 50% identity',\n}\n\nexport default function OrthologSourceSelect({\n value,\n onChange,\n className,\n}: {\n value: OrthologSource\n onChange: (val: OrthologSource) => void\n className?: string\n}) {\n return (\n <TextField2\n variant=\"outlined\"\n label=\"Source\"\n className={className}\n select\n value={value}\n helperText={hints[value]}\n onChange={event => {\n onChange(event.target.value as OrthologSource)\n }}\n >\n {orthologSources.map(val => (\n <MenuItem value={val} key={val}>\n {orthologSourceLabels[val]}\n </MenuItem>\n ))}\n </TextField2>\n )\n}\n", "import React, { useState } from 'react'\n\nimport TextField2 from '../../../components/TextField2'\nimport {\n resolveAssemblySpecies,\n resolveTaxId,\n} from '../../../utils/ncbiTaxonomy'\nimport { fetchTaxonomyInfo } from '../../../utils/taxonomyNames'\nimport { useDebounced, useFetch } from '../../../utils/useFetch'\n\nasync function describeTaxon(query: string, signal: AbortSignal) {\n const taxId = await resolveTaxId(query, signal)\n if (!taxId) {\n throw new Error(`No NCBI taxon matches \"${query}\"`)\n }\n const failures: unknown[] = []\n const info = (\n await fetchTaxonomyInfo([taxId], signal, e => {\n failures.push(e)\n })\n ).get(taxId)\n // a throttle would otherwise read as a taxon NCBI has no name for\n if (!info && failures.length > 0) {\n throw new Error(`NCBI did not answer for the name of taxon ${taxId}`, {\n cause: failures[0],\n })\n }\n const label = [info?.sciname, info?.commonName && `(${info.commonName})`]\n .filter(Boolean)\n .join(' ')\n return { taxId, label: label || `taxon ${taxId}` }\n}\n\n/**\n * The species the query gene came from, as free text resolved against NCBI's\n * taxonomy rather than picked from a fixed list.\n *\n * The resolved taxon is shown back as helper text, which is the whole point of\n * resolving on a debounce instead of on submit: a typo resolves to some other\n * organism rather than to nothing, and the only place that surfaces is the gene\n * lookup, as \"could not resolve NLRP1 in taxon 9986\".\n */\nexport default function QuerySpeciesSelect({\n value,\n assemblyName,\n onChange,\n className,\n}: {\n value: number\n assemblyName?: string\n onChange: (taxId: number) => void\n className?: string\n}) {\n // undefined until the user types, which is what makes the two lookups\n // exclusive rather than both firing on open\n const [typed, setTyped] = useState<string>()\n const debounced = useDebounced(typed, 400)\n\n // Opening on `human` for everyone is the same silent wrong answer the fixed\n // species list gave: on a mouse assembly the gene symbol resolves to the HUMAN\n // gene, and the excluded taxon is human too, so mouse appears twice. The\n // assembly being browsed is the one thing here that already knows the answer.\n //\n // db=assembly already returns the taxon id, so this is the whole lookup \u2014 the\n // taxonomy chain below would be two more requests for an answer we hold. That\n // is not just waste: eutils allows 3 requests a second and throttles by\n // answering without CORS headers, so all four fired on open and the browser\n // reported the throttle as \"blocked by CORS policy\" in the helper text.\n const { data: fromAssembly } = useFetch(\n assemblyName && typed === undefined\n ? [assemblyName, 'assembly-species']\n : null,\n signal => resolveAssemblySpecies(assemblyName!, signal),\n {\n onSuccess: found => {\n if (found) {\n onChange(found.taxId)\n }\n },\n },\n )\n\n const { data: fromText, error } = useFetch(\n debounced?.trim() ? [debounced.trim(), 'taxon'] : null,\n signal => describeTaxon(debounced!, signal),\n {\n onSuccess: ({ taxId }) => {\n onChange(taxId)\n },\n },\n )\n\n // derived, not seeded through an effect: whatever the user typed wins, and\n // until they type anything the assembly's species does, so a lookup that\n // lands while they are mid-word cannot overwrite the field\n const text = typed ?? fromAssembly?.speciesName ?? 'human'\n const resolved =\n typed === undefined ? fromAssembly?.speciesName : fromText?.label\n\n return (\n <TextField2\n variant=\"outlined\"\n label=\"Query species\"\n className={className}\n value={text}\n onChange={event => {\n setTyped(event.target.value)\n }}\n error={!!error}\n helperText={\n error\n ? `${error}`\n : (resolved ?? `the species this gene is from (taxon ${value})`)\n }\n />\n )\n}\n", "import { eutilsJson, eutilsUrl } from './eutils'\n\n/**\n * Free text -> NCBI taxon id. A bare number is taken as the id itself; anything\n * else is searched against db=taxonomy, which resolves a scientific name\n * (`Danio rerio`), a common name (`zebrafish`) and a genus alike.\n *\n * This replaces a fixed list of species the dialog used to offer. The query\n * taxon has to match the assembly the user is browsing -- `resolveGeneId`\n * searches `SYMBOL[Gene Name] AND <taxid>[taxid]` -- so a list that stops at 23\n * species silently resolves the wrong organism's gene for anyone outside it.\n */\nexport async function resolveTaxId(query: string, signal?: AbortSignal) {\n const term = query.trim()\n if (!term) {\n return undefined\n }\n if (/^\\d+$/.test(term)) {\n return Number(term)\n }\n const json = await eutilsJson<{ esearchresult?: { idlist?: string[] } }>(\n eutilsUrl('esearch', {\n db: 'taxonomy',\n term,\n retmax: '1',\n retmode: 'json',\n }),\n { signal },\n )\n const id = json.esearchresult?.idlist?.[0]\n return id ? Number(id) : undefined\n}\n\ninterface AssemblySummary {\n result?: Record<string, { speciestaxid?: string; speciesname?: string }>\n}\n\n/**\n * A JBrowse assembly name -> the species it is an assembly of.\n *\n * The dialog's query species used to open on `human` whoever was browsing, and\n * that is the same silent wrong answer the 23-species list gave: `resolveGeneId`\n * searches `SYMBOL[Gene Name] AND <taxid>[taxid]`, so a user right-clicking a\n * mouse gene got the HUMAN gene of that symbol, its orthologs, and mouse twice\n * \u2014 once as the query row and once as an ortholog, because the excluded taxon\n * was the wrong one. A symbol with no human counterpart failed outright.\n *\n * db=assembly indexes the names JBrowse configs actually carry: hg38, GRCh38,\n * mm39, danRer11, dm6 and sacCer3 all resolve, and so do RefSeq/GenBank\n * accessions. An assembly NCBI has never heard of resolves to nothing and the\n * caller keeps its own default, so this can only improve on guessing.\n */\nexport async function resolveAssemblySpecies(\n assemblyName: string,\n signal?: AbortSignal,\n) {\n const term = assemblyName.trim()\n if (!term) {\n return undefined\n }\n const search = await eutilsJson<{ esearchresult?: { idlist?: string[] } }>(\n eutilsUrl('esearch', {\n db: 'assembly',\n term,\n retmax: '1',\n retmode: 'json',\n }),\n { signal },\n )\n const uid = search.esearchresult?.idlist?.[0]\n if (!uid) {\n return undefined\n }\n const summary = await eutilsJson<AssemblySummary>(\n eutilsUrl('esummary', { db: 'assembly', id: uid, retmode: 'json' }),\n { signal },\n )\n const record = summary.result?.[uid]\n const taxId = Number(record?.speciestaxid)\n return record?.speciesname && taxId\n ? { taxId, speciesName: record.speciesname }\n : undefined\n}\n", "import React, { useMemo, useState } from 'react'\n\nimport { LoadingEllipses, SanitizedHTML } from '@jbrowse/core/ui'\nimport { getEnv, getSession } from '@jbrowse/core/util'\nimport { MenuItem, Typography } from '@mui/material'\nimport { observer } from 'mobx-react'\nimport { makeStyles } from 'tss-react/mui'\n\nimport TextField2 from '../../../components/TextField2'\nimport { useFetch } from '../../../utils/useFetch'\nimport { resolveQueryRowName, useQueryRowName } from '../../useQueryRowName'\nimport {\n featureMatchesId,\n getGeneDisplayName,\n getLinearGenomeView,\n getTranscriptDisplayName,\n} from '../../util'\nimport LaunchPanelContent from '../LaunchPanelContent'\nimport QueryRowSelector from '../QueryRowSelector'\nimport SequenceStatusMessage from '../SequenceStatus'\nimport SubmitCancelActions from '../SubmitCancelActions'\nimport TranscriptSelector from '../TranscriptSelector'\nimport { launchConnectedView, useLaunchSubmit } from '../launchConnectedView'\nimport { useTranscriptSelection } from '../useTranscriptSelection'\nimport { fetchMSA, fetchMSAList } from './fetchMSAData'\nimport { readMsaDatasets } from './types'\n\nimport type { AbstractTrackModel, Feature } from '@jbrowse/core/util'\n\nconst useStyles = makeStyles()({\n selectedContainer: {\n marginTop: 50,\n },\n})\n\nconst PreLoadedMSA = observer(function ({\n model,\n feature,\n handleClose,\n preferredTranscriptId,\n}: {\n model: AbstractTrackModel\n feature: Feature\n handleClose: () => void\n /** the isoform the user right-clicked, preselected in the picker */\n preferredTranscriptId?: string\n}) {\n const session = getSession(model)\n const view = getLinearGenomeView(model)\n const { classes } = useStyles()\n const { pluginManager } = getEnv(model)\n const { assemblyNames } = view\n const { launchError, submit } = useLaunchSubmit(handleClose)\n\n const datasets = readMsaDatasets(session.jbrowse)\n const [selectedDatasetId, setSelectedDatasetId] = useState(\n datasets?.[0]?.datasetId,\n )\n const selectedDataset = datasets?.find(d => d.datasetId === selectedDatasetId)\n const {\n data: msaList,\n isLoading: msaListLoading,\n error: msaListFetchError,\n } = useFetch(\n selectedDataset ? `${selectedDataset.datasetId}-msa-list` : null,\n () => fetchMSAList({ config: selectedDataset!.adapter, pluginManager }),\n )\n\n const transcriptSelection = useTranscriptSelection({\n feature,\n view,\n validIds: msaList,\n preferredTranscriptId,\n })\n const { selectedTranscript, proteinSequence, sequenceStatus } =\n transcriptSelection\n\n // the dataset's name for this transcript, which a track is free not to use\n // as the feature's own id\n const msaId = selectedTranscript\n ? msaList?.find(id => featureMatchesId(selectedTranscript, id))\n : undefined\n const {\n data: msaData,\n isLoading: msaDataLoading,\n error: msaDataFetchError,\n } = useFetch(\n msaId && selectedDataset\n ? `${selectedDataset.datasetId}-${msaId}-msa`\n : null,\n () =>\n fetchMSA({\n msaId: msaId!,\n config: selectedDataset!.adapter,\n pluginManager,\n }),\n )\n\n const msaText = useMemo(\n () =>\n msaData?.map(r => `>${r.get('refName')}\\n${r.get('seq')}`).join('\\n') ??\n '',\n [msaData],\n )\n\n // The dataset's row for this transcript used to be assumed -- the launch\n // named `<transcriptId>_<assembly>` and hoped the file agreed. Nothing\n // checked, and a name the alignment does not carry fails silently: the view\n // opens, renders, and never navigates. The row is found by sequence instead,\n // the same way the Manual tab finds it.\n const queryRow = useQueryRowName(msaText, proteinSequence)\n\n // The name this panel used to launch with unconditionally. A dataset built to\n // that convention does carry the row, so it is worth falling back to when the\n // residues do not match closely enough to find it -- but only when the\n // alignment really has it, which is the check the old code never made.\n const querySeqName = resolveQueryRowName(\n queryRow,\n `${msaId ?? ''}_${assemblyNames[0] ?? ''}`,\n )\n\n const e =\n msaListFetchError ??\n msaDataFetchError ??\n transcriptSelection.error ??\n launchError\n return (\n <>\n <LaunchPanelContent error={e}>\n <TextField2\n select\n label=\"Select MSA dataset\"\n value={selectedDatasetId}\n onChange={event => {\n setSelectedDatasetId(event.target.value)\n }}\n >\n {datasets?.map(d => (\n <MenuItem key={d.datasetId} value={d.datasetId}>\n {d.name}\n </MenuItem>\n ))}\n </TextField2>\n\n {selectedDataset ? (\n <div className={classes.selectedContainer}>\n {!msaListLoading && msaDataLoading ? (\n <LoadingEllipses\n variant=\"h6\"\n message={`Loading MSA for ${getTranscriptDisplayName(selectedTranscript) || msaId}`}\n />\n ) : null}\n {msaListLoading ? (\n <LoadingEllipses\n variant=\"h6\"\n message={`Loading available MSAs for (${selectedDataset.name})`}\n />\n ) : null}\n\n {msaList ? (\n <div>\n <SanitizedHTML html={selectedDataset.description} />\n <TranscriptSelector\n feature={feature}\n {...transcriptSelection}\n />\n {msaText ? (\n <QueryRowSelector {...queryRow} querySeqName={querySeqName} />\n ) : null}\n </div>\n ) : null}\n </div>\n ) : null}\n </LaunchPanelContent>\n\n <SubmitCancelActions\n model={model}\n hint={\n msaDataLoading ? (\n <LoadingEllipses message=\"Loading alignment\" />\n ) : !!msaData?.length && !querySeqName ? (\n <Typography color=\"textSecondary\" variant=\"body2\">\n no row matches this transcript\n </Typography>\n ) : (\n <SequenceStatusMessage status={sequenceStatus} />\n )\n }\n // launching without a query row opens a view that renders and then\n // never navigates, which reads as a broken feature rather than a\n // dataset that does not cover this gene\n submitDisabled={\n !selectedTranscript || !msaData?.length || !querySeqName\n }\n onSubmit={placement => {\n if (selectedTranscript && msaText) {\n submit(() =>\n launchConnectedView({\n view,\n feature: selectedTranscript,\n placement,\n displayName: getGeneDisplayName(selectedTranscript),\n drawNodeBubbles: false,\n labelsAlignRight: true,\n showBranchLen: false,\n colWidth: 10,\n rowHeight: 12,\n colorSchemeName: 'percent_identity_dynamic',\n querySeqName,\n querySeqOffset: queryRow.querySeqOffset,\n data: { msa: msaText },\n }),\n )\n }\n }}\n onCancel={handleClose}\n />\n </>\n )\n})\n\nexport default PreLoadedMSA\n", "import { getAdapter } from '@jbrowse/core/data_adapters/dataAdapterCache'\n\nimport type PluginManager from '@jbrowse/core/PluginManager'\nimport type { AnyConfigurationModel } from '@jbrowse/core/configuration'\nimport type { Feature } from '@jbrowse/core/util'\n\ninterface MsaDataAdapter {\n getMSAList(): Promise<string[]>\n getMSA(msaId: string): Promise<Feature[]>\n}\n\nasync function getMsaAdapter(\n pluginManager: PluginManager,\n config: AnyConfigurationModel,\n) {\n const result = await getAdapter(pluginManager, 'msa', config)\n return result.dataAdapter as unknown as MsaDataAdapter\n}\n\nexport async function fetchMSAList({\n config,\n pluginManager,\n}: {\n config: AnyConfigurationModel\n pluginManager: PluginManager\n}): Promise<string[]> {\n const adapter = await getMsaAdapter(pluginManager, config)\n return adapter.getMSAList()\n}\n\nexport async function fetchMSA({\n config,\n pluginManager,\n msaId,\n}: {\n config: AnyConfigurationModel\n pluginManager: PluginManager\n msaId: string\n}): Promise<Feature[]> {\n const adapter = await getMsaAdapter(pluginManager, config)\n return adapter.getMSA(msaId)\n}\n", "import { readConfObject } from '@jbrowse/core/configuration'\n\nimport type { AnyConfigurationModel } from '@jbrowse/core/configuration'\n\nexport interface Dataset {\n datasetId: string\n name: string\n description?: string\n adapter: AnyConfigurationModel\n}\n\nexport function readMsaDatasets(jbrowse: AnyConfigurationModel) {\n return readConfObject(jbrowse, ['msa', 'datasets']) as Dataset[] | undefined\n}\n", "import React, { useState } from 'react'\n\n// Once visited, a panel stays mounted and is hidden with the `hidden` attribute.\n// Unmounting it discarded whatever the user had typed and re-ran every fetch the\n// panel makes on the way back, so switching tabs to compare two of them cost an\n// EBI round trip and the pasted alignment.\n//\n// Lazy on first visit rather than mounted up front, because a panel mounts\n// fetches of its own: rendering all four on open would query the MSA dataset\n// adapter and the BLAST cache for tabs nobody looked at.\nexport default function TabPanel({\n children,\n value,\n index,\n}: {\n children?: React.ReactNode\n index: number | string\n value: number | string\n}) {\n const active = value === index\n const [visited, setVisited] = useState(active)\n if (active && !visited) {\n setVisited(true)\n }\n return (\n <div role=\"tabpanel\" hidden={!active}>\n {visited || active ? children : null}\n </div>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["require_dataAdapterCache", "__commonJSMin", "exports", "module", "import_react", "import_ui", "import_util", "import_material", "import_react", "import_jsx_runtime", "Settings_default", "_jsx", "import_material", "import_mui", "import_react", "import_material", "import_mobx_react", "import_mui", "import_react", "import_material", "TextField2", "children", "rest", "React", "TextField2_default", "import_react", "import_ui", "import_material", "import_mui", "useStyles", "LaunchPanelContent", "error", "children", "classes", "React", "import_react", "import_ui", "import_material", "SequenceStatusMessage", "status", "React", "import_react", "import_util", "import_material", "import_react", "LaunchPlacementContext", "LaunchPlacementProvider", "children", "state", "readLaunchPlacement", "React", "useLaunchPlacement", "shared", "own", "PlacementToggle", "checked", "onChange", "React", "event", "SubmitCancelActions", "onSubmit", "onCancel", "submitDisabled", "hint", "submitLabel", "model", "sideBySide", "setSideBySide", "useLaunchPlacement", "offerPlacement", "sessionSupportsPlacement", "placement", "writeLaunchPlacement", "readLaunchPlacement", "import_react", "import_material", "import_mui", "import_react", "import_mui", "useStyles", "ReadOnlyTextField2", "value", "classes", "React", "TextField2_default", "useStyles", "TranscriptSelector", "feature", "options", "selectedId", "selectedTranscript", "setSelectedId", "proteinSequence", "sequenceStatus", "validIds", "classes", "showSequence", "setShowSequence", "React", "getGeneDisplayName", "event", "val", "inSet", "id", "featureMatchesId", "len", "mod", "getTranscriptLength", "getId", "getTranscriptDisplayName", "ReadOnlyTextField2", "import_react", "import_util", "builtAlignmentLook", "launchConnectedView", "view", "feature", "placement", "snapshot", "launchMsaView", "useLaunchSubmit", "handleClose", "launchError", "setLaunchError", "launching", "launch", "e", "import_react", "import_react", "import_util", "import_translateTranscript", "import_react", "isNil", "k", "serializeKey", "key", "useFetch", "fetcher", "onSuccess", "serialized", "nonce", "setNonce", "settled", "setSettled", "attempt", "current", "answersThisKey", "latest", "controller", "data", "error", "n", "useDebounced", "value", "ms", "debounced", "setDebounced", "timer", "useFeatureSequence", "view", "feature", "assemblyName", "sequence", "error", "isLoading", "useFetch", "start", "end", "refName", "fetchSeq", "pickSelectedId", "currentId", "options", "validIds", "isValid", "opt", "id", "featureMatchesId", "current", "getId", "firstValid", "sequenceStatus", "error", "isLoading", "proteinSequence", "useTranscriptSelection", "feature", "view", "preferredTranscriptId", "getSortedTranscriptFeatures", "selectedId", "setSelectedId", "validatedSelectedId", "selectedTranscript", "val", "useFeatureSequence", "import_react", "import_ui", "import_jsx_runtime", "Delete_default", "_jsx", "import_material", "import_mobx_react", "import_mui", "useStyles", "getResultDisplayName", "result", "parts", "p", "describeSearch", "CachedBlastResults", "model", "handleClose", "feature", "results", "handleDelete", "handleClearAll", "classes", "view", "getLinearGenomeView", "operationError", "setOperationError", "sideBySide", "useLaunchPlacement", "handleUseCached", "cached", "transcriptId", "msa", "tree", "treeMetadata", "launchConnectedView", "getSortedTranscriptFeatures", "t", "featureMatchesId", "builtAlignmentLook", "e", "React", "err", "Delete_default", "CachedBlastResults_default", "import_react", "import_material", "MsaAlgorithmSelect", "value", "onChange", "className", "React", "TextField2_default", "event", "msaAlgorithms", "val", "msaAlgorithmLabels", "SEARCH_CHOICE_STORAGE_KEY", "MSA_ALGORITHM_STORAGE_KEY", "defaultSearch", "defaultSearchFor", "defaultMsaAlgorithm", "validSearchChoice", "stored", "program", "database", "known", "searchPrograms", "p", "databaseOptionsFor", "d", "validMsaAlgorithm", "msaAlgorithms", "a", "useStoredSearchChoice", "setStored", "useLocalStorage", "choice", "useStoredMsaAlgorithm", "algorithm", "useCachedBlastResults", "geneIds", "results", "error", "isLoading", "mutate", "useFetch", "getAllCachedResults", "r", "id", "deleteCachedResult", "useStyles", "BlastAutomaticPanel", "handleClose", "feature", "model", "children", "preferredTranscriptId", "classes", "view", "getLinearGenomeView", "launchError", "submit", "useLaunchSubmit", "search", "setSearch", "useStoredSearchChoice", "selectedMsaAlgorithm", "setSelectedMsaAlgorithm", "useStoredMsaAlgorithm", "maxHits", "setMaxHits", "defaultMaxHits", "hitCount", "hitCountValid", "isPhmmer", "geneIds", "getGeneIdentifiers", "cached", "useCachedBlastResults", "transcriptSelection", "useTranscriptSelection", "selectedTranscript", "proteinSequence", "sequenceStatus", "e", "React", "LaunchPanelContent", "TextField2_default", "event", "defaultSearchFor", "searchPrograms", "val", "searchProgramLabels", "databaseOptionsFor", "databaseLabel", "MsaAlgorithmSelect", "TranscriptSelector", "ExpandMore_default", "CachedBlastResults_default", "SubmitCancelActions", "SequenceStatusMessage", "placement", "blastParams", "launchConnectedView", "getBlastViewTitle", "builtAlignmentLook", "BlastAutomaticPanel_default", "import_react", "import_util", "import_material", "import_mobx_react", "import_mui", "import_react", "normalize", "seq", "cleanProteinSequence", "identityOverOverlap", "a", "b", "len", "same", "i", "SIMILARITY_FLOOR", "PARTIAL_COVERAGE_FLOOR", "findQueryRow", "msaText", "proteinSequence", "parsed", "parseMSA", "names", "query", "bestMatch", "candidates", "name", "row", "getUngappedSequence", "contained", "containing", "coverage", "identity", "order", "resolveQueryRowName", "queryRow", "fallback", "useQueryRowName", "msaText", "proteinSequence", "override", "setOverride", "names", "match", "findQueryRow", "picked", "querySeqName", "import_react", "import_material", "import_mui", "useStyles", "partialCoverage", "identity", "offset", "covering", "QueryRowSelector", "names", "detected", "querySeqName", "setQuerySeqName", "isAutoDetected", "classes", "React", "TextField2_default", "event", "name", "useStyles", "BlastManualPanel", "handleClose", "feature", "model", "children", "preferredTranscriptId", "classes", "view", "getLinearGenomeView", "launchError", "submit", "useLaunchSubmit", "msaText", "setMsaText", "treeText", "setTreeText", "transcriptSelection", "useTranscriptSelection", "proteinSequence", "selectedTranscript", "error", "queryRow", "useQueryRowName", "s2", "cleanProteinSequence", "link", "BASE_BLAST_URL", "link2", "React", "LaunchPanelContent", "TranscriptSelector", "ExternalLink", "TextField2_default", "event", "QueryRowSelector", "SubmitCancelActions", "placement", "launchConnectedView", "getGeneDisplayName", "BlastManualPanel_default", "import_react", "import_material", "BlastMethodSelector", "lookupMethod", "setLookupMethod", "React", "event", "import_react", "import_material", "import_mui", "useStyles", "BlastSettingsDialog", "handleClose", "ebiEmail", "classes", "tempEbiEmail", "setTempEbiEmail", "React", "TextField2_default", "e", "DEFAULT_EBI_EMAIL", "useStyles", "panelMap", "BlastAutomaticPanel_default", "BlastManualPanel_default", "BlastPanel", "handleClose", "model", "feature", "preferredTranscriptId", "lookupMethod", "setLookupMethod", "ebiEmail", "setEbiEmail", "useLocalStorage", "EBI_EMAIL_STORAGE_KEY", "DEFAULT_EBI_EMAIL", "settingsOpen", "setSettingsOpen", "classes", "Panel", "React", "Settings_default", "BlastMethodSelector", "BlastSettingsDialog", "settings", "import_react", "import_material", "HelpDialog", "HelpButton", "show", "setShow", "React", "Help_default", "import_react", "import_ui", "import_io", "import_material", "import_mobx_react", "import_mui", "useMsaFileText", "location", "debounced", "useDebounced", "data", "error", "isLoading", "useFetch", "useStyles", "ManualMSALoader", "model", "feature", "handleClose", "preferredTranscriptId", "view", "getLinearGenomeView", "classes", "launchError", "submit", "useLaunchSubmit", "inputMethod", "setInputMethod", "msaText", "setMsaText", "treeText", "setTreeText", "msaFileLocation", "setMsaFileLocation", "treeFileLocation", "setTreeFileLocation", "transcriptSelection", "useTranscriptSelection", "selectedTranscript", "proteinSequence", "sequenceStatus", "msaFile", "queryRow", "useQueryRowName", "e", "React", "LaunchPanelContent", "event", "TextField2_default", "TranscriptSelector", "QueryRowSelector", "SubmitCancelActions", "SequenceStatusMessage", "placement", "launchConnectedView", "getGeneDisplayName", "ManualMSALoader_default", "import_react", "import_material", "import_mobx_react", "import_mui", "import_react", "import_material", "ORTHOLOG_SOURCE_STORAGE_KEY", "orthologSourceLabels", "orthologSources", "validOrthologSource", "stored", "s", "useStoredOrthologSource", "setStored", "useLocalStorage", "source", "hints", "OrthologSourceSelect", "value", "onChange", "className", "React", "TextField2_default", "event", "val", "import_react", "resolveTaxId", "query", "signal", "term", "id", "eutilsJson", "eutilsUrl", "resolveAssemblySpecies", "assemblyName", "uid", "record", "taxId", "describeTaxon", "query", "signal", "taxId", "resolveTaxId", "failures", "info", "fetchTaxonomyInfo", "e", "label", "QuerySpeciesSelect", "value", "assemblyName", "onChange", "className", "typed", "setTyped", "debounced", "useDebounced", "fromAssembly", "useFetch", "resolveAssemblySpecies", "found", "fromText", "error", "text", "resolved", "React", "TextField2_default", "event", "useStyles", "rowsHint", "rows", "OrthologPanel", "handleClose", "feature", "model", "preferredTranscriptId", "classes", "view", "getLinearGenomeView", "launchError", "submit", "useLaunchSubmit", "taxId", "setTaxId", "source", "setSource", "useStoredOrthologSource", "msaAlgorithm", "setMsaAlgorithm", "useStoredMsaAlgorithm", "maxSpecies", "setMaxSpecies", "defaultMaxSpecies", "geneCandidates", "getGeneIdentifiers", "transcriptSelection", "useTranscriptSelection", "selectedTranscript", "proteinSequence", "sequenceStatus", "e", "rowCount", "rowCountValid", "React", "LaunchPanelContent", "OrthologSourceSelect", "QuerySpeciesSelect", "MsaAlgorithmSelect", "TextField2_default", "event", "TranscriptSelector", "SubmitCancelActions", "SequenceStatusMessage", "placement", "launchConnectedView", "getGeneDisplayName", "getTranscriptDisplayName", "builtAlignmentLook", "OrthologPanel_default", "import_react", "import_ui", "import_util", "import_material", "import_mobx_react", "import_mui", "import_dataAdapterCache", "getMsaAdapter", "pluginManager", "config", "fetchMSAList", "fetchMSA", "msaId", "import_configuration", "readMsaDatasets", "jbrowse", "useStyles", "PreLoadedMSA", "model", "feature", "handleClose", "preferredTranscriptId", "session", "view", "getLinearGenomeView", "classes", "pluginManager", "assemblyNames", "launchError", "submit", "useLaunchSubmit", "datasets", "readMsaDatasets", "selectedDatasetId", "setSelectedDatasetId", "selectedDataset", "d", "msaList", "msaListLoading", "msaListFetchError", "useFetch", "fetchMSAList", "transcriptSelection", "useTranscriptSelection", "selectedTranscript", "proteinSequence", "sequenceStatus", "msaId", "id", "featureMatchesId", "msaData", "msaDataLoading", "msaDataFetchError", "fetchMSA", "msaText", "r", "queryRow", "useQueryRowName", "querySeqName", "resolveQueryRowName", "e", "React", "LaunchPanelContent", "TextField2_default", "event", "getTranscriptDisplayName", "TranscriptSelector", "QueryRowSelector", "SubmitCancelActions", "SequenceStatusMessage", "placement", "launchConnectedView", "getGeneDisplayName", "PreLoadedMSADataPanel_default", "import_react", "TabPanel", "children", "value", "index", "active", "visited", "setVisited", "React", "LaunchMsaViewDialog", "handleClose", "feature", "model", "preferredTranscriptId", "session", "hasPreloadedDatasets", "readMsaDatasets", "value", "setValue", "React", "LaunchPlacementProvider", "_event", "newValue", "HelpButton", "TabPanel", "OrthologPanel_default", "BlastPanel", "PreLoadedMSADataPanel_default", "ManualMSALoader_default"]
|
|
7
7
|
}
|