jbrowse-plugin-msaview 4.0.0 → 5.1.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/AddHighlightModel/index.js +2 -11
- package/dist/LaunchMsaView/codingFeature.d.ts +0 -12
- package/dist/LaunchMsaView/codingFeature.js +0 -30
- package/dist/LaunchMsaView/codingFeature.test.js +1 -48
- package/dist/LaunchMsaView/components/fetchSeq.d.ts +1 -1
- package/dist/LaunchMsaView/components/fetchSeq.js +3 -10
- package/dist/LaunchMsaView/components/useFeatureSequence.d.ts +1 -1
- package/dist/LaunchMsaView/index.js +2 -12
- package/dist/LaunchMsaView/launchTarget.d.ts +7 -30
- package/dist/LaunchMsaView/launchTarget.js +10 -49
- package/dist/LaunchMsaView/launchTarget.test.js +17 -109
- package/dist/MsaViewPanel/model.d.ts +8 -8
- package/dist/MsaViewPanel/model.js +3 -10
- package/dist/MsaViewPanel/resolveConnectedTranscript.js +1 -7
- package/dist/chunks/{LaunchMsaViewDialog-54LBEZHK.js → LaunchMsaViewDialog-WBXEEHJL.js} +2 -2
- package/dist/chunks/chunk-DECSTFAT.js +2 -0
- package/dist/chunks/chunk-DECSTFAT.js.map +7 -0
- package/dist/chunks/chunk-MHBTV7BZ.js +3 -0
- package/dist/chunks/chunk-MHBTV7BZ.js.map +7 -0
- package/dist/chunks/{model-KEZXRCK6.js → model-7VBTOIJX.js} +4 -4
- package/dist/chunks/model-7VBTOIJX.js.map +7 -0
- package/dist/index.js +1 -1
- package/dist/jbrowse-plugin-msaview.esm.js +2 -2
- package/dist/jbrowse-plugin-msaview.esm.js.map +3 -3
- package/dist/utils/workspaces.js +26 -33
- package/dist/utils/workspaces.test.js +22 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -2
- package/src/AddHighlightModel/index.tsx +5 -15
- package/src/LaunchMsaView/codingFeature.test.ts +1 -64
- package/src/LaunchMsaView/codingFeature.ts +0 -38
- package/src/LaunchMsaView/components/fetchSeq.ts +3 -20
- package/src/LaunchMsaView/index.ts +2 -12
- package/src/LaunchMsaView/launchTarget.test.ts +20 -133
- package/src/LaunchMsaView/launchTarget.ts +18 -70
- package/src/MsaViewPanel/model.ts +3 -10
- package/src/MsaViewPanel/resolveConnectedTranscript.ts +1 -7
- package/src/index.ts +1 -1
- package/src/utils/workspaces.test.ts +26 -0
- package/src/utils/workspaces.ts +35 -33
- package/src/version.ts +1 -1
- package/dist/chunks/chunk-EO7URJUB.js +0 -2
- package/dist/chunks/chunk-EO7URJUB.js.map +0 -7
- package/dist/chunks/chunk-RKVHQK52.js +0 -3
- package/dist/chunks/chunk-RKVHQK52.js.map +0 -7
- package/dist/chunks/model-KEZXRCK6.js.map +0 -7
- /package/dist/chunks/{LaunchMsaViewDialog-54LBEZHK.js.map → LaunchMsaViewDialog-WBXEEHJL.js.map} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{a as Ft}from"./chunk-6YFCSBEE.js";import{D as Et,a as G,c as bt,d as de,e as pe,f as fe,g as te,h as vt,i as qe,j as Ee,k as xe,l as or,m as Mt,q as kt,r as ot,s as _e,v as Ve,x as qt}from"./chunk-
|
|
1
|
+
import{a as Ft}from"./chunk-6YFCSBEE.js";import{D as Et,a as G,c as bt,d as de,e as pe,f as fe,g as te,h as vt,i as qe,j as Ee,k as xe,l as or,m as Mt,q as kt,r as ot,s as _e,v as Ve,x as qt}from"./chunk-MHBTV7BZ.js";import{f as ue,g as St,h as Be,j as tt,k as De,l as At,m as Oe,n as Ct,o as Lt,q as je,r as $e,s as Nt,u as Pt,v as It}from"./chunk-PJZ3XTMG.js";import{a as yt,b as Bt,c as rr}from"./chunk-YUKJI2AH.js";import"./chunk-QAC6JSDZ.js";import{a as wt,b as ke,c as xt,d as Tt}from"./chunk-DECSTFAT.js";import{a as V}from"./chunk-NSASZ5FM.js";import{a as be,c as Ie,d as gt}from"./chunk-IBBQUV2I.js";import{a as tr}from"./chunk-2IWD4OO4.js";import"./chunk-73KAPCJ2.js";import{a as ve}from"./chunk-CVLB4VFP.js";import{a as we}from"./chunk-DNFD5II2.js";import{a as k}from"./chunk-BX4Z274Q.js";import{a as h}from"./chunk-J6KYLXRD.js";import{a as er,b as a}from"./chunk-FY3BTKY4.js";var Go=er((cs,Vo)=>{Vo.exports=JBrowseExports["@jbrowse/core/data_adapters/dataAdapterCache"]});var L=a(h()),Xo=a(we()),Zo=a(be()),ye=a(k());var K=a(h());var Dt=a(gt(),1),Ot=(0,Ie.createSvgIcon)((0,Dt.jsx)("path",{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"}),"Settings");var Ke=a(k()),Co=a(V());var w=a(h());var U=a(k()),fo=a(ve()),ho=a(V());var rt=a(h()),jt=a(k());function nr({children:e,...t}){return rt.default.createElement("div",null,rt.default.createElement(jt.TextField,{...t},e))}var g=nr;var nt=a(h()),$t=a(we()),_t=a(k()),Vt=a(V()),ar=(0,Vt.makeStyles)()({dialogContent:{width:"80em"}});function J({error:e,children:t}){let{classes:o}=ar();return nt.default.createElement(_t.DialogContent,{className:o.dialogContent},e?nt.default.createElement($t.ErrorMessage,{error:e}):null,t)}var at=a(h()),Gt=a(we()),Qt=a(k());function se({status:e}){return e==="loading"?at.default.createElement(Gt.LoadingEllipses,{message:"Translating transcript"}):e==="missing"?at.default.createElement(Qt.Typography,{color:"textSecondary",variant:"body2"},"no coding sequence to align"):null}var me=a(h()),Ut=a(be()),le=a(k());var ie=a(h());var Ht=(0,ie.createContext)(void 0);function Wt({children:e}){let t=(0,ie.useState)(()=>ke()==="splitRight");return ie.default.createElement(Ht.Provider,{value:t},e)}function Ge(){let e=(0,ie.useContext)(Ht),t=(0,ie.useState)(()=>ke()==="splitRight");return e??t}function sr({checked:e,onChange:t}){return me.default.createElement(le.FormControlLabel,{label:"Open beside the genome view",control:me.default.createElement(le.Checkbox,{checked:e,onChange:o=>{t(o.target.checked)}})})}function Y({onSubmit:e,onCancel:t,submitDisabled:o,hint:r,submitLabel:n="Submit",cancelLabel:s="Cancel",model:i}){let[m,u]=Ge(),l=!!i&&wt((0,Ut.getSession)(i));return me.default.createElement(le.DialogActions,{sx:{flexWrap:"wrap",rowGap:1}},l?me.default.createElement(sr,{checked:m,onChange:u}):null,me.default.createElement("div",{style:{display:"flex",alignItems:"center",gap:8,marginLeft:"auto"}},r,me.default.createElement(le.Button,{sx:{flexShrink:0},color:"primary",variant:"contained",disabled:o,onClick:()=>{if(l){let p=m?"splitRight":"stack";xt(p),e(p)}else e(ke())}},n),me.default.createElement(le.Button,{sx:{flexShrink:0},color:"secondary",variant:"contained",onClick:()=>{t()}},s)))}var X=a(h()),Te=a(k()),Jt=a(V());var zt=a(h()),Kt=a(V());var ir=(0,Kt.makeStyles)()({textAreaFont:{fontFamily:"Courier New"}});function st({value:e}){let{classes:t}=ir();return zt.default.createElement(g,{variant:"outlined",multiline:!0,minRows:5,maxRows:10,fullWidth:!0,value:e,slotProps:{input:{readOnly:!0,classes:{input:t.textAreaFont}}}})}var lr=(0,Jt.makeStyles)()({flex:{display:"flex"},minWidth:{minWidth:300},centered:{alignContent:"center",marginLeft:20}});function Z({feature:e,options:t,selectedId:o,selectedTranscript:r,setSelectedId:n,proteinSequence:s,sequenceStatus:i="ready",validIds:m}){let{classes:u}=lr(),[l,p]=(0,X.useState)(!1);return X.default.createElement(X.default.Fragment,null,X.default.createElement("div",{className:u.flex},X.default.createElement(Te.TextField,{variant:"outlined",label:`Choose isoform of ${te(e)}`,helperText:"the query row, so the alignment stays linked to the genome view",select:!0,className:u.minWidth,value:o,onChange:d=>{n(d.target.value)}},t.map(d=>{let c=m?m.some(S=>pe(d,S)):!0,{len:x,mod:b}=bt(d);return X.default.createElement(Te.MenuItem,{value:de(d),key:d.id(),disabled:!c},fe(d)," (",x," aa)"," ",b?" (possible fragment)":"",m?c?" (has data)":" (no data)":"")})),X.default.createElement("div",{className:u.centered},X.default.createElement(Te.Button,{variant:"contained",color:"primary",onClick:()=>{p(!l)}},l?"Hide sequence":"Show sequence"))),l?X.default.createElement(st,{value:s?`>${fe(r)}
|
|
2
2
|
${s}`:i==="missing"?"This transcript has no coding sequence, so there is nothing to translate.":"Loading..."}):null)}var Yt=a(h()),Xt=a(be());var Me={drawNodeBubbles:!0,colWidth:10,rowHeight:12};function Q({view:e,feature:t,placement:o,...r}){return Tt((0,Xt.getSession)(e),{placement:o,connectedViewId:e.id,connectedFeature:t?.toJSON(),...r})}function oe(e){let[t,o]=(0,Yt.useState)();return{launchError:t,submit:r=>{o(void 0),r().then(e,n=>{console.error(n),o(n)})}}}var He=a(h());var Rt=a(be()),eo=a(or());var H=a(h()),Zt=e=>e==null||e===!1;function mr(e){return Zt(e)||Array.isArray(e)&&e.some(Zt)?null:JSON.stringify(e)}function W(e,t,{onSuccess:o}={}){let r=mr(e),[n,s]=(0,H.useState)(0),[i,m]=(0,H.useState)(),u=r===null?null:`${n}\0${r}`,l=i?.attempt===u,p=i?.question===r,d=(0,H.useRef)({fetcher:t,onSuccess:o});return(0,H.useEffect)(()=>{d.current={fetcher:t,onSuccess:o}}),(0,H.useEffect)(()=>{if(u===null||r===null)return;let c=new AbortController;return d.current.fetcher(c.signal).then(x=>{c.signal.aborted||(m({attempt:u,question:r,data:x}),d.current.onSuccess?.(x))}).catch(x=>{c.signal.aborted||m({attempt:u,question:r,error:x})}),()=>{c.abort()}},[u,r]),{data:p?i.data:void 0,error:l?i.error:void 0,isLoading:u!==null&&!l,mutate:(0,H.useCallback)(()=>{s(c=>c+1)},[])}}function Qe(e,t){let[o,r]=(0,H.useState)(e);return(0,H.useEffect)(()=>{let n=setTimeout(()=>{r(e)},t);return()=>{clearTimeout(n)}},[e,t]),o}function to({view:e,feature:t}){let o=e?.assemblyNames?.[0],{data:r,error:n,isLoading:s}=W(t&&o?[t.id(),o,"feature-sequence"]:null,async()=>{let{start:i,end:m,refName:u}=t.toJSON();return Mt({start:i,end:m,refName:u,assemblyName:o,session:(0,Rt.getSession)(e)})});return{proteinSequence:r&&t?(0,eo.translateTranscript)({transcript:t,...r})?.protein??"":"",sequence:r,error:n,isLoading:s}}function cr(e,t,o){if(!o?.length)return e;let r=i=>o.some(m=>pe(i,m)),n=t.find(i=>de(i)===e);if(n&&r(n))return e;let s=t.find(r);return s?de(s):e}function ur({error:e,isLoading:t,proteinSequence:o}){return e?"error":t?"loading":o?"ready":"missing"}function re({feature:e,view:t,validIds:o,preferredTranscriptId:r}){let n=(0,He.useMemo)(()=>qe(e),[e]),[s,i]=(0,He.useState)(()=>de(n.find(c=>pe(c,r??""))??n[0])),m=cr(s,n,o),u=n.find(c=>de(c)===m),{proteinSequence:l,error:p,isLoading:d}=to({view:t,feature:u});return{options:n,selectedId:m,setSelectedId:i,selectedTranscript:u,proteinSequence:l,error:p,isLoading:d,sequenceStatus:ur({error:p,isLoading:d,proteinSequence:l}),validIds:o}}var P=a(h()),ao=a(we());var oo=a(gt(),1),ro=(0,Ie.createSvgIcon)((0,oo.jsx)("path",{d:"M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6zM19 4h-3.5l-1-1h-5l-1 1H5v2h14z"}),"Delete");var q=a(k()),so=a(ve()),io=a(V());function We(e){let{data:t,error:o,isLoading:r,mutate:n}=W(`cached-blast-${e.join(",")}`,async()=>(await kt()).filter(i=>i.geneId&&e.includes(i.geneId)));return{results:t??[],error:o,isLoading:r,handleDelete:async s=>{await ot(s),n()},handleClearAll:async()=>{await Promise.all((t??[]).map(s=>ot(s.id))),n()}}}var dr=(0,io.makeStyles)()({header:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:8},resultList:{maxHeight:300,overflow:"auto"}});function no(e){let t=[e.geneName,e.transcriptName!==e.geneName?e.transcriptName:void 0].filter(o=>!!o);return t.length>0?t.join(" - "):e.geneId??e.transcriptId??"Unknown"}function pr(e){return[e.blastDatabase,e.searchProgram??e.blastProgram??"blastp",e.msaAlgorithm].filter(Boolean).join(" / ")}var fr=(0,so.observer)(function({model:e,handleClose:t,feature:o}){let{classes:r}=dr(),n=G(e),[s,i]=(0,P.useState)(),[m]=Ge(),u=(0,P.useMemo)(()=>xe(o),[o]),{results:l,error:p,isLoading:d,handleDelete:c,handleClearAll:x}=We(u),b=v=>{let{transcriptId:A,msa:N,tree:B,treeMetadata:F}=v;Q({view:n,feature:A?qe(o).find(C=>pe(C,A)):void 0,placement:m?"splitRight":"stack",displayName:`BLAST - ${no(v)}`,...Me,data:{msa:N,tree:B,treeMetadata:F}}).then(t,C=>{console.error(C),i(C)})},S=p??s;return S?P.default.createElement(ao.ErrorMessage,{error:S}):d?P.default.createElement(q.Typography,null,"Loading cached results..."):l.length===0?P.default.createElement(q.Typography,{color:"textSecondary"},"No cached BLAST results found for this gene. Run a BLAST query to cache results."):P.default.createElement("div",null,P.default.createElement("div",{className:r.header},P.default.createElement(q.Typography,{variant:"subtitle1"},"Cached BLAST Results (",l.length,")"),P.default.createElement(q.Button,{size:"small",color:"error",onClick:async()=>{try{i(void 0),await x()}catch(v){i(v)}}},"Clear results for this gene")),P.default.createElement(q.List,{dense:!0,className:r.resultList},l.map(v=>P.default.createElement(q.ListItem,{key:v.id,disablePadding:!0,secondaryAction:P.default.createElement(q.IconButton,{edge:"end",size:"small",onClick:async A=>{A.stopPropagation();try{i(void 0),await c(v.id)}catch(N){i(N)}}},P.default.createElement(ro,{fontSize:"small"}))},P.default.createElement(q.ListItemButton,{onClick:()=>{b(v)}},P.default.createElement(q.ListItemText,{primary:`${no(v)} - ${pr(v)}`,secondary:`${new Date(v.timestamp).toLocaleString()} - Seq: ${v.proteinSequence.slice(0,30)}...`}))))))}),lo=fr;var it=a(h()),mo=a(k());function Fe({value:e,onChange:t,className:o}){return it.default.createElement(g,{variant:"outlined",label:"MSA Algorithm",className:o,select:!0,value:e,helperText:e==="browser"?"no EBI job; rows aligned to the query":void 0,onChange:r=>{t(r.target.value)}},De.map(r=>it.default.createElement(mo.MenuItem,{value:r,key:r},At[r])))}var hr="msaView-blastSearch",gr="msaView-msaAlgorithm",co=je("blastp"),uo="clustalo";function Sr(e){let{program:t,database:o}=e??{},r=Oe.find(n=>n===t);return r&&$e(r).some(n=>n===o)?{program:r,database:o}:co}function yr(e){return De.find(t=>t===e)??uo}function po(){let[e,t]=ue(hr,co);return[Sr(e),o=>{t(o)}]}function Ue(){let[e,t]=ue(gr,uo);return[yr(e),o=>{t(o)}]}var br=(0,ho.makeStyles)()({selectField:{width:150},databaseField:{width:260},cachedResultsAccordion:{marginTop:20},infoText:{marginTop:20}}),vr=(0,fo.observer)(function({handleClose:e,feature:t,model:o,children:r,preferredTranscriptId:n}){let{classes:s}=br(),i=G(o),{launchError:m,submit:u}=oe(e),[l,p]=po(),[d,c]=Ue(),[x,b]=(0,w.useState)(String(Lt)),S=Number(x),v=Number.isInteger(S)&&S>=1,A=l.program==="phmmer",N=(0,w.useMemo)(()=>xe(t),[t]),{results:B,error:F}=We(N),C=re({feature:t,view:i,preferredTranscriptId:n}),{selectedTranscript:E,proteinSequence:D,sequenceStatus:ee}=C,ce=C.error??m??F;return w.default.createElement(w.default.Fragment,null,w.default.createElement(J,{error:ce},r,w.default.createElement(g,{variant:"outlined",label:"Search program",className:s.selectField,select:!0,value:l.program,onChange:T=>{p(je(T.target.value))}},Oe.map(T=>w.default.createElement(U.MenuItem,{value:T,key:T},Ct[T]))),w.default.createElement(g,{variant:"outlined",label:"Database",className:s.databaseField,select:!0,value:l.database,onChange:T=>{p({program:l.program,database:T.target.value})}},$e(l.program).map(T=>w.default.createElement(U.MenuItem,{value:T,key:T},Nt(T)))),A?null:w.default.createElement(Fe,{className:s.selectField,value:d,onChange:c}),w.default.createElement(g,{variant:"outlined",label:"Hits",className:s.selectField,type:"number",value:x,onChange:T=>{b(T.target.value)},error:!v,helperText:"best-scoring sequences to keep"}),w.default.createElement(Z,{feature:t,...C}),w.default.createElement(U.Typography,{variant:"body2",className:s.infoText},A?"phmmer aligns the hits as it finds them, so nothing is realigned afterwards.":"The hits come back from EBI and are then run through the chosen aligner."," ","The EBI queue is the wait, and it runs from seconds to many minutes."),B.length>0?w.default.createElement(U.Accordion,{className:s.cachedResultsAccordion},w.default.createElement(U.AccordionSummary,{expandIcon:w.default.createElement(yt,null)},w.default.createElement(U.Typography,null,"Previous BLAST Results")),w.default.createElement(U.AccordionDetails,null,w.default.createElement(lo,{model:o,handleClose:e,feature:t}))):null),w.default.createElement(Y,{model:o,hint:w.default.createElement(se,{status:ee}),submitDisabled:!D||!v,onSubmit:T=>{if(E){let $=l.program==="phmmer"?{searchProgram:"phmmer",blastDatabase:l.database,maxHits:S,selectedTranscript:E.toJSON(),proteinSequence:D}:{searchProgram:"blastp",blastDatabase:l.database,msaAlgorithm:d,maxHits:S,selectedTranscript:E.toJSON(),proteinSequence:D};u(()=>Q({view:i,feature:E,placement:T,displayName:vt(t,E),...Me,blastParams:$}))}},onCancel:e}))}),go=vr;var y=a(h()),wo=a(be()),ge=a(k()),xo=a(ve()),To=a(V());var ze=a(h());function So(e){return Ee(e).toUpperCase()}function wr(e,t){let o=Math.min(e.length,t.length);if(o===0)return 0;let r=0;for(let n=0;n<o;n++)e[n]===t[n]&&r++;return r/o}var xr=.9,Tr=.5;function yo(e,t){if(!e.trim())return{names:[]};let o;try{o=Pt(e)}catch{return{names:[]}}let r=o.getNames(),n=So(t);return{names:r,match:n?Mr(o,r,n):void 0}}function Mr(e,t,o){let r=[];for(let s of t){let i=So(It(e.getRow(s)));if(!i)continue;if(i===o)return{name:s,quality:"exact",identity:1,offset:0};let m=o.indexOf(i),u=i.indexOf(o);if(m!==-1||u!==-1){let p=Math.min(i.length,o.length)/Math.max(i.length,o.length);p>=Tr&&r.push({name:s,quality:"partial",identity:p,offset:m===-1?-u:m});continue}let l=wr(i,o);l>=xr&&r.push({name:s,quality:"similar",identity:l,offset:0})}let n=["partial","similar"];return r.sort((s,i)=>n.indexOf(s.quality)-n.indexOf(i.quality)||i.identity-s.identity)[0]}function bo(e,t){return e.querySeqName||(e.names.includes(t)?t:"")}function Ae(e,t){let[o,r]=(0,ze.useState)(),{names:n,match:s}=(0,ze.useMemo)(()=>yo(e,t),[e,t]),i=o??s?.name??"";return{detected:s,names:n,querySeqName:i,querySeqOffset:i===s?.name?s.offset:0,setQuerySeqName:r,isAutoDetected:o===void 0&&!!s}}var R=a(h()),Ce=a(k()),vo=a(V());var Ar=(0,vo.makeStyles)()({field:{marginTop:20},alert:{marginTop:10}});function Cr({identity:e,offset:t}){let o=`, covering ${Math.round(e*100)}% of it`;return t>0?`${o} from residue ${t+1}`:t<0?`${o} and running ${-t} residues past its start`:o}function he({names:e,detected:t,querySeqName:o,setQuerySeqName:r,isAutoDetected:n}){let{classes:s}=Ar();return R.default.createElement(R.default.Fragment,null,e.length>0?R.default.createElement(g,{variant:"outlined",label:"MSA row matching the selected transcript",select:!0,fullWidth:!0,className:s.field,value:e.includes(o)?o:"",onChange:i=>{r(i.target.value)}},e.map(i=>R.default.createElement(Ce.MenuItem,{value:i,key:i},i,t?.name===i?" \u2014 matches your protein":""))):R.default.createElement(g,{variant:"outlined",label:"MSA row matching the selected transcript",fullWidth:!0,className:s.field,helperText:"Paste an alignment above and this fills in on its own",value:o,onChange:i=>{r(i.target.value)}}),n&&t?t.quality==="similar"?R.default.createElement(Ce.Alert,{severity:"warning",className:s.alert},R.default.createElement("strong",null,t.name)," is"," ",Math.round(t.identity*100),"% identical to your protein but is not the same sequence. Clicking the alignment navigates the genome view, approximately: wherever the two differ by an insertion or a deletion, every residue after it lands one codon off."):R.default.createElement(Ce.Alert,{severity:"success",className:s.alert},"Matched ",R.default.createElement("strong",null,t.name)," to your protein sequence",t.quality==="exact"?"":Cr(t),". Clicking the alignment will navigate the genome view."):e.length>0&&!o?R.default.createElement(Ce.Alert,{severity:"warning",className:s.alert},"No row matched your protein sequence \u2014 pick the one for your gene above. Without it the alignment still renders, but clicking it will not navigate the genome view."):null)}var Lr=(0,To.makeStyles)()({ncbiLink:{wordBreak:"break-all"},textAreaFont:{fontFamily:"Courier New"},msaInput:{marginBottom:20},step:{marginTop:20},stepBody:{marginLeft:20,marginTop:8}}),Nr=(0,xo.observer)(function({handleClose:e,feature:t,model:o,children:r,preferredTranscriptId:n}){let{classes:s}=Lr(),i=G(o),{launchError:m,submit:u}=oe(e),[l,p]=(0,y.useState)(""),[d,c]=(0,y.useState)(""),x=re({feature:t,view:i,preferredTranscriptId:n}),{proteinSequence:b,selectedTranscript:S,error:v}=x,A=Ae(l,b),N=Ee(b),B=`${tt}?PAGE_TYPE=BlastSearch&PAGE=Proteins&PROGRAM=blastp&QUERY=${N}`,F=`${tt}?PAGE_TYPE=BlastSearch&PAGE=Proteins&PROGRAM=blastp&QUERY=${(0,wo.shorten2)(N,10)}`;return y.default.createElement(y.default.Fragment,null,y.default.createElement(J,{error:m??v},r,y.default.createElement(Z,{feature:t,...x}),y.default.createElement("div",{className:s.step},y.default.createElement(ge.Typography,{variant:"subtitle2"},"1. Run the search at NCBI"),y.default.createElement("div",{className:s.stepBody},b?y.default.createElement("div",{className:s.ncbiLink},y.default.createElement(Ft,{href:B},F)):y.default.createElement(ge.Alert,{severity:"info"},"Pick a transcript above to get a link carrying its protein sequence."))),y.default.createElement("div",{className:s.step},y.default.createElement(ge.Typography,{variant:"subtitle2"},"2. Align the hits"),y.default.createElement("div",{className:s.stepBody},y.default.createElement(ge.Typography,null,`On the results page click "Multiple Alignment" to run COBALT, NCBI's aligner. Download the alignment (.aln) and, if you want the tree drawn, the Newick tree (.nh).`))),y.default.createElement("div",{className:s.step},y.default.createElement(ge.Typography,{variant:"subtitle2"},"3. Paste the results back here"),y.default.createElement("div",{className:s.stepBody},y.default.createElement(g,{variant:"outlined",label:"Alignment",multiline:!0,minRows:5,maxRows:10,fullWidth:!0,className:s.msaInput,slotProps:{input:{className:s.textAreaFont}},placeholder:"Paste the .aln contents here",value:l,onChange:C=>{p(C.target.value)}}),y.default.createElement(g,{variant:"outlined",label:"Tree (optional)",multiline:!0,minRows:3,maxRows:10,fullWidth:!0,slotProps:{input:{className:s.textAreaFont}},placeholder:"Paste the .nh Newick tree here",value:d,onChange:C=>{c(C.target.value)}}),y.default.createElement(he,{...A})))),y.default.createElement(Y,{model:o,submitDisabled:!S||!l.trim(),onSubmit:C=>{S&&u(()=>Q({view:i,feature:S,placement:C,displayName:te(S),querySeqName:A.querySeqName,querySeqOffset:A.querySeqOffset,data:{msa:l,tree:d}}))},onCancel:e}))}),Mo=Nr;var Se=a(h()),ne=a(k());function lt({lookupMethod:e,setLookupMethod:t}){return Se.default.createElement(ne.FormControl,{component:"fieldset"},Se.default.createElement(ne.RadioGroup,{row:!0,value:e,onChange:o=>{t(o.target.value)}},Se.default.createElement(ne.FormControlLabel,{value:"automatic",control:Se.default.createElement(ne.Radio,null),label:"Automatic"}),Se.default.createElement(ne.FormControlLabel,{value:"manual",control:Se.default.createElement(ne.Radio,null),label:"Manual"})))}var z=a(h()),O=a(k()),Ao=a(V());var kr=(0,Ao.makeStyles)()({field:{minWidth:300},help:{marginBottom:8}});function mt({handleClose:e,ebiEmail:t}){let{classes:o}=kr(),[r,n]=(0,z.useState)(t);return z.default.createElement(O.Dialog,{open:!0,maxWidth:"lg",onClose:()=>{e()}},z.default.createElement(O.DialogTitle,null,"EBI settings"),z.default.createElement(O.DialogContent,null,z.default.createElement(O.Typography,{variant:"subtitle2",className:o.help},"Every search this tab runs is submitted to EBI with this address, which is how they reach whoever is generating the load. If your site sends real volume, use your own."),z.default.createElement(g,{autoFocus:!0,margin:"dense",label:"EBI contact email",fullWidth:!0,variant:"outlined",value:r,className:o.field,onChange:s=>{n(s.target.value)}}),z.default.createElement(O.Button,{variant:"contained",onClick:()=>{n(Be)}},"Reset")),z.default.createElement(O.DialogActions,null,z.default.createElement(O.Button,{variant:"contained",color:"secondary",onClick:()=>{e()}},"Cancel"),z.default.createElement(O.Button,{color:"primary",variant:"contained",onClick:()=>{e({ebiEmail:r})}},"Save")))}var Fr=(0,Co.makeStyles)()({settingsButton:{float:"right"}}),Pr={automatic:go,manual:Mo};function ct({handleClose:e,model:t,feature:o,preferredTranscriptId:r}){let[n,s]=(0,K.useState)("automatic"),[i,m]=ue(St,Be),[u,l]=(0,K.useState)(!1),{classes:p}=Fr(),d=Pr[n];return K.default.createElement(K.default.Fragment,null,K.default.createElement(Ke.Tooltip,{title:`EBI settings \u2014 jobs are submitted with ${i}`},K.default.createElement(Ke.IconButton,{className:p.settingsButton,"aria-label":"EBI settings",size:"small",onClick:()=>{l(!0)}},K.default.createElement(Ot,null))),K.default.createElement(d,{model:t,feature:o,handleClose:e,preferredTranscriptId:r},K.default.createElement(lt,{lookupMethod:n,setLookupMethod:s})),u?K.default.createElement(mt,{ebiEmail:i,handleClose:c=>{c&&m(c.ebiEmail),l(!1)}}):null)}var j=a(h());var Je=a(k()),Ir=(0,j.lazy)(()=>import("./HelpDialog-DF4Y536X.js"));function ut(){let[e,t]=(0,j.useState)(!1);return j.default.createElement(j.default.Fragment,null,j.default.createElement(Je.Tooltip,{title:"What each tab does"},j.default.createElement(Je.IconButton,{"aria-label":"Help",onClick:()=>{t(!0)}},j.default.createElement(Bt,null))),e?j.default.createElement(j.Suspense,{fallback:null},j.default.createElement(Ir,{handleClose:()=>{t(!1)}})):null)}var f=a(h()),dt=a(we()),Lo=a(rr()),ae=a(k()),No=a(ve()),ko=a(V());function Br(e){let t=Qe(e,500),{data:o}=W(t?[JSON.stringify(t),"msa-file-text"]:null,()=>(0,Lo.openLocation)(t).readFile("utf8"));return o??""}var qr=(0,ko.makeStyles)()({textAreaFont:{fontFamily:"Courier New"},inputContainer:{marginBottom:30},fileContainer:{maxWidth:500},msaInput:{marginBottom:20}}),Er=(0,No.observer)(function({model:t,feature:o,handleClose:r,preferredTranscriptId:n}){let s=G(t),{classes:i}=qr(),{launchError:m,submit:u}=oe(r),[l,p]=(0,f.useState)("file"),[d,c]=(0,f.useState)(""),[x,b]=(0,f.useState)(""),[S,v]=(0,f.useState)(),[A,N]=(0,f.useState)(),B=re({feature:o,view:s,preferredTranscriptId:n}),{selectedTranscript:F,proteinSequence:C,error:E,sequenceStatus:D}=B,ee=Br(l==="file"?S:void 0),ce=Ae(l==="file"?ee:d,C);return f.default.createElement(f.default.Fragment,null,f.default.createElement(J,{error:m??E},f.default.createElement(ae.FormControl,{component:"fieldset"},f.default.createElement(ae.RadioGroup,{row:!0,value:l,onChange:$=>{p($.target.value)}},f.default.createElement(ae.FormControlLabel,{value:"file",control:f.default.createElement(ae.Radio,null),label:"Open files"}),f.default.createElement(ae.FormControlLabel,{value:"text",control:f.default.createElement(ae.Radio,null),label:"Paste text"}))),f.default.createElement("div",{className:i.inputContainer},l==="file"?f.default.createElement("div",{className:i.fileContainer},f.default.createElement(dt.FileSelector,{name:"MSA File .aln (Clustal), .fa/.mfa (aligned FASTA), .stock (Stockholm), etc)",inline:!0,location:S,setLocation:v}),f.default.createElement(dt.FileSelector,{name:"Tree file .nh (Newick) or .asn (NCBI COBALT ASN.1)",inline:!0,location:A,setLocation:N})):f.default.createElement(f.default.Fragment,null,f.default.createElement(g,{variant:"outlined",name:"MSA",multiline:!0,minRows:5,className:i.msaInput,maxRows:10,fullWidth:!0,placeholder:"Paste MSA here",value:d,onChange:$=>{c($.target.value)}}),f.default.createElement(g,{variant:"outlined",name:"Tree",multiline:!0,minRows:5,maxRows:10,fullWidth:!0,placeholder:"Paste newick tree (optional)",value:x,onChange:$=>{b($.target.value)}}))),f.default.createElement(Z,{feature:o,...B}),f.default.createElement(he,{...ce})),f.default.createElement(Y,{model:t,hint:f.default.createElement(se,{status:D}),submitDisabled:!F||l==="file"&&!S||l==="text"&&!d.trim(),onSubmit:$=>{F&&u(()=>Q({view:s,feature:F,placement:$,displayName:te(F),querySeqName:ce.querySeqName,querySeqOffset:ce.querySeqOffset,...l==="file"?{msaFilehandle:S,treeFilehandle:A}:{data:{msa:d,tree:x}}}))},onCancel:r}))}),Fo=Er;var I=a(h()),Oo=a(k()),jo=a(ve()),$o=a(V());var pt=a(h()),Po=a(k());var Dr="msaview-ortholog-source",Io={ncbi:"NCBI orthologs",panther:"PANTHER",uniref:"UniRef cluster"},Bo=Object.keys(Io);function Or(e){return Bo.find(t=>t===e)??"ncbi"}function qo(){let[e,t]=ue(Dr,"ncbi");return[Or(e),o=>{t(o)}]}var jr={ncbi:"vertebrates and insects",panther:"also yeast, worm, fly and plants",uniref:"all of UniProtKB within 50% identity"};function ft({value:e,onChange:t,className:o}){return pt.default.createElement(g,{variant:"outlined",label:"Source",className:o,select:!0,value:e,helperText:jr[e],onChange:r=>{t(r.target.value)}},Bo.map(r=>pt.default.createElement(Po.MenuItem,{value:r,key:r},Io[r])))}var Ye=a(h());async function Eo(e,t){let o=e.trim();if(!o)return;if(/^\d+$/.test(o))return Number(o);let n=(await Ve(_e("esearch",{db:"taxonomy",term:o,retmax:"1",retmode:"json"}),{signal:t})).esearchresult?.idlist?.[0];return n?Number(n):void 0}async function Do(e,t){let o=e.trim();if(!o)return;let n=(await Ve(_e("esearch",{db:"assembly",term:o,retmax:"1",retmode:"json"}),{signal:t})).esearchresult?.idlist?.[0];if(!n)return;let i=(await Ve(_e("esummary",{db:"assembly",id:n,retmode:"json"}),{signal:t})).result?.[n],m=Number(i?.speciestaxid);return i?.speciesname&&m?{taxId:m,speciesName:i.speciesname}:void 0}async function $r(e,t){let o=await Eo(e,t);if(!o)throw new Error(`No NCBI taxon matches "${e}"`);let r=(await Et([o],t)).get(o),n=[r?.sciname,r?.commonName&&`(${r.commonName})`].filter(Boolean).join(" ");return{taxId:o,label:n||`taxon ${o}`}}function ht({value:e,assemblyName:t,onChange:o,className:r}){let[n,s]=(0,Ye.useState)(),i=Qe(n,400),{data:m}=W(t&&n===void 0?[t,"assembly-species"]:null,c=>Do(t,c),{onSuccess:c=>{c&&o(c.taxId)}}),{data:u,error:l}=W(i?.trim()?[i.trim(),"taxon"]:null,c=>$r(i,c),{onSuccess:({taxId:c})=>{o(c)}}),p=n??m?.speciesName??"human",d=n===void 0?m?.speciesName:u?.label;return Ye.default.createElement(g,{variant:"outlined",label:"Query species",className:r,value:p,onChange:c=>{s(c.target.value)},error:!!l,helperText:l?`${l}`:d??`the species this gene is from (taxon ${e})`})}var _r=(0,$o.makeStyles)()({selectField:{width:180}}),Vr={ncbi:e=>`the ${e} closest species NCBI has`,panther:e=>`the ${e} closest species PANTHER has`,uniref:e=>`${e} rows, one per species, reviewed entries first`},Gr=(0,jo.observer)(function({handleClose:e,feature:t,model:o,preferredTranscriptId:r}){let{classes:n}=_r(),s=G(o),{launchError:i,submit:m}=oe(e),[u,l]=(0,I.useState)(9606),[p,d]=qo(),[c,x]=Ue(),[b,S]=(0,I.useState)(String(qt)),v=(0,I.useMemo)(()=>xe(t),[t]),A=re({feature:t,view:s,preferredTranscriptId:r}),{selectedTranscript:N,proteinSequence:B,sequenceStatus:F}=A,C=A.error??i,E=Number(b),D=Number.isInteger(E)&&E>=2;return I.default.createElement(I.default.Fragment,null,I.default.createElement(J,{error:C},I.default.createElement(Oo.Typography,{variant:"body2"},"Precomputed orthologs, one gene per species, looked up rather than searched for. No BLAST job to queue, and with the in-browser aligner no job at all."),I.default.createElement("div",null,I.default.createElement(ft,{className:n.selectField,value:p,onChange:d}),I.default.createElement(ht,{className:n.selectField,value:u,assemblyName:s.assemblyNames[0],onChange:l}),I.default.createElement(Fe,{className:n.selectField,value:c,onChange:x}),I.default.createElement(g,{variant:"outlined",label:"Rows to align",className:n.selectField,type:"number",value:b,onChange:ee=>{S(ee.target.value)},error:!D,helperText:D?Vr[p](E):"a whole number, 2 or more"})),I.default.createElement(Z,{feature:t,...A})),I.default.createElement(Y,{model:o,hint:I.default.createElement(se,{status:F}),submitDisabled:!B||!D,onSubmit:ee=>{N&&m(()=>Q({view:s,feature:N,placement:ee,displayName:`Orthologs - ${te(t)} - ${fe(N)}`,...Me,orthologParams:{taxId:u,source:p,maxSpecies:E,geneCandidates:v,msaAlgorithm:c,selectedTranscript:N.toJSON(),proteinSequence:B}}))},onCancel:e}))}),_o=Gr;var M=a(h()),Le=a(we()),Ze=a(be()),Re=a(k()),Ko=a(ve()),Jo=a(V());var Qo=a(Go());async function Ho(e,t){return(await(0,Qo.getAdapter)(e,"msa",t)).dataAdapter}async function Wo({config:e,pluginManager:t}){return(await Ho(t,e)).getMSAList()}async function Uo({config:e,pluginManager:t,msaId:o}){return(await Ho(t,e)).getMSA(o)}var zo=a(tr());function Xe(e){return(0,zo.readConfObject)(e,["msa","datasets"])}var Qr=(0,Jo.makeStyles)()({selectedContainer:{marginTop:50}}),Hr=(0,Ko.observer)(function({model:e,feature:t,handleClose:o,preferredTranscriptId:r}){let n=(0,Ze.getSession)(e),s=G(e),{classes:i}=Qr(),{pluginManager:m}=(0,Ze.getEnv)(e),{assemblyNames:u}=s,{launchError:l,submit:p}=oe(o),d=Xe(n.jbrowse),[c,x]=(0,M.useState)(d?.[0]?.datasetId),b=d?.find(_=>_.datasetId===c),{data:S,isLoading:v,error:A}=W(b?`${b.datasetId}-msa-list`:null,()=>Wo({config:b.adapter,pluginManager:m})),N=re({feature:t,view:s,validIds:S,preferredTranscriptId:r}),{selectedId:B,selectedTranscript:F,proteinSequence:C,sequenceStatus:E}=N,{data:D,isLoading:ee,error:ce}=W(B&&b&&S?`${b.datasetId}-${B}-msa`:null,()=>Uo({msaId:B,config:b.adapter,pluginManager:m})),T=(0,M.useMemo)(()=>D?.map(_=>`>${_.get("refName")}
|
|
3
3
|
${_.get("seq")}`).join(`
|
|
4
4
|
`)??"",[D]),$=Ae(T,C),Pe=bo($,`${B}_${u[0]??""}`),Ro=A??ce??N.error??l;return M.default.createElement(M.default.Fragment,null,M.default.createElement(J,{error:Ro},M.default.createElement(g,{select:!0,label:"Select MSA dataset",value:c,onChange:_=>{x(_.target.value)}},d?.map(_=>M.default.createElement(Re.MenuItem,{key:_.datasetId,value:_.datasetId},_.name))),b?M.default.createElement("div",{className:i.selectedContainer},!v&&ee?M.default.createElement(Le.LoadingEllipses,{variant:"h6",message:`Loading MSA for ${fe(F)||B}`}):null,v?M.default.createElement(Le.LoadingEllipses,{variant:"h6",message:`Loading available MSAs for (${b.name})`}):null,S?M.default.createElement("div",null,M.default.createElement(Le.SanitizedHTML,{html:b.description}),M.default.createElement(Z,{feature:t,...N}),T?M.default.createElement(he,{...$,querySeqName:Pe}):null):null):null),M.default.createElement(Y,{model:e,hint:ee?M.default.createElement(Le.LoadingEllipses,{message:"Loading alignment"}):D?.length&&!Pe?M.default.createElement(Re.Typography,{color:"textSecondary",variant:"body2"},"no row matches this transcript"):M.default.createElement(se,{status:E}),submitDisabled:!F||!D?.length||!Pe,onSubmit:_=>{F&&T&&p(()=>Q({view:s,feature:F,placement:_,displayName:te(F),treeAreaWidth:200,treeWidth:100,drawNodeBubbles:!1,labelsAlignRight:!0,showBranchLen:!1,colWidth:10,rowHeight:12,colorSchemeName:"percent_identity_dynamic",querySeqName:Pe,querySeqOffset:$.querySeqOffset,data:{msa:T}}))},onCancel:o}))}),Yo=Hr;var et=a(h());function Ne({children:e,value:t,index:o,...r}){let n=t===o,[s,i]=(0,et.useState)(n);return n&&!s&&i(!0),et.default.createElement("div",{role:"tabpanel",hidden:!n,...r},s||n?e:null)}function Wr({handleClose:e,feature:t,model:o,preferredTranscriptId:r}){let n=(0,Zo.getSession)(o),i=!!Xe(n.jbrowse)?.length,[m,u]=(0,L.useState)("orthologs");return L.default.createElement(Xo.Dialog,{maxWidth:"xl",title:"Launch MSA view",open:!0,onClose:e},L.default.createElement(Wt,null,L.default.createElement("div",{style:{display:"flex",alignItems:"center"}},L.default.createElement(ye.Tabs,{value:m,onChange:(l,p)=>{u(p)}},L.default.createElement(ye.Tab,{label:"Orthologs",value:"orthologs"}),L.default.createElement(ye.Tab,{label:"BLAST query",value:"ncbi_blast"}),i?L.default.createElement(ye.Tab,{label:"Pre-loaded MSA datasets",value:"preloaded_msa"}):null,L.default.createElement(ye.Tab,{label:"Manual upload",value:"manual_msa"})),L.default.createElement(ut,null)),L.default.createElement(Ne,{value:m,index:"orthologs"},L.default.createElement(_o,{handleClose:e,feature:t,model:o,preferredTranscriptId:r})),L.default.createElement(Ne,{value:m,index:"ncbi_blast"},L.default.createElement(ct,{handleClose:e,feature:t,model:o,preferredTranscriptId:r})),i?L.default.createElement(Ne,{value:m,index:"preloaded_msa"},L.default.createElement(Yo,{model:o,feature:t,handleClose:e,preferredTranscriptId:r})):null,L.default.createElement(Ne,{value:m,index:"manual_msa"},L.default.createElement(Fo,{model:o,feature:t,handleClose:e,preferredTranscriptId:r}))))}export{Wr as default};
|
|
5
|
-
//# sourceMappingURL=LaunchMsaViewDialog-
|
|
5
|
+
//# sourceMappingURL=LaunchMsaViewDialog-WBXEEHJL.js.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var w=["stack","splitRight","newTab"],i="splitRight",r="msaView-launchPlacement";function o(e,t){return t in e&&typeof e[t]=="function"}var a=!1;function M(e){return c(e)||o(e,"setUseWorkspaces")&&o(e,"setPendingMove")}function c(e){return o(e,"moveViewToNewTab")&&o(e,"moveViewToSplit")}function p(e){let t=o(e,"setUseWorkspaces"),s=o(e,"setPendingMove");return t!==s&&!a&&(a=!0,console.warn(`jbrowse-plugin-msaview: this session supports workspaces but not ${s?"setUseWorkspaces":"setPendingMove"}, so the MSA view was stacked instead of tiled: the session API moved and the plugin needs updating to match.`)),t&&s}function l(e,t,s){s!=="stack"&&(c(e)?s==="newTab"?e.moveViewToNewTab(t):e.moveViewToSplit(t,"row"):p(e)&&(e.setPendingMove({type:s,viewId:t}),e.setUseWorkspaces(!0)))}function u(e){return w.includes(e)}function m(){try{let e=globalThis.localStorage.getItem(r);return u(e)?e:i}catch(e){return console.error(e),i}}function d(e){try{globalThis.localStorage.setItem(r,e)}catch(t){console.error(t)}}async function P(e,{placement:t="stack",...s}){let n=await e.launchView("MsaView",{type:"MsaView",...s});return l(e,n.id,t),n}export{M as a,m as b,d as c,P as d};
|
|
2
|
+
//# sourceMappingURL=chunk-DECSTFAT.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/utils/workspaces.ts", "../../src/utils/launchMsaView.ts"],
|
|
4
|
+
"sourcesContent": ["import type { AbstractSessionModel } from '@jbrowse/core/util'\n\n/**\n * Where a launched MSA view lands. Every launch names one of these and stops\n * there, so a host that arranges views differently is one function to teach.\n *\n * stack append below whatever is on screen\n * splitRight its own cell to the right, beside the view it is connected to\n * newTab its own tab in the current cell\n */\nexport type MsaViewPlacement = 'stack' | 'splitRight' | 'newTab'\n\nconst PLACEMENTS: MsaViewPlacement[] = ['stack', 'splitRight', 'newTab']\n\n/**\n * What the dialog does unasked. Side-by-side, because a launch from a gene\n * feature sets `connectedViewId`: the pair shares a hover and a highlight, and\n * reads as a split. A session spec defaults to `stack` instead.\n */\nexport const DEFAULT_LAUNCH_PLACEMENT: MsaViewPlacement = 'splitRight'\n\nexport const LAUNCH_PLACEMENT_KEY = 'msaView-launchPlacement'\n\n/**\n * The session actions that place a view in a tiled workspace. Only jbrowse-web\n * and desktop have them, so feature-detect rather than import.\n */\ninterface SessionWithMoves {\n moveViewToNewTab: (viewId: string) => unknown\n moveViewToSplit: (viewId: string, direction: 'row' | 'column') => unknown\n}\n\n// a host from before the workspace was always on\ninterface SessionWithWorkspaces {\n setUseWorkspaces: (useWorkspaces: boolean) => void\n setPendingMove: (move: {\n type: 'newTab' | 'splitRight'\n viewId: string\n }) => void\n}\n\nfunction hasAction(session: AbstractSessionModel, name: string) {\n return (\n name in session &&\n typeof (session as unknown as Record<string, unknown>)[name] === 'function'\n )\n}\n\n// Warned at most once. This is a property of the host, so the answer is the\n// same on every launch and a dialog the user reopens should not stack up noise.\nlet warnedPartial = false\n\nexport function resetWorkspacesWarning() {\n warnedPartial = false\n}\n\n/**\n * Whether this host can honor anything other than `stack`. Silent: the dialog\n * asks on every render, and only a launch is worth warning about.\n */\nexport function sessionSupportsPlacement(session: AbstractSessionModel) {\n return (\n isSessionWithMoves(session) ||\n (hasAction(session, 'setUseWorkspaces') &&\n hasAction(session, 'setPendingMove'))\n )\n}\n\nfunction isSessionWithMoves(\n session: AbstractSessionModel,\n): session is AbstractSessionModel & SessionWithMoves {\n return (\n hasAction(session, 'moveViewToNewTab') &&\n hasAction(session, 'moveViewToSplit')\n )\n}\n\nfunction isSessionWithWorkspaces(\n session: AbstractSessionModel,\n): session is AbstractSessionModel & SessionWithWorkspaces {\n const canEnable = hasAction(session, 'setUseWorkspaces')\n const canPlace = hasAction(session, 'setPendingMove')\n\n // Missing BOTH is an embedded session, with nothing to ask for. Missing ONE\n // is a host that moved the action out from under us: protein3d once stopped\n // tiling silently for weeks when jbrowse-web folded `setPendingMove` into its\n // layout `init`.\n if (canEnable !== canPlace && !warnedPartial) {\n warnedPartial = true\n console.warn(\n `jbrowse-plugin-msaview: this session supports workspaces but not ` +\n `${canPlace ? 'setUseWorkspaces' : 'setPendingMove'}, so the MSA view ` +\n `was stacked instead of tiled: the session API moved and the plugin ` +\n `needs updating to match.`,\n )\n }\n return canEnable && canPlace\n}\n\n/**\n * Put a freshly added view where the launch said to. `stack` is a placement\n * rather than the absence of one, so no caller has to ask what host it is on.\n */\nexport function placeMsaView(\n session: AbstractSessionModel,\n viewId: string,\n placement: MsaViewPlacement,\n) {\n if (placement === 'stack') {\n return\n }\n if (isSessionWithMoves(session)) {\n if (placement === 'newTab') {\n session.moveViewToNewTab(viewId)\n } else {\n session.moveViewToSplit(viewId, 'row')\n }\n } else if (isSessionWithWorkspaces(session)) {\n session.setPendingMove({ type: placement, viewId })\n session.setUseWorkspaces(true)\n }\n}\n\nfunction isPlacement(value: unknown): value is MsaViewPlacement {\n return PLACEMENTS.includes(value as MsaViewPlacement)\n}\n\n/**\n * The dialog's own remembered choice \u2014 not the host's preferences system, which\n * records whether the user likes workspaces and does not exist everywhere.\n */\nexport function readLaunchPlacement(): MsaViewPlacement {\n try {\n const stored = globalThis.localStorage.getItem(LAUNCH_PLACEMENT_KEY)\n return isPlacement(stored) ? stored : DEFAULT_LAUNCH_PLACEMENT\n } catch (error) {\n console.error(error)\n return DEFAULT_LAUNCH_PLACEMENT\n }\n}\n\nexport function writeLaunchPlacement(placement: MsaViewPlacement) {\n try {\n globalThis.localStorage.setItem(LAUNCH_PLACEMENT_KEY, placement)\n } catch (error) {\n console.error(error)\n }\n}\n", "import { placeMsaView } from './workspaces'\n\nimport type { MsaViewPlacement } from './workspaces'\nimport type { AbstractSessionModel } from '@jbrowse/core/util'\n\n/**\n * A launch, stated: what the view is, and where it goes. Everything but\n * `placement` is a react-msaview or plugin-model snapshot property, passed\n * through untouched so this never becomes a list that has to grow.\n */\nexport interface MsaViewLaunchSpec extends Record<string, unknown> {\n /** default `stack`, the only thing an embedded session can do */\n placement?: MsaViewPlacement\n}\n\n/**\n * The one place a launch adds an MSA view -- the dialog's four tabs, the Add\n * menu, and the `LaunchView-MsaView` extension point a session spec arrives on\n * all come through here. Each of them used to run its own `addView` and none\n * placed the result, which is how a launch from a gene feature landed stacked\n * under the very genome view it was connected to.\n */\nexport async function launchMsaView(\n session: AbstractSessionModel,\n { placement = 'stack', ...snapshot }: MsaViewLaunchSpec,\n) {\n const view = await session.launchView('MsaView', {\n type: 'MsaView',\n ...snapshot,\n })\n placeMsaView(session, view.id, placement)\n return view\n}\n"],
|
|
5
|
+
"mappings": "AAYA,IAAMA,EAAiC,CAAC,QAAS,aAAc,QAAQ,EAO1DC,EAA6C,aAE7CC,EAAuB,0BAoBpC,SAASC,EAAUC,EAA+BC,EAAc,CAC9D,OACEA,KAAQD,GACR,OAAQA,EAA+CC,CAAI,GAAM,UAErE,CAIA,IAAIC,EAAgB,GAUb,SAASC,EAAyBC,EAA+B,CACtE,OACEC,EAAmBD,CAAO,GACzBE,EAAUF,EAAS,kBAAkB,GACpCE,EAAUF,EAAS,gBAAgB,CAEzC,CAEA,SAASC,EACPD,EACoD,CACpD,OACEE,EAAUF,EAAS,kBAAkB,GACrCE,EAAUF,EAAS,iBAAiB,CAExC,CAEA,SAASG,EACPH,EACyD,CACzD,IAAMI,EAAYF,EAAUF,EAAS,kBAAkB,EACjDK,EAAWH,EAAUF,EAAS,gBAAgB,EAMpD,OAAII,IAAcC,GAAY,CAACC,IAC7BA,EAAgB,GAChB,QAAQ,KACN,oEACKD,EAAW,mBAAqB,gBAAgB,+GAGvD,GAEKD,GAAaC,CACtB,CAMO,SAASE,EACdP,EACAQ,EACAC,EACA,CACIA,IAAc,UAGdR,EAAmBD,CAAO,EACxBS,IAAc,SAChBT,EAAQ,iBAAiBQ,CAAM,EAE/BR,EAAQ,gBAAgBQ,EAAQ,KAAK,EAE9BL,EAAwBH,CAAO,IACxCA,EAAQ,eAAe,CAAE,KAAMS,EAAW,OAAAD,CAAO,CAAC,EAClDR,EAAQ,iBAAiB,EAAI,GAEjC,CAEA,SAASU,EAAYC,EAA2C,CAC9D,OAAOC,EAAW,SAASD,CAAyB,CACtD,CAMO,SAASE,GAAwC,CACtD,GAAI,CACF,IAAMC,EAAS,WAAW,aAAa,QAAQC,CAAoB,EACnE,OAAOL,EAAYI,CAAM,EAAIA,EAASE,CACxC,OAASC,EAAO,CACd,eAAQ,MAAMA,CAAK,EACZD,CACT,CACF,CAEO,SAASE,EAAqBT,EAA6B,CAChE,GAAI,CACF,WAAW,aAAa,QAAQM,EAAsBN,CAAS,CACjE,OAASQ,EAAO,CACd,QAAQ,MAAMA,CAAK,CACrB,CACF,CC7HA,eAAsBE,EACpBC,EACA,CAAE,UAAAC,EAAY,QAAS,GAAGC,CAAS,EACnC,CACA,IAAMC,EAAO,MAAMH,EAAQ,WAAW,UAAW,CAC/C,KAAM,UACN,GAAGE,CACL,CAAC,EACD,OAAAE,EAAaJ,EAASG,EAAK,GAAIF,CAAS,EACjCE,CACT",
|
|
6
|
+
"names": ["PLACEMENTS", "DEFAULT_LAUNCH_PLACEMENT", "LAUNCH_PLACEMENT_KEY", "hasAction", "session", "name", "warnedPartial", "sessionSupportsPlacement", "session", "isSessionWithMoves", "hasAction", "isSessionWithWorkspaces", "canEnable", "canPlace", "warnedPartial", "placeMsaView", "viewId", "placement", "isPlacement", "value", "PLACEMENTS", "readLaunchPlacement", "stored", "LAUNCH_PLACEMENT_KEY", "DEFAULT_LAUNCH_PLACEMENT", "error", "writeLaunchPlacement", "launchMsaView", "session", "placement", "snapshot", "view", "placeMsaView"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{b as X,c as I,d as K,e as H,o as J}from"./chunk-PJZ3XTMG.js";import{a as Pe}from"./chunk-IBBQUV2I.js";import{a as Te}from"./chunk-2IWD4OO4.js";import{a as Be,b as z}from"./chunk-FY3BTKY4.js";var Ae=Be((gt,te)=>{te.exports=JBrowseExports["@jbrowse/core/util/translateTranscript"]});var E=z(Pe());function ot(e){return(0,E.getContainingView)(e)}function Z(e){return typeof e=="string"&&e!==""}function Y(e){return[...new Set(e.filter(Z))]}function ee(e,t){return t.filter(Z).join(e)}function Ce(e){let n=(e.get("subfeatures")??[]).filter(r=>(r.get("type")==="mRNA"||r.get("type")==="transcript")&&r.get("subfeatures")?.some(o=>o.get("type")==="CDS"));return n.length>0?n:[e]}function Q(e){let t=(0,E.sum)(e.get("subfeatures")?.filter(n=>n.get("type")==="CDS").map(n=>n.get("end")-n.get("start"))??[]);return{len:Math.floor(t/3),mod:t%3}}function st(e){return e?.id()??""}function Ne(e){return e?Y([e.id(),e.get("name"),e.get("id"),e.get("transcript_id")]):[]}function it(e,t){return Ne(e).includes(t)}function Ee(e){return e?ee(" ",[e.get("name"),e.get("id")]):""}function Me(e){return e?ee(" ",[e.get("gene_name")??e.get("name"),e.get("id")?`(${e.get("id")})`:void 0]):""}function at(e,t){return`BLAST - ${Me(e)} - ${Ee(t)}`}function ct(e){return Ce(e).toSorted((n,r)=>Q(r).len-Q(n).len)}function ut(e){return e.replace(/[*&]+$/,"").replaceAll(/[*&]/g,"X")}function mt(e){return Y([e.id(),e.get("id"),e.get("name"),e.get("gene_id"),e.get("gene_name")])}var ne=z(Te());async function lt({start:e,end:t,refName:n,session:r,assemblyName:o}){let{assemblyManager:a,rpcManager:i}=r,c=await a.waitForAssembly(o);if(!c)throw new Error("assembly not found");return{seq:(await i.call("getSequence","CoreGetFeatures",{adapterConfig:(0,ne.getConf)(c,["sequence","adapter"]),regions:[{start:e,end:t,refName:c.getCanonicalRefName(n)??n,assemblyName:o}]}))[0]?.get("seq")??"",assemblyGeneticCodeId:c.getGeneticCodeId(n)}}var _e="jbrowse-plugin-msaview",Re="colin.diesh@gmail.com",oe="https://eutils.ncbi.nlm.nih.gov/entrez/eutils";function se(e){return new URLSearchParams({...e,tool:_e,email:Re})}function L(e,t){return`${oe}/${e}.fcgi?${se(t).toString()}`}function A(e){return L("efetch",e)}function ie(e){return[`${oe}/efetch.fcgi`,{method:"POST",body:se(e)}]}var re=350,M=0;async function ae(e){let t=Date.now(),n=Math.max(t,M);if(M=n+re,n>t)try{await K(n-t,e??void 0)}catch(r){throw M===n+re&&(M=n),r}}async function S(e,t){return await ae(t?.signal),X(e,t)}async function ce(e,t){return await ae(t?.signal),I(e,t)}var Oe={amp:"&",apos:"'",gt:">",lt:"<",quot:'"'};function j(e){return e.replaceAll(/&(#x[\da-f]+|#\d+|[a-z]+);/gi,(t,n)=>n.startsWith("#x")||n.startsWith("#X")?String.fromCodePoint(Number.parseInt(n.slice(2),16)):n.startsWith("#")?String.fromCodePoint(Number(n.slice(1))):Oe[n]??t)}var me="https://api.ncbi.nlm.nih.gov/datasets/v2",$e=100;function Le(e){return e.trim().replace(/^\w+:/,"").replace(/\.\d+$/,"")}async function wt(e,t,n){let r=new Set;for(let o of e){let a=o.trim();if(/^\d+$/.test(a))return{geneId:a,matched:a};let i=Le(a);if(!i||r.has(i))continue;r.add(i);let s=(await ce(L("esearch",{db:"gene",term:`${i}[Gene Name] AND ${t}[taxid]`,retmode:"json",retmax:"1"}),{signal:n})).esearchresult?.idlist?.[0];if(s)return{geneId:s,matched:i}}}async function je(e,{taxa:t,exclude:n,limit:r=$e,signal:o}={}){let a=await I(`${me}/gene/id/${e}/orthologs?returned_content=COMPLETE`,{signal:o}),i=new Map;for(let{gene:c}of a.reports??[]){let s=Number(c?.tax_id);if(c?.gene_id&&s!==n&&(t?.has(s)??!0)&&!i.has(s)&&i.set(s,{taxId:s,geneId:c.gene_id,scientificName:c.taxname??String(s),commonName:c.common_name}),i.size>=r)break}return[...i.values()]}var ue=150;async function de(e,t){let n=new Map;for(let r=0;r<e.length;r+=ue){let o=e.slice(r,r+ue),a=await I(`${me}/gene/id/${o.join(",")}/product_report?page_size=${o.length}`,{signal:t});for(let{product:i}of a.reports??[]){let c=(i?.transcripts??[]).map(u=>({acc:u.protein?.accession_version,len:u.protein?.length??0,mane:/select/i.test(u.select_category??"")})).filter(u=>!!u.acc),s=c.find(u=>u.mane)??[...c].sort((u,d)=>d.len-u.len).at(0);i?.gene_id&&s&&n.set(i.gene_id,s.acc)}}return n}function ge(e){let t=new Map,n,r=[];for(let o of e.split(`
|
|
2
|
+
`))o.startsWith(">")?(n&&t.set(n,r.join("")),n=o.slice(1).split(/\s+/)[0],r=[]):r.push(o.trim());return n&&t.set(n,r.join("")),t}function Fe(e){return e.replace(/[^A-Za-z0-9]+/g,"_").replace(/^_+|_+$/g,"")}function ke(e){let t=new Set;return e.map(n=>{let r=Fe(n)||"row",o=r,a=1;for(;t.has(o);)a+=1,o=`${r}_${a}`;return t.add(o),o})}async function yt(e,t){let n=(await de([e],t)).get(e);if(!n)return;let r=ge(await S(A({db:"protein",id:n,rettype:"fasta",retmode:"text"}),{signal:t})).get(n);return r?{accession:n,sequence:r}:void 0}async function Dt({geneId:e,taxa:t,exclude:n,limit:r,onProgress:o,signal:a}){o("Finding orthologs across species...");let i=await je(e,{taxa:t,exclude:n,limit:r,signal:a});if(i.length<2)throw new Error(`Only ${i.length} ortholog(s) found for this gene \u2014 not enough to align`);o("Selecting a representative protein per species...");let c=await de(i.map(m=>m.geneId),a),s=i.filter(m=>c.has(m.geneId));if(s.length<2)throw new Error("Could not resolve representative proteins for the orthologs");o(`Fetching ${s.length} protein sequences...`);let u=s.map(m=>c.get(m.geneId)),[d,g]=ie({db:"protein",id:u.join(","),rettype:"fasta",retmode:"text"}),x=ge(await S(d,{...g,signal:a})),y=ke(s.map(m=>m.commonName??m.scientificName)),l=s.map((m,h)=>{let p=c.get(m.geneId);return{taxId:m.taxId,label:y[h],scientificName:m.scientificName,commonName:m.commonName,geneId:m.geneId,protein:p,sequence:x.get(p)??""}}).filter(m=>m.sequence);if(l.length<2)throw new Error("Could not fetch protein sequences for the orthologs");return l}var v=(e,t)=>t.some(n=>e instanceof n),le,fe;function ve(){return le||(le=[IDBDatabase,IDBObjectStore,IDBIndex,IDBCursor,IDBTransaction])}function qe(){return fe||(fe=[IDBCursor.prototype.advance,IDBCursor.prototype.continue,IDBCursor.prototype.continuePrimaryKey])}var q=new WeakMap,F=new WeakMap,_=new WeakMap;function Ve(e){let t=new Promise((n,r)=>{let o=()=>{e.removeEventListener("success",a),e.removeEventListener("error",i)},a=()=>{n(w(e.result)),o()},i=()=>{r(e.error),o()};e.addEventListener("success",a),e.addEventListener("error",i)});return _.set(t,e),t}function Ge(e){if(q.has(e))return;let t=new Promise((n,r)=>{let o=()=>{e.removeEventListener("complete",a),e.removeEventListener("error",i),e.removeEventListener("abort",i)},a=()=>{n(),o()},i=()=>{r(e.error||new DOMException("AbortError","AbortError")),o()};e.addEventListener("complete",a),e.addEventListener("error",i),e.addEventListener("abort",i)});q.set(e,t)}var V={get(e,t,n){if(e instanceof IDBTransaction){if(t==="done")return q.get(e);if(t==="store")return n.objectStoreNames[1]?void 0:n.objectStore(n.objectStoreNames[0])}return w(e[t])},set(e,t,n){return e[t]=n,!0},has(e,t){return e instanceof IDBTransaction&&(t==="done"||t==="store")?!0:t in e}};function xe(e){V=e(V)}function Ue(e){return qe().includes(e)?function(...t){return e.apply(G(this),t),w(this.request)}:function(...t){return w(e.apply(G(this),t))}}function We(e){return typeof e=="function"?Ue(e):(e instanceof IDBTransaction&&Ge(e),v(e,ve())?new Proxy(e,V):e)}function w(e){if(e instanceof IDBRequest)return Ve(e);if(F.has(e))return F.get(e);let t=We(e);return t!==e&&(F.set(e,t),_.set(t,e)),t}var G=e=>_.get(e);function we(e,t,{blocked:n,upgrade:r,blocking:o,terminated:a}={}){let i=indexedDB.open(e,t),c=w(i);return r&&i.addEventListener("upgradeneeded",s=>{r(w(i.result),s.oldVersion,s.newVersion,w(i.transaction),s)}),n&&i.addEventListener("blocked",s=>n(s.oldVersion,s.newVersion,s)),c.then(s=>{a&&s.addEventListener("close",()=>a()),o&&s.addEventListener("versionchange",u=>o(u.oldVersion,u.newVersion,u))}).catch(()=>{}),c}var ze=["get","getKey","getAll","getAllKeys","count"],Xe=["put","add","delete","clear"],k=new Map;function he(e,t){if(!(e instanceof IDBDatabase&&!(t in e)&&typeof t=="string"))return;if(k.get(t))return k.get(t);let n=t.replace(/FromIndex$/,""),r=t!==n,o=Xe.includes(n);if(!(n in(r?IDBIndex:IDBObjectStore).prototype)||!(o||ze.includes(n)))return;let a=async function(i,...c){let s=this.transaction(i,o?"readwrite":"readonly"),u=s.store;return r&&(u=u.index(c.shift())),(await Promise.all([u[n](...c),o&&s.done]))[0]};return k.set(t,a),a}xe(e=>({...e,get:(t,n,r)=>he(t,n)||e.get(t,n,r),has:(t,n)=>!!he(t,n)||e.has(t,n)}));var Ke=["continue","continuePrimaryKey","advance"],pe={},U=new WeakMap,ye=new WeakMap,He={get(e,t){if(!Ke.includes(t))return e[t];let n=pe[t];return n||(n=pe[t]=function(...r){U.set(this,ye.get(this)[t](...r))}),n}};async function*Je(...e){let t=this;if(t instanceof IDBCursor||(t=await t.openCursor(...e)),!t)return;t=t;let n=new Proxy(t,He);for(ye.set(n,t),_.set(n,G(t));t;)yield n,t=await(U.get(n)||t.continue()),U.delete(n)}function be(e,t){return t===Symbol.asyncIterator&&v(e,[IDBIndex,IDBObjectStore,IDBCursor])||t==="iterate"&&v(e,[IDBIndex,IDBObjectStore])}xe(e=>({...e,get(t,n,r){return be(t,n)?Je:e.get(t,n,r)},has(t,n){return be(t,n)||e.has(t,n)}}));function R(e,t,n){let r,o=()=>{r=void 0};return()=>(r??=new Promise((a,i)=>{let c=!1;we(e,t,{upgrade:n,blocked(s){c=!0,i(new Error(`${e} is held open at version ${s} by another tab`))},blocking(s,u,d){d.target.close(),o()},terminated:o}).then(s=>{c?s.close():a(s)},i)}).catch(a=>{throw o(),a}),r)}async function B(e,t,n){try{return await t()}catch(r){return console.warn(`[msaview] ${e} failed, continuing without it:`,r),n}}var Qe="jbrowse-msaview-blast-cache",f="blast-results",Ze=2,De=50,W=R(Qe,Ze,(e,t)=>{t<2&&e.objectStoreNames.contains(f)&&e.deleteObjectStore(f),e.objectStoreNames.contains(f)||e.createObjectStore(f,{keyPath:"id"})});function Ye({proteinSequence:e,blastDatabase:t,msaAlgorithm:n,searchProgram:r,transcriptId:o,maxHits:a}){let i=o?`:${o}`:"",c=a===void 0||a===J?"":`:n${a}`;return r==="phmmer"?`phmmer:${t}${i}${c}:${e}`:`${t}:${n}${i}${c}:${e}`}function Nt({proteinSequence:e,blastDatabase:t,msaAlgorithm:n,searchProgram:r,maxHits:o,msa:a,tree:i,treeMetadata:c,rid:s,geneId:u,transcriptId:d,transcriptName:g,geneName:x}){return B("BLAST history write",async()=>{let y=await W(),l={id:Ye({proteinSequence:e,blastDatabase:t,msaAlgorithm:n,searchProgram:r,transcriptId:d,maxHits:o}),proteinSequence:e,blastDatabase:t,msaAlgorithm:n,searchProgram:r,maxHits:o,msa:a,tree:i,treeMetadata:c,rid:s,timestamp:Date.now(),geneId:u,transcriptId:d,transcriptName:g,geneName:x};return await y.put(f,l),await et(y),l},void 0)}async function et(e){try{if(await e.count(f)<=De)return;let t=await e.getAll(f),n=t.toSorted((o,a)=>o.timestamp-a.timestamp).slice(0,t.length-De),r=e.transaction(f,"readwrite");await Promise.all([...n.map(o=>r.store.delete(o.id)),r.done])}catch(t){console.warn("Failed to evict old BLAST cache entries:",t)}}async function Et(){return(await(await W()).getAll(f)).toSorted((n,r)=>r.timestamp-n.timestamp)}async function Mt(e){await(await W()).delete(f,e)}var tt="jbrowse-msaview-taxonomy-cache",T="common-names",nt=2,Se=R(tt,nt,e=>{e.objectStoreNames.contains(T)&&e.deleteObjectStore(T),e.createObjectStore(T,{keyPath:"taxid"})});function rt(e){return B("taxonomy cache read",async()=>{let n=(await Se()).transaction(T,"readonly"),r=await Promise.all(e.map(o=>n.store.get(o)));return await n.done,r},[])}function Ie(e){return B("taxonomy cache write",async()=>{let n=(await Se()).transaction(T,"readwrite");for(let r of e)await n.store.put(r);await n.done},void 0)}async function $t(e,t){let n=[...new Set(e)],r=new Map,o=[],a=await rt(n);for(let s=0;s<n.length;s++){let u=n[s],d=a[s];d?r.set(u,{sciname:d.sciname,commonName:d.commonName}):o.push(u)}if(o.length===0)return r;let i=100,c=[];for(let s=0;s<o.length;s+=i){let u=o.slice(s,s+i),d=u.join(",");try{let g=await S(A({db:"taxonomy",id:d,retmode:"xml"}),{signal:t}),x=new Map,y=/<Taxon>\s*<TaxId>(\d+)<\/TaxId>/g,l;for(;(l=y.exec(g))!==null;){let m=Number(l[1]),h=l.index,p=1,b=h+l[0].length;for(;p>0&&b<g.length;){let O=g.indexOf("<Taxon>",b),$=g.indexOf("</Taxon>",b);if($===-1)break;O!==-1&&O<$?(p++,b=O+7):(p--,b=$+8)}let P=g.slice(h,b),D=x.get(m),C=P.includes("<LineageEx>"),N=D?.includes("<LineageEx>");(!D||C&&!N)&&x.set(m,P)}for(let m of u){let h=x.get(m);if(h){let p=/<GenbankCommonName>(.*?)<\/GenbankCommonName>/.exec(h),b=/<CommonName>(.*?)<\/CommonName>/.exec(h),P=/<ScientificName>(.*?)<\/ScientificName>/.exec(h),D=p?.[1]??b?.[1],C=D&&j(D),N=j(P?.[1]??"");r.set(m,{sciname:N,commonName:C}),c.push({taxid:m,sciname:N,commonName:C})}}}catch(g){if(H(g))throw await Ie(c),g;console.error("Failed to fetch taxonomy data:",g)}}return c.length>0&&await Ie(c),r}export{ot as a,Ce as b,Q as c,st as d,it as e,Ee as f,Me as g,at as h,ct as i,ut as j,mt as k,Ae as l,lt as m,R as n,B as o,Nt as p,Et as q,Mt as r,L as s,A as t,S as u,ce as v,j as w,$e as x,Le as y,wt as z,ke as A,yt as B,Dt as C,$t as D};
|
|
3
|
+
//# sourceMappingURL=chunk-MHBTV7BZ.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["global-externals:@jbrowse/core/util/translateTranscript", "../../src/LaunchMsaView/util.ts", "../../src/LaunchMsaView/components/fetchSeq.ts", "../../src/utils/eutils.ts", "../../src/utils/ncbiOrthologs.ts", "../../node_modules/.pnpm/idb@8.0.3/node_modules/idb/build/index.js", "../../src/utils/idb.ts", "../../src/utils/blastCache.ts", "../../src/utils/taxonomyNames.ts"],
|
|
4
|
+
"sourcesContent": ["module.exports = JBrowseExports[\"@jbrowse/core/util/translateTranscript\"];", "import { getContainingView, sum } from '@jbrowse/core/util'\n\nimport type { AbstractTrackModel, Feature } from '@jbrowse/core/util'\nimport type { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'\n\nexport function getLinearGenomeView(model: AbstractTrackModel) {\n return getContainingView(model) as LinearGenomeViewModel\n}\n\nfunction isNonEmptyString(v: unknown): v is string {\n return typeof v === 'string' && v !== ''\n}\n\nfunction uniqueDefined(vals: unknown[]): string[] {\n return [...new Set(vals.filter(isNonEmptyString))]\n}\n\nfunction joinDefined(sep: string, parts: unknown[]): string {\n return parts.filter(isNonEmptyString).join(sep)\n}\n\nexport function getTranscriptFeatures(feature: Feature) {\n // check if we are looking at a 'two-level' or 'three-level' feature by\n // finding exon/CDS subfeatures. we want to select from transcript names\n const subfeatures = feature.get('subfeatures') ?? []\n\n // Check for mRNA/transcript subfeatures (three-level: gene \u2192 mRNA \u2192 CDS)\n // Filter to only those that have CDS subfeatures (i.e. are coding)\n const transcripts = subfeatures.filter(\n (f: Feature) =>\n (f.get('type') === 'mRNA' || f.get('type') === 'transcript') &&\n f.get('subfeatures')?.some((s: Feature) => s.get('type') === 'CDS'),\n )\n if (transcripts.length > 0) {\n return transcripts\n }\n\n // Has direct CDS children, treat feature itself as the transcript\n // (two-level: gene \u2192 CDS or mRNA \u2192 CDS)\n return [feature]\n}\n\nexport function getTranscriptLength(feature: Feature) {\n const cdsLen = sum(\n feature\n .get('subfeatures')\n ?.filter(f => f.get('type') === 'CDS')\n .map(s => s.get('end') - s.get('start')) ?? [],\n )\n return {\n len: Math.floor(cdsLen / 3),\n mod: cdsLen % 3,\n }\n}\nexport function getId(val?: Feature): string {\n return val?.id() ?? ''\n}\n\nfunction getMatchableIds(val?: Feature): string[] {\n return val\n ? uniqueDefined([\n val.id(),\n val.get('name'),\n val.get('id'),\n val.get('transcript_id'),\n ])\n : []\n}\n\nexport function featureMatchesId(feature: Feature, id: string): boolean {\n return getMatchableIds(feature).includes(id)\n}\n\nexport function getTranscriptDisplayName(val?: Feature) {\n return val ? joinDefined(' ', [val.get('name'), val.get('id')]) : ''\n}\n\nexport function getGeneDisplayName(val?: Feature) {\n return val\n ? joinDefined(' ', [\n val.get('gene_name') ?? val.get('name'),\n val.get('id') ? `(${val.get('id')})` : undefined,\n ])\n : ''\n}\n\nexport function getBlastViewTitle(feature: Feature, transcript: Feature) {\n return `BLAST - ${getGeneDisplayName(feature)} - ${getTranscriptDisplayName(transcript)}`\n}\n\nexport function getSortedTranscriptFeatures(feature: Feature) {\n const transcripts = getTranscriptFeatures(feature)\n return transcripts.toSorted(\n (a, b) => getTranscriptLength(b).len - getTranscriptLength(a).len,\n )\n}\n\n/**\n * A translation as a query, still one residue per codon: g2p numbers codons,\n * and the query row is read through it. So the partial first codon (`&`), an\n * internal stop and an unreadable codon become X, and only what trails the\n * last whole codon is dropped.\n */\nexport function cleanProteinSequence(seq: string) {\n return seq.replace(/[*&]+$/, '').replaceAll(/[*&]/g, 'X')\n}\n\nexport function getGeneIdentifiers(feature: Feature): string[] {\n return uniqueDefined([\n feature.id(),\n feature.get('id'),\n feature.get('name'),\n feature.get('gene_id'),\n feature.get('gene_name'),\n ])\n}\n", "import { getConf } from '@jbrowse/core/configuration'\n\nimport type { AbstractSessionModel } from '@jbrowse/core/util'\n\nexport async function fetchSeq({\n start,\n end,\n refName,\n session,\n assemblyName,\n}: {\n start: number\n end: number\n refName: string\n assemblyName: string\n session: AbstractSessionModel\n}) {\n const { assemblyManager, rpcManager } = session\n const assembly = await assemblyManager.waitForAssembly(assemblyName)\n if (!assembly) {\n throw new Error('assembly not found')\n }\n const feats = await rpcManager.call('getSequence', 'CoreGetFeatures', {\n adapterConfig: getConf(assembly, ['sequence', 'adapter']),\n regions: [\n {\n start,\n end,\n refName: assembly.getCanonicalRefName(refName) ?? refName,\n assemblyName,\n },\n ],\n })\n return {\n seq: (feats[0]?.get('seq') as string | undefined) ?? '',\n // travels with the sequence because the caller needs both to translate, and\n // resolving the assembly twice to get them is the shape that lost it\n assemblyGeneticCodeId: assembly.getGeneticCodeId(refName),\n }\n}\n", "import { jsonfetch, textfetch, timeout } from './fetch'\n\n// NCBI asks that programmatic E-utilities requests identify themselves with a\n// tool name and contact email so they can reach out before throttling, rather\n// than silently rate-limiting. https://www.ncbi.nlm.nih.gov/books/NBK25497/\nconst NCBI_TOOL = 'jbrowse-plugin-msaview'\nconst NCBI_EMAIL = 'colin.diesh@gmail.com'\n\nconst EUTILS = 'https://eutils.ncbi.nlm.nih.gov/entrez/eutils'\n\ntype Endpoint = 'efetch' | 'esearch' | 'esummary'\n\nfunction identified(params: Record<string, string>) {\n return new URLSearchParams({ ...params, tool: NCBI_TOOL, email: NCBI_EMAIL })\n}\n\nexport function eutilsUrl(endpoint: Endpoint, params: Record<string, string>) {\n return `${EUTILS}/${endpoint}.fcgi?${identified(params).toString()}`\n}\n\nexport function efetchUrl(params: Record<string, string>) {\n return eutilsUrl('efetch', params)\n}\n\n/**\n * The same request as a POST body. An `id` list of a few hundred accessions\n * exceeds what a URL carries \u2014 865 of them is ~13KB \u2014 and NCBI documents POST\n * as the route above about 200 ids. eutils sends `ACAO: *` on both verbs.\n */\nexport function efetchPost(params: Record<string, string>) {\n return [\n `${EUTILS}/efetch.fcgi`,\n { method: 'POST', body: identified(params) },\n ] as const\n}\n\n/**\n * eutils allows 3 requests a second without an API key and answers a burst\n * over that with no `Access-Control-Allow-Origin`, which the browser reports as\n * a CORS failure. Every eutils request takes the next start slot, so however\n * many callers ask at once the requests go out under the limit.\n */\nexport const EUTILS_SPACING_MS = 350\n\nlet nextSlot = 0\n\nasync function eutilsSlot(signal?: AbortSignal | null) {\n const now = Date.now()\n const start = Math.max(now, nextSlot)\n nextSlot = start + EUTILS_SPACING_MS\n if (start > now) {\n try {\n await timeout(start - now, signal ?? undefined)\n } catch (e) {\n if (nextSlot === start + EUTILS_SPACING_MS) {\n nextSlot = start\n }\n throw e\n }\n }\n}\n\nexport async function eutilsText(url: string, init?: RequestInit) {\n await eutilsSlot(init?.signal)\n return textfetch(url, init)\n}\n\nexport async function eutilsJson<T>(url: string, init?: RequestInit) {\n await eutilsSlot(init?.signal)\n return jsonfetch<T>(url, init)\n}\n\nconst namedEntities: Record<string, string> = {\n amp: '&',\n apos: \"'\",\n gt: '>',\n lt: '<',\n quot: '\"',\n}\n\n/** Text lifted out of eutils XML still carries its escapes: `5'-3'`. */\nexport function decodeXmlEntities(text: string) {\n return text.replaceAll(\n /&(#x[\\da-f]+|#\\d+|[a-z]+);/gi,\n (entity, name: string) =>\n name.startsWith('#x') || name.startsWith('#X')\n ? String.fromCodePoint(Number.parseInt(name.slice(2), 16))\n : name.startsWith('#')\n ? String.fromCodePoint(Number(name.slice(1)))\n : (namedEntities[name] ?? entity),\n )\n}\n", "// Homolog discovery WITHOUT a search job.\n//\n// The BLAST path answers \"what looks like this sequence\", which is not the\n// question an MSA row set wants \u2014 it wants \"what is homologous to this gene,\n// one per species, labelled by species\". BLAST then costs 10+ minutes to\n// return a redundant, accession-labelled hit list that has to be deduplicated\n// before it reads. NCBI has already computed the answer: the Datasets\n// orthologs endpoint returns one ortholog gene per species, instantly.\n//\n// gene symbol -> gene id -> orthologs -> a representative protein each ->\n// sequences, all from NCBI, in a handful of requests. The caller aligns them\n// (EBI Clustal Omega, ~10s) and overlays CDD domains, which are already baked\n// into the GenPept records (see ncbiDomains.ts).\n//\n// Mirrors jb2hubs' website/src/components/proteinMsa.ts assembler, trimmed to\n// what the launch dialog needs and using this plugin's fetch/eutils helpers.\n\nimport {\n efetchPost,\n efetchUrl,\n eutilsJson,\n eutilsText,\n eutilsUrl,\n} from './eutils'\nimport { jsonfetch } from './fetch'\n\n// v2, not v2alpha: the alpha path still answers /orthologs but 404s\n// /product_report, so an assembler pointed at it silently resolves zero\n// representative proteins and reports \"no orthologs\" for every gene.\nconst DATASETS = 'https://api.ncbi.nlm.nih.gov/datasets/v2'\n\n// NCBI's ortholog report IS the species panel. There is no list here to keep in\n// step with what NCBI knows, and the panel widens by itself as NCBI annotates\n// more genomes.\n//\n// It used to be a hand-written 23-species list intersected with the report, and\n// the intersection is what made the alignment thin: NCBI publishes 165 orthologs\n// for human NLRP1 and 865 for CFTR, so the list kept 12 of the first and 19 of\n// the second. It also carried four species -- fruitfly, yeast, C. elegans and\n// arabidopsis -- that the endpoint has never once returned for a human gene:\n// checked against NLRP1, TP53, ACTB, BRCA1, PIK3CA, APOE and NOTCH1, whose fly\n// ortholog is famous and still absent. NCBI's ortholog sets are vertebrate\n// scoped.\n//\n// The report's OWN order is the ladder the list was hand-built to approximate,\n// and it is per gene. CFTR opens human, mouse, rat, zebrafish, pig, sheep,\n// rabbit, chicken, cattle, ferret, dog, rhesus; NLRP1, which has no ortholog\n// outside placental mammals, opens human, mouse, rhesus, shrew mouse, chimp,\n// dog, cattle, horse. So `limit` takes a prefix and never needs a rank table.\n//\n// The rows are SUBMITTED in that order, not drawn in it -- the view lays rows out\n// by the guide tree the aligner returns.\n//\n// What limits the row count is the aligner, and it is linear in rows at roughly\n// half a second each for a ~1400aa protein: 165 NLRP1 orthologs align at EBI in\n// 88s, 865 CFTR orthologs in 407s. `defaultMaxSpecies` keeps a default run under\n// a minute; EBI's own ceiling is 4000 sequences and 4MB, which even CFTR's full\n// set (1.3MB) sits inside.\nexport const defaultMaxSpecies = 100\n\nexport interface OrthologRow {\n taxId: number\n /** single-token id used identically in the FASTA, the tree and the domain GFF */\n label: string\n scientificName: string\n commonName?: string\n geneId: string\n /** accession.version */\n protein: string\n sequence: string\n}\n\n/**\n * A candidate gene reference as the ortholog services know it: a GFF ID prefix\n * (gene:TP53) and a version suffix (NM_000546.6) stripped off. Shared with\n * pantherOrthologs, which asks PANTHER the same question with the same\n * candidates.\n */\nexport function cleanGeneCandidate(raw: string) {\n return raw\n .trim()\n .replace(/^\\w+:/, '')\n .replace(/\\.\\d+$/, '')\n}\n\n/**\n * A free-text gene reference -> NCBI gene id. A bare number is taken as the id\n * itself; anything else is searched as a gene name within the query taxon.\n * Several candidate identifiers are tried in order, because a JBrowse feature\n * carries whatever its GFF/BigBed had \u2014 `id()`, `name`, `gene_name` \u2014 and only\n * some of those are real symbols. `gene:TP53` and `TP53` are one search.\n */\nexport async function resolveGeneId(\n candidates: string[],\n taxId: number,\n signal?: AbortSignal,\n): Promise<{ geneId: string; matched: string } | undefined> {\n const asked = new Set<string>()\n for (const raw of candidates) {\n const query = raw.trim()\n if (/^\\d+$/.test(query)) {\n return { geneId: query, matched: query }\n }\n const cleaned = cleanGeneCandidate(query)\n if (!cleaned || asked.has(cleaned)) {\n continue\n }\n asked.add(cleaned)\n const json = await eutilsJson<{\n esearchresult?: { idlist?: string[] }\n }>(\n eutilsUrl('esearch', {\n db: 'gene',\n term: `${cleaned}[Gene Name] AND ${taxId}[taxid]`,\n retmode: 'json',\n retmax: '1',\n }),\n { signal },\n )\n const geneId = json.esearchresult?.idlist?.[0]\n if (geneId) {\n return { geneId, matched: cleaned }\n }\n }\n return undefined\n}\n\ninterface OrthologReport {\n reports?: {\n gene?: {\n gene_id?: string\n tax_id?: string | number\n taxname?: string\n common_name?: string\n }\n }[]\n}\n\n/**\n * One ortholog gene per species, in NCBI's report order, capped at `limit`.\n *\n * `taxa` narrows the set when a caller wants specific species; omitted, every\n * species NCBI has an ortholog for is a candidate. `exclude` drops the query\n * taxon, which already has its own `<species>_query` row.\n */\nexport async function fetchOrthologGenes(\n geneId: string,\n {\n taxa,\n exclude,\n limit = defaultMaxSpecies,\n signal,\n }: {\n taxa?: Set<number>\n exclude?: number\n limit?: number\n signal?: AbortSignal\n } = {},\n) {\n const json = await jsonfetch<OrthologReport>(\n `${DATASETS}/gene/id/${geneId}/orthologs?returned_content=COMPLETE`,\n { signal },\n )\n const byTaxon = new Map<\n number,\n {\n taxId: number\n geneId: string\n scientificName: string\n commonName?: string\n }\n >()\n for (const { gene } of json.reports ?? []) {\n const taxId = Number(gene?.tax_id)\n if (\n gene?.gene_id &&\n taxId !== exclude &&\n (taxa?.has(taxId) ?? true) &&\n !byTaxon.has(taxId)\n ) {\n byTaxon.set(taxId, {\n taxId,\n geneId: gene.gene_id,\n scientificName: gene.taxname ?? String(taxId),\n commonName: gene.common_name,\n })\n }\n if (byTaxon.size >= limit) {\n break\n }\n }\n return [...byTaxon.values()]\n}\n\ninterface ProductReport {\n reports?: {\n product?: {\n gene_id?: string\n transcripts?: {\n select_category?: string\n protein?: { accession_version?: string; length?: number }\n }[]\n }\n }[]\n}\n\n// Two ceilings sit between a gene id list and its product report, and both fail\n// by returning less rather than by erroring, so a caller that ignores them just\n// draws a thinner alignment.\n//\n// The ids go in the URL PATH, and NCBI answers HTTP 414 above roughly 8KB of\n// them -- CFTR's 865 orthologs join to 8609 characters and 414 on the nose.\n// `PRODUCT_REPORT_CHUNK` keeps a request well inside that.\n//\n// Then the endpoint paginates at 20 with the count in `total_count` and the rest\n// behind `next_page_token`, which is invisible to a caller reading `reports`.\n// `page_size` covers a chunk in one request. The old 23-species panel never\n// reached this: the query taxon is excluded and NCBI has no ortholog for the\n// four invertebrate entries, so its ceiling was 19.\nconst PRODUCT_REPORT_CHUNK = 150\n\n/**\n * geneId -> representative protein accession: MANE Select where flagged, else\n * the longest isoform. A stable, comparable choice across species \u2014 picking\n * \"the first\" would silently vary with NCBI's ordering.\n */\nexport async function fetchRepresentativeProteins(\n geneIds: string[],\n signal?: AbortSignal,\n) {\n const byGene = new Map<string, string>()\n for (let i = 0; i < geneIds.length; i += PRODUCT_REPORT_CHUNK) {\n const chunk = geneIds.slice(i, i + PRODUCT_REPORT_CHUNK)\n const json = await jsonfetch<ProductReport>(\n `${DATASETS}/gene/id/${chunk.join(',')}/product_report?page_size=${chunk.length}`,\n { signal },\n )\n for (const { product } of json.reports ?? []) {\n const candidates = (product?.transcripts ?? [])\n .map(t => ({\n acc: t.protein?.accession_version,\n len: t.protein?.length ?? 0,\n mane: /select/i.test(t.select_category ?? ''),\n }))\n .filter(\n (c): c is { acc: string; len: number; mane: boolean } => !!c.acc,\n )\n const best =\n candidates.find(c => c.mane) ??\n [...candidates].sort((a, b) => b.len - a.len).at(0)\n if (product?.gene_id && best) {\n byGene.set(product.gene_id, best.acc)\n }\n }\n }\n return byGene\n}\n\n/** accession (first header token) -> ungapped sequence, from a multi-FASTA. */\nexport function parseFasta(text: string) {\n const map = new Map<string, string>()\n let acc: string | undefined\n let buf: string[] = []\n for (const line of text.split('\\n')) {\n if (line.startsWith('>')) {\n if (acc) {\n map.set(acc, buf.join(''))\n }\n acc = line.slice(1).split(/\\s+/)[0]\n buf = []\n } else {\n buf.push(line.trim())\n }\n }\n if (acc) {\n map.set(acc, buf.join(''))\n }\n return map\n}\n\nfunction sanitize(name: string) {\n return name.replace(/[^A-Za-z0-9]+/g, '_').replace(/^_+|_+$/g, '')\n}\n\n/**\n * Sanitized, unique single-token labels used identically in the FASTA headers,\n * the tree leaf names and the domain GFF seq_ids \u2014 that identity is how the\n * viewer pairs a tree leaf to its alignment row to its domain track. Collisions\n * get a numeric suffix rather than silently overwriting a row, and the suffix\n * climbs past labels already emitted: a species genuinely named `human_2` would\n * otherwise take the label the second `human` is about to get, merging two rows\n * into one.\n */\nexport function dedupeLabels(names: string[]) {\n const used = new Set<string>()\n return names.map(name => {\n const base = sanitize(name) || 'row'\n let label = base\n let n = 1\n while (used.has(label)) {\n n += 1\n label = `${base}_${n}`\n }\n used.add(label)\n return label\n })\n}\n\n/**\n * The representative protein for a single gene, with its sequence. Used to\n * decide whether the user's own translated transcript is byte-identical to the\n * RefSeq protein \u2014 if it is, that accession's precomputed CDD domains apply to\n * the query row exactly, and if it isn't, they would land at an offset.\n */\nexport async function fetchProteinForGene(\n geneId: string,\n signal?: AbortSignal,\n) {\n const acc = (await fetchRepresentativeProteins([geneId], signal)).get(geneId)\n if (!acc) {\n return undefined\n }\n const seq = parseFasta(\n await eutilsText(\n efetchUrl({ db: 'protein', id: acc, rettype: 'fasta', retmode: 'text' }),\n { signal },\n ),\n ).get(acc)\n return seq ? { accession: acc, sequence: seq } : undefined\n}\n\n/**\n * The whole NCBI half of the pipeline: gene -> ortholog rows carrying labels,\n * accessions and sequences. Everything here is a precomputed lookup, so this\n * returns in seconds rather than the 10+ minutes a BLAST submission costs.\n */\nexport async function fetchOrthologRows({\n geneId,\n taxa,\n exclude,\n limit,\n onProgress,\n signal,\n}: {\n geneId: string\n taxa?: Set<number>\n exclude?: number\n limit?: number\n onProgress: (arg: string) => void\n signal?: AbortSignal\n}): Promise<OrthologRow[]> {\n onProgress('Finding orthologs across species...')\n const genes = await fetchOrthologGenes(geneId, {\n taxa,\n exclude,\n limit,\n signal,\n })\n if (genes.length < 2) {\n throw new Error(\n `Only ${genes.length} ortholog(s) found for this gene \u2014 not enough to align`,\n )\n }\n\n onProgress('Selecting a representative protein per species...')\n const proteinByGene = await fetchRepresentativeProteins(\n genes.map(g => g.geneId),\n signal,\n )\n const withProtein = genes.filter(g => proteinByGene.has(g.geneId))\n if (withProtein.length < 2) {\n throw new Error(\n 'Could not resolve representative proteins for the orthologs',\n )\n }\n\n onProgress(`Fetching ${withProtein.length} protein sequences...`)\n const accessions = withProtein.map(g => proteinByGene.get(g.geneId)!)\n const [efetch, init] = efetchPost({\n db: 'protein',\n id: accessions.join(','),\n rettype: 'fasta',\n retmode: 'text',\n })\n const seqByAcc = parseFasta(await eutilsText(efetch, { ...init, signal }))\n\n const labels = dedupeLabels(\n withProtein.map(g => g.commonName ?? g.scientificName),\n )\n const rows = withProtein\n .map((g, i) => {\n const protein = proteinByGene.get(g.geneId)!\n return {\n taxId: g.taxId,\n label: labels[i]!,\n scientificName: g.scientificName,\n commonName: g.commonName,\n geneId: g.geneId,\n protein,\n sequence: seqByAcc.get(protein) ?? '',\n }\n })\n .filter(r => r.sequence)\n if (rows.length < 2) {\n throw new Error('Could not fetch protein sequences for the orthologs')\n }\n return rows\n}\n", "const instanceOfAny = (object, constructors) => constructors.some((c) => object instanceof c);\n\nlet idbProxyableTypes;\nlet cursorAdvanceMethods;\n// This is a function to prevent it throwing up in node environments.\nfunction getIdbProxyableTypes() {\n return (idbProxyableTypes ||\n (idbProxyableTypes = [\n IDBDatabase,\n IDBObjectStore,\n IDBIndex,\n IDBCursor,\n IDBTransaction,\n ]));\n}\n// This is a function to prevent it throwing up in node environments.\nfunction getCursorAdvanceMethods() {\n return (cursorAdvanceMethods ||\n (cursorAdvanceMethods = [\n IDBCursor.prototype.advance,\n IDBCursor.prototype.continue,\n IDBCursor.prototype.continuePrimaryKey,\n ]));\n}\nconst transactionDoneMap = new WeakMap();\nconst transformCache = new WeakMap();\nconst reverseTransformCache = new WeakMap();\nfunction promisifyRequest(request) {\n const promise = new Promise((resolve, reject) => {\n const unlisten = () => {\n request.removeEventListener('success', success);\n request.removeEventListener('error', error);\n };\n const success = () => {\n resolve(wrap(request.result));\n unlisten();\n };\n const error = () => {\n reject(request.error);\n unlisten();\n };\n request.addEventListener('success', success);\n request.addEventListener('error', error);\n });\n // This mapping exists in reverseTransformCache but doesn't exist in transformCache. This\n // is because we create many promises from a single IDBRequest.\n reverseTransformCache.set(promise, request);\n return promise;\n}\nfunction cacheDonePromiseForTransaction(tx) {\n // Early bail if we've already created a done promise for this transaction.\n if (transactionDoneMap.has(tx))\n return;\n const done = new Promise((resolve, reject) => {\n const unlisten = () => {\n tx.removeEventListener('complete', complete);\n tx.removeEventListener('error', error);\n tx.removeEventListener('abort', error);\n };\n const complete = () => {\n resolve();\n unlisten();\n };\n const error = () => {\n reject(tx.error || new DOMException('AbortError', 'AbortError'));\n unlisten();\n };\n tx.addEventListener('complete', complete);\n tx.addEventListener('error', error);\n tx.addEventListener('abort', error);\n });\n // Cache it for later retrieval.\n transactionDoneMap.set(tx, done);\n}\nlet idbProxyTraps = {\n get(target, prop, receiver) {\n if (target instanceof IDBTransaction) {\n // Special handling for transaction.done.\n if (prop === 'done')\n return transactionDoneMap.get(target);\n // Make tx.store return the only store in the transaction, or undefined if there are many.\n if (prop === 'store') {\n return receiver.objectStoreNames[1]\n ? undefined\n : receiver.objectStore(receiver.objectStoreNames[0]);\n }\n }\n // Else transform whatever we get back.\n return wrap(target[prop]);\n },\n set(target, prop, value) {\n target[prop] = value;\n return true;\n },\n has(target, prop) {\n if (target instanceof IDBTransaction &&\n (prop === 'done' || prop === 'store')) {\n return true;\n }\n return prop in target;\n },\n};\nfunction replaceTraps(callback) {\n idbProxyTraps = callback(idbProxyTraps);\n}\nfunction wrapFunction(func) {\n // Due to expected object equality (which is enforced by the caching in `wrap`), we\n // only create one new func per func.\n // Cursor methods are special, as the behaviour is a little more different to standard IDB. In\n // IDB, you advance the cursor and wait for a new 'success' on the IDBRequest that gave you the\n // cursor. It's kinda like a promise that can resolve with many values. That doesn't make sense\n // with real promises, so each advance methods returns a new promise for the cursor object, or\n // undefined if the end of the cursor has been reached.\n if (getCursorAdvanceMethods().includes(func)) {\n return function (...args) {\n // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use\n // the original object.\n func.apply(unwrap(this), args);\n return wrap(this.request);\n };\n }\n return function (...args) {\n // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use\n // the original object.\n return wrap(func.apply(unwrap(this), args));\n };\n}\nfunction transformCachableValue(value) {\n if (typeof value === 'function')\n return wrapFunction(value);\n // This doesn't return, it just creates a 'done' promise for the transaction,\n // which is later returned for transaction.done (see idbObjectHandler).\n if (value instanceof IDBTransaction)\n cacheDonePromiseForTransaction(value);\n if (instanceOfAny(value, getIdbProxyableTypes()))\n return new Proxy(value, idbProxyTraps);\n // Return the same value back if we're not going to transform it.\n return value;\n}\nfunction wrap(value) {\n // We sometimes generate multiple promises from a single IDBRequest (eg when cursoring), because\n // IDB is weird and a single IDBRequest can yield many responses, so these can't be cached.\n if (value instanceof IDBRequest)\n return promisifyRequest(value);\n // If we've already transformed this value before, reuse the transformed value.\n // This is faster, but it also provides object equality.\n if (transformCache.has(value))\n return transformCache.get(value);\n const newValue = transformCachableValue(value);\n // Not all types are transformed.\n // These may be primitive types, so they can't be WeakMap keys.\n if (newValue !== value) {\n transformCache.set(value, newValue);\n reverseTransformCache.set(newValue, value);\n }\n return newValue;\n}\nconst unwrap = (value) => reverseTransformCache.get(value);\n\n/**\n * Open a database.\n *\n * @param name Name of the database.\n * @param version Schema version.\n * @param callbacks Additional callbacks.\n */\nfunction openDB(name, version, { blocked, upgrade, blocking, terminated } = {}) {\n const request = indexedDB.open(name, version);\n const openPromise = wrap(request);\n if (upgrade) {\n request.addEventListener('upgradeneeded', (event) => {\n upgrade(wrap(request.result), event.oldVersion, event.newVersion, wrap(request.transaction), event);\n });\n }\n if (blocked) {\n request.addEventListener('blocked', (event) => blocked(\n // Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405\n event.oldVersion, event.newVersion, event));\n }\n openPromise\n .then((db) => {\n if (terminated)\n db.addEventListener('close', () => terminated());\n if (blocking) {\n db.addEventListener('versionchange', (event) => blocking(event.oldVersion, event.newVersion, event));\n }\n })\n .catch(() => { });\n return openPromise;\n}\n/**\n * Delete a database.\n *\n * @param name Name of the database.\n */\nfunction deleteDB(name, { blocked } = {}) {\n const request = indexedDB.deleteDatabase(name);\n if (blocked) {\n request.addEventListener('blocked', (event) => blocked(\n // Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405\n event.oldVersion, event));\n }\n return wrap(request).then(() => undefined);\n}\n\nconst readMethods = ['get', 'getKey', 'getAll', 'getAllKeys', 'count'];\nconst writeMethods = ['put', 'add', 'delete', 'clear'];\nconst cachedMethods = new Map();\nfunction getMethod(target, prop) {\n if (!(target instanceof IDBDatabase &&\n !(prop in target) &&\n typeof prop === 'string')) {\n return;\n }\n if (cachedMethods.get(prop))\n return cachedMethods.get(prop);\n const targetFuncName = prop.replace(/FromIndex$/, '');\n const useIndex = prop !== targetFuncName;\n const isWrite = writeMethods.includes(targetFuncName);\n if (\n // Bail if the target doesn't exist on the target. Eg, getAll isn't in Edge.\n !(targetFuncName in (useIndex ? IDBIndex : IDBObjectStore).prototype) ||\n !(isWrite || readMethods.includes(targetFuncName))) {\n return;\n }\n const method = async function (storeName, ...args) {\n // isWrite ? 'readwrite' : undefined gzipps better, but fails in Edge :(\n const tx = this.transaction(storeName, isWrite ? 'readwrite' : 'readonly');\n let target = tx.store;\n if (useIndex)\n target = target.index(args.shift());\n // Must reject if op rejects.\n // If it's a write operation, must reject if tx.done rejects.\n // Must reject with op rejection first.\n // Must resolve with op value.\n // Must handle both promises (no unhandled rejections)\n return (await Promise.all([\n target[targetFuncName](...args),\n isWrite && tx.done,\n ]))[0];\n };\n cachedMethods.set(prop, method);\n return method;\n}\nreplaceTraps((oldTraps) => ({\n ...oldTraps,\n get: (target, prop, receiver) => getMethod(target, prop) || oldTraps.get(target, prop, receiver),\n has: (target, prop) => !!getMethod(target, prop) || oldTraps.has(target, prop),\n}));\n\nconst advanceMethodProps = ['continue', 'continuePrimaryKey', 'advance'];\nconst methodMap = {};\nconst advanceResults = new WeakMap();\nconst ittrProxiedCursorToOriginalProxy = new WeakMap();\nconst cursorIteratorTraps = {\n get(target, prop) {\n if (!advanceMethodProps.includes(prop))\n return target[prop];\n let cachedFunc = methodMap[prop];\n if (!cachedFunc) {\n cachedFunc = methodMap[prop] = function (...args) {\n advanceResults.set(this, ittrProxiedCursorToOriginalProxy.get(this)[prop](...args));\n };\n }\n return cachedFunc;\n },\n};\nasync function* iterate(...args) {\n // tslint:disable-next-line:no-this-assignment\n let cursor = this;\n if (!(cursor instanceof IDBCursor)) {\n cursor = await cursor.openCursor(...args);\n }\n if (!cursor)\n return;\n cursor = cursor;\n const proxiedCursor = new Proxy(cursor, cursorIteratorTraps);\n ittrProxiedCursorToOriginalProxy.set(proxiedCursor, cursor);\n // Map this double-proxy back to the original, so other cursor methods work.\n reverseTransformCache.set(proxiedCursor, unwrap(cursor));\n while (cursor) {\n yield proxiedCursor;\n // If one of the advancing methods was not called, call continue().\n cursor = await (advanceResults.get(proxiedCursor) || cursor.continue());\n advanceResults.delete(proxiedCursor);\n }\n}\nfunction isIteratorProp(target, prop) {\n return ((prop === Symbol.asyncIterator &&\n instanceOfAny(target, [IDBIndex, IDBObjectStore, IDBCursor])) ||\n (prop === 'iterate' && instanceOfAny(target, [IDBIndex, IDBObjectStore])));\n}\nreplaceTraps((oldTraps) => ({\n ...oldTraps,\n get(target, prop, receiver) {\n if (isIteratorProp(target, prop))\n return iterate;\n return oldTraps.get(target, prop, receiver);\n },\n has(target, prop) {\n return isIteratorProp(target, prop) || oldTraps.has(target, prop);\n },\n}));\n\nexport { deleteDB, openDB, unwrap, wrap };\n", "import { openDB } from 'idb'\n\nimport type { DBSchema, IDBPDatabase, OpenDBCallbacks } from 'idb'\n\n/**\n * Memoized `openDB` for a typed schema, shared by this plugin's caches.\n *\n * Callers share one connection. The opener forgets it whenever it stops being\n * usable, so the next call opens a fresh one instead of replaying a rejection\n * or waiting on a dead handle: when the open fails (IndexedDB is unavailable in\n * some private-browsing modes), when another tab is blocked upgrading the\n * database and this connection steps aside for it, and when the browser\n * terminates the connection.\n *\n * An open blocked by another tab's older connection rejects rather than waiting\n * for that tab to close, which may never happen, since a build that predates\n * `blocking` never steps aside.\n *\n * Passing a DBSchema is what keeps `get`/`getAll` from returning `any`: with an\n * untyped database every cached record reaches the UI unchecked.\n */\nexport function createDbOpener<T extends DBSchema>(\n name: string,\n version: number,\n upgrade: OpenDBCallbacks<T>['upgrade'],\n) {\n let dbPromise: Promise<IDBPDatabase<T>> | undefined\n const forget = () => {\n dbPromise = undefined\n }\n return () => {\n dbPromise ??= new Promise<IDBPDatabase<T>>((resolve, reject) => {\n let gaveUp = false\n openDB<T>(name, version, {\n upgrade,\n blocked(currentVersion) {\n gaveUp = true\n reject(\n new Error(\n `${name} is held open at version ${currentVersion} by another tab`,\n ),\n )\n },\n blocking(_currentVersion, _blockedVersion, event) {\n ;(event.target as IDBDatabase).close()\n forget()\n },\n terminated: forget,\n }).then(db => {\n if (gaveUp) {\n db.close()\n } else {\n resolve(db)\n }\n }, reject)\n }).catch((e: unknown) => {\n forget()\n throw e\n })\n return dbPromise\n }\n}\n\n/**\n * Run a cache operation that the caller can do without. A cache only saves\n * work, so a read that fails answers `fallback` (a miss) and a write that fails\n * is skipped: neither may cost the user a search that already finished.\n */\nexport async function bestEffort<R>(\n what: string,\n operation: () => Promise<R>,\n fallback: R,\n) {\n try {\n return await operation()\n } catch (e) {\n console.warn(`[msaview] ${what} failed, continuing without it:`, e)\n return fallback\n }\n}\n", "import { defaultMaxHits } from '../LaunchMsaView/components/BlastQuery/consts'\nimport { bestEffort, createDbOpener } from './idb'\n\nimport type {\n BlastDatabase,\n MsaAlgorithm,\n PhmmerDatabase,\n SearchProgram,\n} from '../LaunchMsaView/components/BlastQuery/consts'\nimport type { DBSchema, IDBPDatabase } from 'idb'\n\nconst DB_NAME = 'jbrowse-msaview-blast-cache'\nconst STORE_NAME = 'blast-results'\nconst DB_VERSION = 2\n\n/**\n * How many results the history keeps. Every row holds a whole alignment and its\n * tree \u2014 megabytes each \u2014 so an unbounded store grows until the browser starts\n * refusing writes to it, and the user never sees why.\n */\nconst MAX_CACHED_RESULTS = 50\n\nexport interface CachedBlastResult {\n id: string\n proteinSequence: string\n blastDatabase: BlastDatabase | PhmmerDatabase\n /**\n * Only ever set on rows cached by a version that still queried NCBI, where\n * the choice between blastp and quick-blastp was real. Kept so those rows\n * still display; never written now.\n */\n blastProgram?: string\n /** absent on rows cached before phmmer existed, which were all blastp */\n searchProgram?: SearchProgram\n /** absent on phmmer rows, which are aligned by the search itself */\n msaAlgorithm?: MsaAlgorithm\n /** absent on rows saved before it was recorded */\n maxHits?: number\n msa: string\n tree: string\n treeMetadata: string\n rid: string\n timestamp: number\n geneId?: string\n transcriptId?: string\n transcriptName?: string\n geneName?: string\n}\n\ninterface BlastCacheDB extends DBSchema {\n [STORE_NAME]: {\n key: string\n value: CachedBlastResult\n }\n}\n\nconst getDB = createDbOpener<BlastCacheDB>(\n DB_NAME,\n DB_VERSION,\n (db, oldVersion) => {\n if (oldVersion < 2 && db.objectStoreNames.contains(STORE_NAME)) {\n db.deleteObjectStore(STORE_NAME)\n }\n if (!db.objectStoreNames.contains(STORE_NAME)) {\n db.createObjectStore(STORE_NAME, { keyPath: 'id' })\n }\n },\n)\n\n/**\n * One history row per distinct search. Every input that changes the stored\n * alignment is in the key, or re-running the query with another aligner or hit\n * count overwrites the earlier row. A part added later is left out at its old\n * value so rows saved before it still resolve: phmmer keys are prefixed and\n * blastp keys are not, and the hit count appears only when it is not the\n * default.\n */\nexport function createCacheKey({\n proteinSequence,\n blastDatabase,\n msaAlgorithm,\n searchProgram,\n transcriptId,\n maxHits,\n}: {\n proteinSequence: string\n blastDatabase: BlastDatabase | PhmmerDatabase\n msaAlgorithm?: MsaAlgorithm\n searchProgram?: SearchProgram\n transcriptId?: string\n maxHits?: number\n}) {\n const idPart = transcriptId ? `:${transcriptId}` : ''\n const hitsPart =\n maxHits === undefined || maxHits === defaultMaxHits ? '' : `:n${maxHits}`\n return searchProgram === 'phmmer'\n ? `phmmer:${blastDatabase}${idPart}${hitsPart}:${proteinSequence}`\n : `${blastDatabase}:${msaAlgorithm}${idPart}${hitsPart}:${proteinSequence}`\n}\n\n/**\n * Record a finished search in the history. Best effort: the alignment is\n * already in hand, and a browser refusing the write must not turn it into a\n * failed launch.\n */\nexport function saveBlastResult({\n proteinSequence,\n blastDatabase,\n msaAlgorithm,\n searchProgram,\n maxHits,\n msa,\n tree,\n treeMetadata,\n rid,\n geneId,\n transcriptId,\n transcriptName,\n geneName,\n}: {\n proteinSequence: string\n blastDatabase: BlastDatabase | PhmmerDatabase\n msaAlgorithm?: MsaAlgorithm\n searchProgram?: SearchProgram\n maxHits?: number\n msa: string\n tree: string\n treeMetadata: string\n rid: string\n geneId?: string\n transcriptId?: string\n transcriptName?: string\n geneName?: string\n}) {\n return bestEffort(\n 'BLAST history write',\n async () => {\n const db = await getDB()\n const entry: CachedBlastResult = {\n id: createCacheKey({\n proteinSequence,\n blastDatabase,\n msaAlgorithm,\n searchProgram,\n transcriptId,\n maxHits,\n }),\n proteinSequence,\n blastDatabase,\n msaAlgorithm,\n searchProgram,\n maxHits,\n msa,\n tree,\n treeMetadata,\n rid,\n timestamp: Date.now(),\n geneId,\n transcriptId,\n transcriptName,\n geneName,\n }\n await db.put(STORE_NAME, entry)\n await evictOldest(db)\n return entry\n },\n undefined,\n )\n}\n\n/**\n * Drop the oldest rows until the store is back at MAX_CACHED_RESULTS.\n *\n * `count` first so the common save reads no values at all: without a timestamp\n * index the oldest have to be found by loading every row, and each one is an\n * entire alignment. Failing to evict must not fail the save \u2014 the result is\n * already in hand and losing it to a housekeeping error would be the worse\n * outcome.\n */\nasync function evictOldest(db: IDBPDatabase<BlastCacheDB>) {\n try {\n if ((await db.count(STORE_NAME)) <= MAX_CACHED_RESULTS) {\n return\n }\n const all = await db.getAll(STORE_NAME)\n const doomed = all\n .toSorted((a, b) => a.timestamp - b.timestamp)\n .slice(0, all.length - MAX_CACHED_RESULTS)\n const tx = db.transaction(STORE_NAME, 'readwrite')\n await Promise.all([...doomed.map(e => tx.store.delete(e.id)), tx.done])\n } catch (e) {\n console.warn('Failed to evict old BLAST cache entries:', e)\n }\n}\n\nexport async function getAllCachedResults() {\n const db = await getDB()\n const results = await db.getAll(STORE_NAME)\n return results.toSorted((a, b) => b.timestamp - a.timestamp)\n}\n\nexport async function deleteCachedResult(id: string) {\n const db = await getDB()\n await db.delete(STORE_NAME, id)\n}\n", "import { decodeXmlEntities, efetchUrl, eutilsText } from './eutils'\nimport { isAbortError } from './fetch'\nimport { bestEffort, createDbOpener } from './idb'\n\nimport type { DBSchema } from 'idb'\n\nconst DB_NAME = 'jbrowse-msaview-taxonomy-cache'\nconst STORE_NAME = 'common-names'\nconst DB_VERSION = 2\n\ninterface CachedTaxonomy {\n taxid: number\n sciname: string\n commonName?: string\n}\n\ninterface TaxonomyCacheDB extends DBSchema {\n [STORE_NAME]: {\n key: number\n value: CachedTaxonomy\n }\n}\n\nconst getDB = createDbOpener<TaxonomyCacheDB>(DB_NAME, DB_VERSION, db => {\n if (db.objectStoreNames.contains(STORE_NAME)) {\n db.deleteObjectStore(STORE_NAME)\n }\n db.createObjectStore(STORE_NAME, { keyPath: 'taxid' })\n})\n\nfunction getCachedTaxonomies(taxids: number[]) {\n return bestEffort(\n 'taxonomy cache read',\n async () => {\n const db = await getDB()\n const tx = db.transaction(STORE_NAME, 'readonly')\n const results = await Promise.all(\n taxids.map(taxid => tx.store.get(taxid)),\n )\n await tx.done\n return results\n },\n [],\n )\n}\n\nfunction saveTaxonomyCache(entries: CachedTaxonomy[]) {\n return bestEffort(\n 'taxonomy cache write',\n async () => {\n const db = await getDB()\n const tx = db.transaction(STORE_NAME, 'readwrite')\n for (const entry of entries) {\n await tx.store.put(entry)\n }\n await tx.done\n },\n undefined,\n )\n}\n\nexport interface TaxonomyInfo {\n sciname: string\n commonName?: string\n}\n\nexport async function fetchTaxonomyInfo(\n taxidsWithRepeats: number[],\n signal?: AbortSignal,\n): Promise<Map<number, TaxonomyInfo>> {\n // callers pass one taxid per alignment row, and a BLAST hit list is several\n // rows per species: 100 albumin hits are maybe 50 taxa, and asking as they\n // came did 100 IndexedDB reads and sent eutils 100 ids for 50 answers. The\n // result is keyed by taxid, so no caller can tell the difference\n const taxids = [...new Set(taxidsWithRepeats)]\n const result = new Map<number, TaxonomyInfo>()\n const uncachedTaxids: number[] = []\n const cachedResults = await getCachedTaxonomies(taxids)\n\n for (let i = 0; i < taxids.length; i++) {\n const taxid = taxids[i]!\n const cached = cachedResults[i]\n if (cached) {\n result.set(taxid, {\n sciname: cached.sciname,\n commonName: cached.commonName,\n })\n } else {\n uncachedTaxids.push(taxid)\n }\n }\n\n if (uncachedTaxids.length === 0) {\n return result\n }\n\n const batchSize = 100\n const toCache: CachedTaxonomy[] = []\n\n for (let i = 0; i < uncachedTaxids.length; i += batchSize) {\n const batch = uncachedTaxids.slice(i, i + batchSize)\n const idsParam = batch.join(',')\n\n try {\n // textfetch rather than a bare fetch: an NCBI 429/5xx returns an HTML\n // error body that the regexes below silently find nothing in, so without\n // the status check a throttled batch looks like \"these taxa have no\n // names\" instead of reporting why\n const text = await eutilsText(\n efetchUrl({ db: 'taxonomy', id: idsParam, retmode: 'xml' }),\n { signal },\n )\n\n // Build a map of taxid -> taxon block by finding Taxon elements.\n // Prefer entries with <LineageEx> (full top-level entries) over nested\n // entries inside another taxon's LineageEx\n const taxonMap = new Map<number, string>()\n const taxonRegex = /<Taxon>\\s*<TaxId>(\\d+)<\\/TaxId>/g\n let match\n while ((match = taxonRegex.exec(text)) !== null) {\n const matchedTaxid = Number(match[1])\n const startIdx = match.index\n\n // Find the matching closing </Taxon> by counting nesting depth\n let depth = 1\n let endIdx = startIdx + match[0].length\n while (depth > 0 && endIdx < text.length) {\n const openMatch = text.indexOf('<Taxon>', endIdx)\n const closeMatch = text.indexOf('</Taxon>', endIdx)\n if (closeMatch === -1) {\n break\n }\n if (openMatch !== -1 && openMatch < closeMatch) {\n depth++\n endIdx = openMatch + 7\n } else {\n depth--\n endIdx = closeMatch + 8\n }\n }\n\n const taxonXml = text.slice(startIdx, endIdx)\n const existing = taxonMap.get(matchedTaxid)\n const hasLineageEx = taxonXml.includes('<LineageEx>')\n const existingHasLineageEx = existing?.includes('<LineageEx>')\n if (!existing || (hasLineageEx && !existingHasLineageEx)) {\n taxonMap.set(matchedTaxid, taxonXml)\n }\n }\n\n for (const taxid of batch) {\n const taxonXml = taxonMap.get(taxid)\n if (taxonXml) {\n const genbankCommon =\n /<GenbankCommonName>(.*?)<\\/GenbankCommonName>/.exec(taxonXml)\n const commonName = /<CommonName>(.*?)<\\/CommonName>/.exec(taxonXml)\n const sciName = /<ScientificName>(.*?)<\\/ScientificName>/.exec(\n taxonXml,\n )\n const rawName = genbankCommon?.[1] ?? commonName?.[1]\n const name = rawName && decodeXmlEntities(rawName)\n\n const sci = decodeXmlEntities(sciName?.[1] ?? '')\n result.set(taxid, { sciname: sci, commonName: name })\n toCache.push({ taxid, sciname: sci, commonName: name })\n }\n }\n } catch (error) {\n if (isAbortError(error)) {\n await saveTaxonomyCache(toCache)\n throw error\n }\n console.error('Failed to fetch taxonomy data:', error)\n }\n }\n\n if (toCache.length > 0) {\n await saveTaxonomyCache(toCache)\n }\n\n return result\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["require_translateTranscript", "__commonJSMin", "exports", "module", "import_util", "getLinearGenomeView", "model", "isNonEmptyString", "v", "uniqueDefined", "vals", "joinDefined", "sep", "parts", "getTranscriptFeatures", "feature", "transcripts", "f", "s", "getTranscriptLength", "cdsLen", "getId", "val", "getMatchableIds", "featureMatchesId", "id", "getTranscriptDisplayName", "getGeneDisplayName", "getBlastViewTitle", "transcript", "getSortedTranscriptFeatures", "a", "b", "cleanProteinSequence", "seq", "getGeneIdentifiers", "import_configuration", "fetchSeq", "start", "end", "refName", "session", "assemblyName", "assemblyManager", "rpcManager", "assembly", "NCBI_TOOL", "NCBI_EMAIL", "EUTILS", "identified", "params", "eutilsUrl", "endpoint", "efetchUrl", "efetchPost", "EUTILS_SPACING_MS", "nextSlot", "eutilsSlot", "signal", "now", "start", "timeout", "e", "eutilsText", "url", "init", "textfetch", "eutilsJson", "jsonfetch", "namedEntities", "decodeXmlEntities", "text", "entity", "name", "DATASETS", "defaultMaxSpecies", "cleanGeneCandidate", "raw", "resolveGeneId", "candidates", "taxId", "signal", "asked", "query", "cleaned", "geneId", "eutilsJson", "eutilsUrl", "fetchOrthologGenes", "taxa", "exclude", "limit", "json", "jsonfetch", "byTaxon", "gene", "PRODUCT_REPORT_CHUNK", "fetchRepresentativeProteins", "geneIds", "byGene", "i", "chunk", "product", "t", "c", "best", "a", "b", "parseFasta", "text", "map", "acc", "buf", "line", "sanitize", "name", "dedupeLabels", "names", "used", "base", "label", "n", "fetchProteinForGene", "seq", "eutilsText", "efetchUrl", "fetchOrthologRows", "onProgress", "genes", "proteinByGene", "g", "withProtein", "accessions", "efetch", "init", "efetchPost", "seqByAcc", "labels", "rows", "protein", "r", "instanceOfAny", "object", "constructors", "c", "idbProxyableTypes", "cursorAdvanceMethods", "getIdbProxyableTypes", "getCursorAdvanceMethods", "transactionDoneMap", "transformCache", "reverseTransformCache", "promisifyRequest", "request", "promise", "resolve", "reject", "unlisten", "success", "error", "wrap", "cacheDonePromiseForTransaction", "tx", "done", "complete", "idbProxyTraps", "target", "prop", "receiver", "value", "replaceTraps", "callback", "wrapFunction", "func", "args", "unwrap", "transformCachableValue", "newValue", "openDB", "name", "version", "blocked", "upgrade", "blocking", "terminated", "openPromise", "event", "db", "readMethods", "writeMethods", "cachedMethods", "getMethod", "target", "prop", "targetFuncName", "useIndex", "isWrite", "method", "storeName", "args", "tx", "replaceTraps", "oldTraps", "receiver", "advanceMethodProps", "methodMap", "advanceResults", "ittrProxiedCursorToOriginalProxy", "cursorIteratorTraps", "cachedFunc", "iterate", "cursor", "proxiedCursor", "reverseTransformCache", "unwrap", "isIteratorProp", "instanceOfAny", "createDbOpener", "name", "version", "upgrade", "dbPromise", "forget", "resolve", "reject", "gaveUp", "openDB", "currentVersion", "_currentVersion", "_blockedVersion", "event", "db", "e", "bestEffort", "what", "operation", "fallback", "DB_NAME", "STORE_NAME", "DB_VERSION", "MAX_CACHED_RESULTS", "getDB", "createDbOpener", "db", "oldVersion", "createCacheKey", "proteinSequence", "blastDatabase", "msaAlgorithm", "searchProgram", "transcriptId", "maxHits", "idPart", "hitsPart", "defaultMaxHits", "saveBlastResult", "msa", "tree", "treeMetadata", "rid", "geneId", "transcriptName", "geneName", "bestEffort", "entry", "evictOldest", "all", "doomed", "a", "b", "tx", "e", "getAllCachedResults", "deleteCachedResult", "id", "DB_NAME", "STORE_NAME", "DB_VERSION", "getDB", "createDbOpener", "db", "getCachedTaxonomies", "taxids", "bestEffort", "tx", "results", "taxid", "saveTaxonomyCache", "entries", "entry", "fetchTaxonomyInfo", "taxidsWithRepeats", "signal", "result", "uncachedTaxids", "cachedResults", "i", "cached", "batchSize", "toCache", "batch", "idsParam", "text", "eutilsText", "efetchUrl", "taxonMap", "taxonRegex", "match", "matchedTaxid", "startIdx", "depth", "endIdx", "openMatch", "closeMatch", "taxonXml", "existing", "hasLineageEx", "existingHasLineageEx", "genbankCommon", "commonName", "sciName", "rawName", "name", "decodeXmlEntities", "sci", "error", "isAbortError"]
|
|
7
|
+
}
|