jbrowse-plugin-msaview 5.2.0 → 5.3.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/MsaViewPanel/model.d.ts +25 -29
- package/dist/chunks/AboutDialog-447TIFAW.js +2 -0
- package/dist/chunks/{AboutDialog-IRBPUPJK.js.map → AboutDialog-447TIFAW.js.map} +4 -4
- package/dist/chunks/AnnotationFileDialog-S3N5EHHE.js +2 -0
- package/dist/chunks/AnnotationFileDialog-S3N5EHHE.js.map +7 -0
- package/dist/chunks/ExportSVGDialog-7ZHKKQ7W.js +2 -0
- package/dist/chunks/ExportSVGDialog-7ZHKKQ7W.js.map +7 -0
- package/dist/chunks/{FeatureDialog-ZBX3XQZ5.js → FeatureDialog-EEOGSLOG.js} +1 -1
- package/dist/chunks/{FeatureDialog-ZBX3XQZ5.js.map → FeatureDialog-EEOGSLOG.js.map} +1 -1
- package/dist/chunks/HelpDialog-TCWNBZOV.js +2 -0
- package/dist/chunks/HelpDialog-TCWNBZOV.js.map +7 -0
- package/dist/chunks/{LaunchMsaViewDialog-GJAUPGFC.js → LaunchMsaViewDialog-R6CNRASN.js} +2 -2
- package/dist/chunks/{LaunchMsaViewDialog-GJAUPGFC.js.map → LaunchMsaViewDialog-R6CNRASN.js.map} +1 -1
- package/dist/chunks/MetadataDialog-MNSI6NEW.js +2 -0
- package/dist/chunks/{MetadataDialog-KZWQFRF7.js.map → MetadataDialog-MNSI6NEW.js.map} +2 -2
- package/dist/chunks/MsaViewPanel-R2WAER5O.js +2 -0
- package/dist/chunks/{MsaViewPanel-RUZAKFCB.js.map → MsaViewPanel-R2WAER5O.js.map} +1 -1
- package/dist/chunks/{TrackInfoDialog-IFIG77WO.js → TrackInfoDialog-W2F77IPG.js} +2 -2
- package/dist/chunks/{TrackInfoDialog-IFIG77WO.js.map → TrackInfoDialog-W2F77IPG.js.map} +1 -1
- package/dist/chunks/TreeNodeInfoDialog-T5XMPG3R.js +2 -0
- package/dist/chunks/{TreeNodeInfoDialog-VRCVIF26.js.map → TreeNodeInfoDialog-T5XMPG3R.js.map} +2 -2
- package/dist/chunks/chunk-6EOYBBT4.js +2 -0
- package/dist/chunks/chunk-6EOYBBT4.js.map +7 -0
- package/dist/chunks/chunk-A63PUWQZ.js +6 -0
- package/dist/chunks/chunk-A63PUWQZ.js.map +7 -0
- package/dist/chunks/{chunk-NI3VGKQP.js → chunk-BAM67QHH.js} +2 -2
- package/dist/chunks/chunk-CSCUNTGJ.js +18 -0
- package/dist/chunks/chunk-CSCUNTGJ.js.map +7 -0
- package/dist/chunks/chunk-DEFUNIWW.js +8 -0
- package/dist/chunks/chunk-DEFUNIWW.js.map +7 -0
- package/dist/chunks/{chunk-YOTSFJMU.js → chunk-ERCMNTEQ.js} +1 -1
- package/dist/chunks/{chunk-YOTSFJMU.js.map → chunk-ERCMNTEQ.js.map} +1 -1
- package/dist/chunks/{chunk-GDFVLZYX.js → chunk-FEUZKN5V.js} +2 -2
- package/dist/chunks/{chunk-GDFVLZYX.js.map → chunk-FEUZKN5V.js.map} +1 -1
- package/dist/chunks/{chunk-GIHMPOCO.js → chunk-JF6CW6MO.js} +1 -1
- package/dist/chunks/{chunk-GIHMPOCO.js.map → chunk-JF6CW6MO.js.map} +1 -1
- package/dist/chunks/chunk-K55ZVN73.js +5 -0
- package/dist/chunks/chunk-K55ZVN73.js.map +7 -0
- package/dist/chunks/chunk-L6CBIH6H.js +2 -0
- package/dist/chunks/chunk-L6CBIH6H.js.map +7 -0
- package/dist/chunks/{chunk-F3EC6OCO.js → chunk-NWHZOZMG.js} +1 -1
- package/dist/chunks/{chunk-F3EC6OCO.js.map → chunk-NWHZOZMG.js.map} +1 -1
- package/dist/chunks/chunk-OVAXNTPN.js +2 -0
- package/dist/chunks/chunk-OVAXNTPN.js.map +7 -0
- package/dist/chunks/chunk-TSHN6J7U.js +2 -0
- package/dist/chunks/chunk-TSHN6J7U.js.map +7 -0
- package/dist/chunks/{chunk-H6IQBAW7.js → chunk-WAPIOD25.js} +5 -5
- package/dist/chunks/{chunk-H6IQBAW7.js.map → chunk-WAPIOD25.js.map} +1 -1
- package/dist/chunks/chunk-XVNCZQMR.js +2 -0
- package/dist/chunks/{chunk-ZCT7RD24.js.map → chunk-XVNCZQMR.js.map} +1 -1
- package/dist/chunks/{dist-CMWKVHC7.js → dist-GXYZN4ZR.js} +2 -2
- package/dist/chunks/{dist-CMWKVHC7.js.map → dist-GXYZN4ZR.js.map} +3 -3
- package/dist/chunks/dist-N4ZJK63Q.js +2 -0
- package/dist/chunks/{model-VE7IYWNU.js → model-TCPB6WNJ.js} +2 -2
- package/dist/chunks/{model-VE7IYWNU.js.map → model-TCPB6WNJ.js.map} +1 -1
- package/dist/chunks/renderToSvg-53FEV6IJ.js +2 -0
- package/dist/jbrowse-plugin-msaview.esm.js +2 -2
- package/dist/jbrowse-plugin-msaview.esm.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
- package/src/version.ts +1 -1
- package/dist/chunks/AboutDialog-IRBPUPJK.js +0 -2
- package/dist/chunks/AnnotationFileDialog-FCYYZ4JN.js +0 -2
- package/dist/chunks/AnnotationFileDialog-FCYYZ4JN.js.map +0 -7
- package/dist/chunks/ExportSVGDialog-TYYPI6VB.js +0 -2
- package/dist/chunks/ExportSVGDialog-TYYPI6VB.js.map +0 -7
- package/dist/chunks/MetadataDialog-KZWQFRF7.js +0 -2
- package/dist/chunks/MsaViewPanel-RUZAKFCB.js +0 -2
- package/dist/chunks/TreeNodeInfoDialog-VRCVIF26.js +0 -2
- package/dist/chunks/chunk-F726IWCW.js +0 -2
- package/dist/chunks/chunk-F726IWCW.js.map +0 -7
- package/dist/chunks/chunk-NMYD2GWF.js +0 -18
- package/dist/chunks/chunk-NMYD2GWF.js.map +0 -7
- package/dist/chunks/chunk-QQ5LZUIO.js +0 -11
- package/dist/chunks/chunk-QQ5LZUIO.js.map +0 -7
- package/dist/chunks/chunk-QUWPHTZQ.js +0 -2
- package/dist/chunks/chunk-QUWPHTZQ.js.map +0 -7
- package/dist/chunks/chunk-ZCT7RD24.js +0 -2
- package/dist/chunks/dist-R73J3CC3.js +0 -2
- package/dist/chunks/renderToSvg-VDXAB7TT.js +0 -2
- /package/dist/chunks/{chunk-NI3VGKQP.js.map → chunk-BAM67QHH.js.map} +0 -0
- /package/dist/chunks/{dist-R73J3CC3.js.map → dist-N4ZJK63Q.js.map} +0 -0
- /package/dist/chunks/{renderToSvg-VDXAB7TT.js.map → renderToSvg-53FEV6IJ.js.map} +0 -0
package/dist/chunks/{TreeNodeInfoDialog-VRCVIF26.js.map → TreeNodeInfoDialog-T5XMPG3R.js.map}
RENAMED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../node_modules/.pnpm/react-msaview@9.
|
|
3
|
+
"sources": ["../../node_modules/.pnpm/react-msaview@9.1.0_3e54acfe76b6ad0d26e91cd532b7f775/node_modules/react-msaview/src/components/tree/dialogs/TreeNodeInfoDialog.tsx"],
|
|
4
4
|
"sourcesContent": ["import React from 'react'\n\nimport { Dialog } from '@jbrowse/core/ui'\nimport { DialogContent, Typography } from '@mui/material'\nimport { observer } from 'mobx-react'\n\nimport MetadataTable from '../../MetadataTable.tsx'\nimport SequenceTextArea from '../../SequenceTextArea.tsx'\n\nimport type { MsaViewModel } from '../../../model.ts'\n\nconst TreeNodeInfoDialog = observer(function ({\n info,\n model,\n nodeName,\n onClose,\n}: {\n info: Record<string, unknown>\n model: MsaViewModel\n nodeName: string\n onClose: () => void\n}) {\n const { rows } = model\n const metadata = model.rowDataOf(nodeName)\n const res = rows.find(f => f[0] === nodeName)\n return (\n <Dialog\n onClose={() => {\n onClose()\n }}\n open\n title=\"Tree node info\"\n maxWidth=\"xl\"\n >\n <DialogContent>\n <Typography variant=\"h6\">Attributes</Typography>\n <MetadataTable record={{ nodeName, ...info }} />\n <Typography variant=\"h6\">Sequence</Typography>\n {res ? (\n <SequenceTextArea str={[res]} />\n ) : (\n <Typography>Sequence not found</Typography>\n )}\n {metadata ? (\n <>\n <Typography variant=\"h6\">Extra metadata</Typography>\n <MetadataTable record={metadata} />\n </>\n ) : null}\n </DialogContent>\n </Dialog>\n )\n})\n\nexport default TreeNodeInfoDialog\n"],
|
|
5
|
-
"mappings": "
|
|
5
|
+
"mappings": "sbAAA,IAAAA,EAAkB,SAElBC,EAAuB,SACvBC,EAA0C,SAC1CC,EAAyB,SAOzB,IAAMC,KAAqB,YAAS,SAAU,CAC5C,KAAAC,EACA,MAAAC,EACA,SAAAC,EACA,QAAAC,CAAO,EAMR,CACC,GAAM,CAAE,KAAAC,CAAI,EAAKH,EACXI,EAAWJ,EAAM,UAAUC,CAAQ,EACnCI,EAAMF,EAAK,KAAKG,GAAKA,EAAE,CAAC,IAAML,CAAQ,EAC5C,OACE,EAAAM,QAAA,cAAC,SAAM,CACL,QAAS,IAAK,CACZL,EAAO,CACT,EACA,KAAI,GACJ,MAAM,iBACN,SAAS,IAAI,EAEb,EAAAK,QAAA,cAAC,gBAAa,KACZ,EAAAA,QAAA,cAAC,aAAU,CAAC,QAAQ,IAAI,EAAA,YAAA,EACxB,EAAAA,QAAA,cAACC,EAAa,CAAC,OAAQ,CAAE,SAAAP,EAAU,GAAGF,CAAI,CAAE,CAAA,EAC5C,EAAAQ,QAAA,cAAC,aAAU,CAAC,QAAQ,IAAI,EAAA,UAAA,EACvBF,EACC,EAAAE,QAAA,cAACE,EAAgB,CAAC,IAAK,CAACJ,CAAG,CAAC,CAAA,EAE5B,EAAAE,QAAA,cAAC,aAAU,KAAA,oBAAA,EAEZH,EACC,EAAAG,QAAA,cAAA,EAAAA,QAAA,SAAA,KACE,EAAAA,QAAA,cAAC,aAAU,CAAC,QAAQ,IAAI,EAAA,gBAAA,EACxB,EAAAA,QAAA,cAACC,EAAa,CAAC,OAAQJ,CAAQ,CAAA,CAAI,EAEnC,IAAI,CACM,CAGtB,CAAC,EAEDM,EAAeZ",
|
|
6
6
|
"names": ["import_react", "import_ui", "import_material", "import_mobx_react", "TreeNodeInfoDialog", "info", "model", "nodeName", "onClose", "rows", "metadata", "res", "f", "React", "MetadataTable", "SequenceTextArea", "TreeNodeInfoDialog_default"]
|
|
7
7
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../node_modules/.pnpm/react-msaview@9.1.0_3e54acfe76b6ad0d26e91cd532b7f775/node_modules/react-msaview/src/version.ts"],
|
|
4
|
+
"sourcesContent": ["export const version = '9.1.0'\n"],
|
|
5
|
+
"mappings": "AAAO,IAAMA,EAAU",
|
|
6
|
+
"names": ["version"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import{a as O,b as $}from"./chunk-K55ZVN73.js";import{a as _}from"./chunk-73KAPCJ2.js";import{a as J}from"./chunk-J6KYLXRD.js";import{b as z}from"./chunk-FY3BTKY4.js";function V(e){try{return new URL(e).host}catch{return e}}var R=class extends Error{constructor(r,n){super(r);this.status=n}};async function P(e,t){let r;try{r=await fetch(e,t)}catch(n){throw n instanceof TypeError?new Error(`Could not reach ${V(e)} \u2014 the request failed at the network level. This is usually a CORS restriction (the server refused to let this site read the response), an offline connection, or a blocked request.`,{cause:n}):n}if(!r.ok)throw new R(`HTTP ${r.status} fetching ${e} ${(await r.text()).slice(0,500)}`,r.status);return r}async function A(e,t){return(await P(e,t)).text()}async function Nt(e,t){return(await P(e,t)).json()}function N(e,t){return new Promise((r,n)=>{if(t?.aborted){n(new DOMException("Aborted","AbortError"));return}let s=()=>{clearTimeout(o),n(new DOMException("Aborted","AbortError"))},o=setTimeout(()=>{t?.removeEventListener("abort",s),r()},e);t?.addEventListener("abort",s,{once:!0})})}function k(e){return e instanceof Error&&e.name==="AbortError"}var D=z(J());function T(e,t){try{let r=globalThis.localStorage.getItem(e);return r===null?t:JSON.parse(r)}catch(r){return console.error(r),t}}function Dt(e,t){let[r,n]=(0,D.useState)(()=>T(e,t));return[r,o=>{n(o);try{globalThis.localStorage.setItem(e,JSON.stringify(o))}catch(a){console.error(a)}}]}async function q({check:e,intervalSeconds:t,onCountdown:r,signal:n}){for(;;){if(n?.throwIfAborted(),await e())return;for(let s=t;s>0;s--)r(s),await N(1e3,n)}}var M="https://www.ebi.ac.uk/Tools/services/rest",X="msa-ebiContactEmail",I="jbrowse2@berkeley.edu";function Y(){return T(X,I).trim()||I}var Q=new Set(["ERROR","FAILURE","NOT_FOUND"]);async function Z({tool:e,params:t,signal:r}){return(await A(`${M}/${e}/run`,{method:"POST",body:new URLSearchParams({email:Y(),...t}),signal:r})).trim()}var L=900*1e3;async function tt({tool:e,jobId:t,intervalSeconds:r=10,onCountdown:n,signal:s}){let o;await q({intervalSeconds:r,onCountdown:n,signal:s,check:async()=>{let a;try{a=(await A(`${M}/${e}/status/${t}`,{signal:s})).trim()}catch(i){if(k(i))throw i;if(o??=Date.now(),Date.now()-o>=L)throw new Error(`Could not reach EBI to check ${e} job ${t} for ${Math.round(L/6e4)} minutes`,{cause:i});return console.warn("[msaview] EBI status check failed, retrying:",i),!1}if(o=void 0,a==="FINISHED")return!0;if(Q.has(a))throw new Error(`EBI ${e} job ${t} returned status ${a}`);return!1}})}async function Gt({tool:e,label:t,params:r,onProgress:n,onRid:s,signal:o}){n(`Submitting ${t} to EBI...`);let a=await Z({tool:e,params:r,signal:o});return s?.(a),await tt({tool:e,jobId:a,signal:o,onCountdown:i=>{n(`Re-checking ${t} status in... ${i}`)}}),{jobId:a,result:i=>A(`${M}/${e}/result/${a}/${i}`,{signal:o})}}var Ht="https://blast.ncbi.nlm.nih.gov/Blast.cgi",et=["clustalo","muscle","kalign","mafft"],Kt=[...et,"browser"],Wt={clustalo:"Clustal Omega (EBI)",muscle:"MUSCLE (EBI)",kalign:"Kalign (EBI)",mafft:"MAFFT (EBI)",browser:"in browser, query-anchored"},rt=["uniprotkb_swissprot","uniprotkb","pan_proteomes","uniprotkb_trembl"],nt="uniprotkb_swissprot",zt=["blastp","phmmer"],Jt={blastp:"blastp (sequence search)",phmmer:"phmmer (profile HMM search)"},st=["swissprot","uniprotkb","uniprotrefprot","rp75","rp55","rp35","rp15"],ot="swissprot",B=[5,10,20,50,100,150,200,250,500,750,1e3],Vt=100;function Xt(e){return B.find(t=>t>=e)??B.at(-1)}function Yt(e){return e==="phmmer"?{program:e,database:ot}:{program:e,database:nt}}function Qt(e){return e==="phmmer"?st:rt}var it={uniprotkb_swissprot:"UniProtKB/Swiss-Prot (curated)",swissprot:"UniProtKB/Swiss-Prot (curated)",uniprotkb:"UniProtKB (all entries)",uniprotkb_trembl:"UniProtKB/TrEMBL (unreviewed)",pan_proteomes:"Pan-proteomes",uniprotrefprot:"UniProt reference proteomes",rp75:"Representative proteomes, 75%",rp55:"Representative proteomes, 55%",rp35:"Representative proteomes, 35%",rp15:"Representative proteomes, 15% (widest spread)"};function Zt(e){return it[e]}function y(e,t="node",r=0){let n=(a,i)=>({...a,id:i,name:a.name||i,children:[]}),s=n(e,`${t}-${r}`),o=[{src:e,out:s,depth:r}];for(;o.length>0;){let{src:a,out:i,depth:c}=o.pop();if(a.children){i.children=a.children.map((u,f)=>n(u,`${i.id}-${f}-${c+1}`));for(let[u,f]of a.children.entries())o.push({src:f,out:i.children[u],depth:c+1})}}return s}var p=class{rows=new Map;names;width;constructor(t){for(let[r,n]of t)this.rows.has(r)||this.rows.set(r,n);this.names=[...this.rows.keys()]}getRow(t){return this.rows.get(t)??""}getNames(){return this.names}getWidth(){return this.width??=this.getNames().reduce((t,r)=>Math.max(t,this.getRow(r).length),0),this.width}getTree(){return{id:"root",name:"root",noTree:!0,children:this.getNames().map(t=>({id:t,children:[],name:t}))}}getRowData(t){}getStructures(){return{}}getHeader(){return{}}get alignmentNames(){return[]}get seqConsensus(){}get secondaryStructureConsensus(){}get tracks(){return[]}};function S(e){return _(e,{postParenNumeric:"name"})}function j(){return{gf:Object.create(null),gc:Object.create(null),gs:Object.create(null),gr:Object.create(null),seqname:[],seqdata:Object.create(null)}}function b(e,t){if(e)return e;if(t)throw new Error("No format header: # STOCKHOLM 1.0");return j()}var U=/^# STOCKHOLM 1.0/,at=/^\/\/\s*$/,ct=/^#=GF\s+(\S+)\s+(.*?)\s*$/,ut=/^#=GC\s+(\S+)\s+(.*?)\s*$/,pt=/^#=GS\s+(\S+)\s+(\S+)\s+(.*?)\s*$/,ft=/^#=GR\s+(\S+)\s+(\S+)\s+(.*?)\s*$/,lt=/^\s*([^#\s]\S*)\s+(\S+)\s*$/,mt=/\S/;function x(e){return U.test(e)}function G(e,t){let r=t??{},n=[],s=null,o=!1,a=e.split(`
|
|
2
|
+
`);for(let i of a){let c;if(U.test(i))s&&n.push(s),s=j(),o=!1;else if(at.test(i))s&&n.push(s),s=null;else if(c=ct.exec(i)){s=b(s,!!r.strict);let u=c[1],f=s.gf[u]??=[];u==="NH"&&o&&f.length>0?f[f.length-1]+=c[2]:f.push(c[2]),o=u==="NH"}else if(c=ut.exec(i))s=b(s,!!r.strict),s.gc[c[1]]=(s.gc[c[1]]??"")+c[2];else if(c=pt.exec(i)){s=b(s,!!r.strict);let u=s.gs[c[2]]??=Object.create(null);(u[c[1]]??=[]).push(c[3])}else if(c=ft.exec(i)){s=b(s,!!r.strict);let u=s.gr[c[2]]??=Object.create(null);u[c[1]]=(u[c[1]]??"")+c[3]}else if(c=lt.exec(i)){s=b(s,!!r.strict);let u=c[1],f=c[2];s.seqdata[u]===void 0&&(s.seqdata[u]="",s.seqname.push(u)),s.seqdata[u]+=f}else if(mt.test(i)&&r.strict)throw new Error("Malformed line")}return s&&n.push(s),n}var m=class extends p{data;MSA;constructor(t,r){let n=G(t),s=n[r]??n[0];if(!s)throw new Error("No alignments found in Stockholm file");super(s.seqname.map(o=>[o,s.seqdata[o]??""])),this.data=n,this.MSA=s}getMSA(){return this.MSA}get alignmentNames(){return this.data.map((t,r)=>t.gf.DE?.[0]??`Alignment ${r+1}`)}getHeader(){let t=this.MSA.gs.AC??{},r=this.MSA.gs.DR??{};return{General:this.MSA.gf,Accessions:Object.fromEntries(Object.entries(t).map(([n,s])=>[n,s[0]])),Dbxref:Object.fromEntries(Object.entries(r).map(([n,s])=>[n,s.join("; ")]))}}getRowData(t){return{name:t,accession:this.MSA.gs.AC?.[t]?.[0],dbxref:this.MSA.gs.DR?.[t]?.join("; ")}}getStructures(){let t=/PDB; +(\S+) +([^;\s]+); *(-?[0-9]+)-(-?[0-9]+)/,r=this.MSA.gs.DR??{},n={};for(let[s,o]of Object.entries(r))for(let a of o){let i=t.exec(a);i&&(n[s]??=[]).push({pdb:i[1].toLowerCase(),chain:i[2],startPos:+i[3],endPos:+i[4]})}return n}getTree(){let t=this.MSA.gf.NH?.[0];return t?y(S(t)):super.getTree()}get seqConsensus(){return this.MSA.gc.seq_cons}get secondaryStructureConsensus(){return this.MSA.gc.SS_cons}get tracks(){let{seq_cons:t,SS_cons:r,...n}=this.MSA.gc;return[{id:"seqConsensus",name:"Sequence consensus",data:t,customColorScheme:{}},{id:"secondaryStruct",name:"Secondary-structure",data:r,customColorScheme:H},...Object.entries(n).map(([s,o])=>({id:`gc-${s}`,name:s,data:o,customColorScheme:v(s)})),...Object.entries(this.MSA.gr).flatMap(([s,o])=>Object.entries(o).map(([a,i])=>({id:`gr-${a}-${s}`,name:`${a} ${s}`,data:i,customColorScheme:v(s),defaultOff:!0})))]}},H={"<":"lightblue","(":"lightblue","[":"lightblue","{":"lightblue",">":"pink",")":"pink","]":"pink","}":"pink"};function v(e){return e==="SS"||e.endsWith("_SS")?H:{}}function E(e){return/^(#.*\n)*>/.test(e)}function C(e){let t=[],r=new Set,n,s=()=>{n&&!r.has(n.id)&&(r.add(n.id),t.push({id:n.id,seq:n.lines.join("").replaceAll(/\s/g,"")}))},o=0;for(let a of e.split(`
|
|
3
|
+
`))a.startsWith(">")?(s(),o++,n={id:/^>\s*(\S*)/.exec(a)[1]||`unnamed_${o}`,lines:[]}):n?.lines.push(a);return s(),t}function w(e){return typeof e=="string"?C(e):e}var dt=65,ht=90,gt=97,St=122,bt=45;function K(e){return e>=gt&&e<=St}function W(e){return e>=dt&&e<=ht||e===bt}function xt(e){let t=[],r=[""];for(let n of e){let s=n.charCodeAt(0);W(s)?(t.push(n),r.push("")):K(s)&&(r[r.length-1]+=n.toUpperCase())}return{matches:t,inserts:r}}var l=class extends p{constructor(t){let r=w(t),n=wt(r.map(s=>s.seq));super(r.map((s,o)=>[s.id,n[o]]))}static sniff(t){if(typeof t=="string"&&!E(t))return!1;let r=w(t).map(o=>o.seq).filter(o=>!!o);if(r.length<2||new Set(r.map(o=>o.length)).size===1)return!1;let n=!1,s;for(let o of r){let a=0;for(let i=0;i<o.length;i++){let c=o.charCodeAt(i);W(c)?a++:K(c)&&(n=!0)}if(s!==void 0&&a!==s)return!1;s=a}return n}};function wt(e){let t=e.map(xt),r=0;for(let{matches:s}of t)r=Math.max(r,s.length);let n=new Array(r+1).fill(0);for(let{inserts:s}of t)for(let[o,a]of s.entries())n[o]=Math.max(n[o],a.length);return t.map(({matches:s,inserts:o})=>{let a=[];for(let i=0;i<=r;i++){let c=o[i]??"";a.push(c,".".repeat(n[i]-c.length)),i<r&&a.push(s[i]??"-")}return a.join("")})}var d=class extends p{MSA;constructor(t){let r=O(t);super(r.alns.map(n=>[n.id,n.seq])),this.MSA=r}getHeader(){return this.MSA.header}get seqConsensus(){return this.MSA.consensus}};var h=class extends p{constructor(t){super($(t).map(r=>[r.protein,r.seq]))}};var g=class extends p{colonNormalized=new Map;constructor(t){let r=w(t);super(r.map(n=>[n.id,n.seq]));for(let{id:n}of r)n.includes(":")&&this.colonNormalized.set(n.replaceAll(":","_"),n)}getRow(t){return this.rows.get(t)??this.rows.get(this.colonNormalized.get(t)??"")??""}};var Et=/^<(!doctype\s+html|html[\s>])/i,Rt=/^(CLUSTAL|MUSCLE|PROBCONS|MSAPROBS|Kalign)/i;function Tt(e,t=0,r){let n=e.replace(/^\uFEFF/,"").replaceAll(/\r\n?/g,`
|
|
4
|
+
`).trimStart();if(Et.test(n))throw new Error("Received an HTML page, not an alignment. Check that the URL points at the file itself");if(r==="stockholm")return new m(n,t);if(r==="a3m")return new l(n);if(r==="fasta")return new g(n);if(r==="emf")return new h(n);if(r==="clustal")return new d(n);if(x(n))return new m(n,t);if(E(n)){let o=C(n);return l.sniff(o)?new l(o):new g(o)}if(n.startsWith("SEQ"))return new h(n);if(Rt.test(n))return new d(n);let s=n.split(`
|
|
5
|
+
`,1)[0].slice(0,80);throw new Error(s?`Unrecognized alignment format: expected FASTA, A3M, Stockholm, Clustal or EMF, but the first line reads "${s}"`:"The alignment file is empty")}function Mt(e){return e.replaceAll(/[.-]/g,"")}export{R as a,P as b,A as c,Nt as d,N as e,k as f,Dt as g,X as h,I as i,Gt as j,Ht as k,Kt as l,Wt as m,zt as n,Jt as o,Vt as p,Xt as q,Yt as r,Qt as s,Zt as t,m as u,Tt as v,Mt as w};
|
|
6
|
+
//# sourceMappingURL=chunk-A63PUWQZ.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/utils/fetch.ts", "../../src/utils/useLocalStorage.ts", "../../src/utils/poll.ts", "../../src/utils/ebiJobDispatcher.ts", "../../src/LaunchMsaView/components/BlastQuery/consts.ts", "../../node_modules/.pnpm/msa-parsers@9.0.0/node_modules/msa-parsers/src/util.ts", "../../node_modules/.pnpm/msa-parsers@9.0.0/node_modules/msa-parsers/src/msa/BaseMSA.ts", "../../node_modules/.pnpm/msa-parsers@9.0.0/node_modules/msa-parsers/src/msa/parseNewick.ts", "../../node_modules/.pnpm/msa-parsers@9.0.0/node_modules/msa-parsers/src/msa/stockholmParser.ts", "../../node_modules/.pnpm/msa-parsers@9.0.0/node_modules/msa-parsers/src/msa/StockholmMSA.ts", "../../node_modules/.pnpm/msa-parsers@9.0.0/node_modules/msa-parsers/src/msa/fastaRecords.ts", "../../node_modules/.pnpm/msa-parsers@9.0.0/node_modules/msa-parsers/src/msa/A3mMSA.ts", "../../node_modules/.pnpm/msa-parsers@9.0.0/node_modules/msa-parsers/src/msa/ClustalMSA.ts", "../../node_modules/.pnpm/msa-parsers@9.0.0/node_modules/msa-parsers/src/msa/EmfMSA.ts", "../../node_modules/.pnpm/msa-parsers@9.0.0/node_modules/msa-parsers/src/msa/FastaMSA.ts", "../../node_modules/.pnpm/msa-parsers@9.0.0/node_modules/msa-parsers/src/msa/index.ts"],
|
|
4
|
+
"sourcesContent": ["function hostOf(url: string) {\n try {\n return new URL(url).host\n } catch {\n // a relative url, e.g. a same-origin proxy path\n return url\n }\n}\n\nexport class HttpError extends Error {\n constructor(\n message: string,\n readonly status: number,\n ) {\n super(message)\n }\n}\n\nexport async function handleFetch(url: string, args?: RequestInit) {\n let response: Response\n try {\n response = await fetch(url, args)\n } catch (e) {\n // fetch rejects with a bare \"TypeError: Failed to fetch\" for every network\n // level failure, including a cross-origin response the browser refused to\n // hand over. That is not a hypothetical: NCBI's Blast.cgi stopped sending\n // Access-Control-Allow-Origin to third-party origins, and the raw TypeError\n // told users nothing at all about why. See docs/blast.md.\n if (e instanceof TypeError) {\n throw new Error(\n `Could not reach ${hostOf(url)} \u2014 the request failed at the network level. This is usually a CORS restriction (the server refused to let this site read the response), an offline connection, or a blocked request.`,\n { cause: e },\n )\n }\n throw e\n }\n\n if (!response.ok) {\n throw new HttpError(\n `HTTP ${response.status} fetching ${url} ${(await response.text()).slice(0, 500)}`,\n response.status,\n )\n }\n\n return response\n}\n\nexport async function textfetch(url: string, args?: RequestInit) {\n const response = await handleFetch(url, args)\n return response.text()\n}\n\nexport async function jsonfetch<T>(url: string, args?: RequestInit) {\n const response = await handleFetch(url, args)\n return response.json() as Promise<T>\n}\n\nexport function timeout(time: number, signal?: AbortSignal) {\n return new Promise<void>((resolve, reject) => {\n if (signal?.aborted) {\n reject(new DOMException('Aborted', 'AbortError'))\n return\n }\n // the listener is removed on the natural path too: one signal serves every\n // tick of a poll, and a 10-minute job is ~600 sleeps -- leaving each\n // listener behind accumulates them all on that one signal\n const onAbort = () => {\n clearTimeout(id)\n reject(new DOMException('Aborted', 'AbortError'))\n }\n const id = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort)\n resolve()\n }, time)\n signal?.addEventListener('abort', onAbort, { once: true })\n })\n}\n\n/**\n * A cancelled launch has to be told apart from a failed one: it must not render\n * the \"failed\" panel, and it must not touch a model that may already be gone.\n * `fetch` and the sleep above both reject with a DOMException named AbortError,\n * which subclasses Error.\n */\nexport function isAbortError(e: unknown) {\n return e instanceof Error && e.name === 'AbortError'\n}\n", "import { useState } from 'react'\n\n// Vendored rather than imported from `@jbrowse/core/util`: that barrel is\n// host-provided, and a barrel split dropped this export, making the BLAST panel\n// throw \"(0, PR.useLocalStorage) is not a function\" on hosts built during that\n// window. Same failure mode as `defaultCodonTable`; keeping our own copy takes\n// this plugin out of the whack-a-mole.\nexport function readLocalStorage<T>(key: string, initialValue: T): T {\n try {\n const item = globalThis.localStorage.getItem(key)\n return item === null ? initialValue : (JSON.parse(item) as T)\n } catch (error) {\n console.error(error)\n return initialValue\n }\n}\n\nexport function useLocalStorage<T>(key: string, initialValue: T) {\n const [storedValue, setStoredValue] = useState<T>(() =>\n readLocalStorage(key, initialValue),\n )\n const setValue = (value: T) => {\n setStoredValue(value)\n try {\n globalThis.localStorage.setItem(key, JSON.stringify(value))\n } catch (error) {\n console.error(error)\n }\n }\n return [storedValue, setValue] as const\n}\n", "import { timeout } from './fetch'\n\n/**\n * Poll a remote job until it reports done. `check` returns true when finished,\n * false when still pending, and throws on failure. Between checks it counts down\n * `intervalSeconds`, calling `onCountdown` each second so the UI can show\n * progress.\n *\n * `signal` ends the loop with an AbortError: the countdown rejects on the tick\n * it is aborted rather than at the end of the interval, so a cancelled launch\n * stops within a second instead of running for the job's lifetime.\n */\nexport async function pollLoop({\n check,\n intervalSeconds,\n onCountdown,\n signal,\n}: {\n check: () => Promise<boolean>\n intervalSeconds: number\n onCountdown: (secondsRemaining: number) => void\n signal?: AbortSignal\n}) {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n while (true) {\n signal?.throwIfAborted()\n if (await check()) {\n return\n }\n for (let i = intervalSeconds; i > 0; i--) {\n onCountdown(i)\n await timeout(1000, signal)\n }\n }\n}\n", "import { isAbortError, textfetch } from './fetch'\nimport { pollLoop } from './poll'\nimport { readLocalStorage } from './useLocalStorage'\n\n/**\n * EBI's Job Dispatcher REST services (clustalo, muscle, ncbiblast, ...) all\n * speak the same run/status/result protocol, so the transport lives here and\n * each tool only supplies its own parameters and result types.\n *\n * Unlike NCBI's Blast.cgi these endpoints send `Access-Control-Allow-Origin: *`,\n * which is why the BLAST backend moved here \u2014 see docs/blast.md.\n */\nexport const EBI_BASE = 'https://www.ebi.ac.uk/Tools/services/rest'\n\n/**\n * EBI asks for a contact address on every submission so they can reach whoever\n * is generating the load. The default is the project's mailbox; a deployment\n * that sends real volume should name its own maintainer in the BLAST settings\n * dialog.\n */\nexport const EBI_EMAIL_STORAGE_KEY = 'msa-ebiContactEmail'\nexport const DEFAULT_EBI_EMAIL = 'jbrowse2@berkeley.edu'\n\nexport function getEbiEmail() {\n const configured = readLocalStorage(\n EBI_EMAIL_STORAGE_KEY,\n DEFAULT_EBI_EMAIL,\n ).trim()\n return configured || DEFAULT_EBI_EMAIL\n}\n\n/** Statuses that mean the job is over and produced no result. */\nconst FAILED_STATUSES = new Set(['ERROR', 'FAILURE', 'NOT_FOUND'])\n\nasync function submitEbiJob({\n tool,\n params,\n signal,\n}: {\n tool: string\n params: Record<string, string>\n signal?: AbortSignal\n}) {\n const jobId = await textfetch(`${EBI_BASE}/${tool}/run`, {\n method: 'POST',\n body: new URLSearchParams({ email: getEbiEmail(), ...params }),\n signal,\n })\n return jobId.trim()\n}\n\n/**\n * A status check that could not reach EBI at all says nothing about the job, so\n * it is not a reason to abandon one. A job the server has accepted keeps running\n * whatever happens to the poller's connection, and EBI's cluster has answered\n * status checks with a 502 for ten minutes on jobs that then finished (see\n * docs/blast.md).\n *\n * So the poll gives up only once checks have failed without a break for this\n * long: an endpoint that has genuinely gone away must not be polled forever.\n */\nexport const STATUS_FAILURE_BUDGET_MS = 15 * 60 * 1000\n\nexport async function waitForEbiJob({\n tool,\n jobId,\n intervalSeconds = 10,\n onCountdown,\n signal,\n}: {\n tool: string\n jobId: string\n intervalSeconds?: number\n onCountdown: (secondsRemaining: number) => void\n signal?: AbortSignal\n}) {\n let failingSince: number | undefined\n await pollLoop({\n intervalSeconds,\n onCountdown,\n signal,\n check: async () => {\n let status: string\n try {\n status = (\n await textfetch(`${EBI_BASE}/${tool}/status/${jobId}`, { signal })\n ).trim()\n } catch (e) {\n // a cancelled request is the caller giving up, not EBI being\n // unreachable, so it must end the poll rather than be retried\n if (isAbortError(e)) {\n throw e\n }\n failingSince ??= Date.now()\n if (Date.now() - failingSince >= STATUS_FAILURE_BUDGET_MS) {\n throw new Error(\n `Could not reach EBI to check ${tool} job ${jobId} for ${Math.round(STATUS_FAILURE_BUDGET_MS / 60_000)} minutes`,\n { cause: e },\n )\n }\n console.warn('[msaview] EBI status check failed, retrying:', e)\n return false\n }\n failingSince = undefined\n // exact match, not includes(): a job whose status is ERROR must not be\n // able to poll forever waiting for a FINISHED that will never arrive\n if (status === 'FINISHED') {\n return true\n }\n if (FAILED_STATUSES.has(status)) {\n throw new Error(`EBI ${tool} job ${jobId} returned status ${status}`)\n }\n // RUNNING, QUEUED, PENDING and anything else EBI adds later\n return false\n },\n })\n}\n\nexport async function runEbiJob({\n tool,\n label,\n params,\n onProgress,\n onRid,\n signal,\n}: {\n tool: string\n label: string\n params: Record<string, string>\n onProgress: (arg: string) => void\n onRid?: (jobId: string) => void\n signal?: AbortSignal\n}) {\n onProgress(`Submitting ${label} to EBI...`)\n const jobId = await submitEbiJob({ tool, params, signal })\n onRid?.(jobId)\n await waitForEbiJob({\n tool,\n jobId,\n signal,\n onCountdown: s => {\n onProgress(`Re-checking ${label} status in... ${s}`)\n },\n })\n return {\n jobId,\n result: (type: string) =>\n textfetch(`${EBI_BASE}/${tool}/result/${jobId}/${type}`, { signal }),\n }\n}\n", "/**\n * Only used to build the link-out on the manual panel, which sends the user to\n * NCBI's own site to run BLAST there. Nothing fetches this url: NCBI stopped\n * sending Access-Control-Allow-Origin to third-party origins, so a browser\n * cannot read a response from it at all. See docs/blast.md.\n */\nexport const BASE_BLAST_URL = 'https://blast.ncbi.nlm.nih.gov/Blast.cgi'\n\n/** The aligners EBI's Job Dispatcher runs, each a tool name at their REST api. */\nexport const ebiMsaAlgorithms = [\n 'clustalo',\n 'muscle',\n 'kalign',\n 'mafft',\n] as const\nexport type EbiMsaAlgorithm = (typeof ebiMsaAlgorithms)[number]\n\n/**\n * `browser` is no job at all: each sequence is aligned to the query in the\n * page and the rows merged on the query (utils/browserAlign.ts), with the tree\n * built by react-msaview's neighbour joining. It is the aligner for a launch\n * that must not depend on EBI, and for one that wants to be quick -- a\n * hundred 400-residue rows take under a second, and a hundred 1400-residue\n * rows eight, against a Job Dispatcher queue that has been measured at\n * anything from ten seconds to fifteen minutes. Past the per-sequence limit in\n * browserAlign.ts it refuses and names an EBI aligner instead.\n */\nexport const msaAlgorithms = [...ebiMsaAlgorithms, 'browser'] as const\nexport type MsaAlgorithm = (typeof msaAlgorithms)[number]\n\nexport const msaAlgorithmLabels: Record<MsaAlgorithm, string> = {\n clustalo: 'Clustal Omega (EBI)',\n muscle: 'MUSCLE (EBI)',\n kalign: 'Kalign (EBI)',\n mafft: 'MAFFT (EBI)',\n browser: 'in browser, query-anchored',\n}\n\n/**\n * EBI rejects a submission naming a database outside its own list with a 400,\n * so every value here has to appear in\n * https://www.ebi.ac.uk/Tools/services/rest/ncbiblast/parameterdetails/database\n * -- `uniprotkb_reference_proteomes` did not, and 3.0.0 shipped it as a dead\n * menu entry.\n */\nexport const blastDatabaseOptions = [\n 'uniprotkb_swissprot',\n 'uniprotkb',\n 'pan_proteomes',\n 'uniprotkb_trembl',\n] as const\nexport type BlastDatabase = (typeof blastDatabaseOptions)[number]\n\n// curated, so it returns roughly one good sequence per species rather than the\n// many near-identical TrEMBL entries an alignment reads poorly\nconst defaultBlastDatabase: BlastDatabase = 'uniprotkb_swissprot'\n\nexport const searchPrograms = ['blastp', 'phmmer'] as const\nexport type SearchProgram = (typeof searchPrograms)[number]\n\nexport const searchProgramLabels: Record<SearchProgram, string> = {\n blastp: 'blastp (sequence search)',\n phmmer: 'phmmer (profile HMM search)',\n}\n\n/**\n * phmmer offers PDB, AlphaFold, Ensembl Genomes, MEROPS and ChEMBL too, but\n * targets outside UniProt carry no species in their description, so those rows\n * would lose their species and common name. Only the databases that label their\n * hits are offered.\n *\n * rp15..rp75 are the Representative Proteomes: UniProt's reference proteomes\n * thinned so that no two are more than 15% (35%, 55%, 75%) similar, which is\n * the widest taxonomic spread per hit that any of these databases gives. rp15\n * is the one to reach for when the question is \"what is this like across all\n * of life\"; swissprot when it is \"what is this like in the curated set\".\n */\nexport const phmmerDatabaseOptions = [\n 'swissprot',\n 'uniprotkb',\n 'uniprotrefprot',\n 'rp75',\n 'rp55',\n 'rp35',\n 'rp15',\n] as const\nexport type PhmmerDatabase = (typeof phmmerDatabaseOptions)[number]\n\nconst defaultPhmmerDatabase: PhmmerDatabase = 'swissprot'\n\n/**\n * The hit counts EBI's ncbiblast accepts for `alignments` and `scores`. A value\n * off this list is a 400 at submit time, so a request is rounded up to the next\n * one on it.\n */\nconst blastHitCounts = [5, 10, 20, 50, 100, 150, 200, 250, 500, 750, 1000]\n\nexport const defaultMaxHits = 100\n\nexport function snapBlastHitCount(maxHits: number) {\n return blastHitCounts.find(n => n >= maxHits) ?? blastHitCounts.at(-1)!\n}\n\n/**\n * A program together with a database that program actually has.\n *\n * The pair travels as one value because neither service knows the other's\n * database names \u2014 `swissprot` is a phmmer database and `uniprotkb_swissprot` a\n * blastp one \u2014 so a program held apart from its database can drift into a\n * combination EBI answers with a 400, minutes after the user pressed Submit.\n */\nexport type SearchChoice =\n | { program: 'blastp'; database: BlastDatabase }\n | { program: 'phmmer'; database: PhmmerDatabase }\n\nexport function defaultSearchFor(program: SearchProgram): SearchChoice {\n return program === 'phmmer'\n ? { program, database: defaultPhmmerDatabase }\n : { program, database: defaultBlastDatabase }\n}\n\nexport function databaseOptionsFor(program: SearchProgram) {\n return program === 'phmmer' ? phmmerDatabaseOptions : blastDatabaseOptions\n}\n\n/**\n * What each database is called in the menu. The keys are what EBI is sent and\n * are not negotiable; `uniprotkb_swissprot` and `swissprot` are the same\n * collection under each service's own name, so they read the same here.\n */\nconst databaseLabels: Record<BlastDatabase | PhmmerDatabase, string> = {\n uniprotkb_swissprot: 'UniProtKB/Swiss-Prot (curated)',\n swissprot: 'UniProtKB/Swiss-Prot (curated)',\n uniprotkb: 'UniProtKB (all entries)',\n uniprotkb_trembl: 'UniProtKB/TrEMBL (unreviewed)',\n pan_proteomes: 'Pan-proteomes',\n uniprotrefprot: 'UniProt reference proteomes',\n rp75: 'Representative proteomes, 75%',\n rp55: 'Representative proteomes, 55%',\n rp35: 'Representative proteomes, 35%',\n rp15: 'Representative proteomes, 15% (widest spread)',\n}\n\nexport function databaseLabel(database: BlastDatabase | PhmmerDatabase) {\n return databaseLabels[database]\n}\n", "import type { Node, NodeWithIds } from './types.ts'\n\n/**\n * Copy a parsed tree, giving every node a stable id derived from its path, and\n * falling back to that id for an unnamed node.\n *\n * Iterative, like the traversals in @gmod/newick and the Newick emitter in the\n * viewer's neighbor joining: a phylogeny can be a caterpillar whose depth equals\n * its leaf count, and the recursive form of this overflowed the stack somewhere\n * past 5000 deep -- which every tree reaches, since this is the last step of\n * parsing one.\n */\nexport function generateNodeIds(\n tree: Node,\n parent = 'node',\n depth = 0,\n): NodeWithIds {\n const withId = (node: Node, id: string): NodeWithIds => ({\n ...node,\n id,\n name: node.name || id,\n children: [],\n })\n\n const root = withId(tree, `${parent}-${depth}`)\n const stack = [{ src: tree, out: root, depth }]\n while (stack.length > 0) {\n const { src, out, depth: d } = stack.pop()!\n if (src.children) {\n out.children = src.children.map((child, i) =>\n withId(child, `${out.id}-${i}-${d + 1}`),\n )\n for (const [i, child] of src.children.entries()) {\n stack.push({ src: child, out: out.children[i]!, depth: d + 1 })\n }\n }\n }\n return root\n}\n", "import type { MSATrack, NodeWithIds } from '../types.ts'\n\nexport default abstract class BaseMSA {\n protected rows = new Map<string, string>()\n private names: string[]\n private width?: number\n\n /**\n * A repeated name keeps its first row: names index the rows, so listing the\n * name twice would render a phantom duplicate row.\n */\n constructor(rows: Iterable<readonly [string, string]>) {\n for (const [name, seq] of rows) {\n if (!this.rows.has(name)) {\n this.rows.set(name, seq)\n }\n }\n this.names = [...this.rows.keys()]\n }\n\n getRow(name: string): string {\n return this.rows.get(name) ?? ''\n }\n\n getNames(): string[] {\n return this.names\n }\n\n /**\n * Column count of the alignment: the length of its widest row, since a\n * hand-edited fasta or some aligners leave rows short. The viewer's gap\n * analysis counts columns the same way.\n */\n getWidth(): number {\n this.width ??= this.getNames().reduce(\n (max, name) => Math.max(max, this.getRow(name).length),\n 0,\n )\n return this.width\n }\n\n getTree(): NodeWithIds {\n return {\n id: 'root',\n name: 'root',\n noTree: true,\n children: this.getNames().map(name => ({\n id: name,\n children: [],\n name,\n })),\n }\n }\n\n getRowData(\n _name: string,\n ): { name?: string; accession?: string; dbxref?: string } | undefined {\n return undefined\n }\n\n getStructures(): Record<string, unknown> {\n return {}\n }\n\n getHeader(): Record<string, unknown> {\n return {}\n }\n\n get alignmentNames(): string[] {\n return []\n }\n\n get seqConsensus(): string | undefined {\n return undefined\n }\n\n get secondaryStructureConsensus(): string | undefined {\n return undefined\n }\n\n get tracks(): MSATrack[] {\n return []\n }\n}\n", "import { parseNewick } from '@gmod/newick'\n\nimport type { NewickNode } from '@gmod/newick'\n\n/**\n * Newick parsing for phylogenetic trees.\n *\n * `postParenNumeric: 'name'` is the whole reason this wrapper exists. A bare\n * number after a `)` is an internal node label in standard Newick -- typically a\n * bootstrap support value -- but `@gmod/hclust` reuses that slot for a cluster's\n * merge height, and the parser's default guesses between the two by whether the\n * tree carries any `:` branch length. Everything reaching this package is a\n * phylogeny (newick, the tree embedded in Stockholm `#=GF NH`, EMF, ASN.1), so\n * the guess is settled here instead: reading `((A,B)95,(C,D)80);` as lengths\n * would draw a phylogram scaled by support values.\n */\nexport default function parse(s: string): NewickNode {\n return parseNewick(s, { postParenNumeric: 'name' })\n}\n", "/**\n * Stockholm format parser\n * Based on stockholm-js by Ian Holmes\n * Rewritten in TypeScript\n */\n\nexport interface StockholmData {\n gf: Record<string, string[]>\n gc: Record<string, string>\n gs: Record<string, Record<string, string[]>>\n gr: Record<string, Record<string, string>>\n seqname: string[]\n seqdata: Record<string, string>\n}\n\nfunction createStockholm(): StockholmData {\n return {\n gf: Object.create(null),\n gc: Object.create(null),\n gs: Object.create(null),\n gr: Object.create(null),\n seqname: [],\n seqdata: Object.create(null),\n }\n}\n\n// records before a \"# STOCKHOLM 1.0\" header are an error in strict mode,\n// otherwise they implicitly start a new alignment\nfunction ensureStock(\n stock: StockholmData | null,\n strict: boolean,\n): StockholmData {\n if (stock) {\n return stock\n }\n if (strict) {\n throw new Error('No format header: # STOCKHOLM 1.0')\n }\n return createStockholm()\n}\n\nconst formatStartRegex = /^# STOCKHOLM 1.0/\nconst formatEndRegex = /^\\/\\/\\s*$/\nconst gfRegex = /^#=GF\\s+(\\S+)\\s+(.*?)\\s*$/\nconst gcRegex = /^#=GC\\s+(\\S+)\\s+(.*?)\\s*$/\nconst gsRegex = /^#=GS\\s+(\\S+)\\s+(\\S+)\\s+(.*?)\\s*$/\nconst grRegex = /^#=GR\\s+(\\S+)\\s+(\\S+)\\s+(.*?)\\s*$/\n// a sequence line is \"<name> <residues>\". The leading [^#\\s] guards against a\n// two-word comment (\"# note\") being taken as a sequence named '#'; every\n// meaningful '#' line is a #=GF/#=GC/#=GS/#=GR record already matched above.\nconst lineRegex = /^\\s*([^#\\s]\\S*)\\s+(\\S+)\\s*$/\nconst nonwhiteRegex = /\\S/\n\nexport function sniff(text: string): boolean {\n return formatStartRegex.test(text)\n}\n\nexport function parseAll(\n text: string,\n opts?: { strict?: boolean },\n): StockholmData[] {\n const options = opts ?? {}\n const db: StockholmData[] = []\n let stock: StockholmData | null = null\n // one tree spans consecutive `#=GF NH` lines, so a `#=GF TN` naming the\n // next tree, or any other #=GF line, ends it\n let treeContinues = false\n\n const lines = text.split('\\n')\n for (const line of lines) {\n let match: RegExpExecArray | null\n\n if (formatStartRegex.test(line)) {\n if (stock) {\n db.push(stock)\n }\n stock = createStockholm()\n treeContinues = false\n } else if (formatEndRegex.test(line)) {\n if (stock) {\n db.push(stock)\n }\n stock = null\n } else if ((match = gfRegex.exec(line))) {\n stock = ensureStock(stock, !!options.strict)\n const tag = match[1]!\n const values = (stock.gf[tag] ??= [])\n if (tag === 'NH' && treeContinues && values.length > 0) {\n values[values.length - 1] += match[2]!\n } else {\n values.push(match[2]!)\n }\n treeContinues = tag === 'NH'\n } else if ((match = gcRegex.exec(line))) {\n stock = ensureStock(stock, !!options.strict)\n stock.gc[match[1]!] = (stock.gc[match[1]!] ?? '') + match[2]!\n } else if ((match = gsRegex.exec(line))) {\n stock = ensureStock(stock, !!options.strict)\n const byName = (stock.gs[match[2]!] ??= Object.create(null))\n ;(byName[match[1]!] ??= []).push(match[3]!)\n } else if ((match = grRegex.exec(line))) {\n stock = ensureStock(stock, !!options.strict)\n const byName = (stock.gr[match[2]!] ??= Object.create(null))\n byName[match[1]!] = (byName[match[1]!] ?? '') + match[3]!\n } else if ((match = lineRegex.exec(line))) {\n stock = ensureStock(stock, !!options.strict)\n const seqname = match[1]!\n const seqdata = match[2]!\n if (stock.seqdata[seqname] === undefined) {\n stock.seqdata[seqname] = ''\n stock.seqname.push(seqname)\n }\n stock.seqdata[seqname] += seqdata\n } else if (nonwhiteRegex.test(line)) {\n if (options.strict) {\n throw new Error('Malformed line')\n }\n }\n }\n\n if (stock) {\n db.push(stock)\n }\n\n return db\n}\n\nexport function parse(\n text: string,\n opts?: { strict?: boolean },\n): StockholmData {\n const db = parseAll(text, opts)\n if (db.length === 0) {\n throw new Error('No alignments found')\n }\n if (db.length > 1) {\n throw new Error('More than one alignment found')\n }\n return db[0]!\n}\n", "import { generateNodeIds } from '../util.ts'\nimport BaseMSA from './BaseMSA.ts'\nimport parseNewick from './parseNewick.ts'\nimport { parseAll } from './stockholmParser.ts'\n\nimport type { MSATrack, NodeWithIds } from '../types.ts'\nimport type { StockholmData } from './stockholmParser.ts'\n\nexport default class StockholmMSA extends BaseMSA {\n private data: StockholmData[]\n private MSA: StockholmData\n\n constructor(text: string, currentAlignment: number) {\n const res = parseAll(text)\n const aln = res[currentAlignment] ?? res[0]\n if (!aln) {\n throw new Error('No alignments found in Stockholm file')\n }\n super(aln.seqname.map(name => [name, aln.seqdata[name] ?? '']))\n this.data = res\n this.MSA = aln\n }\n\n getMSA() {\n return this.MSA\n }\n\n get alignmentNames() {\n return this.data.map((aln, idx) => aln.gf.DE?.[0] ?? `Alignment ${idx + 1}`)\n }\n\n getHeader() {\n const acEntries = this.MSA.gs.AC ?? {}\n const drEntries = this.MSA.gs.DR ?? {}\n return {\n General: this.MSA.gf,\n Accessions: Object.fromEntries(\n Object.entries(acEntries).map(([k, v]) => [k, v[0]]),\n ),\n Dbxref: Object.fromEntries(\n Object.entries(drEntries).map(([k, v]) => [k, v.join('; ')]),\n ),\n }\n }\n\n getRowData(rowName: string) {\n return {\n name: rowName,\n accession: this.MSA.gs.AC?.[rowName]?.[0],\n dbxref: this.MSA.gs.DR?.[rowName]?.join('; '),\n }\n }\n\n getStructures() {\n const pdbRegex = /PDB; +(\\S+) +([^;\\s]+); *(-?[0-9]+)-(-?[0-9]+)/\n const drEntries = this.MSA.gs.DR ?? {}\n const result: Record<\n string,\n { pdb: string; chain: string; startPos: number; endPos: number }[]\n > = {}\n for (const [id, drList] of Object.entries(drEntries)) {\n for (const dr of drList) {\n const match = pdbRegex.exec(dr)\n if (match) {\n ;(result[id] ??= []).push({\n pdb: match[1]!.toLowerCase(),\n chain: match[2]!,\n startPos: +match[3]!,\n endPos: +match[4]!,\n })\n }\n }\n }\n return result\n }\n\n getTree(): NodeWithIds {\n const tree = this.MSA.gf.NH?.[0]\n return tree ? generateNodeIds(parseNewick(tree)) : super.getTree()\n }\n\n get seqConsensus() {\n return this.MSA.gc.seq_cons\n }\n\n get secondaryStructureConsensus() {\n return this.MSA.gc.SS_cons\n }\n\n /**\n * One text track per `#=GC` line, and one per `#=GR` line that stays hidden\n * until asked for: a Pfam seed carries a few per-row active-site lines, but\n * an Rfam family carries a structure line for every row with a PDB entry.\n */\n get tracks(): MSATrack[] {\n const { seq_cons, SS_cons, ...otherGc } = this.MSA.gc\n return [\n {\n id: 'seqConsensus',\n name: 'Sequence consensus',\n data: seq_cons,\n customColorScheme: {},\n },\n {\n id: 'secondaryStruct',\n name: 'Secondary-structure',\n data: SS_cons,\n customColorScheme: wussColors,\n },\n ...Object.entries(otherGc).map(([tag, data]) => ({\n id: `gc-${tag}`,\n name: tag,\n data,\n customColorScheme: structureColors(tag),\n })),\n ...Object.entries(this.MSA.gr).flatMap(([tag, byRow]) =>\n Object.entries(byRow).map(([row, data]) => ({\n id: `gr-${row}-${tag}`,\n name: `${row} ${tag}`,\n data,\n customColorScheme: structureColors(tag),\n defaultOff: true,\n })),\n ),\n ]\n }\n}\n\n// WUSS writes base-paired columns as open/close brackets of several nesting\n// types (<>, (), [], {}); coloring every open one way and every close the other\n// highlights each helix, including the tRNA acceptor stem written with parens\nconst wussColors: Record<string, string> = {\n '<': 'lightblue',\n '(': 'lightblue',\n '[': 'lightblue',\n '{': 'lightblue',\n '>': 'pink',\n ')': 'pink',\n ']': 'pink',\n '}': 'pink',\n}\n\n// `SS`, and Rfam's per-structure `2GIS_A_SS`\nfunction structureColors(tag: string) {\n return tag === 'SS' || tag.endsWith('_SS') ? wussColors : {}\n}\n\nexport { sniff as stockholmSniff } from './stockholmParser.ts'\n", "export interface FastaRecord {\n id: string\n seq: string\n}\n\n// a `>` record, optionally after `#` header lines such as ColabFold's `#8\\t1`\nexport function fastaSniff(text: string) {\n return /^(#.*\\n)*>/.test(text)\n}\n\n/**\n * Split FASTA-style text (shared by the FASTA and A3M parsers) into records.\n *\n * A record starts at a `>` that begins a line, so a `>` inside a defline\n * (`x->y`, HGVS `c.1799T>A`) stays part of it, and anything before the first\n * record (ColabFold's `#8\\t1` header) is skipped. The id is the first word of\n * the defline, so `> name` reads as `name`, and a defline with no word names\n * its record `unnamed_N` after its position in the file. A repeated id keeps\n * the first record: ids index the row data, so emitting the id twice would\n * render a phantom duplicate row showing the last record's residues.\n */\nexport function splitFastaRecords(text: string): FastaRecord[] {\n const records: FastaRecord[] = []\n const seen = new Set<string>()\n let current: { id: string; lines: string[] } | undefined\n\n const flush = () => {\n if (current && !seen.has(current.id)) {\n seen.add(current.id)\n records.push({\n id: current.id,\n seq: current.lines.join('').replaceAll(/\\s/g, ''),\n })\n }\n }\n\n let count = 0\n for (const line of text.split('\\n')) {\n if (line.startsWith('>')) {\n flush()\n count++\n const id = /^>\\s*(\\S*)/.exec(line)![1] || `unnamed_${count}`\n current = { id, lines: [] }\n } else {\n current?.lines.push(line)\n }\n }\n flush()\n\n return records\n}\n\nexport function toRecords(input: string | FastaRecord[]) {\n return typeof input === 'string' ? splitFastaRecords(input) : input\n}\n", "import BaseMSA from './BaseMSA.ts'\nimport { fastaSniff, toRecords } from './fastaRecords.ts'\n\nimport type { FastaRecord } from './fastaRecords.ts'\n\n/**\n * A3M Format Parser\n *\n * The A3M format consists of aligned FASTA, in which alignments are shown with:\n * - Inserts as lowercase characters\n * - Matches as uppercase characters\n * - Deletions as '-'\n * - Gaps aligned to inserts as '.'\n *\n * Note that gaps aligned to inserts can be omitted in the A3M format.\n *\n * Example:\n * >query\n * ETESMKTVRIREKIKKFLGDRPRNTAEILEHINSTMRHGTTSQQLGNVLSKDKDIVKVGYIKRSGILSGGYDICEWATRNWVAEHCPEWTE\n * >seq1\n * ----MRTTRLRQKIKKFLNERGeANTTEILEHVNSTMRHGTTPQQLGNVLSKDKDILKVATTKRGGALSGRYEICVWTLRP-----------\n *\n * In the above, 'e' after 'G' in seq1 is a lowercase insert.\n *\n * @see https://yanglab.qd.sdu.edu.cn/trRosetta/msa_format.html\n */\n\nconst CODE_A = 65 // 'A'\nconst CODE_Z = 90 // 'Z'\nconst CODE_a = 97 // 'a'\nconst CODE_z = 122 // 'z'\nconst CODE_DASH = 45 // '-'\n\nfunction isLower(code: number): boolean {\n return code >= CODE_a && code <= CODE_z\n}\n\nfunction isMatch(code: number): boolean {\n return (code >= CODE_A && code <= CODE_Z) || code === CODE_DASH\n}\n\ninterface ParsedRow {\n // one entry per match column, in order\n matches: string[]\n // inserts[k] is the run of insert residues sitting immediately BEFORE match\n // column k, already uppercased; inserts[matches.length] holds the trailing\n // run. An insert must never consume a match column, or a row that opens with\n // an insert falls a column out of register with every other row.\n inserts: string[]\n}\n\nfunction parseRow(seq: string): ParsedRow {\n const matches: string[] = []\n const inserts = ['']\n\n for (const ch of seq) {\n const code = ch.charCodeAt(0)\n if (isMatch(code)) {\n matches.push(ch)\n inserts.push('')\n } else if (isLower(code)) {\n inserts[inserts.length - 1] += ch.toUpperCase()\n }\n // '.' is padding aligned to some other row's insert, and anything else is\n // unrecognized -- neither carries alignment information\n }\n\n return { matches, inserts }\n}\n\nexport default class A3mMSA extends BaseMSA {\n constructor(input: string | FastaRecord[]) {\n const records = toRecords(input)\n const expanded = expandA3M(records.map(r => r.seq))\n super(records.map((r, i) => [r.id, expanded[i]!]))\n }\n\n static sniff(input: string | FastaRecord[]): boolean {\n if (typeof input === 'string' && !fastaSniff(input)) {\n return false\n }\n\n const seqs = toRecords(input)\n .map(r => r.seq)\n .filter(s => !!s)\n\n if (seqs.length < 2) {\n return false\n }\n\n // A true aligned FASTA (e.g. impg's fasta-aln output from soft-masked\n // references) has all rows the same total length. A3M's defining feature is\n // variable-length rows, since lowercase inserts live outside the fixed match\n // grid. So equal-length rows are an alignment, not A3M, even when lowercase\n // soft-masking is present.\n if (new Set(seqs.map(s => s.length)).size === 1) {\n return false\n }\n\n let hasLowercase = false\n let matchCount: number | undefined\n for (const seq of seqs) {\n let matches = 0\n for (let i = 0; i < seq.length; i++) {\n const code = seq.charCodeAt(i)\n if (isMatch(code)) {\n matches++\n } else if (isLower(code)) {\n hasLowercase = true\n }\n }\n if (matchCount !== undefined && matches !== matchCount) {\n return false\n }\n matchCount = matches\n }\n return hasLowercase\n }\n}\n\n/**\n * Expand A3M rows into a rectangular alignment: every insert slot is widened to\n * the longest insert any row places there, and rows without one are padded with\n * '.' so all rows stay in register.\n */\nfunction expandA3M(rawSeqs: string[]): string[] {\n const rows = rawSeqs.map(parseRow)\n // a loop, not Math.max(...): an a3m from an hhblits search routinely carries\n // six figures of hits, and spreading one argument per row throws\n // \"Maximum call stack size exceeded\" somewhere past ~125k of them\n let numPositions = 0\n for (const { matches } of rows) {\n numPositions = Math.max(numPositions, matches.length)\n }\n\n // one insert slot before each match column, plus one trailing slot\n const maxInserts = new Array<number>(numPositions + 1).fill(0)\n for (const { inserts } of rows) {\n for (const [pos, ins] of inserts.entries()) {\n maxInserts[pos] = Math.max(maxInserts[pos]!, ins.length)\n }\n }\n\n return rows.map(({ matches, inserts }) => {\n const result: string[] = []\n for (let pos = 0; pos <= numPositions; pos++) {\n const ins = inserts[pos] ?? ''\n result.push(ins, '.'.repeat(maxInserts[pos]! - ins.length))\n if (pos < numPositions) {\n // a row with fewer match columns than the widest is padded out\n result.push(matches[pos] ?? '-')\n }\n }\n return result.join('')\n })\n}\n", "import { parse } from 'clustal-js'\n\nimport BaseMSA from './BaseMSA.ts'\n\nexport default class ClustalMSA extends BaseMSA {\n private MSA: ReturnType<typeof parse>\n\n constructor(text: string) {\n const msa = parse(text)\n super(msa.alns.map(aln => [aln.id, aln.seq]))\n this.MSA = msa\n }\n\n getHeader() {\n return this.MSA.header\n }\n\n get seqConsensus() {\n return this.MSA.consensus\n }\n}\n", "import { parseEmfAln } from 'emf-js'\n\nimport BaseMSA from './BaseMSA.ts'\n\nexport default class EmfMSA extends BaseMSA {\n constructor(text: string) {\n super(parseEmfAln(text).map(aln => [aln.protein, aln.seq]))\n }\n}\n", "import BaseMSA from './BaseMSA.ts'\nimport { toRecords } from './fastaRecords.ts'\n\nimport type { FastaRecord } from './fastaRecords.ts'\n\nexport default class FastaMSA extends BaseMSA {\n // Newick tools write a colon in a name as an underscore\n private colonNormalized = new Map<string, string>()\n\n constructor(input: string | FastaRecord[]) {\n const records = toRecords(input)\n super(records.map(r => [r.id, r.seq]))\n for (const { id } of records) {\n if (id.includes(':')) {\n this.colonNormalized.set(id.replaceAll(':', '_'), id)\n }\n }\n }\n\n getRow(name: string) {\n return (\n this.rows.get(name) ??\n this.rows.get(this.colonNormalized.get(name) ?? '') ??\n ''\n )\n }\n}\n", "import A3mMSA from './A3mMSA.ts'\nimport ClustalMSA from './ClustalMSA.ts'\nimport EmfMSA from './EmfMSA.ts'\nimport FastaMSA from './FastaMSA.ts'\nimport StockholmMSA, { stockholmSniff } from './StockholmMSA.ts'\nimport { fastaSniff, splitFastaRecords } from './fastaRecords.ts'\n\nexport { parseEmfTree } from 'emf-js'\nexport { default as parseNewick } from './parseNewick.ts'\n\nexport type MSAParserType =\n | StockholmMSA\n | A3mMSA\n | FastaMSA\n | EmfMSA\n | ClustalMSA\n\nexport type MSAFormat = 'stockholm' | 'a3m' | 'fasta' | 'emf' | 'clustal'\n\nconst htmlPage = /^<(!doctype\\s+html|html[\\s>])/i\nconst clustalHeader = /^(CLUSTAL|MUSCLE|PROBCONS|MSAPROBS|Kalign)/i\n\n// A caller that knows the format, such as impg emitting fasta-aln, passes\n// `format` to skip sniffing, which cannot always tell FASTA from A3M\nexport function parseMSA(\n input: string,\n currentAlignment = 0,\n format?: MSAFormat,\n): MSAParserType {\n const text = input\n .replace(/^\\uFEFF/, '')\n .replaceAll(/\\r\\n?/g, '\\n')\n .trimStart()\n if (htmlPage.test(text)) {\n throw new Error(\n 'Received an HTML page, not an alignment. Check that the URL points at the file itself',\n )\n }\n if (format === 'stockholm') {\n return new StockholmMSA(text, currentAlignment)\n }\n if (format === 'a3m') {\n return new A3mMSA(text)\n }\n if (format === 'fasta') {\n return new FastaMSA(text)\n }\n if (format === 'emf') {\n return new EmfMSA(text)\n }\n if (format === 'clustal') {\n return new ClustalMSA(text)\n }\n if (stockholmSniff(text)) {\n return new StockholmMSA(text, currentAlignment)\n }\n if (fastaSniff(text)) {\n const records = splitFastaRecords(text)\n return A3mMSA.sniff(records) ? new A3mMSA(records) : new FastaMSA(records)\n }\n if (text.startsWith('SEQ')) {\n return new EmfMSA(text)\n }\n if (clustalHeader.test(text)) {\n return new ClustalMSA(text)\n }\n const firstLine = text.split('\\n', 1)[0]!.slice(0, 80)\n throw new Error(\n firstLine\n ? `Unrecognized alignment format: expected FASTA, A3M, Stockholm, Clustal or EMF, but the first line reads \"${firstLine}\"`\n : 'The alignment file is empty',\n )\n}\n\n/**\n * Get ungapped sequence from an aligned row\n */\nexport function getUngappedSequence(alignedSeq: string): string {\n return alignedSeq.replaceAll(/[.-]/g, '')\n}\n\nexport { default as A3mMSA } from './A3mMSA.ts'\nexport { default as ClustalMSA } from './ClustalMSA.ts'\nexport { default as EmfMSA } from './EmfMSA.ts'\nexport { default as FastaMSA } from './FastaMSA.ts'\nexport { default as StockholmMSA, stockholmSniff } from './StockholmMSA.ts'\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["hostOf", "url", "HttpError", "message", "status", "handleFetch", "args", "response", "e", "textfetch", "jsonfetch", "timeout", "time", "signal", "resolve", "reject", "onAbort", "id", "isAbortError", "import_react", "readLocalStorage", "key", "initialValue", "item", "error", "useLocalStorage", "storedValue", "setStoredValue", "value", "pollLoop", "check", "intervalSeconds", "onCountdown", "signal", "i", "timeout", "EBI_BASE", "EBI_EMAIL_STORAGE_KEY", "DEFAULT_EBI_EMAIL", "getEbiEmail", "readLocalStorage", "FAILED_STATUSES", "submitEbiJob", "tool", "params", "signal", "textfetch", "STATUS_FAILURE_BUDGET_MS", "waitForEbiJob", "jobId", "intervalSeconds", "onCountdown", "failingSince", "pollLoop", "status", "e", "isAbortError", "runEbiJob", "label", "onProgress", "onRid", "s", "type", "BASE_BLAST_URL", "ebiMsaAlgorithms", "msaAlgorithms", "msaAlgorithmLabels", "blastDatabaseOptions", "defaultBlastDatabase", "searchPrograms", "searchProgramLabels", "phmmerDatabaseOptions", "defaultPhmmerDatabase", "blastHitCounts", "defaultMaxHits", "snapBlastHitCount", "maxHits", "n", "defaultSearchFor", "program", "databaseOptionsFor", "databaseLabels", "databaseLabel", "database", "generateNodeIds", "tree", "parent", "depth", "withId", "node", "id", "root", "stack", "src", "out", "d", "child", "i", "BaseMSA", "rows", "name", "seq", "max", "_name", "parse", "s", "parseNewick", "createStockholm", "ensureStock", "stock", "strict", "formatStartRegex", "formatEndRegex", "gfRegex", "gcRegex", "gsRegex", "grRegex", "lineRegex", "nonwhiteRegex", "sniff", "text", "parseAll", "opts", "options", "db", "treeContinues", "lines", "line", "match", "tag", "values", "byName", "seqname", "seqdata", "StockholmMSA", "BaseMSA", "text", "currentAlignment", "res", "parseAll", "aln", "name", "idx", "acEntries", "drEntries", "k", "v", "rowName", "pdbRegex", "result", "id", "drList", "dr", "match", "tree", "generateNodeIds", "parse", "seq_cons", "SS_cons", "otherGc", "wussColors", "tag", "data", "structureColors", "byRow", "row", "fastaSniff", "text", "splitFastaRecords", "records", "seen", "current", "flush", "count", "line", "toRecords", "input", "CODE_A", "CODE_Z", "CODE_a", "CODE_z", "CODE_DASH", "isLower", "code", "isMatch", "parseRow", "seq", "matches", "inserts", "ch", "A3mMSA", "BaseMSA", "input", "records", "toRecords", "expanded", "expandA3M", "r", "i", "fastaSniff", "seqs", "s", "hasLowercase", "matchCount", "rawSeqs", "rows", "numPositions", "maxInserts", "pos", "ins", "result", "ClustalMSA", "BaseMSA", "text", "msa", "parse", "aln", "EmfMSA", "BaseMSA", "text", "parseEmfAln", "aln", "FastaMSA", "BaseMSA", "input", "records", "toRecords", "r", "id", "name", "htmlPage", "clustalHeader", "parseMSA", "input", "currentAlignment", "format", "text", "StockholmMSA", "A3mMSA", "FastaMSA", "EmfMSA", "ClustalMSA", "sniff", "fastaSniff", "records", "splitFastaRecords", "firstLine", "getUngappedSequence", "alignedSeq"]
|
|
7
|
+
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{a as H,c as J,d as S,e as Q,f as Z,p as Y}from"./chunk-
|
|
1
|
+
import{a as H,c as J,d as S,e as Q,f as Z,p as Y}from"./chunk-A63PUWQZ.js";import{a as Pe}from"./chunk-IBBQUV2I.js";import{a as Ne}from"./chunk-2IWD4OO4.js";import{a as Te,b as K}from"./chunk-FY3BTKY4.js";var Re=Te((bt,oe)=>{oe.exports=JBrowseExports["@jbrowse/core/util/translateTranscript"]});var M=K(Pe());function ut(e){return(0,M.getContainingView)(e)}function te(e){return typeof e=="string"&&e!==""}function ne(e){return[...new Set(e.filter(te))]}function re(e,t){return t.filter(te).join(e)}function Ee(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 ee(e){let t=(0,M.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 mt(e){return e?.id()??""}function Me(e){return e?ne([e.id(),e.get("name"),e.get("id"),e.get("transcript_id")]):[]}function dt(e,t){return Me(e).includes(t)}function Ae(e){return e?re(" ",[e.get("name"),e.get("id")]):""}function _e(e){return e?re(" ",[e.get("gene_name")??e.get("name"),e.get("id")?`(${e.get("id")})`:void 0]):""}function lt(e,t){return`BLAST - ${_e(e)} - ${Ae(t)}`}function gt(e){return Ee(e).toSorted((n,r)=>ee(r).len-ee(n).len)}function ft(e){return e.replace(/[*&]+$/,"").replaceAll(/[*&]/g,"X")}function ht(e){return ne([e.id(),e.get("id"),e.get("name"),e.get("gene_id"),e.get("gene_name")])}var se=K(Ne());async function xt({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,se.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",Oe="jbrowse2@berkeley.edu",ae="https://eutils.ncbi.nlm.nih.gov/entrez/eutils";function ce(e){return new URLSearchParams({...e,tool:$e,email:Oe})}function L(e,t){return`${ae}/${e}.fcgi?${ce(t).toString()}`}function _(e){return L("efetch",e)}function ue(e){return[`${ae}/efetch.fcgi`,{method:"POST",body:ce(e)}]}var ie=350,A=0;async function me(e){let t=Date.now(),n=Math.max(t,A);if(A=n+ie,n>t)try{await Q(n-t,e??void 0)}catch(r){throw A===n+ie&&(A=n),r}}async function B(e,t){return await me(t?.signal),J(e,t)}async function de(e,t){return await me(t?.signal),S(e,t)}var je={amp:"&",apos:"'",gt:">",lt:"<",quot:'"'};function k(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))):je[n]??t)}var F="https://api.ncbi.nlm.nih.gov/datasets/v2",Le=100;function ke(e){return e.trim().replace(/^\w+:/,"").replace(/\.\d+$/,"")}function Fe(e,t){let n=e.toLowerCase();return(t.find(o=>o.symbol===e)??t.find(o=>o.synonyms?.includes(e))??t.find(o=>o.symbol?.toLowerCase()===n)??t[0])?.gene_id}async function ve(e,t,n){try{return((await S(`${F}/gene/symbol/${encodeURIComponent(e)}/taxon/${t}`,{signal:n})).reports??[]).flatMap(o=>o.gene?[o.gene]:[])}catch(r){if(r instanceof H&&(r.status===400||r.status===404))return[];throw r}}async function Ge(e,t,n){return(await de(L("esearch",{db:"gene",term:`${e}[Gene Name] AND ${t}[taxid]`,retmode:"json",retmax:"1"}),{signal:n})).esearchresult?.idlist?.[0]}async function Bt(e,t,n){let r=new Set,o=e.map(c=>c.trim()),a=c=>/^\d+$/.test(c);for(let c of o.filter(s=>!a(s))){let s=ke(c);if(!s||r.has(s))continue;r.add(s);let u=Fe(s,await ve(s,t,n))??await Ge(s,t,n);if(u)return{geneId:u,matched:s}}let i=o.find(a);return i?{geneId:i,matched:i}:void 0}async function Ve(e,{taxa:t,exclude:n,limit:r=Le,signal:o}={}){let a=await S(`${F}/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 le=150;async function ge(e,t){let n=new Map;for(let r=0;r<e.length;r+=le){let o=e.slice(r,r+le),a=await S(`${F}/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 fe(e){let t=new Map,n,r=[];for(let o of e.split(`
|
|
2
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 qe(e){return e.replace(/[^A-Za-z0-9]+/g,"_").replace(/^_+|_+$/g,"")}function Ue(e){let t=new Set;return e.map(n=>{let r=qe(n)||"row",o=r,a=1;for(;t.has(o);)a+=1,o=`${r}_${a}`;return t.add(o),o})}async function Ct(e,t){let n=(await ge([e],t)).get(e);if(!n)return;let r=fe(await B(_({db:"protein",id:n,rettype:"fasta",retmode:"text"}),{signal:t})).get(n);return r?{accession:n,sequence:r}:void 0}async function Tt({geneId:e,taxa:t,exclude:n,limit:r,onProgress:o,signal:a}){o("Finding orthologs across species...");let i=await Ve(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 ge(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,h]=ue({db:"protein",id:u.join(","),rettype:"fasta",retmode:"text"}),l=fe(await B(d,{...h,signal:a})),p=Ue(s.map(m=>m.commonName??m.scientificName)),w=s.map((m,b)=>{let g=c.get(m.geneId);return{taxId:m.taxId,label:p[b],scientificName:m.scientificName,commonName:m.commonName,geneId:m.geneId,protein:g,sequence:l.get(g)??""}}).filter(m=>m.sequence);if(w.length<2)throw new Error("Could not fetch protein sequences for the orthologs");return w}var V=(e,t)=>t.some(n=>e instanceof n),he,pe;function We(){return he||(he=[IDBIndex,IDBObjectStore,IDBCursor,IDBDatabase,IDBTransaction])}function ze(){return pe||(pe=["advance","continue","continuePrimaryKey"].map(e=>IDBCursor.prototype[e]))}var q=new WeakMap,v=new WeakMap,R=new WeakMap;function Xe(e){let t=new Promise((n,r)=>{let o=()=>{e.removeEventListener("success",a),e.removeEventListener("error",i)},a=()=>{n(y(e.result)),o()},i=()=>{r(e.error),o()};e.addEventListener("success",a),e.addEventListener("error",i)});return R.set(t,e),t}function Ke(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 U={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 y(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 ye(e){U=e(U)}function He(e){return ze().includes(e)?function(...t){return e.apply(W(this),t),y(this.request)}:function(...t){return y(e.apply(W(this),t))}}function Je(e){return typeof e=="function"?He(e):(e instanceof IDBTransaction&&Ke(e),V(e,We())?new Proxy(e,U):e)}function y(e){if(e instanceof IDBRequest)return Xe(e);if(v.has(e))return v.get(e);let t=Je(e);return Object.is(t,e)||(v.set(e,t),R.set(t,e)),t}var W=e=>R.get(e);function Se(e,t,{blocked:n,upgrade:r,blocking:o,terminated:a}={}){let i=indexedDB.open(e,t),c=y(i);return r&&i.addEventListener("upgradeneeded",s=>{r(y(i.result),s.oldVersion,s.newVersion,y(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 Qe=["get","getKey","getAll","getAllKeys","count"],Ze=["put","add","delete","clear"],G={};function be(e,t){if(!(e instanceof IDBDatabase&&!(t in e)&&typeof t=="string"))return;if(G[t])return G[t];let n=t.replace(/FromIndex$/,""),r=t!==n,o=Ze.includes(n);if(!(n in(r?IDBIndex:IDBObjectStore).prototype)||!(o||Qe.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 G[t]=a}ye(e=>({...e,get:(t,n,r)=>be(t,n)||e.get(t,n,r),has:(t,n)=>!!be(t,n)||e.has(t,n)}));var Ye=["advance","continue","continuePrimaryKey"],xe={},z=new WeakMap,De=new WeakMap,et={get(e,t){if(!Ye.includes(t))return e[t];let n=xe[t];return n||(n=xe[t]=function(...r){z.set(this,De.get(this)[t](...r))}),n}};async function*tt(...e){let t=this;if(t instanceof IDBCursor||(t=await t.openCursor(...e)),!t)return;t=t;let n=new Proxy(t,et);for(De.set(n,t),R.set(n,W(t));t;)yield n,t=await(z.get(n)||t.continue()),z.delete(n)}function we(e,t){return t===Symbol.asyncIterator&&V(e,[IDBIndex,IDBObjectStore,IDBCursor])||t==="iterate"&&V(e,[IDBIndex,IDBObjectStore])}ye(e=>({...e,get(t,n,r){return we(t,n)?tt:e.get(t,n,r)},has(t,n){return we(t,n)||e.has(t,n)}}));function $(e,t,n){let r,o=()=>{r=void 0};return()=>(r??=new Promise((a,i)=>{let c=!1;Se(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 C(e,t,n){try{return await t()}catch(r){return console.warn(`[msaview] ${e} failed, continuing without it:`,r),n}}var nt="jbrowse-msaview-blast-cache",f="blast-results",rt=2,Ie=50,X=$(nt,rt,(e,t)=>{t<2&&e.objectStoreNames.contains(f)&&e.deleteObjectStore(f),e.objectStoreNames.contains(f)||e.createObjectStore(f,{keyPath:"id"})});function ot({proteinSequence:e,blastDatabase:t,msaAlgorithm:n,searchProgram:r,transcriptId:o,maxHits:a}){let i=o?`:${o}`:"",c=a===void 0||a===Y?"":`:n${a}`;return r==="phmmer"?`phmmer:${t}${i}${c}:${e}`:`${t}:${n}${i}${c}:${e}`}function Rt({proteinSequence:e,blastDatabase:t,msaAlgorithm:n,searchProgram:r,maxHits:o,msa:a,tree:i,treeMetadata:c,rid:s,geneId:u,transcriptId:d,transcriptName:h,geneName:l}){return C("BLAST history write",async()=>{let p=await X(),w={id:ot({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:h,geneName:l};return await p.put(f,w),await st(p),w},void 0)}async function st(e){try{if(await e.count(f)<=Ie)return;let t=await e.getAll(f),n=t.toSorted((o,a)=>o.timestamp-a.timestamp).slice(0,t.length-Ie),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 $t(){return(await(await X()).getAll(f)).toSorted((n,r)=>r.timestamp-n.timestamp)}async function Ot(e){await(await X()).delete(f,e)}var it="jbrowse-msaview-taxonomy-cache",T="common-names",at=2,Ce=$(it,at,e=>{e.objectStoreNames.contains(T)&&e.deleteObjectStore(T),e.createObjectStore(T,{keyPath:"taxid"})});function ct(e){return C("taxonomy cache read",async()=>{let n=(await Ce()).transaction(T,"readonly"),r=await Promise.all(e.map(o=>n.store.get(o)));return await n.done,r},[])}function Be(e){return C("taxonomy cache write",async()=>{let n=(await Ce()).transaction(T,"readwrite");for(let r of e)await n.store.put(r);await n.done},void 0)}async function vt(e,t,n){let r=[...new Set(e)],o=new Map,a=[],i=await ct(r);for(let u=0;u<r.length;u++){let d=r[u],h=i[u];h?o.set(d,{sciname:h.sciname,commonName:h.commonName}):a.push(d)}if(a.length===0)return o;let c=100,s=[];for(let u=0;u<a.length;u+=c){let d=a.slice(u,u+c),h=d.join(",");try{let l=await B(_({db:"taxonomy",id:h,retmode:"xml"}),{signal:t}),p=new Map,w=/<Taxon>\s*<TaxId>(\d+)<\/TaxId>/g,m;for(;(m=w.exec(l))!==null;){let b=Number(m[1]),g=m.index,D=1,x=g+m[0].length;for(;D>0&&x<l.length;){let O=l.indexOf("<Taxon>",x),j=l.indexOf("</Taxon>",x);if(j===-1)break;O!==-1&&O<j?(D++,x=O+7):(D--,x=j+8)}let N=l.slice(g,x),I=p.get(b),P=N.includes("<LineageEx>"),E=I?.includes("<LineageEx>");(!I||P&&!E)&&p.set(b,N)}for(let b of d){let g=p.get(b);if(g){let D=/<GenbankCommonName>(.*?)<\/GenbankCommonName>/.exec(g),x=/<CommonName>(.*?)<\/CommonName>/.exec(g),N=/<ScientificName>(.*?)<\/ScientificName>/.exec(g),I=D?.[1]??x?.[1],P=I&&k(I),E=k(N?.[1]??"");o.set(b,{sciname:E,commonName:P}),s.push({taxid:b,sciname:E,commonName:P})}}}catch(l){if(Z(l))throw await Be(s),l;console.error("Failed to fetch taxonomy data:",l),n?.(l)}}return s.length>0&&await Be(s),o}export{ut as a,Ee as b,ee as c,mt as d,dt as e,Ae as f,_e as g,lt as h,gt as i,ft as j,ht as k,Re as l,xt as m,$ as n,C as o,Rt as p,$t as q,Ot as r,L as s,_ as t,B as u,de as v,k as w,Le as x,ke as y,Bt as z,Ue as A,Ct as B,Tt as C,vt as D};
|
|
3
|
-
//# sourceMappingURL=chunk-
|
|
3
|
+
//# sourceMappingURL=chunk-BAM67QHH.js.map
|