loom-browser 0.0.2 → 0.0.4
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/README.md +28 -3
- package/dist/loom-react.esm.js +13290 -0
- package/dist/loom-react.esm.min.js +2 -0
- package/dist/loom-react.esm.min.js.map +1 -0
- package/dist/loom.esm.js +193 -168
- package/dist/loom.esm.min.js +1 -1
- package/dist/loom.esm.min.js.map +1 -1
- package/dist/loom.js +192 -169
- package/dist/loom.min.js +1 -1
- package/dist/loom.min.js.map +1 -1
- package/dist/tsconfig.src.tsbuildinfo +1 -0
- package/dist/types/gtx/zstdWasm.d.ts +4 -1
- package/dist/types/gtx/zstdWasmInlined.d.ts +6 -0
- package/dist/types/headlessGenomeBrowser.d.ts +8 -1
- package/dist/types/index.d.ts +0 -1
- package/dist/types/react/GenomeBrowserContext.d.ts +6 -0
- package/dist/types/react/LoomBrowser.d.ts +86 -0
- package/dist/types/react/hooks/index.d.ts +3 -0
- package/dist/types/react/hooks/useBrowserEvent.d.ts +7 -0
- package/dist/types/react/hooks/useGenomeBrowser.d.ts +7 -0
- package/dist/types/react/hooks/useLocus.d.ts +11 -0
- package/dist/types/react/hooks/useTrackManager.d.ts +11 -0
- package/dist/types/react/index.d.ts +7 -0
- package/dist/types/react/tracks/BedTrack.d.ts +14 -0
- package/dist/types/react/tracks/GeneTrack.d.ts +14 -0
- package/dist/types/react/tracks/GtxTrack.d.ts +13 -0
- package/dist/types/react/tracks/InteractionTrack.d.ts +12 -0
- package/dist/types/react/tracks/RulerTrack.d.ts +6 -0
- package/dist/types/react/tracks/SequenceTrack.d.ts +6 -0
- package/dist/types/react/tracks/WigTrack.d.ts +12 -0
- package/dist/types/react/tracks/index.d.ts +14 -0
- package/dist/types/tracks/annotation/annotationTrackCanvas.d.ts +1 -0
- package/dist/types/tracks/baseTrackCanvas.d.ts +2 -0
- package/dist/types/tracks/interaction/interactionTrackCanvas.d.ts +1 -0
- package/dist/types/tracks/ruler/rulerTrackCanvas.d.ts +1 -0
- package/dist/types/tracks/sequence/sequenceTrackCanvas.d.ts +1 -0
- package/dist/types/tracks/wig/wigTrackCanvas.d.ts +1 -0
- package/dist/types/types.d.ts +2 -0
- package/dist/types/ui/components/LoomBrowserShell.d.ts +9 -1
- package/package.json +20 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loom-react.esm.min.js","sources":["../src/roi/roiSet.ts","../src/roi/roiRenderer.ts","../src/export/canvas2svg.ts","../src/canvasProvider.ts","../src/themes/renderTheme.ts","../src/events.ts","../src/locusUtils.ts","../src/dataLifecycle.ts","../src/genome/chromAlias.ts","../src/genome/chromSizes.ts","../src/data/cachedSequence.ts","../src/genome/genome.ts","../src/data/ucscSequence.ts","../src/tracks/baseTrackCanvas.ts","../src/tracks/dynseq/dynseqRenderer.ts","../src/tracks/wig/wigRenderer.ts","../src/tracks/wig/wigSummary.ts","../src/tracks/wig/wigTrackCanvas.ts","../src/tracks/annotation/annotationRenderer.ts","../src/tracks/annotation/annotationTrackCanvas.ts","../src/pack.ts","../src/tracks/ruler/rulerRenderer.ts","../src/tracks/ruler/rulerTrackCanvas.ts","../src/sequence/sequenceUtils.ts","../src/tracks/sequence/sequenceRenderer.ts","../src/tracks/sequence/sequenceTrackCanvas.ts","../src/io/binaryParser.ts","../src/bigwig/index.ts","../src/dataSources/bigWigDataSource.ts","../src/io/rangeReader.ts","../src/gtx/zstdWasmInlined.ts","../src/gtx/zstdWasm.ts","../src/gtx/gtxReader.ts","../src/gtx/fetchCoordinator.ts","../src/gtx/index.ts","../src/dataSources/gtxDataSource.ts","../src/decode/exonUtils.ts","../src/decode/ucsc.ts","../src/data/ucscApi.ts","../src/dataSources/geneDataSource.ts","../node_modules/tslib/tslib.es6.js","../src/intervalTree.ts","../src/featureCache.ts","../src/tabix/index.ts","../src/decode/bed.ts","../src/decode/gff.ts","../src/decode/bedpe.ts","../src/formats/featureParser.ts","../src/decode/interact.ts","../src/formats/formatDetection.ts","../src/dataSources/textFeatureSource.ts","../src/dataSources/sequenceDataSource.ts","../src/tracks/interaction/interactionRenderer.ts","../src/tracks/interaction/interactionTrackCanvas.ts","../src/trackRegistry.ts","../src/session.ts","../src/dataSources/dataSourceCacheKey.ts","../src/stateProjection.ts","../src/trackSelector.ts","../src/headlessGenomeBrowser.ts","../src/commandDispatcher.ts","../src/remoteProtocol.ts","../src/tracks/axis/axisRenderer.ts","../src/genomeBrowser.ts","../src/contextMenu.ts","../src/react/GenomeBrowserContext.ts","../src/react/LoomBrowser.tsx","../src/react/hooks/useGenomeBrowser.ts","../src/react/hooks/useBrowserEvent.ts","../src/react/hooks/useLocus.ts","../src/react/hooks/useTrackManager.ts","../src/react/tracks/RulerTrack.tsx","../src/react/tracks/WigTrack.tsx","../src/react/tracks/GeneTrack.tsx","../src/react/tracks/BedTrack.tsx","../src/react/tracks/SequenceTrack.tsx","../src/react/tracks/InteractionTrack.tsx","../src/react/tracks/GtxTrack.tsx","../src/ui/components/LoomContextMenu.ts","../src/ui/components/LoomPopup.ts","../src/ui/components/LoomInputDialog.ts"],"sourcesContent":["/**\n * ROISet — a named collection of Regions of Interest.\n *\n * Layer 1 (Data): pure data model, no DOM, no canvas.\n * Mirrors igv.js ROISet (js/roi/ROISet.ts) but with typed interfaces\n * and no feature source abstraction (features stored in-memory).\n */\n\nimport type {ROI, ROISetConfig} from '../types'\n\n/** Default fill color for loaded ROI sets — blue with low alpha. */\nexport const ROI_DEFAULT_COLOR = 'rgba(68, 134, 247, 0.15)'\n\n/** Default fill color for user-defined ROIs — green with low alpha. */\nexport const ROI_USER_DEFINED_COLOR = 'rgba(155, 185, 129, 0.2)'\n\nlet _idCounter = 0\n\n/** Generate a short unique ROI ID. */\nexport function generateROIId(): string {\n return `roi_${Date.now().toString(36)}_${(++_idCounter).toString(36)}`\n}\n\n/**\n * A named collection of ROI features with a default color.\n *\n * Supports add/remove/update operations and spatial filtering.\n * Serializable to ROISetConfig for session persistence.\n */\nexport class ROISet {\n readonly name: string\n readonly isUserDefined: boolean\n color: string\n private _features: ROI[] = []\n\n constructor(config: ROISetConfig) {\n this.name = config.name\n this.color = config.color ?? (config.isUserDefined ? ROI_USER_DEFINED_COLOR : ROI_DEFAULT_COLOR)\n this.isUserDefined = config.isUserDefined ?? false\n if (config.features) {\n this._features = config.features.map(f => ({...f}))\n }\n }\n\n /** All features in this set. */\n get features(): readonly ROI[] {\n return this._features\n }\n\n /** Add a feature to this set. Assigns an ID if missing. */\n addFeature(roi: ROI): ROI {\n const feature: ROI = {\n ...roi,\n id: roi.id || generateROIId(),\n color: roi.color ?? this.color,\n }\n this._features.push(feature)\n this._features.sort((a, b) => a.start - b.start)\n return feature\n }\n\n /** Remove a feature by ID. Returns the removed feature, or undefined. */\n removeFeature(id: string): ROI | undefined {\n const idx = this._features.findIndex(f => f.id === id)\n if (idx < 0) return undefined\n return this._features.splice(idx, 1)[0]\n }\n\n /** Update a feature by ID. Returns the updated feature, or undefined. */\n updateFeature(id: string, changes: Partial<Omit<ROI, 'id'>>): ROI | undefined {\n const feature = this._features.find(f => f.id === id)\n if (!feature) return undefined\n Object.assign(feature, changes)\n if ('start' in changes || 'end' in changes) {\n this._features.sort((a, b) => a.start - b.start)\n }\n return feature\n }\n\n /** Find a feature by ID. */\n findById(id: string): ROI | undefined {\n return this._features.find(f => f.id === id)\n }\n\n /** Get features overlapping a genomic region. */\n getFeatures(chr: string, start: number, end: number): ROI[] {\n return this._features.filter(f =>\n f.chr === chr && f.end > start && f.start < end,\n )\n }\n\n /** Serialize to a JSON-safe config. */\n toJSON(): ROISetConfig {\n return {\n name: this.name,\n color: this.color,\n isUserDefined: this.isUserDefined || undefined,\n features: this._features.map(f => ({...f})),\n }\n }\n}\n","/**\n * Pure stateless ROI overlay renderer — for SVG/PNG export.\n *\n * Layer 2: takes a CanvasRenderingContext2D, draws ROI overlays.\n * No DOM, no state. Used by HeadlessGenomeBrowser.toSVG().\n */\n\nimport type {ROI, RenderContext} from '../types'\n\nexport interface ROIRenderOptions {\n /** Total height to render overlays across (sum of all track heights). */\n totalHeight: number\n /** Height of the label chip at the top of each ROI. */\n headerHeight?: number\n /** Font for ROI labels. */\n font?: string\n /** Label text color. */\n labelColor?: string\n}\n\n/**\n * Render ROI overlays onto a canvas context.\n *\n * Draws semi-transparent filled rectangles spanning the full track height,\n * with a small label chip at the top showing the ROI name.\n */\nexport function renderROIOverlays(\n ctx: CanvasRenderingContext2D,\n rois: ROI[],\n rc: RenderContext,\n options: ROIRenderOptions,\n): void {\n const {totalHeight, headerHeight = 4, font = '9px sans-serif', labelColor = 'rgba(0,0,0,0.7)'} = options\n\n for (const roi of rois) {\n const x = Math.round((roi.start - rc.bpStart) / rc.bpPerPixel)\n const w = Math.max(3, Math.round((roi.end - roi.start) / rc.bpPerPixel))\n\n // Skip if entirely off-screen\n if (x + w < 0 || x > rc.pixelWidth) continue\n\n const color = roi.color ?? 'rgba(68, 134, 247, 0.15)'\n\n // Fill body\n ctx.fillStyle = color\n ctx.fillRect(x, 0, w, totalHeight)\n\n // Border lines (left and right edges, slightly more opaque)\n ctx.strokeStyle = color.replace(/[\\d.]+\\)$/, m => {\n const alpha = Math.min(1, parseFloat(m) * 3)\n return `${alpha})`\n })\n ctx.lineWidth = 1\n ctx.beginPath()\n ctx.moveTo(x + 0.5, 0)\n ctx.lineTo(x + 0.5, totalHeight)\n ctx.moveTo(x + w - 0.5, 0)\n ctx.lineTo(x + w - 0.5, totalHeight)\n ctx.stroke()\n\n // Header chip\n if (headerHeight > 0) {\n ctx.fillStyle = color.replace(/[\\d.]+\\)$/, m => {\n const alpha = Math.min(1, parseFloat(m) * 4)\n return `${alpha})`\n })\n ctx.fillRect(x, 0, w, headerHeight)\n }\n\n // Label (if wide enough and has a name)\n if (roi.name && w > 20) {\n ctx.font = font\n ctx.fillStyle = labelColor\n ctx.textBaseline = 'top'\n ctx.textAlign = 'left'\n const labelX = x + 3\n const labelY = headerHeight + 1\n ctx.fillText(roi.name, labelX, labelY, w - 6)\n }\n }\n}\n","/**\n * Canvas2SVG — A Canvas-to-SVG rendering context.\n *\n * Implements the CanvasRenderingContext2D interface but builds an SVG document\n * instead of rasterizing to pixels. Drop-in replacement for Canvas2D context\n * in our stateless renderers.\n *\n * Port of Canvas 2 SVG v1.0.19 (MIT license, Kerry Liu / Gliffy Inc. 2014)\n * from js/canvas2svg.ts with full TypeScript typing.\n *\n * Layer 1 utility — no DOM attachment, no track logic.\n */\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/** Configuration for creating a Canvas2SVG context. */\nexport interface C2SConfig {\n width?: number\n height?: number\n enableMirroring?: boolean\n ctx?: CanvasRenderingContext2D\n viewbox?: ViewBox\n backdropColor?: string\n}\n\ninterface ViewBox {\n x: number\n y: number\n width: number\n height: number\n}\n\ninterface StyleDef {\n svgAttr?: string\n canvas: string | number | number[] | null\n svg?: string | number | null\n apply?: string\n}\n\ninterface FontData {\n style: string\n size: string\n family: string\n weight: string\n decoration: string\n href: string | null\n}\n\ninterface Position {\n x: number\n y: number\n}\n\n/** Extra methods provided by Canvas2SVG beyond the standard CanvasRenderingContext2D API. */\nexport interface C2SVGExtensions {\n /** Flag indicating this is an SVG rendering context. */\n isSVG: boolean\n /** Create a clipped, translated group (used for per-track viewport rendering). */\n saveWithTranslationAndClipRect(id: string, tx: number, ty: number, width: number, height: number, clipYOffset: number): void\n /** Update the SVG document height and viewBox. */\n setHeight(height: number): void\n /** Serialize the SVG DOM tree to an XML string. */\n getSerializedSvg(fixNamedEntities: boolean): string\n /** Stroke an ellipse element (SVG native, not path-based). */\n strokeEllipse(cx: number, cy: number, rx: number, ry: number, rotation: number, startAngle: number, endAngle: number, isCCW?: boolean): void\n /** Fill an ellipse element (SVG native, not path-based). */\n fillEllipse(cx: number, cy: number, rx: number, ry: number, rotation: number, startAngle: number, endAngle: number, isCCW?: boolean): void\n}\n\n/** A Canvas2SVG context: implements CanvasRenderingContext2D plus SVG-specific extensions. */\nexport type C2SContext = CanvasRenderingContext2D & C2SVGExtensions\n\n// ─── Helper Functions ────────────────────────────────────────────────────────\n\nfunction format(str: string, args: Record<string, string | number>): string {\n let result = str\n for (const key of Object.keys(args)) {\n result = result.replace(new RegExp('\\\\{' + key + '\\\\}', 'gi'), String(args[key]))\n }\n return result\n}\n\nfunction randomString(holder: Record<string, string>): string {\n const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'\n let result: string\n do {\n result = ''\n for (let i = 0; i < 12; i++) {\n result += chars[Math.floor(Math.random() * chars.length)]\n }\n } while (holder[result])\n return result\n}\n\nfunction createNamedToNumberedLookup(items: string, radix: number = 10): Record<string, string> {\n const lookup: Record<string, string> = {}\n const parts = items.split(',')\n for (let i = 0; i < parts.length; i += 2) {\n const entity = '&' + parts[i + 1] + ';'\n const base10 = parseInt(parts[i], radix)\n lookup[entity] = '&#' + base10 + ';'\n }\n lookup['\\\\xa0'] = ' '\n return lookup\n}\n\nfunction getTextAnchor(textAlign: string): string {\n const mapping: Record<string, string> = {\n left: 'start', right: 'end', center: 'middle', start: 'start', end: 'end',\n }\n return mapping[textAlign] || mapping.start\n}\n\nfunction getDominantBaseline(textBaseline: string): string {\n const mapping: Record<string, string> = {\n alphabetic: 'alphabetic',\n hanging: 'hanging',\n top: 'text-before-edge',\n bottom: 'text-after-edge',\n middle: 'central',\n }\n return mapping[textBaseline] || mapping.alphabetic\n}\n\nfunction normalize(vector: [number, number]): [number, number] {\n const len = Math.sqrt(vector[0] * vector[0] + vector[1] * vector[1])\n return [vector[0] / len, vector[1] / len]\n}\n\nfunction intersectRect(\n rect1: { x: number; y: number; width: number; height: number },\n rect2: { x: number; y: number; width: number; height: number },\n): boolean {\n return (\n rect1.x < rect2.x + rect2.width &&\n rect1.x + rect1.width > rect2.x &&\n rect1.y < rect2.y + rect2.height &&\n rect1.y + rect1.height > rect2.y\n )\n}\n\n// ─── Named Entity Lookup ─────────────────────────────────────────────────────\n\nconst namedEntities = createNamedToNumberedLookup(\n '50,nbsp,51,iexcl,52,cent,53,pound,54,curren,55,yen,56,brvbar,57,sect,58,uml,59,copy,' +\n '5a,ordf,5b,laquo,5c,not,5d,shy,5e,reg,5f,macr,5g,deg,5h,plusmn,5i,sup2,5j,sup3,5k,acute,' +\n '5l,micro,5m,para,5n,middot,5o,cedil,5p,sup1,5q,ordm,5r,raquo,5s,frac14,5t,frac12,5u,frac34,' +\n '5v,iquest,60,Agrave,61,Aacute,62,Acirc,63,Atilde,64,Auml,65,Aring,66,AElig,67,Ccedil,' +\n '68,Egrave,69,Eacute,6a,Ecirc,6b,Euml,6c,Igrave,6d,Iacute,6e,Icirc,6f,Iuml,6g,ETH,6h,Ntilde,' +\n '6i,Ograve,6j,Oacute,6k,Ocirc,6l,Otilde,6m,Ouml,6n,times,6o,Oslash,6p,Ugrave,6q,Uacute,' +\n '6r,Ucirc,6s,Uuml,6t,Yacute,6u,THORN,6v,szlig,70,agrave,71,aacute,72,acirc,73,atilde,74,auml,' +\n '75,aring,76,aelig,77,ccedil,78,egrave,79,eacute,7a,ecirc,7b,euml,7c,igrave,7d,iacute,7e,icirc,' +\n '7f,iuml,7g,eth,7h,ntilde,7i,ograve,7j,oacute,7k,ocirc,7l,otilde,7m,ouml,7n,divide,7o,oslash,' +\n '7p,ugrave,7q,uacute,7r,ucirc,7s,uuml,7t,yacute,7u,thorn,7v,yuml,ci,fnof,sh,Alpha,si,Beta,' +\n 'sj,Gamma,sk,Delta,sl,Epsilon,sm,Zeta,sn,Eta,so,Theta,sp,Iota,sq,Kappa,sr,Lambda,ss,Mu,' +\n 'st,Nu,su,Xi,sv,Omicron,t0,Pi,t1,Rho,t3,Sigma,t4,Tau,t5,Upsilon,t6,Phi,t7,Chi,t8,Psi,' +\n 't9,Omega,th,alpha,ti,beta,tj,gamma,tk,delta,tl,epsilon,tm,zeta,tn,eta,to,theta,tp,iota,' +\n 'tq,kappa,tr,lambda,ts,mu,tt,nu,tu,xi,tv,omicron,u0,pi,u1,rho,u2,sigmaf,u3,sigma,u4,tau,' +\n 'u5,upsilon,u6,phi,u7,chi,u8,psi,u9,omega,uh,thetasym,ui,upsih,um,piv,812,bull,816,hellip,' +\n '81i,prime,81j,Prime,81u,oline,824,frasl,88o,weierp,88h,image,88s,real,892,trade,89l,alefsym,' +\n '8cg,larr,8ch,uarr,8ci,rarr,8cj,darr,8ck,harr,8dl,crarr,8eg,lArr,8eh,uArr,8ei,rArr,8ej,dArr,' +\n '8ek,hArr,8g0,forall,8g2,part,8g3,exist,8g5,empty,8g7,nabla,8g8,isin,8g9,notin,8gb,ni,8gf,prod,' +\n '8gh,sum,8gi,minus,8gn,lowast,8gq,radic,8gt,prop,8gu,infin,8h0,ang,8h7,and,8h8,or,8h9,cap,8ha,cup,' +\n '8hb,int,8hk,there4,8hs,sim,8i5,cong,8i8,asymp,8j0,ne,8j1,equiv,8j4,le,8j5,ge,8k2,sub,8k3,sup,8k4,' +\n 'nsub,8k6,sube,8k7,supe,8kl,oplus,8kn,otimes,8l5,perp,8m5,sdot,8o8,lceil,8o9,rceil,8oa,lfloor,8ob,' +\n 'rfloor,8p9,lang,8pa,rang,9ea,loz,9j0,spades,9j3,clubs,9j5,hearts,9j6,diams,ai,OElig,aj,oelig,b0,' +\n 'Scaron,b1,scaron,bo,Yuml,m6,circ,ms,tilde,802,ensp,803,emsp,809,thinsp,80c,zwnj,80d,zwj,80e,lrm,' +\n '80f,rlm,80j,ndash,80k,mdash,80o,lsquo,80p,rsquo,80q,sbquo,80s,ldquo,80t,rdquo,80u,bdquo,810,dagger,' +\n '811,Dagger,81g,permil,81p,lsaquo,81q,rsaquo,85c,euro', 32,\n)\n\n// ─── Style Definitions ───────────────────────────────────────────────────────\n\nconst STYLES: Record<string, StyleDef> = {\n strokeStyle: { svgAttr: 'stroke', canvas: '#000000', svg: 'none', apply: 'stroke' },\n fillStyle: { svgAttr: 'fill', canvas: '#000000', svg: null, apply: 'fill' },\n lineCap: { svgAttr: 'stroke-linecap', canvas: 'butt', svg: 'butt', apply: 'stroke' },\n lineJoin: { svgAttr: 'stroke-linejoin', canvas: 'miter', svg: 'miter', apply: 'stroke' },\n miterLimit: { svgAttr: 'stroke-miterlimit', canvas: 10, svg: 4, apply: 'stroke' },\n lineWidth: { svgAttr: 'stroke-width', canvas: 1, svg: 1, apply: 'stroke' },\n globalAlpha: { svgAttr: 'opacity', canvas: 1, svg: 1, apply: 'fill stroke' },\n font: { canvas: '10px sans-serif' },\n shadowColor: { canvas: '#000000' },\n shadowOffsetX: { canvas: 0 },\n shadowOffsetY: { canvas: 0 },\n shadowBlur: { canvas: 0 },\n textAlign: { canvas: 'start' },\n textBaseline: { canvas: 'alphabetic' },\n lineDash: { svgAttr: 'stroke-dasharray', canvas: null, svg: null, apply: 'stroke' },\n}\n\n// ─── SVG Gradient / Pattern ──────────────────────────────────────────────────\n\nclass SVGCanvasGradient {\n __root: SVGElement\n __ctx: C2S\n\n constructor(gradientNode: SVGElement, ctx: C2S) {\n this.__root = gradientNode\n this.__ctx = ctx\n }\n\n addColorStop(offset: number, color: string): void {\n const stop = this.__ctx.__createElement('stop')\n stop.setAttribute('offset', String(offset))\n if (color && color.indexOf('rgba') !== -1) {\n const regex = /rgba\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d?\\.?\\d*)\\s*\\)/gi\n const matches = regex.exec(color)\n if (matches) {\n stop.setAttribute('stop-color', format('rgb({r},{g},{b})', { r: matches[1], g: matches[2], b: matches[3] }))\n stop.setAttribute('stop-opacity', matches[4])\n }\n } else {\n stop.setAttribute('stop-color', color)\n }\n this.__root.appendChild(stop)\n }\n}\n\nclass SVGCanvasPattern {\n __root: SVGElement\n __ctx: C2S\n\n constructor(pattern: SVGElement, ctx: C2S) {\n this.__root = pattern\n this.__ctx = ctx\n }\n}\n\n// ─── Main Canvas2SVG Class ───────────────────────────────────────────────────\n\n/**\n * Canvas2SVG rendering context.\n *\n * Implements the subset of CanvasRenderingContext2D that our renderers use,\n * plus SVG-specific extensions (saveWithTranslationAndClipRect, setHeight,\n * getSerializedSvg, stroke/fillEllipse).\n *\n * Usage:\n * const ctx = new C2S({ width: 800, height: 600 })\n * // ... draw using standard Canvas2D API ...\n * const svgString = ctx.getSerializedSvg(true)\n */\nexport class C2S {\n // SVG flag\n readonly isSVG = true\n\n // Dimensions\n width: number\n height: number\n\n // Self-reference (matches canvas2svg convention: context.canvas === context)\n canvas: C2S\n\n // Config\n private config: C2SConfig\n private enableMirroring: boolean\n private viewbox: ViewBox | undefined\n\n // Underlying real canvas for measureText\n private __canvas: HTMLCanvasElement\n private __ctx: CanvasRenderingContext2D\n\n // SVG DOM\n private __document: Document\n __root: SVGElement\n private __defs: SVGElement\n private __rootGroup: SVGElement\n private __currentElement: SVGElement\n private __currentElementsToStyle: { element: SVGElement; children: SVGElement[] } | null = null\n\n // State stacks\n private __ids: Record<string, string> = {}\n private __stack: Array<Record<string, unknown>> = []\n private __groupStack: SVGElement[] = []\n\n // Path state\n private __currentDefaultPath = ''\n private __currentPosition: Position = { x: 0, y: 0 }\n\n // Style properties (set via __setDefaultStyles, accessed as this[key])\n strokeStyle: string | CanvasGradient | CanvasPattern = '#000000'\n fillStyle: string | CanvasGradient | CanvasPattern = '#000000'\n lineCap: CanvasLineCap = 'butt'\n lineJoin: CanvasLineJoin = 'miter'\n miterLimit = 10\n lineWidth = 1\n globalAlpha = 1\n font = '10px sans-serif'\n shadowColor = '#000000'\n shadowOffsetX = 0\n shadowOffsetY = 0\n shadowBlur = 0\n textAlign: CanvasTextAlign = 'start'\n textBaseline: CanvasTextBaseline = 'alphabetic'\n lineDash: string | null = null\n\n // Font extensions (not standard canvas, but used by canvas2svg)\n private __fontUnderline: string | undefined\n private __fontHref: string | undefined\n\n constructor(config: C2SConfig = {}) {\n this.config = config\n this.width = config.width ?? 500\n this.height = config.height ?? 500\n this.enableMirroring = config.enableMirroring ?? false\n this.canvas = this\n this.__document = document\n\n if (config.ctx) {\n this.__ctx = config.ctx\n this.__canvas = config.ctx.canvas as HTMLCanvasElement\n } else {\n this.__canvas = this.__document.createElement('canvas')\n this.__ctx = this.__canvas.getContext('2d')!\n }\n\n this.__setDefaultStyles()\n this.__stack = [this.__getStyleState()]\n this.__groupStack = []\n\n // Root SVG element\n this.__root = this.__createElement('svg')\n this.__root.setAttribute('width', String(this.width))\n this.__root.setAttribute('height', String(this.height))\n this.__root.setAttribute('overflow', 'visible')\n\n if (config.viewbox) {\n const vb = config.viewbox\n this.__root.setAttribute('viewBox', `${vb.x} ${vb.y} ${vb.width} ${vb.height}`)\n this.viewbox = config.viewbox\n }\n\n this.__ids = {}\n\n // Defs section\n this.__defs = this.__createElement('defs')\n this.__root.appendChild(this.__defs)\n\n // Backdrop\n const backdropRect = this.__createElement('rect', {\n id: 'svg_output_backdrop',\n width: '100%',\n height: '100%',\n fill: config.backdropColor || 'white',\n })\n this.__root.appendChild(backdropRect)\n\n // Root group\n this.__rootGroup = this.__createElement('g', { id: 'root-group' })\n this.__root.appendChild(this.__rootGroup)\n this.__currentElement = this.__rootGroup\n }\n\n // ─── Dimension Management ────────────────────────────────────────────\n\n setWidth(width: number): void {\n this.width = width\n this.__root.setAttribute('width', String(width))\n if (this.config.viewbox) {\n this.__root.setAttribute('viewBox', `${this.config.viewbox.x} ${this.config.viewbox.y} ${width} ${this.config.viewbox.height}`)\n }\n }\n\n setHeight(height: number): void {\n this.height = height\n this.__root.setAttribute('height', String(height))\n if (this.config.viewbox) {\n this.__root.setAttribute('viewBox', `${this.config.viewbox.x} ${this.config.viewbox.y} ${this.config.viewbox.width} ${height}`)\n }\n }\n\n // ─── SVG Element Creation ────────────────────────────────────────────\n\n __createElement(elementName: string, properties?: Record<string, string | number>, resetFill?: boolean): SVGElement {\n const element = this.__document.createElementNS('http://www.w3.org/2000/svg', elementName)\n if (resetFill) {\n element.setAttribute('fill', 'none')\n element.setAttribute('stroke', 'none')\n }\n if (properties) {\n for (const key of Object.keys(properties)) {\n element.setAttribute(key, String(properties[key]))\n }\n }\n return element\n }\n\n // ─── Style Management ────────────────────────────────────────────────\n\n private __setDefaultStyles(): void {\n for (const key of Object.keys(STYLES)) {\n (this as Record<string, unknown>)[key] = STYLES[key].canvas\n }\n }\n\n private __applyStyleState(styleState: Record<string, unknown>): void {\n for (const key of Object.keys(styleState)) {\n (this as Record<string, unknown>)[key] = styleState[key]\n }\n }\n\n private __getStyleState(): Record<string, unknown> {\n const state: Record<string, unknown> = {}\n for (const key of Object.keys(STYLES)) {\n state[key] = (this as Record<string, unknown>)[key]\n }\n return state\n }\n\n private __applyStyleToCurrentElement(type: string): void {\n let currentElement = this.__currentElement\n const currentStyleGroup = this.__currentElementsToStyle\n if (currentStyleGroup) {\n currentElement.setAttribute(type, '')\n currentElement = currentStyleGroup.element\n currentStyleGroup.children.forEach(node => node.setAttribute(type, ''))\n }\n\n for (const key of Object.keys(STYLES)) {\n const style = STYLES[key]\n const value = (this as Record<string, unknown>)[key]\n if (style.apply) {\n if (value instanceof SVGCanvasPattern) {\n if (value.__ctx) {\n while (value.__ctx.__defs.childNodes.length) {\n const child = value.__ctx.__defs.childNodes[0] as SVGElement\n const id = child.getAttribute('id')!\n this.__ids[id] = id\n this.__defs.appendChild(child)\n }\n }\n currentElement.setAttribute(style.apply, format('url(#{id})', { id: value.__root.getAttribute('id')! }))\n } else if (value instanceof SVGCanvasGradient) {\n currentElement.setAttribute(style.apply, format('url(#{id})', { id: value.__root.getAttribute('id')! }))\n } else if (style.apply.indexOf(type) !== -1 && style.svg !== value) {\n if ((style.svgAttr === 'stroke' || style.svgAttr === 'fill') && typeof value === 'string' && value.indexOf('rgba') !== -1) {\n const regex = /rgba\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d?\\.?\\d*)\\s*\\)/gi\n const matches = regex.exec(value)\n if (matches) {\n currentElement.setAttribute(style.svgAttr!, format('rgb({r},{g},{b})', { r: matches[1], g: matches[2], b: matches[3] }))\n let opacity = parseFloat(matches[4])\n if (this.globalAlpha != null) {\n opacity *= this.globalAlpha\n }\n currentElement.setAttribute(style.svgAttr + '-opacity', String(opacity))\n }\n } else {\n let attr = style.svgAttr!\n if (key === 'globalAlpha') {\n attr = type + '-' + style.svgAttr\n if (currentElement.getAttribute(attr)) {\n continue\n }\n }\n currentElement.setAttribute(attr, String(value))\n }\n }\n }\n }\n }\n\n // ─── Group / Node Traversal ──────────────────────────────────────────\n\n private __closestGroupOrSvg(node?: SVGElement): SVGElement {\n const n = node || this.__currentElement\n if (n.nodeName === 'g' || n.nodeName === 'svg') {\n return n\n }\n return this.__closestGroupOrSvg(n.parentNode as SVGElement)\n }\n\n // ─── Serialization ───────────────────────────────────────────────────\n\n getSerializedSvg(fixNamedEntities: boolean): string {\n let serialized = new XMLSerializer().serializeToString(this.__root)\n if (fixNamedEntities) {\n for (const key of Object.keys(namedEntities)) {\n const regexp = new RegExp(key, 'gi')\n if (regexp.test(serialized)) {\n serialized = serialized.replace(regexp, namedEntities[key])\n }\n }\n }\n return serialized\n }\n\n getSvg(): SVGElement {\n return this.__root\n }\n\n // ─── Save / Restore ──────────────────────────────────────────────────\n\n saveWithTranslationAndClipRect(id: string, tx: number, ty: number, width: number, height: number, clipYOffset: number): void {\n const clipId = `${id}_clip_rect`\n const clipPath = this.__createElement('clipPath', { id: clipId })\n this.__defs.appendChild(clipPath)\n clipPath.appendChild(this.__createElement('rect', {\n x: '0',\n y: String(clipYOffset),\n width: String(width),\n height: String(height),\n }))\n\n const group = this.__createElement('g')\n group.setAttribute('transform', format('translate({x},{y})', { x: tx, y: ty }))\n group.setAttribute('clip-path', format('url(#{id})', { id: clipId }))\n\n const parent = this.__closestGroupOrSvg()\n parent.appendChild(group)\n this.__groupStack.push(parent)\n this.__currentElement = group\n this.__stack.push(this.__getStyleState())\n }\n\n save(): void {\n const group = this.__createElement('g')\n const parent = this.__closestGroupOrSvg()\n this.__groupStack.push(parent)\n parent.appendChild(group)\n this.__currentElement = group\n this.__stack.push(this.__getStyleState())\n }\n\n restore(): void {\n this.__currentElement = this.__groupStack.pop()!\n this.__currentElementsToStyle = null\n if (!this.__currentElement) {\n // childNodes: [0]=defs, [1]=backdrop rect, [2]=rootGroup\n this.__currentElement = this.__root.childNodes[2] as SVGElement\n }\n const state = this.__stack.pop()\n if (state) this.__applyStyleState(state)\n }\n\n // ─── Transforms ──────────────────────────────────────────────────────\n\n private __addTransform(t: string): void {\n const parent = this.__closestGroupOrSvg()\n if (parent.childNodes.length > 0) {\n if (this.__currentElement.nodeName === 'path') {\n if (!this.__currentElementsToStyle) {\n this.__currentElementsToStyle = { element: parent, children: [] }\n }\n this.__currentElementsToStyle.children.push(this.__currentElement)\n this.__applyCurrentDefaultPath()\n }\n const group = this.__createElement('g')\n parent.appendChild(group)\n this.__currentElement = group\n }\n\n let transform = this.__currentElement.getAttribute('transform')\n if (transform) {\n transform += ' '\n } else {\n transform = ''\n }\n transform += t\n this.__currentElement.setAttribute('transform', transform)\n }\n\n scale(x: number, y?: number): void {\n if (y === undefined) y = x\n this.__addTransform(format('scale({x},{y})', { x, y }))\n }\n\n rotate(angle: number): void {\n const degrees = angle * 180 / Math.PI\n this.__addTransform(format('rotate({angle},{cx},{cy})', { angle: degrees, cx: 0, cy: 0 }))\n }\n\n translate(x: number, y: number): void {\n this.__addTransform(format('translate({x},{y})', { x, y }))\n }\n\n transform(a: number, b: number, c: number, d: number, e: number, f: number): void {\n this.__addTransform(format('matrix({a},{b},{c},{d},{e},{f})', { a, b, c, d, e, f }))\n }\n\n // ─── Path Operations ─────────────────────────────────────────────────\n\n beginPath(): void {\n this.__currentDefaultPath = ''\n this.__currentPosition = { x: 0, y: 0 }\n const path = this.__createElement('path', {}, true)\n const parent = this.__closestGroupOrSvg()\n parent.appendChild(path)\n this.__currentElement = path\n }\n\n private __applyCurrentDefaultPath(): void {\n if (this.__currentElement.nodeName === 'path') {\n this.__currentElement.setAttribute('d', this.__currentDefaultPath)\n }\n }\n\n private __addPathCommand(command: string): void {\n this.__currentDefaultPath += ' ' + command\n }\n\n moveTo(x: number, y: number): void {\n if (this.__currentElement.nodeName !== 'path') {\n this.beginPath()\n }\n this.__currentPosition = { x, y }\n this.__addPathCommand(format('M {x} {y}', { x, y }))\n }\n\n closePath(): void {\n if (this.__currentDefaultPath) {\n this.__addPathCommand('Z')\n }\n }\n\n lineTo(x: number, y: number): void {\n this.__currentPosition = { x, y }\n if (this.__currentDefaultPath && this.__currentDefaultPath.indexOf('M') > -1) {\n this.__addPathCommand(format('L {x} {y}', { x, y }))\n } else {\n this.__addPathCommand(format('M {x} {y}', { x, y }))\n }\n }\n\n bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number): void {\n this.__currentPosition = { x, y }\n this.__addPathCommand(format('C {cp1x} {cp1y} {cp2x} {cp2y} {x} {y}', { cp1x, cp1y, cp2x, cp2y, x, y }))\n }\n\n quadraticCurveTo(cpx: number, cpy: number, x: number, y: number): void {\n this.__currentPosition = { x, y }\n this.__addPathCommand(format('Q {cpx} {cpy} {x} {y}', { cpx, cpy, x, y }))\n }\n\n roundRect(x: number, y: number, w: number, h: number, radii?: number | number[]): void {\n // Normalize radii to [tl, tr, br, bl]\n let r: number[]\n if (radii == null) {\n r = [0, 0, 0, 0]\n } else if (typeof radii === 'number') {\n r = [radii, radii, radii, radii]\n } else if (radii.length === 1) {\n r = [radii[0], radii[0], radii[0], radii[0]]\n } else if (radii.length === 2) {\n r = [radii[0], radii[1], radii[0], radii[1]]\n } else if (radii.length === 3) {\n r = [radii[0], radii[1], radii[2], radii[1]]\n } else {\n r = [radii[0], radii[1], radii[2], radii[3]]\n }\n // Clamp radii so they don't exceed half the width/height\n const maxR = Math.min(Math.abs(w) / 2, Math.abs(h) / 2)\n for (let i = 0; i < 4; i++) r[i] = Math.min(r[i], maxR)\n\n this.moveTo(x + r[0], y)\n this.lineTo(x + w - r[1], y)\n if (r[1]) this.arcTo(x + w, y, x + w, y + r[1], r[1])\n this.lineTo(x + w, y + h - r[2])\n if (r[2]) this.arcTo(x + w, y + h, x + w - r[2], y + h, r[2])\n this.lineTo(x + r[3], y + h)\n if (r[3]) this.arcTo(x, y + h, x, y + h - r[3], r[3])\n this.lineTo(x, y + r[0])\n if (r[0]) this.arcTo(x, y, x + r[0], y, r[0])\n this.closePath()\n }\n\n arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): void {\n const x0 = this.__currentPosition?.x\n const y0 = this.__currentPosition?.y\n if (x0 === undefined || y0 === undefined) return\n if (radius < 0) throw new Error('IndexSizeError: The radius provided (' + radius + ') is negative.')\n\n if ((x0 === x1 && y0 === y1) || (x1 === x2 && y1 === y2) || radius === 0) {\n this.lineTo(x1, y1)\n return\n }\n\n const unitVecP1P0 = normalize([x0 - x1, y0 - y1])\n const unitVecP1P2 = normalize([x2 - x1, y2 - y1])\n if (unitVecP1P0[0] * unitVecP1P2[1] === unitVecP1P0[1] * unitVecP1P2[0]) {\n this.lineTo(x1, y1)\n return\n }\n\n const cos = unitVecP1P0[0] * unitVecP1P2[0] + unitVecP1P0[1] * unitVecP1P2[1]\n const theta = Math.acos(Math.abs(cos))\n const unitVecP1Origin = normalize([unitVecP1P0[0] + unitVecP1P2[0], unitVecP1P0[1] + unitVecP1P2[1]])\n const lenP1Origin = radius / Math.sin(theta / 2)\n const x = x1 + lenP1Origin * unitVecP1Origin[0]\n const y = y1 + lenP1Origin * unitVecP1Origin[1]\n\n const unitVecOriginStartTangent: [number, number] = [-unitVecP1P0[1], unitVecP1P0[0]]\n const unitVecOriginEndTangent: [number, number] = [unitVecP1P2[1], -unitVecP1P2[0]]\n const getAngle = (vector: [number, number]) => vector[1] >= 0 ? Math.acos(vector[0]) : -Math.acos(vector[0])\n\n const startAngle = getAngle(unitVecOriginStartTangent)\n const endAngle = getAngle(unitVecOriginEndTangent)\n\n this.lineTo(x + unitVecOriginStartTangent[0] * radius, y + unitVecOriginStartTangent[1] * radius)\n this.arc(x, y, radius, startAngle, endAngle)\n }\n\n // ─── Stroke / Fill ───────────────────────────────────────────────────\n\n stroke(): void {\n if (this.__currentElement.nodeName === 'path') {\n this.__currentElement.setAttribute('paint-order', 'fill stroke markers')\n }\n this.__applyCurrentDefaultPath()\n this.__applyStyleToCurrentElement('stroke')\n }\n\n fill(): void {\n if (this.__currentElement.nodeName === 'path') {\n this.__currentElement.setAttribute('paint-order', 'stroke fill markers')\n }\n this.__applyCurrentDefaultPath()\n this.__applyStyleToCurrentElement('fill')\n }\n\n rect(x: number, y: number, width: number, height: number): void {\n if (this.__currentElement.nodeName !== 'path') {\n this.beginPath()\n }\n this.moveTo(x, y)\n this.lineTo(x + width, y)\n this.lineTo(x + width, y + height)\n this.lineTo(x, y + height)\n this.lineTo(x, y)\n this.closePath()\n }\n\n fillRect(x: number, y: number, width: number, height: number): void {\n // Handle negative dimensions\n if (height < 0) { y += height; height = -height }\n if (width < 0) { x += width; width = -width }\n\n const r2 = { x, y, width, height }\n if (this.viewbox && !intersectRect(this.viewbox, r2)) {\n return\n }\n\n const rect = this.__createElement('rect', r2, true)\n const parent = this.__closestGroupOrSvg()\n parent.appendChild(rect)\n this.__currentElement = rect\n this.__applyStyleToCurrentElement('fill')\n }\n\n strokeRect(x: number, y: number, width: number, height: number): void {\n const rect = this.__createElement('rect', { x, y, width, height }, true)\n const parent = this.__closestGroupOrSvg()\n parent.appendChild(rect)\n this.__currentElement = rect\n this.__applyStyleToCurrentElement('stroke')\n }\n\n // ─── Ellipse ─────────────────────────────────────────────────────────\n\n strokeEllipse(cx: number, cy: number, rx: number, ry: number, _rotation: number, _startAngle: number, _endAngle: number, _isCCW?: boolean): void {\n this.__ellipse(cx, cy, rx, ry, 'stroke')\n }\n\n fillEllipse(cx: number, cy: number, rx: number, ry: number, _rotation: number, _startAngle: number, _endAngle: number, _isCCW?: boolean): void {\n this.__ellipse(cx, cy, rx, ry, 'fill')\n }\n\n private __ellipse(cx: number, cy: number, rx: number, ry: number, style: string): void {\n const element = this.__createElement('ellipse', { cx, cy, rx, ry }, true)\n const parent = this.__closestGroupOrSvg()\n parent.appendChild(element)\n this.__currentElement = element\n this.__applyStyleToCurrentElement(style)\n }\n\n // ─── Clear ───────────────────────────────────────────────────────────\n\n private __clearCanvas(): void {\n const current = this.__closestGroupOrSvg()\n const transform = current.getAttribute('transform')\n const rootGroup = this.__root.childNodes[2] as SVGElement // index 2: defs=0, backdrop=1, rootGroup=2\n const childNodes = rootGroup.childNodes\n for (let i = childNodes.length - 1; i >= 0; i--) {\n if (childNodes[i]) rootGroup.removeChild(childNodes[i])\n }\n this.__currentElement = rootGroup\n this.__groupStack = []\n if (transform) this.__addTransform(transform)\n }\n\n clearRect(x: number, y: number, width: number, height: number): void {\n if (x === 0 && y === 0 && width === this.width && height === this.height) {\n this.__clearCanvas()\n return\n }\n const parent = this.__closestGroupOrSvg()\n const rect = this.__createElement('rect', { x, y, width, height, fill: '#FFFFFF' }, true)\n parent.appendChild(rect)\n }\n\n // ─── Gradients ───────────────────────────────────────────────────────\n\n createLinearGradient(x1: number, y1: number, x2: number, y2: number): SVGCanvasGradient {\n const grad = this.__createElement('linearGradient', {\n id: randomString(this.__ids),\n x1: x1 + 'px',\n x2: x2 + 'px',\n y1: y1 + 'px',\n y2: y2 + 'px',\n gradientUnits: 'userSpaceOnUse',\n })\n this.__defs.appendChild(grad)\n return new SVGCanvasGradient(grad, this)\n }\n\n createRadialGradient(x0: number, y0: number, r0: number, x1: number, y1: number, r1: number): SVGCanvasGradient {\n void r0 // Not used by SVG radial gradient (SVG only has one focus point)\n const grad = this.__createElement('radialGradient', {\n id: randomString(this.__ids),\n cx: x1 + 'px',\n cy: y1 + 'px',\n r: r1 + 'px',\n fx: x0 + 'px',\n fy: y0 + 'px',\n gradientUnits: 'userSpaceOnUse',\n })\n this.__defs.appendChild(grad)\n return new SVGCanvasGradient(grad, this)\n }\n\n // ─── Text ────────────────────────────────────────────────────────────\n\n private __parseFont(): FontData {\n const regex = /^\\s*(?=(?:(?:[-a-z]+\\s*){0,2}(italic|oblique))?)(?=(?:(?:[-a-z]+\\s*){0,2}(small-caps))?)(?=(?:(?:[-a-z]+\\s*){0,2}(bold(?:er)?|lighter|[1-9]00))?)(?:(?:normal|\\1|\\2|\\3)\\s*){0,3}((?:xx?-)?(?:small|large)|medium|smaller|larger|[.\\d]+(?:%|in|[cem]m|ex|p[ctx]))(?:\\s*\\/\\s*(normal|[.\\d]+(?:%|in|[cem]m|ex|p[ctx])))?\\s*([-,'\"\\sa-z0-9]+?)\\s*$/i\n const fontPart = regex.exec(this.font)\n const data: FontData = {\n style: fontPart?.[1] || 'normal',\n size: fontPart?.[4] || '10px',\n family: fontPart?.[6] || 'sans-serif',\n weight: fontPart?.[3] || 'normal',\n decoration: fontPart?.[2] || 'normal',\n href: null,\n }\n if (this.__fontUnderline === 'underline') {\n data.decoration = 'underline'\n }\n if (this.__fontHref) {\n data.href = this.__fontHref\n }\n return data\n }\n\n private __wrapTextLink(font: FontData, element: SVGElement): SVGElement {\n if (font.href) {\n const a = this.__createElement('a')\n a.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', font.href)\n a.appendChild(element)\n return a\n }\n return element\n }\n\n private __applyText(text: string, x: number, y: number, action: string): void {\n const font = this.__parseFont()\n const parent = this.__closestGroupOrSvg()\n const textElement = this.__createElement('text', {\n 'font-family': font.family,\n 'font-size': font.size,\n 'font-style': font.style,\n 'font-weight': font.weight,\n 'text-decoration': font.decoration,\n x,\n y,\n 'text-anchor': getTextAnchor(this.textAlign as string),\n 'dominant-baseline': getDominantBaseline(this.textBaseline as string),\n }, true)\n\n textElement.appendChild(this.__document.createTextNode(text))\n this.__currentElement = textElement\n this.__applyStyleToCurrentElement(action)\n parent.appendChild(this.__wrapTextLink(font, textElement))\n }\n\n fillText(text: string, x: number, y: number): void {\n this.__applyText(text, x, y, 'fill')\n }\n\n strokeText(text: string, x: number, y: number): void {\n this.__applyText(text, x, y, 'stroke')\n }\n\n measureText(text: string): TextMetrics {\n this.__ctx.font = this.font\n return this.__ctx.measureText(text)\n }\n\n // ─── Arc ─────────────────────────────────────────────────────────────\n\n arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, counterClockwise?: boolean): void {\n if (startAngle === endAngle) return\n\n startAngle = startAngle % (2 * Math.PI)\n endAngle = endAngle % (2 * Math.PI)\n if (startAngle === endAngle) {\n endAngle = ((endAngle + 2 * Math.PI) - 0.001 * (counterClockwise ? -1 : 1)) % (2 * Math.PI)\n }\n\n const endX = x + radius * Math.cos(endAngle)\n const endY = y + radius * Math.sin(endAngle)\n const startX = x + radius * Math.cos(startAngle)\n const startY = y + radius * Math.sin(startAngle)\n const sweepFlag = counterClockwise ? 0 : 1\n\n let diff = endAngle - startAngle\n if (diff < 0) diff += 2 * Math.PI\n\n const largeArcFlag = counterClockwise\n ? (diff > Math.PI ? 0 : 1)\n : (diff > Math.PI ? 1 : 0)\n\n this.lineTo(startX, startY)\n this.__addPathCommand(format('A {rx} {ry} {xAxisRotation} {largeArcFlag} {sweepFlag} {endX} {endY}', {\n rx: radius,\n ry: radius,\n xAxisRotation: 0,\n largeArcFlag,\n sweepFlag,\n endX,\n endY,\n }))\n this.__currentPosition = { x: endX, y: endY }\n }\n\n // ─── Clip ────────────────────────────────────────────────────────────\n\n clip(): void {\n const group = this.__closestGroupOrSvg()\n const clipPath = this.__createElement('clipPath')\n const id = randomString(this.__ids)\n const newGroup = this.__createElement('g')\n\n this.__applyCurrentDefaultPath()\n group.removeChild(this.__currentElement)\n clipPath.setAttribute('id', id)\n clipPath.appendChild(this.__currentElement)\n this.__defs.appendChild(clipPath)\n\n group.setAttribute('clip-path', format('url(#{id})', { id }))\n group.appendChild(newGroup)\n this.__currentElement = newGroup\n }\n\n // ─── Image ───────────────────────────────────────────────────────────\n\n drawImage(image: CanvasImageSource | C2S, ...args: number[]): void {\n let dx: number, dy: number, dw: number, dh: number\n let sx = 0, sy = 0, sw: number, sh: number\n\n if (args.length === 2) {\n dx = args[0]; dy = args[1]\n sw = (image as HTMLImageElement).width; sh = (image as HTMLImageElement).height\n dw = sw; dh = sh\n } else if (args.length === 4) {\n dx = args[0]; dy = args[1]; dw = args[2]; dh = args[3]\n sw = (image as HTMLImageElement).width; sh = (image as HTMLImageElement).height\n } else if (args.length === 8) {\n sx = args[0]; sy = args[1]; sw = args[2]; sh = args[3]\n dx = args[4]; dy = args[5]; dw = args[6]; dh = args[7]\n } else {\n throw new Error('Invalid number of arguments passed to drawImage: ' + (args.length + 1))\n }\n\n const parent = this.__closestGroupOrSvg()\n const translateDirective = `translate(${dx}, ${dy})`\n\n if (image instanceof C2S) {\n const svg = image.getSvg().cloneNode(true) as SVGElement\n if (svg.childNodes && svg.childNodes.length > 1) {\n const defs = svg.childNodes[0] as SVGElement\n while (defs.childNodes.length) {\n const child = defs.childNodes[0] as SVGElement\n const id = child.getAttribute('id')\n if (id) this.__ids[id] = id\n this.__defs.appendChild(child)\n }\n const group = svg.childNodes[1] as SVGElement\n if (group) {\n const originTransform = group.getAttribute('transform')\n group.setAttribute('transform', originTransform ? originTransform + ' ' + translateDirective : translateDirective)\n parent.appendChild(group)\n }\n }\n } else {\n const el = image as HTMLCanvasElement | HTMLImageElement\n const svgImage = this.__createElement('image')\n svgImage.setAttribute('width', String(dw))\n svgImage.setAttribute('height', String(dh))\n svgImage.setAttribute('preserveAspectRatio', 'none')\n\n let srcElement: HTMLCanvasElement | HTMLImageElement = el\n if (sx || sy || sw !== el.width || sh !== el.height) {\n const canvas = this.__document.createElement('canvas')\n canvas.width = dw\n canvas.height = dh\n const context = canvas.getContext('2d')!\n context.drawImage(el, sx, sy, sw, sh, 0, 0, dw, dh)\n srcElement = canvas\n }\n\n svgImage.setAttribute('transform', translateDirective)\n if ('toDataURL' in srcElement) {\n svgImage.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', (srcElement as HTMLCanvasElement).toDataURL())\n } else {\n svgImage.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', (srcElement as HTMLImageElement).getAttribute('src') || '')\n }\n parent.appendChild(svgImage)\n }\n }\n\n // ─── Pattern ─────────────────────────────────────────────────────────\n\n createPattern(image: HTMLCanvasElement | HTMLImageElement | C2S, _repetition: string | null): SVGCanvasPattern {\n const pattern = this.__createElement('pattern')\n const id = randomString(this.__ids)\n pattern.setAttribute('id', id)\n pattern.setAttribute('width', String((image as HTMLImageElement).width))\n pattern.setAttribute('height', String((image as HTMLImageElement).height))\n\n if (image instanceof C2S) {\n pattern.appendChild(image.__root.childNodes[1])\n this.__defs.appendChild(pattern)\n } else {\n const img = this.__createElement('image')\n img.setAttribute('width', String(image.width))\n img.setAttribute('height', String(image.height))\n if ('toDataURL' in image) {\n img.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', (image as HTMLCanvasElement).toDataURL())\n } else {\n img.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', (image as HTMLImageElement).getAttribute('src') || '')\n }\n pattern.appendChild(img)\n this.__defs.appendChild(pattern)\n }\n\n return new SVGCanvasPattern(pattern, this)\n }\n\n // ─── Line Dash ───────────────────────────────────────────────────────\n\n setLineDash(dashArray: number[]): void {\n if (dashArray && dashArray.length > 0) {\n this.lineDash = dashArray.join(',')\n } else {\n this.lineDash = null\n }\n }\n\n getLineDash(): number[] {\n if (this.lineDash) {\n return this.lineDash.split(',').map(Number)\n }\n return []\n }\n\n // ─── Stubs (not implementable in SVG) ────────────────────────────────\n\n drawFocusIfNeeded(): void { /* not supported */ }\n createImageData(): ImageData { return new ImageData(1, 1) }\n getImageData(): ImageData { return new ImageData(1, 1) }\n putImageData(): void { /* not supported */ }\n setTransform(): void { /* not supported */ }\n\n // globalCompositeOperation is a property in Canvas2D, keep as writable property\n globalCompositeOperation: GlobalCompositeOperation = 'source-over'\n}\n","/**\n * CanvasProvider — environment abstraction for canvas creation and DPR.\n *\n * Decouples track rendering from browser globals (document, window).\n * DOMCanvasProvider is the default for browser environments.\n * Future: NodeCanvasProvider (wrapping node-canvas) for server-side rendering,\n * MockCanvasProvider for tests.\n *\n * Reference: ai_docs/modernization/headless-v2.md (Phase 1)\n */\n\n/** A canvas and its 2D rendering context, returned by CanvasProvider.createCanvas(). */\nexport interface CanvasAndContext {\n canvas: HTMLCanvasElement\n ctx: CanvasRenderingContext2D\n}\n\n/**\n * Abstraction over canvas creation and device pixel ratio.\n *\n * Implementations:\n * - DOMCanvasProvider — browser (default)\n * - Future: NodeCanvasProvider — server-side (wraps node-canvas)\n * - Future: MockCanvasProvider — tests\n */\nexport interface CanvasProvider {\n /** Create a canvas element with the given logical (CSS) dimensions. */\n createCanvas(width: number, height: number): CanvasAndContext\n /** Device pixel ratio for sharp rendering on high-DPI displays. */\n readonly devicePixelRatio: number\n}\n\n/** Browser-based CanvasProvider using DOM APIs. */\nexport class DOMCanvasProvider implements CanvasProvider {\n createCanvas(width: number, height: number): CanvasAndContext {\n const canvas = document.createElement('canvas')\n canvas.width = width\n canvas.height = height\n const ctx = canvas.getContext('2d')!\n return {canvas, ctx}\n }\n\n get devicePixelRatio(): number {\n return typeof window !== 'undefined' ? (window.devicePixelRatio || 1) : 1\n }\n}\n\n/** Default CanvasProvider for browser environments. */\nexport const defaultCanvasProvider: CanvasProvider = new DOMCanvasProvider()\n","/**\n * Unified RenderTheme system — shadcn-style palette-driven theming.\n *\n * Users define a global palette (primary, secondary, background, foreground, etc.)\n * and each track type knows how to derive its specific config defaults from that\n * palette. Everything is overridable at three levels:\n *\n * 1. Palette-derived defaults (annotation.color = palette.primary)\n * 2. Per-track-type overrides (theme.annotation.borderRadius = 3)\n * 3. Per-track instance overrides (options.config.color = 'red')\n *\n * Renderers never see RenderTheme directly — they still consume AnnotationRenderConfig,\n * WigRenderConfig, etc. The theme system produces those configs.\n */\n\nimport type {AnnotationRenderConfig, WigRenderConfig, RulerRenderConfig, SequenceRenderConfig, InteractionRenderConfig} from '../types'\n\n// ─── Theme types ─────────────────────────────────────────────────────────────\n\n/** Global color palette — the primary customization surface. */\nexport interface ThemePalette {\n /** Main track color (CDS exons, wig bars, signal fill). */\n primary: string\n /** Alternate strand, negative values. */\n secondary: string\n /** Highlights, selections, active states. */\n accent: string\n /** Track canvas background. */\n background: string\n /** Text, labels, tick marks. */\n foreground: string\n /** Subtle elements: baselines, introns, borders. */\n muted: string\n}\n\n/**\n * Unified render theme. Defines a global palette, typography, and nucleotide\n * colors. Each track type derives its config defaults from the palette, with\n * optional per-track-type overrides.\n */\nexport interface RenderTheme {\n palette: ThemePalette\n /** CSS font-family string. Default: 'sans-serif'. */\n fontFamily: string\n /** Base font size in pixels. Default: 10. */\n fontSize: number\n /** Nucleotide color mapping (A, C, G, T, N). */\n nucleotideColors: Record<string, string>\n\n // Per-track-type style overrides (applied after palette-derived defaults)\n annotation?: Partial<AnnotationRenderConfig>\n wig?: Partial<WigRenderConfig>\n ruler?: Partial<RulerRenderConfig>\n sequence?: Partial<SequenceRenderConfig>\n interaction?: Partial<InteractionRenderConfig>\n}\n\n// ─── Default theme (classic igv.js look) ─────────────────────────────────────\n\n/** Returns the default render theme matching classic igv.js appearance. */\nexport function defaultRenderTheme(): RenderTheme {\n return {\n palette: {\n primary: 'rgb(0,0,150)',\n secondary: 'rgb(0,0,150)',\n accent: '#4A90D9',\n background: '#ffffff',\n foreground: '#333333',\n muted: 'rgb(150, 150, 150)',\n },\n fontFamily: 'sans-serif',\n fontSize: 10,\n nucleotideColors: {\n A: '#00C000',\n C: '#0000FF',\n G: '#FFB300',\n T: '#FF0000',\n N: '#808080',\n },\n }\n}\n\n// ─── Theme resolution ────────────────────────────────────────────────────────\n\n/**\n * Deep-merge a partial theme into the defaults.\n * If no overrides provided, returns the default theme.\n */\nexport function resolveTheme(overrides?: Partial<RenderTheme>): RenderTheme {\n const base = defaultRenderTheme()\n if (!overrides) return base\n return {\n palette: {...base.palette, ...overrides.palette},\n fontFamily: overrides.fontFamily ?? base.fontFamily,\n fontSize: overrides.fontSize ?? base.fontSize,\n nucleotideColors: {...base.nucleotideColors, ...overrides.nucleotideColors},\n annotation: overrides.annotation,\n wig: overrides.wig,\n ruler: overrides.ruler,\n sequence: overrides.sequence,\n interaction: overrides.interaction,\n }\n}\n\n// ─── Per-track-type config resolution ────────────────────────────────────────\n\n/**\n * Resolve a full AnnotationRenderConfig from a theme + optional per-track overrides.\n *\n * Resolution: palette-derived defaults → theme.annotation overrides → per-track overrides.\n */\nexport function resolveAnnotationConfig(\n theme: RenderTheme,\n overrides?: Partial<AnnotationRenderConfig>,\n): AnnotationRenderConfig {\n const base: AnnotationRenderConfig = {\n displayMode: 'EXPANDED',\n featureHeight: 14,\n margin: 10,\n expandedRowHeight: 30,\n squishedRowHeight: 15,\n arrowSpacing: 30,\n color: theme.palette.primary,\n altColor: theme.palette.secondary,\n labelField: 'name',\n font: `bold ${theme.fontSize}px ${theme.fontFamily}`,\n drawLabels: true,\n intronColor: theme.palette.muted,\n labelColor: theme.palette.foreground,\n }\n const withTheme = theme.annotation ? {...base, ...theme.annotation} : base\n return overrides ? {...withTheme, ...overrides} : withTheme\n}\n\n/**\n * Resolve a full WigRenderConfig from a theme + optional per-track overrides.\n *\n * Resolution: palette-derived defaults → theme.wig overrides → per-track overrides.\n */\nexport function resolveWigConfig(\n theme: RenderTheme,\n overrides?: Partial<WigRenderConfig>,\n): WigRenderConfig {\n const base: WigRenderConfig = {\n height: 50,\n graphType: 'bar',\n windowFunction: 'mean',\n dataRange: {min: 0, max: 100},\n autoscale: true,\n color: theme.palette.primary,\n altColor: theme.palette.secondary,\n flipAxis: false,\n logScale: false,\n baselineColor: theme.palette.muted,\n overflowColor: 'rgb(255, 32, 255)',\n pointSize: 3,\n background: theme.palette.background,\n nucleotideColors: theme.nucleotideColors,\n showDataRange: true,\n labelColor: theme.palette.foreground,\n labelFont: `bold ${Math.max(9, theme.fontSize - 1)}px ${theme.fontFamily}`,\n }\n const withTheme = theme.wig ? {...base, ...theme.wig} : base\n return overrides ? {...withTheme, ...overrides} : withTheme\n}\n\n/**\n * Resolve a full RulerRenderConfig from a theme + optional per-track overrides.\n *\n * Resolution: palette-derived defaults → theme.ruler overrides → per-track overrides.\n */\nexport function resolveRulerConfig(\n theme: RenderTheme,\n overrides?: Partial<RulerRenderConfig>,\n): RulerRenderConfig {\n const base: RulerRenderConfig = {\n height: 40,\n font: `bold ${theme.fontSize}px ${theme.fontFamily}`,\n tickColor: theme.palette.muted,\n labelColor: theme.palette.foreground,\n baselineColor: theme.palette.muted,\n background: theme.palette.background,\n }\n const withTheme = theme.ruler ? {...base, ...theme.ruler} : base\n return overrides ? {...withTheme, ...overrides} : withTheme\n}\n\n/**\n * Resolve a full SequenceRenderConfig from a theme + optional per-track overrides.\n *\n * Resolution: palette-derived defaults → theme.sequence overrides → per-track overrides.\n */\nexport function resolveSequenceConfig(\n theme: RenderTheme,\n overrides?: Partial<SequenceRenderConfig>,\n): SequenceRenderConfig {\n const base: SequenceRenderConfig = {\n sequenceType: 'dna',\n reversed: false,\n frameTranslate: false,\n background: theme.palette.background,\n nucleotideColors: {...theme.nucleotideColors},\n nonDnaColor: 'rgb(0, 0, 150)',\n defaultHeight: 25,\n translatedHeight: 115,\n sequenceHeight: 15,\n frameHeight: 25,\n frameBorder: 5,\n frameColor1: 'rgb(160,160,160)',\n frameColor2: 'rgb(224,224,224)',\n stopCodonColor: 'rgb(255, 0, 0)',\n startCodonColor: 'rgb(0, 153, 0)',\n useFillText: false,\n frameLabelColor: '#000000',\n frameFont: `bold ${theme.fontSize}px ${theme.fontFamily}`,\n codonBorderRadius: 0,\n }\n const withTheme = theme.sequence ? {...base, ...theme.sequence} : base\n return overrides ? {...withTheme, ...overrides} : withTheme\n}\n\n/**\n * Resolve a full InteractionRenderConfig from a theme + optional per-track overrides.\n *\n * Resolution: palette-derived defaults → theme.interaction overrides → per-track overrides.\n */\nexport function resolveInteractionConfig(\n theme: RenderTheme,\n overrides?: Partial<InteractionRenderConfig>,\n): InteractionRenderConfig {\n const base: InteractionRenderConfig = {\n height: 250,\n arcOrientation: 'UP',\n displayMode: 'nested',\n showBlocks: true,\n blockHeight: 3,\n thickness: 1,\n color: 'rgb(180,25,137)',\n alpha: 0.02,\n logScale: true,\n background: theme.palette.background,\n font: `${Math.max(8, theme.fontSize - 2)}px ${theme.fontFamily}`,\n useScore: false,\n }\n const withTheme = theme.interaction ? {...base, ...theme.interaction} : base\n return overrides ? {...withTheme, ...overrides} : withTheme\n}\n","/**\n * Lightweight typed event emitter.\n *\n * Usage:\n * type Events = { locuschange: { locus: Locus }; zoom: { factor: number } }\n * const emitter = new EventEmitter<Events>()\n * const unsub = emitter.on('locuschange', data => console.log(data.locus))\n * emitter.emit('locuschange', { locus: { chr: 'chr1', start: 0, end: 1000 } })\n * unsub()\n */\n\ntype Handler<T> = (data: T) => void\n\nexport class EventEmitter<EventMap extends object> {\n private listeners = new Map<keyof EventMap, Set<Handler<never>>>()\n\n /** Subscribe to an event. Returns an unsubscribe function. */\n on<K extends keyof EventMap>(event: K, handler: Handler<EventMap[K]>): () => void {\n let set = this.listeners.get(event)\n if (!set) {\n set = new Set()\n this.listeners.set(event, set)\n }\n set.add(handler as Handler<never>)\n return () => { set!.delete(handler as Handler<never>) }\n }\n\n /** Unsubscribe a specific handler, or all handlers for an event. */\n off<K extends keyof EventMap>(event: K, handler?: Handler<EventMap[K]>): void {\n if (!handler) {\n this.listeners.delete(event)\n } else {\n this.listeners.get(event)?.delete(handler as Handler<never>)\n }\n }\n\n /** Emit an event to all subscribers. */\n emit<K extends keyof EventMap>(event: K, data: EventMap[K]): void {\n const set = this.listeners.get(event)\n if (set) {\n for (const handler of set) {\n (handler as Handler<EventMap[K]>)(data)\n }\n }\n }\n\n /** Remove all listeners for all events. */\n removeAllListeners(): void {\n this.listeners.clear()\n }\n}\n","/**\n * Locus parsing, formatting, and clamping utilities.\n */\n\nimport type {Locus} from './types'\nimport type {ChromSizes} from './genome/chromSizes'\nimport type {CumulativeOffsets} from './genome/chromSizes'\n\n/** Check if a locus represents whole genome view. */\nexport function isWholeGenomeView(locus: Locus): boolean {\n return locus.chr.toLowerCase() === 'all'\n}\n\n/**\n * Parse a locus string like \"chr17:7,668,000-7,688,000\" into a Locus object.\n * Accepts with or without commas. Also recognizes \"all\" / \"*\" for whole genome view\n * (requires cumulative offsets to compute end position).\n * Returns null if parsing fails.\n */\nexport function parseLocus(str: string, cumOffsets?: CumulativeOffsets): Locus | null {\n const trimmed = str.trim()\n if (trimmed.toLowerCase() === 'all' || trimmed === '*') {\n if (!cumOffsets) return null\n return {chr: 'all', start: 0, end: cumOffsets.totalLength}\n }\n const cleaned = trimmed.replace(/,/g, '')\n const match = cleaned.match(/^(\\S+):(\\d+)-(\\d+)$/)\n if (!match) return null\n const chr = match[1]\n const start = parseInt(match[2], 10)\n const end = parseInt(match[3], 10)\n if (isNaN(start) || isNaN(end) || end <= start) return null\n return {chr, start, end}\n}\n\n/**\n * Format a Locus object as a human-readable string with thousands separators.\n * e.g., { chr: 'chr17', start: 7668000, end: 7688000 } → \"chr17:7,668,000-7,688,000\"\n */\nexport function formatLocus(locus: Locus): string {\n if (isWholeGenomeView(locus)) return 'All Chromosomes'\n return `${locus.chr}:${Math.round(locus.start).toLocaleString()}-${Math.round(locus.end).toLocaleString()}`\n}\n\n/**\n * Format a base pair length as a human-readable string.\n * e.g., 20000 → \"20 kb\", 2500000 → \"2.5 Mb\", 500 → \"500 bp\"\n */\nexport function formatBpLength(bp: number): string {\n bp = Math.abs(bp)\n if (bp >= 1e9) {\n const val = bp / 1e9\n return `${val % 1 === 0 ? val.toFixed(0) : val.toFixed(1)} Gb`\n }\n if (bp >= 1e6) {\n const val = bp / 1e6\n return `${val % 1 === 0 ? val.toFixed(0) : val.toFixed(1)} Mb`\n }\n if (bp >= 1e3) {\n const val = bp / 1e3\n return `${val % 1 === 0 ? val.toFixed(0) : val.toFixed(1)} kb`\n }\n return `${Math.round(bp)} bp`\n}\n\n/**\n * Clamp a locus to valid chromosome bounds.\n *\n * Enforces:\n * - start >= 0\n * - end <= chromLength (if known)\n * - span <= chromLength (if known)\n *\n * Maintains viewport span when possible by shifting rather than shrinking.\n * Matches the behavior of js/referenceFrame.ts clampStart().\n */\nexport function clampLocus(locus: Locus, chromSizes?: ChromSizes, cumOffsets?: CumulativeOffsets): Locus {\n if (isWholeGenomeView(locus) && cumOffsets) {\n return {chr: 'all', start: Math.max(0, locus.start), end: Math.min(cumOffsets.totalLength, locus.end)}\n }\n let {chr, start, end} = locus\n const chromLength = chromSizes?.[chr]\n\n // Clamp span to chromosome length\n if (chromLength != null && end - start > chromLength) {\n start = 0\n end = chromLength\n }\n\n // Clamp left edge — shift right to keep span\n if (start < 0) {\n const shift = -start\n start = 0\n end += shift\n }\n\n // Clamp right edge — shift left to keep span\n if (chromLength != null && end > chromLength) {\n const shift = end - chromLength\n end = chromLength\n start = Math.max(0, start - shift)\n }\n\n return {chr, start, end}\n}\n","/**\n * Data lifecycle utilities for GenomeBrowser.\n *\n * Pure functions for cache validation and viewport buffering.\n * Used internally by GenomeBrowser to decide when to re-fetch track data.\n */\n\nimport type {Locus, FeatureCacheEntry} from './types'\nimport {isWholeGenomeView} from './locusUtils'\n\n/** How many viewport-widths to buffer on each side (1 = 3x total). */\nconst BUFFER_SCREENS = 1\n\n/** Resolution tolerance — don't re-fetch for zoom changes within ±30%. */\nconst RESOLUTION_TOLERANCE = 0.3\n\n/**\n * Check if a cache entry covers a viewport at a compatible resolution.\n */\nexport function cacheCoversViewport<F>(\n cache: FeatureCacheEntry<F>,\n viewport: Locus,\n bpPerPixel: number,\n): boolean {\n if (cache.locus.chr !== viewport.chr) return false\n if (cache.locus.start > viewport.start || cache.locus.end < viewport.end) return false\n const ratio = bpPerPixel / cache.bpPerPixel\n return ratio >= (1 - RESOLUTION_TOLERANCE) && ratio <= (1 + RESOLUTION_TOLERANCE)\n}\n\n/**\n * Expand a locus by BUFFER_SCREENS on each side for pre-fetching.\n * Produces a 3x viewport region.\n */\nexport function bufferLocus(locus: Locus): Locus {\n // No buffering for whole genome view — data covers entire genome\n if (isWholeGenomeView(locus)) return locus\n\n const span = locus.end - locus.start\n const pad = Math.floor(span * BUFFER_SCREENS)\n return {\n chr: locus.chr,\n start: Math.max(0, Math.floor(locus.start - pad)),\n end: Math.ceil(locus.end + pad),\n }\n}\n","/**\n * Default chromosome alias resolution.\n *\n * Computes NCBI↔UCSC mappings (chr1↔1, chrM↔MT) and case aliases from\n * chromosome names. This covers the ~90% case where BigWig/BAM files use\n * a different naming convention than the genome.\n *\n * Port of js/genome/chromAliasDefaults.ts. In our architecture this is\n * Layer 1 (Data + Layout): pure data, no DOM.\n *\n * Extension points for file-based (ChromAliasFile) and BigBed-based\n * (ChromAliasBB) alias sources can be added later by implementing the\n * same interface and wiring into GenomeImpl.\n */\n\nimport type {ChromAliasRecord} from '../types'\n\n/**\n * Add case-insensitivity and chr-prefix aliases to an alias record.\n * Reusable by future ChromAliasFile/ChromAliasBB implementations.\n *\n * Mirrors igv.js ChromAliasDefaults.addCaseAliases (js/genome/chromAliasDefaults.ts).\n */\nexport function addCaseAliases(record: ChromAliasRecord): void {\n const chr = record.chr\n const upper = chr.toUpperCase()\n const lower = chr.toLowerCase()\n const cap = chr.charAt(0).toUpperCase() + chr.slice(1)\n\n if (chr !== upper) record['_uppercase'] = upper\n if (chr !== lower) record['_lowercase'] = lower\n if (chr !== cap) record['_cap'] = cap\n\n // Toggle chr prefix: \"chr1\" → \"1\", \"1\" → \"chr1\"\n record['_chrprefix_'] = chr.startsWith('chr') ? chr.substring(3) : 'chr' + chr\n}\n\n/**\n * Extract the user-friendly name from an NCBI accession.\n * Example: gi|125745044|ref|NC_002229.3| → NC_002229.3\n */\nfunction getNCBIName(name: string): string {\n const tokens = name.split('|').filter(t => t.length > 0)\n return tokens[tokens.length - 1]\n}\n\nfunction isHumanGenome(id: string): boolean {\n return id.startsWith('hg') || id.startsWith('GRCh') || id === '1kg_ref' || id === 'b37'\n}\n\nfunction isMouseGenome(id: string): boolean {\n return id.startsWith('mm') || id.startsWith('GRCm') || id.startsWith('rheMac')\n}\n\n/**\n * Default chromosome alias resolver.\n *\n * Builds a bidirectional alias cache from chromosome names at construction time.\n * All lookups are synchronous (no network). Covers:\n * - NCBI↔UCSC numeric mapping (chr1↔1, chrM↔MT)\n * - Human sex chromosomes (23↔chrX, 24↔chrY) for hg, GRCh, b37 genomes\n * - Mouse sex chromosomes (21↔chrX, 22↔chrY) for mm, GRCm, rheMac genomes\n * - Case aliases (uppercase, lowercase, capitalized, chr-prefix-flipped)\n * - NCBI gi| accession parsing\n *\n * Mirrors igv.js ChromAliasDefaults (js/genome/chromAliasDefaults.ts).\n */\nexport class ChromAliasDefaults {\n private cache: Map<string, ChromAliasRecord> = new Map()\n\n constructor(chromosomeNames: string[], genomeId?: string) {\n this.buildAliases(chromosomeNames, genomeId ?? '')\n }\n\n /** Resolve alias to canonical name. Returns undefined if not found. */\n getChromosomeName(alias: string): string | undefined {\n const record = this.cache.get(alias)\n return record?.chr\n }\n\n /** Get full alias record for a chromosome or alias. */\n getAliasRecord(alias: string): ChromAliasRecord | undefined {\n return this.cache.get(alias)\n }\n\n private buildAliases(chromosomeNames: string[], genomeId: string): void {\n const records: ChromAliasRecord[] = []\n\n for (const name of chromosomeNames) {\n if (this.cache.has(name)) continue\n\n const record: ChromAliasRecord = {chr: name}\n records.push(record)\n\n if (name.startsWith('gi|')) {\n // NCBI gi| accession\n const alias = getNCBIName(name)\n record['ncbi-gi-versioned'] = alias\n const dotIndex = alias.lastIndexOf('.')\n if (dotIndex > 0) {\n record['ncbi-gi'] = alias.substring(0, dotIndex)\n }\n } else {\n // Standard NCBI↔UCSC mappings\n if (name === 'chrM') {\n record['ncbi'] = 'MT'\n } else if (name === 'MT') {\n record['ucsc'] = 'chrM'\n } else if (name.toLowerCase().startsWith('chr') && Number.isInteger(Number(name.substring(3)))) {\n record['ncbi'] = name.substring(3)\n } else if (Number.isInteger(Number(name))) {\n record['ucsc'] = 'chr' + name\n }\n\n // Species-specific sex chromosome aliases\n if (isHumanGenome(genomeId)) {\n this.addHumanSexAliases(name, record)\n } else if (isMouseGenome(genomeId)) {\n this.addMouseSexAliases(name, record)\n }\n }\n }\n\n // Register all alias values in the cache (every alias → same shared record)\n for (const record of records) {\n addCaseAliases(record)\n for (const value of Object.values(record)) {\n this.cache.set(value, record)\n }\n }\n }\n\n private addHumanSexAliases(name: string, record: ChromAliasRecord): void {\n switch (name) {\n case '23':\n record['ucsc'] = 'chrX'\n record['assembly'] = 'X'\n break\n case '24':\n record['ucsc'] = 'chrY'\n record['assembly'] = 'Y'\n break\n case 'chrX':\n record['ncbi'] = '23'\n record['assembly'] = 'X'\n break\n case 'chrY':\n record['ncbi'] = '24'\n record['assembly'] = 'Y'\n break\n case 'X':\n record['ucsc'] = 'chrX'\n record['ncbi'] = '23'\n break\n case 'Y':\n record['ucsc'] = 'chrY'\n record['ncbi'] = '24'\n break\n }\n }\n\n private addMouseSexAliases(name: string, record: ChromAliasRecord): void {\n switch (name) {\n case '21':\n record['ucsc'] = 'chrX'\n record['assembly'] = 'X'\n break\n case '22':\n record['ucsc'] = 'chrY'\n record['assembly'] = 'Y'\n break\n case 'chrX':\n record['ncbi'] = '21'\n record['assembly'] = 'X'\n break\n case 'chrY':\n record['ncbi'] = '22'\n record['assembly'] = 'Y'\n break\n case 'X':\n record['ucsc'] = 'chrX'\n record['ncbi'] = '21'\n break\n case 'Y':\n record['ucsc'] = 'chrY'\n record['ncbi'] = '22'\n break\n }\n }\n}\n","/**\n * Chromosome size data and utilities.\n *\n * Provides a lightweight ChromSizes type (chr → bp length), a default\n * hg38 dataset, and genome coordinate system utilities for whole genome view.\n */\n\n/** Mapping of chromosome names to their lengths in base pairs. */\nexport type ChromSizes = Record<string, number>\n\n/**\n * Look up the length of a chromosome. Returns undefined if not found.\n */\nexport function getChromLength(chr: string, chromSizes?: ChromSizes): number | undefined {\n return chromSizes?.[chr]\n}\n\n// ─── Whole Genome View utilities ─────────────────────────────────────────────\n\n/** Precomputed genome-wide coordinate system for whole genome view. */\nexport interface CumulativeOffsets {\n /** Chromosome name → genome-wide start position. */\n offsets: Record<string, number>\n /** Total length of all main chromosomes. */\n totalLength: number\n /** Ordered chromosome names used in the WG view. */\n chromosomeNames: string[]\n}\n\nconst MAIN_CHROM_RE = /^chr(\\d+|X|Y|M)$/i\n\n/** Check if a chromosome name is a \"main\" chromosome (chr1-22, X, Y, M). */\nexport function isMainChromosome(name: string): boolean {\n return MAIN_CHROM_RE.test(name)\n}\n\n/**\n * Return ordered list of main chromosome names from chromSizes.\n * Order: chr1-22 (numeric), chrX, chrY, chrM.\n */\nexport function mainChromosomeNames(chromSizes: ChromSizes): string[] {\n const names = Object.keys(chromSizes).filter(isMainChromosome)\n return names.sort((a, b) => {\n const aNum = chromNumber(a)\n const bNum = chromNumber(b)\n return aNum - bNum\n })\n}\n\n/** Map chromosome suffix to sort key: 1-22, then X=23, Y=24, M=25. */\nfunction chromNumber(name: string): number {\n const suffix = name.replace(/^chr/i, '')\n if (suffix === 'X' || suffix === 'x') return 23\n if (suffix === 'Y' || suffix === 'y') return 24\n if (suffix === 'M' || suffix === 'm') return 25\n const n = parseInt(suffix, 10)\n return isNaN(n) ? 100 : n\n}\n\n/**\n * Compute cumulative genome-wide offsets for main chromosomes.\n * Used to map per-chromosome coordinates to a linear genome-wide space.\n */\nexport function computeCumulativeOffsets(chromSizes: ChromSizes): CumulativeOffsets {\n const chromosomeNames = mainChromosomeNames(chromSizes)\n const offsets: Record<string, number> = {}\n let offset = 0\n for (const name of chromosomeNames) {\n offsets[name] = Math.floor(offset)\n offset += chromSizes[name]\n }\n return {offsets, totalLength: Math.floor(offset), chromosomeNames}\n}\n\n/**\n * Convert a genome-wide coordinate back to chromosome-relative coordinates.\n * Returns the chromosome and position within it.\n */\nexport function genomeToChromCoord(\n genomePos: number,\n cumOffsets: CumulativeOffsets,\n): {chr: string; position: number} {\n for (let i = cumOffsets.chromosomeNames.length - 1; i >= 0; i--) {\n const chr = cumOffsets.chromosomeNames[i]\n const offset = cumOffsets.offsets[chr]\n if (genomePos >= offset) {\n return {chr, position: genomePos - offset}\n }\n }\n // Fallback: first chromosome\n const chr = cumOffsets.chromosomeNames[0]\n return {chr, position: Math.max(0, genomePos)}\n}\n\n/**\n * Parse a tab-separated chrom.sizes file into a ChromSizes record.\n * Format: one line per chromosome, `name\\tlength`, with optional comments (#).\n * Mirrors the UCSC chrom.sizes file format.\n */\nexport function parseChromSizes(text: string): ChromSizes {\n const sizes: ChromSizes = {}\n for (const line of text.split('\\n')) {\n const trimmed = line.trim()\n if (!trimmed || trimmed.startsWith('#')) continue\n const parts = trimmed.split('\\t')\n if (parts.length >= 2) {\n const name = parts[0]\n const length = parseInt(parts[1], 10)\n if (name && !isNaN(length) && length > 0) {\n sizes[name] = length\n }\n }\n }\n return sizes\n}\n\n/**\n * GRCh38/hg38 chromosome sizes.\n * Includes main chromosomes (chr1-22, X, Y, M) plus all contigs and alts.\n * Source: UCSC hg38.chrom.sizes\n */\nexport const hg38ChromSizes: ChromSizes = {\n // Main chromosomes\n chr1: 248956422,\n chr2: 242193529,\n chr3: 198295559,\n chr4: 190214555,\n chr5: 181538259,\n chr6: 170805979,\n chr7: 159345973,\n chr8: 145138636,\n chr9: 138394717,\n chr10: 133797422,\n chr11: 135086622,\n chr12: 133275309,\n chr13: 114364328,\n chr14: 107043718,\n chr15: 101991189,\n chr16: 90338345,\n chr17: 83257441,\n chr18: 80373285,\n chr19: 58617616,\n chr20: 64444167,\n chr21: 46709983,\n chr22: 50818468,\n chrX: 156040895,\n chrY: 57227415,\n chrM: 16569,\n // Random contigs\n chr11_KI270721v1_random: 100316,\n chr14_GL000009v2_random: 201709,\n chr14_GL000225v1_random: 211173,\n chr14_KI270722v1_random: 194050,\n chr14_GL000194v1_random: 191469,\n chr14_KI270723v1_random: 38115,\n chr14_KI270724v1_random: 39555,\n chr14_KI270725v1_random: 172810,\n chr14_KI270726v1_random: 43739,\n chr15_KI270727v1_random: 448248,\n chr16_KI270728v1_random: 1872759,\n chr17_GL000205v2_random: 185591,\n chr17_KI270729v1_random: 280839,\n chr17_KI270730v1_random: 112551,\n chr1_KI270706v1_random: 175055,\n chr1_KI270707v1_random: 32032,\n chr1_KI270708v1_random: 127682,\n chr1_KI270709v1_random: 66860,\n chr1_KI270710v1_random: 40176,\n chr1_KI270711v1_random: 42210,\n chr1_KI270712v1_random: 176043,\n chr1_KI270713v1_random: 40745,\n chr1_KI270714v1_random: 41717,\n chr22_KI270731v1_random: 150754,\n chr22_KI270732v1_random: 41543,\n chr22_KI270733v1_random: 179772,\n chr22_KI270734v1_random: 165050,\n chr22_KI270735v1_random: 42811,\n chr22_KI270736v1_random: 181920,\n chr22_KI270737v1_random: 103838,\n chr22_KI270738v1_random: 99375,\n chr22_KI270739v1_random: 73985,\n chr2_KI270715v1_random: 161471,\n chr2_KI270716v1_random: 153799,\n chr3_GL000221v1_random: 155397,\n chr4_GL000008v2_random: 209709,\n chr5_GL000208v1_random: 92689,\n chr9_KI270717v1_random: 40062,\n chr9_KI270718v1_random: 38054,\n chr9_KI270719v1_random: 176845,\n chr9_KI270720v1_random: 39050,\n // Alt contigs\n chr1_KI270762v1_alt: 354444,\n chr1_KI270766v1_alt: 256271,\n chr1_KI270760v1_alt: 109528,\n chr1_KI270765v1_alt: 185285,\n chr1_GL383518v1_alt: 182439,\n chr1_GL383519v1_alt: 110268,\n chr1_GL383520v2_alt: 366580,\n chr1_KI270764v1_alt: 50258,\n chr1_KI270763v1_alt: 911658,\n chr1_KI270759v1_alt: 425601,\n chr1_KI270761v1_alt: 165834,\n chr2_KI270770v1_alt: 136240,\n chr2_KI270773v1_alt: 70887,\n chr2_KI270774v1_alt: 223625,\n chr2_KI270769v1_alt: 120616,\n chr2_GL383521v1_alt: 143390,\n chr2_KI270772v1_alt: 133041,\n chr2_KI270775v1_alt: 138019,\n chr2_KI270771v1_alt: 110395,\n chr2_KI270768v1_alt: 110099,\n chr2_GL582966v2_alt: 96131,\n chr2_GL383522v1_alt: 123821,\n chr2_KI270776v1_alt: 174166,\n chr2_KI270767v1_alt: 161578,\n chr3_JH636055v2_alt: 173151,\n chr3_KI270783v1_alt: 109187,\n chr3_KI270780v1_alt: 224108,\n chr3_GL383526v1_alt: 180671,\n chr3_KI270777v1_alt: 173649,\n chr3_KI270778v1_alt: 248252,\n chr3_KI270781v1_alt: 113034,\n chr3_KI270779v1_alt: 205312,\n chr3_KI270782v1_alt: 162429,\n chr3_KI270784v1_alt: 184404,\n chr4_KI270790v1_alt: 220246,\n chr4_GL383528v1_alt: 376187,\n chr4_KI270787v1_alt: 111943,\n chr4_GL000257v2_alt: 586476,\n chr4_KI270788v1_alt: 158965,\n chr4_GL383527v1_alt: 164536,\n chr4_KI270785v1_alt: 119912,\n chr4_KI270789v1_alt: 205944,\n chr4_KI270786v1_alt: 244096,\n chr5_KI270793v1_alt: 126136,\n chr5_KI270792v1_alt: 179043,\n chr5_KI270791v1_alt: 195710,\n chr5_GL383532v1_alt: 82728,\n chr5_GL949742v1_alt: 226852,\n chr5_KI270794v1_alt: 164558,\n chr5_GL339449v2_alt: 1612928,\n chr5_GL383530v1_alt: 101241,\n chr5_KI270796v1_alt: 172708,\n chr5_GL383531v1_alt: 173459,\n chr5_KI270795v1_alt: 131892,\n chr6_GL000250v2_alt: 4672374,\n chr6_KI270800v1_alt: 175808,\n chr6_KI270799v1_alt: 152148,\n chr6_GL383533v1_alt: 124736,\n chr6_KI270801v1_alt: 870480,\n chr6_KI270802v1_alt: 75005,\n chr6_KB021644v2_alt: 185823,\n chr6_KI270797v1_alt: 197536,\n chr6_KI270798v1_alt: 271782,\n chr7_KI270804v1_alt: 157952,\n chr7_KI270809v1_alt: 209586,\n chr7_KI270806v1_alt: 158166,\n chr7_GL383534v2_alt: 119183,\n chr7_KI270803v1_alt: 1111570,\n chr7_KI270808v1_alt: 271455,\n chr7_KI270807v1_alt: 126434,\n chr7_KI270805v1_alt: 209988,\n chr8_KI270818v1_alt: 145606,\n chr8_KI270812v1_alt: 282736,\n chr8_KI270811v1_alt: 292436,\n chr8_KI270821v1_alt: 985506,\n chr8_KI270813v1_alt: 300230,\n chr8_KI270822v1_alt: 624492,\n chr8_KI270814v1_alt: 141812,\n chr8_KI270810v1_alt: 374415,\n chr8_KI270819v1_alt: 133535,\n chr8_KI270820v1_alt: 36640,\n chr8_KI270817v1_alt: 158983,\n chr8_KI270816v1_alt: 305841,\n chr8_KI270815v1_alt: 132244,\n chr9_GL383539v1_alt: 162988,\n chr9_GL383540v1_alt: 71551,\n chr9_GL383541v1_alt: 171286,\n chr9_GL383542v1_alt: 60032,\n chr9_KI270823v1_alt: 439082,\n chr10_GL383545v1_alt: 179254,\n chr10_KI270824v1_alt: 181496,\n chr10_GL383546v1_alt: 309802,\n chr10_KI270825v1_alt: 188315,\n chr11_KI270832v1_alt: 210133,\n chr11_KI270830v1_alt: 177092,\n chr11_KI270831v1_alt: 296895,\n chr11_KI270829v1_alt: 204059,\n chr11_GL383547v1_alt: 154407,\n chr11_JH159136v1_alt: 200998,\n chr11_JH159137v1_alt: 191409,\n chr11_KI270827v1_alt: 67707,\n chr11_KI270826v1_alt: 186169,\n chr12_GL877875v1_alt: 167313,\n chr12_GL877876v1_alt: 408271,\n chr12_KI270837v1_alt: 40090,\n chr12_GL383549v1_alt: 120804,\n chr12_KI270835v1_alt: 238139,\n chr12_GL383550v2_alt: 153178,\n chr12_GL383552v1_alt: 138655,\n chr12_GL383553v2_alt: 152874,\n chr12_KI270834v1_alt: 119498,\n chr12_GL383551v1_alt: 184319,\n chr12_KI270833v1_alt: 76061,\n chr12_KI270836v1_alt: 56134,\n chr13_KI270840v1_alt: 191684,\n chr13_KI270839v1_alt: 180306,\n chr13_KI270843v1_alt: 103832,\n chr13_KI270841v1_alt: 169134,\n chr13_KI270838v1_alt: 306913,\n chr13_KI270842v1_alt: 37287,\n chr14_KI270844v1_alt: 322166,\n chr14_KI270847v1_alt: 1511111,\n chr14_KI270845v1_alt: 180703,\n chr14_KI270846v1_alt: 1351393,\n chr15_KI270852v1_alt: 478999,\n chr15_KI270851v1_alt: 263054,\n chr15_KI270848v1_alt: 327382,\n chr15_GL383554v1_alt: 296527,\n chr15_KI270849v1_alt: 244917,\n chr15_GL383555v2_alt: 388773,\n chr15_KI270850v1_alt: 430880,\n chr16_KI270854v1_alt: 134193,\n chr16_KI270856v1_alt: 63982,\n chr16_KI270855v1_alt: 232857,\n chr16_KI270853v1_alt: 2659700,\n chr16_GL383556v1_alt: 192462,\n chr16_GL383557v1_alt: 89672,\n chr17_GL383563v3_alt: 375691,\n chr17_KI270862v1_alt: 391357,\n chr17_KI270861v1_alt: 196688,\n chr17_KI270857v1_alt: 2877074,\n chr17_JH159146v1_alt: 278131,\n chr17_JH159147v1_alt: 70345,\n chr17_GL383564v2_alt: 133151,\n chr17_GL000258v2_alt: 1821992,\n chr17_GL383565v1_alt: 223995,\n chr17_KI270858v1_alt: 235827,\n chr17_KI270859v1_alt: 108763,\n chr17_GL383566v1_alt: 90219,\n chr17_KI270860v1_alt: 178921,\n chr18_KI270864v1_alt: 111737,\n chr18_GL383567v1_alt: 289831,\n chr18_GL383570v1_alt: 164789,\n chr18_GL383571v1_alt: 198278,\n chr18_GL383568v1_alt: 104552,\n chr18_GL383569v1_alt: 167950,\n chr18_GL383572v1_alt: 159547,\n chr18_KI270863v1_alt: 167999,\n chr19_KI270868v1_alt: 61734,\n chr19_KI270865v1_alt: 52969,\n chr19_GL383573v1_alt: 385657,\n chr19_GL383575v2_alt: 170222,\n chr19_GL383576v1_alt: 188024,\n chr19_GL383574v1_alt: 155864,\n chr19_KI270866v1_alt: 43156,\n chr19_KI270867v1_alt: 233762,\n chr19_GL949746v1_alt: 987716,\n chr20_GL383577v2_alt: 128386,\n chr20_KI270869v1_alt: 118774,\n chr20_KI270871v1_alt: 58661,\n chr20_KI270870v1_alt: 183433,\n chr21_GL383578v2_alt: 63917,\n chr21_KI270874v1_alt: 166743,\n chr21_KI270873v1_alt: 143900,\n chr21_GL383579v2_alt: 201197,\n chr21_GL383580v2_alt: 74653,\n chr21_GL383581v2_alt: 116689,\n chr21_KI270872v1_alt: 82692,\n chr22_KI270875v1_alt: 259914,\n chr22_KI270878v1_alt: 186262,\n chr22_KI270879v1_alt: 304135,\n chr22_KI270876v1_alt: 263666,\n chr22_KI270877v1_alt: 101331,\n chr22_GL383583v2_alt: 96924,\n chr22_GL383582v2_alt: 162811,\n chrX_KI270880v1_alt: 284869,\n chrX_KI270881v1_alt: 144206,\n chr19_KI270882v1_alt: 248807,\n chr19_KI270883v1_alt: 170399,\n chr19_KI270884v1_alt: 157053,\n chr19_KI270885v1_alt: 171027,\n chr19_KI270886v1_alt: 204239,\n chr19_KI270887v1_alt: 209512,\n chr19_KI270888v1_alt: 155532,\n chr19_KI270889v1_alt: 170698,\n chr19_KI270890v1_alt: 184499,\n chr19_KI270891v1_alt: 170680,\n chr1_KI270892v1_alt: 162212,\n chr2_KI270894v1_alt: 214158,\n chr2_KI270893v1_alt: 161218,\n chr3_KI270895v1_alt: 162896,\n chr4_KI270896v1_alt: 378547,\n chr5_KI270897v1_alt: 1144418,\n chr5_KI270898v1_alt: 130957,\n chr6_GL000251v2_alt: 4795265,\n chr7_KI270899v1_alt: 190869,\n chr8_KI270901v1_alt: 136959,\n chr8_KI270900v1_alt: 318687,\n chr11_KI270902v1_alt: 106711,\n chr11_KI270903v1_alt: 214625,\n chr12_KI270904v1_alt: 572349,\n chr15_KI270906v1_alt: 196384,\n chr15_KI270905v1_alt: 5161414,\n chr17_KI270907v1_alt: 137721,\n chr17_KI270910v1_alt: 157099,\n chr17_KI270909v1_alt: 325800,\n chr17_JH159148v1_alt: 88070,\n chr17_KI270908v1_alt: 1423190,\n chr18_KI270912v1_alt: 174061,\n chr18_KI270911v1_alt: 157710,\n chr19_GL949747v2_alt: 729520,\n chr22_KB663609v1_alt: 74013,\n chrX_KI270913v1_alt: 274009,\n chr19_KI270914v1_alt: 205194,\n chr19_KI270915v1_alt: 170665,\n chr19_KI270916v1_alt: 184516,\n chr19_KI270917v1_alt: 190932,\n chr19_KI270918v1_alt: 123111,\n chr19_KI270919v1_alt: 170701,\n chr19_KI270920v1_alt: 198005,\n chr19_KI270921v1_alt: 282224,\n chr19_KI270922v1_alt: 187935,\n chr19_KI270923v1_alt: 189352,\n chr3_KI270924v1_alt: 166540,\n chr4_KI270925v1_alt: 555799,\n chr6_GL000252v2_alt: 4604811,\n chr8_KI270926v1_alt: 229282,\n chr11_KI270927v1_alt: 218612,\n chr19_GL949748v2_alt: 1064304,\n chr22_KI270928v1_alt: 176103,\n chr19_KI270929v1_alt: 186203,\n chr19_KI270930v1_alt: 200773,\n chr19_KI270931v1_alt: 170148,\n chr19_KI270932v1_alt: 215732,\n chr19_KI270933v1_alt: 170537,\n chr19_GL000209v2_alt: 177381,\n chr3_KI270934v1_alt: 163458,\n chr6_GL000253v2_alt: 4677643,\n chr19_GL949749v2_alt: 1091841,\n chr3_KI270935v1_alt: 197351,\n chr6_GL000254v2_alt: 4827813,\n chr19_GL949750v2_alt: 1066390,\n chr3_KI270936v1_alt: 164170,\n chr6_GL000255v2_alt: 4606388,\n chr19_GL949751v2_alt: 1002683,\n chr3_KI270937v1_alt: 165607,\n chr6_GL000256v2_alt: 4929269,\n chr19_GL949752v1_alt: 987100,\n chr6_KI270758v1_alt: 76752,\n chr19_GL949753v2_alt: 796479,\n chr19_KI270938v1_alt: 1066800,\n // Unplaced contigs\n chrUn_KI270302v1: 2274,\n chrUn_KI270304v1: 2165,\n chrUn_KI270303v1: 1942,\n chrUn_KI270305v1: 1472,\n chrUn_KI270322v1: 21476,\n chrUn_KI270320v1: 4416,\n chrUn_KI270310v1: 1201,\n chrUn_KI270316v1: 1444,\n chrUn_KI270315v1: 2276,\n chrUn_KI270312v1: 998,\n chrUn_KI270311v1: 12399,\n chrUn_KI270317v1: 37690,\n chrUn_KI270412v1: 1179,\n chrUn_KI270411v1: 2646,\n chrUn_KI270414v1: 2489,\n chrUn_KI270419v1: 1029,\n chrUn_KI270418v1: 2145,\n chrUn_KI270420v1: 2321,\n chrUn_KI270424v1: 2140,\n chrUn_KI270417v1: 2043,\n chrUn_KI270422v1: 1445,\n chrUn_KI270423v1: 981,\n chrUn_KI270425v1: 1884,\n chrUn_KI270429v1: 1361,\n chrUn_KI270442v1: 392061,\n chrUn_KI270466v1: 1233,\n chrUn_KI270465v1: 1774,\n chrUn_KI270467v1: 3920,\n chrUn_KI270435v1: 92983,\n chrUn_KI270438v1: 112505,\n chrUn_KI270468v1: 4055,\n chrUn_KI270510v1: 2415,\n chrUn_KI270509v1: 2318,\n chrUn_KI270518v1: 2186,\n chrUn_KI270508v1: 1951,\n chrUn_KI270516v1: 1300,\n chrUn_KI270512v1: 22689,\n chrUn_KI270519v1: 138126,\n chrUn_KI270522v1: 5674,\n chrUn_KI270511v1: 8127,\n chrUn_KI270515v1: 6361,\n chrUn_KI270507v1: 5353,\n chrUn_KI270517v1: 3253,\n chrUn_KI270529v1: 1899,\n chrUn_KI270528v1: 2983,\n chrUn_KI270530v1: 2168,\n chrUn_KI270539v1: 993,\n chrUn_KI270538v1: 91309,\n chrUn_KI270544v1: 1202,\n chrUn_KI270548v1: 1599,\n chrUn_KI270583v1: 1400,\n chrUn_KI270587v1: 2969,\n chrUn_KI270580v1: 1553,\n chrUn_KI270581v1: 7046,\n chrUn_KI270579v1: 31033,\n chrUn_KI270589v1: 44474,\n chrUn_KI270590v1: 4685,\n chrUn_KI270584v1: 4513,\n chrUn_KI270582v1: 6504,\n chrUn_KI270588v1: 6158,\n chrUn_KI270593v1: 3041,\n chrUn_KI270591v1: 5796,\n chrUn_KI270330v1: 1652,\n chrUn_KI270329v1: 1040,\n chrUn_KI270334v1: 1368,\n chrUn_KI270333v1: 2699,\n chrUn_KI270335v1: 1048,\n chrUn_KI270338v1: 1428,\n chrUn_KI270340v1: 1428,\n chrUn_KI270336v1: 1026,\n chrUn_KI270337v1: 1121,\n chrUn_KI270363v1: 1803,\n chrUn_KI270364v1: 2855,\n chrUn_KI270362v1: 3530,\n chrUn_KI270366v1: 8320,\n chrUn_KI270378v1: 1048,\n chrUn_KI270379v1: 1045,\n chrUn_KI270389v1: 1298,\n chrUn_KI270390v1: 2387,\n chrUn_KI270387v1: 1537,\n chrUn_KI270395v1: 1143,\n chrUn_KI270396v1: 1880,\n chrUn_KI270388v1: 1216,\n chrUn_KI270394v1: 970,\n chrUn_KI270386v1: 1788,\n chrUn_KI270391v1: 1484,\n chrUn_KI270383v1: 1750,\n chrUn_KI270393v1: 1308,\n chrUn_KI270384v1: 1658,\n chrUn_KI270392v1: 971,\n chrUn_KI270381v1: 1930,\n chrUn_KI270385v1: 990,\n chrUn_KI270382v1: 4215,\n chrUn_KI270376v1: 1136,\n chrUn_KI270374v1: 2656,\n chrUn_KI270372v1: 1650,\n chrUn_KI270373v1: 1451,\n chrUn_KI270375v1: 2378,\n chrUn_KI270371v1: 2805,\n chrUn_KI270448v1: 7992,\n chrUn_KI270521v1: 7642,\n chrUn_GL000195v1: 182896,\n chrUn_GL000219v1: 179198,\n chrUn_GL000220v1: 161802,\n chrUn_GL000224v1: 179693,\n chrUn_KI270741v1: 157432,\n chrUn_GL000226v1: 15008,\n chrUn_GL000213v1: 164239,\n chrUn_KI270743v1: 210658,\n chrUn_KI270744v1: 168472,\n chrUn_KI270745v1: 41891,\n chrUn_KI270746v1: 66486,\n chrUn_KI270747v1: 198735,\n chrUn_KI270748v1: 93321,\n chrUn_KI270749v1: 158759,\n chrUn_KI270750v1: 148850,\n chrUn_KI270751v1: 150742,\n chrUn_KI270752v1: 27745,\n chrUn_KI270753v1: 62944,\n chrUn_KI270754v1: 40191,\n chrUn_KI270755v1: 36723,\n chrUn_KI270756v1: 79590,\n chrUn_KI270757v1: 71251,\n chrUn_GL000214v1: 137718,\n chrUn_KI270742v1: 186739,\n chrUn_GL000216v2: 176608,\n chrUn_GL000218v1: 161147,\n chrY_KI270740v1_random: 37240,\n}\n","/**\n * Interval-based sequence cache, matching igv.js CachedSequence.\n *\n * Wraps any SequenceProvider and adds:\n * - 100kb minimum query expansion (amortizes small requests)\n * - 10-slot interval cache with FIFO eviction\n * - Deduplication of concurrent in-flight requests\n * - Subsumption: new intervals evict smaller overlapping ones\n *\n * Module-level singleton pattern: call `createCachedSequence(provider)` once,\n * then pass the returned function as the SequenceProvider to WigTrackCanvas.\n */\n\nimport type {Locus, SequenceProvider} from '../types'\n\ninterface SequenceInterval {\n chr: string\n start: number\n end: number\n sequence: string\n}\n\nconst MIN_QUERY_SIZE = 1e5 // 100kb minimum fetch\nconst MAX_INTERVALS = 10\n\n/**\n * Create a cached SequenceProvider wrapping a raw provider.\n *\n * The returned function is a drop-in SequenceProvider with transparent caching.\n */\nexport function createCachedSequence(provider: SequenceProvider): SequenceProvider {\n let cache: SequenceInterval[] = []\n let currentQuery: { interval: Locus; promise: Promise<SequenceInterval> } | null = null\n\n function contains(interval: SequenceInterval, chr: string, start: number, end: number): boolean {\n return interval.chr === chr && interval.start <= start && interval.end >= end\n }\n\n function containsRange(outer: SequenceInterval, inner: SequenceInterval): boolean {\n return outer.chr === inner.chr && outer.start <= inner.start && outer.end >= inner.end\n }\n\n function trimCache(newInterval: SequenceInterval): void {\n // Remove intervals fully subsumed by the new one\n cache = cache.filter(i => !containsRange(newInterval, i))\n // FIFO eviction if at capacity\n if (cache.length >= MAX_INTERVALS) {\n cache.shift()\n }\n }\n\n async function querySequence(chr: string, start: number, end: number, signal?: AbortSignal): Promise<SequenceInterval> {\n // Expand to minimum 100kb, centered on the request\n let qstart = start\n let qend = end\n if ((end - start) < MIN_QUERY_SIZE) {\n const center = Math.round(start + (end - start) / 2)\n qstart = Math.max(0, center - MIN_QUERY_SIZE / 2)\n qend = qstart + MIN_QUERY_SIZE\n }\n // Ensure integers\n qstart = Math.floor(qstart)\n qend = Math.ceil(qend)\n\n const queryLocus: Locus = {chr, start: qstart, end: qend}\n\n // Dedup: if there's an in-flight query that covers this region, reuse it\n if (currentQuery && currentQuery.interval.chr === chr\n && currentQuery.interval.start <= start && currentQuery.interval.end >= end) {\n return currentQuery.promise\n }\n\n const promise = provider(queryLocus, signal).then(sequence => {\n const interval: SequenceInterval = {chr, start: qstart, end: qend, sequence}\n currentQuery = null\n return interval\n })\n\n currentQuery = {interval: queryLocus, promise}\n return promise\n }\n\n return async function cachedFetchSequence(locus: Locus, signal?: AbortSignal): Promise<string> {\n const {chr, start, end} = locus\n\n // Check cache\n let interval = cache.find(i => contains(i, chr, start, end))\n\n if (!interval) {\n interval = await querySequence(chr, start, end, signal)\n trimCache(interval)\n cache.push(interval)\n }\n\n // Slice out the requested region\n const offset = start - interval.start\n const length = end - start\n return interval.sequence.substring(offset, offset + length)\n }\n}\n","/**\n * Genome assembly abstraction.\n *\n * Provides a unified `Genome` object that encapsulates chromosome metadata,\n * cumulative offsets for whole genome view, and optional sequence access.\n *\n * Mirrors igv.js `Genome` class (js/genome/genome.ts) which provides:\n * - Chromosome sizes and metadata\n * - Sequence access via CachedSequence wrapping FASTA/2bit/UCSC API\n * - Cumulative offsets for genome-wide coordinate conversion\n * - Chromosome alias resolution via ChromAliasDefaults (Gap #6)\n *\n * In our architecture this is Layer 1 (Data + Layout): pure data, no DOM.\n * The HeadlessGenomeBrowser (Layer 3) takes a Genome and derives chromSizes,\n * cumulativeOffsets, and sequenceProvider from it.\n *\n * Factory functions:\n * - `createGenomeSync()` — synchronous, requires inline chromSizes\n * - `createGenome()` — async, can fetch chromSizes from URL\n * - `hg38Genome` — pre-built singleton for the default human genome\n */\n\nimport type {Genome, Chromosome, GenomeConfig, SequenceProvider, ChromAliasRecord} from '../types'\nimport type {ChromSizes, CumulativeOffsets} from './chromSizes'\nimport {ChromAliasDefaults} from './chromAlias'\nimport {\n computeCumulativeOffsets,\n mainChromosomeNames,\n hg38ChromSizes,\n parseChromSizes,\n} from './chromSizes'\nimport {createCachedSequence} from '../data/cachedSequence'\nimport {fetchSequence} from '../data/ucscSequence'\n\n// ─── Built-in genome registry ────────────────────────────────────────────────\n\n/** Known built-in genomes. Currently just hg38; extend as needed. */\nconst BUILTIN_CHROM_SIZES: Record<string, ChromSizes> = {\n hg38: hg38ChromSizes,\n}\n\nconst BUILTIN_NAMES: Record<string, string> = {\n hg38: 'Human (GRCh38/hg38)',\n}\n\n// ─── Implementation ──────────────────────────────────────────────────────────\n\nclass GenomeImpl implements Genome {\n readonly id: string\n readonly name?: string\n readonly chromosomeNames: string[]\n readonly chromSizes: ChromSizes\n readonly cumulativeOffsets: CumulativeOffsets\n readonly sequence?: SequenceProvider\n\n private _chromosomes: Map<string, Chromosome>\n private _chromAlias: ChromAliasDefaults\n\n constructor(\n id: string,\n chromSizes: ChromSizes,\n options?: {\n name?: string\n sequence?: SequenceProvider\n },\n ) {\n this.id = id\n this.name = options?.name\n this.chromSizes = chromSizes\n this.chromosomeNames = mainChromosomeNames(chromSizes)\n this.cumulativeOffsets = computeCumulativeOffsets(chromSizes)\n this.sequence = options?.sequence\n\n // Build chromosome map with order\n this._chromosomes = new Map()\n const allNames = Object.keys(chromSizes)\n // Main chromosomes first (in sorted order), then the rest\n const mainSet = new Set(this.chromosomeNames)\n let order = 0\n for (const name of this.chromosomeNames) {\n this._chromosomes.set(name, {name, bpLength: chromSizes[name], order: order++})\n }\n for (const name of allNames) {\n if (!mainSet.has(name)) {\n this._chromosomes.set(name, {name, bpLength: chromSizes[name], order: order++})\n }\n }\n\n // Build chromosome alias resolver from all chromosome names\n this._chromAlias = new ChromAliasDefaults(allNames, id)\n }\n\n getChromosome(name: string): Chromosome | undefined {\n return this._chromosomes.get(name)\n }\n\n getChromosomeLength(name: string): number | undefined {\n return this.chromSizes[name]\n }\n\n getChromosomeName(alias: string): string {\n return this._chromAlias.getChromosomeName(alias) ?? alias\n }\n\n getAliasRecord(chr: string): ChromAliasRecord | undefined {\n return this._chromAlias.getAliasRecord(chr)\n }\n}\n\n// ─── Factories ───────────────────────────────────────────────────────────────\n\n/**\n * Create a Genome synchronously from inline chromosome sizes.\n *\n * Use when chromSizes are already available (e.g., built-in genomes,\n * or after fetching from a URL yourself).\n */\nexport function createGenomeSync(config: GenomeConfig & { chromSizes: ChromSizes }): Genome {\n const id = config.id ?? 'custom'\n const name = config.name ?? BUILTIN_NAMES[id]\n const sequence = resolveSequenceProvider(config)\n\n return new GenomeImpl(id, config.chromSizes, {name, sequence})\n}\n\n/**\n * Create a Genome asynchronously.\n *\n * Supports:\n * - Built-in genome IDs (e.g., \"hg38\") — uses hardcoded chromSizes\n * - Inline chromSizes — same as createGenomeSync\n * - chromSizesURL — fetches and parses tab-separated chrom.sizes file\n *\n * Mirrors igv.js `Genome.createGenome(config, browser)` (js/genome/genome.ts)\n * which loads sequence, cytobands, and chromosomes asynchronously.\n */\nexport async function createGenome(config: GenomeConfig): Promise<Genome> {\n let chromSizes: ChromSizes\n\n if (config.chromSizes) {\n chromSizes = config.chromSizes\n } else if (config.chromSizesURL) {\n const resp = await fetch(config.chromSizesURL)\n if (!resp.ok) {\n throw new Error(`Failed to fetch chrom.sizes: ${resp.status} ${resp.statusText}`)\n }\n const text = await resp.text()\n chromSizes = parseChromSizes(text)\n } else if (config.id && BUILTIN_CHROM_SIZES[config.id]) {\n chromSizes = BUILTIN_CHROM_SIZES[config.id]\n } else {\n throw new Error(\n 'GenomeConfig must provide chromSizes, chromSizesURL, or a known genome id. ' +\n `Known IDs: ${Object.keys(BUILTIN_CHROM_SIZES).join(', ')}`,\n )\n }\n\n const id = config.id ?? 'custom'\n const name = config.name ?? BUILTIN_NAMES[id]\n const sequence = resolveSequenceProvider(config)\n\n return new GenomeImpl(id, chromSizes, {name, sequence})\n}\n\n// ─── Sequence resolution ─────────────────────────────────────────────────────\n\n/**\n * Resolve a sequence provider from config.\n *\n * Priority:\n * 1. Explicit sequenceProvider in config\n * 2. UCSC API via ucscGenome or id (wrapped in CachedSequence)\n * 3. undefined (no sequence)\n */\nfunction resolveSequenceProvider(config: GenomeConfig): SequenceProvider | undefined {\n if (config.sequenceProvider) {\n return config.sequenceProvider\n }\n\n // Auto-create UCSC-based sequence if we have a genome ID\n const ucscGenome = config.ucscGenome ?? config.id\n if (ucscGenome) {\n return createCachedSequence(\n (locus, signal) => fetchSequence(locus, {genome: ucscGenome}, signal),\n )\n }\n\n return undefined\n}\n\n// ─── Pre-built singletons ────────────────────────────────────────────────────\n\n/**\n * Pre-built hg38 genome with UCSC sequence API.\n *\n * This is the default genome used by HeadlessGenomeBrowser when no genome\n * is specified. Equivalent to igv.js's default behavior of loading hg38.\n */\nexport const hg38Genome: Genome = createGenomeSync({\n id: 'hg38',\n chromSizes: hg38ChromSizes,\n})\n","/**\n * UCSC Genome Browser REST API client for genomic sequences.\n *\n * Fetches DNA sequence data from the UCSC REST API.\n * API docs: https://genome.ucsc.edu/goldenPath/help/api.html\n */\n\nimport type {Locus} from '../types'\n\nconst UCSC_API_BASE = 'https://api.genome.ucsc.edu'\n\nexport interface FetchSequenceOptions {\n /** Genome assembly, e.g. \"hg38\", \"hg19\", \"mm10\". Default: \"hg38\". */\n genome?: string\n}\n\ninterface UcscSequenceResponse {\n genome: string\n chrom: string\n start: number\n end: number\n dna: string\n}\n\n/**\n * Fetch DNA sequence for a genomic region from the UCSC REST API.\n *\n * @param locus - The genomic region to fetch\n * @param options - Optional genome assembly (default: hg38)\n * @returns The DNA sequence string (lowercase)\n */\nexport async function fetchSequence(\n locus: Locus,\n options: FetchSequenceOptions = {},\n signal?: AbortSignal,\n): Promise<string> {\n const genome = options.genome ?? 'hg38'\n\n const url = `${UCSC_API_BASE}/getData/sequence?genome=${genome}&chrom=${locus.chr}&start=${locus.start}&end=${locus.end}`\n const resp = await fetch(url, signal ? {signal} : undefined)\n\n if (!resp.ok) {\n throw new Error(`UCSC sequence API error: ${resp.status} ${resp.statusText}`)\n }\n\n const data: UcscSequenceResponse = await resp.json()\n return data.dna\n}\n","/**\n * Base class for canvas-based genomic track renderers.\n *\n * Handles all shared canvas lifecycle: DPR scaling, sizing, resize observation,\n * attach/detach, background fill, and RenderContext construction.\n *\n * Subclasses implement:\n * - type (track type identifier)\n * - computeHeight(width) — return CSS pixel height for current state\n * - getBackground() — return background fill color\n * - doRender(ctx, width, height, rc) — the actual drawing logic\n *\n * This eliminates ~80 lines of identical boilerplate per track type.\n */\n\nimport type {Locus, RenderContext, Track, TrackSessionConfig, HitTestResult, ContextMenuItem} from '../types'\nimport type {RenderTheme} from '../themes/renderTheme'\nimport type {CanvasProvider} from '../canvasProvider'\nimport {defaultCanvasProvider} from '../canvasProvider'\n\nexport abstract class BaseTrackCanvas<TConfig> implements Track {\n protected _canvas: HTMLCanvasElement\n protected _locus: Locus\n protected _config: TConfig\n protected _height = 0\n protected canvasProvider: CanvasProvider\n private resizeObserver: ResizeObserver | null = null\n private container: HTMLElement | null = null\n private _renderSuspended = false\n private _renderPending = false\n private _error: Error | null = null\n private _zoomedOut = false\n\n /**\n * Visibility window in base pairs. When the viewport spans more than this\n * many bp, data is not fetched and \"Zoom in to see features\" is shown.\n * Mirrors igv.js TrackBase.visibilityWindow (js/trackViewport.ts checkZoomIn).\n *\n * Set to undefined or 0 to disable (always fetch). Set > 0 to enable.\n */\n visibilityWindow?: number\n\n abstract readonly type: string\n get canvas(): HTMLCanvasElement { return this._canvas }\n get locus(): Locus { return this._locus }\n get height(): number { return this._height }\n /** Current track config (read-only). Use setConfig() to update. */\n get config(): TConfig { return this._config }\n\n constructor(canvas: HTMLCanvasElement, locus: Locus, config: TConfig, canvasProvider?: CanvasProvider) {\n this._canvas = canvas\n this._locus = locus\n this._config = config\n this.canvasProvider = canvasProvider ?? defaultCanvasProvider\n }\n\n /** Update locus and re-render. */\n setLocus(locus: Locus): void {\n this._locus = locus\n this.render()\n }\n\n /** Merge partial config and re-render. */\n setConfig(config: Partial<TConfig>): void {\n this._config = {...this._config, ...config}\n this.render()\n }\n\n /** Apply a new render theme and re-render. Subclasses must override. */\n abstract setTheme(theme: RenderTheme): void\n\n /** Suspend rendering — calls to render() will be deferred until resumeRendering(). */\n suspendRendering(): void {\n this._renderSuspended = true\n }\n\n /** Resume rendering. If render() was called while suspended, flushes now. */\n resumeRendering(): void {\n this._renderSuspended = false\n if (this._renderPending) {\n this._renderPending = false\n this.render()\n }\n }\n\n /** Set an error state to render on the track canvas. Pass null to clear. */\n setError(error: Error | null): void {\n this._error = error\n this.render()\n }\n\n /**\n * Mark this track as zoomed out beyond its visibility window.\n * When true, render() shows \"Zoom in to see features\" instead of track content.\n * Called by HeadlessGenomeBrowser during data lifecycle.\n */\n setZoomedOut(zoomedOut: boolean): void {\n if (this._zoomedOut === zoomedOut) return\n this._zoomedOut = zoomedOut\n this.render()\n }\n\n /**\n * Hit-test at canvas-relative pixel coordinates.\n * Returns features at that point with pre-formatted popup data.\n * Default: empty (no interactive features). Subclasses override.\n */\n hitTest(_x: number, _y: number): HitTestResult[] {\n return []\n }\n\n /**\n * Return context menu items for a right-click at canvas-relative coordinates.\n * Default: undefined (no track-specific items). Subclasses override.\n */\n getContextMenuItems(_x: number, _y: number): ContextMenuItem[] | undefined {\n return undefined\n }\n\n /**\n * Attach the canvas to a container element.\n * Appends the canvas and sets up a ResizeObserver for automatic re-renders.\n */\n attachTo(container: HTMLElement): void {\n this.detach()\n this.container = container\n container.appendChild(this._canvas)\n this._canvas.style.display = 'block'\n\n this.resizeObserver = new ResizeObserver(() => this.render())\n this.resizeObserver.observe(container)\n this.render()\n }\n\n /** Detach from container and stop observing resizes. */\n detach(): void {\n if (this.resizeObserver) {\n this.resizeObserver.disconnect()\n this.resizeObserver = null\n }\n if (this.container && this._canvas.parentNode === this.container) {\n this.container.removeChild(this._canvas)\n }\n this.container = null\n }\n\n /** Render the track. Handles DPR, sizing, background, then delegates to doRender(). */\n render(): void {\n if (this._renderSuspended) {\n this._renderPending = true\n return\n }\n\n const width = this.container?.clientWidth ?? this._canvas.clientWidth\n if (width === 0) return\n\n const height = this.computeHeight(width)\n this._height = height\n\n // DPR scaling for sharp rendering on high-density displays\n const dpr = this.canvasProvider.devicePixelRatio\n this._canvas.width = width * dpr\n this._canvas.height = height * dpr\n this._canvas.style.width = `${width}px`\n this._canvas.style.height = `${height}px`\n\n const ctx = this._canvas.getContext('2d')!\n ctx.scale(dpr, dpr)\n\n // Background fill\n ctx.fillStyle = this.getBackground()\n ctx.fillRect(0, 0, width, height)\n\n if (this._error) {\n this.renderError(ctx, width, height)\n return\n }\n\n if (this._zoomedOut) {\n this.renderZoomInNotice(ctx, width, height)\n return\n }\n\n const bpPerPixel = (this._locus.end - this._locus.start) / width\n const rc: RenderContext = {\n pixelWidth: width,\n bpStart: this._locus.start,\n bpPerPixel,\n viewportWidth: width,\n }\n\n this.doRender(ctx, width, height, rc)\n }\n\n /** Draw a centered error message on the canvas. */\n protected renderError(ctx: CanvasRenderingContext2D, width: number, height: number): void {\n ctx.font = '12px sans-serif'\n ctx.fillStyle = 'rgb(180, 0, 0)'\n ctx.textAlign = 'center'\n ctx.textBaseline = 'middle'\n ctx.fillText('Error loading track data', width / 2, height / 2)\n }\n\n /**\n * Draw a centered \"Zoom in to see features\" notice.\n * Mirrors igv.js TrackViewport.createZoomInNotice (js/trackViewport.ts).\n */\n protected renderZoomInNotice(ctx: CanvasRenderingContext2D, width: number, height: number): void {\n ctx.font = '12px sans-serif'\n ctx.fillStyle = 'rgb(120, 120, 120)'\n ctx.textAlign = 'center'\n ctx.textBaseline = 'middle'\n ctx.fillText('Zoom in to see features', width / 2, height / 2)\n }\n\n /**\n * Render this track onto an arbitrary context (e.g. Canvas2SVG for SVG export).\n * Skips DPR scaling and canvas-element lifecycle — draws directly at the given\n * dimensions using the track's current locus and state.\n *\n * Mirrors igv.js TrackViewport.renderSVGContext() which calls track.draw()\n * with a C2S context (js/trackViewport.ts lines 525-579).\n */\n renderToContext(ctx: CanvasRenderingContext2D, width: number, height: number): void {\n // Background fill\n ctx.fillStyle = this.getBackground()\n ctx.fillRect(0, 0, width, height)\n\n if (this._error) {\n this.renderError(ctx, width, height)\n return\n }\n if (this._zoomedOut) {\n this.renderZoomInNotice(ctx, width, height)\n return\n }\n\n const bpPerPixel = (this._locus.end - this._locus.start) / width\n const rc: RenderContext = {\n pixelWidth: width,\n bpStart: this._locus.start,\n bpPerPixel,\n viewportWidth: width,\n }\n this.doRender(ctx, width, height, rc)\n }\n\n /**\n * Compute the track height in CSS pixels for the current state.\n * Called at the start of each render(). The width parameter is provided\n * in case height depends on layout (e.g., gene packing).\n */\n protected abstract computeHeight(width: number): number\n\n /** Return the background fill color for the canvas. */\n protected abstract getBackground(): string\n\n /** Perform the actual track-specific rendering onto the prepared canvas. */\n protected abstract doRender(\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n rc: RenderContext,\n ): void\n\n /**\n * Serialize this track's config for session save/restore.\n * Each subclass diffs its config against theme defaults and returns\n * a typed TrackSessionConfig with only overridden fields.\n */\n abstract serializeConfig(theme: RenderTheme): TrackSessionConfig\n}\n","/**\n * Dynamic sequence (dynseq) renderer for wig tracks.\n *\n * Renders DNA base letters (A, C, G, T, N) as filled glyphs whose height\n * is proportional to the wig signal value. Only activates at high zoom\n * (bpPerPixel < 2) where individual bases are resolvable.\n *\n * Ported from js/feature/wigTrack.ts renderDynSeq/drawLetterGlyph/drawSVGPath.\n */\n\n/** Default nucleotide color scheme matching igv.js. */\nexport const defaultNucleotideColors: Readonly<Record<string, string>> = {\n A: '#00C000', // green\n C: '#0000FF', // blue\n G: '#FFB300', // amber/orange\n T: '#FF0000', // red\n N: '#808080', // gray\n}\n\n/** SVG path data for letter glyphs (100x100 coordinate system). */\nconst letterPaths: Record<string, {main: string; overlay?: string}> = {\n A: {\n main: 'M 0 100 L 33 0 L 66 0 L 100 100 L 75 100 L 66 75 L 33 75 L 25 100 L 0 100',\n overlay: 'M 41 55 L 50 25 L 58 55 L 41 55',\n },\n C: {\n main: 'M 100 28 C 100 -13 0 -13 0 50 C 0 113 100 113 100 72 L 75 72 C 75 90 30 90 30 50 C 30 10 75 10 75 28 L 100 28',\n },\n G: {\n main: 'M 100 28 C 100 -13 0 -13 0 50 C 0 113 100 113 100 72 L 100 48 L 55 48 L 55 72 L 75 72 C 75 90 30 90 30 50 C 30 10 75 5 75 28 L 100 28',\n },\n T: {\n main: 'M 0 0 L 0 20 L 35 20 L 35 100 L 65 100 L 65 20 L 100 20 L 100 0 L 0 0',\n },\n N: {\n main: 'M 0 100 L 0 0 L 20 0 L 80 75 L 80 0 L 100 0 L 100 100 L 80 100 L 20 25 L 20 100 L 0 100',\n },\n}\n\n/**\n * Parse a simple SVG path string (M, L, C commands) and fill it on a canvas,\n * scaled to fit within the target rectangle.\n */\nfunction drawSVGPath(\n ctx: CanvasRenderingContext2D,\n pathString: string,\n x: number, y: number,\n width: number, height: number,\n): void {\n const scaleX = width / 100\n const scaleY = height / 100\n\n ctx.beginPath()\n\n const commands = pathString.match(/[MLC][^MLC]*/g)\n if (!commands) return\n\n for (const command of commands) {\n const type = command[0]\n const coords = command.slice(1).trim().split(/[\\s,]+/).map(Number)\n\n if (type === 'M') {\n ctx.moveTo(x + coords[0] * scaleX, y + coords[1] * scaleY)\n } else if (type === 'L') {\n ctx.lineTo(x + coords[0] * scaleX, y + coords[1] * scaleY)\n } else if (type === 'C' && coords.length >= 6) {\n ctx.bezierCurveTo(\n x + coords[0] * scaleX, y + coords[1] * scaleY,\n x + coords[2] * scaleX, y + coords[3] * scaleY,\n x + coords[4] * scaleX, y + coords[5] * scaleY,\n )\n }\n }\n\n ctx.closePath()\n ctx.fill()\n}\n\n/**\n * Draw a single DNA base letter as a filled glyph.\n *\n * @param ctx - Canvas context\n * @param base - The base character (A, C, G, T, N)\n * @param x - Left edge pixel position\n * @param y - Top edge pixel position\n * @param width - Glyph width in pixels\n * @param height - Glyph height in pixels\n * @param color - Fill color\n * @param flipVertical - Flip the glyph vertically (for negative values)\n */\nexport function drawLetterGlyph(\n ctx: CanvasRenderingContext2D,\n base: string,\n x: number, y: number,\n width: number, height: number,\n color: string,\n flipVertical = false,\n backgroundColor = '#ffffff',\n): void {\n const pathData = letterPaths[base] ?? letterPaths.N\n\n ctx.save()\n ctx.fillStyle = color\n\n if (flipVertical) {\n ctx.translate(x + width / 2, y + height / 2)\n ctx.scale(1, -1)\n ctx.translate(-(x + width / 2), -(y + height / 2))\n }\n\n drawSVGPath(ctx, pathData.main, x, y, width, height)\n\n // Overlay path (e.g. the hole in 'A')\n if (pathData.overlay) {\n ctx.fillStyle = backgroundColor\n drawSVGPath(ctx, pathData.overlay, x, y, width, height)\n }\n\n ctx.restore()\n}\n\n/**\n * Render a single wig feature as dynseq (DNA base glyphs scaled by value).\n *\n * @param ctx - Canvas context\n * @param sequence - DNA sequence string for this feature's region\n * @param x - Left edge pixel position of the feature\n * @param width - Pixel width of the feature\n * @param y - Y pixel of the data value\n * @param y0 - Y pixel of the zero line\n * @param value - The wig data value (for determining negative/flip)\n * @param colors - Nucleotide color map\n * @param backgroundColor - Background color for glyph cutouts (e.g. hole in 'A')\n */\nexport function renderDynSeqFeature(\n ctx: CanvasRenderingContext2D,\n sequence: string,\n x: number,\n width: number,\n y: number,\n y0: number,\n value: number,\n colors: Readonly<Record<string, string>> = defaultNucleotideColors,\n backgroundColor = '#ffffff',\n): void {\n const rectY = Math.min(y, y0)\n const rectHeight = Math.max(1, Math.abs(y - y0))\n const baseWidth = width / sequence.length\n const isNegative = value < 0\n\n for (let i = 0; i < sequence.length; i++) {\n const baseX = x + i * baseWidth\n const base = sequence[i].toUpperCase()\n const color = colors[base] ?? colors.N\n drawLetterGlyph(ctx, base, baseX, rectY, baseWidth, rectHeight, color, isNegative, backgroundColor)\n }\n}\n","/**\n * Standalone wig track renderer.\n *\n * Adapted from js/feature/wigTrack.ts draw() method with no `this` context —\n * all configuration is passed as explicit parameters.\n *\n * Supports four graph types: bar, line, points, and dynseq.\n */\n\nimport type {WigFeature, WigRenderConfig, RenderContext} from '../../types'\nimport {renderDynSeqFeature, defaultNucleotideColors} from '../dynseq/dynseqRenderer'\n\n// ─── Scale helpers ──────────────────────────────────────────────────────────\n\nfunction getScaleFactor(min: number, max: number, height: number, logScale: boolean): number {\n const minValue = logScale\n ? (min < 0 ? -Math.log10(Math.abs(min) + 1) : Math.log10(Math.abs(min) + 1))\n : min\n const maxValue = logScale ? Math.log10(Math.abs(max) + 1) : max\n return height / (maxValue - minValue)\n}\n\nfunction computeYPixel(\n value: number,\n dataRange: {min: number; max: number},\n scaleFactor: number,\n flipAxis: boolean,\n logScale: boolean,\n): number {\n if (logScale) {\n let minValue = dataRange.min\n let maxValue = dataRange.max\n minValue = minValue < 0 ? -Math.log10(Math.abs(minValue) + 1) : Math.log10(Math.abs(minValue) + 1)\n maxValue = maxValue < 0 ? -Math.log10(Math.abs(maxValue) + 1) : Math.log10(Math.abs(maxValue) + 1)\n const yValue = value < 0 ? -Math.log10(Math.abs(value) + 1) : Math.log10(value + 1)\n return (flipAxis ? (yValue - minValue) : (maxValue - yValue)) * scaleFactor\n }\n return (flipAxis ? (value - dataRange.min) : (dataRange.max - value)) * scaleFactor\n}\n\n// ─── Color helpers ──────────────────────────────────────────────────────────\n\nfunction resolveColor(colorOrFn: string | ((value: number) => string), value: number): string {\n return typeof colorOrFn === 'function' ? colorOrFn(value) : colorOrFn\n}\n\n/** Parse a CSS color string to [r, g, b]. Supports rgb(), rgba(), #hex (3/4/6/8 digit). */\nfunction parseRGB(color: string): [number, number, number] | undefined {\n // rgb(r, g, b) or rgba(r, g, b, a)\n const rgbMatch = color.match(/^rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)/)\n if (rgbMatch) return [Number(rgbMatch[1]), Number(rgbMatch[2]), Number(rgbMatch[3])]\n\n // #RGB, #RGBA, #RRGGBB, #RRGGBBAA\n const hexMatch = color.match(/^#([0-9a-f]{3,8})$/i)\n if (hexMatch) {\n const hex = hexMatch[1]\n if (hex.length === 3 || hex.length === 4) {\n return [parseInt(hex[0] + hex[0], 16), parseInt(hex[1] + hex[1], 16), parseInt(hex[2] + hex[2], 16)]\n }\n if (hex.length >= 6) {\n return [parseInt(hex.slice(0, 2), 16), parseInt(hex.slice(2, 4), 16), parseInt(hex.slice(4, 6), 16)]\n }\n }\n return undefined\n}\n\nfunction addAlpha(color: string, alpha: number): string {\n const rgb = parseRGB(color)\n if (rgb) return `rgba(${rgb[0]},${rgb[1]},${rgb[2]},${alpha})`\n return color\n}\n\nfunction getColorForValue(value: number, config: WigRenderConfig): string {\n const colorOrFn = (value < 0 && config.altColor) ? config.altColor : config.color\n const resolved = resolveColor(colorOrFn, value)\n return config.alpha != null ? addAlpha(resolved, config.alpha) : resolved\n}\n\n/**\n * Pre-resolve static colors for a render pass.\n * When color/altColor are plain strings (the common case), we can resolve + alpha-blend\n * once instead of per-feature. Returns undefined if colors are dynamic (functions).\n */\nfunction resolveStaticColors(config: WigRenderConfig): { pos: string; neg: string | undefined } | undefined {\n if (typeof config.color !== 'string') return undefined\n if (config.altColor !== undefined && typeof config.altColor !== 'string') return undefined\n\n const pos = config.alpha != null ? addAlpha(config.color, config.alpha) : config.color\n const neg = config.altColor !== undefined\n ? (config.alpha != null ? addAlpha(config.altColor as string, config.alpha) : config.altColor as string)\n : undefined\n return {pos, neg}\n}\n\n/** Get color for a value, using pre-resolved static colors when available. */\nfunction getColor(value: number, config: WigRenderConfig, staticColors: { pos: string; neg: string | undefined } | undefined): string {\n if (staticColors) {\n return (value < 0 && staticColors.neg) ? staticColors.neg : staticColors.pos\n }\n return getColorForValue(value, config)\n}\n\n// ─── Render functions by graph type ─────────────────────────────────────────\n\nfunction renderBarGraph(\n ctx: CanvasRenderingContext2D,\n features: WigFeature[],\n config: WigRenderConfig,\n rc: RenderContext,\n pixelHeight: number,\n yScale: (value: number) => number,\n y0: number,\n bpEnd: number,\n staticColors: ReturnType<typeof resolveStaticColors>,\n): void {\n for (const f of features) {\n if (f.end < rc.bpStart) continue\n if (f.start > bpEnd) break\n\n const x = (f.start - rc.bpStart) / rc.bpPerPixel\n if (Number.isNaN(x)) continue\n\n const y = yScale(f.value)\n const rectEnd = (f.end - rc.bpStart) / rc.bpPerPixel\n const width = Math.max(1, rectEnd - x)\n const height = Math.min(pixelHeight, y - y0)\n\n ctx.fillStyle = getColor(f.value, config, staticColors)\n ctx.fillRect(x, y0, width, height)\n\n // Out-of-range indicators\n if (f.value > config.dataRange.max) {\n ctx.fillStyle = config.overflowColor\n ctx.fillRect(x, 0, width, 3)\n } else if (f.value < config.dataRange.min) {\n ctx.fillStyle = config.overflowColor\n ctx.fillRect(x, pixelHeight - 2, width, 3)\n }\n }\n}\n\nfunction renderLineGraph(\n ctx: CanvasRenderingContext2D,\n features: WigFeature[],\n config: WigRenderConfig,\n rc: RenderContext,\n yScale: (value: number) => number,\n bpEnd: number,\n staticColors: ReturnType<typeof resolveStaticColors>,\n): void {\n let lastPixelEnd = -1\n let lastY: number | undefined\n\n for (const f of features) {\n if (f.end < rc.bpStart) continue\n if (f.start > bpEnd) break\n\n const x = (f.start - rc.bpStart) / rc.bpPerPixel\n if (Number.isNaN(x)) continue\n\n const y = yScale(f.value)\n const rectEnd = (f.end - rc.bpStart) / rc.bpPerPixel\n const width = rectEnd - x\n const color = getColor(f.value, config, staticColors)\n\n ctx.strokeStyle = color\n ctx.lineWidth = 1.5\n\n // Connect to previous point\n if (lastY !== undefined) {\n ctx.beginPath()\n ctx.moveTo(lastPixelEnd, lastY)\n ctx.lineTo(x, y)\n ctx.stroke()\n }\n\n // Horizontal line for this feature's span\n ctx.beginPath()\n ctx.moveTo(x, y)\n ctx.lineTo(x + width, y)\n ctx.stroke()\n\n lastPixelEnd = x + width\n lastY = y\n }\n}\n\nfunction renderPointsGraph(\n ctx: CanvasRenderingContext2D,\n features: WigFeature[],\n config: WigRenderConfig,\n rc: RenderContext,\n pixelHeight: number,\n yScale: (value: number) => number,\n bpEnd: number,\n staticColors: ReturnType<typeof resolveStaticColors>,\n): void {\n const radius = config.pointSize / 2\n\n for (const f of features) {\n if (f.end < rc.bpStart) continue\n if (f.start > bpEnd) break\n\n const x = (f.start - rc.bpStart) / rc.bpPerPixel\n if (Number.isNaN(x)) continue\n\n const y = yScale(f.value)\n const rectEnd = (f.end - rc.bpStart) / rc.bpPerPixel\n const px = x + (rectEnd - x) / 2\n const color = getColor(f.value, config, staticColors)\n\n ctx.fillStyle = color\n ctx.beginPath()\n ctx.arc(px, y, radius, 0, Math.PI * 2)\n ctx.fill()\n\n // Out-of-range indicators\n if (f.value > config.dataRange.max) {\n ctx.fillStyle = config.overflowColor\n ctx.beginPath()\n ctx.arc(px, radius, radius, 0, Math.PI * 2)\n ctx.fill()\n } else if (f.value < config.dataRange.min) {\n ctx.fillStyle = config.overflowColor\n ctx.beginPath()\n ctx.arc(px, pixelHeight - radius, radius, 0, Math.PI * 2)\n ctx.fill()\n }\n }\n}\n\nfunction renderDynSeqGraph(\n ctx: CanvasRenderingContext2D,\n features: WigFeature[],\n config: WigRenderConfig,\n rc: RenderContext,\n pixelHeight: number,\n yScale: (value: number) => number,\n y0: number,\n bpEnd: number,\n staticColors: ReturnType<typeof resolveStaticColors>,\n): void {\n const colors = config.nucleotideColors ?? defaultNucleotideColors\n\n for (const f of features) {\n if (f.end < rc.bpStart) continue\n if (f.start > bpEnd) break\n\n const x = (f.start - rc.bpStart) / rc.bpPerPixel\n if (Number.isNaN(x)) continue\n\n const y = yScale(f.value)\n const rectEnd = (f.end - rc.bpStart) / rc.bpPerPixel\n const width = Math.max(1, rectEnd - x)\n\n if (f.sequence && rc.bpPerPixel < 2) {\n renderDynSeqFeature(ctx, f.sequence, x, width, y, y0, f.value, colors, config.background)\n } else {\n // Fall back to bar rendering when no sequence or zoomed out\n const height = Math.min(pixelHeight, y - y0)\n ctx.fillStyle = getColor(f.value, config, staticColors)\n ctx.fillRect(x, y0, width, height)\n }\n\n // Out-of-range indicators\n if (f.value > config.dataRange.max) {\n ctx.fillStyle = config.overflowColor\n ctx.fillRect(x, 0, width, 3)\n } else if (f.value < config.dataRange.min) {\n ctx.fillStyle = config.overflowColor\n ctx.fillRect(x, pixelHeight - 2, width, 3)\n }\n }\n}\n\n// ─── Data range labels ──────────────────────────────────────────────────────\n\n/** Format a numeric value for axis labels, matching igv.js's prettyPrint logic. */\nfunction prettyPrint(n: number): string {\n if (Number.isInteger(n)) return n.toString()\n if (Math.abs(n) >= 10) return n.toFixed()\n if (Math.abs(n) >= 1) return n.toFixed(1)\n if (Math.abs(n) >= 0.1) return n.toFixed(2)\n return n.toExponential(1)\n}\n\nfunction renderDataRangeLabels(\n ctx: CanvasRenderingContext2D,\n config: WigRenderConfig,\n pixelHeight: number,\n): void {\n if (!config.showDataRange) return\n\n const {min, max} = config.dataRange\n const maxLabel = prettyPrint(config.flipAxis ? min : max)\n const minLabel = prettyPrint(config.flipAxis ? max : min)\n\n ctx.font = config.labelFont\n ctx.textBaseline = 'top'\n ctx.textAlign = 'left'\n\n const pad = 4\n const vPad = 2\n const hPad = 3\n\n // Draw max label (top-left)\n const maxMetrics = ctx.measureText(maxLabel)\n const maxW = maxMetrics.width + hPad * 2\n const maxH = (maxMetrics.actualBoundingBoxDescent ?? 10) + vPad * 2\n ctx.fillStyle = config.background\n ctx.globalAlpha = 0.7\n ctx.fillRect(pad, pad, maxW, maxH)\n ctx.globalAlpha = 1.0\n ctx.fillStyle = config.labelColor\n ctx.fillText(maxLabel, pad + hPad, pad + vPad)\n\n // Draw min label (bottom-left)\n ctx.textBaseline = 'bottom'\n const minMetrics = ctx.measureText(minLabel)\n const minW = minMetrics.width + hPad * 2\n const minH = (minMetrics.actualBoundingBoxAscent ?? 10) + vPad * 2\n const minY = pixelHeight - pad\n ctx.fillStyle = config.background\n ctx.globalAlpha = 0.7\n ctx.fillRect(pad, minY - minH, minW, minH)\n ctx.globalAlpha = 1.0\n ctx.fillStyle = config.labelColor\n ctx.fillText(minLabel, pad + hPad, minY - vPad)\n}\n\n// ─── Track name overlay label ────────────────────────────────────────────────\n\n/**\n * Render the track name as an igv.js-style overlay in the top-left corner.\n * Draws a semi-transparent background pill behind the text for readability.\n * When data range labels are also visible, positions below the max label.\n */\nfunction renderTrackNameLabel(\n ctx: CanvasRenderingContext2D,\n config: WigRenderConfig,\n pixelHeight: number,\n): void {\n if (!config.trackName) return\n if (pixelHeight < 12) return\n\n const pad = 4\n const vPad = 2\n const hPad = 4\n\n ctx.font = 'normal 10px sans-serif'\n ctx.textBaseline = 'top'\n ctx.textAlign = 'left'\n\n // Compute vertical offset — push below data range max label when visible\n let topOffset = pad\n if (config.showDataRange) {\n ctx.save()\n ctx.font = config.labelFont\n const maxLabel = prettyPrint(config.flipAxis ? config.dataRange.min : config.dataRange.max)\n const maxH = (ctx.measureText(maxLabel).actualBoundingBoxDescent ?? 10) + vPad * 2\n ctx.restore()\n ctx.font = 'normal 10px sans-serif'\n topOffset = pad + maxH + 2\n }\n\n const metrics = ctx.measureText(config.trackName)\n const w = metrics.width + hPad * 2\n const h = (metrics.actualBoundingBoxDescent ?? 10) + vPad * 2\n\n // Semi-transparent background\n ctx.fillStyle = config.background\n ctx.globalAlpha = 0.75\n ctx.fillRect(pad, topOffset, w, h)\n ctx.globalAlpha = 1.0\n\n // Border — use labelColor at reduced opacity for theme awareness\n ctx.strokeStyle = config.labelColor\n ctx.globalAlpha = 0.3\n ctx.lineWidth = 0.5\n ctx.strokeRect(pad, topOffset, w, h)\n ctx.globalAlpha = 1.0\n\n // Text\n ctx.fillStyle = config.labelColor\n ctx.fillText(config.trackName, pad + hPad, topOffset + vPad)\n}\n\n// ─── Baseline and guide lines ───────────────────────────────────────────────\n\nfunction renderBaseline(\n ctx: CanvasRenderingContext2D,\n config: WigRenderConfig,\n pixelWidth: number,\n pixelHeight: number,\n): void {\n if (config.dataRange.min >= 0) return\n\n let {min, max} = config.dataRange\n if (config.logScale) {\n min = min < 0 ? -Math.log10(Math.abs(min) + 1) : Math.log10(Math.abs(min) + 1)\n max = max < 0 ? -Math.log10(Math.abs(max) + 1) : Math.log10(Math.abs(max) + 1)\n }\n const ratio = max / (max - min)\n const basepx = config.flipAxis ? (1 - ratio) * pixelHeight : ratio * pixelHeight\n\n ctx.strokeStyle = config.baselineColor\n ctx.lineWidth = 1\n ctx.beginPath()\n ctx.moveTo(0, basepx)\n ctx.lineTo(pixelWidth, basepx)\n ctx.stroke()\n}\n\nfunction renderGuideLines(\n ctx: CanvasRenderingContext2D,\n config: WigRenderConfig,\n pixelWidth: number,\n yScale: (value: number) => number,\n): void {\n if (!config.guideLines) return\n\n for (const line of config.guideLines) {\n const y = yScale(line.y)\n ctx.strokeStyle = line.color\n ctx.lineWidth = 2\n\n if (line.dotted) {\n ctx.setLineDash([5, 5])\n } else {\n ctx.setLineDash([])\n }\n\n ctx.beginPath()\n ctx.moveTo(0, y)\n ctx.lineTo(pixelWidth, y)\n ctx.stroke()\n }\n ctx.setLineDash([])\n}\n\n// ─── Main render entry point ────────────────────────────────────────────────\n\n/**\n * Render wig features onto a canvas context.\n *\n * The canvas should be sized and cleared before calling this.\n */\nexport function renderWigTrack(\n ctx: CanvasRenderingContext2D,\n features: WigFeature[],\n config: WigRenderConfig,\n rc: RenderContext,\n): void {\n if (!features || features.length === 0) return\n if (config.dataRange.max <= config.dataRange.min) return\n\n const pixelHeight = config.height - 1\n const bpEnd = rc.bpStart + rc.pixelWidth * rc.bpPerPixel + 1\n\n const scaleFactor = getScaleFactor(config.dataRange.min, config.dataRange.max, pixelHeight, config.logScale)\n const yScale = (value: number): number =>\n computeYPixel(value, config.dataRange, scaleFactor, config.flipAxis, config.logScale)\n const y0 = yScale(0)\n console.log('[renderWigTrack]', {logScale: config.logScale, scaleFactor, y0, pixelHeight, dataRange: config.dataRange})\n const staticColors = resolveStaticColors(config)\n\n switch (config.graphType) {\n case 'bar':\n renderBarGraph(ctx, features, config, rc, pixelHeight, yScale, y0, bpEnd, staticColors)\n break\n case 'line':\n renderLineGraph(ctx, features, config, rc, yScale, bpEnd, staticColors)\n break\n case 'points':\n renderPointsGraph(ctx, features, config, rc, pixelHeight, yScale, bpEnd, staticColors)\n break\n case 'dynseq':\n renderDynSeqGraph(ctx, features, config, rc, pixelHeight, yScale, y0, bpEnd, staticColors)\n break\n }\n\n renderBaseline(ctx, config, rc.pixelWidth, pixelHeight)\n renderGuideLines(ctx, config, rc.pixelWidth, yScale)\n renderDataRangeLabels(ctx, config, pixelHeight)\n renderTrackNameLabel(ctx, config, pixelHeight)\n}\n","/**\n * Resolution-aware data summarization for wig tracks.\n *\n * When zoomed out, many data points map to the same pixel. This module bins\n * features and applies a window function (mean, min, max) to produce one\n * summary value per pixel-width bin.\n *\n * Ported from js/feature/wigSummary.ts with strict types, no `any`.\n */\n\nimport type {WigFeature, WindowFunction} from '../../types'\n\nclass SummaryBinData {\n bin: number\n sumData: number\n count: number\n min: number\n max: number\n\n constructor(bin: number, feature: WigFeature) {\n this.bin = bin\n this.sumData = feature.value\n this.count = 1\n this.min = feature.value\n this.max = feature.value\n }\n\n add(feature: WigFeature): void {\n this.sumData += feature.value\n this.max = Math.max(feature.value, this.max)\n this.min = Math.min(feature.value, this.min)\n this.count++\n }\n}\n\n/**\n * Summarize wig features by binning into pixel-width windows and applying\n * a window function.\n *\n * Features must be sorted by position. Wig features cannot overlap.\n *\n * @param features - sorted array of wig features\n * @param startBP - start position in base pairs (left edge of viewport)\n * @param bpPerPixel - base pairs per pixel (bin size)\n * @param windowFunction - aggregation function: mean, min, max, or none\n * @returns summarized features (one per pixel-bin)\n */\nexport function summarizeWigData(\n features: WigFeature[],\n startBP: number,\n bpPerPixel: number,\n windowFunction: WindowFunction = 'mean',\n): WigFeature[] {\n if (bpPerPixel <= 1 || !features || features.length === 0 || windowFunction === 'none') {\n return features\n }\n\n const chr = features[0].chr\n const binSize = bpPerPixel\n const summaryFeatures: WigFeature[] = []\n\n const finishBin = (bin: SummaryBinData): void => {\n const start = startBP + bin.bin * binSize\n const end = start + binSize\n let value: number\n switch (windowFunction) {\n case 'mean':\n value = bin.sumData / bin.count\n break\n case 'max':\n value = bin.max\n break\n case 'min':\n value = bin.min\n break\n default:\n throw Error(`Unknown window function: ${windowFunction}`)\n }\n const description = `${windowFunction} of ${bin.count} values`\n summaryFeatures.push({chr, start, end, value, description})\n }\n\n let currentBinData: SummaryBinData | undefined\n for (const f of features) {\n let startBin = Math.floor((f.start - startBP) / binSize)\n const endBin = Math.floor((f.end - startBP) / binSize)\n\n if (currentBinData && startBin === currentBinData.bin) {\n currentBinData.add(f)\n startBin++\n }\n\n if (!currentBinData || endBin > currentBinData.bin) {\n if (currentBinData) {\n finishBin(currentBinData)\n }\n\n // Feature stretches across multiple bins\n if (endBin > startBin) {\n const end = startBP + endBin * binSize\n summaryFeatures.push({chr, start: f.start, end, value: f.value})\n }\n\n currentBinData = new SummaryBinData(endBin, f)\n }\n }\n if (currentBinData) {\n finishBin(currentBinData)\n }\n\n // Consolidate adjacent features with the same value\n if (summaryFeatures.length === 0) return summaryFeatures\n\n const consolidated: WigFeature[] = []\n let lastFeature = summaryFeatures[0]\n for (const f of summaryFeatures) {\n if (lastFeature.value === f.value && f.start <= lastFeature.end) {\n lastFeature = {...lastFeature, end: f.end}\n } else {\n consolidated.push(lastFeature)\n lastFeature = f\n }\n }\n consolidated.push(lastFeature)\n\n return consolidated\n}\n\n/**\n * Compute the min/max data range from a set of wig features.\n * Useful for autoscaling.\n */\nexport function computeWigDataRange(features: WigFeature[]): {min: number; max: number} {\n if (!features || features.length === 0) return {min: 0, max: 100}\n\n let min = Number.MAX_VALUE\n let max = -Number.MAX_VALUE\n for (const f of features) {\n if (!Number.isNaN(f.value)) {\n if (f.value < min) min = f.value\n if (f.value > max) max = f.value\n }\n }\n // All NaN — return default range\n if (min === Number.MAX_VALUE) return {min: 0, max: 100}\n // Ensure zero baseline (matching igv.js doAutoscale behavior)\n if (max > 0) min = Math.min(0, min)\n if (max < 0) max = 0\n\n return {min, max}\n}\n","/**\n * Canvas manager for rendering wig (wiggle) tracks.\n *\n * Extends BaseTrackCanvas — canvas lifecycle is handled by the base class.\n * This class implements wig-specific logic: value scaling, autoscale,\n * and rendering delegation.\n *\n * Data summarization (pixel-width binning) is handled at the data source\n * layer by BigWigDataSource, not here. This keeps the render layer\n * focused on rendering and lets headless consumers benefit from\n * pre-summarized data.\n *\n * For dynseq mode, an optional `sequenceProvider` can be passed at construction.\n * When in dynseq mode, the track automatically fetches and attaches DNA sequence\n * to features at high zoom (bpPerPixel < 2). This matches the igv.js pattern\n * where sequence is fetched during getFeatures(), not during rendering.\n *\n * Usage:\n * const canvas = document.createElement('canvas')\n * const track = new WigTrackCanvas(canvas, { locus, features })\n * track.attachTo(containerDiv)\n */\n\nimport type {WigFeature, WigRenderConfig, WigGraphType, WindowFunction, Locus, RenderContext, WigTrackSessionConfig, WigSessionOverrides, HitTestResult, PopupDataItem, AxisInfo, ContextMenuItem, NumericState, SequenceProvider} from '../../types'\nimport type {CanvasProvider} from '../../canvasProvider'\nimport type {RenderTheme} from '../../themes/renderTheme'\nimport {resolveTheme, resolveWigConfig} from '../../themes/renderTheme'\nimport {BaseTrackCanvas} from '../baseTrackCanvas'\nimport {renderWigTrack} from './wigRenderer'\nimport {computeWigDataRange} from './wigSummary'\n\nexport interface WigTrackCanvasOptions {\n locus: Locus\n features: WigFeature[]\n /** Per-track config overrides. Applied after theme-derived defaults. */\n config?: Partial<WigRenderConfig>\n /** Unified render theme. Palette drives default colors/fonts. */\n theme?: Partial<RenderTheme>\n /** Fixed pixel height. If not set, uses config.height (default 50). */\n height?: number\n /** Background color. Overrides palette.background if set. */\n background?: string\n /** Canvas provider for environment abstraction. Default: DOMCanvasProvider. */\n canvasProvider?: CanvasProvider\n /** Track name for axis label. */\n name?: string\n /** Sequence provider for dynseq rendering. When set, dynseq appears in the graph type menu. */\n sequenceProvider?: SequenceProvider\n}\n\nexport class WigTrackCanvas extends BaseTrackCanvas<WigRenderConfig> {\n private features: WigFeature[]\n private fixedHeight: number | undefined\n private _name: string | undefined\n private _lastDataRange: { min: number; max: number } | null = null\n private _sequenceProvider: SequenceProvider | undefined\n /** Abort controller for in-flight sequence fetch. */\n private _seqAbort: AbortController | null = null\n /** Callback invoked when the user changes the windowing function via context menu. */\n private _onWindowFunctionChange?: (wf: WindowFunction) => void\n\n readonly type = 'wig'\n\n constructor(canvas: HTMLCanvasElement, options: WigTrackCanvasOptions) {\n const theme = resolveTheme(options.theme)\n const config = resolveWigConfig(theme, options.config)\n if (options.background !== undefined) {\n config.background = options.background\n }\n super(canvas, options.locus, config, options.canvasProvider)\n this.features = options.features\n this.fixedHeight = options.height\n this._name = options.name\n this._sequenceProvider = options.sequenceProvider\n }\n\n /** Set a callback invoked when the user changes the windowing function via context menu. */\n set onWindowFunctionChange(cb: ((wf: WindowFunction) => void) | undefined) {\n this._onWindowFunctionChange = cb\n }\n\n /** Update features and re-render. Recomputes autoscale if enabled. */\n setFeatures(features: WigFeature[]): void {\n this.features = features\n if (this._config.graphType === 'dynseq') {\n this.augmentWithSequence()\n } else {\n this.render()\n }\n }\n\n /** Update locus and re-render. Re-fetches sequence in dynseq mode. */\n override setLocus(locus: Locus): void {\n this._locus = locus\n if (this._config.graphType === 'dynseq') {\n this.augmentWithSequence()\n } else {\n this.render()\n }\n }\n\n /** Merge partial config and re-render. Triggers sequence fetch when switching to dynseq. */\n override setConfig(config: Partial<WigRenderConfig>): void {\n const wasDynseq = this._config.graphType === 'dynseq'\n super.setConfig(config)\n if (!wasDynseq && this._config.graphType === 'dynseq') {\n this.augmentWithSequence()\n }\n }\n\n /**\n * Fetch DNA sequence for current features and re-render.\n * At low zoom (bpPerPixel >= 2), skips fetch — the renderer falls back to bars.\n */\n private augmentWithSequence(): void {\n if (!this._sequenceProvider || this.features.length === 0) {\n this.render()\n return\n }\n\n const width = this._canvas.clientWidth\n if (width === 0) { this.render(); return }\n\n const bpPerPixel = (this._locus.end - this._locus.start) / width\n if (bpPerPixel >= 2) {\n // Too zoomed out for dynseq — render as bars, no sequence needed\n this.render()\n return\n }\n\n // Abort any previous sequence fetch\n if (this._seqAbort) this._seqAbort.abort()\n const controller = new AbortController()\n this._seqAbort = controller\n\n const locus: Locus = {\n chr: this._locus.chr,\n start: Math.floor(this._locus.start),\n end: Math.ceil(this._locus.end),\n }\n\n this._sequenceProvider(locus, controller.signal)\n .then(sequence => {\n if (controller.signal.aborted) return\n this._seqAbort = null\n\n // Attach sequence slices to each feature\n this.features = this.features.map(f => {\n const seqStart = Math.max(0, Math.floor(f.start) - locus.start)\n const seqEnd = Math.min(sequence.length, Math.floor(f.end) - locus.start)\n if (seqStart >= seqEnd || seqStart >= sequence.length) return f\n return {...f, sequence: sequence.slice(seqStart, seqEnd)}\n })\n this.render()\n })\n .catch(() => {\n if (!controller.signal.aborted) {\n // Graceful degradation: render without sequence (falls back to bars)\n this._seqAbort = null\n this.render()\n }\n })\n\n // Render immediately with whatever we have (bars fallback)\n this.render()\n }\n\n protected computeHeight(_width: number): number {\n return this.fixedHeight ?? this.config.height\n }\n\n protected getBackground(): string {\n return this.config.background\n }\n\n protected doRender(ctx: CanvasRenderingContext2D, _width: number, height: number, rc: RenderContext): void {\n if (this.features.length === 0) return\n\n // Apply value scaling (normalize then scaleFactor), matching igv.js getFeatures() order.\n // Creates a scaled copy to avoid mutating the original features array.\n const needsScaling = (this.config.normalizationFactor != null && this.config.normalizationFactor !== 1)\n || (this.config.scaleFactor != null && this.config.scaleFactor !== 1)\n const features = needsScaling\n ? this.features.map(f => ({\n ...f,\n value: f.value\n * (this.config.normalizationFactor ?? 1)\n * (this.config.scaleFactor ?? 1),\n }))\n : this.features\n\n // Autoscale if enabled — use only visible features (matching igv.js behavior)\n const effectiveConfig = {...this.config, height, trackName: this._name}\n if (this.config.autoscale) {\n const bpEnd = rc.bpStart + rc.pixelWidth * rc.bpPerPixel\n const visible = features.filter(f => f.end >= rc.bpStart && f.start <= bpEnd)\n const autoRange = computeWigDataRange(visible)\n effectiveConfig.dataRange = autoRange\n // Persist to config so turning off autoscale keeps the last computed range\n // (matches igv.js where this.dataRange is continuously updated by autoscale)\n this._config = {...this._config, dataRange: autoRange}\n }\n\n this._lastDataRange = effectiveConfig.dataRange\n console.log('[wig doRender]', {logScale: effectiveConfig.logScale, autoscale: effectiveConfig.autoscale, flipAxis: effectiveConfig.flipAxis, dataRange: effectiveConfig.dataRange, featureCount: features.length})\n renderWigTrack(ctx, features, effectiveConfig, rc)\n }\n\n getAxisInfo(): AxisInfo | undefined {\n if (!this._lastDataRange) return undefined\n return {\n dataRange: this._lastDataRange,\n color: typeof this.config.color === 'string' ? this.config.color : undefined,\n label: this._name,\n flipAxis: this.config.flipAxis || undefined,\n logScale: this.config.logScale || undefined,\n }\n }\n\n override getContextMenuItems(_x: number, _y: number): ContextMenuItem[] {\n const graphTypes: WigGraphType[] = this._sequenceProvider\n ? ['bar', 'line', 'points', 'dynseq']\n : ['bar', 'line', 'points']\n return [\n {\n label: 'Flip y-axis',\n type: 'checkbox',\n checked: this._config.flipAxis,\n action: () => this.setConfig({flipAxis: !this._config.flipAxis}),\n },\n {\n label: 'Graph type',\n children: graphTypes.map(gt => ({\n label: gt.charAt(0).toUpperCase() + gt.slice(1),\n type: 'checkbox' as const,\n checked: this._config.graphType === gt,\n action: () => this.setConfig({graphType: gt}),\n })),\n },\n {\n label: 'Windowing function',\n children: (['mean', 'min', 'max'] as const).map(wf => ({\n label: wf.charAt(0).toUpperCase() + wf.slice(1),\n type: 'checkbox' as const,\n checked: this._config.windowFunction === wf,\n action: () => {\n this.setConfig({windowFunction: wf})\n if (this._onWindowFunctionChange) this._onWindowFunctionChange(wf)\n },\n })),\n },\n // Autoscale, log scale, set data range — provided by numericDataMenuItems()\n // via getNumericState() at the browser level.\n ]\n }\n\n /**\n * Return numeric state for shared menu items (autoscale, log scale, set data range).\n * The browser calls numericDataMenuItems() with this state when assembling context menus.\n */\n getNumericState(): NumericState {\n return {\n autoscale: this._config.autoscale,\n logScale: this._config.logScale,\n dataRange: this._config.dataRange,\n setAutoscale: (enabled: boolean) => this.setConfig({autoscale: enabled}),\n setLogScale: (enabled: boolean) => this.setConfig({logScale: enabled}),\n setDataRange: (min: number, max: number) => this.setConfig({\n dataRange: {min, max},\n autoscale: false,\n }),\n }\n }\n\n override hitTest(x: number, _y: number): HitTestResult<WigFeature>[] {\n if (this.features.length === 0) return []\n\n const width = this._canvas.clientWidth\n if (width === 0) return []\n\n const bpPerPixel = (this._locus.end - this._locus.start) / width\n const genomicPos = this._locus.start + x * bpPerPixel\n\n for (const f of this.features) {\n if (genomicPos >= f.start && genomicPos < f.end) {\n return [{feature: f, popupData: wigPopupData(f)}]\n }\n }\n return []\n }\n\n setTheme(theme: RenderTheme): void {\n const dataRange = this._config.dataRange\n this._config = {...resolveWigConfig(theme), dataRange}\n this.render()\n }\n\n serializeConfig(theme: RenderTheme): WigTrackSessionConfig {\n const defaults = resolveWigConfig(theme)\n const overrides: WigSessionOverrides = {}\n let hasOverrides = false\n\n const cfg = this.config\n if (cfg.height !== defaults.height) { overrides.height = cfg.height; hasOverrides = true }\n if (cfg.graphType !== defaults.graphType) { overrides.graphType = cfg.graphType; hasOverrides = true }\n if (cfg.windowFunction !== defaults.windowFunction) { overrides.windowFunction = cfg.windowFunction; hasOverrides = true }\n if (!cfg.autoscale && cfg.dataRange) {\n overrides.dataRange = cfg.dataRange\n overrides.autoscale = false\n hasOverrides = true\n }\n if (cfg.autoscale !== defaults.autoscale) { overrides.autoscale = cfg.autoscale; hasOverrides = true }\n\n // Only serialize string colors (drop functions — restored from theme on load)\n if (typeof cfg.color === 'string' && cfg.color !== defaults.color) {\n overrides.color = cfg.color; hasOverrides = true\n }\n if (typeof cfg.altColor === 'string' && cfg.altColor !== (defaults.altColor as string | undefined)) {\n overrides.altColor = cfg.altColor; hasOverrides = true\n }\n\n if (cfg.alpha != null && cfg.alpha !== defaults.alpha) { overrides.alpha = cfg.alpha; hasOverrides = true }\n if (cfg.flipAxis !== defaults.flipAxis) { overrides.flipAxis = cfg.flipAxis; hasOverrides = true }\n if (cfg.logScale !== defaults.logScale) { overrides.logScale = cfg.logScale; hasOverrides = true }\n if (cfg.baselineColor !== defaults.baselineColor) { overrides.baselineColor = cfg.baselineColor; hasOverrides = true }\n if (cfg.overflowColor !== defaults.overflowColor) { overrides.overflowColor = cfg.overflowColor; hasOverrides = true }\n if (cfg.pointSize !== defaults.pointSize) { overrides.pointSize = cfg.pointSize; hasOverrides = true }\n if (cfg.background !== defaults.background) { overrides.background = cfg.background; hasOverrides = true }\n if (cfg.scaleFactor != null && cfg.scaleFactor !== 1) { overrides.scaleFactor = cfg.scaleFactor; hasOverrides = true }\n if (cfg.normalizationFactor != null && cfg.normalizationFactor !== 1) { overrides.normalizationFactor = cfg.normalizationFactor; hasOverrides = true }\n if (cfg.showDataRange !== defaults.showDataRange) { overrides.showDataRange = cfg.showDataRange; hasOverrides = true }\n if (cfg.labelColor !== defaults.labelColor) { overrides.labelColor = cfg.labelColor; hasOverrides = true }\n if (cfg.labelFont !== defaults.labelFont) { overrides.labelFont = cfg.labelFont; hasOverrides = true }\n\n return {\n type: 'wig',\n config: hasOverrides ? overrides : undefined,\n }\n }\n}\n\nfunction wigPopupData(f: WigFeature): PopupDataItem[] {\n const items: PopupDataItem[] = []\n if (f.chr) items.push({name: 'Chr', value: f.chr})\n items.push({name: 'Start', value: Math.floor(f.start).toLocaleString()})\n items.push({name: 'End', value: Math.ceil(f.end).toLocaleString()})\n items.push({name: 'Value', value: Number.isInteger(f.value) ? f.value : f.value.toPrecision(6)})\n if (f.description) items.push({name: 'Description', value: f.description})\n return items\n}\n","/**\n * Standalone annotation feature renderer.\n *\n * Adapted from js/feature/render/renderFeature.ts but with no `this` context —\n * all configuration is passed as explicit parameters.\n *\n * Renders gene, BED, GFF, and peak features with exon/UTR/CDS structure,\n * intron lines, strand arrows, labels, and per-feature colors.\n */\n\nimport type {AnnotationFeature, AnnotationRenderConfig, RenderContext} from '../../types'\n\ninterface FeatureCoords {\n px: number\n px1: number\n pw: number\n}\n\nfunction calculateFeatureCoordinates(feature: AnnotationFeature, bpStart: number, bpPerPixel: number): FeatureCoords {\n let px = (feature.start - bpStart) / bpPerPixel\n let px1 = (feature.end - bpStart) / bpPerPixel\n let pw = px1 - px\n\n if (pw < 3) {\n pw = 3\n px -= 1.5\n }\n\n return {px, px1, pw}\n}\n\n/** Draw a filled (and optionally stroked) rectangle, with optional rounded corners. */\nfunction fillStyledRect(\n ctx: CanvasRenderingContext2D,\n x: number, y: number, w: number, h: number,\n config: AnnotationRenderConfig,\n): void {\n const r = config.borderRadius ?? 0\n if (r > 0 && w > r * 2 && h > r * 2) {\n ctx.beginPath()\n ctx.roundRect(x, y, w, h, r)\n ctx.fill()\n if (config.borderColor && (config.borderWidth ?? 0) > 0) {\n ctx.strokeStyle = config.borderColor\n ctx.lineWidth = config.borderWidth!\n ctx.stroke()\n }\n } else {\n ctx.fillRect(x, y, w, h)\n if (config.borderColor && (config.borderWidth ?? 0) > 0) {\n ctx.strokeStyle = config.borderColor\n ctx.lineWidth = config.borderWidth!\n ctx.strokeRect(x, y, w, h)\n }\n }\n}\n\nfunction renderSingleFeature(\n ctx: CanvasRenderingContext2D,\n feature: AnnotationFeature,\n config: AnnotationRenderConfig,\n rc: RenderContext,\n rowLastLabelX: Record<number, number>,\n): void {\n ctx.save()\n try {\n const color = getColorForFeature(feature, config)\n const utrColor = getUtrColorForFeature(feature, config)\n ctx.fillStyle = color\n ctx.strokeStyle = color\n\n let h: number\n let py: number\n if (config.displayMode === 'SQUISHED' && feature.row !== undefined) {\n h = config.featureHeight / 2\n py = config.margin + config.squishedRowHeight * feature.row\n } else if (config.displayMode === 'EXPANDED' && feature.row !== undefined) {\n h = config.featureHeight\n py = config.margin + config.expandedRowHeight * feature.row\n } else {\n // collapsed\n h = config.featureHeight\n py = config.margin\n }\n\n const cy = py + h / 2\n const h2 = h / 2\n const py2 = cy - h2 / 2\n\n const exonCount = feature.exons ? feature.exons.length : 0\n const coord = calculateFeatureCoordinates(feature, rc.bpStart, rc.bpPerPixel)\n const step = config.arrowSpacing\n const direction = feature.strand === '+' ? 1 : feature.strand === '-' ? -1 : 0\n\n const intronArrowColor = config.arrowColor ?? color\n const exonArrowColor = config.arrowInExonColor ?? 'white'\n\n if (exonCount === 0) {\n // Single-exon / no-exon feature — draw as solid rect\n const xLeft = Math.max(0, coord.px)\n const xRight = Math.min(rc.pixelWidth, coord.px1)\n const width = xRight - xLeft\n\n ctx.fillStyle = color\n fillStyledRect(ctx, xLeft, py, width, h, config)\n\n // Strand arrows inside the rect\n if (direction !== 0) {\n ctx.strokeStyle = exonArrowColor\n for (let x = xLeft + step / 2; x < xRight; x += step) {\n drawArrowhead(ctx, x, cy, direction)\n }\n }\n } else {\n // Multi-exon transcript — draw intron line\n ctx.save()\n ctx.strokeStyle = config.intronColor ?? color\n ctx.lineWidth = config.intronLineWidth ?? 1\n if (config.intronDash && config.intronDash.length > 0) {\n ctx.setLineDash(config.intronDash)\n }\n ctx.beginPath()\n ctx.moveTo(coord.px + 1, cy)\n ctx.lineTo(coord.px1 - 1, cy)\n ctx.stroke()\n ctx.restore()\n\n // Strand arrows along intron line\n ctx.strokeStyle = intronArrowColor\n const xLeft = Math.max(0, coord.px) + step / 2\n const xRight = Math.min(rc.pixelWidth, coord.px1)\n for (let x = xLeft; x < xRight; x += step) {\n drawArrowhead(ctx, x, cy, direction)\n }\n\n // Draw each exon\n for (const exon of feature.exons!) {\n let ePx = Math.round((exon.start - rc.bpStart) / rc.bpPerPixel)\n let ePx1 = Math.round((exon.end - rc.bpStart) / rc.bpPerPixel)\n let ePw = Math.max(1, ePx1 - ePx)\n\n if (ePx + ePw < 0) continue // off left edge\n if (ePx > rc.pixelWidth) break // off right edge\n\n if (exon.utr) {\n // Entire exon is UTR — draw at half height with UTR color\n ctx.fillStyle = utrColor\n fillStyledRect(ctx, ePx, py2, ePw, h2, config)\n } else {\n // Handle UTR portions at exon boundaries\n if (exon.cdStart) {\n const ePxU = Math.round((exon.cdStart - rc.bpStart) / rc.bpPerPixel)\n ctx.fillStyle = utrColor\n fillStyledRect(ctx, ePx, py2, ePxU - ePx, h2, config) // UTR at start\n ePw -= (ePxU - ePx)\n ePx = ePxU\n }\n if (exon.cdEnd) {\n const ePxU = Math.round((exon.cdEnd - rc.bpStart) / rc.bpPerPixel)\n ctx.fillStyle = utrColor\n fillStyledRect(ctx, ePxU, py2, ePx1 - ePxU, h2, config) // UTR at end\n ePw -= (ePx1 - ePxU)\n ePx1 = ePxU\n }\n\n ePw = Math.max(ePw, 1)\n ctx.fillStyle = color\n fillStyledRect(ctx, ePx, py, ePw, h, config)\n\n // Strand arrows inside wide exons\n if (ePw > step + 5 && direction !== 0) {\n ctx.strokeStyle = exonArrowColor\n for (let x = ePx + step / 2; x < ePx1; x += step) {\n drawArrowhead(ctx, x, cy, direction)\n }\n }\n }\n }\n }\n\n // Labels\n if (config.drawLabels && config.displayMode !== 'SQUISHED') {\n renderFeatureLabel(ctx, feature, coord.px, coord.px1, py, config, rc, rowLastLabelX)\n }\n } finally {\n ctx.restore()\n }\n}\n\nfunction drawArrowhead(ctx: CanvasRenderingContext2D, x: number, cy: number, direction: number): void {\n ctx.beginPath()\n ctx.moveTo(x - direction * 2, cy - 2)\n ctx.lineTo(x, cy)\n ctx.stroke()\n ctx.beginPath()\n ctx.moveTo(x - direction * 2, cy + 2)\n ctx.lineTo(x, cy)\n ctx.stroke()\n}\n\n/** Safely look up a label field on a AnnotationFeature by property name. */\nfunction getFeatureLabel(feature: AnnotationFeature, field: string): string | undefined {\n const labelFields: Record<string, string | undefined> = {\n name: feature.name,\n id: feature.id,\n chr: feature.chr,\n }\n return labelFields[field] ?? feature.name\n}\n\nfunction renderFeatureLabel(\n ctx: CanvasRenderingContext2D,\n feature: AnnotationFeature,\n featureX: number,\n featureX1: number,\n featureY: number,\n config: AnnotationRenderConfig,\n rc: RenderContext,\n rowLastLabelX: Record<number, number>,\n): void {\n const name = getFeatureLabel(feature, config.labelField)\n if (!name || name === '.') return\n\n ctx.save()\n try {\n ctx.font = config.labelFont ?? config.font\n\n const t1 = Math.max(featureX, 0)\n const t2 = Math.min(featureX1, rc.viewportWidth)\n const centerX = (t1 + t2) / 2\n\n const transform = config.displayMode === 'COLLAPSED' && config.labelDisplayMode === 'SLANT'\n const labelY = transform ? featureY + 20 : featureY + 25\n\n ctx.fillStyle = config.labelColor ?? getColorForFeature(feature, config)\n\n const textMetrics = ctx.measureText(name)\n const xleft = centerX - textMetrics.width / 2\n const xright = centerX + textMetrics.width / 2\n const lastLabelX = rowLastLabelX[feature.row!] ?? -Number.MAX_SAFE_INTEGER\n\n if (xleft > lastLabelX) {\n rowLastLabelX[feature.row!] = xright\n\n // Clear background behind label\n const lx = centerX - textMetrics.width / 2 - 1\n const ly = labelY - textMetrics.actualBoundingBoxAscent - 1\n const lw = textMetrics.width + 2\n const lh = textMetrics.actualBoundingBoxAscent + textMetrics.actualBoundingBoxDescent + 2\n if (config.labelBackground) {\n ctx.fillStyle = config.labelBackground\n ctx.fillRect(lx, ly, lw, lh)\n ctx.fillStyle = config.labelColor ?? getColorForFeature(feature, config)\n } else {\n ctx.clearRect(lx, ly, lw, lh)\n }\n\n if (transform) {\n ctx.save()\n ctx.translate(centerX, labelY)\n ctx.rotate(Math.PI / 4)\n ctx.fillText(name, 0, 0)\n ctx.restore()\n } else {\n ctx.textAlign = 'center'\n ctx.fillText(name, centerX, labelY)\n }\n }\n } finally {\n ctx.restore()\n }\n}\n\nfunction getColorForFeature(feature: AnnotationFeature, config: AnnotationRenderConfig): string {\n if (feature.color) return feature.color\n if (config.altColor && feature.strand === '-') {\n return config.altColor\n }\n return config.color\n}\n\nfunction getUtrColorForFeature(feature: AnnotationFeature, config: AnnotationRenderConfig): string {\n if (feature.strand === '-') {\n return config.altUtrColor ?? config.utrColor ?? getColorForFeature(feature, config)\n }\n return config.utrColor ?? config.color\n}\n\n/**\n * Render a set of annotation features onto a canvas context.\n *\n * Features should already have `.row` assigned (via `pack()`).\n * The canvas should be sized and cleared before calling this.\n */\nexport function renderAnnotationTrack(\n ctx: CanvasRenderingContext2D,\n features: AnnotationFeature[],\n config: AnnotationRenderConfig,\n rc: RenderContext,\n): void {\n const rowLastLabelX: Record<number, number> = {}\n\n for (const feature of features) {\n if (feature.row === undefined) continue\n\n // Skip features entirely outside the viewport\n const pxEnd = (feature.end - rc.bpStart) / rc.bpPerPixel\n const pxStart = (feature.start - rc.bpStart) / rc.bpPerPixel\n if (pxEnd < 0 || pxStart > rc.pixelWidth) continue\n\n renderSingleFeature(ctx, feature, config, rc, rowLastLabelX)\n }\n}\n","/**\n * Canvas manager for rendering annotation features (gene, BED, GFF, peaks).\n *\n * Extends BaseTrackCanvas — canvas lifecycle (DPR, resize, attach/detach,\n * background) is handled by the base class. This class only implements\n * annotation-specific logic: feature packing, height computation, and rendering.\n *\n * Usage:\n * const canvas = document.createElement('canvas')\n * const track = new AnnotationTrackCanvas(canvas, { locus, features })\n * track.attachTo(containerDiv)\n */\n\nimport type {AnnotationFeature, AnnotationRenderConfig, DisplayMode, Locus, RenderContext, AnnotationTrackSessionConfig, AnnotationSessionOverrides, HitTestResult, PopupDataItem, AxisInfo, ContextMenuItem} from '../../types'\nimport type {CanvasProvider} from '../../canvasProvider'\nimport type {WorkerProvider} from '../../workerProvider'\nimport type {RenderTheme} from '../../themes/renderTheme'\nimport {resolveTheme, resolveAnnotationConfig} from '../../themes/renderTheme'\nimport {BaseTrackCanvas} from '../baseTrackCanvas'\nimport {packFeatures} from '../../pack'\nimport {renderAnnotationTrack} from './annotationRenderer'\n\n// Re-export Locus for backwards compatibility (docs-site imports it from here)\nexport type {Locus} from '../../types'\n\nexport interface AnnotationTrackCanvasOptions {\n locus: Locus\n features: AnnotationFeature[]\n /** Per-track config overrides. Applied after theme-derived defaults. */\n config?: Partial<AnnotationRenderConfig>\n /** Unified render theme. Palette drives default colors/fonts. */\n theme?: Partial<RenderTheme>\n /** Fixed pixel height. If not set, computed from row count. */\n height?: number\n /** Background color. Default: palette.background. */\n background?: string\n /** Canvas provider for environment abstraction. Default: DOMCanvasProvider. */\n canvasProvider?: CanvasProvider\n /** Worker provider for offloading CPU-intensive tasks (packing). */\n workerProvider?: WorkerProvider\n /** Track name for axis label. */\n name?: string\n}\n\nexport class AnnotationTrackCanvas extends BaseTrackCanvas<AnnotationRenderConfig> {\n private features: AnnotationFeature[]\n private fixedHeight: number | undefined\n private background: string\n private _name: string | undefined\n private workerProvider?: WorkerProvider\n\n /** Most recently packed features, available after render(). */\n private packedFeatures: AnnotationFeature[] = []\n /** Whether packedFeatures was pre-computed by async worker (skip sync pack in computeHeight). */\n private packedReady = false\n\n readonly type = 'annotation'\n\n constructor(canvas: HTMLCanvasElement, options: AnnotationTrackCanvasOptions) {\n const theme = resolveTheme(options.theme)\n const config = resolveAnnotationConfig(theme, options.config)\n super(\n canvas,\n options.locus,\n config,\n options.canvasProvider,\n )\n this.features = options.features\n this.fixedHeight = options.height\n this.background = options.background ?? theme.palette.background\n this._name = options.name\n this.workerProvider = options.workerProvider\n }\n\n /** Update features and re-render. Dispatches async pack when workerProvider is set. */\n setFeatures(features: AnnotationFeature[]): void {\n this.features = features\n if (this.workerProvider) {\n // Deep-copy for worker, then render when done\n const copies = features.map(f => ({...f}))\n this.workerProvider.execute({task: 'pack', features: copies})\n .then(packed => {\n this.packedFeatures = packed\n this.packedReady = true\n this.render()\n })\n .catch(() => {\n // Fallback: render will use synchronous packing\n this.packedReady = false\n this.render()\n })\n } else {\n this.packedReady = false\n this.render()\n }\n }\n\n protected computeHeight(_width: number): number {\n if (!this.packedReady) {\n // Synchronous fallback: deep-copy features so pack() doesn't mutate the source array\n this.packedFeatures = this.features.map(f => ({...f}))\n packFeatures(this.packedFeatures)\n }\n\n const maxRow = this.packedFeatures.reduce((max, f) => Math.max(max, f.row ?? 0), 0)\n const rowHeight = this.config.displayMode === 'SQUISHED'\n ? this.config.squishedRowHeight\n : this.config.expandedRowHeight\n return this.fixedHeight ?? (this.config.margin * 2 + (maxRow + 1) * rowHeight + 10)\n }\n\n protected getBackground(): string {\n return this.background\n }\n\n protected doRender(ctx: CanvasRenderingContext2D, _width: number, _height: number, rc: RenderContext): void {\n renderAnnotationTrack(ctx, this.packedFeatures, this.config, rc)\n }\n\n getAxisInfo(): AxisInfo | undefined {\n return this._name ? {label: this._name} : undefined\n }\n\n override getContextMenuItems(_x: number, _y: number): ContextMenuItem[] {\n const modes: DisplayMode[] = ['EXPANDED', 'SQUISHED', 'COLLAPSED']\n return [{\n label: 'Display mode',\n children: modes.map(mode => ({\n label: mode.charAt(0) + mode.slice(1).toLowerCase(),\n type: 'checkbox' as const,\n checked: this._config.displayMode === mode,\n action: () => this.setConfig({displayMode: mode}),\n })),\n }]\n }\n\n override hitTest(x: number, y: number): HitTestResult<AnnotationFeature>[] {\n if (this.packedFeatures.length === 0) return []\n\n const width = this._canvas.clientWidth\n if (width === 0) return []\n\n const bpPerPixel = (this._locus.end - this._locus.start) / width\n const genomicPos = this._locus.start + x * bpPerPixel\n\n const rowHeight = this._config.displayMode === 'SQUISHED'\n ? this._config.squishedRowHeight\n : this._config.expandedRowHeight\n const row = Math.floor((y - this._config.margin) / rowHeight)\n if (row < 0) return []\n\n const results: HitTestResult<AnnotationFeature>[] = []\n for (const f of this.packedFeatures) {\n if (f.row !== row) continue\n if (genomicPos < f.start || genomicPos > f.end) continue\n results.push({feature: f, popupData: annotationPopupData(f)})\n }\n return results\n }\n\n setTheme(theme: RenderTheme): void {\n this._config = resolveAnnotationConfig(theme)\n this.background = theme.palette.background\n this.render()\n }\n\n serializeConfig(theme: RenderTheme): AnnotationTrackSessionConfig {\n const defaults = resolveAnnotationConfig(theme)\n const overrides: AnnotationSessionOverrides = {}\n let hasOverrides = false\n\n const keys = Object.keys(this.config) as (keyof AnnotationRenderConfig)[]\n for (const key of keys) {\n const val = this.config[key]\n const def = defaults[key]\n if (val !== def && val !== undefined) {\n ;(overrides as Record<string, unknown>)[key] = val\n hasOverrides = true\n }\n }\n\n return {\n type: 'annotation',\n config: hasOverrides ? overrides : undefined,\n }\n }\n}\n\nfunction annotationPopupData(f: AnnotationFeature): PopupDataItem[] {\n const items: PopupDataItem[] = []\n if (f.name) items.push({name: 'Name', value: f.name})\n if (f.id) items.push({name: 'ID', value: f.id})\n if (f.chr) items.push({name: 'Chr', value: f.chr})\n items.push({name: 'Start', value: f.start.toLocaleString()})\n items.push({name: 'End', value: f.end.toLocaleString()})\n if (f.strand) items.push({name: 'Strand', value: f.strand})\n if (f.cdStart != null && f.cdEnd != null && f.cdStart !== f.cdEnd) {\n items.push({name: 'CDS', value: `${f.cdStart.toLocaleString()}-${f.cdEnd.toLocaleString()}`})\n }\n if (f.exons) items.push({name: 'Exons', value: f.exons.length})\n return items\n}\n","/**\n * Generic feature packing — greedy interval scheduling for row assignment.\n *\n * Assigns a `row` number to each feature so that no two features in the same\n * row overlap. Features are sorted by start position, then placed in the first\n * available row. This is used by every annotation-style track (genes, BED, GFF,\n * VCF, interactions, etc.).\n *\n * Mirrors igv.js featurePacker.ts (js/feature/featurePacker.ts) which uses the\n * same greedy algorithm with a generic {start, end, row} interface.\n *\n * @example\n * ```ts\n * const features = [{start: 100, end: 200}, {start: 150, end: 300}, {start: 250, end: 400}]\n * packFeatures(features)\n * // features[0].row === 0, features[1].row === 1, features[2].row === 0\n * ```\n */\n\n/**\n * Minimal interface for packable features.\n * Any object with start/end coordinates and a mutable row field.\n * Mirrors igv.js PackableFeature (js/feature/featurePacker.ts).\n */\nexport interface Packable {\n start: number\n end: number\n row?: number\n}\n\n/**\n * Assign row numbers to features using greedy interval scheduling.\n * Features are sorted by start position, then placed in the first row\n * where they don't overlap a previously placed feature.\n *\n * Mutates features in place by setting `.row`.\n *\n * @param features - Array of features to pack. Must have `start` and `end`.\n * @param maxRows - Maximum number of rows. Features beyond this limit are\n * still assigned rows but pile up. Default: unlimited.\n * Matches igv.js behavior in featurePacker.ts and featureTrack.ts (default maxRows: 1000).\n */\nexport function packFeatures<T extends Packable>(features: T[], maxRows?: number): void {\n const limit = maxRows ?? Number.MAX_SAFE_INTEGER\n const rowEnds: number[] = [-1000]\n\n features.sort((a, b) => a.start - b.start)\n\n for (const feature of features) {\n const len = Math.min(rowEnds.length, limit)\n let placed = false\n for (let r = 0; r < len; r++) {\n if (feature.start >= rowEnds[r]) {\n feature.row = r\n rowEnds[r] = feature.end\n placed = true\n break\n }\n }\n if (!placed) {\n feature.row = rowEnds.length\n rowEnds.push(feature.end)\n }\n }\n}\n","/**\n * Stateless ruler track renderer.\n *\n * Draws genomic coordinate tick marks and labels onto a canvas context.\n * Ported from js/rulerTrack.ts but with no igv.js dependencies.\n */\n\nimport type {RulerRenderConfig, RenderContext} from '../../types'\nimport type {CumulativeOffsets} from '../../genome/chromSizes'\n\ninterface Tick {\n majorTick: number\n majorUnit: string\n unitMultiplier: number\n}\n\n/** Compute tick spacing based on visible base pair length. */\nfunction findSpacing(bpLength: number): Tick {\n if (bpLength < 10) {\n return {majorTick: 1, majorUnit: 'bp', unitMultiplier: 1}\n }\n\n const nZeroes = Math.floor(Math.log10(bpLength))\n\n let majorUnit = 'bp'\n let unitMultiplier = 1\n if (nZeroes > 9) {\n majorUnit = 'gb'\n unitMultiplier = 1e9\n } else if (nZeroes > 6) {\n majorUnit = 'mb'\n unitMultiplier = 1e6\n } else if (nZeroes > 3) {\n majorUnit = 'kb'\n unitMultiplier = 1e3\n }\n\n const nMajorTicks = bpLength / Math.pow(10, nZeroes - 1)\n const threshold = 3 * 25\n\n const majorTick = nMajorTicks < threshold\n ? Math.pow(10, nZeroes - 1)\n : Math.pow(10, nZeroes) / 2\n\n return {majorTick, majorUnit, unitMultiplier}\n}\n\n/** Format a number with thousands separators. */\nfunction formatNumber(n: number): string {\n return Math.floor(n).toLocaleString('en-US')\n}\n\n/**\n * Render a genomic coordinate ruler onto a canvas context.\n *\n * Stateless — all state is passed as parameters.\n * Draws tick marks, labels with SI-prefix units, and a baseline.\n */\nexport function renderRulerTrack(\n ctx: CanvasRenderingContext2D,\n config: RulerRenderConfig,\n rc: RenderContext,\n): void {\n const height = config.height\n const tickHeight = 6\n const shim = 2\n\n const bpLength = Math.floor(rc.pixelWidth * rc.bpPerPixel)\n const tick = findSpacing(bpLength)\n\n let nTick = Math.floor(rc.bpStart / tick.majorTick) - 1\n\n // Compute tick pixel delta and label width for overlap avoidance\n const getBP = (n: number) => Math.floor(n * tick.majorTick)\n const getX = (bp: number) => Math.round((bp - 1 - rc.bpStart + 0.5) / rc.bpPerPixel)\n\n const tickDelta = getX(getBP(1 + nTick)) - getX(getBP(nTick))\n const sampleLabel = `${formatNumber(getBP(nTick) / tick.unitMultiplier)} ${tick.majorUnit}`\n const labelLength = Math.floor(ctx.measureText(sampleLabel).width)\n const labelLengthShim = 0.25 * labelLength\n\n ctx.font = config.font\n ctx.fillStyle = config.labelColor\n ctx.strokeStyle = config.tickColor\n ctx.lineWidth = 1\n\n let accumulatedTickDelta = tickDelta\n let xTick: number\n\n do {\n const bp = getBP(nTick)\n const rulerLabel = `${formatNumber(bp / tick.unitMultiplier)} ${tick.majorUnit}`\n\n xTick = getX(bp)\n const labelWidth = ctx.measureText(rulerLabel).width\n const xLabel = Math.round(xTick - labelWidth / 2)\n\n // Draw label if it fits without overlapping\n if (xLabel > 0 && (labelLengthShim + labelLength) <= accumulatedTickDelta) {\n ctx.fillStyle = config.labelColor\n ctx.fillText(rulerLabel, xLabel, height - (tickHeight / 0.75))\n accumulatedTickDelta = 0\n }\n\n // Major tick\n if (xTick > 0) {\n ctx.beginPath()\n ctx.moveTo(xTick, height - tickHeight)\n ctx.lineTo(xTick, height - shim)\n ctx.stroke()\n }\n\n // Minor tick (halfway to next major)\n const nextBP = getBP(1 + nTick)\n const nextX = getX(nextBP)\n const minorX = xTick + (nextX - xTick) / 2\n if (minorX > 0 && minorX < rc.pixelWidth) {\n ctx.beginPath()\n ctx.moveTo(minorX, height - tickHeight)\n ctx.lineTo(minorX, height - shim)\n ctx.stroke()\n }\n\n ++nTick\n accumulatedTickDelta += tickDelta\n } while (xTick < rc.pixelWidth)\n\n // Baseline\n ctx.strokeStyle = config.baselineColor\n ctx.beginPath()\n ctx.moveTo(0, height - shim)\n ctx.lineTo(rc.pixelWidth, height - shim)\n ctx.stroke()\n}\n\n/** Whole genome context needed by the WG ruler renderer. */\nexport interface WholeGenomeRulerContext {\n cumulativeOffsets: CumulativeOffsets\n chromSizes: Record<string, number>\n}\n\n/**\n * Render a whole genome ruler showing chromosome rectangles with labels and dividers.\n * Port of js/rulerTrack.ts drawWholeGenome() + renderChromosomeRect().\n */\nexport function renderWholeGenomeRuler(\n ctx: CanvasRenderingContext2D,\n config: RulerRenderConfig,\n rc: RenderContext,\n wg: WholeGenomeRulerContext,\n): void {\n const height = config.height\n const {cumulativeOffsets, chromSizes} = wg\n\n // White background\n ctx.fillStyle = config.background ?? 'white'\n ctx.fillRect(0, 0, rc.pixelWidth, height)\n\n ctx.textAlign = 'center'\n ctx.textBaseline = 'middle'\n ctx.font = config.font\n\n for (const name of cumulativeOffsets.chromosomeNames) {\n const xBP = cumulativeOffsets.offsets[name]\n const wBP = chromSizes[name]\n if (xBP === undefined || wBP === undefined) continue\n\n const x = Math.round((xBP - rc.bpStart) / rc.bpPerPixel)\n const w = Math.round(wBP / rc.bpPerPixel)\n\n // Vertical divider on right edge\n ctx.strokeStyle = '#bfbfbf'\n ctx.lineWidth = 1\n ctx.beginPath()\n ctx.moveTo(x + w, 0)\n ctx.lineTo(x + w, height)\n ctx.stroke()\n\n // Shortened label (remove \"chr\" prefix)\n const shortName = name.startsWith('chr') ? name.substring(3) : name\n const labelWidth = ctx.measureText(shortName).width\n if (w > labelWidth) {\n ctx.fillStyle = '#444444'\n ctx.fillText(shortName, x + w / 2, height / 2)\n }\n }\n}\n","/**\n * Canvas manager for rendering a genomic coordinate ruler.\n *\n * Extends BaseTrackCanvas — canvas lifecycle is handled by the base class.\n * This class only implements ruler-specific rendering.\n *\n * Usage:\n * const canvas = document.createElement('canvas')\n * const ruler = new RulerTrackCanvas(canvas, { locus })\n * ruler.attachTo(containerDiv)\n */\n\nimport type {Locus, RulerRenderConfig, RenderContext, RulerTrackSessionConfig, RulerSessionOverrides} from '../../types'\nimport type {CanvasProvider} from '../../canvasProvider'\nimport type {RenderTheme} from '../../themes/renderTheme'\nimport type {CumulativeOffsets, ChromSizes} from '../../genome/chromSizes'\nimport {resolveTheme, resolveRulerConfig} from '../../themes/renderTheme'\nimport {isWholeGenomeView} from '../../locusUtils'\nimport {BaseTrackCanvas} from '../baseTrackCanvas'\nimport {renderRulerTrack, renderWholeGenomeRuler} from './rulerRenderer'\n\nexport interface RulerTrackCanvasOptions {\n locus: Locus\n /** Per-track config overrides. Applied after theme-derived defaults. */\n config?: Partial<RulerRenderConfig>\n /** Unified render theme. Palette drives default colors/fonts. */\n theme?: Partial<RenderTheme>\n /** Canvas provider for environment abstraction. Default: DOMCanvasProvider. */\n canvasProvider?: CanvasProvider\n /** Cumulative offsets for whole genome view. */\n cumulativeOffsets?: CumulativeOffsets\n /** Chromosome sizes for whole genome view. */\n chromSizes?: ChromSizes\n}\n\nexport class RulerTrackCanvas extends BaseTrackCanvas<RulerRenderConfig> {\n readonly type = 'ruler'\n private _cumulativeOffsets?: CumulativeOffsets\n private _chromSizes?: ChromSizes\n\n constructor(canvas: HTMLCanvasElement, options: RulerTrackCanvasOptions) {\n const theme = resolveTheme(options.theme)\n const config = resolveRulerConfig(theme, options.config)\n super(\n canvas,\n options.locus,\n config,\n options.canvasProvider,\n )\n this._cumulativeOffsets = options.cumulativeOffsets\n this._chromSizes = options.chromSizes\n }\n\n /** Set cumulative offsets for whole genome view (called by browser). */\n setCumulativeOffsets(offsets: CumulativeOffsets): void {\n this._cumulativeOffsets = offsets\n }\n\n /** Set chromosome sizes for whole genome view (called by browser). */\n setChromSizes(sizes: ChromSizes): void {\n this._chromSizes = sizes\n }\n\n protected computeHeight(_width: number): number {\n return this.config.height\n }\n\n protected getBackground(): string {\n return this.config.background\n }\n\n protected doRender(ctx: CanvasRenderingContext2D, _width: number, _height: number, rc: RenderContext): void {\n if (isWholeGenomeView(this._locus) && this._cumulativeOffsets && this._chromSizes) {\n renderWholeGenomeRuler(ctx, this.config, rc, {\n cumulativeOffsets: this._cumulativeOffsets,\n chromSizes: this._chromSizes,\n })\n } else {\n renderRulerTrack(ctx, this.config, rc)\n }\n }\n\n setTheme(theme: RenderTheme): void {\n this._config = resolveRulerConfig(theme)\n this.render()\n }\n\n serializeConfig(theme: RenderTheme): RulerTrackSessionConfig {\n const defaults = resolveRulerConfig(theme)\n const overrides: RulerSessionOverrides = {}\n let hasOverrides = false\n\n const keys = Object.keys(this.config) as (keyof RulerRenderConfig)[]\n for (const key of keys) {\n const val = this.config[key]\n const def = defaults[key]\n if (val !== def && val !== undefined) {\n ;(overrides as Record<string, unknown>)[key] = val\n hasOverrides = true\n }\n }\n\n return {\n type: 'ruler',\n config: hasOverrides ? overrides : undefined,\n }\n }\n}\n","/**\n * DNA/RNA sequence utilities — complement, reverse-complement, and codon translation.\n *\n * Layer 1 (Data + Layout): Pure functions, no DOM, no canvas. Can run in Node.js,\n * workers, or any environment.\n *\n * Ported from:\n * - js/util/sequenceUtils.ts (complement/reverseComplement)\n * - js/util/translationDict.ts (codon table)\n * - js/sequenceTrack.ts (complement table with IUPAC codes, translateSequence)\n */\n\n// ─── Complement tables ────────────────────────────────────────────────────────\n\n/**\n * Base-pair complement mapping including all IUPAC ambiguity codes.\n *\n * Mirrors igv.js complement table in js/sequenceTrack.ts (t1/t2 arrays)\n * and js/util/sequenceUtils.ts (pairs array). We merge both into a single\n * bidirectional Map for O(1) lookup.\n */\nconst complements: ReadonlyMap<string, string> = (() => {\n const map = new Map<string, string>()\n // Standard + IUPAC pairs from js/sequenceTrack.ts\n const t1 = ['A', 'G', 'C', 'T', 'Y', 'R', 'W', 'S', 'K', 'M', 'D', 'V', 'H', 'B', 'N', 'X']\n const t2 = ['T', 'C', 'G', 'A', 'R', 'Y', 'W', 'S', 'M', 'K', 'H', 'B', 'D', 'V', 'N', 'X']\n for (let i = 0; i < t1.length; i++) {\n map.set(t1[i], t2[i])\n map.set(t1[i].toLowerCase(), t2[i].toLowerCase())\n }\n return map\n})()\n\n/** Return the complement of a single base (identity if unknown). */\nexport function complementBase(base: string): string {\n return complements.get(base) ?? base\n}\n\n/** Return the complement of a DNA sequence (no reversal). */\nexport function complementSequence(sequence: string): string {\n let comp = ''\n for (const base of sequence) {\n comp += complements.get(base) ?? base\n }\n return comp\n}\n\n/** Return the reverse complement of a DNA sequence. */\nexport function reverseComplementSequence(sequence: string): string {\n let comp = ''\n let idx = sequence.length\n while (idx-- > 0) {\n const base = sequence[idx]\n comp += complements.get(base) ?? base\n }\n return comp\n}\n\n// ─── Codon translation ───────────────────────────────────────────────────────\n\n/**\n * Standard genetic code: 64 codons → single-letter amino acid or 'STOP'.\n *\n * Direct port of js/util/translationDict.ts.\n */\nexport const translationDict: Readonly<Record<string, string>> = {\n 'TTT': 'F', 'TTC': 'F',\n 'TTA': 'L', 'TTG': 'L', 'CTT': 'L', 'CTC': 'L', 'CTA': 'L', 'CTG': 'L',\n 'ATT': 'I', 'ATC': 'I', 'ATA': 'I',\n 'ATG': 'M',\n 'GTT': 'V', 'GTC': 'V', 'GTA': 'V', 'GTG': 'V',\n 'TCT': 'S', 'TCC': 'S', 'TCA': 'S', 'TCG': 'S', 'AGT': 'S', 'AGC': 'S',\n 'CCT': 'P', 'CCC': 'P', 'CCA': 'P', 'CCG': 'P',\n 'ACT': 'T', 'ACC': 'T', 'ACA': 'T', 'ACG': 'T',\n 'GCT': 'A', 'GCC': 'A', 'GCA': 'A', 'GCG': 'A',\n 'TAT': 'Y', 'TAC': 'Y',\n 'TAA': 'STOP', 'TAG': 'STOP', 'TGA': 'STOP',\n 'CAT': 'H', 'CAC': 'H',\n 'CAA': 'Q', 'CAG': 'Q',\n 'AAT': 'N', 'AAC': 'N',\n 'AAA': 'K', 'AAG': 'K',\n 'GAT': 'D', 'GAC': 'D',\n 'GAA': 'E', 'GAG': 'E',\n 'TGT': 'C', 'TGC': 'C',\n 'TGG': 'W',\n 'CGT': 'R', 'CGC': 'R', 'CGA': 'R', 'CGG': 'R', 'AGA': 'R', 'AGG': 'R',\n 'GGT': 'G', 'GGC': 'G', 'GGA': 'G', 'GGG': 'G',\n}\n\n/** A single codon translation result. */\nexport interface CodonTranslation {\n /** The 3-base codon string. */\n codons: string\n /** Single-letter amino acid code, 'STOP', or '' for unknown codons. */\n aminoA: string\n}\n\n/**\n * Translate a DNA sequence into three reading frames.\n *\n * Returns an array of 3 frames (offset 0, 1, 2). Each frame is an array\n * of codon translations.\n *\n * When `reversed` is true, each individual codon is reversed before lookup\n * (matching igv.js SequenceTrack.translateSequence behavior — this is NOT\n * the same as reverse-complement; the complement is applied separately\n * to the display sequence).\n *\n * Port of js/sequenceTrack.ts translateSequence().\n */\nexport function translateSequence(\n seq: string,\n reversed = false,\n): CodonTranslation[][] {\n const threeFrame: CodonTranslation[][] = [[], [], []]\n\n for (let fNum = 0; fNum < 3; fNum++) {\n let idx = fNum\n while ((seq.length - idx) >= 3) {\n let codon = seq.slice(idx, idx + 3)\n if (reversed) {\n codon = codon.split('').reverse().join('')\n }\n const aa = translationDict[codon.toUpperCase()] ?? ''\n threeFrame[fNum].push({codons: codon, aminoA: aa})\n idx += 3\n }\n }\n\n return threeFrame\n}\n","/**\n * Pure sequence track renderer — stateless, no DOM, no side effects.\n *\n * Layer 2 (Track Canvas + Themed Renderers): Takes a CanvasRenderingContext2D\n * and draws. All rendering decisions are driven by the config and render context.\n *\n * Port of js/sequenceTrack.ts draw() method with full feature parity:\n * - Base rendering as colored rectangles (zoomed out) or text (zoomed in)\n * - Reverse complement display\n * - Three-frame amino acid translation with START/STOP highlighting\n *\n * The BP_PER_PIXEL_THRESHOLD (1/10 = 0.1) controls text vs block rendering,\n * matching igv.js exactly.\n */\n\nimport type {RenderContext, SequenceRenderConfig} from '../../types'\nimport {complementBase, translateSequence} from '../../sequence/sequenceUtils'\n\n/** Threshold: above this, bases render as colored blocks; below, as text. */\nconst BP_PER_PIXEL_THRESHOLD = 1 / 10\n\n/** Sequence data passed from the data lifecycle to the renderer. */\nexport interface SequenceFeature {\n /** Genomic position of the first base in the sequence string. */\n bpStart: number\n /** The nucleotide sequence string. */\n sequence: string\n}\n\n/**\n * Resolve the fill color for a single base character.\n *\n * Resolution order matches igv.js SequenceTrack.fillColor():\n * 1. Track override color (if set)\n * 2. Nucleotide color map (for DNA)\n * 3. Non-DNA fallback color (for RNA/protein)\n */\nfunction fillColor(\n base: string,\n config: SequenceRenderConfig,\n): string {\n if (config.color) return config.color\n if (config.sequenceType === 'dna') {\n return config.nucleotideColors[base.toUpperCase()] ?? '#808080'\n }\n return config.nonDnaColor\n}\n\n/**\n * Render the sequence track onto a canvas context.\n *\n * Pure function — no state, no side effects, no DOM. Matches igv.js\n * SequenceTrack.draw() (js/sequenceTrack.ts) with exact feature parity.\n *\n * @param ctx - Canvas 2D rendering context (already DPR-scaled by BaseTrackCanvas)\n * @param seqFeature - The sequence data (bpStart + sequence string), or null if no data\n * @param config - Full resolved SequenceRenderConfig\n * @param rc - Render context (bpStart, bpPerPixel, pixelWidth)\n */\nexport function renderSequenceTrack(\n ctx: CanvasRenderingContext2D,\n seqFeature: SequenceFeature | null,\n config: SequenceRenderConfig,\n rc: RenderContext,\n): void {\n if (!seqFeature || !seqFeature.sequence) return\n\n let sequence = seqFeature.sequence\n\n // Apply complement for reverse strand display (matching igv.js)\n if (config.reversed) {\n sequence = sequence.split('').map(c => complementBase(c)).join('')\n }\n\n const sequenceBpStart = seqFeature.bpStart\n const bpEnd = 1 + rc.bpStart + (rc.pixelWidth * rc.bpPerPixel)\n const {sequenceHeight, frameBorder} = config\n\n // ─── Render nucleotide bases ──────────────────────────────────────────\n for (let bp = Math.floor(rc.bpStart); bp <= bpEnd; bp++) {\n const seqIdx = Math.floor(bp - sequenceBpStart)\n if (seqIdx < 0 || seqIdx >= sequence.length) continue\n\n const offsetBP = bp - rc.bpStart\n const aPixel = offsetBP / rc.bpPerPixel\n const pixelWidth = 1 / rc.bpPerPixel\n const baseLetter = sequence[seqIdx]\n const color = fillColor(baseLetter, config)\n\n if (rc.bpPerPixel > BP_PER_PIXEL_THRESHOLD) {\n // Block mode: colored rectangles (no text)\n ctx.fillStyle = color\n ctx.fillRect(aPixel, frameBorder, pixelWidth, sequenceHeight - frameBorder)\n } else {\n // Text mode: centered base letter\n const textWidth = ctx.measureText(baseLetter).width\n const textPixel = aPixel + 0.5 * (pixelWidth - textWidth)\n ctx.strokeStyle = color\n ctx.strokeText(baseLetter, textPixel, sequenceHeight)\n }\n }\n\n // ─── Three-frame translation ──────────────────────────────────────────\n // Frame backgrounds render at any zoom where sequence is visible (matching igv.js).\n // Text labels only render at high zoom (bpPerPixel <= 0.1).\n if (config.frameTranslate) {\n let y = sequenceHeight + 2 * frameBorder\n const translatedSequence = translateSequence(sequence, config.reversed)\n const radius = config.codonBorderRadius\n\n for (let fNum = 0; fNum < translatedSequence.length; fNum++) {\n const aaSequence = translatedSequence[fNum]\n\n for (let idx = 0; idx < aaSequence.length; idx++) {\n let bgColor = idx % 2 === 0 ? config.frameColor1 : config.frameColor2\n const cv = aaSequence[idx]\n\n const bpPos = sequenceBpStart + fNum + (idx * 3)\n const bpOffset = bpPos - rc.bpStart\n const p0 = Math.floor(bpOffset / rc.bpPerPixel)\n const p1 = Math.floor((bpOffset + 3) / rc.bpPerPixel)\n const pc = Math.round((p0 + p1) / 2)\n\n if (p1 < 0) continue // off left edge\n if (p0 > rc.pixelWidth) break // off right edge\n\n let aaLabel = cv.aminoA\n let isSpecialCodon = false\n if (cv.aminoA.indexOf('STOP') > -1) {\n bgColor = config.stopCodonColor\n aaLabel = 'STOP'\n isSpecialCodon = true\n } else if (cv.aminoA === 'M') {\n bgColor = config.startCodonColor\n aaLabel = 'START'\n isSpecialCodon = true\n }\n\n // Frame background (with optional rounded corners for start/stop codons)\n ctx.fillStyle = bgColor\n if (isSpecialCodon && radius > 0) {\n ctx.beginPath()\n ctx.roundRect(p0, y, p1 - p0, config.frameHeight, radius)\n ctx.fill()\n } else {\n ctx.fillRect(p0, y, p1 - p0, config.frameHeight)\n }\n\n // Amino acid label (only at high zoom)\n // Always use fillText for translation labels — strokeText produces\n // hollow outlines that are hard to read for multi-character text.\n if (rc.bpPerPixel <= BP_PER_PIXEL_THRESHOLD) {\n ctx.font = config.frameFont\n const labelWidth = ctx.measureText(aaLabel).width\n const labelColor = isSpecialCodon && config.codonLabelColor\n ? config.codonLabelColor\n : config.frameLabelColor\n ctx.fillStyle = labelColor\n ctx.fillText(aaLabel, pc - labelWidth / 2, y + 15)\n }\n }\n y += config.frameHeight + frameBorder\n }\n }\n}\n","/**\n * Sequence track canvas — extends BaseTrackCanvas for DNA/RNA sequence display.\n *\n * Layer 2 (Track Canvas): Manages canvas lifecycle, DPR scaling, config state,\n * and delegates rendering to the pure sequenceRenderer.\n *\n * Port of js/sequenceTrack.ts with full feature parity:\n * - DNA/RNA/protein sequence rendering\n * - Reverse complement toggle\n * - Three-frame amino acid translation toggle\n * - Dynamic height (25px default, 115px with translation)\n * - Context menu items (strand toggle, translation toggle)\n * - Visibility window enforcement (bpPerPixel threshold of 10)\n * - Session serialization\n *\n * Data is provided via the standard DataSource lifecycle — the browser fetches\n * sequence through a SequenceDataSource and pushes it via setFeatures().\n * Also supports direct setSequence() for standalone usage.\n */\n\nimport {BaseTrackCanvas} from '../baseTrackCanvas'\nimport type {\n Locus, RenderContext, SequenceRenderConfig, TrackSessionConfig,\n ContextMenuItem, SequenceTrackSessionConfig,\n} from '../../types'\nimport type {RenderTheme} from '../../themes/renderTheme'\nimport {resolveSequenceConfig} from '../../themes/renderTheme'\nimport {resolveTheme} from '../../themes/renderTheme'\nimport {renderSequenceTrack} from './sequenceRenderer'\nimport type {SequenceFeature} from './sequenceRenderer'\nimport type {CanvasProvider} from '../../canvasProvider'\n\n/**\n * bpPerPixel threshold above which sequence data is not loaded.\n * Matches igv.js bppSequenceThreshold = 10.\n */\nconst BPP_SEQUENCE_THRESHOLD = 10\n\n/** Options for constructing a SequenceTrackCanvas. */\nexport interface SequenceTrackCanvasOptions {\n locus: Locus\n config?: Partial<SequenceRenderConfig>\n theme?: Partial<RenderTheme>\n canvasProvider?: CanvasProvider\n}\n\nexport class SequenceTrackCanvas extends BaseTrackCanvas<SequenceRenderConfig> {\n readonly type = 'sequence'\n\n private _sequence: SequenceFeature | null = null\n private _theme: RenderTheme\n\n constructor(canvas: HTMLCanvasElement, options: SequenceTrackCanvasOptions) {\n const theme = resolveTheme(options.theme)\n const config = resolveSequenceConfig(theme, options.config)\n super(canvas, options.locus, config, options.canvasProvider)\n this._theme = theme\n\n // The SequenceDataSource handles the bpPerPixel threshold check,\n // returning empty features when zoomed out. The track will simply\n // render nothing in that case (no sequence data).\n }\n\n /**\n * Whether the current viewport is zoomed in enough to fetch/render sequence.\n * Matches igv.js bppSequenceThreshold check in getFeatures().\n */\n shouldFetchSequence(bpPerPixel: number): boolean {\n return bpPerPixel <= BPP_SEQUENCE_THRESHOLD\n }\n\n /**\n * Standard DataSource lifecycle: browser pushes SequenceFeature[] from SequenceDataSource.\n * Takes the first element (single sequence region) or clears if empty (zoomed out).\n */\n setFeatures(features: SequenceFeature[]): void {\n this._sequence = features.length > 0 ? features[0] : null\n this.render()\n }\n\n /** Set the sequence data directly. For standalone usage without a DataSource. */\n setSequence(feature: SequenceFeature | null): void {\n this._sequence = feature\n this.render()\n }\n\n /** Get the current sequence data (for context menu operations). */\n getSequence(): SequenceFeature | null {\n return this._sequence\n }\n\n /** Toggle reverse complement display. */\n toggleReversed(): void {\n this.setConfig({reversed: !this._config.reversed} as Partial<SequenceRenderConfig>)\n }\n\n /** Toggle three-frame translation display. */\n toggleFrameTranslate(): void {\n this.setConfig({frameTranslate: !this._config.frameTranslate} as Partial<SequenceRenderConfig>)\n }\n\n /**\n * Return context menu items for the sequence track.\n *\n * Matches igv.js SequenceTrack.menuItemList() + contextMenuItemList():\n * - Strand toggle (Forward/Reverse)\n * - Translation toggle (Three-frame Translate / Close Translation)\n */\n override getContextMenuItems(_x: number, _y: number): ContextMenuItem[] | undefined {\n const items: ContextMenuItem[] = [\n {\n label: this._config.reversed ? 'Forward' : 'Reverse',\n action: () => this.toggleReversed(),\n },\n {\n label: this._config.frameTranslate ? 'Close Translation' : 'Three-frame Translate',\n action: () => this.toggleFrameTranslate(),\n },\n ]\n return items\n }\n\n // ─── BaseTrackCanvas abstract implementations ─────────────────────────\n\n protected computeHeight(_width: number): number {\n return this._config.frameTranslate\n ? this._config.translatedHeight\n : this._config.defaultHeight\n }\n\n protected getBackground(): string {\n return this._config.background\n }\n\n protected doRender(\n ctx: CanvasRenderingContext2D,\n _width: number,\n _height: number,\n rc: RenderContext,\n ): void {\n renderSequenceTrack(ctx, this._sequence, this._config, rc)\n }\n\n setTheme(theme: RenderTheme): void {\n this._config = resolveSequenceConfig(theme)\n this._theme = theme\n this.render()\n }\n\n serializeConfig(theme: RenderTheme): TrackSessionConfig {\n const defaults = resolveSequenceConfig(theme)\n const overrides: Partial<SequenceRenderConfig> = {}\n\n // Only serialize non-default values\n if (this._config.sequenceType !== defaults.sequenceType) overrides.sequenceType = this._config.sequenceType\n if (this._config.reversed !== defaults.reversed) overrides.reversed = this._config.reversed\n if (this._config.frameTranslate !== defaults.frameTranslate) overrides.frameTranslate = this._config.frameTranslate\n if (this._config.color !== defaults.color) overrides.color = this._config.color\n if (this._config.background !== defaults.background) overrides.background = this._config.background\n\n const result: SequenceTrackSessionConfig = {type: 'sequence'}\n if (Object.keys(overrides).length > 0) {\n result.config = overrides\n }\n return result\n }\n}\n","/**\n * Binary data parser for reading structured binary data from a DataView.\n * Port of js/binary.ts, simplified for BigWig reading (no VPointer).\n */\nexport class BinaryParser {\n littleEndian: boolean\n position: number\n readonly view: DataView\n readonly length: number\n\n constructor(dataView: DataView, littleEndian: boolean = true) {\n this.littleEndian = littleEndian\n this.position = 0\n this.view = dataView\n this.length = dataView.byteLength\n }\n\n setPosition(position: number): void {\n this.position = position\n }\n\n available(): number {\n return this.length - this.position\n }\n\n remLength(): number {\n return this.length - this.position\n }\n\n getByte(): number {\n const retValue = this.view.getUint8(this.position)\n this.position++\n return retValue\n }\n\n getShort(): number {\n const retValue = this.view.getInt16(this.position, this.littleEndian)\n this.position += 2\n return retValue\n }\n\n getUShort(): number {\n const retValue = this.view.getUint16(this.position, this.littleEndian)\n this.position += 2\n return retValue\n }\n\n getInt(): number {\n const retValue = this.view.getInt32(this.position, this.littleEndian)\n this.position += 4\n return retValue\n }\n\n getUInt(): number {\n const retValue = this.view.getUint32(this.position, this.littleEndian)\n this.position += 4\n return retValue\n }\n\n getLong(): number {\n const b: number[] = []\n for (let i = 0; i < 8; i++) {\n b[i] = this.view.getUint8(this.position + i)\n }\n\n let value = 0\n if (this.littleEndian) {\n for (let i = 7; i >= 0; i--) {\n value = (value * 256) + b[i]\n }\n } else {\n for (let i = 0; i < 8; i++) {\n value = (value * 256) + b[i]\n }\n }\n this.position += 8\n return value\n }\n\n getString(len?: number): string {\n let s = ''\n let c: number\n while ((c = this.view.getUint8(this.position++)) !== 0) {\n s += String.fromCharCode(c)\n if (len && s.length === len) break\n }\n return s\n }\n\n getFixedLengthString(len: number): string {\n let s = ''\n for (let i = 0; i < len; i++) {\n const c = this.view.getUint8(this.position++)\n if (c > 0) {\n s += String.fromCharCode(c)\n }\n }\n return s\n }\n\n getFloat(): number {\n const retValue = this.view.getFloat32(this.position, this.littleEndian)\n this.position += 4\n return retValue\n }\n\n getDouble(): number {\n const retValue = this.view.getFloat64(this.position, this.littleEndian)\n this.position += 8\n return retValue\n }\n\n skip(n: number): number {\n this.position += n\n return this.position\n }\n}\n","/**\n * BigWig reader — public API.\n *\n * Thin wrapper around @gmod/bbi that preserves the existing public API.\n * All binary parsing, decompression, and zoom level selection is handled\n * by @gmod/bbi internally.\n */\n\nimport {BigWig} from '@gmod/bbi'\nimport {RemoteFile} from 'generic-filehandle2'\nimport type {WigFeature, WindowFunction, Locus} from '../types'\nimport type {WorkerProvider} from '../workerProvider'\nimport type {Feature} from '@gmod/bbi'\n\n// Re-export BinaryParser from its new home for backward compatibility\nexport {BinaryParser} from '../io/binaryParser'\n\nexport interface FetchBigWigOptions {\n /** Resolution in base pairs per pixel. Used to select an appropriate zoom level. */\n bpPerPixel?: number\n /** Aggregation function for zoom-level data. Default: 'mean'. */\n windowFunction?: WindowFunction\n /** @deprecated Worker dispatch is handled internally by @gmod/bbi. */\n workerProvider?: WorkerProvider\n /** AbortSignal for cancelling in-flight HTTP requests. */\n signal?: AbortSignal\n}\n\n/** Header metadata from a BigWig file. */\nexport interface BigWigHeader {\n bwVersion: number\n nZoomLevels: number\n chromTreeOffset: number\n fullDataOffset: number\n fullIndexOffset: number\n fieldCount: number\n definedFieldCount: number\n autoSqlOffset: number\n totalSummaryOffset: number\n uncompressBuffSize: number\n extensionOffset: number\n}\n\n/** Summary statistics for the entire BigWig file. */\nexport interface BigWigTotalSummary {\n basesCovered: number\n minVal: number\n maxVal: number\n sumData: number\n sumSquares: number\n mean: number\n stddev: number\n}\n\n// ─── Internal helpers ─────────────────────────────────────────────────────────\n\n// Cache BigWig instances by URL to reuse parsed headers and trees\nconst readerCache = new Map<string, BigWig>()\n\nfunction getGmodReader(url: string): BigWig {\n let reader = readerCache.get(url)\n if (!reader) {\n reader = new BigWig({filehandle: new RemoteFile(url)})\n readerCache.set(url, reader)\n }\n return reader\n}\n\n/**\n * Convert @gmod/bbi Feature to our WigFeature, applying windowFunction\n * for summary data.\n */\nfunction featureToWig(f: Feature, chr: string, wf: WindowFunction): WigFeature | undefined {\n if (f.score === undefined && !f.summary) return undefined\n\n let value: number\n if (f.summary) {\n switch (wf) {\n case 'min': value = f.minScore ?? f.score ?? 0; break\n case 'max': value = f.maxScore ?? f.score ?? 0; break\n case 'mean':\n default: value = f.score ?? 0; break\n }\n } else {\n value = f.score ?? 0\n }\n\n return {chr, start: f.start, end: f.end, value}\n}\n\n// ─── Public API ───────────────────────────────────────────────────────────────\n\n/**\n * Thin wrapper around @gmod/bbi BigWig that preserves the legacy API.\n */\nexport class BigWigReader {\n private readonly bw: BigWig\n\n constructor(url: string, _workerProvider?: WorkerProvider) {\n this.bw = getGmodReader(url)\n }\n\n async loadHeader(signal?: AbortSignal): Promise<BigWigHeader> {\n const h = await this.bw.getHeader({signal})\n return {\n bwVersion: h.version,\n nZoomLevels: h.numZoomLevels,\n chromTreeOffset: h.chromosomeTreeOffset,\n fullDataOffset: h.unzoomedDataOffset,\n fullIndexOffset: h.unzoomedIndexOffset,\n fieldCount: h.fieldCount,\n definedFieldCount: h.definedFieldCount,\n autoSqlOffset: h.asOffset,\n totalSummaryOffset: h.totalSummaryOffset,\n uncompressBuffSize: h.uncompressBufSize,\n extensionOffset: h.extHeaderOffset,\n }\n }\n\n async getTotalSummary(signal?: AbortSignal): Promise<BigWigTotalSummary | undefined> {\n const h = await this.bw.getHeader({signal})\n const s = h.totalSummary\n if (!s) return undefined\n const mean = s.basesCovered > 0 ? s.scoreSum / s.basesCovered : 0\n const variance = s.basesCovered > 0\n ? (s.scoreSumSquares / s.basesCovered) - (mean * mean)\n : 0\n return {\n basesCovered: s.basesCovered,\n minVal: s.scoreMin,\n maxVal: s.scoreMax,\n sumData: s.scoreSum,\n sumSquares: s.scoreSumSquares,\n mean,\n stddev: Math.sqrt(Math.max(0, variance)),\n }\n }\n\n async readFeatures(\n chr: string,\n bpStart: number,\n bpEnd: number,\n bpPerPixel?: number,\n windowFunction: WindowFunction = 'mean',\n signal?: AbortSignal,\n ): Promise<WigFeature[]> {\n const opts: {signal?: AbortSignal; basesPerSpan?: number} = {signal}\n if (bpPerPixel && windowFunction !== 'none') {\n opts.basesPerSpan = bpPerPixel\n }\n\n const features = await this.bw.getFeatures(chr, bpStart, bpEnd, opts)\n const result: WigFeature[] = []\n for (const f of features) {\n const wig = featureToWig(f, chr, windowFunction)\n if (wig) result.push(wig)\n }\n return result\n }\n\n async readWGFeatures(\n chromNames: string[],\n bpPerPixel: number,\n windowFunction: WindowFunction = 'mean',\n signal?: AbortSignal,\n ): Promise<WigFeature[]> {\n const allFeatures: WigFeature[] = []\n for (const chr of chromNames) {\n try {\n const features = await this.readFeatures(\n chr, 0, Number.MAX_SAFE_INTEGER, bpPerPixel, windowFunction, signal,\n )\n allFeatures.push(...features)\n } catch {\n // Skip chromosomes that don't exist in the file\n }\n }\n return allFeatures\n }\n}\n\n/**\n * Fetch BigWig features for a genomic locus.\n */\nexport async function fetchBigWigFeatures(\n url: string,\n locus: Locus,\n options: FetchBigWigOptions = {},\n): Promise<WigFeature[]> {\n const reader = new BigWigReader(url, options.workerProvider)\n return reader.readFeatures(\n locus.chr,\n locus.start,\n locus.end,\n options.bpPerPixel,\n options.windowFunction ?? 'mean',\n options.signal,\n )\n}\n\n/**\n * Fetch BigWig features across all specified chromosomes for whole genome view.\n * Returns features with per-chromosome coordinates (caller transforms to genome-wide).\n */\nexport async function fetchBigWigWGFeatures(\n url: string,\n chromNames: string[],\n bpPerPixel: number,\n options: Pick<FetchBigWigOptions, 'windowFunction' | 'workerProvider' | 'signal'> = {},\n): Promise<WigFeature[]> {\n const reader = new BigWigReader(url, options.workerProvider)\n return reader.readWGFeatures(\n chromNames,\n bpPerPixel,\n options.windowFunction ?? 'mean',\n options.signal,\n )\n}\n\n/** Clear the BigWig reader cache (useful for testing or memory management). */\nexport function clearBigWigCache(): void {\n readerCache.clear()\n}\n","import type {DataSource, Locus, WigFeature, WindowFunction} from '../types'\nimport type {WorkerProvider} from '../workerProvider'\nimport type {CumulativeOffsets} from '../genome/chromSizes'\nimport {fetchBigWigFeatures, fetchBigWigWGFeatures} from '../bigwig'\nimport {summarizeWigData} from '../tracks/wig/wigSummary'\nimport {isWholeGenomeView} from '../locusUtils'\n\nexport class BigWigDataSource implements DataSource<WigFeature> {\n private _windowFunction: WindowFunction\n private workerProvider?: WorkerProvider\n private _cumulativeOffsets?: CumulativeOffsets\n private _resolveChromName?: (chr: string) => string\n\n constructor(private url: string, windowFunction: WindowFunction = 'mean', workerProvider?: WorkerProvider) {\n this._windowFunction = windowFunction\n this.workerProvider = workerProvider\n }\n\n get windowFunction(): WindowFunction { return this._windowFunction }\n\n /** Update the window function for future fetches. */\n setWindowFunction(wf: WindowFunction): void {\n this._windowFunction = wf\n }\n\n /** Set cumulative offsets for whole genome view coordinate transformation. */\n setCumulativeOffsets(offsets: CumulativeOffsets): void {\n this._cumulativeOffsets = offsets\n }\n\n /** Set a chromosome name resolver for alias resolution (e.g., \"1\" → \"chr1\"). */\n setChromNameResolver(resolver: (chr: string) => string): void {\n this._resolveChromName = resolver\n }\n\n async fetch(locus: Locus, bpPerPixel: number, signal: AbortSignal): Promise<WigFeature[]> {\n if (isWholeGenomeView(locus) && this._cumulativeOffsets) {\n return this.fetchWG(bpPerPixel, signal)\n }\n\n // Resolve chromosome alias before querying the BigWig reader\n const resolvedLocus = this._resolveChromName\n ? {...locus, chr: this._resolveChromName(locus.chr)}\n : locus\n\n const features = await fetchBigWigFeatures(this.url, resolvedLocus, {\n bpPerPixel,\n windowFunction: this._windowFunction,\n workerProvider: this.workerProvider,\n signal,\n })\n\n // Summarize to pixel resolution (matching igv.js wigTrack.getFeatures())\n if (bpPerPixel > 1 && this._windowFunction !== 'none' && features.length > 0) {\n if (this.workerProvider) {\n return this.workerProvider.execute({\n task: 'summarize',\n features,\n startBP: locus.start,\n bpPerPixel,\n windowFunction: this._windowFunction,\n })\n }\n return summarizeWigData(features, locus.start, bpPerPixel, this._windowFunction)\n }\n return features\n }\n\n /**\n * Fetch all chromosomes for whole genome view and transform to genome-wide coordinates.\n * Port of js/bigwig/bwSource.ts getWGValues().\n */\n private async fetchWG(bpPerPixel: number, signal: AbortSignal): Promise<WigFeature[]> {\n const offsets = this._cumulativeOffsets!\n const features = await fetchBigWigWGFeatures(\n this.url,\n offsets.chromosomeNames,\n bpPerPixel,\n {windowFunction: this._windowFunction, workerProvider: this.workerProvider, signal},\n )\n\n // Transform to genome-wide coordinates\n const wgFeatures: WigFeature[] = []\n for (const f of features) {\n const offset = offsets.offsets[f.chr]\n if (offset === undefined) continue\n wgFeatures.push({\n ...f,\n chr: 'all',\n start: offset + f.start,\n end: offset + f.end,\n })\n }\n wgFeatures.sort((a, b) => a.start - b.start)\n\n // Summarize at genome-wide scale\n if (bpPerPixel > 1 && this._windowFunction !== 'none' && wgFeatures.length > 0) {\n if (this.workerProvider) {\n return this.workerProvider.execute({\n task: 'summarize',\n features: wgFeatures,\n startBP: 0,\n bpPerPixel,\n windowFunction: this._windowFunction,\n })\n }\n return summarizeWigData(wgFeatures, 0, bpPerPixel, this._windowFunction)\n }\n return wgFeatures\n }\n}\n","/**\n * HTTP range request reader using native fetch.\n * Replaces igvxhr + BufferedReader for BigWig file reading.\n *\n * Handles cross-origin 307/302 redirects that strip the Range header.\n * When a redirect causes the server to return 200 (full content) instead of\n * 206 (partial), we either retry against the final URL or slice the correct\n * bytes from the full response — matching igvxhr behavior.\n */\n\nexport interface ByteRange {\n start: number\n size: number\n}\n\n/**\n * Fetch a byte range from a URL as an ArrayBuffer.\n *\n * Handles two redirect failure modes:\n * 1. Cross-origin redirect strips Range header → server returns 200 (full file).\n * We retry directly against response.url (the final URL post-redirect).\n * 2. If retry still returns 200, we slice the requested bytes from the full\n * response (matching igvxhr's fallback behavior).\n *\n * On HTTP 416 (Range Not Satisfiable), fetches the actual file size via HEAD\n * and retries once with a clamped range.\n */\nexport async function fetchRange(url: string, range: ByteRange, signal?: AbortSignal): Promise<ArrayBuffer> {\n const end = range.start + range.size - 1\n const headers = {'Range': `bytes=${range.start}-${end}`}\n\n let response = await fetch(url, {headers, signal})\n\n // If redirected and Range was stripped (200 instead of 206), retry against final URL\n if (response.status === 200 && response.redirected && response.url && response.url !== url) {\n response = await fetch(response.url, {headers, signal})\n }\n\n if (response.status === 416) {\n const contentLength = await getContentLength(url, signal)\n const clampedSize = Math.min(range.size, contentLength - range.start)\n if (clampedSize <= 0) {\n throw new Error(`HTTP range request failed: 416 Range Not Satisfiable (file size: ${contentLength})`)\n }\n return fetchRange(url, {start: range.start, size: clampedSize}, signal)\n }\n\n if (!response.ok && response.status !== 206) {\n throw new Error(`HTTP range request failed: ${response.status} ${response.statusText}`)\n }\n\n // If we still got 200 (full file) despite retrying, slice the correct bytes\n // (matches igvxhr behavior: xhr.response.slice(range.start, range.start + range.size))\n if (response.status === 200) {\n const fullBuffer = await response.arrayBuffer()\n return fullBuffer.slice(range.start, range.start + range.size)\n }\n\n return response.arrayBuffer()\n}\n\n/**\n * Fetch the Content-Length of a URL via a HEAD request.\n * If redirected and Content-Length is missing, retries against the final URL.\n */\nexport async function getContentLength(url: string, signal?: AbortSignal): Promise<number> {\n let response = await fetch(url, {method: 'HEAD', signal})\n\n // If redirected and we didn't get Content-Length, retry against final URL\n if (response.redirected && response.url && response.url !== url) {\n const cl = response.headers.get('Content-Length')\n if (!cl) {\n response = await fetch(response.url, {method: 'HEAD', signal})\n }\n }\n\n if (!response.ok) {\n throw new Error(`HEAD request failed: ${response.status} ${response.statusText}`)\n }\n const cl = response.headers.get('Content-Length')\n if (!cl) throw new Error('No Content-Length header in HEAD response')\n return parseInt(cl, 10)\n}\n\n/**\n * Buffered reader that caches fetched data to minimize HTTP requests.\n * When a requested range is within the cached buffer, no fetch is needed.\n *\n * On HTTP 416, recovers by fetching the file's Content-Length and retrying,\n * matching js/bigwig/bufferedReader.ts behavior.\n */\nexport class BufferedRangeReader {\n private readonly url: string\n private readonly bufferSize: number\n private cachedRange: ByteRange\n private cachedData: ArrayBuffer | undefined\n private contentLength: number | undefined\n\n constructor(url: string, bufferSize: number = 512000) {\n this.url = url\n this.bufferSize = bufferSize\n this.cachedRange = {start: -1, size: -1}\n }\n\n async dataViewForRange(requestedRange: ByteRange, signal?: AbortSignal, retries: number = 0): Promise<DataView> {\n try {\n const hasData = (\n this.cachedData !== undefined &&\n this.cachedRange.start <= requestedRange.start &&\n (this.cachedRange.start + this.cachedRange.size) >= (requestedRange.start + requestedRange.size)\n )\n\n if (!hasData) {\n let bufferSize = requestedRange.size\n ? Math.max(this.bufferSize, requestedRange.size)\n : this.bufferSize\n\n if (this.contentLength) {\n bufferSize = Math.min(bufferSize, this.contentLength - requestedRange.start)\n }\n\n const loadRange: ByteRange = {start: requestedRange.start, size: bufferSize}\n this.cachedData = await fetchRange(this.url, loadRange, signal)\n this.cachedRange = loadRange\n }\n\n const bufferStart = requestedRange.start - this.cachedRange.start\n const len = this.cachedData!.byteLength\n return new DataView(this.cachedData!, bufferStart, len - bufferStart)\n } catch (e: unknown) {\n if (retries === 0 && e instanceof Error && e.message.includes('416')) {\n try {\n this.contentLength = await getContentLength(this.url, signal)\n return this.dataViewForRange(requestedRange, signal, retries + 1)\n } catch (e1) {\n console.error(e1)\n }\n }\n throw e\n }\n }\n\n async loadArrayBuffer(range: ByteRange, signal?: AbortSignal): Promise<ArrayBuffer> {\n return fetchRange(this.url, range, signal)\n }\n}\n","/**\n * Base64-inlined zstd WASM binary (from @bokuweb/zstd-wasm, MIT license).\n * Eliminates the need for bundlers to handle `new URL('./zstd.wasm', import.meta.url)`.\n */\n\n// eslint-disable-next-line @typescript-eslint/naming-convention\nconst ZSTD_WASM_BASE64 = `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AWohACAGIAhqIQYMAQsACwALQQAhAgNAIAIgBUZFBEAgBCACIAlqLQAAQQF0aiIAIAAvAQAiAEEBajsBACAQIABBAXRqIAIgBWo7AQAgAkEBaiECDAELCyADQR9rIQQgA0EQdCAFayIFQYCABGohCUEAIQZBACEAQQAhAgNAIAIgCkYNAQJAAkACQAJAAkAgASACQQF0ai8BACIDDgIAAgELIA0gAkEDdGogCTYCBAwDCyADQf//A0cNAQsgDSACQQN0aiIDIABBAWs2AgAgAyAFNgIEIABBAWohAAwBCyANIAJBA3RqIgcgACADwSIDazYCACAHIAQgA0EBa2dqIgdBEHQgAyAHdGs2AgQgACADaiEACyACQQFqIQIMAAsACyAGCxcAIAAgASACIANCgIDs/Mub741PELIBCxcAIAAgASACIANCgIDs/Mub741PELMBCxcAIAAgASACIANCgIDs/Mub741PELQBCxcAIAAgASACIANCgICA2Mub741PELIBCxcAIAAgASACIANCgICA2Mub741PELMBCxcAIAAgASACIANCgICA2Mub741PELQBC6EKAhd/An4jAEGAAmsiEyQAIAEgACgCBCIOayIIQQEgACgCuAF0IgRrIAAoAhAiEiAIIBJrIARLGyERIAAoAhghFyAAKAIMIRQgACgCCCEWQQYgACgCxAEiBCAEQQZPGyEYIAApA1AhGyAAKAIkIQsgACgCKCEJIAAoAlwhDAJAIAAoAtwBRQRAIABBLGohEAJ/IAggACgCHCIEa0GAA00EQEEYIAtrIQ8gCSEGIAwhByAODAELIAQgBEHgAGoiBSAEIAVLGyEPQRggC2shCiAOQQhqIQ0DQCAEIA9GRQRAIBAgBEEHcUECdGoiBigCACEFIAYgACgCUCAEIA1qKAAAQbHz3fF5bHMgCnY2AgAgCSAFQQJ2QcD///8DcSIVaiIGQT9BACAGLQAAIgdBP3FBAUYbIAdBAWtBP3FqIgc6AAAgBiAHaiAFOgAAIAwgFUECdGogB0ECdGogBDYCACAEQQFqIQQMAQsLQQggAUEBaiIFIA4gCEEgayIEaiIGa0EBaiIHIAdBCE8bQQAgBSAGTxsgBGohCkEYIAAoAiRrIQ8gACgCKCEGIAAoAlwhByAEIQUDQCAFIApPRQRAIBAgBUEHcUECdGogACgCUCAF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IAQgGWooAABBsfPd8XlscyAPdjYCACAGIAVBBHZB8P///wBxIhpqIgpBD0EAIAotAAAiDUEPcUEBRhsgDUEBa0EPcWoiDToAACAKIA1qIAU6AAAgByAaQQJ0aiANQQJ0aiAENgIAIARBAWohBAwBCwsgACAJNgIcIBAgCUEHcUECdGoiBCgCACEHIAQgG6cgCSAOaigACEGx893xeWxzQRggC2t2NgIADAELIAEoAAAhBCAAIAk2AhwgG6cgBEGx893xeWxzQRggC2t2IQcLIBIgESAXGyEQIBQgFmohDyAOIBRqIRJBASAYdCEGIAAgACgCWCAHajYCWCAHQf8BcUGBgoQIbCEKIAggB0EEdkHw////AHEiDWoiCy0AACEIQgAhG0EQIQQDQCALIARBBGsiBWooAAAgCnMiEUGAgYKEeHJBgYKECGsgEXJBgIGChHhxQYGBgQFsQRx2rSAbQgSGhCEbIARBB0sgBSEEDQALQQAhBSAbp0F/cyIEQf//A3EgCEEPcXYgBEEAIAhrQQ9xdHKtQv//A4MhGyAMIA1BAnRqIQwDQAJAIAZFIBtQcg0AIBunaCAIakEPcSIEBEAgDCAEQQJ0aigCACIEIBBJDQEgEyAFQQJ0aiAENgIAIAZBAWshBiAFQQFqIQULIBtCAX0gG4MhGwwBCwtBACEEIAsgCEEBa0EPcUEPQQAgCEEPcUEBRhtqIgY6AAAgBiALaiAHOgAAIAAgACgCHCIAQQFqNgIcIAwgBkECdGogADYCAEEDIQYgCUEDaiEMIAFBBGohByABQQNrIQkDQAJAIAQgBUYEQCAGIQAMAQsCQCAGAn8gFCATIARBAnRqKAIAIghNBEAgCCAOaiIAIAZqQQNrKAAAIAYgCWooAABHDQIgASAAIAIQBgwBCyAIIBZqIgAoAAAgASgAAEcNASAHIABBBGogAiAPIBIQBUEEagsiAE8NACADIAwgCGs2AgAgACIGIAFqIAJGDQELIARBAWohBAwBCwsgE0GAAmokACAACxcAIAAgASACIANCgIDs/Mub741PELUBCxcAIAAgASACIANCgIDs/Mub741PELYBCxcAIAAgASACIANCgIDs/Mub741PELcBCxcAIAAgASACIANCgICA2Mub741PELUBCxcAIAAgASACIANCgICA2Mub741PELYBCxcAIAAgASAC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DCAJEJIBIAEoAgwhBAJAIB4gByANaiIPTwRAIA0pAAAhIiAEIA0pAAg3AAggBCAiNwAAIAdBEUkNASANKQAQISIgASgCDCIEIA0pABg3ABggBCAiNwAQIAdBIUgNASANQRBqIQYgBCAHaiENIARBIGohBANAIAYpABAhIiAEIAYpABg3AAggBCAiNwAAIAYpACAhIiAEIAYpACg3ABggBCAiNwAQIAZBIGohBiAEQSBqIgQgDUkNAAsMAQsgBCANIA8gHhAHCyABIAEoAgwgB2o2AgwgASgCBCEEIAdBgIAETwRAIAFBATYCJCABIAQgASgCAGtBA3U2AigLIAQgDDYCACAEIAc7AQQgCUEDayIHQYCABE8EQCABQQI2AiQgASAEIAEoAgBrQQN1NgIoCyAEIAc7AQYgASAEQQhqNgIEIAkgD2oiDQUgByANagshDyAFQQFqIQUMAQsLIBFBAhCQAQwACwALvQEBAX8CQCAAKAIMIgZFDQAgACgCBCAGTw0AIAAoAhgiBiADTQRAIAMgBksEQCAAIAMgBmsQUgsgACADIAQQXyAAKAIYIQYLIAMgACgCFEkgAyAGT3INACAGIANrIgQgBUkNACACKAIAIgMEQCADQf8fSw0BIAQgASADQQN0akEEaygCAE0NAQsgACgCHCEAIAEgA0EDdGogBDYCBCABIAIoAgBBA3RqIABBA2o2AgAgAiACKAIAQQFqNgIACwtMACAEQQNxBEBBfw8LIAVBgCBJBEBBvn8PCyABKAIAQf4BTQRAIAAgASACIANBASAEEKkBDwsgAUH/ATYCACAAIAEgAiADIAQgBRAiC40CAgN/AX4gACACaiEEAkACQCACQQhOBEAgACABayICQXlIDQELA0AgACAETw0CIAAgAS0AADoAACAAQQFqIQAgAUEBaiEBDAALAAsCQAJAIAJBb0sNACAAIARBIGsiAksNACABKQAAIQYgACABKQAINwAIIAAgBjcAACACIABrIgVBEU4EQCAAQRBqIQAgASEDA0AgAykAECEGIAAgAykAGDcACCAAIAY3AAAgAykAICEGIAAgAykAKDcAGCAAIAY3ABAgA0EgaiEDIABBIGoiACACSQ0ACwsgASAFaiEBDAELIAAhAgsDQCACIARPDQEgAiABLQAAOgAAIAJBAWohAiABQQFqIQEMAAsACwuR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AAJ/IAIgACgClOsBBH8gACgC0OkBBUGAgAgLIgIgA2pBQGtLBEAgACABIAJqQSBqIgE2AvzrAUEBIQIgASADagwBCyADQYCABE0EQCAAIABBiOwBaiIBNgL86wFBACECIAEgA2oMAQsgACABIARqIgEgA2siAkHg/wNqIgQgAiAFGzYC/OsBQQIhAiADIARqQYCABGsgASAFGwshAyAAIAI2AoTsASAAIAM2AoDsAQtSAQN/AkAgACgCmOsBIgFFDQAgASgCACABKAK01QEiAiABKAK41QEiAxAUIAIEQCADIAEgAhEJAAwBCyABEBgLIABBADYCqOsBIABCADcDmOsBCyYAIANBGHQgAUEQdGogACAAQQh0IAJyIANBAUYbcq1CgYCAgBB+C0UBAX8CQCAAKAIkRQRAIABBARDQAUGIf0sNAQsgACgCDCICIAFqIgEgACgCFEsEQCAAQQE6ABxBAA8LIAAgATYCDAsgAgtPAQF/IAFFIAAgAhDQAUGIf0tyRQRAIAAoAhQgAWsiAyAAKAIMSQRAIABBAToAHEEADwsgACgCECADSwRAIAAgAzYCEAsgACADNgIUCyADC00BAX8CQCAAKAIkRQRAIAAoAggiAiABQQNqQfz/AXFqIgEgACgCBE0NAQsgAEEBOgAcQQAPCyAAIAE2AhAgACABNgIMIAAgATYCCCACC7oBAQF/IwBBEGsiCiQAIAogAzYCDCAIIApBDGogASACIAggCRAiGkEAIQMCfwJAAkACQAJAIAAOAgACAQsgBiAHIAggCigCDBBqIQMMAQsgAEF+cUECRw0AIAQgCCAKKAIMEGsiA0GIf0sNAQsgASACaiEAA0AgACABTUUEQCABIQggBQRAIAUgAS0AAGohCAsgAUEBaiEBIAMgCC0AAGohAwwBCwsgA0EDdgwBCyACQQpsCyAKQRBqJAALXAEEfyAAKAIEIAAoAgAiA2tBA3UhBANAIAIgBEZFBEAgASADIAJBA3RqLwEEaiEBIAAoAiggAkYEQCABQYCABGogASAAKAIkQQFGGyEBCyACQQFqIQIMAQsLIAELrAMBDH8jAEEQayIFJAAgACABKALoECABKALsECABQcABaiABQawbaiABKALQEiABKALUEhCeASICQYh/TQRAIAEoAtQSIQYgASgC0BIhAiABKALsECEHIAAoAhQh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IAAgBmogACAFaiATEAYhDCAGIANrIQgCQCAGIBRNBEAgAykAACEhIAEoAgwiBSADKQAINwAIIAUgITcAACAIQRFJDQEgAykAECEhIAEoAgwiByADKQAYNwAYIAcgITcAECAIQSFIDQEgA0EQaiEFIAcgCGohAyAHQSBqIQcDQCAFKQAQISEgByAFKQAYNwAIIAcgITcAACAFKQAgISEgByAFKQAoNwAYIAcgITcAECAFQSBqIQUgB0EgaiIHIANJDQALDAELIAEoAgwgAyADIAhqIBQQBwsgASABKAIMIAhqNgIMIAEoAgQhAyAIQYCABE8EQCABQQE2AiQgASADIAEoAgBrQQN1NgIoCyADIAk2AgAgAyAIOwEEIAAgDGoiAEEDayIFQYCABE8EQCABQQI2AiQgASADIAEoAgBrQQN1NgIoCyADIAU7AQYgASADQQhqNgIEIAQhByAAIAZqIgUhAyAFIBFLDQAgCyAQIBlqKAAAQbHz3fF5bCAPdkECdGogEEECajYCACALIAVBAmsiACgAAEGx893xeWwgD3ZBAnRqIAAgCms2AgBBACEHIARFDQADQAJAIAQhByAFIBFLDQAgBSgAACIAIAUgBGsoAABHDQAgBUEEaiIDIAMgBGsgExAGIQQgCyAAQbHz3fF5bCAPdkECdGogBSAKazYCACABKAIMIQACQCAFIBRNBEAgBSkAACEhIAAgBSkACDcACCAAICE3AAAMAQsgACAFIAUgFBAHCyABKAIEIgBBATYCACAAQQA7AQQgBEEBaiIGQYCABE8EQCABQQI2AiQgASAAIAEoAgBrQQN1NgIoCyADIARqIQUgACAGOwEGIAEgAEEIajYCBCAOIQQgByEODAELCyAFIQMMAAsACyATQSBrIQ9BwAAgBGutISIDQCAFIBdqIg1BAWoiDCARTw0GQQAgDmshFSAFQYABaiEQIAVBAWohCCALIAUpAABCgMaV/cub741PfiAiiKciAEECdGooAgAhBCAFKQABISEgFyEJAkADQAJAIAwhEiANIgYgFWoiDSgAACEUIAsgAEECdGogBSAKayIMNgIAICFCgMaV/cub741PfiAiiKchAAJAAkAgDgRAIAYoAAAgFEYNAQsCQAJAAkAgBCAWSQ0AIAUoAAAgBCAKaigAAEcNACAIIQYgBSEIDAELIAsgAEECdGoi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DSAEayEFIAYgBGshCEEBIQkgByEEDAMLIAkgEmohDCALIABBAnRqKAIAIQQgEikAACEhIAYgCWoiDSAQTwRAIBBBgAFqIRAgCUEBaiEJCyASIQggBiEFIAwgEUkNAQwHCwsgDiEEIAchDgsgACAIaiAAIAVqIBMQBiENIAggA2shBgJAIAggD00EQCADKQAAISEgASgCDCIFIAMpAAg3AAggBSAhNwAAIAZBEUkNASADKQAQISEgASgCDCIHIAMpABg3ABggByAhNwAQIAZBIUgNASADQRBqIQUgBiAHaiEDIAdBIGohBwNAIAUpABAhISAHIAUpABg3AAggByAhNwAAIAUpACAhISAHIAUpACg3ABggByAhNwAQIAVBIGohBSAHQSBqIgcgA0kNAAsMAQsgASgCDCADIAMgBmogDxAHCyABIAEoAgwgBmo2AgwgASgCBCEDIAZBgIAETwRAIAFBATYCJCABIAMgASgCAGtBA3U2AigLIAMgCTYCACADIAY7AQQgACANaiIAQQNrIgVBgIAETwRAIAFBAjYCJCABIAMgASgCAGtBA3U2AigLIAMgBTsBBiABIANBCGo2AgQgBCEHIAAgCGoiBSEDIAUgEUsNACALIAwgGWopAABCgICA2Mub741PfiAiiKdBAnRqIAxBAmo2AgAgCyAFQQJrIgApAABCgICA2Mub741PfiAiiKdBAnRqIAAgCms2AgBBACEHIARFDQADQAJAIAQhByAFIBFLDQAgBSgAACAFIARrKAAARw0AIAVBBGoiAyADIARrIBMQBiEEIAsgBSkAAEKAgIDYy5vvjU9+ICKIp0ECdGogBSAKazYCACABKAIMIQACQCAFIA9NBEAgBSkAACEhIAAgBSkACDcACCAAICE3AAAMAQsgACAFIAUgDxAHCyABKAIEIgBBATYCACAAQQA7AQQgBEEBaiIGQYCABE8EQCABQQI2AiQgASAAIAEoAgBrQQN1NgIoCyADIARqIQUgACAGOwEGIAEgAEEIajYCBCAOIQQgByEODAELCyAFIQMMAAsACyATQSBrIQ9BwAAgBGutISIDQCAFIBdqIg1BAWoiDCARTw0DQQAgDmshFSAFQYABaiEQIAVBAWohBiALIAUpAABCgMaV/cub741PfiAiiKciBEECdGooAgAhACAFKQABISEgFyEJAkADQAJAIAwhEiANIgggFWoiDSgAACEUIAsgBEECdGogBSAKayIMNgIAICFCgMaV/cub741PfiAiiKchBAJAAkAgDgRAIAgoAAAgFEYNAQsCQAJAIAUoAABB+jwgACAKaiAAIBZJIg0bKAAARyANckUEQCAGIQggBSEGDAELIAsgBEECdGoiBCgCACEAIAgpAAAgBCAGIAprIgw2AgBCgMaV/cub741PfiAiiKchBCAGKAAAQfo8IAAgCmogACAWSSIFGygAAEcgBXINAyAJQQVPDQELIAsgBEECdGogCCAKazYCAAsgBiAAIApqIgVrIghBA2ohCUEEIQADQCAFIBhNIAMgBk9yDQMgBkEBayIELQAAIAVBAWsiBy0AAEcNAyAAQQFqIQAgByEFIAQhBgwACwALIA1BAWstAAAhACAIQQFrLQAAIQUgCyAEQQJ0aiAGIAprNgIAQQVBBCAAIAVGIgQbIQAgDSAEayEFIAggBGshBkEBIQkgByEEDAMLIAkgEmohDCALIARBAnRqKAIAIQAgEikAACEhIAggCWoiDSAQTwRAIBBBgAFqIRAgCUEBaiEJCyASIQYgCCEFIAwgEUkNAQwGCwsgDiEEIAghDgsgACAGaiAAIAVqIBMQBiENIAYgA2shCAJAIAYgD00EQCADKQAAISEgASgCDCIFIAMpAAg3AAggBSAhNwAAIAhBEUkNASADKQAQISEgASgCDCIHIAMpABg3ABggByAhNwAQIAhBIUgNASADQRBqIQUgByAIaiEDIAdBIGohBwNAIAUpABAhISAHIAUpABg3AAggByAhNwAAIAUpACAhISAHIAUpACg3ABggByAhNwAQIAVBIGohBSAHQSBqIgcgA0kNAAsMAQsgASgCDCADIAMgCGogDxAHCyABIAEoAgwgCGo2AgwgASgCBCEDIAhBgIAETwRAIAFBATYCJCABIAMgASgCAGtBA3U2AigLIAMgCTYCACADIAg7AQQgACANaiIAQQNrIgVBgIAETwRAIAFBAjYCJCABIAMgASgCAGtBA3U2AigLIAMgBTsBBiABIANBCGo2AgQgBCEHIAAgBmoiBSEDIAUgEUsNACALIAwgGWopAABCgMaV/cub741PfiAiiKdBAnRqIAxBAmo2AgAgCyAFQQJrIgApAABCgMaV/cub741PfiAiiKdBAnRqIAAgCms2AgBBACEHIARFDQADQAJAIAQhByAFIBFLDQAgBSgAACAFIARrKAAARw0AIAVBBGoiAyADIARrIBMQBiEEIAsgBSkAAEKAxpX9y5vvjU9+ICKIp0ECdGogBSAKazYCACABKAIMIQACQCAFIA9NBEAgBSkAACEhIAAgBSkACDcACCAAICE3AAAMAQsgACAFIAUgDxAHCyABKAIEIgBBATYCACAAQQA7AQQgBEEBaiIGQYCABE8EQCABQQI2AiQgASAAIAEoAgBrQQN1NgIoCyADIARqIQUgACAGOwEGIAEgAEEIajYCBCAOIQQgByEODAELCyAFIQMMAAsACyATQSBrIQ9BwAAgBGutISIDQCAFIBdqIg1BAWoiDCARTw0CQQAgDmshFSAFQYABaiEQIAVBAWohBiALIAUpAABCgIDs/Mub741PfiAiiKciBEECdGooAgAhACAFKQABISEgFyEJAkADQAJAIAwhEiANIgggFWoiDSgAACEUIAsgBEECdGogBSAKayIMNgIAICFCgIDs/Mub741PfiAiiKchBAJAAkAgDgRAIAgoAAAgFEYNAQsCQAJAIAUoAABB+jwgACAKaiAAIBZJIg0bKAAARyANckUEQCAGIQggBSEGDAELIAsgBEECdGoiBCgCACEAIAgpAAAgBCAGIAprIgw2AgBCgIDs/Mub741PfiAiiKchBCAGKAAAQfo8IAAgCmogACAWSSIFGygAAEcgBXINAyAJQQVPDQELIAsgBEECdGogCCAKazYCAAsgBiAAIApqIgVrIghBA2ohCUEEIQADQCAFIBhNIAMgBk9yDQMgBkEBayIELQAAIAVBAWsiBy0AAEcNAyAAQQFqIQAgByEFIAQhBgwACwALIA1BAWstAAAhACAIQQFrLQAAIQUgCyAEQQJ0aiAGIAprNgIAQQVBBCAAIAVGIgQbIQAgDSAEayEFIAggBGshBkEBIQkgByEEDAMLIAkgEmohDCALIARBAnRqKAIAIQAgEikAACEhIAggCWoiDSAQTwRAIBBBgAFqIRAgCUEBaiEJCyASIQYgCCEFIAwgEUkNAQwFCwsgDiEEIAghDgsgACAGaiAAIAVqIBMQBiENIAYgA2shCAJAIAYgD00EQCADKQAAISEgASgCDCIFIAMpAAg3AAggBSAhNwAAIAhBEUkNASADKQAQISEgASgCDCIHIAMpABg3ABggByAhNwAQIAhBIUgNASADQRBqIQUgByAIaiEDIAdBIGohBwNAIAUpABAhISAHIAUpABg3AAggByAhNwAAIAUpACAhISAHIAUpACg3ABggByAhNwAQIAVBIGohBSAHQSBqIgcgA0kNAAsMAQsgASgCDCADIAMgCGogDxAHCyABIAEoAgwgCGo2AgwgASgCBCEDIAhBgIAETwRAIAFBATYCJCABIAMgASgCAGtBA3U2AigLIAMgCTYCACADIAg7AQQgACANaiIAQQNrIgVBgIAETwRAIAFBAjYCJCABIAMgASgCAGtBA3U2AigLIAMgBTsBBiABIANBCGo2AgQgBCEHIAAgBmoiBSEDIAUgEUsNACALIAwgGWopAABCgIDs/Mub741PfiAiiKdBAnRqIAxBAmo2AgAgCyAFQQJrIgApAABCgIDs/Mub741PfiAiiKdBAnRqIAAgCms2AgBBACEHIARFDQADQAJAIAQhByAFIBFLDQAgBSgAACAFIARrKAAARw0AIAVBBGoiAyADIARrIBMQBiEEIAsgBSkAAEKAgOz8y5vvjU9+ICKIp0ECdGogBSAKazYCACABKAIMIQACQCAFIA9NBEAgBSkAACEhIAAgBSkACDcACCAAICE3AAAMAQsgACAFIAUgDxAHCyABKAIEIgBBATYCACAAQQA7AQQgBEEBaiIGQYCABE8EQCABQQI2AiQgASAAIAEoAgBrQQN1NgIoCyADIARqIQUgACAGOwEGIAEgAEEIajYCBCAOIQQgByEODAELCyAFIQMMAAsACyATQSBrIQ9BwAAgBGutISIDQCAFIBdqIg1BAWoiDCARTw0BQQAgDmshFSAFQYABaiEQIAVBAWohBiALIAUpAABCgICA2Mub741PfiAiiKciBEECdGooAgAhACAFKQABISEgFyEJAkADQAJAIAwhEiANIgggFWoiDSgAACEUIAsgBEECdGogBSAKayIMNgIAICFCgICA2Mub741PfiAiiKchBAJAAkAgDgRAIAgoAAAgFEYNAQsCQAJAIAUoAABB+jwgACAKaiAAIBZJIg0bKAAARyANckUEQCAGIQggBSEGDAELIAsgBEECdGoiBCgCACEAIAgpAAAgBCAGIAprIgw2AgBCgICA2Mub741PfiAiiKchBCAGKAAAQfo8IAAgCmogACAWSSIFGygAAEcgBXINAyAJQQVPDQELIAsgBEECdGogCCAKazYCAAsgBiAAIApqIgVrIghBA2ohCUEEIQADQCAFIBhNIAMgBk9yDQMgBkEBayIELQAAIAVBAWsiBy0AAEcNAyAAQQFqIQAgByEFIAQhBgwACwALIA1BAWstAAAhACAIQQFrLQAAIQUgCyAEQQJ0aiAGIAprNgIAQQVBBCAAIAVGIgQbIQAgDSAEayEFIAggBGshBkEBIQkgByEEDAMLIAkgEmohDCALIARBAnRqKAIAIQAgEikAACEhIAggCWoiDSAQTwRAIBBBgAFqIRAgCUEBaiEJCyASIQYgCCEFIAwgEUkNAQwECwsgDiEEIAghDgsgACAGaiAAIAVqIBMQBiENIAYgA2shCAJAIAYgD00EQCADKQAAISEgASgCDCIFIAMpAAg3AAggBSAhNwAAIAhBEUkNASADKQAQISEgASgCDCIHIAMpABg3ABggByAhNwAQIAhBIUgNASADQRBqIQUgByAIaiEDIAdBIGohBwNAIAUpABAhISAHIAUpABg3AAggByAhNwAAIAUpACAhISAHIAUpACg3ABggByAhNwAQIAVBIGohBSAHQSBqIgcgA0kNAAsMAQsgASgCDCADIAMgCGogDxAHCyABIAEoAgwgCGo2AgwgASgCBCEDIAhBgIAETwRAIAFBATYCJCABIAMgASgCAGtBA3U2AigLIAMgCTYCACADIAg7AQQgACANaiIAQQNrIgVBgIAETwRAIAFBAjYCJCABIAMgASgCAGtBA3U2AigLIAMgBTsBBiABIANBCGo2AgQgBCEHIAAgBmoiBSEDIAUgEUsNACALIAwgGWopAABCgICA2Mub741PfiAiiKdBAnRqIAxBAmo2AgAgCyAFQQJrIgApAABCgICA2Mub741PfiAiiKdBAnRqIAAgCms2AgBBACEHIARFDQADQAJAIAQhByAFIBFLDQAgBSgAACAFIARrKAAARw0AIAVBBGoiAyADIARrIBMQBiEEIAsgBSkAAEKAgIDYy5vvjU9+ICKIp0ECdGogBSAKazYCACABKAIMIQACQCAFIA9NBEAgBSkAACEhIAAgBSkACDcACCAAICE3AAAMAQsgACAFIAUgDxAHCyABKAIEIgBBATYCACAAQQA7AQQgBEEBaiIGQYCABE8EQCABQQI2AiQgASAAIAEoAgBrQQN1NgIoCyADIARqIQUgACAGOwEGIAEgAEEIajYCBCAOIQQgByEODAELCyAFIQMMAAsACyACIA4gG0EAIB0bIA4bNgIAIAIgByAbIB5BACAfGyIAIA4bIAAgHRsgBxs2AgQgEyADawugAQEGfyAAKAKcEyAAKALUBSAAKALYBRAUIABBnBNqAkAgACgCrBMiAEUNACAAQRBqIQMgACgCnCYhAiAAKAKYJiEBAkAgACAAKAIQIgRPBEAgACgCFCEGIANBAEEsEAkaIAQgASACEBQgACAGTw0BDAILIANBAEEsEAkaIAQgASACEBQLIAEEQCACIAAgAREJAAwBCyAAEBgLQQBBJBAJGgssACAAKAKAE0UEQCAAEJYBIABBDGpBAEG0ARAJGiAAQQE2AiwgAEEDNgI4CwsVACABBEAgAiAAIAERCAAPCyAAEG8LIgAgACABIAMQZSABNQKAICAANQKAICACQQ5qrH5+QgSIWgvYBgEHf0EDIRQgDARAIAEoAgAhFAsgCkEDaiERIAtBA2shFyAKIAtqIRUgDkEANgIAAkACQAJAAkACQCAFRQRAIBcNAQwFCwJ/AkACQAJAAkAgASgCACISDgICAAELIBEgBCAFEKABIQUMBQsgEUEDQQQgBUGACEHIAUEAIAwbIgtrSRsgBUGAgAEgC2tPaiIWaiETQQAhCyAMRSASQQJHckUEQCATIAFBBGogASgChAEQCCABKAKEASILaiETCyAVIBNrIRICfyAWQQNGBEAgEyASIAQgBSAAECEMAQsgEyASIAQgBSAAEKMBCyISQQFrQYd/Sw0GIAxFIAsgEmoiCyAFT3ENACAWIAtB//8AS0EEQQMgC0H/B0sbak8NAQsgESAXIAQgBRChAQwBCyASIBNqIAVBBHQhBAJAAkACQAJAIBZBBGsOAgECAAsgCiAEIBRqIAtBDnRqIgQ7AAMgCiAEQRB2OgAFDAILIBEgBCAUaiALQRJ0akEIajYAAAwBCyAKIAtBCnY6AAcgCiAEIBRqIAtBFnRqQQxqNgADCyAOQQE2AgAgEWsLIgVBiH9LDQIgBUUNAwwBCyARQQA6AABBASEFCyAJKAIEIQkgD0EANgIAIBUgBSARaiIEa0EESA0CAkACfyADQYABTwRAIANB//0BTQRAIAQgAzoAASAEIANBCHZBgAFyOgAAIARBAmoMAgsgBEH/AToAACAEIANBgP4BazsAASAEQQNqDAELIAQgAzoAAEEBIQ4gA0UNASAEQQFqCyEOIABBiAhqIQUgCUEZSyEJIA5BAWohDAJAIA0EQCAOIAEoAowBQQR0IAEoAogBQQZ0aiABKAKQAUECdGo6AAAgDCABQZQBaiABKAKcAhAIIAEoApwCaiEMDAELIA5B/AE6AAALIAwgFSAMayAAQYwOaiAHIAUgCCAAQbgZaiAGIAIgAyAJEJ8BIgVBiH9LDQECQCANRQ0AIAEoAqACIgBFDQAgACAFakEESQ0DCyAFIAxqIQBBACEFIAAgDmtBBEgNASAPQQE2AgAgACAEayIOQYh/SwRAIA4PCyAORQ0BCyAKIAQgDmogCmsiBUEDdCAQakEUayIAOwAAIAogAEEQdjoAAgsgBQ8LQQAPC0G6fwtJAQN/IwBBEGsiBSQAA0AgAiAERkUEQCAFQQhqIAAgASAEQQN0ahBmIARBAWohBCAFKAIMIAZqIQYMAQsLIAVBEGokACADIAZqC4sGAQt/IwBBEGsiDSQAIAEoAhQhDyABKAIQIQ4gASgCGCEQIABBADYCECABKAIEIAEoAgAiFGtBA3UhFQNAIAsgFUZFBEBBHyAUIAtBA3RqIgwoAgBnayETIAwvAQYhEiALIA5qAn8gDC8BBCIMQcAATwRAQTIgDGdrDAELIAxB8CZqLQAACzoAACALIBBqIBM6AAAgCyAPaiASQYABTwR/QcMAIBJnawUgEkGwJ2otAAALOgAAQQEgESATQRhLGyERIAtBAWohCwwBCwsgASgCJCILQQFGBH8gDiABKAIoakEjOgAAIAEoAiQFIAsLQQJGBEAgDyABKAIoakE0OgAACyAAIBE2AhQgDUEjNgIMIAggDUEMaiAOIAIgCSAKECIhASAEIAMoAtwbNgLcGyAAIARB3BtqIAggDSgCDCIMIAEgAkEJIANBsBFqIgFBgCVBBkEBIAcQaSILNgIAAkACQAJAIAUgBiAFayAEQbARakEJIAsgCCAMIA4gAkGAJUEGQSMgAUGkCiAJIAoQaCIBQYh/TQRAIAtBAkYEQCAAIAE2AhALIA1BHzYCCCAIIA1BCGogECACIAkgChAiIQwgDSgCCCELIAQgAygC1Bs2AtQbIAAgBEHUG2ogCCALIAwgAkEIIANBwCRBBSALQR1JIAcQaSIMNgIEIAEgBWoiDiAGIA5rIARBCCAMIAggCyAQIAJBwCRBBUEcIANBhAYgCSAKEGgiAUGIf0sNASAMQQJGBEAgACABNgIQCyANQTQ2AgQgCCANQQRqIA8gAiAJIAoQIiELIAQgAygC2Bs2AtgbIAAgBEHYG2ogCCANKAIEIgwgCyACQQkgA0GEBmoiC0HQJUEGQQEgBxBpIgM2AgggASAOaiIHIAYgB2sgBEGEBmpBCSADIAggDCAPIAJB0CVBBkE0IAtBrAsgCSAKEGgiAUGIf0sNAiADQQJGBEAgACABNgIQCyAAIAEgB2ogBWs2AgwMAwsgACABNgIMDAILIAAgATYCDAwBCyAAIAE2AgwLIA1BEGokAAszAQF/AkACQAJAIAAoAkBBAWsOAgIAAQtBAQ8LIAAoAhxBAUcNACAAKAIYQQBHIQELIAELhwUBCX8jAEEgayIIJAAgAygCHCEMIAAoAgghByAAKAIMIQkgAxCdASEKIAhB/wE2AgggASgChAghCyACIAFBiAgQCCENQQAhAgJAAkACQAJAAkAgCg0AIAkgB2siCUEGQT8gASgChAhBAkYbTQ0AIAUgCEEIaiAHIAkgBSAGEFgiB0GIf0sNAUEBIQIgByAJRg0AQQAhAiAHIAlBB3ZBBGpNDQAgCCgCCCECIAtBAUYEQCABIAUgAhCoASELCyANQQBBhAgQCSIKIAUgAkELIAkgAiAFQYAIaiIOIAZBgAhrIg8gCiAFIAxBB0tBAXQQpwEgDiAPEG0iB0GIf0sNASAKIAUgAhAZIQwgBEEEakGAASAKIAIgByAOIA8QbiEHAkACQCALRQ0AIAEgBSACEBkiCyAJTw0AQQMhAiALIAcgDGpNIAdBDGogCU9yDQELQQAhAiAHIAxqIAlJDQMLIAogAUGICBAIGgsgBCACNgIAIARBADYChAEMAgsgBCAHNgKEAQwCCyAEQQI2AgAgCkEBNgKECCAEIAc2AoQBIAdBiH9LDQELAkACfyAAKAIEIgIgACgCACIHRgRAIA1CADcC3CMgDUEANgLkI0EAIQNBACEFQQAhAEEAIQJBAAwBCyAIQQhqIAAgAiAHa0EDdSABQYgIaiANQYgIaiAEQZQBaiAEQZkCaiADKAIcIAUgBUHUAWogBkHUAWsQnAEgCCgCFCIAQYh/Sw0BIAgoAhghAiAIKAIQIQUgCCgCDCEDIAgoAggLIQEgBCACNgKgAiAEIAU2ApABIAQgAzYCjAEgBCABNgKIAQsgBCAANgKcAiAAQQAgAEGJf08bIQcLIAhBIGokACAHC6oHAQV/IwBB0ABrIgskACALIAA2AkggCyAANgJEIAsgACABakEEazYCTEG6fyEAIAFBBU8EQCALQSxqIAIgAyAJQQFrIgBqIgwtAAAQHCALQRxqIAQgACAFaiIBLQAAEBwgC0EMaiAGIAAgB2oiBC0AABAcIAggAEEDdGoiAi8BBCEAIAsgBC0AAEHQGGotAAAiBDYCQCALIAAgBEECdEGwI2ooAgBxNgI8IAtBPGoiDRANIAIvAQYhACALIAsoAkAiBCAMLQAAQYAXai0AACIGajYCQCALIAsoAjwgACAGQQJ0QbAjaigCAHEgBHRyNgI8IA0QDQJ/IAoEQEEYIQBBACEGAkAgAS0AACIBQRhJBEAgASEADAELIAFBGEYNACACKAIAIQQgCyALKAJAIgwgAUEYayIGajYCQCALIAsoAjwgBCAGQQJ0QbAjaigCAHEgDHRyNgI8IAtBPGoQDQsgAigCACAGdgwBCyABLQAAIQAgAigCAAshASALIAsoAkAiAiAAajYCQCALIAsoAjwgAEECdEGwI2ooAgAgAXEgAnRyNgI8IAlBAmshACALQTxqEA0DQCAAIAlPRQRAIAAgB2otAAAhASAAIANqLQAAIQQgC0E8aiIOIAtBHGogACAFai0AACICECMgDiALQSxqIAQQIyAOEA0gDiALQQxqIAEQIyAOEA0gCCAAQQN0aiIGLwEEIQ0gCyALKAJAIg8gAUHQGGotAAAiDGoiATYCQCALIAsoAjwgDSAMQQJ0QbAjaigCAHEgD3RyIg02AjwgDCAEQYAXai0AACIEakEZTwRAIA4QDSALKAI8IQ0gCygCQCEBCyAGLwEGIQwgCyABIARqNgJAIAsgDCAEQQJ0QbAjaigCAHEgAXQgDXI2AjwgC0E8ahANAn8gCgRAQQAhBAJAIAJBGEkEQCACIQEMAQtBGCEBIAJBGEYNACAGKAIAIQwgCyALKAJAIg0gAkEYayIEajYCQCALIAsoAjwgDCAEQQJ0QbAjaigCAHEgDXRyNgI8IAtBPGoQDQsgBigCACAEdgwBCyACIQEgBigCAAshBiALIAsoAkAiAiABajYCQCALIAsoAjwgAUECdEGwI2ooAgAgBnEgAnRyNgI8IABBAWshACALQTxqEA0MAQsLIAtBPGoiACALKAIsIAsoAjgQVCAAIAsoAhwgCygCKBBUIAAgCygCDCALKAIYEFQgABC+ASIAQbp/IAAbIQALIAtB0ABqJAAgAAtoAQF/AkACQAJAAkAgAkH/H0tBAkEBIAJBH0sbaiIDQQJrDgIBAgALIAAgAkEDdEEBcjoAAAwCCyAAIAJBBHRBBXI7AAAMAQsgACACQQR0QQ1yNgAACyAAIANqIAEtAAA6AAAgA0EBagt3AQN/Qbp/IQUgASADQf8fS0ECQQEgA0EfSxtqIgQgA2oiBk8EfwJAAkACQAJAIARBAmsOAgECAAsgACADQQN0OgAADAILIAAgA0EEdEEEcjsAAAwBCyAAIANBBHRBDHI2AAALIAAgBGogAiADEAgaIAYFQbp/CwsdACAAIAEgAiADIAQgBUEBIAYgByAIIAkgChClAQuPAgEFfwJAIAFBEUkgA0EMSXINACAAQQZqIgcgAUEGayACIANBA2pBAnYiBiAEECEiBUGIf0sEQCAFDwsgBUGAgARrQYGAfEkNACAAIAU7AAAgBSAHaiIFIAAgAWoiByAFayACIAZqIgggBiAEECEiAUGIf0sEQCABDwsgAUGAgARrQYGAfEkNACAAIAE7AAIgASAFaiIFIAcgBWsgBiAIaiIIIAYgBBAhIgFBiH9LBEAgAQ8LIAFBgIAEa0GBgHxJDQAgACABOwAEIAEgBWoiBSAHIAVrIAYgCGoiASACIANqIAFrIAQQISIBQYh/SwRAIAEPCyABQYCABGtBgYB8SQ0AIAEgBWogAGshCQsgCQtXACACIAFrIQICfyAFRQRAIAEgAiADIAQgBhAhDAELIAEgAiADIAQgBhCjAQsiAkGIf00EfyACRQRAQQAPCyABIAJqIABrIgBBACAAIARBAWtJGwUgAgsLqgUBBX8jAEEQayIOJAAgDiAENgIMAkAgCEEAIAdrQQNxIg1rIg9BACAIIA9PG0GENkkEQEG+fyEMDAELIAFFIANFcg0AIANBgIAISwRAQbh/IQwMAQsgBUEMSwRAQVQhDAwBCyAEQf8BSwRAQVIhDAwBCyAERQRAIA5B/wE2AgxB/wEhBAsgACABaiEQAkAgCkUgC0EEcUVyIg9FBEAgCigCAEECRg0BCyAHIA1qQQAgCCANTxshDSALQQhxRSADQYDAAklyRQRAIA4gBDYCCCANIA5BCGogAkGAIBBTIgdBiH9LBEAgByEMDAMLIA4gBDYCBCANIA5BBGogAiADakGAIGtBgCAQUyIEQYh/SwRAIAQhDAwDCyAEIAdqQcUASQ0CCyANIA5BDGogAiADIA1BhBBqIghBgCAQWCIEQYh/SwRAIAQhDAwCCyADIARGBEAgACACLQAAOgAAQQEhDAwCCyAEIANBB3ZBBGpNDQECQCAKRQ0AIAooAgAiBEEBRgRAIAkgDSAOKAIMEKgBRQRAIApBADYCAAwCCyAPRQ0CDAELIA8gBEVyRQ0BCyANQYAIaiIHIA0gDigCDCIPIAVBCyAFGyADIA8gCEGAJiAHIA0gCxCnASAIQYAmEG0iBEGIf0sEQCAEIQwMAgsgACABIAcgDyAEIAhB7AUQbiIBQYh/SwRAIAEhDAwCCwJAIAoEQAJAIAooAgBFBEAgAUEMaiEIDAELIAkgDSAPEBkgByANIA8QGSABak0gAUEMaiIIIANPcg0DCyADIAhNDQMgCkEANgIADAELIAFBDGogA08NAgsgCQRAIAkgB0GECBAIGgsgACAAIAFqIBAgAiADIAYgBxCkASEMDAELIAAgACAQIAIgAyAGIAkQpAEhDAsgDkEQaiQAIAwLHQAgACABIAIgAyAEIAVBACAGIAcgCCAJIAoQpQEL+AEBBn8CQCAHQQJxRQRAIAAgASACQQEQ5wEhCAwBCyACQQFqIQggA0HsBWohCkEAIQFBACEHA0AgByAIRkUEQCABIAYgB0ECdGooAgBBAEdqIQEgB0EBaiEHDAELCyAEQewFayELQX4hCSAAIQhBICABZ2siDCEHA0AgACAHSQ0BAkAgBSAGIAIgByADIAQQbSIBQYh/Sw0AIAEgB0kgByAMS3ENAiAKIAsgBSACIAEgAyAEEG4iAUGIf0sNACAFIAYgAhAZIAFqIgEgCUEBaksNAiAHIAggASAJSSINGyEIIAEgCSANGyEJCyAHQQFqIQcMAAsACyAIC18BA38gAC0AASACTwR/IABBBGohAyACQQFqIQRBACECQQAhAANAIAAgBEZFBEAgAiABIABBAnQiBWooAgBBAEcgAyAFai0AAEVxciECIABBAWohAAwBCwsgAkUFQQALC/IFAQh/IAEoAgBBAnRBBGohDCADRQRAIABBACAMEAkaIAFBADYCAEEADwsgBUGAGGohCCAFQYAQaiEJIAVBgAhqIQogBUEAQYAgEAkhByACIANqIgtBD2shDSACKAAAIQMDfyANIAJBBGpNBH8DfyACIAtPBH9BACEDQQAhAgN/IAJBgAJGBH9B/wEhAgNAIAIiBUEBayECIAcgBUECdGooAgBFDQALAn8gBARAQVAgBSABKAIASw0BGgsgASAFNgIAIAAgByAMEAoaIAMLBSAHIAJBAnQiBWoiCyALKAIAIAUgCGooAgAgBSAJaigCACAFIApqKAIAampqIgU2AgAgBSADIAMgBUkbIQMgAkEBaiECDAELCwUgByACLQAAQQJ0aiIDIAMoAgBBAWo2AgAgAkEBaiECDAELCwUgAigABCEFIAcgA0H/AXFBAnRqIgYgBigCAEEBajYCACAKIANBBnZB/AdxaiIGIAYoAgBBAWo2AgAgCSADQQ52QfwHcWoiBiAGKAIAQQFqNgIAIAggA0EWdkH8B3FqIgMgAygCAEEBajYCACACKAAIIQMgByAFQf8BcUECdGoiBiAGKAIAQQFqNgIAIAogBUEGdkH8B3FqIgYgBigCAEEBajYCACAJIAVBDnZB/AdxaiIGIAYoAgBBAWo2AgAgCCAFQRZ2QfwHcWoiBSAFKAIAQQFqNgIAIAIoAAwhBSAHIANB/wFxQQJ0aiIGIAYoAgBBAWo2AgAgCiADQQZ2QfwHcWoiBiAGKAIAQQFqNgIAIAkgA0EOdkH8B3FqIgYgBigCAEEBajYCACAIIANBFnZB/AdxaiIDIAMoAgBBAWo2AgAgAigAECEDIAcgBUH/AXFBAnRqIgYgBigCAEEBajYCACAKIAVBBnZB/AdxaiIGIAYoAgBBAWo2AgAgCSAFQQ52QfwHcWoiBiAGKAIAQQFqNgIAIAggBUEWdkH8B3FqIgUgBSgCAEEBajYCACACQRBqIQIMAQsLC5cDAg1/AX4gASAAKAIEIgxrIgZBASAAKAK8ASIIdCIJayIFQQAgBSAGTRshDSAAKAIQIgUgBkEBIAAoArgBdCIHayAFIAYgBWsgB0sbIAAoAhgbIQ4gACgCHCIFIAYgBSAGSxshCkEBIAAoAsQBdCEHQX8gCHRBf3MhCyAJQQFrIQ9BwAAgACgCwAFrrSESIAAoAlwhCCAAKALcASEQIAAoAmQhCQNAIAUgCkcEQCAJIAUgC3FBAnRqIAggBSAMaikAACAEfiASiKdBAnRqIhEoAgA2AgAgESAFNgIAIAVBAWohBSAQRQ0BCwsgACAGNgIcQQMhACAGQQNqIQogAUEDayELIAggASkAACAEfiASiKdBAnRqIQUCQANAAkAgB0UNACAFKAIAIgYgDkkNAAJAIAYgDGoiBSAAakEDaygAACAAIAtqKAAARw0AIAEgBSACEAYiBSAATQ0AIAMgCiAGazYCACAFIgAgAWogAkYNAwsgBiANTQ0AIAdBAWshByAJIAYgD3FBAnRqIQUMAQsLIAAhBQsgBQtaAQJ/IABBACAGEAkhACACQQFrIQIDQCACIAdNRQRAIAAgASAHai8AAEG5893xeWwgBXYgBHFqIgggCCgCAEEBajYCACAHIANqIQcMAQsLIAAgAiADbjYCgCALiQ0CGX8CfiMAQYACayIUJAAgASAAKAIEIg1rIgpBASAAKAK4AXQiBmsgACgCECISIAogEmsgBksbIRUgACgCGCEWIAAoAsQBIgZBBkshF0EBIAZBBmt0IAEpAAAgBH4iHkHCACAAKAK0ASIPKALAAWutiKchGiAAKAIMIRNBBiAGIAZBBk8bIRsgACkDUCEfIAAoAiQhCyAAKAIoIQkgACgCXCEMAkAgACgC3AFFBEAgAEEsaiEQAn8gCiAAKAIcIgVrQYADTQRAQTggC2utIR4gCSEHIAwhCCANDAELIAUgBUHgAGoiBiAFIAZLGyEOIA1BCGohEUE4IAtrrSEeA0AgBSAORkUEQCAQIAVBB3FBAnRqIgcoAgAhBiAHIAApA1AgBSARaikAACAEfoUgHog+AgAgCSAGQQJ2QcD///8DcSIYaiIHQT9BACAHLQAAIghBP3FBAUYbIAhBAWtBP3FqIgg6AAAgByAIaiAGOgAAIAwgGEECdGogCEECdGogBTYCACAFQQFqIQUMAQsLQQggAUEBaiIGIA0gCkEgayIFaiIHa0EBaiIIIAhBCE8bQQAgBiAHTxsgBWohDkE4IAAoAiRrrSEeIAAoAighByAAKAJcIQggBSEGA0AgBiAOT0UEQCAQIAZBB3FBAnRqIAApA1AgBiANaikAACAEfoUgHog+AgAgBkEBaiEGDAELCyAAKAIECyAFIAogBSAKSxshGEEIaiEcA0AgBSAYRkUEQCAQIAVBB3FBAnRqIg4oAgAhBiAOIAApA1AgBSAcaikAACAEfoUgHog+AgAgByAGQQJ2QcD///8DcSIdaiIOQT9BACAOLQAAIhFBP3FBAUYbIBFBAWtBP3FqIhE6AAAgDiARaiAGOgAAIAggHUECdGogEUECdGogBTYCACAFQQFqIQUMAQsLIAAgCjYCHCAQIApBB3FBAnRqIgYoAgAhCCAGIAogDWopAAggBH4gH4VBOCALa62IPgIADAELIAAgCjYCHCAeIB+FQTggC2utiKchCAsgEiAVIBYbIRFBACAXGyEVIBpBAnQhEiANIBNqIQ5BASAbdCEHIAAgACgCWCAIajYCWCAIQf8BcUGBgoQIbCEWIAkgCEECdkHA////A3EiF2oiCy0AACIQrSEfQgAhHkHAACEFA0AgCyAFQQRrIgZqKAAAIBZzIglBgIGChHhyQYGChAhrIAlyQYCBgoR4cUGBgYEBbEEcdq0gHkIEhoQhHiAFQQdLIAYhBQ0ACyAeQn+FIB+KIR4gDCAXQQJ0aiEGQQAhCQNAAkAgB0UgHlByDQAgHqciBWggHkIgiKdoQSBzIAUbIBBqQT9xIgUEQCAGIAVBAnRqKAIAIgUgEUkNASAUIAlBAnRqIAU2AgAgCUEBaiEJIAdBAWshBwsgHkIBfSAegyEeDAELC0EAIQUgCyAQQQFrQT9xQT9BACAQQT9xQQFGG2oiDDoAACALIAxqIAg6AAAgACAAKAIcIgBBAWo2AhwgBiAMQQJ0aiAANgIAQQMhBiAKQQNqIQwgAUEDayEIA0ACQCAFIAlGBEAgBiEADAELAkAgDSAUIAVBAnRqKAIAIgpqIgAgBmpBA2soAAAgBiAIaigAAEcNACABIAAgAhAGIgAgBk0NACADIAwgCms2AgAgACIGIAFqIAJGDQELIAVBAWohBQwBCwsgDygCXCILIBJBAnRqIRAgEyAPKAIEIghqIRMgDygCACENQQAhBQNAIAVBA0ZFBEAgBUEBaiEFDAELCyAHIBVqIgZBAyAGIAZBA08bIhFrIQkgAUEEaiEKIAwgDSATa2ohDCALIBJBAnRqKAIMIgtBCHYhBiAPKAJkIRJBACEFAkACQANAIAUgEUcEQCAQIAVBAnRqKAIAIg9FDQICQCAIIA9qIgcoAAAgASgAAEcNACAKIAdBBGogAiANIA4QBUEEaiIHIABNDQAgAyAMIA9rNgIAIAciACABaiACRg0ECyAFQQFqIQUMAQsLIAkgC0H/AXEiByAHIAlLGyEPQQAhCUEAIQUDQCAFIA9GBEADQCAJIA9GDQMCQCAIIBIgBkECdGooAgAiBWoiBygAACABKAAARw0AIAogB0EEaiACIA0gDhAFQQRqIgcgAE0NACADIAwgBWs2AgAgByIAIAFqIAJGDQULIAZBAWohBiAJQQFqIQkMAAsABSAFQQFqIQUMAQsACwALIAAhBwsgFEGAAmokACAHC/YMAhl/An4jAEGAAmsiFCQAIAEgACgCBCINayIKQQEgACgCuAF0IgVrIAAoAhAiEiAKIBJrIAVLGyEVIAAoAhghFiAAKALEASIFQQVLIRdBASAFQQVrdCABKQAAIAR+Ih5BwgAgACgCtAEiDygCwAFrrYinIRogACgCDCETQQUgBSAFQQVPGyEbIAApA1AhHyAAKAIkIQsgACgCKCEJIAAoAlwhDAJAIAAoAtwBRQRAIABBLGohEAJ/IAogACgCHCIGa0GAA00EQEE4IAtrrSEeIAkhByAMIQggDQwBCyAGIAZB4ABqIgUgBSAGSRshDiANQQhqIRFBOCALa60hHgNAIAYgDkZFBEAgECAGQQdxQQJ0aiIHKAIAIQUgByAAKQNQIAYgEWopAAAgBH6FIB6IPgIAIAkgBUEDdkHg////AXEiGWoiB0EfQQAgBy0AACIIQR9xQQFGGyAIQQFrQR9xaiIIOgAAIAcgCGogBToAACAMIBlBAnRqIAhBAnRqIAY2AgAgBkEBaiEGDAELC0EIIAFBAWoiBSANIApBIGsiBmoiB2tBAWoiCCAIQQhPG0EAIAUgB08bIAZqIQ5BOCAAKAIka60hHiAAKAIoIQcgACgCXCEIIAYhBQNAIAUgDk9FBEAgECAFQQdxQQJ0aiAAKQNQIAUgDWopAAAgBH6FIB6IPgIAIAVBAWohBQwBCwsgACgCBAsgBiAKIAYgCksbIRlBCGohHANAIAYgGUZFBEAgECAGQQdxQQJ0aiIOKAIAIQUgDiAAKQNQIAYgHGopAAAgBH6FIB6IPgIAIAcgBUEDdkHg////AXEiHWoiDkEfQQAgDi0AACIRQR9xQQFGGyARQQFrQR9xaiIROgAAIA4gEWogBToAACAIIB1BAnRqIBFBAnRqIAY2AgAgBkEBaiEGDAELCyAAIAo2AhwgECAKQQdxQQJ0aiIFKAIAIQggBSAKIA1qKQAIIAR+IB+FQTggC2utiD4CAAwBCyAAIAo2AhwgHiAfhUE4IAtrrYinIQgLIBIgFSAWGyERQQAgFxshFSAaQQJ0IRIgDSATaiEOQQEgG3QhByAAIAAoAlggCGo2AlggCEH/AXFBgYKECGwhFiAJIAhBA3ZB4P///wFxIhdqIhAtAAAhC0EAIQVBICEGA0AgBUEEdCAQIAZBBGsiCWooAAAgFnMiBUGAgYKEeHJBgYKECGsgBXJBgIGChHhxQYGBgQFsQRx2ciEFIAZBB0sgCSEGDQALIAwgF0ECdGohDCAFQX9zIAt4rSEeQQAhCQNAAkAgB0UgHlByDQAgHqdoIAtqQR9xIgUEQCAMIAVBAnRqKAIAIgUgEUkNASAUIAlBAnRqIAU2AgAgCUEBaiEJIAdBAWshBwsgHkIBfSAegyEeDAELC0EAIQYgECALQQFrQR9xQR9BACALQR9xQQFGG2oiBToAACAFIBBqIAg6AAAgACAAKAIcIgBBAWo2AhwgDCAFQQJ0aiAANgIAQQMhBSAKQQNqIQwgAUEDayEIA0ACQCAGIAlGBEAgBSEADAELAkAgDSAUIAZBAnRqKAIAIgpqIgAgBWpBA2soAAAgBSAIaigAAEcNACABIAAgAhAGIgAgBU0NACADIAwgCms2AgAgACIFIAFqIAJGDQELIAZBAWohBgwBCwsgDygCXCILIBJBAnRqIRAgEyAPKAIEIghqIRMgDygCACENQQAhBgNAIAZBA0ZFBEAgBkEBaiEGDAELCyAHIBVqIgVBAyAFIAVBA08bIhFrIQkgAUEEaiEKIAwgDSATa2ohDCALIBJBAnRqKAIMIgtBCHYhBSAPKAJkIRJBACEGAkACQANAIAYgEUcEQCAQIAZBAnRqKAIAIg9FDQICQCAIIA9qIgcoAAAgASgAAEcNACAKIAdBBGogAiANIA4QBUEEaiIHIABNDQAgAyAMIA9rNgIAIAciACABaiACRg0ECyAGQQFqIQYMAQsLIAkgC0H/AXEiByAHIAlLGyEPQQAhCUEAIQYDQCAGIA9GBEADQCAJIA9GDQMCQCAIIBIgBUECdGooAgAiBmoiBygAACABKAAARw0AIAogB0EEaiACIA0gDhAFQQRqIgcgAE0NACADIAwgBms2AgAgByIAIAFqIAJGDQULIAVBAWohBSAJQQFqIQkMAAsABSAGQQFqIQYMAQsACwALIAAhBwsgFEGAAmokACAHC5MNAhl/An4jAEGAAmsiFCQAIAEgACgCBCINayILQQEgACgCuAF0IgZrIAAoAhAiESALIBFrIAZLGyEVIAAoAhghFiAAKALEASIGQQRLIRdBASAGQQRrdCABKQAAIAR+Ih5BwgAgACgCtAEiEigCwAFrrYinIRogACgCDCETQQQgBiAGQQRPGyEbIAApA1AhHyAAKAIkIQogACgCKCEJIAAoAlwhDAJAIAAoAtwBRQRAIABBLGohDwJ/IAsgACgCHCIFa0GAA00EQEE4IAprrSEeIAkhByAMIQggDQwBCyAFIAVB4ABqIgYgBSAGSxshDiANQQhqIRBBOCAKa60hHgNAIAUgDkZFBEAgDyAFQQdxQQJ0aiIHKAIAIQYgByAAKQNQIAUgEGopAAAgBH6FIB6IPgIAIAkgBkEEdkHw////AHEiGGoiB0EPQQAgBy0AACIIQQ9xQQFGGyAIQQFrQQ9xaiIIOgAAIAcgCGogBjoAACAMIBhBAnRqIAhBAnRqIAU2AgAgBUEBaiEFDAELC0EIIAFBAWoiBiANIAtBIGsiBWoiB2tBAWoiCCAIQQhPG0EAIAYgB08bIAVqIQ5BOCAAKAIka60hHiAAKAIoIQcgACgCXCEIIAUhBgNAIAYgDk9FBEAgDyAGQQdxQQJ0aiAAKQNQIAYgDWopAAAgBH6FIB6IPgIAIAZBAWohBgwBCwsgACgCBAsgBSALIAUgC0sbIRhBCGohHANAIAUgGEZFBEAgDyAFQQdxQQJ0aiIOKAIAIQYgDiAAKQNQIAUgHGopAAAgBH6FIB6IPgIAIAcgBkEEdkHw////AHEiHWoiDkEPQQAgDi0AACIQQQ9xQQFGGyAQQQFrQQ9xaiIQOgAAIA4gEGogBjoAACAIIB1BAnRqIBBBAnRqIAU2AgAgBUEBaiEFDAELCyAAIAs2AhwgDyALQQdxQQJ0aiIGKAIAIQggBiALIA1qKQAIIAR+IB+FQTggCmutiD4CAAwBCyAAIAs2AhwgHiAfhUE4IAprrYinIQgLIBEgFSAWGyEQQQAgFxshFSAaQQJ0IREgDSATaiEOQQEgG3QhByAAIAAoAlggCGo2AlggCEH/AXFBgYKECGwhFiAJIAhBBHZB8P///wBxIhdqIg8tAAAhCkIAIR5BECEFA0AgDyAFQQRrIgZqKAAAIBZzIglBgIGChHhyQYGChAhrIAlyQYCBgoR4cUGBgYEBbEEcdq0gHkIEhoQhHiAFQQdLIAYhBQ0AC0EAIQkgHqdBf3MiBkH//wNxIApBD3F2IAZBACAKa0EPcXRyrUL//wODIR4gDCAXQQJ0aiEGA0ACQCAHRSAeUHINACAep2ggCmpBD3EiBQRAIAYgBUECdGooAgAiBSAQSQ0BIBQgCUECdGogBTYCACAJQQFqIQkgB0EBayEHCyAeQgF9IB6DIR4MAQsLQQAhBSAPIApBAWtBD3FBD0EAIApBD3FBAUYbaiIMOgAAIAwgD2ogCDoAACAAIAAoAhwiAEEBajYCHCAGIAxBAnRqIAA2AgBBAyEGIAtBA2ohDCABQQNrIQgDQAJAIAUgCUYEQCAGIQAMAQsCQCANIBQgBUECdGooAgAiC2oiACAGakEDaygAACAGIAhqKAAARw0AIAEgACACEAYiACAGTQ0AIAMgDCALazYCACAAIgYgAWogAkYNAQsgBUEBaiEFDAELCyASKAJcIgogEUECdGohDyATIBIoAgQiCGohEyASKAIAIQ1BACEFA0AgBUEDRkUEQCAFQQFqIQUMAQsLIAcgFWoiBkEDIAYgBkEDTxsiEGshCSABQQRqIQsgDCANIBNraiEMIAogEUECdGooAgwiEUEIdiEGIBIoAmQhEkEAIQUCQAJAA0AgBSAQRwRAIA8gBUECdGooAgAiCkUNAgJAIAggCmoiBygAACABKAAARw0AIAsgB0EEaiACIA0gDhAFQQRqIgcgAE0NACADIAwgCms2AgAgByIAIAFqIAJGDQQLIAVBAWohBQwBCwsgCSARQf8BcSIHIAcgCUsbIQpBACEJQQAhBQNAIAUgCkYEQANAIAkgCkYNAwJAIAggEiAGQQJ0aigCACIFaiIHKAAAIAEoAABHDQAgCyAHQQRqIAIgDSAOEAVBBGoiByAATQ0AIAMgDCAFazYCACAHIgAgAWogAkYNBQsgBkEBaiEGIAlBAWohCQwACwAFIAVBAWohBQwBCwALAAsgACEHCyAUQYACaiQAIAcLmQ0CG38CfiMAQYACayISJAAgASAAKAIEIglrIgxBASAAKAK4AXQiBmsgACgCECIUIAwgFGsgBksbIRUgACgCGCEWIAAoArQBIg8oAiggASkAACAEfiIgQTggDygCJGutiKciGUECdkHA////A3EiGkECdCEbIA8oAlwhHCAAKAIMIRhBBiAAKALEASIGIAZBBk8bIR0gACkDUCEhIAAoAiQhCyAAKAIoIQcgACgCXCENAkAgACgC3AFFBEAgAEEsaiERAn8gDCAAKAIcIgVrQYADTQRAQTggC2utISAgByEIIA0hCiAJDAELIAUgBUHgAGoiBiAFIAZLGyEOIAlBCGohEEE4IAtrrSEgA0AgBSAORkUEQCARIAVBB3FBAnRqIggoAgAhBiAIIAApA1AgBSAQaikAACAEfoUgIIg+AgAgByAGQQJ2QcD///8DcSIXaiIIQT9BACAILQAAIgpBP3FBAUYbIApBAWtBP3FqIgo6AAAgCCAKaiAGOgAAIA0gF0ECdGogCkECdGogBTYCACAFQQFqIQUMAQsLQQggAUEBaiIGIAkgDEEgayIFaiIIa0EBaiIKIApBCE8bQQAgBiAITxsgBWohDkE4IAAoAiRrrSEgIAAoAighCCAAKAJcIQogBSEGA0AgBiAOT0UEQCARIAZBB3FBAnRqIAApA1AgBiAJaikAACAEfoUgIIg+AgAgBkEBaiEGDAELCyAAKAIECyAFIAwgBSAMSxshF0EIaiEeA0AgBSAXRkUEQCARIAVBB3FBAnRqIg4oAgAhBiAOIAApA1AgBSAeaikAACAEfoUgIIg+AgAgCCAGQQJ2QcD///8DcSIfaiIOQT9BACAOLQAAIhBBP3FBAUYbIBBBAWtBP3FqIhA6AAAgDiAQaiAGOgAAIAogH0ECdGogEEECdGogBTYCACAFQQFqIQUMAQsLIAAgDDYCHCARIAxBB3FBAnRqIgYoAgAhCCAGIAkgDGopAAggBH4gIYVBOCALa62IPgIADAELIAAgDDYCHCAgICGFQTggC2utiKchCAsgFCAVIBYbIRQgGmohESAbIBxqIQ4gCSAYaiEQQQEgHXQhBiAAIAAoAlggCGo2AlggCEH/AXFBgYKECGwhFSAHIAhBAnZBwP///wNxIhZqIgotAAAiC60hIUIAISBBwAAhBQNAIAogBUEEayIHaigAACAVcyITQYCBgoR4ckGBgoQIayATckGAgYKEeHFBgYGBAWxBHHatICBCBIaEISAgBUEHSyAHIQUNAAsgIEJ/hSAhiiEgIA0gFkECdGohB0EAIQ0DQAJAIAZFICBQcg0AICCnIgVoICBCIIinaEEgcyAFGyALakE/cSIFBEAgByAFQQJ0aigCACIFIBRJDQEgEiANQQJ0aiAFNgIAIA1BAWohDSAGQQFrIQYLICBCAX0gIIMhIAwBCwtBACEFIAogC0EBa0E/cUE/QQAgC0E/cUEBRhtqIgs6AAAgCiALaiAIOgAAIAAgACgCHCIAQQFqNgIcIAcgC0ECdGogADYCAEEDIQcgDEEDaiEIIAFBA2shCgNAAkAgBSANRgRAIAchAAwBCwJAIAkgEiAFQQJ0aigCACILaiIAIAdqQQNrKAAAIAcgCmooAABHDQAgASAAIAIQBiIAIAdNDQAgAyAIIAtrNgIAIAAiByABaiACRg0BCyAFQQFqIQUMAQsLIBlB/wFxQYGChAhsIQogES0AACEJIA8oAgAhDSAPKAIEIQggDygCDCEPQgAhIEHAACEFA0AgESAFQQRrIgdqKAAAIApzIgtBgIGChHhyQYGChAhrIAtyQYCBgoR4cUGBgYEBbEEcdq0gIEIEhoQhICAFQQdLIAchBQ0AC0EAIQcgIEJ/hSIgQQAgCWtBP3GthiAgIAmtiIQhICAJQT9xIQUDQAJAIAZFICBQcg0AICCnIgloICBCIIinaEEgcyAJGyAFakE/cSIJBEAgDiAJQQJ0aigCACIJIA9JDQEgEiAHQQJ0aiAJNgIAIAdBAWohByAGQQFrIQYLICBCAX0gIIMhIAwBCwsgCCAYaiEJIAFBBGohCiAMIA1qQQNqIQxBACEFA0ACQCAFIAdGBEAgACEGDAELAkAgCCASIAVBAnRqKAIAIg9qIgYoAAAgASgAAEcNACAKIAZBBGogAiANIBAQBUEEaiIGIABNDQAgAyAMIAkgD2prNgIAIAYiACABaiACRg0BCyAFQQFqIQUMAQsLIBJBgAJqJAAgBgvfDAIbfwJ+IwBBgAJrIhIkACABIAAoAgQiDWsiCkEBIAAoArgBdCIGayAAKAIQIhMgCiATayAGSxshFCAAKAIYIRUgACgCtAEiECgCKCABKQAAIAR+IiBBOCAQKAIka62IpyIaQQN2QeD///8BcSIXQQJ0IRsgECgCXCEcIAAoAgwhGUEFIAAoAsQBIgYgBkEFTxshHSAAKQNQISEgACgCJCELIAAoAighByAAKAJcIQwCQCAAKALcAUUEQCAAQSxqIQ4CfyAKIAAoAhwiBWtBgANNBEBBOCALa60hICAHIQkgDCEIIA0MAQsgBSAFQeAAaiIGIAUgBksbIQ8gDUEIaiERQTggC2utISADQCAFIA9GRQRAIA4gBUEHcUECdGoiCSgCACEGIAkgACkDUCAFIBFqKQAAIAR+hSAgiD4CACAHIAZBA3ZB4P///wFxIhhqIglBH0EAIAktAAAiCEEfcUEBRhsgCEEBa0EfcWoiCDoAACAIIAlqIAY6AAAgDCAYQQJ0aiAIQQJ0aiAFNgIAIAVBAWohBQwBCwtBCCABQQFqIgYgDSAKQSBrIgVqIglrQQFqIgggCEEITxtBACAGIAlPGyAFaiEPQTggACgCJGutISAgACgCKCEJIAAoAlwhCCAFIQYDQCAGIA9PRQRAIA4gBkEHcUECdGogACkDUCAGIA1qKQAAIAR+hSAgiD4CACAGQQFqIQYMAQsLIAAoAgQLIAUgCiAFIApLGyEYQQhqIR4DQCAFIBhGRQRAIA4gBUEHcUECdGoiDygCACEGIA8gACkDUCAFIB5qKQAAIAR+hSAgiD4CACAJIAZBA3ZB4P///wFxIh9qIg9BH0EAIA8tAAAiEUEfcUEBRhsgEUEBa0EfcWoiEToAACAPIBFqIAY6AAAgCCAfQQJ0aiARQQJ0aiAFNgIAIAVBAWohBQwBCwsgACAKNgIcIA4gCkEHcUECdGoiBigCACEIIAYgCiANaikACCAEfiAhhUE4IAtrrYg+AgAMAQsgACAKNgIcICAgIYVBOCALa62IpyEICyATIBQgFRshDyAXaiETIBsgHGohESANIBlqIRRBASAddCEGIAAgACgCWCAIajYCWCAIQf8BcUGBgoQIbCEVIAcgCEEDdkHg////AXEiFmoiDi0AACELQQAhB0EgIQUDQCAHQQR0IA4gBUEEayIJaigAACAVcyIHQYCBgoR4ckGBgoQIayAHckGAgYKEeHFBgYGBAWxBHHZyIQcgBUEHSyAJIQUNAAsgDCAWQQJ0aiEJIAdBf3MgC3itISBBACEMA0ACQCAGRSAgUHINACAgp2ggC2pBH3EiBQRAIAkgBUECdGooAgAiBSAPSQ0BIBIgDEECdGogBTYCACAMQQFqIQwgBkEBayEGCyAgQgF9ICCDISAMAQsLQQAhBSAOIAtBAWtBH3FBH0EAIAtBH3FBAUYbaiIHOgAAIAcgDmogCDoAACAAIAAoAhwiAEEBajYCHCAJIAdBAnRqIAA2AgBBAyEHIApBA2ohCSABQQNrIQgDQAJAIAUgDEYEQCAHIQAMAQsCQCANIBIgBUECdGooAgAiC2oiACAHakEDaygAACAHIAhqKAAARw0AIAEgACACEAYiACAHTQ0AIAMgCSALazYCACAAIgcgAWogAkYNAQsgBUEBaiEFDAELCyAaQf8BcUGBgoQIbCELIBMtAAAhDCAQKAIAIQkgECgCBCEIIBAoAgwhEEEAIQdBICEFA0AgB0EEdCATIAVBBGsiDWooAAAgC3MiB0GAgYKEeHJBgYKECGsgB3JBgIGChHhxQYGBgQFsQRx2ciEHIAVBB0sgDSEFDQALIAdBf3MgDHitISBBACEHA0ACQCAGRSAgUHINACAgp2ggDGpBH3EiBQRAIBEgBUECdGooAgAiBSAQSQ0BIBIgB0ECdGogBTYCACAHQQFqIQcgBkEBayEGCyAgQgF9ICCDISAMAQsLIAggGWohDSABQQRqIQwgCSAKakEDaiEKQQAhBQNAAkAgBSAHRgRAIAAhBgwBCwJAIAggEiAFQQJ0aigCACIQaiIGKAAAIAEoAABHDQAgDCAGQQRqIAIgCSAUEAVBBGoiBiAATQ0AIAMgCiANIBBqazYCACAGIgAgAWogAkYNAQsgBUEBaiEFDAELCyASQYACaiQAIAYLmQ0CG38CfiMAQYACayISJAAgASAAKAIEIgtrIgxBASAAKAK4AXQiBmsgACgCECITIAwgE2sgBksbIRUgACgCGCEWIAAoArQBIg8oAiggASkAACAEfiIgQTggDygCJGutiKciGUEEdkHw////AHEiGkECdCEbIA8oAlwhHCAAKAIMIRhBBCAAKALEASIGIAZBBE8bIR0gACkDUCEhIAAoAiQhCiAAKAIoIQcgACgCXCENAkAgACgC3AFFBEAgAEEsaiEQAn8gDCAAKAIcIgVrQYADTQRAQTggCmutISAgByEJIA0hCCALDAELIAUgBUHgAGoiBiAFIAZLGyEOIAtBCGohEUE4IAprrSEgA0AgBSAORkUEQCAQIAVBB3FBAnRqIgkoAgAhBiAJIAApA1AgBSARaikAACAEfoUgIIg+AgAgByAGQQR2QfD///8AcSIXaiIJQQ9BACAJLQAAIghBD3FBAUYbIAhBAWtBD3FqIgg6AAAgCCAJaiAGOgAAIA0gF0ECdGogCEECdGogBTYCACAFQQFqIQUMAQsLQQggAUEBaiIGIAsgDEEgayIFaiIJa0EBaiIIIAhBCE8bQQAgBiAJTxsgBWohDkE4IAAoAiRrrSEgIAAoAighCSAAKAJcIQggBSEGA0AgBiAOT0UEQCAQIAZBB3FBAnRqIAApA1AgBiALaikAACAEfoUgIIg+AgAgBkEBaiEGDAELCyAAKAIECyAFIAwgBSAMSxshF0EIaiEeA0AgBSAXRkUEQCAQIAVBB3FBAnRqIg4oAgAhBiAOIAApA1AgBSAeaikAACAEfoUgIIg+AgAgCSAGQQR2QfD///8AcSIfaiIOQQ9BACAOLQAAIhFBD3FBAUYbIBFBAWtBD3FqIhE6AAAgDiARaiAGOgAAIAggH0ECdGogEUECdGogBTYCACAFQQFqIQUMAQsLIAAgDDYCHCAQIAxBB3FBAnRqIgYoAgAhCSAGIAsgDGopAAggBH4gIYVBOCAKa62IPgIADAELIAAgDDYCHCAgICGFQTggCmutiKchCQsgEyAVIBYbIQ4gGmohEyAbIBxqIREgCyAYaiEVQQEgHXQhBiAAIAAoAlggCWo2AlggCUH/AXFBgYKECGwhCiAHIAlBBHZB8P///wBxIhZqIhAtAAAhCEIAISBBECEFA0AgECAFQQRrIgdqKAAAIApzIhRBgIGChHhyQYGChAhrIBRyQYCBgoR4cUGBgYEBbEEcdq0gIEIEhoQhICAFQQdLIAchBQ0AC0EAIQogIKdBf3MiBUH//wNxIAhBD3F2IAVBACAIa0EPcXRyrUL//wODISAgDSAWQQJ0aiEHA0ACQCAGRSAgUHINACAgp2ggCGpBD3EiBQRAIAcgBUECdGooAgAiBSAOSQ0BIBIgCkECdGogBTYCACAKQQFqIQogBkEBayEGCyAgQgF9ICCDISAMAQsLQQAhBSAQIAhBAWtBD3FBD0EAIAhBD3FBAUYbaiINOgAAIA0gEGogCToAACAAIAAoAhwiAEEBajYCHCAHIA1BAnRqIAA2AgBBAyEHIAxBA2ohDSABQQNrIQkDQAJAIAUgCkYEQCAHIQAMAQsCQCALIBIgBUECdGooAgAiCGoiACAHakEDaygAACAHIAlqKAAARw0AIAEgACACEAYiACAHTQ0AIAMgDSAIazYCACAAIgcgAWogAkYNAQsgBUEBaiEFDAELCyAZQf8BcUGBgoQIbCEIIBMtAAAhCyAPKAIAIQ0gDygCBCEJIA8oAgwhD0IAISBBECEFA0AgEyAFQQRrIgdqKAAAIAhzIgpBgIGChHhyQYGChAhrIApyQYCBgoR4cUGBgYEBbEEcdq0gIEIEhoQhICAFQQdLIAchBQ0AC0EAIQcgIKdBf3MiBUH//wNxIAtBD3F2IAVBACALa0EPcXRyrUL//wODISADQAJAIAZFICBQcg0AICCnaCALakEPcSIFBEAgESAFQQJ0aigCACIFIA9JDQEgEiAHQQJ0aiAFNgIAIAdBAWohByAGQQFrIQYLICBCAX0gIIMhIAwBCwsgCSAYaiELIAFBBGohCCAMIA1qQQNqIQxBACEFA0ACQCAFIAdGBEAgACEGDAELAkAgCSASIAVBAnRqKAIAIg9qIgYoAAAgASgAAEcNACAIIAZBBGogAiANIBUQBUEEaiIGIABNDQAgAyAMIAsgD2prNgIAIAYiACABaiACRg0BCyAFQQFqIQUMAQsLIBJBgAJqJAAgBguNCgIWfwN+IwBBgAJrIhQkACABIAAoAgQiDWsiCkEBIAAoArgBdCIGayAAKAIQIhggCiAYayAGSxshFSAAKAIYIRYgACgCDCEXIAAoAgghGUEGIAAoAsQBIgYgBkEGTxshECAAKQNQIR0gACgCJCESIAAoAighCyAAKAJcIRECQCAAKALcAUUEQCAAQSxqIRMCfyAKIAAoAhwiBWtBgANNBEBBOCASa60hGyALIQggESEGIA0MAQsgBSAFQeAAaiIGIAUgBksbIQkgDUEIaiEIQTggEmutIRwDQCAFIAlGRQRAIBMgBUEHcUECdGoiBigCACEOIAYgACkDUCAFIAhqKQAAIAR+hSAciD4CACALIA5BAnZBwP///wNxIgdqIg9BP0EAIA8tAAAiBkE/cUEBRhsgBkEBa0E/cWoiBjoAACAGIA9qIA46AAAgESAHQQJ0aiAGQQJ0aiAFNgIAIAVBAWohBQwBCwtBCCABQQFqIgggDSAKQSBrIgVqIgdrQQFqIgYgBkEITxtBACAHIAhNGyAFaiEJQTggACgCJGutIRsgACgCKCEIIAAoAlwhBiAFIQcDQCAHIAlPRQRAIBMgB0EHcUECdGogACkDUCAHIA1qKQAAIAR+hSAbiD4CACAHQQFqIQcMAQsLIAAoAgQLIAUgCiAFIApLGyEOQQhqIQ8DQCAFIA5GRQRAIBMgBUEHcUECdGoiBygCACEaIAcgACkDUCAFIA9qKQAAIAR+hSAbiD4CACAIIBpBAnZBwP///wNxIglqIgxBP0EAIAwtAAAiB0E/cUEBRhsgB0EBa0E/cWoiBzoAACAHIAxqIBo6AAAgBiAJQQJ0aiAHQQJ0aiAFNgIAIAVBAWohBQwBCwsgACAKNgIcIBMgCkEHcUECdGoiBigCACEMIAYgCiANaikACCAEfiAdhUE4IBJrrYg+AgAMAQsgASkAACAAIAo2AhwgBH4gHYVBOCASa62IpyEMCyAYIBUgFhshFSAXIBlqIRYgDSAXaiEOQQEgEHQhBiAAIAAoAlggDGo2AlggDEH/AXFBgYKECGwhDyALIAxBAnZBwP///wNxIglqIhAtAAAiC60hHEIAIRtBwAAhBQNAIBAgBUEEayIHaigAACAPcyIIQYCBgoR4ckGBgoQIayAIckGAgYKEeHFBgYGBAWxBHHatIBtCBIaEIRsgBUEHSyAHIQUNAAsgG0J/hSAciiEbIBEgCUECdGohCEEAIQcDQAJAIAZFIBtQcg0AIBunIgVoIBtCIIinaEEgcyAFGyALakE/cSIFBEAgCCAFQQJ0aigCACIFIBVJDQEgFCAHQQJ0aiAFNgIAIAdBAWohByAGQQFrIQYLIBtCAX0gG4MhGwwBCwtBACEFIBAgC0EBa0E/cUE/QQAgC0E/cUEBRhtqIgY6AAAgBiAQaiAMOgAAIAAgACgCHCIAQQFqNgIcIAggBkECdGogADYCAEEDIQYgCkEDaiELIAFBBGohESABQQNrIQgDQAJAIAUgB0YEQCAGIQAMAQsCQCAGAn8gFyAUIAVBAnRqKAIAIglNBEAgCSANaiIAIAZqQQNrKAAAIAYgCGooAABHDQIgASAAIAIQBgwBCyAJIBlqIgAoAAAgASgAAEcNASARIABBBGogAiAWIA4QBUEEagsiAE8NACADIAsgCWs2AgAgACIGIAFqIAJGDQELIAVBAWohBQwBCwsgFEGAAmokACAAC/oJAhZ/An4jAEGAAmsiEiQAIAEgACgCBCIPayIJQQEgACgCuAF0IgVrIAAoAhAiESAJIBFrIAVLGyETIAAoAhghFCAAKAIMIRUgACgCCCEYQQUgACgCxAEiBSAFQQVPGyEWIAApA1AhHCAAKAIkIQwgACgCKCEKIAAoAlwhEAJAIAAoAtwBRQRAIABBLGohDQJ/IAkgACgCHCIFa0GAA00EQEE4IAxrrSEbIAohByAQIQggDwwBCyAFIAVB4ABqIgYgBSAGSxshCyAPQQhqIQ5BOCAMa60hGwNAIAUgC0ZFBEAgDSAFQQdxQQJ0aiIHKAIAIQYgByAAKQNQIAUgDmopAAAgBH6FIBuIPgIAIAogBkEDdkHg////AXEiF2oiB0EfQQAgBy0AACIIQR9xQQFGGyAIQQFrQR9xaiIIOgAAIAcgCGogBjoAACAQIBdBAnRqIAhBAnRqIAU2AgAgBUEBaiEFDAELC0EIIAFBAWoiBiAPIAlBIGsiBWoiB2tBAWoiCCAIQQhPG0EAIAYgB08bIAVqIQtBOCAAKAIka60hGyAAKAIoIQcgACgCXCEIIAUhBgNAIAYgC09FBEAgDSAGQQdxQQJ0aiAAKQNQIAYgD2opAAAgBH6FIBuIPgIAIAZBAWohBgwBCwsgACgCBAsgBSAJIAUgCUsbIRdBCGohGQNAIAUgF0ZFBEAgDSAFQQdxQQJ0aiILKAIAIQYgCyAAKQNQIAUgGWopAAAgBH6FIBuIPgIAIAcgBkEDdkHg////AXEiGmoiC0EfQQAgCy0AACIOQR9xQQFGGyAOQQFrQR9xaiIOOgAAIAsgDmogBjoAACAIIBpBAnRqIA5BAnRqIAU2AgAgBUEBaiEFDAELCyAAIAk2AhwgDSAJQQdxQQJ0aiIFKAIAIQggBSAJIA9qKQAIIAR+IByFQTggDGutiD4CAAwBCyABKQAAIAAgCTYCHCAEfiAchUE4IAxrrYinIQgLIBEgEyAUGyERIBUgGGohCyAPIBVqIQ5BASAWdCEHIAAgACgCWCAIajYCWCAIQf8BcUGBgoQIbCETIAogCEEDdkHg////AXEiFGoiDS0AACEMQQAhBkEgIQUDQCAGQQR0IA0gBUEEayIKaigAACATcyIGQYCBgoR4ckGBgoQIayAGckGAgYKEeHFBgYGBAWxBHHZyIQYgBUEHSyAKIQUNAAsgECAUQQJ0aiEKIAZBf3MgDHitIRtBACEGA0ACQCAHRSAbUHINACAbp2ggDGpBH3EiBQRAIAogBUECdGooAgAiBSARSQ0BIBIgBkECdGogBTYCACAHQQFrIQcgBkEBaiEGCyAbQgF9IBuDIRsMAQsLQQAhBSANIAxBAWtBH3FBH0EAIAxBH3FBAUYbaiIHOgAAIAcgDWogCDoAACAAIAAoAhwiAEEBajYCHCAKIAdBAnRqIAA2AgBBAyEAIAlBA2ohECABQQRqIQggAUEDayEJA0ACQCAFIAZGBEAgACEHDAELAkAgAAJ/IBUgEiAFQQJ0aigCACIKTQRAIAogD2oiByAAakEDaygAACAAIAlqKAAARw0CIAEgByACEAYMAQsgCiAYaiIHKAAAIAEoAABHDQEgCCAHQQRqIAIgCyAOEAVBBGoLIgdPDQAgAyAQIAprNgIAIAciACABaiACRg0BCyAFQQFqIQUMAQsLIBJBgAJqJAAgBwuXCgIWfwJ+IwBBgAJrIhQkACABIAAoAgQiDWsiCkEBIAAoArgBdCIGayAAKAIQIhggCiAYayAGSxshFSAAKAIYIRYgACgCDCEXIAAoAgghGUEEIAAoAsQBIgYgBkEETxshDiAAKQNQIRwgACgCJCESIAAoAighCyAAKAJcIRECQCAAKALcAUUEQCAAQSxqIRMCfyAKIAAoAhwiBWtBgANNBEBBOCASa60hGyALIQggESEGIA0MAQsgBSAFQeAAaiIGIAUgBksbIQkgDUEIaiEIQTggEmutIRsDQCAFIAlGRQRAIBMgBUEHcUECdGoiBigCACEPIAYgACkDUCAFIAhqKQAAIAR+hSAbiD4CACALIA9BBHZB8P///wBxIgdqIhBBD0EAIBAtAAAiBkEPcUEBRhsgBkEBa0EPcWoiBjoAACAGIBBqIA86AAAgESAHQQJ0aiAGQQJ0aiAFNgIAIAVBAWohBQwBCwtBCCABQQFqIgggDSAKQSBrIgVqIgdrQQFqIgYgBkEITxtBACAHIAhNGyAFaiEJQTggACgCJGutIRsgACgCKCEIIAAoAlwhBiAFIQcDQCAHIAlPRQRAIBMgB0EHcUECdGogACkDUCAHIA1qKQAAIAR+hSAbiD4CACAHQQFqIQcMAQsLIAAoAgQLIAUgCiAFIApLGyEPQQhqIRADQCAFIA9GRQRAIBMgBUEHcUECdGoiBygCACEaIAcgACkDUCAFIBBqKQAAIAR+hSAbiD4CACAIIBpBBHZB8P///wBxIglqIgxBD0EAIAwtAAAiB0EPcUEBRhsgB0EBa0EPcWoiBzoAACAHIAxqIBo6AAAgBiAJQQJ0aiAHQQJ0aiAFNgIAIAVBAWohBQwBCwsgACAKNgIcIBMgCkEHcUECdGoiBigCACEMIAYgCiANaikACCAEfiAchUE4IBJrrYg+AgAMAQsgASkAACAAIAo2AhwgBH4gHIVBOCASa62IpyEMCyAYIBUgFhshFSAXIBlqIRYgDSAXaiEPQQEgDnQhBiAAIAAoAlggDGo2AlggDEH/AXFBgYKECGwhECALIAxBBHZB8P///wBxIglqIgstAAAhDkIAIRtBECEFA0AgCyAFQQRrIgdqKAAAIBBzIghBgIGChHhyQYGChAhrIAhyQYCBgoR4cUGBgYEBbEEcdq0gG0IEhoQhGyAFQQdLIAchBQ0AC0EAIQcgG6dBf3MiBUH//wNxIA5BD3F2IAVBACAOa0EPcXRyrUL//wODIRsgESAJQQJ0aiEIA0ACQCAGRSAbUHINACAbp2ggDmpBD3EiBQRAIAggBUECdGooAgAiBSAVSQ0BIBQgB0ECdGogBTYCACAHQQFqIQcgBkEBayEGCyAbQgF9IBuDIRsMAQsLQQAhBSALIA5BAWtBD3FBD0EAIA5BD3FBAUYbaiIGOgAAIAYgC2ogDDoAACAAIAAoAhwiAEEBajYCHCAIIAZBAnRqIAA2AgBBAyEGIApBA2ohCyABQQRqIREgAUEDayEIA0ACQCAFIAdGBEAgBiEADAELAkAgBgJ/IBcgFCAFQQJ0aigCACIJTQRAIAkgDWoiACAGakEDaygAACAGIAhqKAAARw0CIAEgACACEAYMAQsgCSAZaiIAKAAAIAEoAABHDQEgESAAQQRqIAIgFiAPEAVBBGoLIgBPDQAgAyALIAlrNgIAIAAiBiABaiACRg0BCyAFQQFqIQUMAQsLIBRBgAJqJAAgAAu5CQIUfwJ+IwBBgAJrIhIkACABIAAoAgQiD2siCkEBIAAoArgBdCIGayAAKAIQIhEgCiARayAGSxshFCAAKAIYIRVBBiAAKALEASIGIAZBBk8bIRYgACkDUCEaIAAoAiQhDCAAKAIoIQkgACgCXCEQAkAgACgC3AFFBEAgAEEsaiENAn8gCiAAKAIcIgVrQYADTQRAQTggDGutIRkgCSEHIBAhCCAPDAELIAUgBUHgAGoiBiAFIAZLGyELIA9BCGohDkE4IAxrrSEZA0AgBSALRkUEQCANIAVBB3FBAnRqIgcoAgAhBiAHIAApA1AgBSAOaikAACAEfoUgGYg+AgAgCSAGQQJ2QcD///8DcSITaiIHQT9BACAHLQAAIghBP3FBAUYbIAhBAWtBP3FqIgg6AAAgByAIaiAGOgAAIBAgE0ECdGogCEECdGogBTYCACAFQQFqIQUMAQsLQQggAUEBaiIGIA8gCkEgayIFaiIHa0EBaiIIIAhBCE8bQQAgBiAHTxsgBWohC0E4IAAoAiRrrSEZIAAoAighByAAKAJcIQggBSEGA0AgBiALT0UEQCANIAZBB3FBAnRqIAApA1AgBiAPaikAACAEfoUgGYg+AgAgBkEBaiEGDAELCyAAKAIECyAFIAogBSAKSxshE0EIaiEXA0AgBSATRkUEQCANIAVBB3FBAnRqIgsoAgAhBiALIAApA1AgBSAXaikAACAEfoUgGYg+AgAgByAGQQJ2QcD///8DcSIYaiILQT9BACALLQAAIg5BP3FBAUYbIA5BAWtBP3FqIg46AAAgCyAOaiAGOgAAIAggGEECdGogDkECdGogBTYCACAFQQFqIQUMAQsLIAAgCjYCHCANIApBB3FBAnRqIgYoAgAhCCAGIAogD2opAAggBH4gGoVBOCAMa62IPgIADAELIAEpAAAgACAKNgIcIAR+IBqFQTggDGutiKchCAsgESAUIBUbIRFBASAWdCEHIAAgACgCWCAIajYCWCAIQf8BcUGBgoQIbCELIAkgCEECdkHA////A3EiDmoiDC0AACINrSEaQgAhGUHAACEFA0AgDCAFQQRrIgZqKAAAIAtzIglBgIGChHhyQYGChAhrIAlyQYCBgoR4cUGBgYEBbEEcdq0gGUIEhoQhGSAFQQdLIAYhBQ0ACyAZQn+FIBqKIRkgECAOQQJ0aiEGQQAhCQNAAkAgB0UgGVByDQAgGaciBWggGUIgiKdoQSBzIAUbIA1qQT9xIgUEQCAGIAVBAnRqKAIAIgUgEUkNASASIAlBAnRqIAU2AgAgCUEBaiEJIAdBAWshBwsgGUIBfSAZgyEZDAELC0EAIQUgDCANQQFrQT9xQT9BACANQT9xQQFGG2oiBzoAACAHIAxqIAg6AAAgACAAKAIcIgBBAWo2AhwgBiAHQQJ0aiAANgIAQQMhBiAKQQNqIQAgAUEDayEIA0ACQCAFIAlGBEAgBiEHDAELAkAgDyASIAVBAnRqKAIAIhBqIgcgBmpBA2soAAAgBiAIaigAAEcNACABIAcgAhAGIgcgBk0NACADIAAgEGs2AgAgByIGIAFqIAJGDQELIAVBAWohBQwBCwsgEkGAAmokACAHC6YJAhR/An4jAEGAAmsiEiQAIAEgACgCBCIQayIKQQEgACgCuAF0IgVrIAAoAhAiESAKIBFrIAVLGyETIAAoAhghFUEFIAAoAsQBIgUgBUEFTxshFiAAKQNQIRogACgCJCEMIAAoAighCSAAKAJcIQ0CQCAAKALcAUUEQCAAQSxqIQ4CfyAKIAAoAhwiBmtBgANNBEBBOCAMa60hGSAJIQcgDSEIIBAMAQsgBiAGQeAAaiIFIAUgBkkbIQsgEEEIaiEPQTggDGutIRkDQCAGIAtGRQRAIA4gBkEHcUECdGoiBygCACEFIAcgACkDUCAGIA9qKQAAIAR+hSAZiD4CACAJIAVBA3ZB4P///wFxIhRqIgdBH0EAIActAAAiCEEfcUEBRhsgCEEBa0EfcWoiCDoAACAHIAhqIAU6AAAgDSAUQQJ0aiAIQQJ0aiAGNgIAIAZBAWohBgwBCwtBCCABQQFqIgUgECAKQSBrIgZqIgdrQQFqIgggCEEITxtBACAFIAdPGyAGaiELQTggACgCJGutIRkgACgCKCEHIAAoAlwhCCAGIQUDQCAFIAtPRQRAIA4gBUEHcUECdGogACkDUCAFIBBqKQAAIAR+hSAZiD4CACAFQQFqIQUMAQsLIAAoAgQLIAYgCiAGIApLGyEUQQhqIRcDQCAGIBRGRQRAIA4gBkEHcUECdGoiCygCACEFIAsgACkDUCAGIBdqKQAAIAR+hSAZiD4CACAHIAVBA3ZB4P///wFxIhhqIgtBH0EAIAstAAAiD0EfcUEBRhsgD0EBa0EfcWoiDzoAACALIA9qIAU6AAAgCCAYQQJ0aiAPQQJ0aiAGNgIAIAZBAWohBgwBCwsgACAKNgIcIA4gCkEHcUECdGoiBSgCACEHIAUgCiAQaikACCAEfiAahUE4IAxrrYg+AgAMAQsgASkAACAAIAo2AhwgBH4gGoVBOCAMa62IpyEHCyARIBMgFRshEUEBIBZ0IQwgACAAKAJYIAdqNgJYIAdB/wFxQYGChAhsIQsgCSAHQQN2QeD///8BcSIPaiIOLQAAIQhBACEFQSAhBgNAIAVBBHQgDiAGQQRrIglqKAAAIAtzIgVBgIGChHhyQYGChAhrIAVyQYCBgoR4cUGBgYEBbEEcdnIhBSAGQQdLIAkhBg0ACyANIA9BAnRqIQ0gBUF/cyAIeK0hGUEAIQkDQAJAIAxFIBlQcg0AIBmnaCAIakEfcSIFBEAgDSAFQQJ0aigCACIFIBFJDQEgEiAJQQJ0aiAFNgIAIAxBAWshDCAJQQFqIQkLIBlCAX0gGYMhGQwBCwtBACEGIA4gCEEBa0EfcUEfQQAgCEEfcUEBRhtqIgU6AAAgBSAOaiAHOgAAIAAgACgCHCIAQQFqNgIcIA0gBUECdGogADYCAEEDIQUgCkEDaiENIAFBA2shBwNAAkAgBiAJRgRAIAUhAAwBCwJAIBAgEiAGQQJ0aigCACIIaiIAIAVqQQNrKAAAIAUgB2ooAABHDQAgASAAIAIQBiIAIAVNDQAgAyANIAhrNgIAIAAiBSABaiACRg0BCyAGQQFqIQYMAQsLIBJBgAJqJAAgAAvDCQIUfwJ+IwBBgAJrIhQkACABIAAoAgQiD2siCkEBIAAoArgBdCIFayAAKAIQIhUgCiAVayAFSxshGCAAKAIYIQ1BBCAAKALEASIFIAVBBE8bIREgACkDUCEaIAAoAiQhEiAAKAIoIQsgACgCXCEMAkAgACgC3AFFBEAgAEEsaiETAn8gCiAAKAIcIgZrQYADTQRAQTggEmutIRkgCyEHIAwhCCAPDAELIAYgBkHgAGoiBSAFIAZJGyEOIA9BCGohCEE4IBJrrSEZA0AgBiAORkUEQCATIAZBB3FBAnRqIgUoAgAhECAFIAApA1AgBiAIaikAACAEfoUgGYg+AgAgCyAQQQR2QfD///8AcSIHaiIJQQ9BACAJLQAAIgVBD3FBAUYbIAVBAWtBD3FqIgU6AAAgBSAJaiAQOgAAIAwgB0ECdGogBUECdGogBjYCACAGQQFqIQYMAQsLQQggAUEBaiIIIA8gCkEgayIGaiIHa0EBaiIFIAVBCE8bQQAgByAITRsgBmohDkE4IAAoAiRrrSEZIAAoAighByAAKAJcIQggBiEFA0AgBSAOT0UEQCATIAVBB3FBAnRqIAApA1AgBSAPaikAACAEfoUgGYg+AgAgBUEBaiEFDAELCyAAKAIECyAGIAogBiAKSxshEEEIaiEJA0AgBiAQRkUEQCATIAZBB3FBAnRqIgUoAgAhFiAFIAApA1AgBiAJaikAACAEfoUgGYg+AgAgByAWQQR2QfD///8AcSIOaiIXQQ9BACAXLQAAIgVBD3FBAUYbIAVBAWtBD3FqIgU6AAAgBSAXaiAWOgAAIAggDkECdGogBUECdGogBjYCACAGQQFqIQYMAQsLIAAgCjYCHCATIApBB3FBAnRqIgUoAgAhCCAFIAogD2opAAggBH4gGoVBOCASa62IPgIADAELIAEpAAAgACAKNgIcIAR+IBqFQTggEmutiKchCAsgFSAYIA0bIRBBASARdCEHIAAgACgCWCAIajYCWCAIQf8BcUGBgoQIbCEJIAsgCEEEdkHw////AHEiDmoiES0AACENQgAhGUEQIQYDQCARIAZBBGsiBWooAAAgCXMiC0GAgYKEeHJBgYKECGsgC3JBgIGChHhxQYGBgQFsQRx2rSAZQgSGhCEZIAZBB0sgBSEGDQALQQAhCSAZp0F/cyIFQf//A3EgDUEPcXYgBUEAIA1rQQ9xdHKtQv//A4MhGSAMIA5BAnRqIQwDQAJAIAdFIBlQcg0AIBmnaCANakEPcSIFBEAgDCAFQQJ0aigCACIFIBBJDQEgFCAJQQJ0aiAFNgIAIAlBAWohCSAHQQFrIQcLIBlCAX0gGYMhGQwBCwtBACEGIBEgDUEBa0EPcUEPQQAgDUEPcUEBRhtqIgU6AAAgBSARaiAIOgAAIAAgACgCHCIAQQFqNgIcIAwgBUECdGogADYCAEEDIQUgCkEDaiEIIAFBA2shCwNAAkAgBiAJRgRAIAUhBwwBCwJAIA8gFCAGQQJ0aigCACIMaiIAIAVqQQNrKAAAIAUgC2ooAABHDQAgASAAIAIQBiIHIAVNDQAgAyAIIAxrNgIAIAciBSABaiACRg0BCyAGQQFqIQYMAQsLIBRBgAJqJAAgBwvYBgITfwJ+IAEgACgCBCIKayIFQQEgACgCvAEiC3QiDGsiB0EAIAUgB08bIQ4gACgCECIHIAVBASAAKAK4AXQiBmsgByAFIAdrIAZLGyAAKAIYGyEPIAAoAhwiBiAFIAUgBkkbIQcgASkAACAEfiIZQcIAIAAoArQBIgkoAsABa62IpyIIQQJ0IRAgCSgCXCITIAhBBHRqIRRBASAAKALEAXQhCCAKIAAoAgwiFWohEkF/IAt0QX9zIQ0gDEEBayEWQcAAIAAoAsABa60hGCAAKAJcIQsgACgC3AEhESAAKAJkIQwDQCAGIAdHBEAgDCAGIA1xQQJ0aiALIAYgCmopAAAgBH4gGIinQQJ0aiIXKAIANgIAIBcgBjYCACAGQQFqIQYgEUUNAQsLIAAgBTYCHEEDIQcgBUEDaiENIAFBA2shESALIBkgGIinQQJ0aiEGAkADQAJAIAhFDQAgBigCACIFIA9JDQACQCAFIApqIgAgB2pBA2soAAAgByARaigAAEcNACABIAAgAhAGIgAgB00NACADIA0gBWs2AgAgACIHIAFqIAJGDQMLIAUgDk0NACAIQQFrIQggDCAFIBZxQQJ0aiEGDAELCyAHIQALIBUgCSgCBCILaiEFIAkoAgAhCkEAIQYDQCAGQQNGRQRAIAZBAWohBgwBCwtBACEGIAhBA2siB0EAIAcgCE0bIQdBAyAIIAhBA08bIQ4gAUEEaiEMIA0gCiAFa2ohDSATIBBBAnRqKAIMIg9BCHYhCCAJKAJkIRACQAJAA0AgBiAORwRAIBQgBkECdGooAgAiCUUNAgJAIAkgC2oiBSgAACABKAAARw0AIAwgBUEEaiACIAogEhAFQQRqIgUgAE0NACADIA0gCWs2AgAgBSEAIAEgBWogAkYNBAsgBkEBaiEGDAELCyAHIA9B/wFxIgUgBSAHSxshCUEAIQdBACEGA0AgBiAJRgRAA0AgByAJRg0DAkAgCyAQIAhBAnRqKAIAIgZqIgUoAAAgASgAAEcNACAMIAVBBGogAiAKIBIQBUEEaiIFIABNDQAgAyANIAZrNgIAIAUhACABIAVqIAJGDQULIAhBAWohCCAHQQFqIQcMAAsABSAGQQFqIQYMAQsACwALIAAhBQsgBQuaBQIQfwJ+IAEgACgCBCILayIIQQEgACgCvAEiB3QiCWsiBkEAIAYgCE0bIQwgACgCECIGIAhBASAAKAK4AXQiBWsgBiAIIAZrIAVLGyAAKAIYGyEPIAAoAhwiBSAIIAUgCEsbIQ1BASAAKALEAXQhCiALIAAoAgwiEGohEUF/IAd0QX9zIQ4gCUEBayESQcAAIAAoAsABa60hFSAAKAJcIQYgACgC3AEhEyAAKAK0ASEHIAAoAmQhCQNAIAUgDUcEQCAJIAUgDnFBAnRqIAYgBSALaikAACAEfiAViKdBAnRqIhQoAgA2AgAgFCAFNgIAIAVBAWohBSATRQ0BCwsgACAINgIcQQMhACAIQQNqIQ0gAUEDayEOIAYgASkAACAEfiIWIBWIp0ECdGohBQJAA0ACQCAKRQ0AIAUoAgAiBSAPSQ0AAkAgBSALaiIGIABqQQNrKAAAIAAgDmooAABHDQAgASAGIAIQBiIGIABNDQAgAyANIAVrNgIAIAYiACABaiACRg0DCyAFIAxNDQAgCkEBayEKIAkgBSAScUECdGohBQwBCwsgACEGCyAHKAIAIgsgBygCBCIJayIAQQEgBygCvAF0IgVrIgxBACAAIAxPGyEMIAFBBGohDyAFQQFrIQ0gACAIakEDaiEIIAcoAlwgFkHAACAHKALAAWutiKdBAnRqIQUgBygCDCEOIAcoAmQhBwJAA0ACQCAKRQ0AIAUoAgAiBSAOSQ0AAkAgBSAJaiIAKAAAIAEoAABHDQAgDyAAQQRqIAIgCyAREAVBBGoiACAGTQ0AIAMgCCAFIBBqazYCACAAIQYgACABaiACRg0DCyAFIAxNDQAgCkEBayEKIAcgBSANcUECdGohBQwBCwsgBiEACyAAC+cDAhF/AX4gASAAKAIEIgprIgZBASAAKAK8ASIIdCIJayIFQQAgBSAGTRshDyAAKAIQIgUgBkEBIAAoArgBdCIHayAFIAYgBWsgB0sbIAAoAhgbIRAgACgCHCIFIAYgBSAGSxshC0EBIAAoAsQBdCEHIAAoAggiESAAKAIMIg5qIRIgCiAOaiETQX8gCHRBf3MhDCAJQQFrIRRBwAAgACgCwAFrrSEWIAAoAlwhCCAAKALcASENIAAoAmQhCQNAIAUgC0cEQCAJIAUgDHFBAnRqIAggBSAKaikAACAEfiAWiKdBAnRqIhUoAgA2AgAgFSAFNgIAIAVBAWohBSANRQ0BCwsgACAGNgIcQQMhACAGQQNqIQsgAUEEaiEMIAFBA2shDSAIIAEpAAAgBH4gFoinQQJ0aiEFAkADQAJAIAdFDQAgBSgCACIGIBBJDQACQAJ/IAYgDk8EQCAGIApqIgUgAGpBA2soAAAgACANaigAAEcNAiABIAUgAhAGDAELIAYgEWoiBSgAACABKAAARw0BIAwgBUEEaiACIBIgExAFQQRqCyIFIABNDQAgAyALIAZrNgIAIAUiACABaiACRg0DCyAGIA9NDQAgB0EBayEHIAkgBiAUcUECdGohBQwBCwsgACEFCyAFC/sJAiN/AX4jAEEQayIUJAACQCADIAEoAgQiCyABKAIcIgJqSQ0AIAMgC2shCgNAIAIgCk9FBEAgASACIAtqIAQgCiAJQQAQECACaiECDAELCyABIAo2AhxBASABKAIQIgIgAyABKAIEIhVrIg1BASABKAK4AXQiCmsgAiANIAJrIApLGyABKAIYGyIWIBZBAU0bISIgDUF/IAEoArwBQQFrdEF/cyIbayICQQAgAiANTRshHCABKAJcIAMpAAAgCH4iLUHAACABKALAAWutiKdBAnRqIiMoAgAhDCABKAK0ASISKAIAIh0gEigCBCIeayIXQX8gEigCvAFBAWt0QX9zIh9rIBIoAhAiGCAXIBhrIB9LGyEkIB4gFiAXayIZayElIA0gGCAZamshJiAGIAZBA2oiAiACIAZJGyEnIAEoAmQiKCANIBtxQQN0aiITQQRqIQ9B/x8gASgCzAEiAiACQf8fTxshKSADQQRqIRogB0EBayEKIBUgASgCDCIgaiEhIA0gIGshKiANQQlqIRBBASABKALEAXQhESASKALAASErIAYhAgNAIAIgJ0cEQCANAn8gAkEDRgRAIAUoAgBBAWsMAQsgBSACQQJ0aigCAAsiC2shBwJAAn8gKiALQQFrIixLBEAgByAWSQ0CIAMoAAAgAyALaygAAEcNAiAaIBogC2sgBBAGDAELICYgLE0gByAga0F8S3INASADKAAAIAcgJWoiBygAAEcNASAaIAdBBGogBCAdICEQBQtBBGoiByAKTQ0AIAAgDkEDdGoiCiAHNgIEIAogAiAGa0EBajYCACAOQQFqIQ4gByApSw0DIAciCiADaiAERg0DCyACQQFqIQIMAQsLICMgDTYCACANQQNqIQZBACEHQQAhBQJAAkACQAJAAkADQCARRSAMICJJcg0CIAogAyAFIAcgBSAHSRsiAmogDCAVaiINIAJqIAQQBiACaiICSQRAIAAgDkEDdGoiCiACNgIEIAogBiAMazYCACACIAxqIBAgAiAQIAxrSxshECAOQQFqIQ4gAiADaiAERiACQYAgS3INBSACIQoLICggDCAbcUEDdGohCwJAAkACQCACIA1qLQAAIAIgA2otAABJBEAgEyAMNgIAIAwgHEsNASAUQQxqIRMMBQsgDyAMNgIAIAwgHE0NAiALIQ8gAiEHDAELIAIhBSALQQRqIhMhCwsgEUEBayERIAsoAgAhDAwBCwsgFEEMaiEPCyAPQQA2AgAgE0EANgIADAELIA9BADYCACATQQA2AgAgEUUNAgsgFSAZaiEPIBIoAlwgLUHAACAra62Ip0ECdGohAiASKAJkIQ1BACEMQQAhBwNAIBFFDQIgAigCACIFIBhNDQIgCiADIAcgDCAHIAxJGyICaiAFIB5qIgsgAmogBCAdICEQBSACaiICSQRAIAAgDkEDdGoiCiACNgIEIAogBiAFIBlqIgprNgIAIAIgCmogECACIBAgCmtLGyEQIA5BAWohDiACQYAgSw0DIAIhCiACIANqIARGDQMLIAUgJE0NAiARQQFrIREgAiAHIAsgBSAPaiACIAVqIBdJGyACai0AACACIANqLQAASSILGyEHIAwgAiALGyEMIA0gBSAfcUEDdGogC0ECdGohAgwACwALIA9BADYCACATQQA2AgALIAEgEEEIazYCHAsgFEEQaiQAIA4LsgcBG38jAEEQayIUJAACQCADIAEoAgQiDSABKAIcIgJqSQ0AIAMgDWshCwNAIAIgC09FBEAgASACIA1qIAQgCyAJQQEQECACaiECDAELCyABIAs2AhxBASABKAIQIgIgAyABKAIEIhBrIgxBASABKAK4AXQiC2sgAiAMIAJrIAtLGyABKAIYGyIVIBVBAU0bIR0gDEF/IAEoArwBQQFrdEF/cyIZayICQQAgAiAMTRshGiAMIBVrIR4gBiAGQQNqIgIgAiAGSRshHyABKAJkIiAgDCAZcUEDdGoiEUEEaiESIAEoAlwgAykAACAIfkHAACABKALAAWutiKdBAnRqIiEoAgAhCkH/HyABKALMASICIAJB/x9PGyEiIANBBGohFiAHQQFrIQsgECABKAIMIg9qIRsgASgCCCIXIA9qIRwgDCAPayEjIAxBCWohE0EBIAEoAsQBdCEYIAYhAgNAIAIgH0cEQCAMAn8gAkEDRgRAIAUoAgBBAWsMAQsgBSACQQJ0aigCAAsiDWshBwJAAn8gIyANQQFrIiRLBEAgByAVSQ0CIAMoAAAgAyANaygAAEcNAiAWIBYgDWsgBBAGDAELIB4gJE0gByAPa0F8S3INASADKAAAIAcgF2oiBygAAEcNASAWIAdBBGogBCAcIBsQBQtBBGoiByALTQ0AIAAgDkEDdGoiCyAHNgIEIAsgAiAGa0EBajYCACAOQQFqIQ4gByAiSw0DIAciCyADaiAERg0DCyACQQFqIQIMAQsLICEgDDYCACAMQQNqIQxBACEHQQAhBQJAA0AgGEUgCiAdSXINASADIAUgByAFIAdJGyICaiEGAn8gDyACIApqTQRAIAYgCiAQaiACaiAEEAYgAmohAiAQDAELIBcgECAGIAogF2ogAmogBCAcIBsQBSACaiICIApqIA9JGwshBiACIAtLBEAgACAOQQN0aiILIAI2AgQgCyAMIAprNgIAIAIgCmogEyACIBMgCmtLGyETIA5BAWohDiACQYAgSw0CIAIhCyACIANqIARGDQILICAgCiAZcUEDdGohDQJAAkACQCAGIApqIAJqLQAAIAIgA2otAABJBEAgESAKNgIAIAogGksNASAUQQxqIREMBQsgEiAKNgIAIAogGk0NAiANIRIgAiEHDAELIAIhBSANQQRqIhEhDQsgGEEBayEYIA0oAgAhCgwBCwsgFEEMaiESCyASQQA2AgAgEUEANgIAIAEgE0EIazYCHAsgFEEQaiQAIA4LmwYBFH8jAEEQayITJAACQCADIAEoAgQiCiABKAIcIgJqSQ0AIAMgCmshCwNAIAIgC09FBEAgASACIApqIAQgCyAJQQAQECACaiECDAELCyABIAs2AhxBASABKAIQIgIgAyABKAIEIhdrIgxBASABKAK4AXQiC2sgAiAMIAJrIAtLGyABKAIYGyIPIA9BAU0bIRggDEF/IAEoArwBQQFrdEF/cyIUayICQQAgAiAMTRshFSAGIAZBA2oiAiACIAZJGyEZIAEoAmQiGiAMIBRxQQN0aiIQQQRqIREgASgCXCADKQAAIAh+QcAAIAEoAsABa62Ip0ECdGoiGygCACENQf8fIAEoAswBIgIgAkH/H08bIRwgA0EEaiEWIAdBAWshCyAMIAEoAgxrIR0gDEEJaiESQQEgASgCxAF0IQcgBiECA0AgAiAZRwRAAkACfyACQQNGBEAgBSgCAEEBawwBCyAFIAJBAnRqKAIACyIKQQFrIB1P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ASAJIBgpAgA3A3ggDCAlIAlB+ABqIAlBzAJqICQgDyAnICEQGiEKDAELIAMgGmohCyADIAxqIQggGCgCCCENIBopAAAhSyAMIBopAAg3AAggDCBLNwAAAkAgA0ERSQ0AIB8pAAAhSyAMIB8pAAg3ABggDCBLNwAQIANBEGtBEUgNACAMQSBqIQMgHyETA0AgEykAECFLIAMgEykAGDcACCADIEs3AAAgEykAICFLIAMgEykAKDcAGCADIEs3ABAgE0EgaiETIANBIGoiAyAISQ0ACwsgCCANayEDIAkgCzYCzAIgCCAPayANSQRAIA0gCCAna0sNDyAhICEgAyAPayILaiIDIBVqTwRAIAggAyAVEAoaDAILIAsgFWohFSAIIANBACALaxAKIAtrIQggDyEDCyANQRBPBEAgAykAACFLIAggAykACDcACCAIIEs3AAAgFUERSA0BIAggFWohCyAIQRBqIQgDQCADKQAQIUsgCCADKQAYNwAIIAggSzcAACADKQAgIUsgCCADKQAoNwAYIAggSzcAECADQSBqIQMgCEEgaiIIIAtJDQALDAELAkAgDUEHTQRAIAggAy0AADoAACAIIAMtAAE6AAEgCCADLQACOgACIAggAy0AAzoAAyAIIAMgDUECdCILQeDPAGooAgBqIgMoAAA2AAQgAyALQYDQAGooAgBrIQMMAQsgCCADKQAANwAACyAVQQlJDQAgCCAVaiENIAhBCGoiCyADQQhqIgNrQQ9MBEADQCALIAMpAAA3AAAgA0EIaiEDIAtBCGoiCyANSQ0ADAILAAsgAykAACFLIAsgAykACDcACCALIEs3AAAgFUEZSA0AIAhBGGohCANAIAMpABAhSyAIIAMpABg3AAggCCBLNwAAIAMpACAhSyAIIAMpACg3ABggCCBLNwAQIANBIGohAyAIQSBqIgggDUkNAAsLIApBiH9LBEAgCiEEDA4LIBggEDYCCCAYIA42AgQgGCAUNgIAICQhFwwDCyANQSBrIQgCQAJAIA0gF0sNACAMIBgoAgQiFiADaiIKaiAISw0AIApBIGogJSAMa00NAQsgCSAYKAIINgKQASAJIBgpAgA3A4gBIAwgJSAIIAlBiAFqIAlBzAJqIBcgDyAnICEQciEKDAILIAMgDGohCCAYKAIIIRMgCykAACFLIAwgCykACDcACCAM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SyAMIBMpABg3ABggDCBLNwAQIAhBEGtBEUgNACATQRBqIQMgDEEgaiEIA0AgAykAECFLIAggAykAGDcACCAIIEs3AAAgAykAICFLIAggAykAKDcAGCAIIEs3ABAgA0EgaiEDIAhBIGoiCCAKSQ0ACwsgCiANayEDIAkgCzYCzAIgCiAPayANSQRAIA0gCiAna0sNDSAhICEgAyAPayIIaiIDIBVqTwRAIAogAyAVEAoaDAMLIAggFWohFSAKIANBACAIaxAKIAhrIQogDyEDCyANQRBPBEAgAykAACFLIAogAykACDcACCAKIEs3AAAgFUERSA0CIAogFWohCyAKQRBqIQgDQCADKQAQIUsgCCADKQAYNwAIIAggSzcAACADKQAgIUsgCCADKQAoNwAYIAggSzcAECADQSBqIQMgCEEgaiIIIAtJDQALDAILAkAgDUEHTQRAIAogAy0AADoAACAKIAMtAAE6AAEgCiADLQACOgACIAogAy0AAzoAAyAKIAMgDUECdCIIQeDPAGooAgBqIgMoAAA2AAQgAyAIQYDQAGooAgBrIQMMAQsgCiADKQAANwAACyAVQQlJDQEgCiAVaiELIApBCGoiCCADQQhqIgNrQQ9MBEADQCAIIAMpAAA3AAAgA0EIaiEDIAhBCGoiCCALSQ0ADAMLAAsgAykAACFLIAggAykACDcACCAIIEs3AAAgFUEZSA0BIApBGGohCANAIAMpABAhSyAIIAMpABg3AAggCCBLNwAAIAMpACAhSyAIIAMpACg3ABggCCBLNwAQIANBIGohAyAIQSBqIgggC0kNAAsMAQsCQAJAIAkoAswCIgogDSgCACIDaiILIBdLDQAgDCANKAIEIhAgA2oiDmogHUsNACAOQSBqICUgDGtNDQELIAkgDSgCCDYCcCAJIA0pAgA3A2ggDCAlIAlB6ABqIAlBzAJqIBcgDyAnICEQGiEODAELIAMgDGohCCANKAIIIQ0gCikAACFLIAwgCikACDcACCAMIEs3AAACQCADQRFJDQAgCikAECFLIAwgCikAGDcAGCAMIEs3ABAgA0EQa0ERSA0AIApBEGohAyAMQSBqIQoDQCADKQAQIUsgCiADKQAYNwAIIAogSzcAACADKQAgIUsgCiADKQAoNwAYIAogSzcAECADQSBqIQMgCkEgaiIKIAhJDQALCyAI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a0EPTARAA0AgCCADKQAANwAAIANBCGohAyAIQQhqIgggDUkNAAwCCwALIAMpAAAhSyAIIAMpAAg3AAggCCBLNwAAIAxBGUgNACAKQRhqIQgDQCADKQAQIUsgCCADKQAYNwAIIAggSzcAACADKQAgIUsgCCADKQAoNwAYIAggSzcAECADQSBqIQMgCEEgaiIIIA1JDQALCyAEQYh/Sw0MIBFBAWshESAEIAtqIQsMAQsLIBFBAEwNCCADIA5HBEBBun8hBCADIA5rIgMgICALa0sNCyALIA4gAxBZIAMgC2ohCyAIIANrIQgLIAkgAEGI7AFqIgM2AswCIABBADYChOwBIABBiOwFaiEWIAkgCDYCqAEgCSAMNgKsASAJIBA2ArABAkACQAJAIAhBgIAESg0AIAsgCCAMaiIEaiAgQSBrSw0AIARBIGogICALa00NAQsgCSAJKAKwATYCMCAJIAkpA6gBNwMoIAsgICAJQShqIAlBzAJqIBYgDyAjIBoQGiEEDAELIAMgCGohDSAIIAtqIQogAykAACFLIAsgAykACDcACCALIEs3AAACQCAIQRFJDQAgACkAmOwBIUsgCyAAQaDsAWopAAA3ABggCyBLNwAQIAhBEGtBEUgNACAAQZjsAWohAyALQSBqIQgDQCADKQAQIUsgCCADKQAYNwAIIAggSzcAACADKQAgIUsgCCADKQAoNwAYIAggSzcAECADQSBqIQMgCEEgaiIIIApJDQALCyAKIBBrIQMgCSANNgLMAiAKIA9rIBBJBEAgECAKICNrSw0KIBogGiADIA9rIghqIgMgDGpPBEAgCiADIAwQChoMAgsgCiADQQAgCGsQCiAJIAggDGoiDDYCrAEgCGshCiAPIQMLIBBBEE8EQCADKQAAIUsgCiADKQAINwAIIAogSzcAACAMQRFIDQEgCiAMaiENIApBEGohCANAIAMpABAhSyAIIAMpABg3AAggCCBLNwAAIAMpACAhSyAIIAMpACg3ABggCCBLNwAQIANBIGohAyAIQSBqIgggDUkNAAsMAQsCQCAQQQdNBEAgCiADLQAAOgAAIAogAy0AAToAASAKIAMtAAI6AAIgCiADLQADOgADIAogAyAQQQJ0IghB4M8AaigCAGoiAygAADYABCADIAhBgNAAaigCAGshAwwBCyAKIAMpAAA3AAALIAko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ayIDNgLoASAJIAMoAAA2AuABDAELIAMgCSgC7AEiDkYNACAJIAQgAyAOayAEQQN2IgQgAyAEayAOSRsiBEEDdGs2AuQBIAkgAyAEayIDNgLoASAJIAMoAAA2AuABCyAJIAg2AqgBIAkgETYCrAEgCSAKNgKwAQJAAkACQCAJKALMAiIDIAhqIg4gFksNACALIAggEWoiBGogFUsNACAEQSBqICAgC2tNDQELIAkgCSgCsAE2AiAgCSAJKQOoATcDGCALICAgCUEYaiAJQcwCaiAWIA8gIyAaEBohBAwBCyAIIAtqIQwgAykAACFLIAsgAykACDcACCALIEs3AAACQCAIQRFJDQAgAykAECFLIAsgAykAGDcAGCALIEs3ABAgCEEQa0ERSA0AIANBEGohAyALQSBqIQgDQCADKQAQIUsgCCADKQAYNwAIIAggSzcAACADKQAgIUsgCCADKQAoNwAYIAggSzcAECADQSBqIQMgCEEgaiIIIAxJDQALCyAMIAprIQMgCSAONgLMAiAMIA9rIApJBEAgCiAMICNrSw0LIBogGiADIA9rIg5qIgMgEWpPBEAgDCADIBEQChoMAgsgDCADQQAgDmsQCiAJIA4gEWoiETYCrAEgDmshDCAPIQMLIApBEE8EQCADKQAAIUsgDCADKQAINwAIIAwgSzcAACARQRFIDQEgDCARaiEKIAxBEGohCANAIAMpABAhSyAIIAMpABg3AAggCCBLNwAAIAMpACAhSyAIIAMpACg3ABggCCBLNwAQIANBIGohAyAIQSBqIgggCkkNAAsMAQsCQCAKQQdNBEAgDCADLQAAOgAAIAwgAy0AAToAASAMIAMtAAI6AAIgDCADLQADOgADIAwgAyAKQQJ0IghB4M8AaigCAGoiAygAADYABCADIAhBgNAAaigCAGshAwwBCyAMIAMpAAA3AAALIAkoAqwBIg5BCUkNACAMIA5qIQogDEEIaiIIIANBCGoiA2tBD0wEQANAIAggAykAADcAACADQQhqIQMgCEEIaiIIIApJDQAMAgsACyADKQAAIUsgCCADKQAINwAIIAggSzcAACAOQRlIDQAgDEEYaiEIA0AgAykAECFLIAggAykAGDcACCAIIEs3AAAgAykAICFLIAggAykAKDcAGCAIIEs3ABAgA0EgaiEDIAhBIGoiCCAKSQ0ACwsg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AWoiB0H//wNLDQEMAgsCQAJAIAcgDkkNACAHIAtqIgcpAAAgIlINACAAQQhqIAdBCGogChAGQQhqIQUgACAHayEIA0AgACADTSAHIA9Ncg0CIABBAWsiBi0AACAHQQFrIgctAABHDQIgBUEBaiEFIAYhAAwACwALAkAgCSAUc0H/AXENACAJQQh2IgcgGU0NACAHIBJqIgkpAAAgIlINACAAQQhqIAlBCGogCiATIA8QBUEIaiEFIAwgByAWamshCANAIAkgGk0gACADTXINAiAAQQFrIgYtAAAgCUEBayIJLQAARw0CIAVBAWohBSAGIQAMAAsACwJAAkACQCAIIA5LBEAgCCALaiIHKAAAIAAoAABHDQEMAwsgDSAec0H/AXENACANQQh2IgggGU0NACAIIBJqIgcoAAAgACgAAEYNAQsgACAAIANrQQh1akEBaiEADAULIAggFmohCAsgFSAAKQABIiJC48iVvcub741PfiImICSIp0ECdGoiBigCACEFIBwgJiAliKciFEEGdkH8//8fcWooAgAhDSAGIBE2AgAgAEEBaiEGAkACQCAFIA5JDQAgBSALaiIJKQAAICJSDQAgAEEJaiAJQQhqIAoQBkEIaiEFIAYgCWshCANAIAkgD00gAyAGT3INAiAGQQFrIgAtAAAgCUEBayIJLQAARw0CIAVBAWohBSAAIQYMAAsACwJAIA0gFHNB/wFxDQAgDUEIdiINIBlNDQAgDSASaiIJKQAAICJSDQAgAEEJaiAJQQhqIAogEyAPEAVBCGohBSARIA0gFmprIQgDQCAJIBpNIAMgBk9yDQIgBkEBayIALQAAIAlBAWsiCS0AAEcNAiAFQQFqIQUgACEGDAALAAsgB0EEaiEGIABBBGohBSAIIA5JBEAgBSAGIAogEyAPEAVBBGohBSAMIAhrIQgDQCAAIANNIAcgGk1yDQMgAEEBayIGLQAAIAdBAWsiBy0AAEcNAyAFQQFqIQUgBiEADAALAAsgBSAGIAoQBkEEaiEFIAAgB2shCANAIAAgA00gByAPTXINAiAAQQFrIgYtAAAgB0EBayIHLQAARw0CIAVBAWohBSAGIQAMAAsACyAGIQALIAAgA2shBwJAIAAgEE0EQCADKQAAISIgASgCDCIGIAMpAAg3AAggBiAiNwAAIAdBEUkNASADKQAQISIgASgC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IiNC48iVvcub741PfiIlICSIp0ECdGoiBSgCACEHIBcgI6dBsfPd8XlsIgwgDXZBAnRqIhQoAgAhCCAcICUgIoinIhtBBnZB/P//H3FqKAIAIQkgHyAMIB52IiBBBnZB/P//H3FqKAIAIREgFCAAIAtrIgw2AgAgBSAMNgIAAkACQAJAIAxBAWoiFCAEayIFIA5rQXxLDQAgEiAFIBZraiAFIAtqIAUgDkkiBRsiISgAACAAKAABRw0AIABBBWogIUEEaiAKIBMgCiAFGyAPEAUhByAAQQFqIgAgA2shCAJAIAAgEE0EQCADKQAAISMgASgCDCIFIAMpAAg3AAggBSAjNwAAIAhBEUkNASADKQAQISMgASgCDCIFIAMpABg3ABggBSAjNwAQIAhBIUgNASADQRBqIQMgBSAIaiEJIAVBIGohBQNAIAMpABAhIyAFIAMpABg3AAggBSAjNwAAIAMpACAhIyAFIAMpACg3ABggBSAjNwAQIANBIGohAyAFQSBqIgUgCUkNAAsMAQsgASgCDCADIAMgCGogEBAHCyABIAEoAgwgCGo2AgwgASgCBCEDIAhBgIAETwRAIAFBATYCJCABIAMgASgCAGtBA3U2AigLIAdBBGohBSADQQE2AgAgAyAIOwEEIAdBAWoiB0H//wNLDQEMAgsCQAJAIAcgDkkNACAHIAtqIgcpAAAgI1INACAAQQhqIAdBCGogChAGQQhqIQUgACAHayEIA0AgACADTSAHIA9Ncg0CIABBAWsiBi0AACAHQQFrIgctAABHDQIgBUEBaiEFIAYhAAwACwALAkAgCSAbc0H/AXENACAJQQh2IgcgGU0NACAHIBJqIgkpAAAgI1INACAAQQhqIAlBCGogCiATIA8QBUEIaiEFIAwgByAWamshCANAIAkgGk0gACADTXINAiAAQQFrIgYtAAAgCUEBayIJLQAARw0CIAVBAWohBSAGIQAMAAsACwJAAkACQCAIIA5LBEAgCCALaiIHKAAAIAAoAABHDQEMAwsgESAgc0H/AXENACARQQh2IgggGU0NACAIIBJqIgcoAAAgACgAAEYNAQsgACAAIANrQQh1akEBaiEADAULIAggFmohCAsgFSAAKQABIiNC48iVvcub741PfiIlICSIp0ECdGoiBigCACEFIBwgJSAiiKciG0EGdkH8//8fcWoo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A0EQaiEDIAUgB2ohCCAHQSBqIQcDQCADKQAQISIgByADKQAYNwAIIAcgIjcAACADKQAgISIgByADKQAoNwAYIAcgIjcAECADQSBqIQMgB0EgaiIHIAhJDQALDAELIAEoAgwgAyADIAVqIAsQBwsgASABKAIMIAVqNgIMIAEoAgQhAyAFQYCABE8EQCABQQE2AiQgASADIAEoAgBrQQN1NgIoCyAJQQRqIQcgA0EBNgIAIAMgBTsBBCAJQQFqIghB//8DTQ0DDAELAkAgCkH/AXEEQCAAKAAAIQUMAQsgACgAACEFIBhBCHYiGCAeTQ0AIBYgGGoiCigAACAFRyAOIBFJcg0AIABBBGogCkEEaiAMIBcgExAFQQRqIQcDQAJAIAAgA00gCiAaTXINACAAQQFrIgYtAAAgCkEBayIKLQAARw0AIAdBAWohByAGIQAMAQsLIAAgA2shBgJAIAAgC00EQCADKQAAISIgASgCDCIFIAMpAAg3AAggBSAiNwAAIAZBEUkNASADKQAQISIgASgCDCIFIAMpABg3ABggBSAiNwAQIAZBIUgNASADQRBqIQMgBSAGaiEJIAVBIGohCANAIAMpABAhIiAIIAMpABg3AAggCCAiNwAAIAMpACAhIiAIIAMpACg3ABggCCAiNwAQIANBIGohAyAIQSBqIgggCUkNAAsMAQsgASgCDCADIAMgBmogCxAHCyABIAEoAgwgBmo2AgwgASgCBCEDIAZBgIAETwRAIAFBATYCJCABIAMgASgCAGtBA3U2AigLIAMgFSAYIBtqayIFQQNqNgIAIAMgBjsBBCAEIQYgBSEEIAdBA2siCEH//wNLDQEMAwsgBUH6PCANIBFqIgggDiARSyIKGygAAEcgCnJFBEAgAEEEaiAIQQRqIAwQBkEEaiEHIAAgCGshBQNAAkAgACADTSAIIBNNcg0AIABBAWsiBi0AACAIQQFrIggtAABHDQAgB0EBaiEHIAYhAAwBCwsgACADayEGAkAgACALTQRAIAMpAAAhIiABKAIMIgkgAykACDcACCAJICI3AAAgBkERSQ0BIAMpABAhIiABKAIMIgkgAykAGDcAGCAJICI3ABAgBkEhSA0BIANBEGohAyAGIAlqIQogCUEgaiEIA0AgAykAECEiIAggAykAGDcACCAIICI3AAAgAykAICEiIAggAykA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IARBABBWGiABQQA2AiQgASABKAIANgIEIAEgASgCCDYCDCAAIAAoAgwgBGoiBjYCDCAAIAY2AhwgACAGNgIQIAAgACgCBCAEazYCBAsgACABIAIgAyAEQQAQViAFQRBqJAALEAAgACABIAIgAyAEQQAQVgshACAAIAEgAiADIAQgBSAGIAdCgIDs/Mub741PQQYQuwELIQAgACABIAIgAyAEIAUgBiAHQoCAgNjLm++NT0EFELsBC/8JASN/IwBBEGsiEiQAAkAgAyABKAIEIgkgASgCHCICakkNACADIAlrIQgDQCACIAhPRQRAIAEgAiAJaiAEIAhBBEEAEBAgAmohAgwBCwsgASAINgIcQQEgASgCECICIAMgASgCBCITayILQQEgASgCuAF0IghrIAIgCyACayAISxsgASgCGBsiFCAUQQFNGyEgIAtBfyABKAK8AUEBa3RBf3MiGWsiAkEAIAIgC00bIRogASgCXCADKAAAQbHz3fF5bEEgIAEoAsABa3ZBAnRqIiEoAgAhCiABKAK0ASIQKAIAIhsgECgCBCIcayIVQX8gECgCvAFBAWt0QX9zIh1rIBAoAhAiFiAVIBZrIB1LGyEiIBwgFCAVayIXayEjIAsgFiAXamshJCAGIAZBA2oiAiACIAZJGyElIAEoAmQiJiALIBlxQQN0aiIRQQRqIQ1B/x8gASgCzAEiAiACQf8fTxshJyADQQRqIRggB0EBayEIIBMgASgCDCIeaiEfIAsgHmshKCALQQlqIQ5BASABKALEAXQhDyAQKALAASEpIAYhAgNAIAIgJUcEQCALAn8gAkEDRgRAIAUoAgBBAWsMAQsgBSACQQJ0aigCAAsiCWshBwJAAn8gKCAJQQFrIipLBEAgByAUSQ0CIAMoAAAgAyAJaygAAEcNAiAYIBggCWsgBBAGDAELICQgKk0gByAea0F8S3INASADKAAAIAcgI2oiBygAAEcNASAYIAdBBGogBCAbIB8QBQtBBGoiByAITQ0AIAAgDEEDdGoiCCAHNgIEIAggAiAGa0EBajYCACAMQQFqIQwgByAnSw0DIAciCCADaiAERg0DCyACQQFqIQIMAQsLICEgCzYCACALQQNqIQZBACEHQQAhBQJAAkACQAJAAkADQCAPRSAKICBJcg0CIAggAyAFIAcgBSAHSRsiAmogCiATaiILIAJqIAQQBiACaiICSQRAIAAgDEEDdGoiCCACNgIEIAggBiAKazYCACACIApqIA4gAiAOIAprSxshDiAMQQFqIQwgAiADaiAERiACQYAgS3INBSACIQgLICYgCiAZcUEDdGohCQJAAkACQCACIAtqLQAAIAIgA2otAABJBEAgESAKNgIAIAogGksNASASQQxqIREMBQsgDSAKNgIAIAogGk0NAiAJIQ0gAiEHDAELIAIhBSAJQQRqIhEhCQsgD0EBayEPIAkoAgAhCgwBCwsgEkEMaiENCyANQQA2AgAgEUEANgIADAELIA1BADYCACARQQA2AgAgD0UNAgsgECgCXCADKAAAQbHz3fF5bEEgIClrdkECdGohAiATIBdqIQ0gECgCZCELQQAhCkEAIQcDQCAPRQ0CIAIoAgAiBSAWTQ0CIAggAyAHIAogByAKSRsiAmogBSAcaiIJIAJqIAQgGyAfEAUgAmoiAkkEQCAAIAxBA3RqIgggAjYCBCAIIAYgBSAXaiIIazYCACACIAhqIA4gAiAOIAhrSxshDiAMQQFqIQwgAkGAIEsNAyACIQggAiADaiAERg0DCyAFICJNDQIgD0EBayEPIAIgByAJIAUgDWogAiAFaiAVSRsgAmotAAAgAiADai0AAEkiCRshByAKIAIgCRshCiALIAUgHXFBA3RqIAlBAnRqIQIMAAsACyANQQA2AgAgEUEANgIACyABIA5BCGs2AhwLIBJBEGokACAMC/wKASR/IwBBEGsiFCQAAkAgAyABKAIEIgwgASgCHCIJakkNACADIAxrIQgDQCAIIAlNRQRAIAEgCSAMaiAEIAhBA0EAEBAgCWohCQwBCwsgASAINgIcQQEgASgCECIIIAMgASgCBCITayINQQEgASgCuAF0IglrIAggDSAIayAJSxsgASgCGBsiFSAVQQFNGyEaIA1BfyABKAK8AUEBa3RBf3MiG2siCEEAIAggDU0bIRwgASgCXCADKAAAQbHz3fF5bEEgIAEoAsABa3ZBAnRqIiMoAgAhCiABKAK0ASIRKAIAIh0gESgCBCIeayIWQX8gESgCvAFBAWt0QX9zIh9rIBEoAhAiFyAWIBdrIB9LGyEkIB4gFSAWayIYayElIA0gFyAYamshJiAGIAZBA2oiCCAGIAhLGyEnIAEoAmQiKCANIBtxQQN0aiISQQRqIQ5B/x8gASgCzAEiCCAIQf8fTxshICADQQNqIRkgB0EBayEIIBMgASgCDCIhaiEiIA0gIWshKSANQQlqIQ9BASABKALEAXQhECARKALAASEqIAYhCQNAIAkgJ0cEQCANAn8gCUEDRgRAIAUoAgBBAWsMAQsgBSAJQQJ0aigCAAsiDGshBwJAAn8gKSAMQQFrIitLBEAgByAVSQ0CIAMgDGsoAAAgAygAAHNB////B3ENAiAZIBkgDGsgBBAGDAELICYgK00gByAha0F8S3INASAHICVqIgcoAAAgAygAAHNB////B3ENASAZIAdBA2ogBCAdICIQBQtBA2oiByAITQ0AIAAgC0EDdGoiCCAHNgIEIAggCSAGa0EBajYCACALQQFqIQsgByAgSw0DIAciCCADaiAERg0DCyAJQQFqIQkMAQsLIAECfwJAIAhBAksNACABIAIgAxCOASICIBpJDQAgDSACayIFQf//D0sNACADIAIgE2ogBBAGIgJBA0kNACAAIAI2AgQgACAFQQNqNgIAIAIgIE0EQEEBIQsgAiIIIANqIARHDQELQQEhCyANQQFqDAELICMgDTYCACANQQNqIQZBACEHQQAhBQJAAkACQAJAAkADQCAQRSAKIBpJcg0CIAggAyAFIAcgBSAHSRsiAmogCiATaiIJIAJqIAQQBiACaiICSQRAIAAgC0EDdGoiCCACNgIEIAggBiAKazYCACACIApqIA8gAiAPIAprSxshDyALQQFqIQsgAiADaiAERiACQYAgS3INBSACIQgLICggCiAbcUEDdGohDAJAAkACQCACIAlqLQAAIAIgA2otAABJBEAgEiAKNgIAIAogHEsNASAUQQxqIRIMBQsgDiAKNgIAIAogHE0NAiAMIQ4gAiEHDAELIAIhBSAMQQRqIhIhDAsgEEEBayEQIAwoAgAhCgwBCwsgFEEMaiEOCyAOQQA2AgAgEkEANgIADAELIA5BADYCACASQQA2AgAgEEUNAgsgESgCXCADKAAAQbHz3fF5bEEgICprdkECdGohCSATIBhqIQwgESgCZCEOQQAhCkEAIQcDQCAQRQ0CIAkoAgAiBSAXTQ0CIAggAyAHIAogByAKSRsiAmogBSAeaiIJIAJqIAQgHSAiEAUgAmoiAkkEQCAAIAtBA3RqIgggAjYCBCAIIAYgBSAYaiIIazYC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Bg8AAAAAAAAGEgAAAAAAAAYVAAAAAAAABhgAAAAAAAAGGwAAAAAAAAYeAAAAAAAABiEAAAAAAAEGIwAAAAAAAQYnAAAAAAACBisAAAAAAAMGMwAAAAAABAZDAAAAAAAFBmMAAAAAAAgGAwEAACAAAAQEAAAAMAAABAQAAAAQAAAEBQAAACAAAAUHAAAAIAAABQgAAAAgAAAFCgAAACAAAAULAAAAAAAABg4AAAAAAAAGEQAAAAAAAAYUAAAAAAAABhcAAAAAAAAGGgAAAAAAAAYdAAAAAAAABiAAAAAAABAGAwABAAAADwYDgAAAAAAOBgNAAAAAAA0GAyAAAAAADAYDEAAAAAALBgMIAAAAAAoGAwQAQbQjC3wBAAAAAwAAAAcAAAAPAAAAHwAAAD8AAAB/AAAA/wAAAP8BAAD/AwAA/wcAAP8PAAD/HwAA/z8AAP9/AAD//wAA//8BAP//AwD//wcA//8PAP//HwD//z8A//9/AP///wD///8B////A////wf///8P////H////z////9/AEHAJAuhAgEAAQABAAEAAQABAAIAAgACAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAP////////////8AAAAAAAAEAAMAAgACAAIAAgACAAIAAgACAAIAAgACAAEAAQABAAIAAgACAAIAAgACAAIAAgACAAMAAgABAAEAAQABAAEA//////////8AAAAAAAAAAAEABAADAAIAAgACAAIAAgACAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEA//////////////////8AAAAAAAAsAAAALQAAAC4AAAAvAAAACAAAAAkAAAAKAAAACgAAACAAQfEmC+QBAQIDBAUGBwgJCgsMDQ4PEBARERISExMUFBQUFRUVFRYWFhYWFhYWFxcXFxcXFxcYGBgYGBgYGBgYGBgYGBgYAAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gICEhIiIjIyQkJCQlJSUlJiYmJiYmJiYnJycnJycnJygoKCgoKCgoKCgoKCgoKCgpKSkpKSkpKSkpKSkpKSkpKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioAAAAAAAAAAAEAAAACAAAAAgAAAAMAAAADAAAABAAAAAQAAAAEAEHgKAv9JxMAAAAMAAAADQAAAAEAAAAGAAAAAQAAAAEAAAATAAAADQAAAA4AAAABAAAABwAAAAAAAAABAAAAFAAAAA8AAAAQAAAAAQAAAAYAAAAAAAAAAQAAABUAAAAQAAAAEQAAAAEAAAAFAAAAAAAAAAIAAAAVAAAAEgAAABIAAAABAAAABQAAAAAAAAACAAAAFQAAABIAAAATAAAAAwAAAAUAAAACAAAAAwAAABUAAAASAAAAEwAAAAMAAAAFAAAABAAAAAQAAAAVAAAAEwAAABQAAAAEAAAABQAAAAgAAAAEAAAAFQAAABMAAAAUAAAABAAAAAUAAAAQAAAABQAAABYAAAAUAAAAFQAAAAQAAAAFAAAAEAAAAAUAAAAWAAAAFQAAABYAAAAFAAAABQAAABAAAAAFAAAAFgAAABUAAAAWAAAABgAAAAUAAAAQAAAABQAAABYAAAAWAAAAFwAAAAYAAAAFAAAAIAAAAAUAAAAWAAAAFgAAABYAAAAEAAAABQAAACAAAAAGAAAAFgAAABYAAAAXAAAABQAAAAUAAAAgAAAABgAAABYAAAAXAAAAFwAAAAYAAAAFAAAAIAAAAAYAAAAWAAAAFgAAABYAAAAFAAAABQAAADAAAAAHAAAAFwAAABcAAAAWAAAABQAAAAQAAABAAAAABwAAABcAAAAXAAAAFgAAAAYAAAADAAAAQAAAAAgAAAAXAAAAGAAAABYAAAAHAAAAAwAAAAABAAAJAAAAGQAAABkAAAAXAAAABwAAAAMAAAAAAQAACQAAABoAAAAaAAAAGAAAAAcAAAADAAAAAAIAAAkAAAAbAAAAGwAAABkAAAAJAAAAAwAAAOcDAAAJAAAAEgAAAAwAAAANAAAAAQAAAAUAAAABAAAAAQAAABIAAAANAAAADgAAAAEAAAAGAAAAAAAAAAEAAAASAAAADgAAAA4AAAABAAAABQAAAAAAAAACAAAAEgAAABAAAAAQAAAAAQAAAAQAAAAAAAAAAgAAABIAAAAQAAAAEQAAAAMAAAAFAAAAAgAAAAMAAAASAAAAEQAAABIAAAAFAAAABQAAAAIAAAADAAAAEgAAABIAAAATAAAAAwAAAAUAAAAEAAAABAAAABIAAAASAAAAEwAAAAQAAAAEAAAABAAAAAQAAAASAAAAEgAAABMAAAAEAAAABAAAAAgAAAAFAAAAEgAAABIAAAATAAAABQAAAAQAAAAIAAAABQAAABIAAAASAAAAEwAAAAYAAAAEAAAACAAAAAUAAAASAAAAEgAAABMAAAAFAAAABAAAAAwAAAAGAAAAEgAAABMAAAATAAAABwAAAAQAAAAMAAAABgAAABIAAAASAAAAEwAAAAQAAAAEAAAAEAAAAAcAAAASAAAAEgAAABMAAAAEAAAAAwAAACAAAAAHAAAAEgAAABIAAAATAAAABgAAAAMAAACAAAAABwAAABIAAAATAAAAEwAAAAYAAAADAAAAgAAAAAgAAAASAAAAEwAAABMAAAAIAAAAAwAAAAABAAAIAAAAEgAAABMAAAATAAAABgAAAAMAAACAAAAACQAAABIAAAATAAAAEwAAAAgAAAADAAAAAAEAAAkAAAASAAAAEwAAABMAAAAKAAAAAwAAAAACAAAJAAAAEgAAABMAAAATAAAADAAAAAMAAAAAAgAACQAAABIAAAATAAAAEwAAAA0AAAADAAAA5wMAAAkAAAARAAAADAAAAAwAAAABAAAABQAAAAEAAAABAAAAEQAAAAwAAAANAAAAAQAAAAYAAAAAAAAAAQAAABEAAAANAAAADwAAAAEAAAAFAAAAAAAAAAEAAAARAAAADwAAABAAAAACAAAABQAAAAAAAAACAAAAEQAAABEAAAARAAAAAgAAAAQAAAAAAAAAAgAAABEAAAAQAAAAEQAAAAMAAAAEAAAAAgAAAAMAAAARAAAAEAAAABEAAAADAAAABAAAAAQAAAAEAAAAEQAAABAAAAARAAAAAwAAAAQAAAAIAAAABQAAABEAAAAQAAAAEQAAAAQAAAAEAAAACAAAAAUAAAARAAAAEAAAABEAAAAFAAAABAAAAAgAAAAFAAAAEQAAABAAAAARAAAABgAAAAQAAAAIAAAABQAAABEAAAARAAAAEQAAAAUAAAAEAAAACAAAAAYAAAARAAAAEgAAABEAAAAHAAAABAAAAAwAAAAGAAAAEQAAABIAAAARAAAAAwAAAAQAAAAMAAAABwAAABEAAAASAAAAEQAAAAQAAAADAAAAIAAAAAcAAAARAAAAEgAAABEAAAAGAAAAAwAAAAABAAAHAAAAEQAAABIAAAARAAAABgAAAAMAAACA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`\n\nlet _bytes: Uint8Array | undefined\n\n/** Decode the base64 string to bytes (cached after first call). */\nexport function getZstdWasmBytes(): Uint8Array {\n if (_bytes) return _bytes\n\n const binaryString = atob(ZSTD_WASM_BASE64)\n _bytes = new Uint8Array(binaryString.length)\n for (let i = 0; i < binaryString.length; i++) {\n _bytes[i] = binaryString.charCodeAt(i)\n }\n return _bytes\n}\n","/**\n * First-party zstd WASM decompression module.\n *\n * Directly instantiates the zstd WASM binary (from @bokuweb/zstd-wasm, MIT license)\n * without the Emscripten glue code that breaks webpack bundling.\n *\n * The WASM binary is base64-inlined to avoid bundler issues with\n * `new URL('./zstd.wasm', import.meta.url)` (e.g. Turbopack).\n *\n * Only exposes decompression with dictionary — the minimum needed for GTX.\n */\n\nimport {getZstdWasmBytes} from './zstdWasmInlined'\n\n// ─── WASM memory management ─────────────────────────────────────────────────\n\nlet wasmMemory: WebAssembly.Memory\nlet HEAP8: Int8Array\nlet HEAPU8: Uint8Array\nlet wasmExports: Record<string, CallableFunction>\nlet initialized = false\nlet initPromise: Promise<void> | undefined\n\nfunction updateMemoryViews(): void {\n const b = wasmMemory.buffer\n HEAP8 = new Int8Array(b)\n HEAPU8 = new Uint8Array(b)\n}\n\n// ─── WASM imports (matching the Emscripten-compiled binary's expectations) ──\n\nlet ABORT = false\nlet noExitRuntime = true\n\nfunction abort(what?: string): never {\n const msg = 'Aborted(' + (what ?? '') + ')'\n ABORT = true\n throw new WebAssembly.RuntimeError(msg)\n}\n\nfunction keepRuntimeAlive(): boolean {\n return noExitRuntime\n}\n\nfunction _proc_exit(code: number): void {\n if (!keepRuntimeAlive()) {\n ABORT = true\n }\n}\n\nfunction __abort_js(): never {\n abort('')\n}\n\nfunction __emscripten_runtime_keepalive_clear(): void {\n noExitRuntime = false\n}\n\n// Timer support (required by WASM but unused in practice for decompression)\nconst timers: Record<number, { id: ReturnType<typeof setTimeout>; timeout_ms: number }> = {}\nlet __emscripten_timeout: (which: number, now: number) => void\n\nfunction __setitimer_js(which: number, timeout_ms: number): number {\n if (timers[which]) {\n clearTimeout(timers[which].id)\n delete timers[which]\n }\n if (!timeout_ms) return 0\n const id = setTimeout(() => {\n delete timers[which]\n __emscripten_timeout(which, performance.now())\n }, timeout_ms)\n timers[which] = {id, timeout_ms}\n return 0\n}\n\nfunction alignMemory(size: number, alignment: number): number {\n return Math.ceil(size / alignment) * alignment\n}\n\nfunction _emscripten_resize_heap(requestedSize: number): boolean {\n const oldSize = HEAPU8.length\n requestedSize >>>= 0\n const maxHeapSize = 2147483648\n if (requestedSize > maxHeapSize) return false\n for (let cutDown = 1; cutDown <= 4; cutDown *= 2) {\n let overGrownHeapSize = oldSize * (1 + 0.2 / cutDown)\n overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296)\n const newSize = Math.min(maxHeapSize, alignMemory(Math.max(requestedSize, overGrownHeapSize), 65536))\n const pages = ((newSize - wasmMemory.buffer.byteLength + 65535) / 65536) | 0\n try {\n wasmMemory.grow(pages)\n updateMemoryViews()\n return true\n } catch { /* retry with smaller size */ }\n }\n return false\n}\n\n// The WASM binary expects imports keyed by single letters (Emscripten minification):\n// a: _proc_exit\n// b: __emscripten_runtime_keepalive_clear\n// c: __abort_js\n// d: __setitimer_js\n// e: _emscripten_resize_heap\nconst wasmImports = {\n a: _proc_exit,\n b: __emscripten_runtime_keepalive_clear,\n c: __abort_js,\n d: __setitimer_js,\n e: _emscripten_resize_heap,\n}\n\n// ─── Initialization ─────────────────────────────────────────────────────────\n\n/**\n * Initialize the zstd WASM module. Idempotent — safe to call multiple times.\n * Instantiates from the base64-inlined binary.\n */\nexport async function initZstd(): Promise<void> {\n if (initialized) return\n if (initPromise) return initPromise\n initPromise = doInit()\n return initPromise\n}\n\nasync function doInit(): Promise<void> {\n const binary = getZstdWasmBytes()\n const importObject = {a: wasmImports}\n const module = await WebAssembly.compile(binary.buffer as ArrayBuffer)\n const instance = await WebAssembly.instantiate(module, importObject)\n\n const exports = instance.exports as Record<string, WebAssembly.Global | WebAssembly.Memory | CallableFunction>\n\n // WASM exports (Emscripten minified names):\n // f: memory\n // g: __wasm_call_ctors (runtime init)\n // h: ZSTD_isError\n // n: ZSTD_createDCtx\n // o: ZSTD_freeDCtx\n // p: ZSTD_getFrameContentSize\n // q: ZSTD_decompress_usingDict\n // s: malloc\n // t: free\n wasmMemory = exports['f'] as WebAssembly.Memory\n updateMemoryViews()\n\n // Call constructors to initialize the runtime\n ;(exports['g'] as CallableFunction)()\n\n // Also set the timeout callback from exports\n __emscripten_timeout = exports['v'] as (which: number, now: number) => void\n\n wasmExports = exports as unknown as Record<string, CallableFunction>\n initialized = true\n}\n\n// ─── Public API ─────────────────────────────────────────────────────────────\n\n/** Create a decompression context. Returns an opaque handle. */\nexport function createDCtx(): number {\n if (!initialized) throw new Error('zstd WASM not initialized — call initZstd() first')\n return wasmExports['n']() as number\n}\n\n/** Free a decompression context. */\nexport function freeDCtx(dctx: number): void {\n if (!initialized) return\n wasmExports['o'](dctx)\n}\n\n/**\n * Decompress a zstd-compressed buffer using a dictionary.\n * Returns a newly allocated Uint8Array with the decompressed data.\n */\nexport function decompressUsingDict(\n dctx: number,\n compressed: Uint8Array,\n dictionary: Uint8Array,\n): Uint8Array {\n if (!initialized) throw new Error('zstd WASM not initialized — call initZstd() first')\n\n const malloc = wasmExports['s'] as (size: number) => number\n const free = wasmExports['t'] as (ptr: number) => void\n const getFrameContentSize = wasmExports['p'] as (src: number, srcSize: number) => number\n const decompress = wasmExports['q'] as (\n dctx: number, dst: number, dstCapacity: number,\n src: number, srcSize: number,\n dict: number, dictSize: number,\n ) => number\n const isError = wasmExports['h'] as (code: number) => number\n\n // Allocate WASM heap memory for input\n const srcPtr = malloc(compressed.byteLength)\n HEAP8.set(compressed, srcPtr)\n\n // Allocate for dictionary\n const dictPtr = malloc(dictionary.byteLength)\n HEAP8.set(dictionary, dictPtr)\n\n // Determine output size\n const contentSize = getFrameContentSize(srcPtr, compressed.byteLength)\n const dstCapacity = contentSize === -1 ? 1024 * 1024 : contentSize // 1MB default\n\n const dstPtr = malloc(dstCapacity)\n try {\n const sizeOrError = decompress(dctx, dstPtr, dstCapacity, srcPtr, compressed.byteLength, dictPtr, dictionary.byteLength)\n\n if (isError(sizeOrError)) {\n throw new Error(`zstd decompression failed with code ${sizeOrError}`)\n }\n\n // Copy result out of WASM heap (slice creates an independent copy)\n const result = new Uint8Array(HEAPU8.buffer, dstPtr, sizeOrError).slice()\n return result\n } finally {\n free(dstPtr)\n free(srcPtr)\n free(dictPtr)\n }\n}\n","/**\n * GTX file reader — binary format for bundled genomic signal data.\n *\n * A GTX file packs multiple experiments (BigWig-equivalent signal tracks) into\n * a single file with:\n * - Tile-based indexing (flat arrays, not R-trees)\n * - zstd dictionary compression for small chunk sizes\n * - Per-experiment metadata\n * - Multi-resolution zoom levels\n *\n * Uses HTTP Range Requests for selective remote access — never downloads\n * the full file.\n *\n * Layer 1 (Data + Layout): no DOM, no canvas.\n */\n\nimport {fetchRange} from '../io/rangeReader'\nimport {BinaryParser} from '../io/binaryParser'\nimport type {WigFeature} from '../types'\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport interface GtxHeader {\n version: number\n genome: string\n nExperiments: number\n resolution: number\n payloadEncoding: number\n nZoomLevels: number\n chromDirectoryOffset: number\n experimentMetadataOffset: number\n dictionaryOffset: number\n dictionarySize: number\n zoomDirectoryOffset: number\n groupStatsDirectoryOffset: number\n}\n\nexport interface ChromEntry {\n name: string\n length: number\n tileIndexOffset: number\n tileIndexLength: number\n nTiles: number\n}\n\nexport interface ExperimentEntry {\n id: string\n experimentIndex: number\n metadata: Map<string, string>\n}\n\nexport interface ExperimentPointer {\n offset: number\n size: number\n}\n\nexport interface TileEntry {\n positionsOffset: number\n positionsSize: number\n experimentPointers: ExperimentPointer[]\n}\n\nexport interface ZoomLevel {\n reductionLevel: number\n chromTileIndexes: Map<string, ZoomChromEntry>\n}\n\nexport interface ZoomChromEntry {\n tileIndexOffset: number\n tileIndexLength: number\n nTiles: number\n}\n\n// ─── Constants ───────────────────────────────────────────────────────────────\n\nconst GTX_MAGIC = 0x00585447 // \"GTX\\0\" as little-endian u32\nconst HEADER_FETCH_SIZE = 256 // enough for any reasonable genome string\n\n// Standard tile sizes used by the Rust GTX writer (tried in order).\n// The writer picks the first size where ceil(chromLength / tileSize) produces\n// nTiles. We replicate this logic to get the exact integer tile boundaries.\nconst STANDARD_TILE_SIZES = [50_000, 100_000, 200_000, 500_000, 1_000_000]\n\nimport {initZstd, createDCtx, freeDCtx, decompressUsingDict} from './zstdWasm'\n\n/**\n * Infer the integer tile size from chromosome length and tile count.\n * Matches the Rust writer's logic: tile_size is a fixed integer, and\n * n_tiles = ceil(chrom_length / tile_size). The last tile may be smaller.\n */\nfunction inferTileSize(chromLength: number, nTiles: number): number {\n for (const ts of STANDARD_TILE_SIZES) {\n if (Math.ceil(chromLength / ts) === nTiles) {\n return ts\n }\n }\n // Fallback: derive from nTiles (integer division, rounding up)\n return Math.ceil(chromLength / nTiles)\n}\n\n// ─── Reader ──────────────────────────────────────────────────────────────────\n\nexport class GtxReader {\n private readonly url: string\n\n // Cached init data\n private header?: GtxHeader\n private dictionary?: Uint8Array\n private dctx?: number\n private experiments: ExperimentEntry[] = []\n private experimentIdToIndex = new Map<string, number>()\n private chromosomes = new Map<string, ChromEntry>()\n private chromOrder: string[] = [] // ordered chromosome names (matches chrom directory order)\n private tileIndexCache = new Map<string, TileEntry[]>()\n private zoomLevels: ZoomLevel[] = []\n private zoomTileIndexCache = new Map<string, TileEntry[]>() // key: `${zoomIdx}:${chrom}`\n\n private initialized = false\n private initPromise?: Promise<void>\n\n constructor(url: string) {\n this.url = url\n }\n\n // ─── Initialization ──────────────────────────────────────────────────\n\n /**\n * Initialize the reader: fetch header, dictionary, experiment metadata,\n * and chromosome directory. Idempotent — safe to call multiple times.\n *\n * Note: init does NOT forward the caller's AbortSignal to avoid a race\n * condition where aborting one track's fetch would leave the shared reader\n * half-initialized (header set but metadata empty), permanently broken\n * for all subsequent callers.\n */\n async init(_signal?: AbortSignal): Promise<void> {\n if (this.initialized) return\n if (this.initPromise) return this.initPromise\n this.initPromise = this._doInit().catch(err => {\n // Reset so a future init() call can retry\n this.initPromise = undefined\n throw err\n })\n return this.initPromise\n }\n\n private async _doInit(): Promise<void> {\n await initZstd()\n\n // Step 1: Fetch and parse header (no signal — init must complete atomically)\n const headerBuf = await fetchRange(this.url, {start: 0, size: HEADER_FETCH_SIZE})\n this.header = this.parseHeader(new BinaryParser(new DataView(headerBuf), true))\n const h = this.header\n\n // Step 2: Fetch metadata + dictionary and chrom + zoom directories.\n // File layout: header → metadata → dictionary → DATA BLOCKS → chrom dir → zoom dir → checksum\n // Metadata and dictionary are adjacent (~65 KB total).\n // Chrom and zoom directories are adjacent at the end (~8 KB total).\n // Two range requests instead of downloading the entire file.\n\n // Metadata: experimentMetadataOffset → dictionaryOffset (adjacent)\n const metadataSize = h.dictionaryOffset - h.experimentMetadataOffset\n\n // Batch metadata + dictionary (they're adjacent)\n const metaDictStart = h.experimentMetadataOffset\n const metaDictSize = metadataSize + h.dictionarySize\n\n // Chrom + zoom directories: chromDirectoryOffset → end of file\n // (the trailing 8-byte xxHash64 checksum won't affect parsing since\n // the directory parsers read a known structure and stop)\n const dirStart = h.chromDirectoryOffset\n const hasZoom = h.nZoomLevels > 0 && h.zoomDirectoryOffset > 0\n\n const dirFetchSize = this.computeDirFetchSize(h)\n\n // Fetch both ranges concurrently\n const [metaDictBuf, dirBuf] = await Promise.all([\n fetchRange(this.url, {start: metaDictStart, size: metaDictSize}),\n fetchRange(this.url, {start: dirStart, size: dirFetchSize}),\n ])\n\n // Parse metadata (first part of metaDictBuf)\n this.parseExperimentMetadata(new BinaryParser(\n new DataView(metaDictBuf, 0, metadataSize),\n true,\n ))\n\n // Parse dictionary (second part of metaDictBuf)\n this.dictionary = new Uint8Array(metaDictBuf, metadataSize, h.dictionarySize)\n\n // Create decompression context\n this.dctx = createDCtx()\n\n // Parse chromosome directory — clamp to actual buffer size\n const chromDirLength = hasZoom\n ? Math.min(h.zoomDirectoryOffset - h.chromDirectoryOffset, dirBuf.byteLength)\n : dirBuf.byteLength\n this.parseChromDirectory(new BinaryParser(\n new DataView(dirBuf, 0, chromDirLength),\n true,\n ))\n\n // Parse zoom directory if present.\n // Exclude the trailing 8-byte xxHash64 checksum from the DataView\n // so the parser doesn't read into it and misinterpret random bytes.\n if (hasZoom) {\n const zoomStart = h.zoomDirectoryOffset - dirStart\n const zoomLength = dirBuf.byteLength - zoomStart - 8 // subtract 8-byte checksum\n if (zoomStart >= 0 && zoomLength > 0) {\n this.parseZoomDirectory(new BinaryParser(\n new DataView(dirBuf, zoomStart, zoomLength),\n true,\n ))\n }\n }\n\n this.initialized = true\n }\n\n // ─── Header Parsing ──────────────────────────────────────────────────\n\n private parseHeader(p: BinaryParser): GtxHeader {\n const magic = p.getUInt()\n if (magic !== GTX_MAGIC) {\n throw new Error(`Not a GTX file (magic: 0x${magic.toString(16)}, expected 0x${GTX_MAGIC.toString(16)})`)\n }\n\n const version = p.getUShort()\n const genomeLen = p.getUShort()\n const genome = p.getFixedLengthString(genomeLen)\n const nExperiments = p.getUInt()\n const resolution = p.getUInt()\n const payloadEncoding = p.getByte()\n const nZoomLevels = p.getByte()\n const chromDirectoryOffset = this.readU64(p)\n const experimentMetadataOffset = this.readU64(p)\n const dictionaryOffset = this.readU64(p)\n const dictionarySize = p.getUInt()\n const zoomDirectoryOffset = this.readU64(p)\n const groupStatsDirectoryOffset = this.readU64(p)\n\n return {\n version, genome, nExperiments, resolution, payloadEncoding,\n nZoomLevels, chromDirectoryOffset, experimentMetadataOffset,\n dictionaryOffset, dictionarySize, zoomDirectoryOffset,\n groupStatsDirectoryOffset,\n }\n }\n\n // ─── Metadata Parsing ────────────────────────────────────────────────\n\n private parseExperimentMetadata(p: BinaryParser): void {\n const count = p.getUInt()\n for (let i = 0; i < count; i++) {\n const idLen = p.getUShort()\n const id = p.getFixedLengthString(idLen)\n const experimentIndex = p.getUInt()\n const nMeta = p.getUShort()\n const metadata = new Map<string, string>()\n for (let j = 0; j < nMeta; j++) {\n const keyLen = p.getUShort()\n const key = p.getFixedLengthString(keyLen)\n const valLen = p.getUShort()\n const val = p.getFixedLengthString(valLen)\n metadata.set(key, val)\n }\n const entry: ExperimentEntry = {id, experimentIndex, metadata}\n this.experiments.push(entry)\n this.experimentIdToIndex.set(id, experimentIndex)\n }\n }\n\n private parseChromDirectory(p: BinaryParser): void {\n const nChromosomes = p.getUShort()\n for (let i = 0; i < nChromosomes; i++) {\n const nameLen = p.getUShort()\n const name = p.getFixedLengthString(nameLen)\n const length = p.getUInt()\n const tileIndexOffset = this.readU64(p)\n const tileIndexLength = p.getUInt()\n const nTiles = p.getUInt()\n this.chromosomes.set(name, {name, length, tileIndexOffset, tileIndexLength, nTiles})\n this.chromOrder.push(name)\n }\n }\n\n private parseZoomDirectory(p: BinaryParser): void {\n const nZoomLevels = p.getByte()\n for (let i = 0; i < nZoomLevels; i++) {\n const reductionLevel = p.getUInt()\n const nChroms = p.getUShort()\n const chromTileIndexes = new Map<string, ZoomChromEntry>()\n for (let j = 0; j < nChroms; j++) {\n // Zoom entries are positional — no name strings.\n // Chromosome order matches the main chrom directory.\n const tileIndexOffset = this.readU64(p)\n const tileIndexLength = p.getUInt()\n const nTiles = p.getUInt()\n const name = this.chromOrder[j] ?? `chrom_${j}`\n chromTileIndexes.set(name, {tileIndexOffset, tileIndexLength, nTiles})\n }\n this.zoomLevels.push({reductionLevel, chromTileIndexes})\n }\n }\n\n // ─── Tile Index Loading ──────────────────────────────────────────────\n\n /**\n * Lazily fetch and parse the tile index for a chromosome.\n * Cached after first load.\n */\n async loadTileIndex(chrom: string, signal?: AbortSignal): Promise<TileEntry[]> {\n await this.init(signal)\n\n const cached = this.tileIndexCache.get(chrom)\n if (cached) return cached\n\n const chromEntry = this.chromosomes.get(chrom)\n if (!chromEntry) throw new Error(`Unknown chromosome: ${chrom}`)\n\n const buf = await fetchRange(this.url, {\n start: chromEntry.tileIndexOffset,\n size: chromEntry.tileIndexLength,\n }, signal)\n\n const tiles = this.parseTileIndex(new BinaryParser(new DataView(buf), true), chromEntry.nTiles)\n this.tileIndexCache.set(chrom, tiles)\n return tiles\n }\n\n private async loadZoomTileIndex(zoomIdx: number, chrom: string, signal?: AbortSignal): Promise<TileEntry[]> {\n const cacheKey = `${zoomIdx}:${chrom}`\n const cached = this.zoomTileIndexCache.get(cacheKey)\n if (cached) return cached\n\n const zoomLevel = this.zoomLevels[zoomIdx]\n if (!zoomLevel) throw new Error(`Unknown zoom level: ${zoomIdx}`)\n\n const chromEntry = zoomLevel.chromTileIndexes.get(chrom)\n if (!chromEntry) throw new Error(`Unknown chromosome in zoom: ${chrom}`)\n\n const buf = await fetchRange(this.url, {\n start: chromEntry.tileIndexOffset,\n size: chromEntry.tileIndexLength,\n }, signal)\n\n const tiles = this.parseTileIndex(new BinaryParser(new DataView(buf), true), chromEntry.nTiles)\n this.zoomTileIndexCache.set(cacheKey, tiles)\n return tiles\n }\n\n private parseTileIndex(p: BinaryParser, nTiles: number): TileEntry[] {\n const parsedNTiles = p.getUInt()\n const nExperiments = p.getUInt()\n if (parsedNTiles !== nTiles) {\n throw new Error(`Tile count mismatch: expected ${nTiles}, got ${parsedNTiles}`)\n }\n\n const tiles: TileEntry[] = []\n for (let i = 0; i < nTiles; i++) {\n const positionsOffset = this.readU64(p)\n const positionsSize = p.getUInt()\n const experimentPointers: ExperimentPointer[] = []\n for (let j = 0; j < nExperiments; j++) {\n const offset = this.readU64(p)\n const size = p.getUInt()\n experimentPointers.push({offset, size})\n }\n tiles.push({positionsOffset, positionsSize, experimentPointers})\n }\n return tiles\n }\n\n // ─── Data Reading ────────────────────────────────────────────────────\n\n /**\n * Read signal data for one or more experiments in a genomic region.\n * Multiple experiments from the same tile are fetched with merged byte ranges.\n *\n * @returns Map from experiment index to WigFeature array\n */\n async readFeatures(\n chrom: string,\n start: number,\n end: number,\n experimentIndexes: number[],\n bpPerPixel?: number,\n signal?: AbortSignal,\n ): Promise<Map<number, WigFeature[]>> {\n await this.init(signal)\n const h = this.header!\n\n // Select zoom level if appropriate\n if (bpPerPixel !== undefined && bpPerPixel > 1) {\n const zoomIdx = this.selectZoomLevel(bpPerPixel)\n if (zoomIdx !== undefined) {\n return this.readZoomFeatures(chrom, start, end, experimentIndexes, zoomIdx, signal)\n }\n }\n\n const chromEntry = this.chromosomes.get(chrom)\n if (!chromEntry) return new Map()\n\n const tiles = await this.loadTileIndex(chrom, signal)\n const tileSize = inferTileSize(chromEntry.length, chromEntry.nTiles)\n\n const firstTile = Math.max(0, Math.floor(start / tileSize))\n const lastTile = Math.min(chromEntry.nTiles - 1, Math.floor(Math.max(0, end - 1) / tileSize))\n\n // Collect byte ranges to fetch\n const fetchPlan: Array<{\n tileIdx: number\n expIdx: number\n pointer: ExperimentPointer\n }> = []\n\n for (let t = firstTile; t <= lastTile; t++) {\n const tile = tiles[t]\n for (const expIdx of experimentIndexes) {\n const ptr = tile.experimentPointers[expIdx]\n if (ptr && ptr.size > 0) {\n fetchPlan.push({tileIdx: t, expIdx, pointer: ptr})\n }\n }\n }\n\n if (fetchPlan.length === 0) return new Map()\n\n // Merge nearby ranges and fetch\n const chunks = await this.fetchMergedRanges(fetchPlan, signal)\n\n // Decompress and assemble results\n const result = new Map<number, WigFeature[]>()\n for (const expIdx of experimentIndexes) {\n result.set(expIdx, [])\n }\n\n for (const {tileIdx, expIdx, data} of chunks) {\n const decompressed = this.decompress(data)\n const values = new Float32Array(decompressed.buffer, decompressed.byteOffset, decompressed.byteLength / 4)\n\n const tileStart = tileIdx * tileSize\n const tileEnd = Math.min((tileIdx + 1) * tileSize, chromEntry.length)\n const overlapStart = Math.max(start, tileStart)\n const overlapEnd = Math.min(end, tileEnd)\n\n const firstBin = Math.floor((overlapStart - tileStart) / h.resolution)\n const lastBin = Math.ceil((overlapEnd - tileStart) / h.resolution)\n\n const features = result.get(expIdx)!\n for (let bin = firstBin; bin < lastBin && bin < values.length; bin++) {\n const value = values[bin]\n if (value === 0) continue\n const binStart = tileStart + bin * h.resolution\n const binEnd = Math.min(binStart + h.resolution, chromEntry.length)\n features.push({chr: chrom, start: binStart, end: binEnd, value})\n }\n }\n\n return result\n }\n\n /**\n * Read zoom-level data for one or more experiments.\n */\n private async readZoomFeatures(\n chrom: string,\n start: number,\n end: number,\n experimentIndexes: number[],\n zoomIdx: number,\n signal?: AbortSignal,\n ): Promise<Map<number, WigFeature[]>> {\n const zoomLevel = this.zoomLevels[zoomIdx]\n if (!zoomLevel) return new Map()\n\n const chromZoom = zoomLevel.chromTileIndexes.get(chrom)\n if (!chromZoom) return new Map()\n\n const chromEntry = this.chromosomes.get(chrom)\n if (!chromEntry) return new Map()\n\n const tiles = await this.loadZoomTileIndex(zoomIdx, chrom, signal)\n // Zoom uses the same tile grid as full resolution\n const tileSize = inferTileSize(chromEntry.length, chromZoom.nTiles)\n const zoomBinSize = zoomLevel.reductionLevel\n\n const firstTile = Math.max(0, Math.floor(start / tileSize))\n const lastTile = Math.min(chromZoom.nTiles - 1, Math.floor(Math.max(0, end - 1) / tileSize))\n\n const fetchPlan: Array<{\n tileIdx: number\n expIdx: number\n pointer: ExperimentPointer\n }> = []\n\n for (let t = firstTile; t <= lastTile; t++) {\n const tile = tiles[t]\n for (const expIdx of experimentIndexes) {\n const ptr = tile.experimentPointers[expIdx]\n if (ptr && ptr.size > 0) {\n fetchPlan.push({tileIdx: t, expIdx, pointer: ptr})\n }\n }\n }\n\n if (fetchPlan.length === 0) return new Map()\n\n const chunks = await this.fetchMergedRanges(fetchPlan, signal)\n\n const result = new Map<number, WigFeature[]>()\n for (const expIdx of experimentIndexes) {\n result.set(expIdx, [])\n }\n\n for (const {tileIdx, expIdx, data} of chunks) {\n const decompressed = this.decompress(data)\n const allValues = new Float32Array(decompressed.buffer, decompressed.byteOffset, decompressed.byteLength / 4)\n\n // Zoom data layout: [means..., maxes...] — first half is means, second half is maxes\n const nZoomBins = allValues.length / 2\n const means = allValues.subarray(0, nZoomBins)\n\n const tileStart = tileIdx * tileSize\n const tileEnd = Math.min((tileIdx + 1) * tileSize, chromEntry.length)\n const overlapStart = Math.max(start, tileStart)\n const overlapEnd = Math.min(end, tileEnd)\n\n const firstBin = Math.floor((overlapStart - tileStart) / zoomBinSize)\n const lastBin = Math.ceil((overlapEnd - tileStart) / zoomBinSize)\n\n const features = result.get(expIdx)!\n for (let bin = firstBin; bin < lastBin && bin < means.length; bin++) {\n const value = means[bin]\n if (value === 0) continue\n const binStart = tileStart + bin * zoomBinSize\n const binEnd = Math.min(binStart + zoomBinSize, chromEntry.length)\n features.push({chr: chrom, start: binStart, end: binEnd, value})\n }\n }\n\n return result\n }\n\n // ─── Experiment Metadata Stubs ───────────────────────────────────────\n\n /** Returns all experiment IDs in this GTX file. */\n getExperimentIds(): string[] {\n return this.experiments.map(e => e.id)\n }\n\n /** Returns metadata key-value pairs for an experiment, or undefined if not found. */\n getExperimentMetadata(id: string): Map<string, string> | undefined {\n const entry = this.experiments.find(e => e.id === id)\n return entry?.metadata\n }\n\n /** Resolve an experiment ID to its numeric index. */\n resolveExperimentIndex(id: string): number | undefined {\n return this.experimentIdToIndex.get(id)\n }\n\n /** Get the parsed header (must call init() first). */\n getHeader(): GtxHeader | undefined {\n return this.header\n }\n\n /** Get all chromosome entries. */\n getChromosomes(): Map<string, ChromEntry> {\n return this.chromosomes\n }\n\n // ─── Internal Helpers ────────────────────────────────────────────────\n\n /**\n * Compute the fetch size for the chrom + zoom directory region.\n *\n * The directories sit at the end of the file, followed only by an 8-byte\n * xxHash64 checksum. We compute the span from known offsets, and the\n * trailing checksum bytes won't affect parsing since directory parsers\n * read a known structure and stop.\n */\n private computeDirFetchSize(h: GtxHeader): number {\n // groupStatsDirectoryOffset marks the end of zoom directory\n if (h.groupStatsDirectoryOffset > 0 && h.groupStatsDirectoryOffset > h.chromDirectoryOffset) {\n // Include 8 bytes past groupStats to cover the checksum (harmless)\n return h.groupStatsDirectoryOffset - h.chromDirectoryOffset + 8\n }\n // Zoom directory + generous padding for zoom data after it\n if (h.nZoomLevels > 0 && h.zoomDirectoryOffset > 0) {\n return (h.zoomDirectoryOffset - h.chromDirectoryOffset) + 256 * 1024\n }\n // No zoom — just chrom directory + padding\n return 256 * 1024\n }\n\n /**\n * Select the best zoom level for a given bp/pixel resolution.\n * Returns undefined if full resolution should be used.\n */\n private selectZoomLevel(bpPerPixel: number): number | undefined {\n // Select the coarsest zoom level where zoom_bin_size < bpPerPixel * 2\n let bestIdx: number | undefined\n for (let i = 0; i < this.zoomLevels.length; i++) {\n if (this.zoomLevels[i].reductionLevel < bpPerPixel * 2) {\n bestIdx = i\n }\n }\n return bestIdx\n }\n\n /**\n * Merge adjacent/nearby byte ranges and fetch, then split back to\n * per-experiment chunks.\n */\n private async fetchMergedRanges(\n plan: Array<{tileIdx: number; expIdx: number; pointer: ExperimentPointer}>,\n signal?: AbortSignal,\n ): Promise<Array<{tileIdx: number; expIdx: number; data: Uint8Array}>> {\n // Sort by file offset for merging\n const sorted = [...plan].sort((a, b) => a.pointer.offset - b.pointer.offset)\n\n // Merge ranges that are within 1KB of each other\n const MERGE_GAP = 1024\n const mergedRanges: Array<{start: number; end: number; items: typeof sorted}> = []\n\n for (const item of sorted) {\n const itemEnd = item.pointer.offset + item.pointer.size\n const last = mergedRanges[mergedRanges.length - 1]\n\n if (last && item.pointer.offset - last.end <= MERGE_GAP) {\n last.end = Math.max(last.end, itemEnd)\n last.items.push(item)\n } else {\n mergedRanges.push({\n start: item.pointer.offset,\n end: itemEnd,\n items: [item],\n })\n }\n }\n\n // Fetch all merged ranges concurrently\n const fetches = mergedRanges.map(async range => {\n const buf = await fetchRange(this.url, {\n start: range.start,\n size: range.end - range.start,\n }, signal)\n return {range, buf}\n })\n\n const results = await Promise.all(fetches)\n const chunks: Array<{tileIdx: number; expIdx: number; data: Uint8Array}> = []\n\n for (const {range, buf} of results) {\n for (const item of range.items) {\n const localOffset = item.pointer.offset - range.start\n const data = new Uint8Array(buf, localOffset, item.pointer.size)\n chunks.push({tileIdx: item.tileIdx, expIdx: item.expIdx, data})\n }\n }\n\n return chunks\n }\n\n /** Decompress a zstd-compressed chunk using the cached dictionary. */\n private decompress(data: Uint8Array): Uint8Array {\n if (!this.dictionary || this.dctx === undefined) {\n throw new Error('GTX reader not initialized — call init() first')\n }\n return decompressUsingDict(this.dctx, data, this.dictionary)\n }\n\n /** Read a u64 from BinaryParser (as JavaScript number). */\n private readU64(p: BinaryParser): number {\n return p.getLong()\n }\n\n /** Clean up the decompression context. */\n dispose(): void {\n if (this.dctx !== undefined) {\n freeDCtx(this.dctx)\n this.dctx = undefined\n }\n }\n}\n","/**\n * GTX fetch coordinator — batches requests from multiple GtxDataSource\n * instances into a single readFeatures() call.\n *\n * When loadAllTracksIfNeeded fires for 5 GTX tracks, all 5\n * GtxDataSource.fetch() calls run synchronously in the same tick.\n * Each calls coordinator.request() which is synchronous — no awaits\n * before the batching logic. Requests are collected, then flushed\n * on the next microtask as a single readFeatures() call with all\n * experiment indexes, merging byte ranges across experiments.\n *\n * Layer 1 (Data + Layout): no DOM, no canvas.\n */\n\nimport {GtxReader} from './gtxReader'\nimport type {WigFeature, Locus} from '../types'\n\ninterface PendingExperiment {\n experimentId: string\n resolve: (features: WigFeature[]) => void\n reject: (err: unknown) => void\n}\n\ninterface PendingBatch {\n locus: Locus\n bpPerPixel: number\n signal: AbortSignal | undefined\n experiments: PendingExperiment[]\n}\n\n// One coordinator per GTX URL (same lifetime as the GtxReader)\nconst coordinators = new Map<string, GtxFetchCoordinator>()\n\nexport function getCoordinator(url: string, reader: GtxReader): GtxFetchCoordinator {\n let coord = coordinators.get(url)\n if (!coord) {\n coord = new GtxFetchCoordinator(url, reader)\n coordinators.set(url, coord)\n }\n return coord\n}\n\nexport function clearCoordinators(): void {\n coordinators.clear()\n}\n\nexport class GtxFetchCoordinator {\n private pending = new Map<string, PendingBatch>()\n\n constructor(\n private url: string,\n private reader: GtxReader,\n ) {}\n\n /**\n * Request features for one experiment. Fully synchronous — collects the\n * request and returns a promise that resolves when the batch flushes.\n *\n * The flush handles reader.init() internally, so callers do NOT need\n * to await init() before calling this. This is critical: if callers\n * awaited init(), the await would yield and each continuation would\n * resume in a separate microtask, defeating batching.\n */\n request(\n experimentId: string,\n locus: Locus,\n bpPerPixel: number,\n signal?: AbortSignal,\n ): Promise<WigFeature[]> {\n const key = `${locus.chr}:${locus.start}-${locus.end}|${bpPerPixel}`\n const existing = this.pending.get(key)\n\n if (existing) {\n return new Promise<WigFeature[]>((resolve, reject) => {\n existing.experiments.push({experimentId, resolve, reject})\n })\n }\n\n return new Promise<WigFeature[]>((resolve, reject) => {\n const batch: PendingBatch = {\n locus,\n bpPerPixel,\n signal,\n experiments: [{experimentId, resolve, reject}],\n }\n this.pending.set(key, batch)\n queueMicrotask(() => this.flush(key))\n })\n }\n\n private async flush(key: string): Promise<void> {\n const batch = this.pending.get(key)\n if (!batch) return\n this.pending.delete(key)\n\n const {locus, bpPerPixel, signal, experiments} = batch\n\n try {\n // Init inside flush — not in each caller\n await this.reader.init()\n\n // Resolve all experiment IDs to indexes\n const expIndexes: number[] = []\n const idToIdx = new Map<string, number>()\n for (const exp of experiments) {\n const idx = this.reader.resolveExperimentIndex(exp.experimentId)\n if (idx === undefined) {\n exp.reject(new Error(`Unknown experiment: ${exp.experimentId}`))\n continue\n }\n idToIdx.set(exp.experimentId, idx)\n expIndexes.push(idx)\n }\n\n if (expIndexes.length === 0) return\n\n // Single readFeatures call with all experiment indexes\n const result = await this.reader.readFeatures(\n locus.chr,\n locus.start,\n locus.end,\n expIndexes,\n bpPerPixel,\n signal,\n )\n\n // Distribute results\n for (const exp of experiments) {\n const idx = idToIdx.get(exp.experimentId)\n if (idx !== undefined) {\n exp.resolve(result.get(idx) ?? [])\n }\n }\n } catch (err) {\n for (const exp of experiments) {\n exp.reject(err)\n }\n }\n }\n}\n","/**\n * GTX reader — public API.\n *\n * Reads GTX binary files via HTTP range requests and returns\n * WigFeature[] arrays ready for rendering. A single GTX file\n * bundles multiple experiments; the reader is cached per URL\n * and shared across all experiments from the same file.\n *\n * Layer 1 (Data + Layout): no DOM, no canvas.\n */\n\nexport {GtxReader} from './gtxReader'\nexport type {GtxHeader, ChromEntry, ExperimentEntry} from './gtxReader'\n\nimport {GtxReader} from './gtxReader'\nimport {clearCoordinators} from './fetchCoordinator'\nimport type {WigFeature, WindowFunction, Locus} from '../types'\nimport type {WorkerProvider} from '../workerProvider'\n\nexport interface FetchGtxOptions {\n /** Resolution in base pairs per pixel. Used to select an appropriate zoom level. */\n bpPerPixel?: number\n /** Aggregation function for zoom-level data. Default: 'mean'. */\n windowFunction?: WindowFunction\n /** Worker provider for offloading decode work (reserved for future use). */\n workerProvider?: WorkerProvider\n /** AbortSignal for cancelling in-flight HTTP requests. */\n signal?: AbortSignal\n}\n\n// Cache readers by URL to reuse parsed headers, dictionaries, and indexes\nconst readerCache = new Map<string, GtxReader>()\n\nfunction getReader(url: string): GtxReader {\n let reader = readerCache.get(url)\n if (!reader) {\n reader = new GtxReader(url)\n readerCache.set(url, reader)\n }\n return reader\n}\n\n/**\n * Fetch GTX features for a single experiment at a genomic locus.\n */\nexport async function fetchGtxFeatures(\n url: string,\n experimentId: string,\n locus: Locus,\n options: FetchGtxOptions = {},\n): Promise<WigFeature[]> {\n const reader = getReader(url)\n await reader.init(options.signal)\n\n const expIdx = reader.resolveExperimentIndex(experimentId)\n if (expIdx === undefined) {\n throw new Error(`Unknown experiment: ${experimentId}`)\n }\n\n const result = await reader.readFeatures(\n locus.chr,\n locus.start,\n locus.end,\n [expIdx],\n options.bpPerPixel,\n options.signal,\n )\n\n return result.get(expIdx) ?? []\n}\n\n/**\n * Fetch GTX features across all specified chromosomes for whole genome view.\n * Returns features with per-chromosome coordinates (caller transforms to genome-wide).\n */\nexport async function fetchGtxWGFeatures(\n url: string,\n experimentId: string,\n chromNames: string[],\n bpPerPixel: number,\n options: Pick<FetchGtxOptions, 'windowFunction' | 'workerProvider' | 'signal'> = {},\n): Promise<WigFeature[]> {\n const reader = getReader(url)\n await reader.init(options.signal)\n\n const expIdx = reader.resolveExperimentIndex(experimentId)\n if (expIdx === undefined) {\n throw new Error(`Unknown experiment: ${experimentId}`)\n }\n\n const allFeatures: WigFeature[] = []\n\n // Fetch each chromosome. GTX supports multi-experiment per request,\n // but for WG view we iterate chromosomes.\n for (const chrom of chromNames) {\n try {\n const result = await reader.readFeatures(\n chrom, 0, Number.MAX_SAFE_INTEGER,\n [expIdx],\n bpPerPixel,\n options.signal,\n )\n const features = result.get(expIdx)\n if (features) {\n allFeatures.push(...features)\n }\n } catch {\n // Skip chromosomes not in the GTX file\n }\n }\n\n return allFeatures\n}\n\n/**\n * Fetch GTX features for multiple experiments simultaneously.\n * Optimizes network by merging byte ranges for experiments in the same tiles.\n */\nexport async function fetchGtxMultiFeatures(\n url: string,\n experimentIds: string[],\n locus: Locus,\n options: FetchGtxOptions = {},\n): Promise<Map<string, WigFeature[]>> {\n const reader = getReader(url)\n await reader.init(options.signal)\n\n const idToIdx = new Map<string, number>()\n const indexes: number[] = []\n for (const id of experimentIds) {\n const idx = reader.resolveExperimentIndex(id)\n if (idx === undefined) {\n throw new Error(`Unknown experiment: ${id}`)\n }\n idToIdx.set(id, idx)\n indexes.push(idx)\n }\n\n const result = await reader.readFeatures(\n locus.chr,\n locus.start,\n locus.end,\n indexes,\n options.bpPerPixel,\n options.signal,\n )\n\n // Map back from experiment index to experiment ID\n const output = new Map<string, WigFeature[]>()\n for (const [id, idx] of idToIdx) {\n output.set(id, result.get(idx) ?? [])\n }\n return output\n}\n\n/** Clear the GTX reader cache (useful for testing or memory management). */\nexport function clearGtxCache(): void {\n for (const reader of readerCache.values()) {\n reader.dispose()\n }\n readerCache.clear()\n clearCoordinators()\n}\n","/**\n * GTX data source — DataSource<WigFeature> backed by a GTX file.\n *\n * A single GTX file contains multiple experiments. Each GtxDataSource\n * instance reads one experiment (by ID), but shares the underlying\n * GtxReader (and its cached header, dictionary, indexes) with other\n * GtxDataSource instances pointing to the same URL.\n *\n * Request coalescing: when multiple GtxDataSource instances for the\n * same URL call fetch() in the same tick (e.g., loadAllTracksIfNeeded),\n * the GtxFetchCoordinator batches them into a single readFeatures()\n * call with merged byte ranges — the core GTX performance advantage.\n *\n * Drop-in replacement for BigWigDataSource when the data is in GTX format.\n *\n * Layer 1 (Data + Layout): no DOM, no canvas.\n */\n\nimport type {DataSource, Locus, WigFeature, WindowFunction} from '../types'\nimport type {WorkerProvider} from '../workerProvider'\nimport type {CumulativeOffsets} from '../genome/chromSizes'\nimport {GtxReader} from '../gtx'\nimport {getCoordinator} from '../gtx/fetchCoordinator'\nimport {fetchGtxWGFeatures} from '../gtx'\nimport {summarizeWigData} from '../tracks/wig/wigSummary'\nimport {isWholeGenomeView} from '../locusUtils'\n\n// Cache readers by URL (shared with gtx/index.ts reader cache)\nconst readerCache = new Map<string, GtxReader>()\n\nfunction getReader(url: string): GtxReader {\n let reader = readerCache.get(url)\n if (!reader) {\n reader = new GtxReader(url)\n readerCache.set(url, reader)\n }\n return reader\n}\n\nexport class GtxDataSource implements DataSource<WigFeature> {\n private _windowFunction: WindowFunction\n private workerProvider?: WorkerProvider\n private _cumulativeOffsets?: CumulativeOffsets\n private _resolveChromName?: (chr: string) => string\n private reader: GtxReader\n\n constructor(\n private url: string,\n private experimentId: string,\n windowFunction: WindowFunction = 'mean',\n workerProvider?: WorkerProvider,\n ) {\n this._windowFunction = windowFunction\n this.workerProvider = workerProvider\n this.reader = getReader(url)\n }\n\n get windowFunction(): WindowFunction { return this._windowFunction }\n\n /** Update the window function for future fetches. */\n setWindowFunction(wf: WindowFunction): void {\n this._windowFunction = wf\n }\n\n /** Set cumulative offsets for whole genome view coordinate transformation. */\n setCumulativeOffsets(offsets: CumulativeOffsets): void {\n this._cumulativeOffsets = offsets\n }\n\n /** Set a chromosome name resolver for alias resolution (e.g., \"1\" → \"chr1\"). */\n setChromNameResolver(resolver: (chr: string) => string): void {\n this._resolveChromName = resolver\n }\n\n async fetch(locus: Locus, bpPerPixel: number, signal: AbortSignal): Promise<WigFeature[]> {\n if (isWholeGenomeView(locus) && this._cumulativeOffsets) {\n return this.fetchWG(bpPerPixel, signal)\n }\n\n // Resolve chromosome alias before querying\n const resolvedLocus = this._resolveChromName\n ? {...locus, chr: this._resolveChromName(locus.chr)}\n : locus\n\n // Use coordinator for batched fetching. coordinator.request() is\n // synchronous — no awaits before batching. All GtxDataSource\n // instances for the same URL that call fetch() in the same tick\n // are collected and flushed as a single readFeatures() call.\n // The coordinator handles reader.init() internally during flush.\n const coordinator = getCoordinator(this.url, this.reader)\n const features = await coordinator.request(\n this.experimentId,\n resolvedLocus,\n bpPerPixel,\n signal,\n )\n\n // Summarize to pixel resolution\n if (bpPerPixel > 1 && this._windowFunction !== 'none' && features.length > 0) {\n if (this.workerProvider) {\n return this.workerProvider.execute({\n task: 'summarize',\n features,\n startBP: locus.start,\n bpPerPixel,\n windowFunction: this._windowFunction,\n })\n }\n return summarizeWigData(features, locus.start, bpPerPixel, this._windowFunction)\n }\n return features\n }\n\n /**\n * Fetch all chromosomes for whole genome view and transform to genome-wide coordinates.\n */\n private async fetchWG(bpPerPixel: number, signal: AbortSignal): Promise<WigFeature[]> {\n const offsets = this._cumulativeOffsets!\n const features = await fetchGtxWGFeatures(\n this.url,\n this.experimentId,\n offsets.chromosomeNames,\n bpPerPixel,\n {windowFunction: this._windowFunction, signal},\n )\n\n // Transform to genome-wide coordinates\n const wgFeatures: WigFeature[] = []\n for (const f of features) {\n const offset = offsets.offsets[f.chr]\n if (offset === undefined) continue\n wgFeatures.push({\n ...f,\n chr: 'all',\n start: offset + f.start,\n end: offset + f.end,\n })\n }\n wgFeatures.sort((a, b) => a.start - b.start)\n\n // Summarize at genome-wide scale\n if (bpPerPixel > 1 && this._windowFunction !== 'none' && wgFeatures.length > 0) {\n if (this.workerProvider) {\n return this.workerProvider.execute({\n task: 'summarize',\n features: wgFeatures,\n startBP: 0,\n bpPerPixel,\n windowFunction: this._windowFunction,\n })\n }\n return summarizeWigData(wgFeatures, 0, bpPerPixel, this._windowFunction)\n }\n return wgFeatures\n }\n}\n","/**\n * Shared exon and feature utilities used by multiple decoders (BED, genePred, GFF).\n *\n * Layer 1 (Data + Layout): pure functions, no I/O, no DOM.\n */\n\nimport type {Exon} from '../types'\n\n/**\n * Mark UTR exons and partial UTR boundaries.\n *\n * For non-coding transcripts (cdStart === cdEnd), all exons are marked as UTR.\n * For coding transcripts, exons entirely outside the CDS are marked as UTR,\n * and exons overlapping CDS boundaries get cdStart/cdEnd set.\n *\n * Port of js/feature/decode/ucsc.ts::findUTRs.\n */\nexport function findUTRs(exons: Exon[], cdStart: number, cdEnd: number): void {\n // Non-coding transcript: cdsStart === cdsEnd → all exons are UTR\n if (cdStart === cdEnd) {\n for (const exon of exons) {\n exon.utr = true\n }\n return\n }\n\n for (const exon of exons) {\n if (exon.end < cdStart || exon.start > cdEnd) {\n exon.utr = true\n } else {\n if (cdStart >= exon.start && cdStart <= exon.end) {\n exon.cdStart = cdStart\n }\n if (cdEnd >= exon.start && cdEnd <= exon.end) {\n exon.cdEnd = cdEnd\n }\n }\n }\n}\n\n/**\n * Parse a color value from a BED column (comma-separated RGB or hex) into a CSS color string.\n *\n * Accepts:\n * - \"r,g,b\" (e.g. \"255,0,0\" → \"rgb(255,0,0)\")\n * - \"#RRGGBB\" or \"#RGB\" (returned as-is)\n * - \".\" or \"0\" → returns undefined (no color)\n *\n * Port of igv.js IGVColor.createColorString() for the subset used by BED format.\n */\nexport function parseColorString(value: string): string | undefined {\n if (!value || value === '.' || value === '0') return undefined\n\n // Already a hex color\n if (value.startsWith('#')) return value\n\n // Comma-separated RGB\n const parts = value.split(',')\n if (parts.length >= 3) {\n const r = parseInt(parts[0].trim())\n const g = parseInt(parts[1].trim())\n const b = parseInt(parts[2].trim())\n if (!isNaN(r) && !isNaN(g) && !isNaN(b)) {\n return `rgb(${r},${g},${b})`\n }\n }\n\n return undefined\n}\n\n/** Parse a strand character to a typed strand value. */\nexport function parseStrand(s: string): '+' | '-' | undefined {\n if (s === '+') return '+'\n if (s === '-') return '-'\n return undefined\n}\n","/**\n * UCSC gene prediction format decoders.\n *\n * Ported from js/feature/decode/ucsc.ts — handles genePred, genePredExt,\n * and refGene formats. These are the formats used by UCSC genome browser\n * for gene annotations (ncbiRefSeq, knownGene, etc.).\n */\n\nimport type {Exon, AnnotationFeature} from '../types'\nimport {findUTRs, parseStrand} from './exonUtils'\n\n/**\n * Decode a UCSC \"genePred\" record (basic gene prediction format).\n *\n * Column layout (no bin): name, chrom, strand, txStart, txEnd, cdsStart, cdsEnd,\n * exonCount, exonStarts, exonEnds\n * Column layout (with bin): bin, name, chrom, strand, txStart, txEnd, cdsStart, cdsEnd,\n * exonCount, exonStarts, exonEnds, score, name2\n *\n * @param tokens - Tab-split fields from a single line\n * @param shift - 1 if the record has a leading `bin` column (refGene), 0 otherwise\n */\nexport function decodeGenePred(tokens: string[], shift: 0 | 1 = 0): AnnotationFeature | undefined {\n if (tokens.length <= 10 + shift) return undefined\n\n const cdStart = parseInt(tokens[5 + shift])\n const cdEnd = parseInt(tokens[6 + shift])\n\n const feature: AnnotationFeature = {\n id: tokens[0 + shift],\n chr: tokens[1 + shift],\n strand: parseStrand(tokens[2 + shift]),\n start: parseInt(tokens[3 + shift]),\n end: parseInt(tokens[4 + shift]),\n cdStart,\n cdEnd,\n name: tokens.length > 11 + shift ? tokens[11 + shift] : tokens[0 + shift],\n }\n\n const exons = decodeExons(\n parseInt(tokens[7 + shift]),\n tokens[8 + shift],\n tokens[9 + shift],\n )\n findUTRs(exons, cdStart, cdEnd)\n feature.exons = exons\n\n return feature\n}\n\n/**\n * Decode a UCSC \"genePredExt\" record. refGene files are in this format.\n *\n * Same as genePred but with additional columns:\n * ..., score, name2, cdsStartStat, cdsEndStat, exonFrames\n *\n * @param tokens - Tab-split fields from a single line\n * @param shift - 1 if the record has a leading `bin` column (refGene), 0 otherwise\n */\nexport function decodeGenePredExt(tokens: string[], shift: 0 | 1 = 0): AnnotationFeature | undefined {\n if (tokens.length <= 11 + shift) return undefined\n\n const cdStart = parseInt(tokens[5 + shift])\n const cdEnd = parseInt(tokens[6 + shift])\n\n const feature: AnnotationFeature = {\n name: tokens[11 + shift],\n chr: tokens[1 + shift],\n strand: parseStrand(tokens[2 + shift]),\n start: parseInt(tokens[3 + shift]),\n end: parseInt(tokens[4 + shift]),\n cdStart,\n cdEnd,\n id: tokens[0 + shift],\n }\n\n // Score (column 10+shift, if present)\n if (tokens.length > 10 + shift) {\n const s = parseInt(tokens[10 + shift])\n if (!isNaN(s)) feature.score = s\n }\n\n // cdsStartStat / cdsEndStat (columns 12-13+shift)\n if (tokens.length > 13 + shift) {\n feature.cdsStartStat = tokens[12 + shift]\n feature.cdsEndStat = tokens[13 + shift]\n }\n\n // exonFrames is column 14+shift\n const exons = decodeExons(\n parseInt(tokens[7 + shift]),\n tokens[8 + shift],\n tokens[9 + shift],\n tokens[14 + shift],\n )\n findUTRs(exons, cdStart, cdEnd)\n feature.exons = exons\n\n return feature\n}\n\n/**\n * Decode a UCSC REST API JSON record into a AnnotationFeature.\n *\n * The UCSC API returns JSON objects with the same fields as the text format\n * but as named properties instead of positional columns.\n */\nexport function decodeRefGeneJson(rec: RefGeneRecord): AnnotationFeature {\n const cdStart = rec.cdsStart\n const cdEnd = rec.cdsEnd\n\n const feature: AnnotationFeature = {\n name: rec.name2,\n chr: rec.chrom,\n strand: parseStrand(rec.strand),\n start: rec.txStart,\n end: rec.txEnd,\n cdStart,\n cdEnd,\n id: rec.name,\n }\n\n if (rec.score !== undefined) feature.score = rec.score\n if (rec.cdsStartStat) feature.cdsStartStat = rec.cdsStartStat\n if (rec.cdsEndStat) feature.cdsEndStat = rec.cdsEndStat\n\n const exonStarts = rec.exonStarts.replace(/,$/, '').split(',')\n const exonEnds = rec.exonEnds.replace(/,$/, '').split(',')\n const frameOffsets = rec.exonFrames\n ? rec.exonFrames.replace(/,$/, '').split(',')\n : undefined\n\n const exons: Exon[] = []\n for (let i = 0; i < rec.exonCount; i++) {\n const start = parseInt(exonStarts[i])\n const end = parseInt(exonEnds[i])\n const exon: Exon = {start, end}\n if (frameOffsets) {\n const fo = parseInt(frameOffsets[i])\n if (fo !== -1) exon.readingFrame = fo\n }\n exons.push(exon)\n }\n findUTRs(exons, cdStart, cdEnd)\n feature.exons = exons\n\n return feature\n}\n\n/** Shape of a record returned by the UCSC REST API for ncbiRefSeq/refGene tracks. */\nexport interface RefGeneRecord {\n bin?: number\n name: string\n name2: string\n chrom: string\n strand: string\n txStart: number\n txEnd: number\n cdsStart: number\n cdsEnd: number\n exonCount: number\n exonStarts: string\n exonEnds: string\n score?: number\n cdsStartStat?: string\n cdsEndStat?: string\n exonFrames?: string\n}\n\n// --- Internal helpers ---\n\n/**\n * Parse exons from comma-separated start/end strings.\n * Matches js/feature/decode/ucsc.ts::decodeExons.\n */\nfunction decodeExons(\n exonCount: number,\n startsString: string,\n endsString: string,\n frameOffsetsString?: string,\n): Exon[] {\n const exonStarts = startsString.replace(/,$/, '').split(',')\n const exonEnds = endsString.replace(/,$/, '').split(',')\n const frameOffsets = frameOffsetsString\n ? frameOffsetsString.replace(/,$/, '').split(',')\n : undefined\n\n const exons: Exon[] = []\n for (let i = 0; i < exonCount; i++) {\n const start = parseInt(exonStarts[i])\n const end = parseInt(exonEnds[i])\n const exon: Exon = {start, end}\n if (frameOffsets) {\n const fo = parseInt(frameOffsets[i])\n if (fo !== -1) exon.readingFrame = fo\n }\n exons.push(exon)\n }\n return exons\n}\n","/**\n * UCSC Genome Browser REST API client.\n *\n * Fetches gene annotation data from the UCSC REST API and decodes it\n * into GeneFeature objects using the same parsing logic as igv.js.\n *\n * API docs: https://genome.ucsc.edu/goldenPath/help/api.html\n */\n\nimport type {AnnotationFeature, Locus} from '../types'\nimport {decodeRefGeneJson} from '../decode/ucsc'\nimport type {RefGeneRecord} from '../decode/ucsc'\n\nconst UCSC_API_BASE = 'https://api.genome.ucsc.edu'\n\nexport interface FetchGenesOptions {\n /** Genome assembly, e.g. \"hg38\", \"hg19\", \"mm10\". Default: \"hg38\". */\n genome?: string\n /** UCSC track name, e.g. \"ncbiRefSeq\", \"knownGene\". Default: \"ncbiRefSeq\". */\n track?: string\n}\n\n/**\n * Fetch gene features for a genomic region from the UCSC REST API.\n *\n * Uses the same ncbiRefSeq track that igv.js loads by default for hg38.\n */\nexport async function fetchGeneFeatures(\n locus: Locus,\n options: FetchGenesOptions = {},\n signal?: AbortSignal,\n): Promise<AnnotationFeature[]> {\n const genome = options.genome ?? 'hg38'\n const track = options.track ?? 'ncbiRefSeq'\n\n const url = `${UCSC_API_BASE}/getData/track?genome=${genome}&track=${track}&chrom=${locus.chr}&start=${locus.start}&end=${locus.end}`\n const resp = await fetch(url, signal ? {signal} : undefined)\n\n if (!resp.ok) {\n throw new Error(`UCSC API error: ${resp.status} ${resp.statusText}`)\n }\n\n const data = await resp.json()\n const records: RefGeneRecord[] = data[track] ?? []\n return records.map(decodeRefGeneJson)\n}\n","import type {DataSource, Locus, AnnotationFeature} from '../types'\nimport type {CumulativeOffsets} from '../genome/chromSizes'\nimport {fetchGeneFeatures} from '../data/ucscApi'\nimport type {FetchGenesOptions} from '../data/ucscApi'\nimport {isWholeGenomeView} from '../locusUtils'\n\n/** Maximum number of WG features to avoid rendering performance issues (reservoir sampling). */\nconst MAX_WG_FEATURES = 10_000\n\nexport class GeneDataSource implements DataSource<AnnotationFeature> {\n private _cumulativeOffsets?: CumulativeOffsets\n\n constructor(private options: FetchGenesOptions = {}) {}\n\n /** Set cumulative offsets for whole genome view coordinate transformation. */\n setCumulativeOffsets(offsets: CumulativeOffsets): void {\n this._cumulativeOffsets = offsets\n }\n\n async fetch(locus: Locus, _bpPerPixel: number, signal: AbortSignal): Promise<AnnotationFeature[]> {\n if (isWholeGenomeView(locus) && this._cumulativeOffsets) {\n return this.fetchWG(signal)\n }\n return fetchGeneFeatures(locus, this.options, signal)\n }\n\n /**\n * Fetch genes for all main chromosomes and transform to genome-wide coordinates.\n * Follows igv.js computeWGFeatures() pattern: strips exons, downsamples.\n */\n private async fetchWG(signal: AbortSignal): Promise<AnnotationFeature[]> {\n const offsets = this._cumulativeOffsets!\n\n // Fetch all chromosomes in parallel\n const promises = offsets.chromosomeNames.map(chr =>\n fetchGeneFeatures({chr, start: 0, end: Number.MAX_SAFE_INTEGER}, this.options, signal)\n .catch(() => [] as AnnotationFeature[]) // Skip chromosomes that fail\n )\n\n const perChromResults = await Promise.all(promises)\n\n // Transform to genome-wide coordinates, strip exons for WG scale\n const wgFeatures: AnnotationFeature[] = []\n for (let i = 0; i < offsets.chromosomeNames.length; i++) {\n const chr = offsets.chromosomeNames[i]\n const offset = offsets.offsets[chr]\n if (offset === undefined) continue\n\n for (const f of perChromResults[i]) {\n wgFeatures.push({\n ...f,\n chr: 'all',\n start: offset + f.start,\n end: offset + f.end,\n // Strip detailed structure — too zoomed out\n exons: undefined,\n cdStart: undefined,\n cdEnd: undefined,\n })\n }\n }\n\n // Downsample with reservoir sampling if too many features\n if (wgFeatures.length > MAX_WG_FEATURES) {\n return reservoirSample(wgFeatures, MAX_WG_FEATURES)\n }\n\n return wgFeatures\n }\n}\n\n/** Reservoir sampling — uniform random sample of k items from an array. */\nfunction reservoirSample<T>(items: T[], k: number): T[] {\n const reservoir = items.slice(0, k)\n for (let i = k; i < items.length; i++) {\n const j = Math.floor(Math.random() * (i + 1))\n if (j < k) {\n reservoir[j] = items[i]\n }\n }\n return reservoir\n}\n","/******************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global Reflect, Promise, SuppressedError, Symbol, Iterator */\r\n\r\nvar extendStatics = function(d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n};\r\n\r\nexport function __extends(d, b) {\r\n if (typeof b !== \"function\" && b !== null)\r\n throw new TypeError(\"Class extends value \" + String(b) + \" is not a constructor or null\");\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nexport var __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n }\r\n return __assign.apply(this, arguments);\r\n}\r\n\r\nexport function __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n t[p[i]] = s[p[i]];\r\n }\r\n return t;\r\n}\r\n\r\nexport function __decorate(decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n}\r\n\r\nexport function __param(paramIndex, decorator) {\r\n return function (target, key) { decorator(target, key, paramIndex); }\r\n}\r\n\r\nexport function __esDecorate(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {\r\n function accept(f) { if (f !== void 0 && typeof f !== \"function\") throw new TypeError(\"Function expected\"); return f; }\r\n var kind = contextIn.kind, key = kind === \"getter\" ? \"get\" : kind === \"setter\" ? \"set\" : \"value\";\r\n var target = !descriptorIn && ctor ? contextIn[\"static\"] ? ctor : ctor.prototype : null;\r\n var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});\r\n var _, done = false;\r\n for (var i = decorators.length - 1; i >= 0; i--) {\r\n var context = {};\r\n for (var p in contextIn) context[p] = p === \"access\" ? {} : contextIn[p];\r\n for (var p in contextIn.access) context.access[p] = contextIn.access[p];\r\n context.addInitializer = function (f) { if (done) throw new TypeError(\"Cannot add initializers after decoration has completed\"); extraInitializers.push(accept(f || null)); };\r\n var result = (0, decorators[i])(kind === \"accessor\" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);\r\n if (kind === \"accessor\") {\r\n if (result === void 0) continue;\r\n if (result === null || typeof result !== \"object\") throw new TypeError(\"Object expected\");\r\n if (_ = accept(result.get)) descriptor.get = _;\r\n if (_ = accept(result.set)) descriptor.set = _;\r\n if (_ = accept(result.init)) initializers.unshift(_);\r\n }\r\n else if (_ = accept(result)) {\r\n if (kind === \"field\") initializers.unshift(_);\r\n else descriptor[key] = _;\r\n }\r\n }\r\n if (target) Object.defineProperty(target, contextIn.name, descriptor);\r\n done = true;\r\n};\r\n\r\nexport function __runInitializers(thisArg, initializers, value) {\r\n var useValue = arguments.length > 2;\r\n for (var i = 0; i < initializers.length; i++) {\r\n value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);\r\n }\r\n return useValue ? value : void 0;\r\n};\r\n\r\nexport function __propKey(x) {\r\n return typeof x === \"symbol\" ? x : \"\".concat(x);\r\n};\r\n\r\nexport function __setFunctionName(f, name, prefix) {\r\n if (typeof name === \"symbol\") name = name.description ? \"[\".concat(name.description, \"]\") : \"\";\r\n return Object.defineProperty(f, \"name\", { configurable: true, value: prefix ? \"\".concat(prefix, \" \", name) : name });\r\n};\r\n\r\nexport function __metadata(metadataKey, metadataValue) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n}\r\n\r\nexport function __awaiter(thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nexport function __generator(thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === \"function\" ? Iterator : Object).prototype);\r\n return g.next = verb(0), g[\"throw\"] = verb(1), g[\"return\"] = verb(2), typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (g && (g = 0, op[0] && (_ = 0)), _) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\r\n\r\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n var desc = Object.getOwnPropertyDescriptor(m, k);\r\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\r\n desc = { enumerable: true, get: function() { return m[k]; } };\r\n }\r\n Object.defineProperty(o, k2, desc);\r\n}) : (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n o[k2] = m[k];\r\n});\r\n\r\nexport function __exportStar(m, o) {\r\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\r\n}\r\n\r\nexport function __values(o) {\r\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\r\n if (m) return m.call(o);\r\n if (o && typeof o.length === \"number\") return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\r\n}\r\n\r\nexport function __read(o, n) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n if (!m) return o;\r\n var i = m.call(o), r, ar = [], e;\r\n try {\r\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n }\r\n catch (error) { e = { error: error }; }\r\n finally {\r\n try {\r\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n }\r\n finally { if (e) throw e.error; }\r\n }\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spread() {\r\n for (var ar = [], i = 0; i < arguments.length; i++)\r\n ar = ar.concat(__read(arguments[i]));\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spreadArrays() {\r\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n r[k] = a[j];\r\n return r;\r\n}\r\n\r\nexport function __spreadArray(to, from, pack) {\r\n if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\r\n if (ar || !(i in from)) {\r\n if (!ar) ar = Array.prototype.slice.call(from, 0, i);\r\n ar[i] = from[i];\r\n }\r\n }\r\n return to.concat(ar || Array.prototype.slice.call(from));\r\n}\r\n\r\nexport function __await(v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nexport function __asyncGenerator(thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = Object.create((typeof AsyncIterator === \"function\" ? AsyncIterator : Object).prototype), verb(\"next\"), verb(\"throw\"), verb(\"return\", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }\r\n function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\r\n\r\nexport function __asyncDelegator(o) {\r\n var i, p;\r\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; }\r\n}\r\n\r\nexport function __asyncValues(o) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var m = o[Symbol.asyncIterator], i;\r\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n}\r\n\r\nexport function __makeTemplateObject(cooked, raw) {\r\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n return cooked;\r\n};\r\n\r\nvar __setModuleDefault = Object.create ? (function(o, v) {\r\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\r\n}) : function(o, v) {\r\n o[\"default\"] = v;\r\n};\r\n\r\nvar ownKeys = function(o) {\r\n ownKeys = Object.getOwnPropertyNames || function (o) {\r\n var ar = [];\r\n for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;\r\n return ar;\r\n };\r\n return ownKeys(o);\r\n};\r\n\r\nexport function __importStar(mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== \"default\") __createBinding(result, mod, k[i]);\r\n __setModuleDefault(result, mod);\r\n return result;\r\n}\r\n\r\nexport function __importDefault(mod) {\r\n return (mod && mod.__esModule) ? mod : { default: mod };\r\n}\r\n\r\nexport function __classPrivateFieldGet(receiver, state, kind, f) {\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\r\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\r\n}\r\n\r\nexport function __classPrivateFieldSet(receiver, state, value, kind, f) {\r\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\r\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\r\n}\r\n\r\nexport function __classPrivateFieldIn(state, receiver) {\r\n if (receiver === null || (typeof receiver !== \"object\" && typeof receiver !== \"function\")) throw new TypeError(\"Cannot use 'in' operator on non-object\");\r\n return typeof state === \"function\" ? receiver === state : state.has(receiver);\r\n}\r\n\r\nexport function __addDisposableResource(env, value, async) {\r\n if (value !== null && value !== void 0) {\r\n if (typeof value !== \"object\" && typeof value !== \"function\") throw new TypeError(\"Object expected.\");\r\n var dispose, inner;\r\n if (async) {\r\n if (!Symbol.asyncDispose) throw new TypeError(\"Symbol.asyncDispose is not defined.\");\r\n dispose = value[Symbol.asyncDispose];\r\n }\r\n if (dispose === void 0) {\r\n if (!Symbol.dispose) throw new TypeError(\"Symbol.dispose is not defined.\");\r\n dispose = value[Symbol.dispose];\r\n if (async) inner = dispose;\r\n }\r\n if (typeof dispose !== \"function\") throw new TypeError(\"Object not disposable.\");\r\n if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };\r\n env.stack.push({ value: value, dispose: dispose, async: async });\r\n }\r\n else if (async) {\r\n env.stack.push({ async: true });\r\n }\r\n return value;\r\n\r\n}\r\n\r\nvar _SuppressedError = typeof SuppressedError === \"function\" ? SuppressedError : function (error, suppressed, message) {\r\n var e = new Error(message);\r\n return e.name = \"SuppressedError\", e.error = error, e.suppressed = suppressed, e;\r\n};\r\n\r\nexport function __disposeResources(env) {\r\n function fail(e) {\r\n env.error = env.hasError ? new _SuppressedError(e, env.error, \"An error was suppressed during disposal.\") : e;\r\n env.hasError = true;\r\n }\r\n var r, s = 0;\r\n function next() {\r\n while (r = env.stack.pop()) {\r\n try {\r\n if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);\r\n if (r.dispose) {\r\n var result = r.dispose.call(r.value);\r\n if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });\r\n }\r\n else s |= 1;\r\n }\r\n catch (e) {\r\n fail(e);\r\n }\r\n }\r\n if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();\r\n if (env.hasError) throw env.error;\r\n }\r\n return next();\r\n}\r\n\r\nexport function __rewriteRelativeImportExtension(path, preserveJsx) {\r\n if (typeof path === \"string\" && /^\\.\\.?\\//.test(path)) {\r\n return path.replace(/\\.(tsx)$|((?:\\.d)?)((?:\\.[^./]+?)?)\\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {\r\n return tsx ? preserveJsx ? \".jsx\" : \".js\" : d && (!ext || !cm) ? m : (d + ext + \".\" + cm.toLowerCase() + \"js\");\r\n });\r\n }\r\n return path;\r\n}\r\n\r\nexport default {\r\n __extends: __extends,\r\n __assign: __assign,\r\n __rest: __rest,\r\n __decorate: __decorate,\r\n __param: __param,\r\n __esDecorate: __esDecorate,\r\n __runInitializers: __runInitializers,\r\n __propKey: __propKey,\r\n __setFunctionName: __setFunctionName,\r\n __metadata: __metadata,\r\n __awaiter: __awaiter,\r\n __generator: __generator,\r\n __createBinding: __createBinding,\r\n __exportStar: __exportStar,\r\n __values: __values,\r\n __read: __read,\r\n __spread: __spread,\r\n __spreadArrays: __spreadArrays,\r\n __spreadArray: __spreadArray,\r\n __await: __await,\r\n __asyncGenerator: __asyncGenerator,\r\n __asyncDelegator: __asyncDelegator,\r\n __asyncValues: __asyncValues,\r\n __makeTemplateObject: __makeTemplateObject,\r\n __importStar: __importStar,\r\n __importDefault: __importDefault,\r\n __classPrivateFieldGet: __classPrivateFieldGet,\r\n __classPrivateFieldSet: __classPrivateFieldSet,\r\n __classPrivateFieldIn: __classPrivateFieldIn,\r\n __addDisposableResource: __addDisposableResource,\r\n __disposeResources: __disposeResources,\r\n __rewriteRelativeImportExtension: __rewriteRelativeImportExtension,\r\n};\r\n","/**\n * Augmented red-black interval tree for efficient overlap queries.\n *\n * Port of igv.js `js/intervalTree.ts` (CLR-based implementation).\n * Typed generically — values stored in intervals are `T` instead of `unknown`.\n *\n * Each node stores augmented min/max for its subtree, enabling O(log n + k)\n * overlap queries via subtree pruning.\n *\n * Layer 1 (Data + Layout) — pure data structure, no DOM, no canvas.\n */\n\nconst BLACK = 1\nconst RED = 2\n\n/** An interval with an associated value. */\nexport interface Interval<T = unknown> {\n low: number\n high: number\n value: T\n}\n\ninterface TreeNode<T> {\n color: number\n parent: TreeNode<T>\n left: TreeNode<T>\n right: TreeNode<T>\n interval: Interval<T>\n /** Augmented: maximum high value in this subtree. */\n max: number\n /** Augmented: minimum low value in this subtree. */\n min: number\n}\n\n// Shared NIL sentinel — avoids null checks throughout.\n// Self-referential: NIL.parent = NIL.left = NIL.right = NIL.\nconst NIL = {} as TreeNode<never>\nNIL.color = BLACK\nNIL.parent = NIL\nNIL.left = NIL\nNIL.right = NIL\n// NIL needs valid min/max for comparisons in applyUpdate.\n// Use +Infinity/-Infinity so NIL never wins min/max comparisons.\nNIL.min = Infinity\nNIL.max = -Infinity\n\n/**\n * Augmented red-black interval tree.\n *\n * Public API:\n * - `insert(start, end, value)` — O(log n) insertion\n * - `findOverlapping(start, end)` — O(log n + k) query, returns sorted intervals\n * - `mapIntervals(fn)` — apply function to every interval (in-order)\n */\nexport class IntervalTree<T = unknown> {\n root: TreeNode<T>\n\n constructor() {\n this.root = NIL as TreeNode<T>\n }\n\n /**\n * Insert an interval [start, end] with associated value.\n * Maintains red-black balance and augmented min/max.\n */\n insert(start: number, end: number, value: T): void {\n const interval: Interval<T> = {low: start, high: end, value}\n const x = this.#createNode(interval)\n this.#treeInsert(x)\n x.color = RED\n let node = x\n while (node !== this.root && node.parent.color === RED) {\n if (node.parent === node.parent.parent.left) {\n const y = node.parent.parent.right\n if (y.color === RED) {\n node.parent.color = BLACK\n y.color = BLACK\n node.parent.parent.color = RED\n node = node.parent.parent\n } else {\n if (node === node.parent.right) {\n node = node.parent\n this.#leftRotate(node)\n }\n node.parent.color = BLACK\n node.parent.parent.color = RED\n this.#rightRotate(node.parent.parent)\n }\n } else {\n const y = node.parent.parent.left\n if (y.color === RED) {\n node.parent.color = BLACK\n y.color = BLACK\n node.parent.parent.color = RED\n node = node.parent.parent\n } else {\n if (node === node.parent.left) {\n node = node.parent\n this.#rightRotate(node)\n }\n node.parent.color = BLACK\n node.parent.parent.color = RED\n this.#leftRotate(node.parent.parent)\n }\n }\n }\n this.root.color = BLACK\n }\n\n /**\n * Find all intervals overlapping [start, end].\n * Returns intervals sorted by `low` value.\n */\n findOverlapping(start: number, end: number): Interval<T>[] {\n if (this.root === (NIL as TreeNode<T>)) return []\n\n const results = this.#searchAll(start, end, this.root, [])\n\n if (results.length > 1) {\n results.sort((a, b) => a.low - b.low)\n }\n\n return results\n }\n\n /**\n * Apply a function to every interval in the tree.\n */\n mapIntervals(fn: (interval: Interval<T>) => void): void {\n const applyInterval = (node: TreeNode<T>): void => {\n fn(node.interval)\n if (node.left !== (NIL as TreeNode<T>)) applyInterval(node.left)\n if (node.right !== (NIL as TreeNode<T>)) applyInterval(node.right)\n }\n if (this.root !== (NIL as TreeNode<T>)) {\n applyInterval(this.root)\n }\n }\n\n #createNode(interval: Interval<T>): TreeNode<T> {\n return {\n parent: NIL as TreeNode<T>,\n left: NIL as TreeNode<T>,\n right: NIL as TreeNode<T>,\n interval,\n color: RED,\n max: interval.high,\n min: interval.low,\n }\n }\n\n #searchAll(low: number, high: number, node: TreeNode<T>, results: Interval<T>[]): Interval<T>[] {\n // Check if this node's interval overlaps the query\n if (node.interval.low <= high && low <= node.interval.high) {\n results.push(node.interval)\n }\n\n // Prune: left subtree can contain overlaps only if its max >= query low\n if (node.left !== (NIL as TreeNode<T>) && node.left.max >= low) {\n this.#searchAll(low, high, node.left, results)\n }\n\n // Prune: right subtree can contain overlaps only if its min <= query high\n if (node.right !== (NIL as TreeNode<T>) && node.right.min <= high) {\n this.#searchAll(low, high, node.right, results)\n }\n\n return results\n }\n\n #leftRotate(x: TreeNode<T>): void {\n const y = x.right\n x.right = y.left\n if (y.left !== (NIL as TreeNode<T>)) {\n y.left.parent = x\n }\n y.parent = x.parent\n if (x.parent === (NIL as TreeNode<T>)) {\n this.root = y\n } else {\n if (x.parent.left === x) {\n x.parent.left = y\n } else {\n x.parent.right = y\n }\n }\n y.left = x\n x.parent = y\n this.#applyUpdate(x)\n }\n\n #rightRotate(x: TreeNode<T>): void {\n const y = x.left\n x.left = y.right\n if (y.right !== (NIL as TreeNode<T>)) {\n y.right.parent = x\n }\n y.parent = x.parent\n if (x.parent === (NIL as TreeNode<T>)) {\n this.root = y\n } else {\n if (x.parent.right === x) {\n x.parent.right = y\n } else {\n x.parent.left = y\n }\n }\n y.right = x\n x.parent = y\n this.#applyUpdate(x)\n }\n\n /** Update augmented min/max from node up to root. */\n #applyUpdate(node: TreeNode<T>): void {\n while (node !== (NIL as TreeNode<T>)) {\n const nodeMax = node.left.max > node.right.max ? node.left.max : node.right.max\n const intervalHigh = node.interval.high\n node.max = nodeMax > intervalHigh ? nodeMax : intervalHigh\n\n const nodeMin = node.left.min < node.right.min ? node.left.min : node.right.min\n const intervalLow = node.interval.low\n node.min = nodeMin < intervalLow ? nodeMin : intervalLow\n\n node = node.parent\n }\n }\n\n /** BST insertion (no RB rebalancing — done by caller). */\n #treeInsert(x: TreeNode<T>): void {\n let node = this.root\n let y = NIL as TreeNode<T>\n while (node !== (NIL as TreeNode<T>)) {\n y = node\n if (x.interval.low <= node.interval.low) {\n node = node.left\n } else {\n node = node.right\n }\n }\n x.parent = y\n\n if (y === (NIL as TreeNode<T>)) {\n this.root = x\n x.left = x.right = NIL as TreeNode<T>\n } else {\n if (x.interval.low <= y.interval.low) {\n y.left = x\n } else {\n y.right = x\n }\n }\n\n this.#applyUpdate(x)\n }\n}\n","/**\n * Feature cache with interval-tree-backed spatial queries.\n *\n * Port of igv.js `js/feature/featureCache.ts`. Features are grouped by\n * chromosome, sorted, chunked, and indexed via IntervalTree for O(log n + k)\n * range queries.\n *\n * Layer 1 (Data + Layout) — pure data structure, no DOM, no canvas.\n */\n\nimport {IntervalTree} from './intervalTree'\n\n/** Minimal interface for features stored in the cache. */\nexport interface CacheableFeature {\n chr: string\n start: number\n end: number\n}\n\n/**\n * Range metadata describing what genomic region is fully cached.\n * When present, `containsRange()` delegates to this; when absent,\n * the cache is assumed to contain all features (e.g., whole-file load).\n */\nexport interface CacheRange {\n contains(chr: string, start: number, end: number): boolean\n}\n\n/** Index range pointing into the sorted allFeatures[chr] array. */\ninterface IndexRange {\n start: number\n end: number\n}\n\n/**\n * Spatial feature cache backed by per-chromosome interval trees.\n *\n * Features are chunked (max(10, len/10) per chunk) to reduce tree size\n * while maintaining fast overlap queries. Matches igv.js FeatureCache.\n *\n * @typeParam F - Feature type, must have chr/start/end at minimum.\n */\nexport class FeatureCache<F extends CacheableFeature> {\n /** Per-chromosome interval trees indexing feature chunks. */\n readonly treeMap: Record<string, IntervalTree<IndexRange>>\n /** Optional range metadata for partial-cache validation. */\n readonly range: CacheRange | undefined\n /** Total number of cached features across all chromosomes. */\n readonly count: number\n /** All features grouped by chromosome, sorted by start. */\n readonly allFeatures: Record<string, F[]>\n\n constructor(featureList?: F[], range?: CacheRange) {\n const features = featureList ?? []\n this.range = range\n this.count = features.length\n const {treeMap, allFeatures} = buildTreeMap(features)\n this.treeMap = treeMap\n this.allFeatures = allFeatures\n }\n\n /**\n * Check if the cache covers a genomic range.\n * Returns true when no range metadata is set (cache assumed complete)\n * or when the range metadata confirms coverage.\n */\n containsRange(chr: string, start: number, end: number): boolean {\n return this.range === undefined || this.range.contains(chr, start, end)\n }\n\n /**\n * Query features overlapping [start, end] on the given chromosome.\n * Returns features sorted by start position. O(log n + k) via interval tree.\n */\n queryFeatures(chr: string, start: number, end: number): F[] {\n const tree = this.treeMap[chr]\n if (!tree) return []\n\n const intervals = tree.findOverlapping(start, end)\n if (intervals.length === 0) return []\n\n // Trim features within matching chunks to the exact query range.\n // Relies on allFeatures[chr] being sorted by start.\n const featureList: F[] = []\n const all = this.allFeatures[chr]\n if (all) {\n for (const interval of intervals) {\n const indexRange = interval.value\n for (let i = indexRange.start; i < indexRange.end; i++) {\n const feature = all[i]\n if (feature.start > end) break\n else if (feature.end >= start) {\n featureList.push(feature)\n }\n }\n }\n featureList.sort((a, b) => a.start - b.start)\n }\n return featureList\n }\n\n /**\n * Search all cached features matching a predicate.\n * Scans every feature across all chromosomes — O(n).\n */\n findFeatures(fn: (f: F) => boolean): F[] {\n const found: F[] = []\n for (const featureList of Object.values(this.allFeatures)) {\n for (const f of featureList) {\n if (fn(f)) {\n found.push(f)\n }\n }\n }\n return found\n }\n\n /**\n * Returns all features grouped by chromosome.\n */\n getAllFeatures(): Record<string, F[]> {\n return this.allFeatures\n }\n}\n\n/**\n * Build per-chromosome interval trees from a feature list.\n *\n * Groups features by chr, sorts each group by start, chunks into groups\n * of max(10, len/10), and indexes chunk bounds in an interval tree.\n * This reduces tree size by 10x+ while maintaining fast overlap queries.\n */\nfunction buildTreeMap<F extends CacheableFeature>(\n featureList: F[],\n): {treeMap: Record<string, IntervalTree<IndexRange>>; allFeatures: Record<string, F[]>} {\n const treeMap: Record<string, IntervalTree<IndexRange>> = {}\n const allFeatures: Record<string, F[]> = {}\n const chromosomes: string[] = []\n\n // Group by chromosome\n for (const feature of featureList) {\n const chr = feature.chr\n let list = allFeatures[chr]\n if (!list) {\n chromosomes.push(chr)\n list = []\n allFeatures[chr] = list\n }\n list.push(feature)\n }\n\n // Build interval tree per chromosome\n for (const chr of chromosomes) {\n const chrFeatures = allFeatures[chr]\n chrFeatures.sort((a, b) => a.start === b.start ? 0 : (a.start > b.start ? 1 : -1))\n treeMap[chr] = buildIntervalTree(chrFeatures)\n }\n\n return {treeMap, allFeatures}\n}\n\n/**\n * Build an interval tree for a sorted feature array.\n *\n * Features are lumped into chunks of max(10, len/10) to reduce tree node\n * count. Each tree node stores the genomic extent of its chunk (min start,\n * max end) and an IndexRange pointing into the sorted array.\n */\nfunction buildIntervalTree<F extends CacheableFeature>(featureList: F[]): IntervalTree<IndexRange> {\n const tree = new IntervalTree<IndexRange>()\n const len = featureList.length\n const chunkSize = Math.max(10, Math.round(len / 10))\n\n for (let i = 0; i < len; i += chunkSize) {\n const e = Math.min(len, i + chunkSize)\n const subArray: IndexRange = {start: i, end: e}\n const iStart = featureList[i].start\n let iEnd = iStart\n for (let j = i; j < e; j++) {\n iEnd = Math.max(iEnd, featureList[j].end)\n }\n tree.insert(iStart, iEnd, subArray)\n }\n\n return tree\n}\n","/**\n * Tabix/BGZF reader — public API.\n *\n * Thin wrapper around @gmod/tabix that preserves the existing public API.\n * All BGZF decompression, index parsing, and block fetching is handled\n * by @gmod/tabix internally.\n */\n\nimport {TabixIndexedFile} from '@gmod/tabix'\nimport {RemoteFile} from 'generic-filehandle2'\nimport type {WorkerProvider} from '../workerProvider'\n\n// ─── Types (preserved for backward compatibility) ─────────────────────────────\n\nexport interface TabixReaderOptions {\n /** URL to the .tbi index file. Defaults to `url + '.tbi'`. */\n indexUrl?: string\n /** @deprecated Worker dispatch is handled internally by @gmod/tabix. */\n workerProvider?: WorkerProvider\n}\n\nexport interface TabixHeader {\n nref: number\n format: number\n colSeq: number\n colBeg: number\n colEnd: number\n meta: number\n skip: number\n sequenceNames: string[]\n}\n\n// ─── Public API ───────────────────────────────────────────────────────────────\n\n/**\n * Thin wrapper around @gmod/tabix TabixIndexedFile that preserves the legacy API.\n */\nexport class TabixReader {\n private readonly tabix: TabixIndexedFile\n\n constructor(url: string, options?: TabixReaderOptions) {\n const indexUrl = options?.indexUrl ?? url + '.tbi'\n this.tabix = new TabixIndexedFile({\n filehandle: new RemoteFile(url),\n tbiFilehandle: new RemoteFile(indexUrl),\n })\n }\n\n /** Get the tabix header metadata. */\n async getHeader(signal?: AbortSignal): Promise<TabixHeader> {\n const meta = await this.tabix.getMetadata({signal})\n const refNames = Object.keys(meta.refNameToId)\n return {\n nref: refNames.length,\n format: meta.format === 'VCF' ? 2 : meta.format === 'SAM' ? 1 : 0,\n colSeq: meta.columnNumbers.ref,\n colBeg: meta.columnNumbers.start,\n colEnd: meta.columnNumbers.end,\n meta: meta.metaChar?.charCodeAt(0) ?? 0,\n skip: 0,\n sequenceNames: refNames,\n }\n }\n\n /** Get sequence names from the index. */\n async getSequenceNames(signal?: AbortSignal): Promise<string[]> {\n const meta = await this.tabix.getMetadata({signal})\n return Object.keys(meta.refNameToId)\n }\n\n /**\n * Read header lines from the beginning of the BGZF data file.\n * Returns lines that start with the meta character (e.g. '#' for VCF).\n */\n async readHeaderLines(signal?: AbortSignal): Promise<string[]> {\n const headerStr = await this.tabix.getHeader({signal})\n if (!headerStr) return []\n return headerStr.split('\\n').filter(line => line.length > 0)\n }\n\n /**\n * Read all text lines overlapping a genomic range.\n *\n * @param chr - Chromosome/sequence name\n * @param start - Start position (0-based)\n * @param end - End position (exclusive)\n */\n async readLines(\n chr: string,\n start: number,\n end: number,\n signal?: AbortSignal,\n ): Promise<string[]> {\n const lines: string[] = []\n await this.tabix.getLines(chr, start, end, {\n lineCallback: (line: string) => {\n lines.push(line)\n },\n signal,\n })\n return lines\n }\n}\n","/**\n * BED format decoders — BED (3-12 columns), narrowPeak, broadPeak, bedGraph, gappedPeak.\n *\n * Port of js/feature/decode/ucsc.ts (decodeBed, decodePeak, decodeNarrowPeak,\n * decodeBedGraph, decodeGappedPeak).\n *\n * Layer 1 (Data + Layout): pure functions, no I/O, no DOM.\n */\n\nimport type {Exon, BedFeature, PeakFeature, BedGraphFeature} from '../types'\nimport {findUTRs, parseColorString, parseStrand} from './exonUtils'\n\n/** Header metadata extracted from track lines and column directives. */\nexport interface BedHeader {\n nameField?: string\n /** When true, column 4 may contain GFF-style key=value attributes. */\n gffTags?: boolean\n /** Column index for color (from #columns directive). */\n colorColumn?: number\n /** Column index for thickness (from #columns directive). */\n thicknessColumn?: number\n}\n\n/**\n * Decode a BED format line (3-12 columns) into a BedFeature.\n *\n * Port of js/feature/decode/ucsc.ts::decodeBed().\n * Preserves igv.js patterns:\n * - Column count gating with maxColumnCount\n * - GFF-style attribute parsing in col4 when contains `=` and `;`\n * - Exon block validation (count < 1000, sizes.length === starts.length === count)\n * - Early return on parse errors (partial feature returned, not rejected)\n * - Color parsing for col8 (skip \".\" and \"0\")\n */\nexport function decodeBed(\n tokens: string[],\n header?: BedHeader,\n maxColumnCount: number = Number.MAX_SAFE_INTEGER,\n): BedFeature | undefined {\n\n if (tokens.length < 3) return undefined\n\n const gffTags = header?.gffTags\n\n const chr = tokens[0]\n const start = parseInt(tokens[1])\n const end = tokens.length > 2 ? parseInt(tokens[2]) : start + 1\n if (isNaN(start) || isNaN(end)) return undefined\n\n const feature: BedFeature = {chr, start, end, score: 1000}\n\n let columnCount = 3\n\n // Column 3: name (or GFF-style attributes)\n if (tokens.length > 3 && columnCount++ < maxColumnCount) {\n if (tokens[3].indexOf(';') > 0 && tokens[3].indexOf('=') > 0) {\n const attrs = parseGFFStyleAttributes(tokens[3])\n feature.attributes = attrs\n if (gffTags) {\n if (header?.nameField != null && attrs[header.nameField]) {\n feature.name = attrs[header.nameField]\n } else if (!feature.name) {\n for (const field of gffNameFields) {\n if (attrs[field]) {\n feature.name = attrs[field]\n break\n }\n }\n }\n }\n }\n if (!feature.name && !gffTags) {\n feature.name = tokens[3] === '.' ? '' : tokens[3]\n }\n }\n\n // Column 4: score\n if (tokens.length > 4 && columnCount++ < maxColumnCount) {\n feature.score = tokens[4] === '.' ? 0 : Number(tokens[4])\n if (isNaN(feature.score)) return feature\n }\n\n // Column 5: strand\n if (tokens.length > 5 && columnCount++ < maxColumnCount) {\n const s = tokens[5]\n if (s !== '.' && s !== '+' && s !== '-') return feature\n feature.strand = s as '+' | '-' | '.'\n }\n\n // Column 6: thickStart (cdStart)\n if (tokens.length > 6 && columnCount++ < maxColumnCount) {\n feature.cdStart = parseInt(tokens[6])\n if (isNaN(feature.cdStart)) return feature\n }\n\n // Column 7: thickEnd (cdEnd)\n if (tokens.length > 7 && columnCount++ < maxColumnCount) {\n feature.cdEnd = parseInt(tokens[7])\n if (isNaN(feature.cdEnd)) return feature\n }\n\n // Column 8: color\n if (tokens.length > 8 && columnCount++ < maxColumnCount) {\n if (tokens[8] !== '.' && tokens[8] !== '0') {\n feature.color = parseColorString(tokens[8])\n }\n }\n\n // Columns 9-11: exon blocks (blockCount, blockSizes, blockStarts)\n if (tokens.length > 11 && columnCount++ < maxColumnCount) {\n const exonCount = parseInt(tokens[9])\n // Basic sanity check\n if (exonCount > 1000) return feature\n\n const exonSizes = tokens[10].replace(/,$/, '').split(',')\n const exonStarts = tokens[11].replace(/,$/, '').split(',')\n if (!(exonSizes.length === exonStarts.length && exonCount === exonSizes.length)) {\n return feature\n }\n\n const exons: Exon[] = []\n for (let i = 0; i < exonCount; i++) {\n const eStart = start + parseInt(exonStarts[i])\n const eEnd = eStart + parseInt(exonSizes[i])\n exons.push({start: eStart, end: eEnd})\n }\n if (exons.length > 0) {\n findUTRs(exons, feature.cdStart ?? start, feature.cdEnd ?? end)\n feature.exons = exons\n }\n }\n\n // Optional extra columns from header directives\n if (header) {\n if (header.thicknessColumn !== undefined && tokens.length > header.thicknessColumn) {\n feature.thickness = parseFloat(tokens[header.thicknessColumn])\n }\n if (header.colorColumn !== undefined && tokens.length > header.colorColumn) {\n const c = parseColorString(tokens[header.colorColumn])\n if (c) feature.color = c\n }\n }\n\n return feature\n}\n\n/**\n * Decode a broadPeak/regionPeak format line (BED6+3: signal, pValue, qValue).\n *\n * Port of js/feature/decode/ucsc.ts::decodePeak().\n */\nexport function decodeBroadPeak(tokens: string[], header?: BedHeader): PeakFeature | undefined {\n const bed = decodeBed(tokens, header, 6) as PeakFeature | undefined\n if (!bed) return undefined\n\n if (tokens.length > 6) bed.signal = parseFloat(tokens[6])\n if (tokens.length > 7) bed.pValue = parseFloat(tokens[7])\n if (tokens.length > 8) bed.qValue = parseFloat(tokens[8])\n\n return bed\n}\n\n/**\n * Decode a narrowPeak format line (BED6+4: signal, pValue, qValue, peak).\n *\n * Port of js/feature/decode/ucsc.ts::decodeNarrowPeak().\n */\nexport function decodeNarrowPeak(tokens: string[], header?: BedHeader): PeakFeature | undefined {\n const bed = decodeBed(tokens, header, 6) as PeakFeature | undefined\n if (!bed) return undefined\n\n if (tokens.length > 6) bed.signal = parseFloat(tokens[6])\n if (tokens.length > 7) bed.pValue = parseFloat(tokens[7])\n if (tokens.length > 8) bed.qValue = parseFloat(tokens[8])\n if (tokens.length > 9) bed.peak = parseInt(tokens[9])\n\n return bed\n}\n\n/**\n * Decode a gappedPeak format line (BED12+3: signal, pValue, qValue).\n *\n * Port of js/feature/decode/ucsc.ts::decodeGappedPeak().\n */\nexport function decodeGappedPeak(tokens: string[], header?: BedHeader): PeakFeature | undefined {\n const bed = decodeBed(tokens, header) as PeakFeature | undefined\n if (!bed) return undefined\n\n if (tokens.length > 12) bed.signal = parseFloat(tokens[12])\n if (tokens.length > 13) bed.pValue = parseFloat(tokens[13])\n if (tokens.length > 14) bed.qValue = parseFloat(tokens[14])\n\n return bed\n}\n\n/**\n * Decode a BedGraph line (chr, start, end, value).\n *\n * Port of js/feature/decode/ucsc.ts::decodeBedGraph().\n */\nexport function decodeBedGraph(tokens: string[]): BedGraphFeature | undefined {\n if (tokens.length < 4) return undefined\n\n const chr = tokens[0]\n const start = parseInt(tokens[1])\n const end = parseInt(tokens[2])\n const value = parseFloat(tokens[3])\n\n if (isNaN(start) || isNaN(end) || isNaN(value)) return undefined\n\n return {chr, start, end, value}\n}\n\n/**\n * Decode a refFlat format line.\n *\n * Format: geneName, name, chrom, strand, txStart, txEnd, cdsStart, cdsEnd,\n * exonCount, exonStarts, exonEnds\n *\n * Port of js/feature/decode/ucsc.ts::decodeReflat().\n */\nexport function decodeRefflat(tokens: string[]): BedFeature | undefined {\n if (tokens.length < 11) return undefined\n\n const chr = tokens[2]\n const start = parseInt(tokens[4])\n const end = parseInt(tokens[5])\n const cdStart = parseInt(tokens[6])\n const cdEnd = parseInt(tokens[7])\n const strand = parseStrand(tokens[3])\n\n if (isNaN(start) || isNaN(end)) return undefined\n\n const feature: BedFeature = {\n chr,\n start,\n end,\n name: tokens[0],\n strand: strand as BedFeature['strand'],\n cdStart,\n cdEnd,\n }\n\n const exonCount = parseInt(tokens[8])\n const exonStarts = tokens[9].replace(/,$/, '').split(',')\n const exonEnds = tokens[10].replace(/,$/, '').split(',')\n\n if (exonCount > 0 && exonStarts.length === exonCount && exonEnds.length === exonCount) {\n const exons: Exon[] = []\n for (let i = 0; i < exonCount; i++) {\n exons.push({start: parseInt(exonStarts[i]), end: parseInt(exonEnds[i])})\n }\n findUTRs(exons, cdStart, cdEnd)\n feature.exons = exons\n }\n\n return feature\n}\n\n// ─── Internal helpers ────────────────────────────────────────────────────────\n\nconst gffNameFields = ['Name', 'transcript_id', 'gene_name', 'gene', 'gene_id', 'alias', 'locus', 'name']\n\n/** Parse GFF-style key=value attributes from BED column 4. */\nfunction parseGFFStyleAttributes(value: string): Record<string, string> {\n const attrs: Record<string, string> = {}\n const pairs = value.split(';')\n for (const pair of pairs) {\n const idx = pair.indexOf('=')\n if (idx > 0) {\n const key = pair.substring(0, idx).trim()\n const val = pair.substring(idx + 1).trim()\n attrs[key] = val\n }\n }\n return attrs\n}\n","/**\n * GFF3/GTF format decoders and transcript assembly.\n *\n * Ports:\n * - js/feature/gff/gff.ts (decodeGFF3, decodeGTF)\n * - js/feature/gff/parseAttributeString.ts (parseAttributeString, decodeGFFAttribute)\n * - js/feature/gff/gffHelper.ts (combineFeatures — transcript assembly)\n * - js/feature/gff/so.ts (sequence ontology type checks)\n *\n * Layer 1 (Data + Layout): pure functions, no I/O, no DOM.\n */\n\nimport type {Exon, GFFRecord, GFFFeature} from '../types'\n\n// ─── Sequence ontology type checks (port of js/feature/gff/so.ts) ───────────\n\nconst transcriptTypes = new Set([\n 'transcript', 'primary_transcript', 'processed_transcript', 'mRNA', 'mrna',\n 'lnc_RNA', 'miRNA', 'ncRNA', 'rRNA', 'scRNA', 'snRNA', 'snoRNA', 'tRNA',\n])\nconst cdsTypes = new Set(['CDS', 'cds', 'start_codon', 'stop_codon'])\nconst utrTypes = new Set(['5UTR', '3UTR', 'UTR', 'five_prime_UTR', 'three_prime_UTR', \"3'-UTR\", \"5'-UTR\"])\nconst exonTypes = new Set(['exon', 'coding-exon'])\n\nconst transcriptPartTypes = new Set<string>()\nfor (const cltn of [cdsTypes, utrTypes, exonTypes]) {\n for (const t of cltn) transcriptPartTypes.add(t)\n}\n\nexport function isTranscript(type: string): boolean {\n return transcriptTypes.has(type) || type.endsWith('RNA') || type.endsWith('transcript')\n}\nexport function isTranscriptPart(type: string): boolean {\n return transcriptPartTypes.has(type) || type.endsWith('RNA') || isIntron(type)\n}\nexport function isExon(type: string): boolean { return exonTypes.has(type) }\nexport function isIntron(type: string): boolean { return type.includes('intron') }\nexport function isCoding(type: string): boolean { return cdsTypes.has(type) }\nexport function isUTR(type: string): boolean { return utrTypes.has(type) }\n\n// ─── GFF attribute parsing (port of js/feature/gff/parseAttributeString.ts) ─\n\nconst gffEncodings = new Map<string, string>([\n ['%09', '\\t'], ['%0A', '\\n'], ['%0D', '\\r'], ['%25', '%'],\n ['%3B', ';'], ['%3D', '='], ['%26', '&'], ['%2C', ','],\n])\n\n/** Decode GFF3 percent-encoded characters. */\nexport function decodeGFFAttribute(str: string): string {\n if (!str.includes('%')) return str\n let decoded = ''\n for (let i = 0; i < str.length; i++) {\n if (str.charCodeAt(i) === 37 && i < str.length - 2) {\n const key = str.substring(i, i + 3)\n if (gffEncodings.has(key)) {\n decoded += gffEncodings.get(key)!\n } else {\n decoded += key\n }\n i += 2\n } else {\n decoded += str.charAt(i)\n }\n }\n return decoded\n}\n\n/**\n * Parse GFF/GTF attribute string (column 9) into key-value pairs.\n *\n * Returns an array (not a map) because attribute keys are not required to be unique.\n * GFF3 uses `=` as key-value delimiter, GTF uses space.\n *\n * Port of js/feature/gff/parseAttributeString.ts::parseAttributeString().\n */\nexport function parseGFFAttributes(attributeString: string, keyValueDelim: string = '='): Array<[string, string]> {\n const isGff3 = keyValueDelim === '='\n const attributes: Array<[string, string]> = []\n for (let kv of attributeString.split(';')) {\n kv = kv.trim()\n const idx = kv.indexOf(keyValueDelim)\n if (idx > 0 && idx < kv.length - 1) {\n let key = decodeGFFAttribute(kv.substring(0, idx).trim())\n let value = decodeGFFAttribute(kv.substring(idx + 1).trim())\n if (!isGff3) {\n key = stripQuotes(key)\n value = stripQuotes(value)\n }\n attributes.push([key, value])\n }\n }\n return attributes\n}\n\nfunction stripQuotes(value: string): string {\n if (value.startsWith('\"') && value.endsWith('\"')) {\n return value.substring(1, value.length - 1)\n }\n return value\n}\n\n// ─── Single-record decoders (port of js/feature/gff/gff.ts) ────────────────\n\nfunction decodeBase(tokens: string[], _delim: string): GFFRecord | undefined {\n if (tokens.length < 9) return undefined\n\n const start = parseInt(tokens[3]) - 1 // GFF is 1-based\n const end = parseInt(tokens[4])\n if (isNaN(start) || isNaN(end)) return undefined\n\n const score = tokens[5] === '.' ? undefined : Number(tokens[5])\n const strand = tokens[6] === '+' || tokens[6] === '-' || tokens[6] === '.'\n ? tokens[6] as '+' | '-' | '.'\n : undefined\n const phase = tokens[7] === '.' ? undefined : parseInt(tokens[7])\n\n return {\n chr: tokens[0],\n source: decodeGFFAttribute(tokens[1]),\n type: tokens[2],\n start,\n end,\n score: score !== undefined && !isNaN(score) ? score : undefined,\n strand,\n phase: phase !== undefined && !isNaN(phase) ? phase : undefined,\n attributeString: tokens[8],\n attributes: {},\n }\n}\n\n/**\n * Decode a single GFF3 record line.\n *\n * Parses column 9 attributes with `=` delimiter, extracts ID, Parent, color.\n */\nexport function decodeGFF3(tokens: string[]): GFFRecord | undefined {\n const feature = decodeBase(tokens, '=')\n if (!feature) return undefined\n\n const attributes = parseGFFAttributes(feature.attributeString, '=')\n const attrs: Record<string, string> = {}\n\n for (const [key, value] of attributes) {\n attrs[key] = value\n const keyLower = key.toLowerCase()\n if (keyLower === 'color' || keyLower === 'colour') {\n feature.color = value\n } else if (key === 'ID') {\n feature.id = value\n } else if (key === 'Parent') {\n feature.parent = value\n }\n }\n feature.attributes = attrs\n\n return feature\n}\n\n/**\n * Decode a single GTF record line.\n *\n * Parses column 9 attributes with space delimiter, infers ID/Parent from\n * feature type (gene→gene_id, transcript→transcript_id, exon→transcript_id parent).\n */\nexport function decodeGTF(tokens: string[]): GFFRecord | undefined {\n const feature = decodeBase(tokens, ' ')\n if (!feature) return undefined\n\n const attributes = parseGFFAttributes(feature.attributeString, ' ')\n const attrs: Record<string, string> = {}\n\n // Infer ID/Parent fields based on feature type\n let idField: string | undefined\n let parentField: string | undefined\n switch (feature.type) {\n case 'gene':\n idField = 'gene_id'\n break\n case 'transcript':\n idField = 'transcript_id'\n parentField = 'gene_id'\n break\n default:\n parentField = 'transcript_id'\n }\n\n for (const [key, value] of attributes) {\n attrs[key] = value\n const keyLower = key.toLowerCase()\n if (keyLower === 'color' || keyLower === 'colour') {\n feature.color = value\n } else if (key === idField) {\n feature.id = value\n } else if (key === parentField) {\n feature.parent = value\n }\n }\n feature.attributes = attrs\n\n return feature\n}\n\n// ─── GFF name field resolution ──────────────────────────────────────────────\n\nconst gffNameFields = ['Name', 'transcript_id', 'gene_name', 'gene', 'gene_id', 'alias', 'locus', 'name']\n\nfunction getAttributeValue(record: GFFRecord, name: string): string | undefined {\n if (record.attributes[name] !== undefined) return record.attributes[name]\n // Fall back to parsing attribute string\n const delim = record.attributeString.includes('=') ? '=' : ' '\n const attrs = parseGFFAttributes(record.attributeString, delim)\n for (const [key, value] of attrs) {\n if (key === name) return value\n }\n return undefined\n}\n\n// ─── Transcript assembly (port of js/feature/gff/gffHelper.ts) ─────────────\n\ninterface AssemblyOptions {\n /** Custom name field to use for feature names. */\n nameField?: string\n /** Feature types to filter out (default: ['chromosome']). */\n filterTypes?: string[]\n}\n\n/** Internal transcript model used during assembly. */\ninterface TranscriptBuilder {\n record: GFFRecord\n exons: Exon[]\n parts: GFFRecord[]\n cdStart?: number\n cdEnd?: number\n geneRecord?: GFFRecord\n}\n\n/**\n * Assemble flat GFFRecords into hierarchical GFFFeatures (transcripts with exon structure).\n *\n * Combines gene→transcript→exon/CDS records by parent/ID relationships.\n * Handles both GFF3 (explicit ID/Parent) and GTF (inferred from feature type).\n *\n * Port of js/feature/gff/gffHelper.ts::combineFeatures().\n */\nexport function assembleGFFTranscripts(\n records: GFFRecord[],\n format: 'gff3' | 'gtf' | 'gff',\n options?: AssemblyOptions,\n): GFFFeature[] {\n const filterTypes = new Set(options?.filterTypes ?? ['chromosome'])\n let filtered = records.filter(r => !filterTypes.has(r.type))\n\n // For GFF3, merge multi-part features with same ID\n if (format === 'gff3' || format === 'gff') {\n filtered = combineFeaturesById(filtered)\n }\n\n const result = combineFeaturesByType(filtered, format, options?.nameField)\n return result\n}\n\n/**\n * Combine multiple non-transcript features with the same ID on the same chromosome.\n * Port of GFFHelper.combineFeaturesById().\n */\nfunction combineFeaturesById(records: GFFRecord[]): GFFRecord[] {\n const chrIdMap = new Map<string, Map<string, GFFRecord[]>>()\n const combined: GFFRecord[] = []\n\n for (const f of records) {\n if (isTranscriptPart(f.type) || isTranscript(f.type) || !f.id) {\n combined.push(f)\n } else {\n let idMap = chrIdMap.get(f.chr)\n if (!idMap) {\n idMap = new Map()\n chrIdMap.set(f.chr, idMap)\n }\n let arr = idMap.get(f.id)\n if (arr) {\n arr.push(f)\n } else {\n idMap.set(f.id, [f])\n }\n }\n }\n\n for (const idMap of chrIdMap.values()) {\n for (const arr of idMap.values()) {\n if (arr.length > 1) {\n // Use first as prototype, merge spans as exons\n const cf = {...arr[0]}\n const exons: Array<{start: number; end: number}> = []\n for (const f of arr) {\n cf.start = Math.min(cf.start, f.start)\n cf.end = Math.max(cf.end, f.end)\n exons.push({start: f.start, end: f.end})\n }\n // Store merged exons in a temporary property\n ;(cf as GFFRecord & {_mergedExons?: Array<{start: number; end: number}>})._mergedExons = exons\n combined.push(cf)\n } else {\n combined.push(arr[0])\n }\n }\n }\n\n return combined\n}\n\n/**\n * Build gene→transcript→exon hierarchy from flat records.\n * Port of GFFHelper.combineFeaturesByType().\n */\nfunction combineFeaturesByType(\n records: GFFRecord[],\n format: string,\n nameField?: string,\n): GFFFeature[] {\n // Build gene map\n const geneMap: Record<string, GFFRecord> = Object.create(null)\n for (const r of records) {\n if (r.type === 'gene' || r.type.endsWith('_gene')) {\n if (r.id) geneMap[r.id] = r\n }\n }\n\n // Build transcript map\n const transcripts: Record<string, TranscriptBuilder> = Object.create(null)\n const result: GFFFeature[] = []\n const consumed = new Set<GFFRecord>()\n\n for (const r of records) {\n if (isTranscript(r.type) && r.id !== undefined) {\n const builder: TranscriptBuilder = {\n record: r,\n exons: [],\n parts: [],\n }\n transcripts[r.id] = builder\n consumed.add(r)\n\n // Link to parent gene\n if (r.parent && geneMap[r.parent]) {\n builder.geneRecord = geneMap[r.parent]\n consumed.add(geneMap[r.parent])\n }\n }\n }\n\n // Add exons and transcript parts\n for (const r of records) {\n if (isTranscriptPart(r.type)) {\n const parents = getParents(r)\n if (parents) {\n for (const parentId of parents) {\n let transcript = transcripts[parentId]\n if (!transcript && (format === 'gtf')) {\n // GTF does not require explicit transcript record\n const pseudoRecord: GFFRecord = {...r, type: 'transcript'}\n transcript = {record: pseudoRecord, exons: [], parts: []}\n transcripts[parentId] = transcript\n }\n if (transcript) {\n if (isExon(r.type)) {\n transcript.exons.push({start: r.start, end: r.end})\n } else {\n transcript.parts.push(r)\n }\n // Expand transcript bounds\n transcript.record.start = Math.min(transcript.record.start, r.start)\n transcript.record.end = Math.max(transcript.record.end, r.end)\n consumed.add(r)\n }\n }\n }\n }\n }\n\n // Finish transcripts: assemble parts, compute CDS/UTR\n for (const id of Object.keys(transcripts)) {\n const t = transcripts[id]\n finishTranscript(t)\n result.push(transcriptToFeature(t, nameField))\n }\n\n // Add unconsumed features as simple features\n for (const r of records) {\n if (!consumed.has(r)) {\n result.push(recordToSimpleFeature(r, nameField))\n }\n }\n\n // Number exons\n numberExons(result)\n\n return result\n}\n\n/** Assemble CDS/UTR parts into exon structure. Port of GFFTranscript.finish(). */\nfunction finishTranscript(t: TranscriptBuilder): void {\n // Sort parts\n t.parts.sort((a, b) => a.start - b.start)\n\n // Create implicit exons from CDS/UTR parts if no explicit exons\n if (t.parts.length > 0) {\n let lastStart = t.parts[0].start\n let lastEnd = t.parts[0].end\n\n for (let i = 1; i < t.parts.length; i++) {\n const part = t.parts[i]\n if (isIntron(part.type)) continue\n if (part.start <= lastEnd) {\n lastEnd = Math.max(lastEnd, part.end)\n } else {\n // Gap — check if an exon already covers this span\n if (!findExonContaining(t.exons, lastStart, lastEnd)) {\n t.exons.push({start: lastStart, end: lastEnd})\n }\n lastStart = part.start\n lastEnd = part.end\n }\n }\n if (!findExonContaining(t.exons, lastStart, lastEnd)) {\n t.exons.push({start: lastStart, end: lastEnd})\n t.record.start = Math.min(t.record.start, lastStart)\n t.record.end = Math.max(t.record.end, lastEnd)\n }\n }\n\n // Apply CDS parts\n for (const part of t.parts) {\n if (isCoding(part.type)) {\n addCDS(t, part)\n } else if (isUTR(part.type)) {\n addUTR(t, part)\n }\n }\n\n // Sort exons and mark fully UTR exons\n t.exons.sort((a, b) => a.start - b.start)\n if (t.cdStart !== undefined && t.cdEnd !== undefined) {\n for (const exon of t.exons) {\n if (exon.end < t.cdStart! || exon.start > t.cdEnd!) {\n exon.utr = true\n }\n }\n }\n}\n\nfunction findExonContaining(exons: Exon[], start: number, end: number): Exon | undefined {\n for (const exon of exons) {\n if (exon.end >= end && exon.start <= start) return exon\n }\n return undefined\n}\n\nfunction addCDS(t: TranscriptBuilder, cds: GFFRecord): void {\n const exon = findExonContaining(t.exons, cds.start, cds.end)\n if (exon) {\n exon.cdStart = exon.cdStart !== undefined ? Math.min(cds.start, exon.cdStart) : cds.start\n exon.cdEnd = exon.cdEnd !== undefined ? Math.max(cds.end, exon.cdEnd) : cds.end\n // Reading frame from phase\n if (cds.phase !== undefined) {\n const readingFrame = (3 - cds.phase) % 3\n if (exon.readingFrame === undefined) {\n exon.readingFrame = readingFrame\n }\n }\n }\n t.cdStart = t.cdStart !== undefined ? Math.min(cds.start, t.cdStart) : cds.start\n t.cdEnd = t.cdEnd !== undefined ? Math.max(cds.end, t.cdEnd) : cds.end\n}\n\nfunction addUTR(t: TranscriptBuilder, utr: GFFRecord): void {\n const exon = findExonContaining(t.exons, utr.start, utr.end)\n if (exon) {\n if (utr.start === exon.start && utr.end === exon.end) {\n exon.utr = true\n } else {\n if (utr.end < exon.end) {\n exon.cdStart = utr.end\n }\n if (exon.cdEnd === undefined || utr.start > exon.cdEnd) {\n exon.cdEnd = utr.start\n }\n }\n }\n}\n\nfunction getParents(r: GFFRecord): string[] | null {\n if (r.parent && r.parent.trim() !== '') {\n return r.parent.trim().split(',')\n }\n return null\n}\n\n/** Convert a TranscriptBuilder into a GFFFeature. */\nfunction transcriptToFeature(t: TranscriptBuilder, nameField?: string): GFFFeature {\n const r = t.record\n const name = resolveName(r, nameField)\n\n return {\n chr: r.chr,\n start: r.start,\n end: r.end,\n name,\n id: r.id,\n strand: r.strand === '+' || r.strand === '-' ? r.strand : undefined,\n type: r.type,\n source: r.source,\n score: r.score,\n cdStart: t.cdStart,\n cdEnd: t.cdEnd,\n exons: t.exons.length > 0 ? t.exons : undefined,\n attributes: r.attributes,\n color: r.color,\n }\n}\n\n/** Convert a GFFRecord into a simple GFFFeature (no transcript assembly). */\nfunction recordToSimpleFeature(r: GFFRecord, nameField?: string): GFFFeature {\n const name = resolveName(r, nameField)\n const mergedExons = (r as GFFRecord & {_mergedExons?: Array<{start: number; end: number}>})._mergedExons\n\n return {\n chr: r.chr,\n start: r.start,\n end: r.end,\n name,\n id: r.id,\n strand: r.strand === '+' || r.strand === '-' ? r.strand : undefined,\n type: r.type,\n source: r.source,\n score: r.score,\n exons: mergedExons,\n attributes: r.attributes,\n color: r.color,\n }\n}\n\nfunction resolveName(r: GFFRecord, nameField?: string): string | undefined {\n if (nameField) {\n return getAttributeValue(r, nameField)\n }\n for (const field of gffNameFields) {\n const v = getAttributeValue(r, field)\n if (v) return v\n }\n return undefined\n}\n\n/** Assign exon numbers based on strand direction. Port of GFFHelper.numberExons(). */\nfunction numberExons(features: GFFFeature[]): void {\n for (const f of features) {\n if (f.exons) {\n for (let i = 0; i < f.exons.length; i++) {\n f.exons[i].number = f.strand === '-' ? f.exons.length - i : i + 1\n }\n }\n }\n}\n","/**\n * BEDPE format decoder — pairwise genomic interactions (Hi-C, ChIA-PET, SVs).\n *\n * Standard BEDPE: 10+ columns (chr1/start1/end1/chr2/start2/end2/name/score/strand1/strand2).\n * Variants: 7-column (score in name column), hiccups (6 standard + extra columns).\n *\n * Port of js/feature/decode/bedpe.ts.\n * Layer 1 (Data + Layout): pure functions, no I/O, no DOM.\n */\n\nimport type {InteractionFeature} from '../types'\n\n/** Header metadata for BEDPE files. */\nexport interface BedpeHeader {\n /** Whether this is a hiccups-format file (auto-detected on first feature). */\n hiccups?: boolean\n /** Column names from header line. */\n columnNames?: string[]\n /** Column index for per-feature color. */\n colorColumn?: number\n /** Column index for per-feature line thickness. */\n thicknessColumn?: number\n}\n\n/**\n * Decode a single BEDPE line into an InteractionFeature.\n *\n * Handles standard 10-column BEDPE and hiccups variants.\n * Returns undefined for unparseable lines.\n */\nexport function decodeBedpe(tokens: string[], header?: BedpeHeader): InteractionFeature | undefined {\n if (tokens.length < 6) return undefined\n\n const chr1 = tokens[0]\n const start1 = parseInt(tokens[1])\n const end1 = parseInt(tokens[2])\n const chr2 = tokens[3]\n const start2 = parseInt(tokens[4])\n const end2 = parseInt(tokens[5])\n\n if (isNaN(start1) || isNaN(end1) || isNaN(start2) || isNaN(end2)) return undefined\n\n // Detect hiccups format on first feature (store on header for reuse)\n if (header && header.hiccups === undefined) {\n header.hiccups = header.columnNames ? isHiccups(header.columnNames) : false\n }\n const hiccups = header?.hiccups ?? false\n const stdColumns = hiccups ? 6 : 10\n\n const feature: InteractionFeature = {\n chr: chr1, start: 0, end: 0,\n chr1, start1, end1,\n chr2, start2, end2,\n dup: false,\n }\n\n if (!hiccups) {\n if (tokens.length > 6 && tokens[6] !== '.') {\n feature.name = tokens[6]\n }\n if (tokens.length > 7 && tokens[7] !== '.') {\n feature.score = Number(tokens[7])\n }\n if (tokens.length > 8 && tokens[8] !== '.') {\n feature.strand1 = tokens[8]\n }\n if (tokens.length > 9 && tokens[9] !== '.') {\n feature.strand2 = tokens[9]\n }\n }\n\n // Optional extra columns (color, thickness)\n if (header) {\n if (header.colorColumn !== undefined && header.colorColumn < tokens.length) {\n feature.color = tokens[header.colorColumn]\n }\n if (header.thicknessColumn !== undefined && header.thicknessColumn < tokens.length) {\n feature.thickness = Number(tokens[header.thicknessColumn])\n }\n if (tokens.length > stdColumns && header.columnNames && header.columnNames.length === tokens.length) {\n feature.extras = tokens.slice(stdColumns)\n }\n }\n\n // Set bounding extent for same-chromosome features\n if (chr1 === chr2) {\n feature.chr = chr1\n feature.start = Math.min(start1, start2)\n feature.end = Math.max(end1, end2)\n }\n\n return feature\n}\n\n/**\n * Post-process BEDPE features:\n * 1. Auto-detect score in name column (non-standard 7-col variant).\n * 2. Duplicate inter-chromosome features so each chromosome has a copy.\n */\nexport function fixBedPE(features: InteractionFeature[]): void {\n if (features.length === 0) return\n\n // Check if name column contains numeric scores\n const first = features[0]\n if (first.score === undefined && first.name !== undefined) {\n const allNumeric = features.every(f => f.name === undefined || f.name === '.' || isNumeric(f.name))\n if (allNumeric) {\n for (const f of features) {\n f.score = Number(f.name)\n f.name = undefined\n }\n }\n }\n\n // Duplicate inter-chr features for both chromosomes\n const interChr = features.filter(f => f.chr1 !== f.chr2)\n for (const f1 of interChr) {\n const f2: InteractionFeature = {...f1, dup: true}\n features.push(f2)\n\n f1.chr = f1.chr1\n f1.start = f1.start1\n f1.end = f1.end1\n\n f2.chr = f2.chr2\n f2.start = f2.start2\n f2.end = f2.end2\n }\n}\n\n/** Detect hiccups format from column headers. */\nexport function isHiccups(columns: string[]): boolean {\n return columns.includes('fdrDonut') || columns.includes('fdr_donut')\n}\n\nfunction isNumeric(s: string): boolean {\n return !isNaN(Number(s)) && s.trim() !== ''\n}\n","/**\n * Feature parser — lines → typed features.\n *\n * Dispatches to format-specific decoders based on format string. Handles\n * header parsing, comment skipping, delimiter selection, and GFF assembly.\n *\n * Port of js/feature/featureParser.ts.\n *\n * Layer 1 (Data + Layout): pure functions, no I/O, no DOM.\n */\n\nimport type {BedFeature, PeakFeature, BedGraphFeature, GFFRecord, GFFFeature, InteractionFeature, TextFileFormat} from '../types'\nimport {decodeBed, decodeBroadPeak, decodeNarrowPeak, decodeBedGraph, decodeGappedPeak, decodeRefflat} from '../decode/bed'\nimport type {BedHeader} from '../decode/bed'\nimport {decodeGFF3, decodeGTF, assembleGFFTranscripts} from '../decode/gff'\nimport {decodeGenePred, decodeGenePredExt} from '../decode/ucsc'\nimport {decodeBedpe, fixBedPE} from '../decode/bedpe'\nimport type {BedpeHeader} from '../decode/bedpe'\nimport {decodeInteract} from '../decode/interact'\n\n/** Decoder function type — takes tokens from a split line, returns a feature or undefined. */\nexport type DecoderFunction = (tokens: string[], header?: Record<string, unknown>) => unknown | undefined\n\n/** Header metadata extracted from track lines, column directives, and format directives. */\nexport interface FeatureHeader {\n format?: string\n nameField?: string\n gffTags?: boolean\n columnNames?: string[]\n colorColumn?: number\n thicknessColumn?: number\n /** Properties parsed from track lines. */\n properties?: Record<string, string>\n /** Wig step/span directive state (for fixedStep/variableStep). */\n wig?: WigDirective\n /** Column shift (1 for refgene/ensgene formats). */\n shift?: number\n}\n\ninterface WigDirective {\n format: string\n chrom: string\n start?: number\n step?: number\n span: number\n index?: number\n}\n\ninterface DecoderInfo {\n decode: (tokens: string[], header: FeatureHeader) => unknown | undefined\n delimiter: string | RegExp\n /** Whether parsed features need GFF transcript assembly. */\n requiresAssembly: boolean\n /** Optional post-processing of all decoded features (e.g., BEDPE fixup). */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n postProcess?: (features: any[]) => void\n}\n\n/**\n * Get the appropriate decoder function and delimiter for a format string.\n *\n * Port of js/feature/featureParser.ts::setDecoder().\n */\nexport function getDecoder(format: TextFileFormat, _header?: FeatureHeader): DecoderInfo {\n switch (format) {\n case 'broadpeak':\n case 'peaks':\n return {decode: (t, h) => decodeBroadPeak(t, toBedHeader(h)), delimiter: /\\s+/, requiresAssembly: false}\n case 'narrowpeak':\n return {decode: (t, h) => decodeNarrowPeak(t, toBedHeader(h)), delimiter: /\\s+/, requiresAssembly: false}\n case 'bedgraph':\n return {decode: (t) => decodeBedGraph(t), delimiter: /\\s+/, requiresAssembly: false}\n case 'gff3':\n case 'gff':\n return {decode: (t) => decodeGFF3(t), delimiter: '\\t', requiresAssembly: true}\n case 'gtf':\n return {decode: (t) => decodeGTF(t), delimiter: '\\t', requiresAssembly: true}\n case 'refflat':\n return {decode: (t) => decodeRefflat(t), delimiter: /\\s+/, requiresAssembly: false}\n case 'genepred':\n return {decode: (t) => decodeGenePred(t, 0), delimiter: /\\s+/, requiresAssembly: false}\n case 'genepredext':\n return {decode: (t) => decodeGenePredExt(t, 0), delimiter: /\\s+/, requiresAssembly: false}\n case 'ensgene':\n return {decode: (t) => decodeGenePred(t, 1), delimiter: /\\s+/, requiresAssembly: false}\n case 'refgene':\n return {decode: (t) => decodeGenePredExt(t, 1), delimiter: /\\s+/, requiresAssembly: false}\n case 'gappedpeak':\n return {decode: (t, h) => decodeGappedPeak(t, toBedHeader(h)), delimiter: /\\s+/, requiresAssembly: false}\n case 'bedpe':\n return {decode: (t, h) => decodeBedpe(t, toBedpeHeader(h)), delimiter: /\\s+/, requiresAssembly: false, postProcess: fixBedPE}\n case 'interact':\n case 'longrange':\n return {decode: (t) => decodeInteract(t), delimiter: /\\s+/, requiresAssembly: false}\n case 'bed':\n default:\n return {decode: (t, h) => decodeBed(t, toBedHeader(h)), delimiter: /\\s+/, requiresAssembly: false}\n }\n}\n\nfunction toBedHeader(h?: FeatureHeader): BedHeader | undefined {\n if (!h) return undefined\n return {\n nameField: h.nameField,\n gffTags: h.gffTags,\n colorColumn: h.colorColumn,\n thicknessColumn: h.thicknessColumn,\n }\n}\n\nfunction toBedpeHeader(h?: FeatureHeader): BedpeHeader | undefined {\n if (!h) return undefined\n return {\n columnNames: h.columnNames,\n colorColumn: h.colorColumn,\n thicknessColumn: h.thicknessColumn,\n }\n}\n\n/**\n * Parse header information from text lines.\n *\n * Extracts track line properties, column names, format directives\n * (#gffTags, ##gff-version 3, etc.).\n *\n * Port of js/feature/featureParser.ts::parseHeader().\n */\nexport function parseHeader(lines: string[], format: TextFileFormat): FeatureHeader {\n const header: FeatureHeader = {format}\n let columnNames: string[] | undefined\n\n for (const line of lines) {\n if (line.startsWith('track') || line.startsWith('#track')) {\n const props = parseTrackLine(line)\n Object.assign(header, {properties: props})\n if (props.type === 'interact') header.format = 'interact'\n if (props.type === 'gcnv') header.format = 'gcnv'\n } else if (line.startsWith('browser')) {\n // UCSC browser line, ignore\n } else if (line.startsWith('#columns')) {\n const cd = parseColumnsDirective(line)\n if (cd.colorColumn !== undefined) header.colorColumn = cd.colorColumn\n if (cd.thicknessColumn !== undefined) header.thicknessColumn = cd.thicknessColumn\n } else if (line.startsWith('##gff-version 3')) {\n header.format = 'gff3'\n } else if (line.startsWith('#gffTags')) {\n header.gffTags = true\n } else if (line.startsWith('fixedStep') || line.startsWith('variableStep')) {\n // Wig directive — we're in the data section\n break\n } else if (line.startsWith('#')) {\n const tokens = line.split('\\t')\n if (tokens.length > 1) columnNames = tokens\n } else {\n // First non-header line reached\n break\n }\n }\n\n if (columnNames) {\n header.columnNames = columnNames\n for (let n = 0; n < columnNames.length; n++) {\n if (columnNames[n] === 'color' || columnNames[n] === 'colour') {\n header.colorColumn = n\n } else if (columnNames[n] === 'thickness') {\n header.thicknessColumn = n\n }\n }\n }\n\n return header\n}\n\n/**\n * Parse text lines into features for a given format.\n *\n * Handles: comment/header skipping, delimiter-based tokenization,\n * WIG directive parsing, GFF transcript assembly.\n *\n * Port of js/feature/featureParser.ts::parseFeatures().\n */\nexport function parseFeatures(\n lines: string[],\n format: TextFileFormat,\n options?: {\n header?: FeatureHeader\n assembleGFF?: boolean\n },\n): Array<BedFeature | PeakFeature | BedGraphFeature | GFFFeature | GFFRecord | InteractionFeature> {\n\n const header: FeatureHeader = options?.header ?? parseHeader(lines, format)\n const resolvedFormat = (header.format ?? format) as TextFileFormat\n const info = getDecoder(resolvedFormat, header)\n const delimiter = info.delimiter\n\n const allFeatures: unknown[] = []\n const wigState: {wig?: WigDirective} = {}\n\n for (const line of lines) {\n if (!line || line.startsWith('track') || line.startsWith('#') || line.startsWith('browser')) {\n continue\n }\n\n // WIG directives\n if (resolvedFormat === 'wig') {\n if (line.startsWith('fixedStep')) {\n wigState.wig = parseFixedStep(line)\n continue\n }\n if (line.startsWith('variableStep')) {\n wigState.wig = parseVariableStep(line)\n continue\n }\n }\n\n const tokens = line.split(delimiter)\n if (tokens.length < 1) continue\n\n // For wig format, pass wig state in header\n const decodeHeader = resolvedFormat === 'wig'\n ? {...header, wig: wigState.wig}\n : header\n\n const feature = info.decode(tokens, decodeHeader)\n if (feature) {\n allFeatures.push(feature)\n }\n }\n\n // Post-process (e.g., BEDPE fixup: score detection, inter-chr duplication)\n if (info.postProcess) {\n info.postProcess(allFeatures)\n }\n\n // GFF/GTF transcript assembly\n if (info.requiresAssembly && (options?.assembleGFF !== false)) {\n const gffFormat = resolvedFormat === 'gff' ? 'gff' :\n resolvedFormat === 'gff3' ? 'gff3' : 'gtf'\n return assembleGFFTranscripts(\n allFeatures as GFFRecord[],\n gffFormat as 'gff3' | 'gtf' | 'gff',\n {nameField: header.nameField},\n )\n }\n\n return allFeatures as Array<BedFeature | PeakFeature | BedGraphFeature | GFFFeature | InteractionFeature>\n}\n\n// ─── Internal helpers ────────────────────────────────────────────────────────\n\n/**\n * Parse a UCSC track line into key=value pairs.\n * Port of js/feature/featureParser.ts::parseTrackLine().\n */\nfunction parseTrackLine(line: string): Record<string, string> {\n const properties: Record<string, string> = {}\n const tokens = line.split(/(?:\")([^\"]+)(?:\")|([^\\s\"]+)(?=\\s+|$)/g)\n\n let curr: string | undefined\n const tmp: string[] = []\n for (const tk of tokens) {\n if (!tk || tk.trim().length === 0) continue\n if (tk.endsWith('=')) {\n curr = tk\n } else if (curr) {\n tmp.push(curr + tk)\n curr = undefined\n } else {\n tmp.push(tk)\n }\n }\n\n for (const str of tmp) {\n if (!str) break\n const kv = str.split('=', 2)\n if (kv.length === 2) {\n properties[kv[0].trim()] = kv[1].trim()\n }\n }\n return properties\n}\n\n/** Parse #columns directive. Port of js/feature/featureParser.ts::parseColumnsDirective(). */\nfunction parseColumnsDirective(line: string): {colorColumn?: number; thicknessColumn?: number} {\n const result: {colorColumn?: number; thicknessColumn?: number} = {}\n const t1 = line.split(/\\s+/)\n if (t1.length === 2) {\n const t2 = t1[1].split(';')\n for (const kv of t2) {\n const t = kv.split('=')\n if (t[0] === 'color') result.colorColumn = parseInt(t[1]) - 1\n else if (t[0] === 'thickness') result.thicknessColumn = parseInt(t[1]) - 1\n }\n }\n return result\n}\n\nfunction parseFixedStep(line: string): WigDirective {\n const tokens = line.split(/\\s+/)\n const chrom = tokens[1].split('=')[1]\n const start = parseInt(tokens[2].split('=')[1], 10) - 1\n const step = parseInt(tokens[3].split('=')[1], 10)\n const span = tokens.length > 4 ? parseInt(tokens[4].split('=')[1], 10) : 1\n return {format: 'fixedStep', chrom, start, step, span, index: 0}\n}\n\nfunction parseVariableStep(line: string): WigDirective {\n const tokens = line.split(/\\s+/)\n const chrom = tokens[1].split('=')[1]\n const span = tokens.length > 2 ? parseInt(tokens[2].split('=')[1], 10) : 1\n return {format: 'variableStep', chrom, span}\n}\n","/**\n * UCSC interact format decoder — 18-column pairwise genomic interactions.\n *\n * See https://genome.ucsc.edu/goldenpath/help/interact.html\n *\n * Columns: chrom, chromStart, chromEnd, name, score, value, exp, color,\n * sourceChrom, sourceStart, sourceEnd, sourceName, sourceStrand,\n * targetChrom, targetStart, targetEnd, targetName, targetStrand\n *\n * Port of js/feature/decode/interact.ts.\n * Layer 1 (Data + Layout): pure functions, no I/O, no DOM.\n */\n\nimport type {InteractionFeature} from '../types'\n\n/**\n * Decode a single UCSC interact format line into an InteractionFeature.\n *\n * Returns undefined for lines with fewer than 6 columns.\n */\nexport function decodeInteract(tokens: string[]): InteractionFeature | undefined {\n if (tokens.length < 6) return undefined\n\n const chr = tokens[0]\n const start = parseInt(tokens[1])\n const end = parseInt(tokens[2])\n\n const chr1 = tokens[8]\n const start1 = parseInt(tokens[9])\n const end1 = parseInt(tokens[10])\n\n const chr2 = tokens[13]\n const start2 = parseInt(tokens[14])\n const end2 = parseInt(tokens[15])\n\n const colorToken = tokens[7]\n const color = colorToken === '.' ? undefined\n : colorToken === '0' ? 'rgb(0,0,0)'\n : colorToken\n\n return {\n chr, start, end,\n chr1, start1, end1,\n chr2, start2, end2,\n name: tokens[3],\n score: Number(tokens[4]),\n value: Number(tokens[5]),\n color,\n dup: false,\n }\n}\n","/**\n * Format detection from URL/filename and track type inference.\n *\n * Port of js/util/fileFormatUtils.ts (inferFileFormatFromName, knownFileExtensions)\n * and js/util/trackUtils.ts (inferTrackType).\n *\n * Layer 1 (Data + Layout): pure functions, no I/O, no DOM.\n */\n\n/** Comprehensive set of known file extensions. Port of js/util/fileFormatUtils.ts. */\nexport const knownFileExtensions: ReadonlySet<string> = new Set([\n 'narrowpeak', 'broadpeak', 'regionpeak', 'peaks',\n 'bedgraph', 'wig',\n 'gff3', 'gff', 'gtf',\n 'fusionjuncspan', 'refflat',\n 'seg', 'aed', 'bed', 'bedmethyl',\n 'vcf',\n 'bb', 'bigbed', 'biginteract', 'biggenepred', 'bignarrowpeak',\n 'bw', 'bigwig',\n 'bam', 'tdf',\n 'refgene', 'genepred', 'genepredext',\n 'bedpe', 'bp', 'snp', 'rmsk', 'cram',\n 'gwas', 'maf', 'mut', 'hiccups',\n 'fasta', 'fa', 'fna',\n 'pytor', 'hic', 'qtl',\n 'gtx',\n])\n\n/**\n * Infer file format from a URL or filename.\n *\n * Strips compression extensions (.gz, .bgz), auxiliary extensions (.txt, .tab, .tsv),\n * then checks the remaining extension against known formats.\n *\n * Port of js/util/fileFormatUtils.ts::inferFileFormatFromName().\n */\nexport function inferFormatFromPath(path: string): string | undefined {\n if (!path) return undefined\n\n let fn = path.toLowerCase()\n\n // Extract filename from URL (strip query params, path)\n const qIdx = fn.indexOf('?')\n if (qIdx > 0) fn = fn.substring(0, qIdx)\n const slashIdx = fn.lastIndexOf('/')\n if (slashIdx >= 0) fn = fn.substring(slashIdx + 1)\n\n // Special case: UCSC refgene files\n if (fn.endsWith('refgene.txt.gz') ||\n fn.endsWith('refgene.txt.bgz') ||\n fn.endsWith('refgene.txt') ||\n fn.endsWith('refgene.sorted.txt.gz') ||\n fn.endsWith('refgene.sorted.txt.bgz')) {\n return 'refgene'\n }\n\n // Strip compression extensions\n if (fn.endsWith('.gz')) fn = fn.substring(0, fn.length - 3)\n if (fn.endsWith('.bgz')) fn = fn.substring(0, fn.length - 4)\n\n // Strip auxiliary extensions\n if (fn.endsWith('.txt') || fn.endsWith('.tab') || fn.endsWith('.tsv')) {\n fn = fn.substring(0, fn.length - 4)\n }\n\n const idx = fn.lastIndexOf('.')\n const ext = idx < 0 ? fn : fn.substring(idx + 1)\n\n switch (ext) {\n case 'bw':\n return 'bigwig'\n case 'bb':\n return 'bigbed'\n case 'fasta':\n case 'fa':\n case 'fna':\n return 'fasta'\n case 'gtx':\n return 'gtx'\n default:\n if (knownFileExtensions.has(ext)) return ext\n return undefined\n }\n}\n\n/** Binary formats that cannot be read as text. */\nconst binaryFormats = new Set(['bigwig', 'bw', 'bigbed', 'bb', 'biginteract', 'biggenepred', 'bignarrowpeak', 'tdf', 'bam', 'cram', 'gtx'])\n\n/** Check if a format string represents a binary (non-text) format. */\nexport function isBinaryFormat(format: string): boolean {\n return binaryFormats.has(format.toLowerCase())\n}\n\n/** BigWig/BigBed format set — these use BWSource in igv.js. */\nexport const bbFormats = new Set(['bigwig', 'bw', 'bigbed', 'bb', 'biginteract', 'biggenepred', 'bignarrowpeak'])\n\n/**\n * Check if a URL is likely tabix-indexed.\n *\n * Only `.bgz` (bgzip-specific extension) is auto-detected as indexed.\n * Plain `.gz` files may be either bgzipped+tabix-indexed or plain gzipped,\n * so callers should explicitly set `indexed: true` or provide an `indexURL`\n * for those. This matches igv.js behavior where indexURL must be configured\n * for BED/GFF files to use tabix.\n */\nexport function isLikelyIndexed(url: string): boolean {\n const lower = url.toLowerCase()\n // Strip query params\n const qIdx = lower.indexOf('?')\n const path = qIdx > 0 ? lower.substring(0, qIdx) : lower\n return path.endsWith('.bgz')\n}\n\n/**\n * Infer the tabix index URL from a data file URL.\n * Appends '.tbi' to the URL (respecting query parameters).\n *\n * Port of js/util/fileFormatUtils.ts::inferIndexPath().\n */\nexport function inferIndexURL(url: string): string {\n if (url.includes('?')) {\n const idx = url.indexOf('?')\n return url.substring(0, idx) + '.tbi' + url.substring(idx)\n }\n return url + '.tbi'\n}\n\n/**\n * Infer the track type from a file format.\n *\n * Port of js/util/trackUtils.ts::inferTrackType().\n */\nexport function inferTrackType(format: string | undefined): string | undefined {\n if (!format) return undefined\n\n switch (format.toLowerCase()) {\n case 'bw':\n case 'bigwig':\n case 'wig':\n case 'bedgraph':\n case 'tdf':\n case 'gtx':\n return 'wig'\n case 'vcf':\n case 'vcftabix':\n return 'variant'\n case 'seg':\n return 'seg'\n case 'mut':\n case 'maf':\n return 'mut'\n case 'bam':\n case 'cram':\n return 'alignment'\n case 'hiccups':\n case 'bedpe':\n case 'bedpe-loop':\n case 'biginteract':\n case 'longrange':\n case 'hic':\n return 'interact'\n case 'bp':\n return 'arc'\n case 'gwas':\n return 'gwas'\n case 'bed':\n case 'bigbed':\n case 'bb':\n case 'biggenepred':\n case 'bignarrowpeak':\n return 'bedtype'\n case 'fasta':\n return 'sequence'\n case 'pytor':\n return 'cnvpytor'\n case 'qtl':\n return 'qtl'\n default:\n return 'annotation'\n }\n}\n","/**\n * DataSource for text-based genomic feature files (BED, GFF, peaks, etc.).\n *\n * Supports:\n * - Indexed files (via TabixReader) — query by region, on-demand parsing\n * - Non-indexed files — fetch all, cache in FeatureCache, query locally\n * - Automatic format detection from URL\n * - Chromosome alias resolution\n *\n * Port of js/feature/textFeatureSource.ts and js/feature/featureFileReader.ts.\n * Layer 1 (Data + Layout): no DOM.\n */\n\nimport type {DataSource, Locus, TextFileFormat} from '../types'\nimport type {CacheableFeature} from '../featureCache'\nimport type {CumulativeOffsets} from '../genome/chromSizes'\nimport type {WorkerProvider} from '../workerProvider'\nimport {FeatureCache} from '../featureCache'\nimport {TabixReader} from '../tabix'\nimport {parseFeatures, parseHeader} from '../formats/featureParser'\nimport type {FeatureHeader} from '../formats/featureParser'\nimport {inferFormatFromPath, isLikelyIndexed, inferIndexURL} from '../formats/formatDetection'\nimport {isWholeGenomeView} from '../locusUtils'\nimport {mainChromosomeNames} from '../genome/chromSizes'\n\nexport interface TextFeatureSourceConfig {\n /** URL to the data file. */\n url: string\n /** Explicit format override. When absent, inferred from URL. */\n format?: TextFileFormat\n /** Index URL override. Defaults to url + '.tbi'. */\n indexURL?: string\n /** Whether the file is indexed (tabix). Auto-detected if absent. */\n indexed?: boolean\n /** For GFF: whether to assemble transcript models. Default: true. */\n assembleGFF?: boolean\n /** Worker provider for offloading CPU-intensive tasks. */\n workerProvider?: WorkerProvider\n}\n\n/**\n * DataSource for text-based genomic feature files.\n *\n * For indexed files: uses TabixReader to query by region, parses lines on each fetch.\n * For non-indexed files: loads entire file on first fetch, caches in FeatureCache.\n */\nexport class TextFeatureSource<F extends CacheableFeature = CacheableFeature> implements DataSource<F> {\n private readonly url: string\n private readonly format: TextFileFormat\n private readonly assembleGFF: boolean\n private readonly _indexed: boolean\n private readonly workerProvider?: WorkerProvider\n private _resolveChromName?: (chr: string) => string\n private _cumulativeOffsets?: CumulativeOffsets\n\n // Indexed path\n private tabixReader?: TabixReader\n\n // Non-indexed path\n private featureCache?: FeatureCache<F>\n private allFeaturesLoaded = false\n\n // Header (parsed lazily on first load)\n private header?: FeatureHeader\n\n constructor(config: TextFeatureSourceConfig) {\n this.url = config.url\n this.workerProvider = config.workerProvider\n\n // Detect format\n const detected = config.format ?? inferFormatFromPath(config.url) as TextFileFormat | undefined\n this.format = detected ?? 'bed'\n\n this.assembleGFF = config.assembleGFF !== false\n\n // Determine if indexed\n if (config.indexed !== undefined) {\n this._indexed = config.indexed\n } else if (config.indexURL) {\n this._indexed = true\n } else {\n this._indexed = isLikelyIndexed(config.url)\n }\n\n // Set up TabixReader for indexed files\n if (this._indexed) {\n const indexUrl = config.indexURL ?? inferIndexURL(config.url)\n this.tabixReader = new TabixReader(config.url, {indexUrl, workerProvider: this.workerProvider})\n }\n }\n\n /** Whether this source is indexed (queryable by region). */\n get indexed(): boolean { return this._indexed }\n\n /** Set a chromosome name resolver for alias resolution. */\n setChromNameResolver(resolver: (chr: string) => string): void {\n this._resolveChromName = resolver\n }\n\n /** Set cumulative offsets for whole genome view coordinate transformation. */\n setCumulativeOffsets(offsets: CumulativeOffsets): void {\n this._cumulativeOffsets = offsets\n }\n\n /** Get sequence names from the file/index (for chromosome alias setup). */\n async getSequenceNames(signal?: AbortSignal): Promise<string[]> {\n if (this.tabixReader) {\n return this.tabixReader.getSequenceNames(signal)\n }\n // For non-indexed files, load all features first, extract from cache\n if (this.featureCache) {\n return Object.keys(this.featureCache.getAllFeatures())\n }\n return []\n }\n\n async fetch(locus: Locus, bpPerPixel: number, signal: AbortSignal): Promise<F[]> {\n if (isWholeGenomeView(locus) && this._cumulativeOffsets) {\n return this.fetchWG(signal)\n }\n\n const chr = this._resolveChromName\n ? this._resolveChromName(locus.chr)\n : locus.chr\n\n if (this._indexed && this.tabixReader) {\n return this.fetchIndexed(chr, locus.start, locus.end, signal)\n }\n return this.fetchNonIndexed(chr, locus.start, locus.end, signal)\n }\n\n private async fetchIndexed(chr: string, start: number, end: number, signal?: AbortSignal): Promise<F[]> {\n const reader = this.tabixReader!\n\n // Load header lazily for format metadata\n if (!this.header) {\n const headerLines = await reader.readHeaderLines(signal)\n this.header = parseHeader(headerLines, this.format)\n }\n\n const lines = await reader.readLines(chr, start, end, signal)\n\n const features = parseFeatures(lines, this.format, {\n header: this.header,\n assembleGFF: this.assembleGFF,\n }) as F[]\n\n // Sort by start position\n features.sort((a, b) => a.start - b.start)\n\n return features\n }\n\n private async fetchNonIndexed(chr: string, start: number, end: number, signal?: AbortSignal): Promise<F[]> {\n if (!this.allFeaturesLoaded) {\n await this.loadAllFeatures(signal)\n }\n return this.featureCache?.queryFeatures(chr, start, end) ?? []\n }\n\n private async loadAllFeatures(signal?: AbortSignal): Promise<void> {\n // Fetch entire file\n const response = await globalThis.fetch(this.url, {signal})\n if (!response.ok) {\n throw new Error(`Failed to fetch ${this.url}: ${response.status} ${response.statusText}`)\n }\n\n // Handle gzipped content: decompress if Content-Encoding wasn't already handled\n // by the browser (transparent decompression) or if the URL ends in .gz/.bgz\n let text: string\n const urlLower = this.url.toLowerCase()\n const isGzUrl = urlLower.endsWith('.gz') || urlLower.endsWith('.bgz') ||\n urlLower.includes('.gz?') || urlLower.includes('.bgz?')\n const contentEncoding = response.headers.get('Content-Encoding')\n const transparentlyDecompressed = contentEncoding === 'gzip' || contentEncoding === 'deflate'\n\n if (isGzUrl && !transparentlyDecompressed) {\n // Server sent raw gzip bytes — decompress manually\n const buffer = await response.arrayBuffer()\n const ds = new DecompressionStream('gzip')\n const decompressed = new Response(\n new Response(buffer).body!.pipeThrough(ds),\n )\n text = await decompressed.text()\n } else {\n text = await response.text()\n }\n\n const lines = text.split(/\\r?\\n/)\n\n // Parse header\n this.header = parseHeader(lines, this.format)\n\n // Parse features (offload to worker for large files)\n const features = (this.workerProvider\n ? await this.workerProvider.execute({\n task: 'parseFeatures',\n lines,\n format: this.format,\n header: this.header,\n assembleGFF: this.assembleGFF,\n })\n : parseFeatures(lines, this.format, {\n header: this.header,\n assembleGFF: this.assembleGFF,\n })\n ) as F[]\n\n // Sort by chr then start\n features.sort((a, b) => {\n if (a.chr === b.chr) return a.start - b.start\n return a.chr.localeCompare(b.chr)\n })\n\n // Build cache\n this.featureCache = new FeatureCache(features)\n this.allFeaturesLoaded = true\n }\n\n private async fetchWG(signal: AbortSignal): Promise<F[]> {\n const offsets = this._cumulativeOffsets!\n\n if (this._indexed) {\n // For indexed files, fetch all main chromosomes\n const chrNames = mainChromosomeNames(\n Object.fromEntries(\n offsets.chromosomeNames.map(name => [name, offsets.offsets[name] ?? 0])\n ) as Record<string, number>,\n )\n\n const allFeatures: F[] = []\n for (const chrName of chrNames) {\n try {\n const features = await this.fetchIndexed(\n chrName, 0, Number.MAX_SAFE_INTEGER, signal,\n )\n const offset = offsets.offsets[chrName]\n if (offset === undefined) continue\n for (const f of features) {\n allFeatures.push({\n ...f,\n chr: 'all',\n start: offset + f.start,\n end: offset + f.end,\n })\n }\n } catch {\n // Skip chromosomes that fail\n }\n }\n allFeatures.sort((a, b) => a.start - b.start)\n return allFeatures\n } else {\n // Non-indexed: load all, transform coordinates\n if (!this.allFeaturesLoaded) {\n await this.loadAllFeatures(signal)\n }\n const allByChrom = this.featureCache?.getAllFeatures() ?? {}\n const wgFeatures: F[] = []\n for (const [chr, features] of Object.entries(allByChrom)) {\n const offset = offsets.offsets[chr]\n if (offset === undefined) continue\n for (const f of features) {\n wgFeatures.push({\n ...f,\n chr: 'all',\n start: offset + f.start,\n end: offset + f.end,\n })\n }\n }\n wgFeatures.sort((a, b) => a.start - b.start)\n return wgFeatures\n }\n }\n}\n","import type {DataSource, Locus, SequenceProvider} from '../types'\nimport type {SequenceFeature} from '../tracks/sequence/sequenceRenderer'\n\n/**\n * bpPerPixel threshold above which sequence data is not loaded.\n * Matches igv.js bppSequenceThreshold = 10.\n */\nconst BPP_SEQUENCE_THRESHOLD = 10\n\n/**\n * DataSource for sequence tracks — wraps a SequenceProvider to conform\n * to the standard DataSource<SequenceFeature> interface.\n *\n * This mirrors igv.js SequenceTrack.getFeatures() which calls\n * browser.genome.getSequence() and returns {bpStart, sequence}.\n * Returns a single-element array when zoomed in, empty array when zoomed out.\n */\nexport class SequenceDataSource implements DataSource<SequenceFeature> {\n constructor(private sequenceProvider: SequenceProvider) {}\n\n async fetch(locus: Locus, bpPerPixel: number, signal: AbortSignal): Promise<SequenceFeature[]> {\n if (bpPerPixel > BPP_SEQUENCE_THRESHOLD) {\n return []\n }\n const start = Math.floor(locus.start)\n const end = Math.floor(locus.end)\n const sequence = await this.sequenceProvider({chr: locus.chr, start, end}, signal)\n if (signal.aborted) return []\n return [{bpStart: start, sequence}]\n }\n}\n","/**\n * Stateless renderer for interaction (arc/BEDPE) tracks.\n *\n * Draws pairwise genomic contacts as arcs connecting two regions.\n * Two display modes:\n * - \"nested\": arc height proportional to genomic distance (ctx.arc)\n * - \"proportional\": arc height proportional to score/value (ctx.ellipse)\n *\n * Inter-chromosome interactions are drawn as colored rectangles.\n *\n * Port of js/feature/interactionTrack.ts draw methods.\n * Layer 2 (Track Canvas): uses CanvasRenderingContext2D, no DOM.\n */\n\nimport type {InteractionFeature, InteractionRenderConfig, RenderContext} from '../../types'\n\n/** Draw state stored on features during rendering for hit-testing. */\nexport type InteractionDrawState =\n | NestedDrawState\n | ProportionalDrawState\n | RectDrawState\n\ninterface NestedDrawState {\n type: 'nested'\n xc: number\n yc: number\n r: number\n}\n\ninterface ProportionalDrawState {\n type: 'proportional'\n xc: number\n yc: number\n radiusX: number\n radiusY: number\n}\n\ninterface RectDrawState {\n type: 'rect'\n x: number\n y: number\n w: number\n h: number\n}\n\n/** Feature with transient draw state attached during rendering. */\nexport interface DrawnInteractionFeature extends InteractionFeature {\n drawState?: InteractionDrawState\n}\n\n/**\n * Render interaction features onto a canvas context.\n *\n * Stateless: all state is passed in, no side effects beyond canvas drawing\n * and attaching drawState to features for hit-testing.\n */\nexport function renderInteractionTrack(\n ctx: CanvasRenderingContext2D,\n features: DrawnInteractionFeature[],\n config: InteractionRenderConfig,\n rc: RenderContext,\n): void {\n // Clear background\n ctx.fillStyle = config.background\n ctx.fillRect(0, 0, rc.pixelWidth, config.height)\n\n if (!features || features.length === 0) return\n\n if (config.displayMode === 'proportional') {\n drawProportional(ctx, features, config, rc)\n } else {\n drawNested(ctx, features, config, rc)\n }\n}\n\n// ─── Nested arcs ─────────────────────────────────────────────────────────────\n\nfunction drawNested(\n ctx: CanvasRenderingContext2D,\n features: DrawnInteractionFeature[],\n config: InteractionRenderConfig,\n rc: RenderContext,\n): void {\n const {bpStart, bpPerPixel, pixelWidth, viewportWidth} = rc\n const direction = config.arcOrientation === 'UP'\n const y = direction ? config.height : 0\n\n // Autoscale theta to fit largest visible arc within track height\n const {sinTheta, cosTheta, theta} = autoscaleNested(features, config, rc)\n\n ctx.font = config.font\n ctx.textAlign = 'center'\n\n for (const feature of features) {\n feature.drawState = undefined\n\n let color = feature.color ?? config.color\n ctx.lineWidth = feature.thickness ?? config.thickness\n\n if (feature.chr1 === feature.chr2 || feature.chr === 'all') {\n const m1 = (feature.start1 + feature.end1) / 2\n const m2 = (feature.start2 + feature.end2) / 2\n const mLeft = Math.min(m1, m2)\n const mRight = Math.max(m1, m2)\n\n let pixelStart = Math.round((mLeft - bpStart) / bpPerPixel)\n let pixelEnd = Math.round((mRight - bpStart) / bpPerPixel)\n if (pixelEnd < 0 || pixelStart > pixelWidth) continue\n\n let w = pixelEnd - pixelStart\n if (w < 3) { w = 3; pixelStart-- }\n\n const a = w / 2\n const r = a / sinTheta\n const b = cosTheta * r\n const xc = pixelStart + a\n\n let yc: number, startAngle: number, endAngle: number\n if (direction) {\n yc = config.height + b\n startAngle = Math.PI + Math.PI / 2 - theta\n endAngle = Math.PI + Math.PI / 2 + theta\n } else {\n yc = -b\n startAngle = Math.PI / 2 - theta\n endAngle = Math.PI / 2 + theta\n }\n\n // Draw endpoint blocks\n if (config.showBlocks && feature.chr !== 'all') {\n ctx.fillStyle = color\n const s1 = (feature.start1 - bpStart) / bpPerPixel\n const e1 = (feature.end1 - bpStart) / bpPerPixel\n const s2 = (feature.start2 - bpStart) / bpPerPixel\n const e2 = (feature.end2 - bpStart) / bpPerPixel\n const hb = direction ? -config.blockHeight : config.blockHeight\n ctx.fillRect(s1, y, e1 - s1, hb)\n ctx.fillRect(s2, y, e2 - s2, hb)\n }\n\n // Alpha shade arcs extending beyond viewport (unless score-based shading)\n if (!config.useScore && w > viewportWidth) {\n color = addAlpha(color, config.alpha)\n }\n\n ctx.strokeStyle = color\n ctx.fillStyle = color\n ctx.beginPath()\n ctx.arc(xc, yc, r, startAngle, endAngle, false)\n ctx.stroke()\n\n feature.drawState = {type: 'nested', xc, yc, r}\n } else {\n drawInterChrRect(ctx, feature, config, rc, color, direction)\n }\n }\n}\n\n// ─── Proportional arcs ───────────────────────────────────────────────────────\n\nfunction drawProportional(\n ctx: CanvasRenderingContext2D,\n features: DrawnInteractionFeature[],\n config: InteractionRenderConfig,\n rc: RenderContext,\n): void {\n const {bpStart, bpPerPixel, pixelWidth} = rc\n const direction = config.arcOrientation === 'UP'\n const y = direction ? config.height : 0\n\n // Compute data range for scaling\n const dataRange = computeDataRange(features)\n const yScale = config.logScale\n ? (config.height - 1) / (Math.log10(dataRange.max + 1))\n : (config.height - 1) / (dataRange.max || 1)\n\n for (const feature of features) {\n feature.drawState = undefined\n\n const value = feature.value ?? feature.score ?? 0\n if (value === undefined || isNaN(value)) continue\n\n const radiusY = Math.round((config.logScale ? Math.log10(value + 1) : value) * yScale)\n\n if (feature.chr1 === feature.chr2 || feature.chr === 'all') {\n const m1 = (feature.start1 + feature.end1) / 2\n const m2 = (feature.start2 + feature.end2) / 2\n const mLeft = Math.min(m1, m2)\n const mRight = Math.max(m1, m2)\n\n let pixelStart = Math.round((mLeft - bpStart) / bpPerPixel)\n let pixelEnd = Math.round((mRight - bpStart) / bpPerPixel)\n let w = pixelEnd - pixelStart\n if (w < 3) { w = 3; pixelStart-- }\n\n const radiusX = w / 2\n const xc = pixelStart + w / 2\n const counterClockwise = direction\n\n const color = feature.color ?? config.color\n ctx.strokeStyle = color\n ctx.lineWidth = feature.thickness ?? config.thickness\n\n ctx.beginPath()\n ctx.ellipse(xc, y, radiusX, radiusY, 0, 0, Math.PI, counterClockwise)\n ctx.stroke()\n\n // Alpha fill\n if (config.alpha > 0) {\n ctx.fillStyle = addAlpha(color, config.alpha)\n ctx.fill()\n }\n\n // Endpoint blocks\n if (config.showBlocks && feature.chr !== 'all') {\n ctx.fillStyle = color\n const s1 = (feature.start1 - bpStart) / bpPerPixel\n const e1 = (feature.end1 - bpStart) / bpPerPixel\n const s2 = (feature.start2 - bpStart) / bpPerPixel\n const e2 = (feature.end2 - bpStart) / bpPerPixel\n const hb = direction ? -config.blockHeight : config.blockHeight\n ctx.fillRect(s1, y, e1 - s1, hb)\n ctx.fillRect(s2, y, e2 - s2, hb)\n }\n\n feature.drawState = {type: 'proportional', xc, yc: y, radiusX, radiusY}\n } else {\n // Inter-chromosome\n if (pixelWidth <= 0) continue\n const pixelStart2 = Math.round((feature.start - bpStart) / bpPerPixel)\n const pixelEnd2 = Math.round((feature.end - bpStart) / bpPerPixel)\n if (pixelEnd2 < 0 || pixelStart2 > pixelWidth) continue\n\n const h = Math.min(radiusY, config.height - 13)\n const color = feature.color ?? config.color\n drawInterChrRect(ctx, feature, config, rc, color, direction, h)\n }\n }\n}\n\n// ─── Inter-chromosome rectangles ─────────────────────────────────────────────\n\nfunction drawInterChrRect(\n ctx: CanvasRenderingContext2D,\n feature: DrawnInteractionFeature,\n config: InteractionRenderConfig,\n rc: RenderContext,\n color: string,\n direction: boolean,\n maxHeight?: number,\n): void {\n const {bpStart, bpPerPixel, pixelWidth} = rc\n\n let pixelStart = Math.round((feature.start - bpStart) / bpPerPixel)\n let pixelEnd = Math.round((feature.end - bpStart) / bpPerPixel)\n if (pixelEnd < 0 || pixelStart > pixelWidth) return\n\n let w = pixelEnd - pixelStart\n if (w < 3) { w = 3; pixelStart-- }\n\n const otherChr = feature.chr === feature.chr1 ? feature.chr2 : feature.chr1\n const h = maxHeight ?? config.height / 2\n\n // Use a semi-transparent color for inter-chr rects\n ctx.fillStyle = addAlpha(color, 0.5)\n ctx.font = config.font\n ctx.textAlign = 'center'\n\n if (direction) {\n const rectY = config.height - h\n ctx.fillRect(pixelStart, rectY, w, h)\n ctx.fillStyle = color\n ctx.fillText(otherChr, pixelStart + w / 2, rectY - 5)\n feature.drawState = {type: 'rect', x: pixelStart, y: rectY, w, h}\n } else {\n ctx.fillRect(pixelStart, 0, w, h)\n ctx.fillStyle = color\n ctx.fillText(otherChr, pixelStart + w / 2, h + 13)\n feature.drawState = {type: 'rect', x: pixelStart, y: 0, w, h}\n }\n}\n\n// ─── Autoscale helpers ───────────────────────────────────────────────────────\n\nfunction autoscaleNested(\n features: InteractionFeature[],\n config: InteractionRenderConfig,\n rc: RenderContext,\n): {sinTheta: number; cosTheta: number; theta: number} {\n const {bpStart, bpPerPixel, pixelWidth, viewportWidth} = rc\n\n let max = 0\n for (const feature of features) {\n const pixelStart = (feature.start - bpStart) / bpPerPixel\n const pixelEnd = (feature.end - bpStart) / bpPerPixel\n if (pixelStart >= 0 && pixelEnd <= pixelWidth) {\n max = Math.max(max, pixelEnd - pixelStart)\n }\n }\n\n const a = Math.min(viewportWidth, max) / 2\n let theta = Math.PI / 4 // default\n if (max > 0) {\n const coa = (config.height - 10) / a\n theta = estimateTheta(coa)\n }\n\n return {\n sinTheta: Math.sin(theta),\n cosTheta: Math.cos(theta),\n theta,\n }\n}\n\n/**\n * Estimate theta given the ratio of track height to half the feature width.\n * Port of igv.js estimateTheta().\n */\nfunction estimateTheta(x: number): number {\n const coa = [0.01570925532366355, 0.15838444032453644, 0.3249196962329063, 0.5095254494944288, 0.7265425280053609, 0.9999999999999999]\n const theta = [0.031415926535897934, 0.3141592653589793, 0.6283185307179586, 0.9424777960769379, 1.2566370614359172, 1.5707963267948966]\n\n let idx = 0\n for (; idx < coa.length; idx++) {\n if (coa[idx] > x) break\n }\n\n const left = idx === 0 ? 0 : coa[idx - 1]\n const right = idx < coa.length ? coa[idx] : 1\n const r = (x - left) / (right - left)\n\n const thetaLeft = idx === 0 ? 0 : theta[idx - 1]\n const thetaRight = idx < theta.length ? theta[idx] : Math.PI / 2\n\n return Math.min(Math.PI / 2, thetaLeft + r * (thetaRight - thetaLeft))\n}\n\nfunction computeDataRange(features: InteractionFeature[]): {min: number; max: number} {\n let max = 0\n for (const f of features) {\n const v = f.value ?? f.score ?? 0\n if (!isNaN(v)) max = Math.max(max, v)\n }\n return {min: 0, max}\n}\n\n// ─── Color utilities ─────────────────────────────────────────────────────────\n\nconst alphaCache = new Map<string, string>()\n\nfunction addAlpha(color: string, alpha: number): string {\n const key = `${color}_${alpha}`\n let cached = alphaCache.get(key)\n if (cached) return cached\n\n // Parse rgb(r,g,b) or hex\n const rgb = parseRGB(color)\n if (rgb) {\n cached = `rgba(${rgb.r},${rgb.g},${rgb.b},${alpha})`\n } else {\n cached = color // fallback\n }\n alphaCache.set(key, cached)\n return cached\n}\n\nfunction parseRGB(color: string): {r: number; g: number; b: number} | undefined {\n // rgb(r,g,b) or rgba(r,g,b,a)\n const rgbMatch = color.match(/^rgba?\\((\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)/)\n if (rgbMatch) {\n return {r: parseInt(rgbMatch[1]), g: parseInt(rgbMatch[2]), b: parseInt(rgbMatch[3])}\n }\n // #RRGGBB or #RGB\n const hexMatch = color.match(/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i)\n if (hexMatch) {\n return {r: parseInt(hexMatch[1], 16), g: parseInt(hexMatch[2], 16), b: parseInt(hexMatch[3], 16)}\n }\n return undefined\n}\n\n/**\n * Format a genomic position for popup display.\n */\nexport function positionString(chr: string, start: number, end: number, strand?: string): string {\n const startStr = (start + 1).toLocaleString()\n const endStr = end.toLocaleString()\n return strand && strand !== '.'\n ? `${chr}:${startStr}-${endStr} (${strand})`\n : `${chr}:${startStr}-${endStr}`\n}\n","/**\n * Canvas manager for rendering interaction (arc/BEDPE) tracks.\n *\n * Extends BaseTrackCanvas — canvas lifecycle is handled by the base class.\n * This class implements interaction-specific logic: arc rendering, hit-testing,\n * and popup data.\n *\n * Usage:\n * const canvas = document.createElement('canvas')\n * const track = new InteractionTrackCanvas(canvas, { locus, features: [] })\n * track.attachTo(containerDiv)\n */\n\nimport type {\n InteractionFeature, InteractionRenderConfig,\n Locus, RenderContext, InteractionTrackSessionConfig,\n InteractionSessionOverrides, HitTestResult, PopupDataItem,\n AxisInfo, ContextMenuItem, NumericState,\n} from '../../types'\nimport {defaultInteractionRenderConfig} from '../../types'\nimport type {CanvasProvider} from '../../canvasProvider'\nimport type {RenderTheme} from '../../themes/renderTheme'\nimport {resolveTheme, resolveInteractionConfig} from '../../themes/renderTheme'\nimport {BaseTrackCanvas} from '../baseTrackCanvas'\nimport {renderInteractionTrack, positionString} from './interactionRenderer'\nimport type {DrawnInteractionFeature, InteractionDrawState} from './interactionRenderer'\n\nexport interface InteractionTrackCanvasOptions {\n locus: Locus\n features: InteractionFeature[]\n /** Per-track config overrides. Applied after theme-derived defaults. */\n config?: Partial<InteractionRenderConfig>\n /** Unified render theme. Palette drives default colors/fonts. */\n theme?: Partial<RenderTheme>\n /** Background color. Overrides config.background if set. */\n background?: string\n /** Canvas provider for environment abstraction. Default: DOMCanvasProvider. */\n canvasProvider?: CanvasProvider\n /** Track name for axis label. */\n name?: string\n}\n\nexport class InteractionTrackCanvas extends BaseTrackCanvas<InteractionRenderConfig> {\n private features: DrawnInteractionFeature[]\n private _name: string | undefined\n\n readonly type = 'interact'\n\n constructor(canvas: HTMLCanvasElement, options: InteractionTrackCanvasOptions) {\n const theme = resolveTheme(options.theme)\n const config = resolveInteractionConfig(theme, options.config)\n if (options.background !== undefined) {\n config.background = options.background\n }\n super(canvas, options.locus, config, options.canvasProvider)\n this.features = options.features\n this._name = options.name\n }\n\n /** Update features and re-render. */\n setFeatures(features: InteractionFeature[]): void {\n this.features = features\n this.render()\n }\n\n protected computeHeight(_width: number): number {\n return this.config.height\n }\n\n protected getBackground(): string {\n return this.config.background\n }\n\n protected doRender(ctx: CanvasRenderingContext2D, _width: number, _height: number, rc: RenderContext): void {\n renderInteractionTrack(ctx, this.features, this._config, rc)\n }\n\n /** Hit-test: find features at canvas-relative pixel coordinates. */\n override hitTest(x: number, y: number): HitTestResult<InteractionFeature>[] {\n const candidates: Array<{score: number; feature: DrawnInteractionFeature}> = []\n const isProportional = this._config.displayMode === 'proportional'\n\n for (const feature of this.features) {\n if (!feature.drawState) continue\n\n const ds = feature.drawState\n\n if (ds.type === 'nested') {\n const dx = x - ds.xc\n const dy = y - ds.yc\n const dist = Math.abs(Math.sqrt(dx * dx + dy * dy) - ds.r)\n if (dist < 5) {\n candidates.push({score: dist, feature})\n }\n } else if (ds.type === 'proportional') {\n const dx = x - ds.xc\n const dy = y - ds.yc\n const ellipseScore = (dx / ds.radiusX) * (dx / ds.radiusX)\n + (dy / ds.radiusY) * (dy / ds.radiusY)\n if (ellipseScore <= 1) {\n candidates.push({score: 1 / ellipseScore, feature})\n }\n } else if (ds.type === 'rect') {\n const tolerance = 5\n if (x >= ds.x - tolerance && x <= ds.x + ds.w + tolerance &&\n y >= ds.y && y <= ds.y + ds.h) {\n candidates.push({score: -Math.abs(x - (ds.x + ds.w / 2)), feature})\n break\n }\n }\n }\n\n if (candidates.length > 1) {\n candidates.sort((a, b) => a.score - b.score)\n }\n\n return candidates.map(c => ({\n feature: c.feature,\n popupData: this.buildPopupData(c.feature),\n }))\n }\n\n private buildPopupData(feature: InteractionFeature): PopupDataItem[] {\n const data: PopupDataItem[] = []\n data.push({name: 'Region 1', value: positionString(feature.chr1, feature.start1, feature.end1, feature.strand1)})\n data.push({name: 'Region 2', value: positionString(feature.chr2, feature.start2, feature.end2, feature.strand2)})\n if (feature.name) data.push({name: 'Name', value: feature.name})\n if (feature.value !== undefined) data.push({name: 'Value', value: feature.value})\n if (feature.score !== undefined) data.push({name: 'Score', value: feature.score})\n if (feature.type !== undefined) data.push({name: 'Type', value: feature.type})\n return data\n }\n\n setTheme(theme: RenderTheme): void {\n this._config = resolveInteractionConfig(theme)\n this.render()\n }\n\n /** Serialize config for session save/restore, diffed against theme defaults. */\n serializeConfig(theme: RenderTheme): InteractionTrackSessionConfig {\n const resolved = resolveInteractionConfig(resolveTheme(theme))\n const overrides: InteractionSessionOverrides = {}\n\n const keys = Object.keys(this._config) as (keyof InteractionRenderConfig)[]\n for (const key of keys) {\n const cur = this._config[key]\n const def = resolved[key]\n if (cur !== def) {\n ;(overrides as Record<string, unknown>)[key] = cur\n }\n }\n\n return {\n type: 'interact',\n name: this._name,\n config: Object.keys(overrides).length > 0 ? overrides : undefined,\n }\n }\n\n /** Return axis info for proportional display mode. */\n getAxisInfo(): AxisInfo | undefined {\n if (this._config.displayMode !== 'proportional') return undefined\n const dataRange = computeDataRange(this.features)\n return {\n label: this._name,\n dataRange,\n flipAxis: this._config.arcOrientation === 'DOWN',\n logScale: this._config.logScale,\n }\n }\n\n /** Context menu items for arc display settings. */\n override getContextMenuItems(_x: number, _y: number): ContextMenuItem[] {\n const items: ContextMenuItem[] = []\n\n // Display mode toggle\n items.push({\n label: 'Nested Arcs',\n type: 'checkbox',\n checked: this._config.displayMode === 'nested',\n action: () => this.setConfig({displayMode: 'nested'}),\n })\n items.push({\n label: 'Proportional Arcs',\n type: 'checkbox',\n checked: this._config.displayMode === 'proportional',\n action: () => this.setConfig({displayMode: 'proportional'}),\n })\n\n items.push({label: '', type: 'separator'})\n\n // Arc direction toggle\n items.push({\n label: 'Toggle Arc Direction',\n action: () => this.setConfig({\n arcOrientation: this._config.arcOrientation === 'UP' ? 'DOWN' : 'UP',\n }),\n })\n\n // Block visibility toggle\n items.push({\n label: this._config.showBlocks ? 'Hide Blocks' : 'Show Blocks',\n action: () => this.setConfig({showBlocks: !this._config.showBlocks}),\n })\n\n return items\n }\n\n /** Return numeric state for proportional mode (data range, log scale). */\n getNumericState(): NumericState | undefined {\n if (this._config.displayMode !== 'proportional') return undefined\n\n const dataRange = computeDataRange(this.features)\n return {\n autoscale: true,\n logScale: this._config.logScale,\n dataRange,\n setAutoscale: () => {}, // always autoscale for now\n setLogScale: (enabled: boolean) => this.setConfig({logScale: enabled}),\n setDataRange: () => {}, // autoscale handles this\n }\n }\n\n /** Render onto an arbitrary context (e.g. SVG export). */\n renderToContext(ctx: CanvasRenderingContext2D, width: number, height: number): void {\n const rc: RenderContext = {\n pixelWidth: width,\n bpStart: this._locus.start,\n bpPerPixel: (this._locus.end - this._locus.start) / width,\n viewportWidth: width,\n }\n const effectiveConfig = {...this._config, height}\n renderInteractionTrack(ctx, this.features, effectiveConfig, rc)\n }\n}\n\nfunction computeDataRange(features: InteractionFeature[]): {min: number; max: number} {\n let max = 0\n for (const f of features) {\n const v = f.value ?? f.score ?? 0\n if (!isNaN(v)) max = Math.max(max, v)\n }\n return {min: 0, max}\n}\n","/**\n * Track registry — extensible factory for creating tracks from session configs.\n *\n * Mirrors igv.js `trackFactory.ts` (`js/trackFactory.ts`), which uses a\n * `Map<string, TrackCreator>` with type alias resolution and runtime\n * registration via `registerTrackClass()` / `registerTrackCreatorFunction()`.\n *\n * Our implementation follows the same pattern: a central `Map` of creators,\n * type aliases, and public registration functions. The key difference is that\n * igv.js creators take `(config, browser)` and return a Track, whereas ours\n * take `(trackConfig, context)` and return a `CreatedTrack` (track + data\n * source + metadata) since data sources are first-class in our architecture.\n */\n\nimport type {\n Locus, Track, DataSource, DataSourceConfig,\n TrackSessionConfig,\n WigTrackSessionConfig,\n AnnotationTrackSessionConfig,\n RulerTrackSessionConfig,\n SequenceTrackSessionConfig,\n InteractionTrackSessionConfig,\n SequenceProvider,\n} from './types'\nimport type {CanvasProvider} from './canvasProvider'\nimport {defaultCanvasProvider} from './canvasProvider'\nimport type {WorkerProvider} from './workerProvider'\nimport type {RenderTheme} from './themes/renderTheme'\nimport {WigTrackCanvas} from './tracks/wig/wigTrackCanvas'\nimport {AnnotationTrackCanvas} from './tracks/annotation/annotationTrackCanvas'\nimport {RulerTrackCanvas} from './tracks/ruler/rulerTrackCanvas'\nimport {SequenceTrackCanvas} from './tracks/sequence/sequenceTrackCanvas'\nimport {BigWigDataSource} from './dataSources/bigWigDataSource'\nimport {GtxDataSource} from './dataSources/gtxDataSource'\nimport {GeneDataSource} from './dataSources/geneDataSource'\nimport {TextFeatureSource} from './dataSources/textFeatureSource'\nimport {SequenceDataSource} from './dataSources/sequenceDataSource'\nimport {InteractionTrackCanvas} from './tracks/interaction/interactionTrackCanvas'\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/** Context passed to every track creator function. */\nexport interface TrackCreatorContext {\n locus: Locus\n canvasProvider: CanvasProvider\n workerProvider?: WorkerProvider\n theme?: Partial<RenderTheme>\n /** Sequence provider from the genome, used by sequence tracks. */\n sequenceProvider?: SequenceProvider\n}\n\n/** Result of creating a track — the track itself plus optional data source. */\nexport interface CreatedTrack {\n track: Track\n dataSource: DataSource | null\n dataSourceConfig: DataSourceConfig | null\n name?: string\n order?: number\n}\n\n/**\n * Factory function that creates a track + data source from a session config.\n *\n * Mirrors igv.js `TrackCreator = (config, browser) => Track` but returns\n * a richer result since we separate track rendering from data sourcing.\n */\nexport type TrackCreator = (\n trackConfig: TrackSessionConfig,\n context: TrackCreatorContext,\n) => CreatedTrack\n\n// ─── Registry ────────────────────────────────────────────────────────────────\n\nconst registry = new Map<string, TrackCreator>()\nconst typeAliases = new Map<string, string>()\n\n/**\n * Register a track creator for a given type string.\n *\n * Mirrors igv.js `registerTrackCreatorFunction()` (js/trackFactory.ts).\n */\nexport function registerTrackCreator(type: string, creator: TrackCreator): void {\n registry.set(type, creator)\n}\n\n/**\n * Register a type alias so that e.g. \"gene\" resolves to \"annotation\".\n *\n * Mirrors igv.js alias resolution in `getTrack()` (js/trackFactory.ts lines 78-96)\n * where switch/case maps \"annotation\"→\"feature\", \"genes\"→\"feature\", etc.\n */\nexport function registerTypeAlias(alias: string, canonicalType: string): void {\n typeAliases.set(alias, canonicalType)\n}\n\n/** Resolve a type string through aliases. */\nfunction resolveType(type: string): string {\n return typeAliases.get(type) ?? type\n}\n\n/**\n * Look up a track creator by type (resolving aliases first).\n *\n * Mirrors igv.js `getTrack()` (js/trackFactory.ts) which resolves aliases\n * then looks up in the `trackFunctions` Map.\n */\nexport function getTrackCreator(type: string): TrackCreator | undefined {\n return registry.get(resolveType(type))\n}\n\n/**\n * Return all known track type strings (canonical + aliases).\n *\n * Mirrors igv.js `knownTrackTypes()` (js/trackFactory.ts).\n */\nexport function knownTrackTypes(): Set<string> {\n const types = new Set<string>(registry.keys())\n for (const alias of typeAliases.keys()) {\n types.add(alias)\n }\n return types\n}\n\n// ─── Built-in data source helpers ────────────────────────────────────────────\n\nexport function createDataSource(\n config: DataSourceConfig,\n workerProvider?: WorkerProvider,\n): DataSource {\n switch (config.type) {\n case 'bigwig':\n return new BigWigDataSource(config.url, config.windowFunction, workerProvider)\n case 'gtx':\n return new GtxDataSource(config.url, config.experimentId, config.windowFunction, workerProvider)\n case 'ucsc':\n return new GeneDataSource({genome: config.genome, track: config.track})\n case 'text':\n return new TextFeatureSource({\n url: config.url,\n format: config.format,\n indexURL: config.indexURL,\n indexed: config.indexed,\n workerProvider,\n })\n }\n}\n\n// ─── Built-in track creators ─────────────────────────────────────────────────\n\nfunction createWigTrack(trackConfig: TrackSessionConfig, ctx: TrackCreatorContext): CreatedTrack {\n const config = trackConfig as WigTrackSessionConfig\n const {canvas} = ctx.canvasProvider.createCanvas(0, 0)\n const track = new WigTrackCanvas(canvas, {\n locus: ctx.locus,\n features: [],\n config: config.config,\n theme: ctx.theme,\n canvasProvider: ctx.canvasProvider,\n })\n let dataSource: DataSource | null = null\n let dataSourceConfig: DataSourceConfig | null = null\n if (config.dataSource) {\n dataSourceConfig = config.dataSource\n dataSource = createDataSource(config.dataSource, ctx.workerProvider)\n }\n return {track, dataSource, dataSourceConfig, name: config.name, order: config.order}\n}\n\nfunction createAnnotationTrack(trackConfig: TrackSessionConfig, ctx: TrackCreatorContext): CreatedTrack {\n const config = trackConfig as AnnotationTrackSessionConfig\n const {canvas} = ctx.canvasProvider.createCanvas(0, 0)\n const track = new AnnotationTrackCanvas(canvas, {\n locus: ctx.locus,\n features: [],\n config: config.config,\n theme: ctx.theme,\n canvasProvider: ctx.canvasProvider,\n workerProvider: ctx.workerProvider,\n })\n let dataSource: DataSource | null = null\n let dataSourceConfig: DataSourceConfig | null = null\n if (config.dataSource) {\n dataSourceConfig = config.dataSource\n dataSource = createDataSource(config.dataSource, ctx.workerProvider)\n }\n return {track, dataSource, dataSourceConfig, name: config.name, order: config.order}\n}\n\nfunction createRulerTrack(trackConfig: TrackSessionConfig, ctx: TrackCreatorContext): CreatedTrack {\n const config = trackConfig as RulerTrackSessionConfig\n const {canvas} = ctx.canvasProvider.createCanvas(0, 0)\n const track = new RulerTrackCanvas(canvas, {\n locus: ctx.locus,\n config: config.config,\n theme: ctx.theme,\n canvasProvider: ctx.canvasProvider,\n })\n return {track, dataSource: null, dataSourceConfig: null, name: config.name, order: config.order}\n}\n\nfunction createSequenceTrack(trackConfig: TrackSessionConfig, ctx: TrackCreatorContext): CreatedTrack {\n const config = trackConfig as SequenceTrackSessionConfig\n const {canvas} = ctx.canvasProvider.createCanvas(0, 0)\n const track = new SequenceTrackCanvas(canvas, {\n locus: ctx.locus,\n config: config.config,\n theme: ctx.theme,\n canvasProvider: ctx.canvasProvider,\n })\n // Create a SequenceDataSource if a sequence provider is available (from the genome).\n // This mirrors igv.js where SequenceTrack.getFeatures() calls browser.genome.getSequence().\n const dataSource = ctx.sequenceProvider\n ? new SequenceDataSource(ctx.sequenceProvider)\n : null\n return {track, dataSource, dataSourceConfig: null, name: config.name, order: config.order}\n}\n\nfunction createInteractionTrack(trackConfig: TrackSessionConfig, ctx: TrackCreatorContext): CreatedTrack {\n const config = trackConfig as InteractionTrackSessionConfig\n const {canvas} = ctx.canvasProvider.createCanvas(0, 0)\n const track = new InteractionTrackCanvas(canvas, {\n locus: ctx.locus,\n features: [],\n config: config.config,\n theme: ctx.theme,\n canvasProvider: ctx.canvasProvider,\n name: config.name,\n })\n let dataSource: DataSource | null = null\n let dataSourceConfig: DataSourceConfig | null = null\n if (config.dataSource) {\n dataSourceConfig = config.dataSource\n dataSource = createDataSource(config.dataSource, ctx.workerProvider)\n }\n return {track, dataSource, dataSourceConfig, name: config.name, order: config.order}\n}\n\n// ─── Register built-ins ──────────────────────────────────────────────────────\n\nregisterTrackCreator('wig', createWigTrack)\nregisterTrackCreator('annotation', createAnnotationTrack)\nregisterTrackCreator('ruler', createRulerTrack)\nregisterTrackCreator('sequence', createSequenceTrack)\nregisterTrackCreator('interact', createInteractionTrack)\n\n// Type aliases — mirrors igv.js alias resolution in getTrack() (js/trackFactory.ts)\nregisterTypeAlias('gene', 'annotation')\nregisterTypeAlias('refgene', 'annotation')\nregisterTypeAlias('bigwig', 'wig')\nregisterTypeAlias('bedgraph', 'wig')\n\n// Text feature format → track type aliases\nregisterTypeAlias('bed', 'annotation')\nregisterTypeAlias('gff3', 'annotation')\nregisterTypeAlias('gtf', 'annotation')\nregisterTypeAlias('gff', 'annotation')\nregisterTypeAlias('narrowpeak', 'annotation')\nregisterTypeAlias('broadpeak', 'annotation')\nregisterTypeAlias('genepred', 'annotation')\nregisterTypeAlias('genepredext', 'annotation')\nregisterTypeAlias('refflat', 'annotation')\n\n// Interaction format aliases\nregisterTypeAlias('bedpe', 'interact')\nregisterTypeAlias('arc', 'interact')\nregisterTypeAlias('longrange', 'interact')\n\n// ─── Convenience: create from session config ─────────────────────────────────\n\n/**\n * Create a track from a session config using the registry.\n *\n * This replaces the switch/case in the old `createTrackFromSession()`.\n * Unknown types throw an error (mirrors igv.js behavior where `getTrack()`\n * returns undefined and the browser logs a warning).\n */\nexport function createTrackFromConfig(\n trackConfig: TrackSessionConfig,\n locus: Locus,\n options: {\n canvasProvider?: CanvasProvider\n workerProvider?: WorkerProvider\n theme?: Partial<RenderTheme>\n sequenceProvider?: SequenceProvider\n } = {},\n): CreatedTrack {\n const creator = getTrackCreator(trackConfig.type)\n if (!creator) {\n throw new Error(`Unknown track type: \"${trackConfig.type}\". Known types: ${[...knownTrackTypes()].join(', ')}`)\n }\n return creator(trackConfig, {\n locus,\n canvasProvider: options.canvasProvider ?? defaultCanvasProvider,\n workerProvider: options.workerProvider,\n theme: options.theme,\n sequenceProvider: options.sequenceProvider,\n })\n}\n","/**\n * Session serialization and igv.js compatibility.\n *\n * Provides:\n * - igv.js session import/export (fromIgvSession / toIgvSession)\n * - Track creation via the track registry (createTrackFromSession)\n *\n * Track creation is delegated to the track registry (src/trackRegistry.ts),\n * which provides an extensible Map-based factory. This module re-exports\n * the registry's `createTrackFromConfig` under the legacy name for backward\n * compatibility with existing session-loading code.\n *\n * Per-track config serialization is distributed to each track canvas class\n * (WigTrackCanvas.serializeConfig, AnnotationTrackCanvas.serializeConfig, etc.)\n */\n\nimport type {\n SessionConfig,\n TrackSessionConfig,\n WigTrackSessionConfig,\n AnnotationTrackSessionConfig,\n RulerTrackSessionConfig,\n InteractionTrackSessionConfig,\n InteractionSessionOverrides,\n WigSessionOverrides,\n AnnotationSessionOverrides,\n BigWigDataSourceConfig,\n TextDataSourceConfig,\n IgvSessionObject,\n IgvTrackConfig,\n Locus,\n WindowFunction,\n DisplayMode,\n SequenceProvider,\n} from './types'\nimport type {CanvasProvider} from './canvasProvider'\nimport type {WorkerProvider} from './workerProvider'\nimport type {RenderTheme} from './themes/renderTheme'\nimport {createTrackFromConfig} from './trackRegistry'\nimport {parseLocus, formatLocus} from './locusUtils'\n\n// Re-export CreatedTrack from registry — this is the canonical definition\nexport type {CreatedTrack} from './trackRegistry'\n\nexport const SESSION_VERSION = '1.0'\n\n// ─── Data source factory ─────────────────────────────────────────────────────\n\nexport interface CreateDataSourceOptions {\n /** Worker provider for offloading CPU-intensive tasks in data sources. */\n workerProvider?: WorkerProvider\n}\n\n/**\n * @deprecated Use the track registry (`createTrackFromConfig`) instead, which\n * handles data source creation internally. Kept for direct data source creation\n * in non-session contexts.\n */\nexport {createDataSource} from './trackRegistry'\n\n// ─── Track factory ──────────────────────────────────────────────────────────\n\nexport interface CreateTrackFromSessionOptions extends CreateDataSourceOptions {\n /** Canvas provider for creating track canvases. */\n canvasProvider?: CanvasProvider\n /** Render theme for config resolution. */\n theme?: Partial<RenderTheme>\n /** Sequence provider from the genome, used by sequence tracks. */\n sequenceProvider?: SequenceProvider\n}\n\n/**\n * Create a track canvas + data source from a serialized TrackSessionConfig.\n *\n * Delegates to the track registry's `createTrackFromConfig()`, which uses\n * the extensible Map-based factory instead of a switch/case.\n */\nexport function createTrackFromSession(\n trackConfig: TrackSessionConfig,\n locus: Locus,\n options: CreateTrackFromSessionOptions = {},\n) {\n return createTrackFromConfig(trackConfig, locus, options)\n}\n\n// ─── igv.js session conversion ───────────────────────────────────────────────\n\n/** Map igv.js track type strings to our track types. */\nconst IGV_TRACK_TYPE_MAP: Record<string, TrackSessionConfig['type']> = {\n 'wig': 'wig',\n 'bigwig': 'wig',\n 'bedgraph': 'wig',\n 'annotation': 'annotation',\n 'gene': 'annotation',\n 'refgene': 'annotation',\n 'bed': 'annotation',\n 'gff3': 'annotation',\n 'gtf': 'annotation',\n 'narrowpeak': 'annotation',\n 'broadpeak': 'annotation',\n 'sequence': 'sequence',\n 'interact': 'interact',\n 'bedpe': 'interact',\n 'arc': 'interact',\n}\n\n/**\n * Convert an igv.js session object to our SessionConfig format.\n * Unknown track types are skipped with a console warning.\n */\nexport function fromIgvSession(igvSession: IgvSessionObject): SessionConfig {\n // Parse locus\n const locusStr = Array.isArray(igvSession.locus) ? igvSession.locus[0] : igvSession.locus\n const locus = locusStr ? parseLocus(locusStr) : null\n if (!locus) {\n throw new Error(`Cannot parse locus from igv session: ${locusStr}`)\n }\n\n const tracks: TrackSessionConfig[] = []\n if (igvSession.tracks) {\n for (const igvTrack of igvSession.tracks) {\n const converted = convertIgvTrack(igvTrack)\n if (converted) tracks.push(converted)\n }\n }\n\n return {\n version: SESSION_VERSION,\n locus,\n tracks,\n }\n}\n\nfunction convertIgvTrack(igvTrack: IgvTrackConfig): TrackSessionConfig | null {\n const ourType = IGV_TRACK_TYPE_MAP[igvTrack.type ?? '']\n if (!ourType) {\n if (igvTrack.type !== 'sequence' && igvTrack.type !== 'ruler') {\n console.warn(`Skipping unsupported igv.js track type: ${igvTrack.type}`)\n }\n // Convert ruler tracks\n if (igvTrack.type === 'ruler') {\n const rulerConfig: RulerTrackSessionConfig = {type: 'ruler'}\n if (igvTrack.height) rulerConfig.config = {height: igvTrack.height}\n return rulerConfig\n }\n return null\n }\n\n switch (ourType) {\n case 'wig':\n return convertIgvWigTrack(igvTrack)\n case 'annotation':\n return convertIgvAnnotationTrack(igvTrack)\n case 'interact':\n return convertIgvInteractionTrack(igvTrack)\n case 'ruler':\n return {type: 'ruler'}\n case 'sequence':\n return {type: 'sequence'}\n }\n}\n\nfunction convertIgvWigTrack(igvTrack: IgvTrackConfig): WigTrackSessionConfig {\n const result: WigTrackSessionConfig = {type: 'wig'}\n\n if (igvTrack.name) result.name = igvTrack.name\n if (igvTrack.order != null) result.order = igvTrack.order\n\n // Data source\n if (igvTrack.url) {\n const ds: BigWigDataSourceConfig = {type: 'bigwig', url: igvTrack.url}\n if (igvTrack.windowFunction) {\n ds.windowFunction = igvTrack.windowFunction as WindowFunction\n }\n result.dataSource = ds\n }\n\n // Config overrides\n const config: WigSessionOverrides = {}\n let hasConfig = false\n\n if (igvTrack.color) { config.color = igvTrack.color; hasConfig = true }\n if (igvTrack.altColor) { config.altColor = igvTrack.altColor; hasConfig = true }\n if (igvTrack.height != null) { config.height = igvTrack.height; hasConfig = true }\n if (igvTrack.autoscale != null) { config.autoscale = igvTrack.autoscale; hasConfig = true }\n if (igvTrack.min != null && igvTrack.max != null) {\n config.dataRange = {min: igvTrack.min, max: igvTrack.max}\n hasConfig = true\n }\n\n if (hasConfig) result.config = config\n\n return result\n}\n\nfunction convertIgvAnnotationTrack(igvTrack: IgvTrackConfig): AnnotationTrackSessionConfig {\n const result: AnnotationTrackSessionConfig = {type: 'annotation'}\n\n if (igvTrack.name) result.name = igvTrack.name\n if (igvTrack.order != null) result.order = igvTrack.order\n\n // Data source — gene tracks in igv.js can come from URLs (text files) or UCSC\n if (igvTrack.url) {\n const ds: TextDataSourceConfig = {type: 'text', url: igvTrack.url}\n if (igvTrack.indexURL) ds.indexURL = igvTrack.indexURL\n if (igvTrack.format) ds.format = igvTrack.format as TextDataSourceConfig['format']\n result.dataSource = ds\n }\n\n // Config overrides\n const config: AnnotationSessionOverrides = {}\n let hasConfig = false\n\n if (igvTrack.color) { config.color = igvTrack.color; hasConfig = true }\n if (igvTrack.height != null) { config.featureHeight = igvTrack.height; hasConfig = true }\n if (igvTrack.displayMode) {\n config.displayMode = igvTrack.displayMode.toUpperCase() as DisplayMode\n hasConfig = true\n }\n\n if (hasConfig) result.config = config\n\n return result\n}\n\n/**\n * Convert our SessionConfig to an igv.js-compatible session object.\n */\nexport function toIgvSession(session: SessionConfig): IgvSessionObject {\n const igvSession: IgvSessionObject = {\n locus: formatLocus(session.locus),\n tracks: [],\n }\n\n for (const track of session.tracks) {\n const igvTrack = convertToIgvTrack(track)\n if (igvTrack) igvSession.tracks!.push(igvTrack)\n }\n\n return igvSession\n}\n\nfunction convertToIgvTrack(track: TrackSessionConfig): IgvTrackConfig | null {\n switch (track.type) {\n case 'wig':\n return convertToIgvWigTrack(track)\n case 'annotation':\n return convertToIgvAnnotationTrack(track)\n case 'interact':\n return convertToIgvInteractionTrack(track)\n case 'ruler':\n return {type: 'ruler', height: track.config?.height}\n case 'sequence':\n return {type: 'sequence'}\n }\n}\n\nfunction convertToIgvWigTrack(track: WigTrackSessionConfig): IgvTrackConfig {\n const igv: IgvTrackConfig = {type: 'wig'}\n\n if (track.name) igv.name = track.name\n if (track.order != null) igv.order = track.order\n\n // URL from data source\n if (track.dataSource) {\n if (track.dataSource.type === 'bigwig') {\n igv.url = track.dataSource.url\n if (track.dataSource.windowFunction) igv.windowFunction = track.dataSource.windowFunction\n }\n }\n\n // Config\n if (track.config) {\n if (track.config.color) igv.color = track.config.color\n if (track.config.altColor) igv.altColor = track.config.altColor\n if (track.config.height != null) igv.height = track.config.height\n if (track.config.autoscale != null) igv.autoscale = track.config.autoscale\n if (track.config.dataRange) {\n igv.min = track.config.dataRange.min\n igv.max = track.config.dataRange.max\n }\n }\n\n return igv\n}\n\nfunction convertToIgvAnnotationTrack(track: AnnotationTrackSessionConfig): IgvTrackConfig {\n const igv: IgvTrackConfig = {type: 'annotation'}\n\n if (track.name) igv.name = track.name\n if (track.order != null) igv.order = track.order\n\n if (track.config) {\n if (track.config.color) igv.color = track.config.color\n if (track.config.displayMode) igv.displayMode = track.config.displayMode\n }\n\n return igv\n}\n\nfunction convertIgvInteractionTrack(igvTrack: IgvTrackConfig): InteractionTrackSessionConfig {\n const result: InteractionTrackSessionConfig = {type: 'interact'}\n\n if (igvTrack.name) result.name = igvTrack.name\n if (igvTrack.order != null) result.order = igvTrack.order\n\n if (igvTrack.url) {\n const ds: TextDataSourceConfig = {type: 'text', url: igvTrack.url}\n if (igvTrack.indexURL) ds.indexURL = igvTrack.indexURL\n if (igvTrack.format) ds.format = igvTrack.format as TextDataSourceConfig['format']\n result.dataSource = ds\n }\n\n const config: InteractionSessionOverrides = {}\n let hasConfig = false\n\n if (igvTrack.color) { config.color = igvTrack.color; hasConfig = true }\n if (igvTrack.height != null) { config.height = igvTrack.height; hasConfig = true }\n\n if (hasConfig) result.config = config\n\n return result\n}\n\nfunction convertToIgvInteractionTrack(track: InteractionTrackSessionConfig): IgvTrackConfig {\n const igv: IgvTrackConfig = {type: 'interact'}\n\n if (track.name) igv.name = track.name\n if (track.order != null) igv.order = track.order\n\n if (track.dataSource?.type === 'text') {\n igv.url = track.dataSource.url\n if (track.dataSource.indexURL) igv.indexURL = track.dataSource.indexURL\n if (track.dataSource.format) igv.format = track.dataSource.format\n }\n\n if (track.config) {\n if (track.config.color) igv.color = track.config.color\n if (track.config.height != null) igv.height = track.config.height\n }\n\n return igv\n}\n","/**\n * Derive a stable cache key from a DataSourceConfig.\n *\n * Used by HeadlessGenomeBrowser to group tracks that share the same\n * underlying data source, enabling fetch deduplication when multiple\n * tracks point to the same URL/region.\n */\n\nimport type {DataSourceConfig} from '../types'\n\nexport function dataSourceCacheKey(config: DataSourceConfig): string {\n switch (config.type) {\n case 'bigwig':\n return `bigwig:${config.url}:${config.windowFunction ?? 'mean'}`\n case 'gtx':\n return `gtx:${config.url}:${config.experimentId}`\n case 'ucsc':\n return `ucsc:${config.genome ?? ''}:${config.track ?? ''}`\n case 'text':\n return `text:${config.url}:${config.format ?? ''}:${config.indexURL ?? ''}`\n }\n}\n","/**\n * StateProjection — concise state snapshots with record/diff support.\n *\n * Wraps a HeadlessGenomeBrowser to produce compact, serializable state objects.\n * Supports snapshotting (record) and incremental diffs against prior snapshots.\n *\n * Feature summarization reads from the browser's cache via getCachedFeatures(),\n * filters to the visible viewport, and applies type-specific summarization.\n *\n * Swappable: consumers can extend or replace this class for custom projection logic.\n */\n\nimport type {\n Locus, TrackFeatureSummary,\n WigFeature, WigFeatureSummary,\n AnnotationFeature, AnnotationFeatureSummary,\n InteractionFeature, InteractionFeatureSummary,\n ROISetConfig,\n} from './types'\nimport type {HeadlessGenomeBrowser, ManagedTrack} from './headlessGenomeBrowser'\nimport {computeWigDataRange} from './tracks/wig/wigSummary'\n\n// ─── Projected state types ───────────────────────────────────────────────────\n\n/** Zoom level classification based on viewport span. */\nexport type ZoomLevel = 'base' | 'element' | 'gene' | 'region' | 'chromosome' | 'genome'\n\n/** Concise summary of a single track, suitable for LLM consumption. */\nexport interface TrackSummary {\n id: string\n type: string\n name?: string\n metadata?: Record<string, string>\n /** True when a data source exists but no cached data is available yet. */\n loading?: boolean\n featureSummary?: TrackFeatureSummary\n}\n\n/** Full projected state of the browser — concise, JSON-serializable. */\nexport interface ProjectedState {\n locus: Locus\n /** Formatted locus string, e.g. \"chr17:7,668,421-7,687,490\" */\n locusString: string\n /** Viewport span in base pairs. */\n span: number\n zoomLevel: ZoomLevel\n genome?: string\n tracks: TrackSummary[]\n rois: ROISetConfig[]\n}\n\n/** Per-field [before, after] diff for a track whose feature summary changed. */\nexport interface TrackChangeDiff {\n id: string\n type: string\n featureCount?: [number, number]\n signalRange?: [{ min: number; max: number }, { min: number; max: number }]\n featureNames?: [string[], string[]]\n packingDepth?: [number, number]\n valueRange?: [{ min: number; max: number }, { min: number; max: number }]\n}\n\n/** Diff between two projected states — only includes what changed. */\nexport interface StateDiff {\n /** Present if locus changed. */\n locus?: [Locus, Locus]\n /** Present if zoom level changed. */\n zoomLevel?: [ZoomLevel, ZoomLevel]\n /** Tracks added since the snapshot. */\n tracksAdded?: TrackSummary[]\n /** Track IDs removed since the snapshot. */\n tracksRemoved?: string[]\n /** Tracks whose feature summary changed, with per-field [before, after] tuples. */\n tracksChanged?: TrackChangeDiff[]\n /** Present if ROIs changed. */\n roisChanged?: boolean\n /** True if nothing changed. */\n unchanged: boolean\n}\n\nexport interface GetStateOptions {\n /** If provided, record the state under this key for future diff() calls. */\n record?: string\n}\n\n// ─── StateProjection class ──────────────────────────────────────────────────\n\nexport class StateProjection {\n private browser: HeadlessGenomeBrowser\n private snapshots = new Map<string, ProjectedState>()\n\n constructor(browser: HeadlessGenomeBrowser) {\n this.browser = browser\n }\n\n /** Get the current projected state. Optionally record it under a key. */\n getState(options?: GetStateOptions): ProjectedState {\n const state = this.project()\n if (options?.record) {\n this.snapshots.set(options.record, structuredClone(state))\n }\n return state\n }\n\n /**\n * Diff the current state against a named snapshot.\n * Returns an object describing only what changed.\n * Throws if the key doesn't exist.\n */\n diff(key: string): StateDiff {\n const prev = this.snapshots.get(key)\n if (!prev) {\n throw new Error(`No snapshot recorded under key \"${key}\"`)\n }\n\n const current = this.project()\n const result: StateDiff = {unchanged: true}\n\n // Locus change\n if (prev.locus.chr !== current.locus.chr ||\n prev.locus.start !== current.locus.start ||\n prev.locus.end !== current.locus.end) {\n result.locus = [prev.locus, current.locus]\n result.unchanged = false\n }\n\n // Zoom level change\n if (prev.zoomLevel !== current.zoomLevel) {\n result.zoomLevel = [prev.zoomLevel, current.zoomLevel]\n result.unchanged = false\n }\n\n // Track diffs\n const prevIds = new Set(prev.tracks.map(t => t.id))\n const currentIds = new Set(current.tracks.map(t => t.id))\n\n const added = current.tracks.filter(t => !prevIds.has(t.id))\n const removed = prev.tracks.filter(t => !currentIds.has(t.id)).map(t => t.id)\n\n if (added.length > 0) {\n result.tracksAdded = added\n result.unchanged = false\n }\n if (removed.length > 0) {\n result.tracksRemoved = removed\n result.unchanged = false\n }\n\n // Tracks that exist in both but whose feature summary changed\n const changed: TrackChangeDiff[] = []\n for (const ct of current.tracks) {\n if (!prevIds.has(ct.id)) continue\n const pt = prev.tracks.find(t => t.id === ct.id)!\n if (!featureSummariesEqual(pt.featureSummary, ct.featureSummary)) {\n const diff = diffFeatureSummary(ct.id, ct.type, pt.featureSummary, ct.featureSummary)\n if (diff) changed.push(diff)\n }\n }\n if (changed.length > 0) {\n result.tracksChanged = changed\n result.unchanged = false\n }\n\n // ROI change\n if (JSON.stringify(prev.rois) !== JSON.stringify(current.rois)) {\n result.roisChanged = true\n result.unchanged = false\n }\n\n return result\n }\n\n /** Record the current state under a key without returning it. */\n record(key: string): void {\n this.snapshots.set(key, structuredClone(this.project()))\n }\n\n /** Delete a snapshot by key. */\n deleteSnapshot(key: string): boolean {\n return this.snapshots.delete(key)\n }\n\n /** Get a previously recorded snapshot by key. */\n getSnapshot(key: string): ProjectedState | undefined {\n return this.snapshots.get(key)\n }\n\n /** List all snapshot keys. */\n snapshotKeys(): string[] {\n return [...this.snapshots.keys()]\n }\n\n /** Clear all snapshots. */\n clearSnapshots(): void {\n this.snapshots.clear()\n }\n\n // ─── Internal projection logic ──────────────────────────────────────\n\n private project(): ProjectedState {\n const raw = this.browser.locus\n const locus: Locus = {chr: raw.chr, start: Math.round(raw.start), end: Math.round(raw.end)}\n const span = locus.end - locus.start\n const managedTracks = this.browser.getManagedTracks()\n\n return {\n locus,\n locusString: formatLocusCompact(locus),\n span,\n zoomLevel: classifyZoom(span),\n genome: this.browser.genome?.id,\n tracks: managedTracks\n .filter(mt => mt.track.type !== 'ruler')\n .map(mt => this.projectTrack(mt, locus)),\n rois: this.browser.toJSON().rois ?? [],\n }\n }\n\n private projectTrack(mt: ManagedTrack, locus: Locus): TrackSummary {\n const featureSummary = this.summarizeFeatures(mt, locus)\n const hasDataSource = mt.dataSource != null\n const hasCachedData = mt.cache != null\n return {\n id: mt.id,\n type: mt.track.type,\n name: mt.name,\n metadata: mt.metadata,\n loading: hasDataSource && !hasCachedData ? true : undefined,\n featureSummary,\n }\n }\n\n /**\n * Summarize cached features for a track, filtered to the visible viewport.\n * Reads from the browser's cache via getCachedFeatures() and applies\n * type-specific summarization. Override this method in subclasses for\n * custom summary formats.\n */\n protected summarizeFeatures(mt: ManagedTrack, locus: Locus): TrackFeatureSummary | undefined {\n switch (mt.track.type) {\n case 'wig':\n return this.summarizeWig(mt, locus)\n case 'annotation':\n return this.summarizeAnnotation(mt, locus)\n case 'interact':\n return this.summarizeInteraction(mt, locus)\n default:\n return undefined\n }\n }\n\n private summarizeWig(mt: ManagedTrack, locus: Locus): WigFeatureSummary | undefined {\n const features = this.browser.getCachedFeatures<WigFeature>(mt.track)\n if (!features) return undefined\n const visible = filterByLocus(features, locus)\n return {\n featureCount: visible.length,\n signalRange: visible.length > 0 ? computeWigDataRange(visible) : {min: 0, max: 0},\n }\n }\n\n private summarizeAnnotation(mt: ManagedTrack, locus: Locus): AnnotationFeatureSummary | undefined {\n const features = this.browser.getCachedFeatures<AnnotationFeature>(mt.track)\n if (!features) return undefined\n const visible = filterByLocus(features, locus)\n const MAX_NAMES = 20\n const nameSet = new Set<string>()\n for (const f of visible) {\n if (f.name && nameSet.size < MAX_NAMES) nameSet.add(f.name)\n }\n const packingDepth = visible.reduce((max, f) => Math.max(max, f.row ?? 0), 0)\n return {\n featureCount: visible.length,\n featureNames: [...nameSet],\n packingDepth,\n }\n }\n\n private summarizeInteraction(mt: ManagedTrack, locus: Locus): InteractionFeatureSummary | undefined {\n const features = this.browser.getCachedFeatures<InteractionFeature>(mt.track)\n if (!features) return undefined\n const visible = filterByLocus(features, locus)\n let max = 0\n for (const f of visible) {\n const v = f.value ?? f.score ?? 0\n if (!isNaN(v)) max = Math.max(max, v)\n }\n return {\n featureCount: visible.length,\n valueRange: {min: 0, max},\n }\n }\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\n/** Classify viewport span into a human-readable zoom level. */\nfunction classifyZoom(span: number): ZoomLevel {\n if (span <= 100) return 'base'\n if (span <= 10_000) return 'element'\n if (span <= 500_000) return 'gene'\n if (span <= 10_000_000) return 'region'\n if (span <= 250_000_000) return 'chromosome'\n return 'genome'\n}\n\n/** Format locus compactly: \"chr17:7,668,421-7,687,490\" */\nfunction formatLocusCompact(locus: Locus): string {\n return `${locus.chr}:${locus.start.toLocaleString()}-${locus.end.toLocaleString()}`\n}\n\n/** Filter features to those overlapping the visible viewport locus. */\nfunction filterByLocus<F extends { start: number; end: number }>(features: F[], locus: Locus): F[] {\n return features.filter(f => f.end > locus.start && f.start < locus.end)\n}\n\n/** Build a per-field [before, after] diff for changed feature summaries. */\nfunction diffFeatureSummary(\n id: string,\n type: string,\n a: TrackFeatureSummary | undefined,\n b: TrackFeatureSummary | undefined,\n): TrackChangeDiff | undefined {\n const diff: TrackChangeDiff = {id, type}\n let hasChange = false\n\n const ac = (a as unknown as Record<string, unknown>) ?? {}\n const bc = (b as unknown as Record<string, unknown>) ?? {}\n\n // Compare each known summary field\n for (const key of ['featureCount', 'signalRange', 'featureNames', 'packingDepth', 'valueRange'] as const) {\n const av = ac[key]\n const bv = bc[key]\n if (JSON.stringify(av) !== JSON.stringify(bv)) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ;(diff as any)[key] = [av ?? null, bv ?? null]\n hasChange = true\n }\n }\n\n return hasChange ? diff : undefined\n}\n\n/** Deep equality check for feature summaries (both may be undefined). */\nfunction featureSummariesEqual(\n a: TrackFeatureSummary | undefined,\n b: TrackFeatureSummary | undefined,\n): boolean {\n if (a === b) return true\n if (!a || !b) return false\n return JSON.stringify(a) === JSON.stringify(b)\n}\n","/**\n * TrackSelector — SQL-ish WHERE clause for matching tracks by metadata.\n *\n * Selectors support matching on track ID, name (string or RegExp), type,\n * and arbitrary metadata key-value pairs. All provided fields use AND semantics:\n * a track must match every specified criterion.\n *\n * ```ts\n * // Remove all ATAC-seq tracks\n * browser.removeTracks({ where: { assay: 'ATAC-seq' } })\n *\n * // Find wig tracks from K562\n * browser.findTracks({ type: 'wig', where: { biosample: 'K562' } })\n * ```\n */\n\nimport type {ManagedTrack} from './headlessGenomeBrowser'\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/** Selector for matching tracks by ID, name, type, and/or metadata. */\nexport interface TrackSelector {\n /** Exact match against track ID. */\n id?: string\n /** String: case-insensitive substring match. RegExp: test against track name. */\n name?: string | RegExp\n /** Exact match against track type (e.g. 'wig', 'annotation', 'interact'). */\n type?: string\n /** Metadata key-value matching. Every entry must match (AND semantics). */\n where?: Record<string, string>\n}\n\n// ─── Matching ────────────────────────────────────────────────────────────────\n\n/** Test whether a single managed track matches all criteria in a selector. */\nexport function matchesSelector(mt: ManagedTrack, selector: TrackSelector): boolean {\n // ID: exact match\n if (selector.id !== undefined && mt.id !== selector.id) {\n return false\n }\n\n // Name: substring (case-insensitive) or RegExp\n if (selector.name !== undefined) {\n const trackName = mt.name ?? ''\n if (typeof selector.name === 'string') {\n if (!trackName.toLowerCase().includes(selector.name.toLowerCase())) {\n return false\n }\n } else {\n // RegExp\n if (!selector.name.test(trackName)) {\n return false\n }\n }\n }\n\n // Type: exact match\n if (selector.type !== undefined && mt.track.type !== selector.type) {\n return false\n }\n\n // Where: every key-value must match in metadata\n if (selector.where !== undefined) {\n const meta = mt.metadata\n if (!meta) return false\n for (const [key, value] of Object.entries(selector.where)) {\n if (meta[key] !== value) return false\n }\n }\n\n return true\n}\n\n/** Select all managed tracks matching a selector. */\nexport function selectTracks(tracks: readonly ManagedTrack[], selector: TrackSelector): ManagedTrack[] {\n return tracks.filter(mt => matchesSelector(mt, selector))\n}\n","/**\n * Headless GenomeBrowser — pure data/navigation/caching core with zero DOM dependencies.\n *\n * Manages locus state, track coordination, data lifecycle (buffered fetch, caching,\n * abort), events, and theming. Can run in Node.js, workers, or any environment.\n *\n * The DOM-attached `GenomeBrowser` extends this class to add pointer events,\n * ResizeObserver, canvas stacking, and sweep-to-zoom.\n *\n * Usage (headless):\n * const browser = new HeadlessGenomeBrowser({\n * locus: { chr: 'chr17', start: 7668000, end: 7688000 },\n * viewportWidth: 800,\n * })\n * browser.addTrack(track, dataSource)\n * browser.setLocus({ chr: 'chr17', start: 7670000, end: 7680000 })\n * browser.dispose()\n */\n\nimport type {\n Locus, Track, DataSource, DataDrivenTrack, FeatureCacheEntry,\n SessionConfig, TrackSessionConfig, DataSourceConfig,\n TrackInteractionEvent, TrackContextMenuEvent,\n WindowFunction, BigWigDataSourceConfig, GtxDataSourceConfig, UCSCDataSourceConfig, TextDataSourceConfig,\n WigRenderConfig, AnnotationRenderConfig, RulerRenderConfig, SequenceRenderConfig, InteractionRenderConfig, TextFileFormat,\n SequenceProvider, Genome, SequenceTrackSessionConfig,\n ROI, ROISetConfig, ROIInteractionEvent,\n} from './types'\nimport {ROISet} from './roi/roiSet'\nimport {renderROIOverlays} from './roi/roiRenderer'\nimport type {CanvasProvider} from './canvasProvider'\nimport {C2S} from './export/canvas2svg'\nimport {defaultCanvasProvider} from './canvasProvider'\nimport type {WorkerProvider} from './workerProvider'\nimport type {PopupProvider} from './popupProvider'\nimport type {ContextMenuProvider} from './contextMenuProvider'\nimport type {RenderTheme} from './themes/renderTheme'\nimport {resolveTheme} from './themes/renderTheme'\nimport {EventEmitter} from './events'\nimport {parseLocus, clampLocus} from './locusUtils'\nimport {cacheCoversViewport, bufferLocus} from './dataLifecycle'\nimport type {ChromSizes, CumulativeOffsets} from './genome/chromSizes'\nimport {isWholeGenomeView} from './locusUtils'\nimport {hg38Genome} from './genome/genome'\nimport {\n SESSION_VERSION,\n createTrackFromSession,\n type CreateTrackFromSessionOptions,\n} from './session'\nimport {createTrackFromConfig} from './trackRegistry'\nimport {RulerTrackCanvas} from './tracks/ruler/rulerTrackCanvas'\nimport {WigTrackCanvas} from './tracks/wig/wigTrackCanvas'\nimport {AnnotationTrackCanvas} from './tracks/annotation/annotationTrackCanvas'\nimport {SequenceTrackCanvas} from './tracks/sequence/sequenceTrackCanvas'\nimport {InteractionTrackCanvas} from './tracks/interaction/interactionTrackCanvas'\nimport {BigWigDataSource} from './dataSources/bigWigDataSource'\nimport {GtxDataSource} from './dataSources/gtxDataSource'\nimport {GeneDataSource} from './dataSources/geneDataSource'\nimport {TextFeatureSource} from './dataSources/textFeatureSource'\nimport {dataSourceCacheKey} from './dataSources/dataSourceCacheKey'\nimport {StateProjection} from './stateProjection'\nimport type {TrackSelector} from './trackSelector'\nimport {selectTracks} from './trackSelector'\n\nexport const BrowserEvent = {\n LocusChange: 'locuschange',\n TrackAdded: 'trackadded',\n TrackRemoved: 'trackremoved',\n TrackOrderChanged: 'trackorderchanged',\n DataLoaded: 'dataloaded',\n DataError: 'dataerror',\n RenderError: 'rendererror',\n TrackClick: 'trackclick',\n TrackHover: 'trackhover',\n TrackContextMenu: 'trackcontextmenu',\n ROIAdded: 'roiadded',\n ROIRemoved: 'roiremoved',\n ROIChanged: 'roichanged',\n ROIClick: 'roiclick',\n ROIContextMenu: 'roicontextmenu',\n ThemeChanged: 'themechange',\n} as const\n\nexport interface BrowserEvents {\n [BrowserEvent.LocusChange]: { locus: Locus }\n [BrowserEvent.TrackAdded]: { track: Track }\n [BrowserEvent.TrackRemoved]: { track: Track }\n [BrowserEvent.TrackOrderChanged]: { tracks: Track[] }\n [BrowserEvent.DataLoaded]: { track: Track }\n [BrowserEvent.DataError]: { track: Track; error: Error }\n [BrowserEvent.RenderError]: { track: Track; error: Error }\n [BrowserEvent.TrackClick]: TrackInteractionEvent\n [BrowserEvent.TrackHover]: TrackInteractionEvent\n [BrowserEvent.TrackContextMenu]: TrackContextMenuEvent\n [BrowserEvent.ROIAdded]: { roi: ROI; set: ROISet }\n [BrowserEvent.ROIRemoved]: { roi: ROI; set: ROISet }\n [BrowserEvent.ROIChanged]: { roi: ROI; changes: Partial<ROI>; set: ROISet }\n [BrowserEvent.ROIClick]: ROIInteractionEvent\n [BrowserEvent.ROIContextMenu]: ROIInteractionEvent\n [BrowserEvent.ThemeChanged]: { theme: RenderTheme }\n}\n\n/** Internal bookkeeping for a track + optional data source. */\nexport interface ManagedTrack {\n /** Stable string identifier. Auto-generated on addTrack if not provided. */\n id: string\n track: Track\n dataSource: DataSource | null\n /** Serializable data source config — stored for session save/restore. */\n dataSourceConfig: DataSourceConfig | null\n /** Track name for session serialization. */\n name?: string\n /** Track ordering for session serialization. */\n order?: number\n /** Arbitrary key-value metadata (e.g., assay, biosample, tissue). */\n metadata?: Record<string, string>\n cache: FeatureCacheEntry | null\n abortController: AbortController | null\n /** Max visible height in pixels — enables scrollable container in DOM browser. */\n maxTrackHeight?: number\n}\n\nexport interface HeadlessGenomeBrowserOptions {\n locus: Locus\n /** Viewport width in CSS pixels. Required for headless; DOM browser reads from container. */\n viewportWidth?: number\n /** Canvas provider for environment abstraction. Default: DOMCanvasProvider. */\n canvasProvider?: CanvasProvider\n /** Worker provider for offloading CPU-intensive tasks. Default: main-thread execution. */\n workerProvider?: WorkerProvider\n /** Popup provider for rendering feature popups on click/hover. Default in GenomeBrowser: DefaultPopupProvider. Pass null to disable. */\n popupProvider?: PopupProvider | null\n /** Context menu provider for right-click menus. Default: DefaultContextMenuProvider. Pass null to disable. */\n contextMenuProvider?: ContextMenuProvider | null\n /** Unified render theme. Palette drives default colors/fonts for all tracks. */\n theme?: Partial<RenderTheme>\n /**\n * Genome assembly. Provides chromosome sizes, cumulative offsets, and sequence.\n * Default: hg38Genome. Pass null to disable clamping/sequence.\n */\n genome?: Genome | null\n /** Custom StateProjection subclass instance. Default: lazily created StateProjection. */\n stateProjection?: StateProjection\n}\n\n// ─── Convenience factory option types ────────────────────────────────────────\n\nexport interface AddRulerOptions {\n config?: Partial<RulerRenderConfig>\n /** Max visible height — enables scrollable container in DOM browser. */\n maxTrackHeight?: number\n}\n\nexport interface AddWigTrackOptions {\n config?: Partial<WigRenderConfig>\n /** Fixed pixel height (overrides config.height). */\n height?: number\n /** Background color. */\n background?: string\n /** Window function for BigWig summarization. Default: 'mean'. */\n windowFunction?: WindowFunction\n /** Max visible height — enables scrollable container in DOM browser. */\n maxTrackHeight?: number\n /** Track name for axis label. */\n name?: string\n /** Arbitrary key-value metadata (e.g., assay, biosample, tissue). */\n metadata?: Record<string, string>\n}\n\nexport interface AddGtxTrackOptions {\n /** Experiment ID within the GTX file. */\n experimentId: string\n config?: Partial<WigRenderConfig>\n /** Fixed pixel height (overrides config.height). */\n height?: number\n /** Background color. */\n background?: string\n /** Window function for summarization. Default: 'mean'. */\n windowFunction?: WindowFunction\n /** Max visible height — enables scrollable container in DOM browser. */\n maxTrackHeight?: number\n /** Track name for axis label. */\n name?: string\n /** Arbitrary key-value metadata (e.g., assay, biosample, tissue). */\n metadata?: Record<string, string>\n}\n\nexport interface AddSequenceTrackOptions {\n config?: Partial<SequenceRenderConfig>\n /** Max visible height — enables scrollable container in DOM browser. */\n maxTrackHeight?: number\n}\n\nexport interface AddBedTrackOptions {\n config?: Partial<AnnotationRenderConfig>\n /** Fixed pixel height. */\n height?: number\n /** Background color. */\n background?: string\n /** Explicit format override. When absent, inferred from URL. */\n format?: TextFileFormat\n /** Index URL override for tabix-indexed files. */\n indexURL?: string\n /** Whether the file is tabix-indexed. Auto-detected if absent. */\n indexed?: boolean\n /** Max visible height — enables scrollable container in DOM browser. */\n maxTrackHeight?: number\n /** Track name for axis label. */\n name?: string\n /** Arbitrary key-value metadata (e.g., assay, biosample, tissue). */\n metadata?: Record<string, string>\n}\n\nexport interface AddInteractionTrackOptions {\n config?: Partial<InteractionRenderConfig>\n /** Background color. */\n background?: string\n /** Explicit format override (e.g., 'bedpe', 'interact'). Inferred from URL if absent. */\n format?: TextFileFormat\n /** Index URL override for tabix-indexed files. */\n indexURL?: string\n /** Whether the file is tabix-indexed. Auto-detected if absent. */\n indexed?: boolean\n /** Track name for axis label. */\n name?: string\n /** Arbitrary key-value metadata (e.g., assay, biosample, tissue). */\n metadata?: Record<string, string>\n}\n\nexport interface AddAnnotationTrackOptions {\n config?: Partial<AnnotationRenderConfig>\n /** Fixed pixel height. */\n height?: number\n /** Background color. */\n background?: string\n /** Genome assembly for UCSC API. Default: 'hg38'. */\n genome?: string\n /** UCSC track name. Default: 'ncbiRefSeq'. */\n track?: string\n /** Max visible height — enables scrollable container in DOM browser. */\n maxTrackHeight?: number\n /** Track name for axis label. Default: 'Genes'. */\n name?: string\n /** Arbitrary key-value metadata (e.g., assay, biosample, tissue). */\n metadata?: Record<string, string>\n}\n\n/** Generate a unique track ID: \"{type}-{counter}\" or \"track-{counter}\" if type is unknown. */\nlet nextTrackId = 0\nfunction generateTrackId(type?: string): string {\n return `${type ?? 'track'}-${nextTrackId++}`\n}\n\nexport class HeadlessGenomeBrowser {\n protected _locus: Locus\n protected _viewportWidth: number\n protected managedTracks: ManagedTrack[] = []\n protected roiSets: ROISet[] = []\n /** Inflight fetch promises keyed by (cacheKey + fetchRegion + bpPerPixel) for deduplication. */\n private inflightFetches = new Map<string, { promise: Promise<unknown[]>; fetchRegion: Locus; bpPerPixel: number }>()\n\n /** Canvas provider for environment abstraction. Available for convenience API / future use. */\n readonly canvasProvider: CanvasProvider\n /** Worker provider for offloading CPU-intensive tasks. */\n readonly workerProvider?: WorkerProvider\n /** Popup provider for rendering feature popups on click/hover. */\n readonly popupProvider?: PopupProvider\n /** Context menu provider for right-click menus. */\n readonly contextMenuProvider?: ContextMenuProvider\n /** Resolved render theme. Available for track creation in convenience API. */\n private _theme: RenderTheme\n /**\n * Genome assembly. Provides chromosome sizes, cumulative offsets, and optional sequence.\n * Undefined when genome/clamping is disabled (null was passed).\n */\n readonly genome?: Genome\n /** Chromosome sizes for locus clamping. Derived from genome. Undefined when clamping is disabled. */\n readonly chromSizes?: ChromSizes\n /** Precomputed cumulative offsets for whole genome view. Derived from genome. Undefined when chromSizes is not set. */\n readonly cumulativeOffsets?: CumulativeOffsets\n /** Sequence provider for dynseq rendering on wig tracks. Derived from genome.sequence unless overridden. */\n readonly sequenceProvider?: SequenceProvider\n readonly events = new EventEmitter<BrowserEvents>()\n private _state?: StateProjection\n\n get theme(): RenderTheme { return this._theme }\n get locus(): Locus { return this._locus }\n get viewportWidth(): number { return this._viewportWidth }\n\n /** Agent-friendly state projection manager. Lazily created on first access. */\n get state(): StateProjection {\n if (!this._state) this._state = new StateProjection(this)\n return this._state\n }\n\n constructor(options: HeadlessGenomeBrowserOptions) {\n this.genome = options.genome === null ? undefined : (options.genome ?? hg38Genome)\n this.chromSizes = this.genome?.chromSizes\n this.cumulativeOffsets = this.genome?.cumulativeOffsets\n this.sequenceProvider = this.genome?.sequence\n\n this._locus = this.clamp({...options.locus})\n this._viewportWidth = options.viewportWidth ?? 0\n this.canvasProvider = options.canvasProvider ?? defaultCanvasProvider\n this.workerProvider = options.workerProvider\n this.popupProvider = options.popupProvider ?? undefined\n this.contextMenuProvider = options.contextMenuProvider ?? undefined\n this._theme = resolveTheme(options.theme)\n if (options.stateProjection) this._state = options.stateProjection\n }\n\n /** Clamp a locus to valid chromosome bounds. No-op if chromSizes is not set. */\n protected clamp(locus: Locus): Locus {\n return this.chromSizes ? clampLocus(locus, this.chromSizes, this.cumulativeOffsets) : locus\n }\n\n /** Subscribe to a browser event. Returns an unsubscribe function. */\n on<K extends keyof BrowserEvents>(event: K, handler: (data: BrowserEvents[K]) => void): () => void {\n return this.events.on(event, handler)\n }\n\n /** Unsubscribe from a browser event. */\n off<K extends keyof BrowserEvents>(event: K, handler?: (data: BrowserEvents[K]) => void): void {\n this.events.off(event, handler)\n }\n\n /**\n * Update the viewport width and re-render.\n * In headless mode, call this when the logical viewport size changes.\n * The DOM browser calls this automatically from ResizeObserver.\n */\n setViewportWidth(width: number): void {\n this._viewportWidth = width\n this.render()\n this.loadAllTracksIfNeeded()\n }\n\n /** Add a track with an optional data source for automatic data management. */\n addTrack<F>(track: Track, dataSource?: DataSource<F>, dataSourceConfig?: DataSourceConfig, maxTrackHeight?: number): string {\n const id = generateTrackId(track.type)\n const mt: ManagedTrack = {\n id,\n track,\n dataSource: (dataSource as DataSource | undefined) ?? null,\n dataSourceConfig: dataSourceConfig ?? null,\n cache: null,\n abortController: null,\n maxTrackHeight,\n }\n this.managedTracks.push(mt)\n track.setLocus(this._locus)\n\n this.events.emit(BrowserEvent.TrackAdded, {track})\n\n // Trigger initial data load if data source provided\n if (dataSource) {\n this.loadTrackWithDedup(mt)\n }\n\n return id\n }\n\n /** Remove a track by reference or by stable string ID. */\n removeTrack(trackOrId: Track | string): void {\n const idx = typeof trackOrId === 'string'\n ? this.managedTracks.findIndex(mt => mt.id === trackOrId)\n : this.managedTracks.findIndex(mt => mt.track === trackOrId)\n if (idx >= 0) {\n const mt = this.managedTracks[idx]\n if (mt.abortController) mt.abortController.abort()\n this.managedTracks.splice(idx, 1)\n this.events.emit(BrowserEvent.TrackRemoved, {track: mt.track})\n }\n }\n\n /**\n * Move a track to a new position in the track list.\n * Emits BrowserEvent.TrackOrderChanged with the new track order.\n */\n moveTrack(track: Track, toIndex: number): void {\n const fromIndex = this.managedTracks.findIndex(mt => mt.track === track)\n if (fromIndex < 0) return\n const clampedIndex = Math.max(0, Math.min(toIndex, this.managedTracks.length - 1))\n if (fromIndex === clampedIndex) return\n const [moved] = this.managedTracks.splice(fromIndex, 1)\n this.managedTracks.splice(clampedIndex, 0, moved)\n this.events.emit(BrowserEvent.TrackOrderChanged, {tracks: this.managedTracks.map(mt => mt.track)})\n }\n\n /** Get the current track order. */\n getTrackOrder(): Track[] {\n return this.managedTracks.map(mt => mt.track)\n }\n\n /** Find a managed track by its stable string ID. Returns undefined if not found. */\n getManagedTrack(id: string): ManagedTrack | undefined {\n return this.managedTracks.find(mt => mt.id === id)\n }\n\n /** Find a Track by its stable string ID. Returns undefined if not found. */\n getTrack(id: string): Track | undefined {\n return this.managedTracks.find(mt => mt.id === id)?.track\n }\n\n /** Get all managed tracks (read-only snapshot). */\n getManagedTracks(): readonly ManagedTrack[] {\n return this.managedTracks\n }\n\n /**\n * Find all managed tracks matching a selector.\n *\n * ```ts\n * browser.findTracks({ type: 'wig', where: { biosample: 'K562' } })\n * browser.findTracks({ name: 'H3K27ac' })\n * ```\n */\n findTracks(selector: TrackSelector): ManagedTrack[] {\n return selectTracks(this.managedTracks, selector)\n }\n\n /**\n * Remove all tracks matching a selector. Returns the number of tracks removed.\n *\n * ```ts\n * browser.removeTracks({ where: { assay: 'ATAC-seq' } }) // remove all ATAC-seq tracks\n * browser.removeTracks({ type: 'wig' }) // remove all wig tracks\n * ```\n */\n removeTracks(selector: TrackSelector): number {\n const matches = selectTracks(this.managedTracks, selector)\n for (const mt of matches) {\n this.removeTrack(mt.id)\n }\n return matches.length\n }\n\n /**\n * Merge metadata into all tracks matching a selector. Returns the number of tracks updated.\n * New keys are added; existing keys are overwritten.\n *\n * ```ts\n * browser.updateTrackMetadata({ type: 'wig' }, { project: 'ENCODE' })\n * ```\n */\n updateTrackMetadata(selector: TrackSelector, metadata: Record<string, string>): number {\n const matches = selectTracks(this.managedTracks, selector)\n for (const mt of matches) {\n mt.metadata = {...mt.metadata, ...metadata}\n }\n return matches.length\n }\n\n /** Update the locus and re-render all tracks. Clamped to chromosome bounds. */\n setLocus(locus: Locus): void {\n this._locus = this.clamp({...locus})\n for (const mt of this.managedTracks) {\n mt.track.setLocus(this._locus)\n }\n this.loadAllTracksIfNeeded()\n this.events.emit(BrowserEvent.LocusChange, {locus: this._locus})\n }\n\n /**\n * Parse a locus string and navigate to it.\n * e.g., \"chr17:7,668,000-7,688,000\"\n * Returns true if navigation succeeded.\n */\n search(query: string): boolean {\n const locus = parseLocus(query, this.cumulativeOffsets)\n if (!locus) return false\n this.setLocus(locus)\n return true\n }\n\n /** Zoom in by a factor (default 2x) around the center. */\n zoomIn(factor = 2): void {\n this.zoomByFactor(1 / factor)\n }\n\n /** Zoom out by a factor (default 2x) around the center. */\n zoomOut(factor = 2): void {\n this.zoomByFactor(factor)\n }\n\n private zoomByFactor(factor: number): void {\n this.zoomAroundCenter(factor)\n }\n\n /**\n * Zoom by a scale factor around an optional genomic coordinate.\n *\n * If `centerBP` is omitted, zooms around the viewport center (default).\n * When provided, the zoom keeps `centerBP` at the same relative position\n * in the viewport — e.g. for pointer-anchored pinch/wheel zoom.\n *\n * @param factor - Scale factor. <1 = zoom in, >1 = zoom out.\n * @param centerBP - Optional genomic coordinate to anchor the zoom on.\n */\n zoomAroundCenter(factor: number, centerBP?: number): void {\n // In WG mode, zooming is a no-op (matching igv.js behavior)\n if (isWholeGenomeView(this._locus)) return\n\n const center = centerBP ?? (this._locus.start + this._locus.end) / 2\n const currentSpan = this._locus.end - this._locus.start\n let newSpan = currentSpan * factor\n\n // Cap zoom-out at whole chromosome; transition to WG if at max\n if (factor > 1 && this.chromSizes && this._viewportWidth > 0) {\n const chromLength = this.chromSizes[this._locus.chr]\n if (chromLength != null) {\n if (newSpan >= chromLength && this.cumulativeOffsets) {\n // Already viewing full chromosome — transition to whole genome\n this.setLocus({chr: 'all', start: 0, end: this.cumulativeOffsets.totalLength})\n return\n }\n newSpan = Math.min(newSpan, chromLength)\n }\n }\n\n // When a center point is specified, preserve its fractional position\n // in the viewport. When not specified, zoom symmetrically around center.\n if (centerBP != null) {\n const frac = (centerBP - this._locus.start) / currentSpan\n this.setLocus({\n chr: this._locus.chr,\n start: centerBP - frac * newSpan,\n end: centerBP - frac * newSpan + newSpan,\n })\n } else {\n const halfSpan = newSpan / 2\n this.setLocus({\n chr: this._locus.chr,\n start: center - halfSpan,\n end: center + halfSpan,\n })\n }\n }\n\n /** Force a data reload for all managed tracks (e.g., after config change). */\n reloadData(): void {\n for (const mt of this.managedTracks) {\n if (mt.dataSource) {\n mt.cache = null\n }\n }\n this.loadAllTracksIfNeeded()\n }\n\n /** Get the cached features for a track, if available. */\n getCachedFeatures<F>(track: Track): F[] | undefined {\n const mt = this.managedTracks.find(m => m.track === track)\n return mt?.cache?.features as F[] | undefined\n }\n\n /** Re-render all tracks at current locus. */\n render(): void {\n if (this._viewportWidth === 0) return\n for (const mt of this.managedTracks) {\n try {\n mt.track.render()\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n console.error('[loom] Render error:', error)\n mt.track.setError(error)\n this.events.emit(BrowserEvent.RenderError, {track: mt.track, error})\n }\n }\n }\n\n // ─── ROI (Region of Interest) management ────────────────────────────────\n\n /**\n * Add a single ROI to a named set. Creates a user-defined set if it doesn't exist.\n * Returns the ROI (with generated ID if none provided).\n */\n addROI(roi: ROI, setName = 'User-defined'): ROI {\n let set = this.roiSets.find(s => s.name === setName)\n if (!set) {\n set = new ROISet({name: setName, isUserDefined: true, features: []})\n this.roiSets.push(set)\n }\n const added = set.addFeature(roi)\n this.events.emit(BrowserEvent.ROIAdded, {roi: added, set})\n return added\n }\n\n /** Add a full ROI set from config. Returns the created ROISet. */\n addROISet(config: ROISetConfig): ROISet {\n const set = new ROISet(config)\n this.roiSets.push(set)\n for (const roi of set.features) {\n this.events.emit(BrowserEvent.ROIAdded, {roi, set})\n }\n return set\n }\n\n /** Remove an ROI by ID (searches all sets). Returns true if found and removed. */\n removeROI(roiId: string): boolean {\n for (const set of this.roiSets) {\n const removed = set.removeFeature(roiId)\n if (removed) {\n this.events.emit(BrowserEvent.ROIRemoved, {roi: removed, set})\n return true\n }\n }\n return false\n }\n\n /** Update an ROI by ID. Returns the updated ROI, or undefined if not found. */\n updateROI(roiId: string, changes: Partial<Omit<ROI, 'id'>>): ROI | undefined {\n for (const set of this.roiSets) {\n const updated = set.updateFeature(roiId, changes)\n if (updated) {\n this.events.emit(BrowserEvent.ROIChanged, {roi: updated, changes, set})\n return updated\n }\n }\n return undefined\n }\n\n /** Remove all ROI sets. */\n clearROIs(): void {\n this.roiSets = []\n }\n\n /** Get all ROIs across all sets (flattened). */\n getROIs(): ROI[] {\n return this.roiSets.flatMap(s => [...s.features])\n }\n\n /** Get all ROI sets. */\n getROISets(): readonly ROISet[] {\n return this.roiSets\n }\n\n /** Find ROIs overlapping a genomic region (searches all sets). */\n findROIsAtLocus(chr: string, start: number, end: number): ROI[] {\n return this.roiSets.flatMap(s => s.getFeatures(chr, start, end))\n }\n\n /** Get ROIs visible in the current viewport. */\n getVisibleROIs(): ROI[] {\n return this.findROIsAtLocus(this._locus.chr, this._locus.start, this._locus.end)\n }\n\n // ─── SVG/PNG Export ─────────────────────────────────────────────────────\n\n /**\n * Export the current view as an SVG string.\n *\n * Creates a Canvas2SVG context, renders each track with clipped groups and\n * vertical offsets, and returns the serialized SVG. Named entities are\n * replaced with numeric equivalents for standalone SVG compatibility.\n *\n * Mirrors igv.js Browser.toSVG() (js/browser.ts lines 352-388).\n *\n * @param options.width — Override viewport width (defaults to current viewportWidth).\n * @param options.backdropColor — Background color (defaults to 'white').\n */\n toSVG(options?: { width?: number; backdropColor?: string }): string {\n const width = options?.width ?? this._viewportWidth\n if (width === 0) throw new Error('Cannot export SVG with zero viewport width')\n\n // Compute total height from all tracks\n let totalHeight = 0\n const trackHeights: number[] = []\n for (const mt of this.managedTracks) {\n const h = mt.track.height || 50 // fallback if not yet rendered\n trackHeights.push(h)\n totalHeight += h\n }\n\n const ctx = new C2S({\n width,\n height: totalHeight,\n viewbox: {x: 0, y: 0, width, height: totalHeight},\n backdropColor: options?.backdropColor ?? 'white',\n })\n\n // Render each track with vertical offset and clipping\n let y = 0\n for (let i = 0; i < this.managedTracks.length; i++) {\n const track = this.managedTracks[i].track\n const h = trackHeights[i]\n const id = `track_${i}_${track.type}`\n\n ctx.saveWithTranslationAndClipRect(id, 0, y, width, h, 0)\n if (track.renderToContext) {\n track.renderToContext(ctx as unknown as CanvasRenderingContext2D, width, h)\n }\n ctx.restore()\n y += h\n }\n\n // Render ROI overlays on top of all tracks\n const visibleROIs = this.getVisibleROIs()\n if (visibleROIs.length > 0) {\n const bpPerPixel = (this._locus.end - this._locus.start) / width\n const rc = {pixelWidth: width, bpStart: this._locus.start, bpPerPixel, viewportWidth: width}\n renderROIOverlays(\n ctx as unknown as CanvasRenderingContext2D,\n visibleROIs,\n rc,\n {totalHeight},\n )\n }\n\n ctx.setHeight(totalHeight)\n return ctx.getSerializedSvg(true)\n }\n\n // ─── Session serialization ─────────────────────────────────────────────\n\n /**\n * Serialize browser state to a SessionConfig.\n * Track configs are serialized via per-type serializers that drop\n * non-serializable values (functions, Promises) and only include\n * fields that differ from theme defaults.\n */\n toJSON(): SessionConfig {\n const tracks: TrackSessionConfig[] = []\n for (const mt of this.managedTracks) {\n const serialized = mt.track.serializeConfig(this.theme)\n // Merge in browser-level bookkeeping (id, name, order, metadata, data source)\n serialized.id = mt.id\n if (mt.name) serialized.name = mt.name\n if (mt.order != null) serialized.order = mt.order\n if (mt.metadata) serialized.metadata = mt.metadata\n if (mt.dataSourceConfig && 'dataSource' in serialized) {\n serialized.dataSource = mt.dataSourceConfig\n }\n tracks.push(serialized)\n }\n\n // Serialize genome config (only id for built-in genomes)\n const genomeConfig = this.genome\n ? {id: this.genome.id, name: this.genome.name}\n : undefined\n\n // Serialize ROI sets (only if non-empty)\n const rois = this.roiSets.length > 0\n ? this.roiSets.map(s => s.toJSON())\n : undefined\n\n return {\n version: SESSION_VERSION,\n locus: {...this._locus},\n viewportWidth: this._viewportWidth || undefined,\n genome: genomeConfig,\n tracks,\n rois,\n }\n }\n\n /**\n * Load a session, replacing all current tracks.\n * Disposes existing state, sets locus, and recreates tracks + data sources.\n *\n * Tracks are created headlessly (not attached to the DOM). Subclasses like\n * GenomeBrowser can override this to also attach track canvases to the DOM.\n */\n loadSession(session: SessionConfig, options?: CreateTrackFromSessionOptions): void {\n // Dispose existing state\n for (const mt of this.managedTracks) {\n if (mt.abortController) mt.abortController.abort()\n }\n this.managedTracks = []\n this.roiSets = []\n\n // Set locus\n this._locus = {...session.locus}\n if (session.viewportWidth) {\n this._viewportWidth = session.viewportWidth\n }\n\n // Recreate tracks from session config\n const trackOptions: CreateTrackFromSessionOptions = {\n canvasProvider: this.canvasProvider,\n workerProvider: this.workerProvider,\n theme: options?.theme,\n sequenceProvider: this.sequenceProvider,\n }\n\n for (const trackConfig of session.tracks) {\n const created = createTrackFromSession(trackConfig, this._locus, trackOptions)\n // Wire chromosome alias resolution for data sources that support it\n if (this.genome && created.dataSource) {\n if (created.dataSource instanceof BigWigDataSource || created.dataSource instanceof GtxDataSource) {\n created.dataSource.setChromNameResolver(alias => this.genome!.getChromosomeName(alias))\n } else if (created.dataSource instanceof TextFeatureSource) {\n created.dataSource.setChromNameResolver(alias => this.genome!.getChromosomeName(alias))\n if (this.cumulativeOffsets) {\n created.dataSource.setCumulativeOffsets(this.cumulativeOffsets)\n }\n }\n }\n this.addTrack(created.track, created.dataSource ?? undefined, created.dataSourceConfig ?? undefined)\n // Restore bookkeeping fields for round-trip serialization\n const mt = this.managedTracks[this.managedTracks.length - 1]\n if (trackConfig.id) mt.id = trackConfig.id\n if (created.name) mt.name = created.name\n if (created.order != null) mt.order = created.order\n if (trackConfig.metadata) mt.metadata = trackConfig.metadata\n }\n\n // Restore ROI sets\n if (session.rois) {\n for (const roiConfig of session.rois) {\n this.addROISet(roiConfig)\n }\n }\n\n this.events.emit(BrowserEvent.LocusChange, {locus: this._locus})\n }\n\n /**\n * Create a new HeadlessGenomeBrowser from a session config.\n * Creates the browser and loads all tracks from the session.\n */\n static fromSession(\n session: SessionConfig,\n options?: HeadlessGenomeBrowserOptions & CreateTrackFromSessionOptions,\n ): HeadlessGenomeBrowser {\n const browser = new HeadlessGenomeBrowser({\n locus: session.locus,\n viewportWidth: session.viewportWidth ?? options?.viewportWidth,\n canvasProvider: options?.canvasProvider,\n workerProvider: options?.workerProvider,\n theme: session.theme ?? options?.theme,\n })\n browser.loadSession(session, options)\n return browser\n }\n\n // ─── Generic track creation from config ─────────────────────────────────\n\n /**\n * Add a track from a session config using the track registry.\n *\n * Mirrors igv.js `Browser.createTrack(config)` (js/browser.ts lines 1074-1151)\n * which resolves type aliases via `getTrack()` and instantiates through the\n * track factory. Our version delegates to `createTrackFromConfig()` in the\n * registry, then registers the created track with this browser's data lifecycle.\n *\n * This is the generic entry point — the convenience methods below\n * (addRuler, addWigTrack, addGeneTrack) are sugar for common cases.\n */\n addTrackFromConfig(trackConfig: TrackSessionConfig): Track {\n const created = createTrackFromConfig(trackConfig, this._locus, {\n canvasProvider: this.canvasProvider,\n workerProvider: this.workerProvider,\n theme: this.theme,\n sequenceProvider: this.sequenceProvider,\n })\n // Wire chromosome alias resolution for data sources that support it\n if (this.genome && created.dataSource) {\n if (created.dataSource instanceof BigWigDataSource) {\n created.dataSource.setChromNameResolver(alias => this.genome!.getChromosomeName(alias))\n } else if (created.dataSource instanceof TextFeatureSource) {\n created.dataSource.setChromNameResolver(alias => this.genome!.getChromosomeName(alias))\n if (this.cumulativeOffsets) {\n created.dataSource.setCumulativeOffsets(this.cumulativeOffsets)\n }\n }\n }\n this.addTrack(created.track, created.dataSource ?? undefined, created.dataSourceConfig ?? undefined)\n const mt = this.managedTracks[this.managedTracks.length - 1]\n if (trackConfig.id) mt.id = trackConfig.id\n if (created.name) mt.name = created.name\n if (created.order != null) mt.order = created.order\n if (trackConfig.metadata) mt.metadata = trackConfig.metadata\n return created.track\n }\n\n // ─── Convenience factories ────────────────────────────────────────────\n\n /** Add a ruler track. */\n addRuler(options?: AddRulerOptions): RulerTrackCanvas {\n const {canvas} = this.canvasProvider.createCanvas(0, 0)\n const track = new RulerTrackCanvas(canvas, {\n locus: this._locus,\n config: options?.config,\n theme: this.theme,\n canvasProvider: this.canvasProvider,\n cumulativeOffsets: this.cumulativeOffsets,\n chromSizes: this.chromSizes,\n })\n this.addTrack(track, undefined, undefined, options?.maxTrackHeight)\n return track\n }\n\n /** Add a BigWig signal track. */\n addWigTrack(url: string, options?: AddWigTrackOptions): WigTrackCanvas {\n const {canvas} = this.canvasProvider.createCanvas(0, 0)\n const windowFunction = options?.windowFunction ?? 'mean'\n const track = new WigTrackCanvas(canvas, {\n locus: this._locus,\n features: [],\n config: options?.config,\n height: options?.height,\n background: options?.background,\n theme: this.theme,\n canvasProvider: this.canvasProvider,\n name: options?.name,\n sequenceProvider: this.sequenceProvider,\n })\n const dataSource = new BigWigDataSource(url, windowFunction, this.workerProvider)\n if (this.cumulativeOffsets) {\n dataSource.setCumulativeOffsets(this.cumulativeOffsets)\n }\n if (this.genome) {\n dataSource.setChromNameResolver(alias => this.genome!.getChromosomeName(alias))\n }\n const dataSourceConfig: BigWigDataSourceConfig = {\n type: 'bigwig', url, windowFunction,\n }\n this.addTrack(track, dataSource, dataSourceConfig, options?.maxTrackHeight)\n if (options?.metadata) this.managedTracks[this.managedTracks.length - 1].metadata = options.metadata\n\n // Wire windowing function callback: update data source, invalidate cache, re-fetch\n track.onWindowFunctionChange = (wf) => {\n dataSource.setWindowFunction(wf)\n const mt = this.managedTracks.find(m => m.track === track)\n if (mt) {\n mt.cache = null\n if (mt.dataSourceConfig && mt.dataSourceConfig.type === 'bigwig') {\n (mt.dataSourceConfig as BigWigDataSourceConfig).windowFunction = wf\n }\n }\n this.loadAllTracksIfNeeded()\n }\n\n return track\n }\n\n /** Add a GTX signal track (single experiment from a multi-experiment GTX file). */\n addGtxTrack(url: string, options: AddGtxTrackOptions): WigTrackCanvas {\n const {canvas} = this.canvasProvider.createCanvas(0, 0)\n const windowFunction = options.windowFunction ?? 'mean'\n const track = new WigTrackCanvas(canvas, {\n locus: this._locus,\n features: [],\n config: options.config,\n height: options.height,\n background: options.background,\n theme: this.theme,\n canvasProvider: this.canvasProvider,\n name: options.name,\n sequenceProvider: this.sequenceProvider,\n })\n const dataSource = new GtxDataSource(url, options.experimentId, windowFunction, this.workerProvider)\n if (this.cumulativeOffsets) {\n dataSource.setCumulativeOffsets(this.cumulativeOffsets)\n }\n if (this.genome) {\n dataSource.setChromNameResolver(alias => this.genome!.getChromosomeName(alias))\n }\n const dataSourceConfig: GtxDataSourceConfig = {\n type: 'gtx', url, experimentId: options.experimentId, windowFunction,\n }\n this.addTrack(track, dataSource, dataSourceConfig, options.maxTrackHeight)\n if (options.metadata) this.managedTracks[this.managedTracks.length - 1].metadata = options.metadata\n\n // Wire windowing function callback\n track.onWindowFunctionChange = (wf) => {\n dataSource.setWindowFunction(wf)\n const mt = this.managedTracks.find(m => m.track === track)\n if (mt) {\n mt.cache = null\n if (mt.dataSourceConfig && mt.dataSourceConfig.type === 'gtx') {\n (mt.dataSourceConfig as GtxDataSourceConfig).windowFunction = wf\n }\n }\n this.loadAllTracksIfNeeded()\n }\n\n return track\n }\n\n /** Add a UCSC gene annotation track. */\n addGeneTrack(options?: AddAnnotationTrackOptions): AnnotationTrackCanvas {\n const {canvas} = this.canvasProvider.createCanvas(0, 0)\n const track = new AnnotationTrackCanvas(canvas, {\n locus: this._locus,\n features: [],\n config: options?.config,\n height: options?.height,\n background: options?.background,\n theme: this.theme,\n canvasProvider: this.canvasProvider,\n workerProvider: this.workerProvider,\n name: options?.name ?? 'Genes',\n })\n const genome = options?.genome\n const ucscTrack = options?.track\n const dataSource = new GeneDataSource({genome, track: ucscTrack})\n if (this.cumulativeOffsets) {\n dataSource.setCumulativeOffsets(this.cumulativeOffsets)\n }\n const dataSourceConfig: UCSCDataSourceConfig = {\n type: 'ucsc', genome, track: ucscTrack,\n }\n this.addTrack(track, dataSource, dataSourceConfig, options?.maxTrackHeight)\n if (options?.metadata) this.managedTracks[this.managedTracks.length - 1].metadata = options.metadata\n return track\n }\n\n /** Add a BED/peak annotation track from a URL. Supports plain text and tabix-indexed files. */\n addBedTrack(url: string, options?: AddBedTrackOptions): AnnotationTrackCanvas {\n const {canvas} = this.canvasProvider.createCanvas(0, 0)\n const format = options?.format as TextFileFormat | undefined\n const track = new AnnotationTrackCanvas(canvas, {\n locus: this._locus,\n features: [],\n config: options?.config,\n height: options?.height,\n background: options?.background,\n theme: this.theme,\n canvasProvider: this.canvasProvider,\n workerProvider: this.workerProvider,\n name: options?.name,\n })\n const dataSource = new TextFeatureSource({\n url,\n format,\n indexURL: options?.indexURL,\n indexed: options?.indexed,\n workerProvider: this.workerProvider,\n })\n if (this.genome) {\n dataSource.setChromNameResolver(alias => this.genome!.getChromosomeName(alias))\n }\n if (this.cumulativeOffsets) {\n dataSource.setCumulativeOffsets(this.cumulativeOffsets)\n }\n const dataSourceConfig: TextDataSourceConfig = {\n type: 'text', url, format, indexURL: options?.indexURL, indexed: options?.indexed,\n }\n this.addTrack(track, dataSource, dataSourceConfig, options?.maxTrackHeight)\n if (options?.metadata) this.managedTracks[this.managedTracks.length - 1].metadata = options.metadata\n return track\n }\n\n /** Add an interaction (arc/BEDPE) track from a URL. */\n addInteractionTrack(url: string, options?: AddInteractionTrackOptions): InteractionTrackCanvas {\n const {canvas} = this.canvasProvider.createCanvas(0, 0)\n const format = options?.format as TextFileFormat | undefined\n const track = new InteractionTrackCanvas(canvas, {\n locus: this._locus,\n features: [],\n config: options?.config,\n background: options?.background,\n theme: this.theme,\n canvasProvider: this.canvasProvider,\n name: options?.name,\n })\n const dataSource = new TextFeatureSource({\n url,\n format,\n indexURL: options?.indexURL,\n indexed: options?.indexed,\n workerProvider: this.workerProvider,\n })\n if (this.genome) {\n dataSource.setChromNameResolver(alias => this.genome!.getChromosomeName(alias))\n }\n if (this.cumulativeOffsets) {\n dataSource.setCumulativeOffsets(this.cumulativeOffsets)\n }\n const dataSourceConfig: TextDataSourceConfig = {\n type: 'text', url, format, indexURL: options?.indexURL, indexed: options?.indexed,\n }\n this.addTrack(track, dataSource, dataSourceConfig)\n if (options?.metadata) this.managedTracks[this.managedTracks.length - 1].metadata = options.metadata\n return track\n }\n\n /** Add a DNA/RNA sequence track. Data fetching is handled automatically via the genome's sequence provider. */\n addSequenceTrack(options?: AddSequenceTrackOptions): SequenceTrackCanvas {\n const trackConfig: SequenceTrackSessionConfig = {type: 'sequence', config: options?.config}\n const track = this.addTrackFromConfig(trackConfig) as SequenceTrackCanvas\n if (options?.maxTrackHeight != null) {\n const mt = this.managedTracks.find(m => m.track === track)\n if (mt) mt.maxTrackHeight = options.maxTrackHeight\n }\n return track\n }\n\n /** Apply a new render theme to the browser and all existing tracks. */\n setTheme(theme: Partial<RenderTheme>): void {\n this._theme = resolveTheme(theme)\n for (const mt of this.managedTracks) {\n mt.track.setTheme(this._theme)\n }\n this.events.emit(BrowserEvent.ThemeChanged, {theme: this._theme})\n }\n\n /** Clean up event listeners, abort in-flight requests, clear tracks and ROIs. */\n dispose(): void {\n this.events.removeAllListeners()\n if (this.popupProvider) this.popupProvider.dispose()\n if (this.contextMenuProvider) this.contextMenuProvider.dispose()\n for (const mt of this.managedTracks) {\n if (mt.abortController) mt.abortController.abort()\n }\n this.managedTracks = []\n this.roiSets = []\n }\n\n // ─── Interaction resolution ────────────────────────────────────────────\n\n /**\n * Resolve pixel coordinates on a track canvas to interaction data.\n * Used by GenomeBrowser to build event payloads from pointer events.\n * Returns null if the track has no features at the given point.\n */\n protected resolveInteraction(track: Track, x: number, y: number): TrackInteractionEvent | null {\n const results = track.hitTest(x, y)\n if (results.length === 0) return null\n\n const width = track.canvas.clientWidth\n const bpPerPixel = width > 0 ? (this._locus.end - this._locus.start) / width : 0\n const genomicLocation = this._locus.start + x * bpPerPixel\n\n return {\n track,\n genomicLocation,\n features: results.map(r => r.feature),\n popupData: results.flatMap(r => r.popupData),\n x,\n y,\n }\n }\n\n // ─── Data lifecycle ──────────────────────────────────────────────────────\n\n protected loadAllTracksIfNeeded(): void {\n // Clear stale inflight entries — navigation invalidates all pending fetches\n this.inflightFetches.clear()\n\n for (const mt of this.managedTracks) {\n if (mt.dataSource) {\n this.loadTrackWithDedup(mt)\n }\n }\n }\n\n /**\n * Load data for a single track, deduplicating against inflight fetches\n * from other tracks with the same data source identity.\n *\n * Works for both initial addTrack() loads and bulk loadAllTracksIfNeeded() calls.\n */\n private loadTrackWithDedup(mt: ManagedTrack): void {\n const width = this._viewportWidth\n if (width === 0) return\n const bpPerPixel = (this._locus.end - this._locus.start) / width\n\n // Visibility window check — mirrors igv.js checkZoomIn() in js/trackViewport.ts.\n const vw = mt.track.visibilityWindow\n const beyondVisibilityWindow = vw != null && vw > 0 && bpPerPixel * width > vw\n if ('setZoomedOut' in mt.track && typeof (mt.track as {setZoomedOut: (v: boolean) => void}).setZoomedOut === 'function') {\n (mt.track as {setZoomedOut: (v: boolean) => void}).setZoomedOut(beyondVisibilityWindow)\n }\n if (beyondVisibilityWindow) {\n if (mt.abortController) {\n mt.abortController.abort()\n mt.abortController = null\n }\n return\n }\n\n // Cache hit — no fetch needed\n if (mt.cache && cacheCoversViewport(mt.cache, this._locus, bpPerPixel)) {\n return\n }\n\n // Cancel stale in-flight request for this track\n if (mt.abortController) mt.abortController.abort()\n\n const fetchRegion = bufferLocus(this._locus)\n const dsKey = mt.dataSourceConfig ? dataSourceCacheKey(mt.dataSourceConfig) : null\n\n // Check if another track with the same data source already has a valid cache\n if (dsKey) {\n for (const other of this.managedTracks) {\n if (other === mt || !other.dataSourceConfig || !other.cache) continue\n if (dataSourceCacheKey(other.dataSourceConfig) === dsKey\n && cacheCoversViewport(other.cache, this._locus, bpPerPixel)) {\n mt.cache = other.cache\n mt.abortController = null\n mt.track.setError(null)\n const track = mt.track as DataDrivenTrack\n if (typeof track.setFeatures === 'function') {\n track.setFeatures(other.cache.features)\n }\n this.events.emit(BrowserEvent.DataLoaded, {track: mt.track})\n return\n }\n }\n }\n\n // Check for an inflight fetch from another track with the same data source\n const inflightKey = dsKey ? `${dsKey}|${fetchRegion.chr}:${fetchRegion.start}-${fetchRegion.end}|${bpPerPixel}` : null\n const inflight = inflightKey ? this.inflightFetches.get(inflightKey) : null\n\n if (inflight) {\n // Reuse the existing inflight fetch — no new network request\n mt.abortController = null // no independent abort — rides on the existing fetch\n inflight.promise\n .then(features => {\n mt.cache = {locus: inflight.fetchRegion, bpPerPixel: inflight.bpPerPixel, features}\n mt.track.setError(null)\n const track = mt.track as DataDrivenTrack\n if (typeof track.setFeatures === 'function') {\n track.setFeatures(features)\n }\n this.events.emit(BrowserEvent.DataLoaded, {track: mt.track})\n })\n .catch(err => {\n // AbortErrors propagate from the source track's abort — ignore them\n if (err instanceof DOMException && err.name === 'AbortError') return\n const error = err instanceof Error ? err : new Error(String(err))\n console.error('[loom] Data fetch error (dedup):', error)\n mt.track.setError(error)\n this.events.emit(BrowserEvent.DataError, {track: mt.track, error})\n })\n return\n }\n\n // No inflight match — start a new fetch\n const controller = new AbortController()\n mt.abortController = controller\n\n const promise = mt.dataSource!.fetch(fetchRegion, bpPerPixel, controller.signal)\n\n // Register in inflight map for dedup by subsequent tracks\n if (inflightKey) {\n this.inflightFetches.set(inflightKey, {promise, fetchRegion, bpPerPixel})\n }\n\n promise\n .then(features => {\n if (controller.signal.aborted) return\n mt.cache = {locus: fetchRegion, bpPerPixel, features}\n mt.abortController = null\n mt.track.setError(null)\n const track = mt.track as DataDrivenTrack\n if (typeof track.setFeatures === 'function') {\n track.setFeatures(features)\n }\n this.events.emit(BrowserEvent.DataLoaded, {track: mt.track})\n })\n .catch(err => {\n if (!controller.signal.aborted) {\n const error = err instanceof Error ? err : new Error(String(err))\n console.error('[loom] Data fetch error:', error)\n mt.track.setError(error)\n this.events.emit(BrowserEvent.DataError, {track: mt.track, error})\n }\n })\n .finally(() => {\n // Clean up inflight entry (only if it's still our entry)\n if (inflightKey && this.inflightFetches.get(inflightKey)?.promise === promise) {\n this.inflightFetches.delete(inflightKey)\n }\n })\n }\n}\n","/**\n * CommandDispatcher — transport-agnostic command dispatch for HeadlessGenomeBrowser.\n *\n * Maps a vocabulary of 8 commands (discriminated union on `command` field) to\n * browser method calls. Designed for reuse across WebSocket (remoteProtocol.ts)\n * and future MCP transport.\n *\n * Follows the discriminated-union + result-map pattern from workerProvider.ts.\n */\n\nimport {BrowserEvent} from './headlessGenomeBrowser'\nimport type {HeadlessGenomeBrowser, ManagedTrack} from './headlessGenomeBrowser'\nimport type {\n ROI, ROISetConfig, TrackSessionConfig, SessionConfig,\n} from './types'\nimport type {TrackSelector} from './trackSelector'\nimport type {ProjectedState, TrackSummary, StateDiff} from './stateProjection'\nimport {dataSourceCacheKey} from './dataSources/dataSourceCacheKey'\n\n// ─── Error ──────────────────────────────────────────────────────────────────\n\nexport type CommandErrorCode =\n | 'UNKNOWN_COMMAND'\n | 'INVALID_ARGS'\n | 'TRACK_NOT_FOUND'\n | 'NOT_IMPLEMENTED'\n | 'EXPORT_UNAVAILABLE'\n | 'NAVIGATION_FAILED'\n | 'INTERNAL_ERROR'\n\nexport class CommandError extends Error {\n constructor(\n public readonly code: CommandErrorCode,\n message: string,\n ) {\n super(message)\n this.name = 'CommandError'\n }\n}\n\n// ─── Wire-safe TrackSelector ────────────────────────────────────────────────\n\n/** JSON-serializable variant of TrackSelector. */\nexport interface WireTrackSelector {\n /** Exact match against track ID. */\n id?: string\n /** Case-insensitive substring match against track name. */\n name?: string\n /** Regex pattern string — converted to RegExp(pattern, 'i'). Takes precedence over `name`. */\n nameRegex?: string\n /** Exact match against track type (e.g. 'wig', 'annotation', 'interact'). */\n type?: string\n /** Metadata key-value matching. AND semantics. */\n where?: Record<string, string>\n}\n\n/** Convert wire selector to internal TrackSelector. */\nexport function toTrackSelector(wire: WireTrackSelector): TrackSelector {\n const selector: TrackSelector = {}\n if (wire.id !== undefined) selector.id = wire.id\n if (wire.nameRegex !== undefined) {\n selector.name = new RegExp(wire.nameRegex, 'i')\n } else if (wire.name !== undefined) {\n selector.name = wire.name\n }\n if (wire.type !== undefined) selector.type = wire.type\n if (wire.where !== undefined) selector.where = wire.where\n return selector\n}\n\n// ─── Command argument types (discriminated union) ───────────────────────────\n\nexport interface GetBrowserStateArgs {\n command: 'get_browser_state'\n /** Record state under this snapshot key for future diff() calls. */\n record?: string\n}\n\nexport interface NavigateArgs {\n command: 'navigate'\n /** Locus string (e.g. \"chr17:7,668,000-7,688,000\" or gene name \"TP53\"). */\n locus?: string\n /** Zoom direction. */\n zoom?: 'in' | 'out'\n /** Zoom factor (default 2). */\n factor?: number\n}\n\nexport interface ModifyTracksArgs {\n command: 'modify_tracks'\n actions: ModifyTrackAction[]\n}\n\nexport type ModifyTrackAction =\n | { action: 'add'; config: TrackSessionConfig }\n | { action: 'remove'; selector: WireTrackSelector }\n | { action: 'find'; selector: WireTrackSelector }\n | { action: 'update_metadata'; selector: WireTrackSelector; metadata: Record<string, string> }\n\nexport interface QueryFeaturesArgs {\n command: 'query_features'\n /** Track ID to query. */\n trackId: string\n /** If true, return a feature summary instead of raw features. */\n summarize?: boolean\n}\n\nexport interface AnnotateArgs {\n command: 'annotate'\n}\n\nexport interface SetLayoutArgs {\n command: 'set_layout'\n /** Desired track configuration. Reconciler diffs against current state. */\n tracks: TrackSessionConfig[]\n /** If provided, navigate to this locus. */\n locus?: string\n}\n\nexport interface ExportViewArgs {\n command: 'export_view'\n format: 'svg' | 'png' | 'session'\n /** Override width in pixels. */\n width?: number\n}\n\nexport interface ManageROIsArgs {\n command: 'manage_rois'\n action: ROIAction\n}\n\nexport type ROIAction =\n | { action: 'add'; roi: ROI; setName?: string }\n | { action: 'remove'; roiId: string }\n | { action: 'update'; roiId: string; changes: Partial<Omit<ROI, 'id'>> }\n | { action: 'clear' }\n | { action: 'list' }\n | { action: 'list_sets' }\n | { action: 'find_at_locus'; chr: string; start: number; end: number }\n | { action: 'get_visible' }\n\nexport interface SubscribeEventsArgs {\n command: 'subscribe_events'\n /** Event names to subscribe to. Use `['*']` for all events, `[]` for none. */\n events: string[]\n}\n\nexport type CommandArgs =\n | GetBrowserStateArgs\n | NavigateArgs\n | ModifyTracksArgs\n | QueryFeaturesArgs\n | AnnotateArgs\n | SetLayoutArgs\n | ExportViewArgs\n | ManageROIsArgs\n | SubscribeEventsArgs\n\n// ─── Result types ───────────────────────────────────────────────────────────\n\nexport interface ModifyTrackActionResult {\n action: string\n success: boolean\n trackId?: string\n tracks?: TrackSummary[]\n count?: number\n error?: string\n}\n\nexport interface ModifyTracksResult {\n results: ModifyTrackActionResult[]\n}\n\nexport interface QueryFeaturesResult {\n trackId: string\n featureCount: number\n features?: unknown[]\n summary?: unknown\n}\n\nexport interface SetLayoutResult {\n added: string[]\n removed: string[]\n unchanged: string[]\n}\n\nexport type ManageROIsResult =\n | { action: 'add'; roi: ROI }\n | { action: 'remove'; success: boolean }\n | { action: 'update'; roi: ROI | undefined }\n | { action: 'clear' }\n | { action: 'list'; rois: ROI[] }\n | { action: 'list_sets'; sets: ROISetConfig[] }\n | { action: 'find_at_locus'; rois: ROI[] }\n | { action: 'get_visible'; rois: ROI[] }\n\nexport interface SubscribeEventsResult {\n subscribed: string[]\n}\n\nexport interface CommandResultMap {\n get_browser_state: ProjectedState\n navigate: boolean\n modify_tracks: ModifyTracksResult\n query_features: QueryFeaturesResult\n annotate: never\n set_layout: SetLayoutResult\n export_view: string | SessionConfig\n manage_rois: ManageROIsResult\n subscribe_events: SubscribeEventsResult\n}\n\n// ─── Dispatcher options ─────────────────────────────────────────────────────\n\nexport interface CommandDispatcherOptions {\n /** Whether the browser supports PNG export (true for DOM GenomeBrowser). */\n supportsPNG?: boolean\n /** Custom PNG exporter — called when format is 'png'. Allows GenomeBrowser to inject toPNG(). */\n exportPNG?: () => Promise<string>\n /** Callback when agent subscribes to events. Used by RemoteConnection to filter forwarding. */\n onSubscribeEvents?: (events: string[]) => void\n}\n\n// ─── CommandDispatcher ──────────────────────────────────────────────────────\n\nexport class CommandDispatcher {\n private browser: HeadlessGenomeBrowser\n private options: CommandDispatcherOptions\n\n constructor(browser: HeadlessGenomeBrowser, options?: CommandDispatcherOptions) {\n this.browser = browser\n this.options = options ?? {}\n }\n\n /** Dispatch a command to the appropriate handler. */\n async dispatch(args: GetBrowserStateArgs): Promise<ProjectedState>\n async dispatch(args: NavigateArgs): Promise<boolean>\n async dispatch(args: ModifyTracksArgs): Promise<ModifyTracksResult>\n async dispatch(args: QueryFeaturesArgs): Promise<QueryFeaturesResult>\n async dispatch(args: AnnotateArgs): Promise<never>\n async dispatch(args: SetLayoutArgs): Promise<SetLayoutResult>\n async dispatch(args: ExportViewArgs): Promise<string | SessionConfig>\n async dispatch(args: ManageROIsArgs): Promise<ManageROIsResult>\n async dispatch(args: SubscribeEventsArgs): Promise<SubscribeEventsResult>\n async dispatch(args: CommandArgs): Promise<CommandResultMap[CommandArgs['command']]>\n async dispatch(args: CommandArgs): Promise<CommandResultMap[CommandArgs['command']]> {\n switch (args.command) {\n case 'get_browser_state': return this.handleGetState(args)\n case 'navigate': return this.handleNavigate(args)\n case 'modify_tracks': return this.handleModifyTracks(args)\n case 'query_features': return this.handleQueryFeatures(args)\n case 'annotate': return this.handleAnnotate()\n case 'set_layout': return this.handleSetLayout(args)\n case 'export_view': return this.handleExportView(args)\n case 'manage_rois': return this.handleManageROIs(args)\n case 'subscribe_events': return this.handleSubscribeEvents(args)\n default:\n throw new CommandError('UNKNOWN_COMMAND', `Unknown command: ${(args as unknown as Record<string, unknown>).command}`)\n }\n }\n\n // ─── Handlers ───────────────────────────────────────────────────────────\n\n private handleGetState(args: GetBrowserStateArgs): ProjectedState {\n return this.browser.state.getState(args.record ? {record: args.record} : undefined)\n }\n\n private handleNavigate(args: NavigateArgs): boolean {\n if (!args.locus && !args.zoom) {\n throw new CommandError('INVALID_ARGS', 'navigate requires at least one of: locus, zoom')\n }\n\n let result = true\n\n if (args.locus) {\n const ok = this.browser.search(args.locus)\n if (!ok) {\n throw new CommandError('NAVIGATION_FAILED', `Could not parse locus: \"${args.locus}\"`)\n }\n result = ok\n }\n\n if (args.zoom === 'in') {\n this.browser.zoomIn(args.factor)\n } else if (args.zoom === 'out') {\n this.browser.zoomOut(args.factor)\n }\n\n return result\n }\n\n private handleModifyTracks(args: ModifyTracksArgs): ModifyTracksResult {\n if (!args.actions || args.actions.length === 0) {\n throw new CommandError('INVALID_ARGS', 'modify_tracks requires at least one action')\n }\n\n const results: ModifyTrackActionResult[] = []\n\n for (const action of args.actions) {\n switch (action.action) {\n case 'add': {\n const track = this.browser.addTrackFromConfig(action.config)\n const mt = this.browser.getManagedTracks().find(m => m.track === track)\n results.push({\n action: 'add',\n success: true,\n trackId: mt?.id,\n })\n break\n }\n case 'remove': {\n const count = this.browser.removeTracks(toTrackSelector(action.selector))\n results.push({action: 'remove', success: count > 0, count})\n break\n }\n case 'find': {\n const found = this.browser.findTracks(toTrackSelector(action.selector))\n const summaries = found.map(mt => managedTrackToSummary(mt))\n results.push({action: 'find', success: true, tracks: summaries})\n break\n }\n case 'update_metadata': {\n const count = this.browser.updateTrackMetadata(\n toTrackSelector(action.selector),\n action.metadata,\n )\n results.push({action: 'update_metadata', success: count > 0, count})\n break\n }\n default:\n results.push({\n action: (action as Record<string, unknown>).action as string,\n success: false,\n error: `Unknown action: ${(action as Record<string, unknown>).action}`,\n })\n }\n }\n\n return {results}\n }\n\n private handleQueryFeatures(args: QueryFeaturesArgs): QueryFeaturesResult {\n const track = this.browser.getTrack(args.trackId)\n if (!track) {\n throw new CommandError('TRACK_NOT_FOUND', `No track with id '${args.trackId}'`)\n }\n\n const features = this.browser.getCachedFeatures(track) ?? []\n\n if (args.summarize) {\n // Use the state projection to get the feature summary\n const state = this.browser.state.getState()\n const trackSummary = state.tracks.find(t => t.id === args.trackId)\n return {\n trackId: args.trackId,\n featureCount: features.length,\n summary: trackSummary?.featureSummary,\n }\n }\n\n return {\n trackId: args.trackId,\n featureCount: features.length,\n features,\n }\n }\n\n private handleAnnotate(): never {\n throw new CommandError('NOT_IMPLEMENTED', 'Annotations are not yet supported (Phase 3)')\n }\n\n private handleSetLayout(args: SetLayoutArgs): SetLayoutResult {\n if (!args.tracks) {\n throw new CommandError('INVALID_ARGS', 'set_layout requires a tracks array')\n }\n\n const currentTracks = [...this.browser.getManagedTracks()]\n const matched = new Set<string>() // IDs of current tracks that match a desired track\n const toAdd: TrackSessionConfig[] = []\n const unchanged: string[] = []\n\n // Pass 1: match desired tracks to current tracks\n for (const desired of args.tracks) {\n const match = this.findMatchingTrack(desired, currentTracks, matched)\n if (match) {\n matched.add(match.id)\n unchanged.push(match.id)\n } else {\n toAdd.push(desired)\n }\n }\n\n // Pass 2: remove unmatched current tracks\n const removed: string[] = []\n for (const mt of currentTracks) {\n if (!matched.has(mt.id)) {\n this.browser.removeTrack(mt.id)\n removed.push(mt.id)\n }\n }\n\n // Pass 3: add new tracks\n const added: string[] = []\n for (const config of toAdd) {\n const track = this.browser.addTrackFromConfig(config)\n const mt = this.browser.getManagedTracks().find(m => m.track === track)\n if (mt) added.push(mt.id)\n }\n\n // Optional navigation\n if (args.locus) {\n this.browser.search(args.locus)\n }\n\n return {added, removed, unchanged}\n }\n\n /** Find a current track that matches a desired config. */\n private findMatchingTrack(\n desired: TrackSessionConfig,\n current: readonly ManagedTrack[],\n alreadyMatched: Set<string>,\n ): ManagedTrack | undefined {\n // First: match by explicit ID\n if (desired.id) {\n return current.find(mt => mt.id === desired.id && !alreadyMatched.has(mt.id))\n }\n\n // Second: match by type + data source cache key\n const desiredKey = this.layoutMatchKey(desired)\n return current.find(mt => {\n if (alreadyMatched.has(mt.id)) return false\n if (mt.track.type !== desired.type) return false\n if (!mt.dataSourceConfig) return !desiredKey\n return desiredKey === dataSourceCacheKey(mt.dataSourceConfig)\n })\n }\n\n /** Compute a stable match key from a track session config's data source. */\n private layoutMatchKey(config: TrackSessionConfig): string | undefined {\n if ('dataSource' in config && config.dataSource) {\n return dataSourceCacheKey(config.dataSource)\n }\n return undefined\n }\n\n private async handleExportView(args: ExportViewArgs): Promise<string | SessionConfig> {\n switch (args.format) {\n case 'svg':\n return this.browser.toSVG(args.width ? {width: args.width} : undefined)\n case 'png': {\n if (!this.options.supportsPNG || !this.options.exportPNG) {\n throw new CommandError(\n 'EXPORT_UNAVAILABLE',\n 'PNG export requires a DOM-attached GenomeBrowser',\n )\n }\n return this.options.exportPNG()\n }\n case 'session':\n return this.browser.toJSON()\n default:\n throw new CommandError('INVALID_ARGS', `Unknown export format: ${args.format}`)\n }\n }\n\n private handleManageROIs(args: ManageROIsArgs): ManageROIsResult {\n const {action} = args\n switch (action.action) {\n case 'add':\n return {action: 'add', roi: this.browser.addROI(action.roi, action.setName)}\n case 'remove':\n return {action: 'remove', success: this.browser.removeROI(action.roiId)}\n case 'update':\n return {action: 'update', roi: this.browser.updateROI(action.roiId, action.changes)}\n case 'clear':\n this.browser.clearROIs()\n return {action: 'clear'}\n case 'list':\n return {action: 'list', rois: this.browser.getROIs()}\n case 'list_sets':\n return {action: 'list_sets', sets: this.browser.getROISets().map(s => s.toJSON())}\n case 'find_at_locus':\n return {\n action: 'find_at_locus',\n rois: this.browser.findROIsAtLocus(action.chr, action.start, action.end),\n }\n case 'get_visible':\n return {action: 'get_visible', rois: this.browser.getVisibleROIs()}\n default:\n throw new CommandError('INVALID_ARGS', `Unknown ROI action: ${(action as Record<string, unknown>).action}`)\n }\n }\n\n private handleSubscribeEvents(args: SubscribeEventsArgs): SubscribeEventsResult {\n if (!Array.isArray(args.events)) {\n throw new CommandError('INVALID_ARGS', 'subscribe_events requires an events array')\n }\n\n const validEvents = new Set(Object.values(BrowserEvent) as string[])\n const subscribed: string[] = []\n\n for (const name of args.events) {\n if (name === '*') {\n subscribed.push('*')\n } else if (validEvents.has(name)) {\n subscribed.push(name)\n } else {\n throw new CommandError('INVALID_ARGS', `Unknown event name: \"${name}\". Valid events: ${[...validEvents].join(', ')}`)\n }\n }\n\n this.options.onSubscribeEvents?.(subscribed)\n return {subscribed}\n }\n}\n\n// ─── Helpers ────────────────────────────────────────────────────────────────\n\n/** Convert a ManagedTrack to a concise TrackSummary (for modify_tracks find results). */\nfunction managedTrackToSummary(mt: ManagedTrack): TrackSummary {\n return {\n id: mt.id,\n type: mt.track.type,\n name: mt.name,\n metadata: mt.metadata,\n loading: mt.dataSource != null && mt.cache == null,\n }\n}\n","/**\n * RemoteProtocol — WebSocket message framing and event forwarding.\n *\n * Provides `RemoteConnection` which bridges a `HeadlessGenomeBrowser` to a\n * WebSocket-like transport. Incoming command messages are dispatched via\n * `CommandDispatcher`; browser events are forwarded as unsolicited messages.\n *\n * The `RemoteSocket` interface is minimal and testable — works with browser\n * WebSocket, the `ws` npm package, or mock implementations.\n */\n\nimport {BrowserEvent} from './headlessGenomeBrowser'\nimport type {HeadlessGenomeBrowser, BrowserEvents} from './headlessGenomeBrowser'\nimport {CommandDispatcher, CommandError} from './commandDispatcher'\nimport type {CommandArgs, CommandDispatcherOptions} from './commandDispatcher'\n\n// ─── Wire message types ─────────────────────────────────────────────────────\n\n/** Inbound: agent/server sends a command request. */\nexport interface RequestMessage {\n id: string\n command: string\n args?: Record<string, unknown>\n}\n\n/** Outbound: successful command result. */\nexport interface ResponseMessage {\n id: string\n result: unknown\n}\n\n/** Outbound: command failed. */\nexport interface ErrorMessage {\n id: string\n error: { code: string; message: string }\n}\n\n/** Outbound: unsolicited browser event. */\nexport interface EventMessage {\n event: string\n data: unknown\n}\n\nexport type OutboundMessage = ResponseMessage | ErrorMessage | EventMessage\n\n// ─── RemoteSocket interface ─────────────────────────────────────────────────\n\n/**\n * Minimal WebSocket-like interface.\n * Works with browser WebSocket, Node `ws`, or test mocks.\n */\nexport interface RemoteSocket {\n send(data: string): void\n addEventListener(type: 'message', handler: (event: { data: string }) => void): void\n addEventListener(type: 'close', handler: () => void): void\n addEventListener(type: 'error', handler: (event: unknown) => void): void\n removeEventListener(type: string, handler: (...args: unknown[]) => void): void\n readonly readyState: number\n}\n\nexport const READY_STATE_OPEN = 1\n\n// ─── RemoteConnection ───────────────────────────────────────────────────────\n\nexport class RemoteConnection {\n private dispatcher: CommandDispatcher\n private socket: RemoteSocket\n private browser: HeadlessGenomeBrowser\n private unsubscribers: Array<() => void> = []\n private messageHandler: (event: { data: string }) => void\n private closeHandler: () => void\n private detached = false\n /** null = no subscription (default, no events forwarded). Set with subscribe_events command. */\n private subscribedEvents: Set<string> | null = null\n\n constructor(\n browser: HeadlessGenomeBrowser,\n socket: RemoteSocket,\n options?: CommandDispatcherOptions,\n ) {\n this.browser = browser\n this.socket = socket\n this.dispatcher = new CommandDispatcher(browser, {\n ...options,\n onSubscribeEvents: (events) => { this.subscribedEvents = new Set(events) },\n })\n\n this.messageHandler = (event) => { void this.handleMessage(event.data) }\n this.closeHandler = () => this.detach()\n\n socket.addEventListener('message', this.messageHandler)\n socket.addEventListener('close', this.closeHandler)\n\n this.subscribeToEvents()\n }\n\n /** Disconnect: unsubscribe all event listeners and stop forwarding. */\n detach(): void {\n if (this.detached) return\n this.detached = true\n for (const unsub of this.unsubscribers) unsub()\n this.unsubscribers = []\n this.socket.removeEventListener('message', this.messageHandler as (...args: unknown[]) => void)\n this.socket.removeEventListener('close', this.closeHandler as (...args: unknown[]) => void)\n }\n\n /** Whether this connection has been detached. */\n get isDetached(): boolean {\n return this.detached\n }\n\n // ─── Message handling ───────────────────────────────────────────────\n\n private async handleMessage(raw: string): Promise<void> {\n let parsed: RequestMessage\n try {\n parsed = JSON.parse(raw) as RequestMessage\n } catch {\n // Malformed JSON — can't respond without an id, drop it.\n return\n }\n\n if (!parsed.id || !parsed.command) return\n\n try {\n const commandArgs = {command: parsed.command, ...parsed.args} as CommandArgs\n const result = await this.dispatcher.dispatch(commandArgs)\n this.send({id: parsed.id, result})\n } catch (err) {\n if (err instanceof CommandError) {\n this.send({id: parsed.id, error: {code: err.code, message: err.message}})\n } else {\n this.send({\n id: parsed.id,\n error: {code: 'INTERNAL_ERROR', message: (err as Error).message ?? 'Unknown error'},\n })\n }\n }\n }\n\n private send(msg: OutboundMessage): void {\n if (this.socket.readyState === READY_STATE_OPEN && !this.detached) {\n this.socket.send(JSON.stringify(msg))\n }\n }\n\n // ─── Event forwarding ───────────────────────────────────────────────\n\n private subscribeToEvents(): void {\n const eventNames = Object.values(BrowserEvent)\n for (const eventName of eventNames) {\n const unsub = this.browser.on(\n eventName as keyof BrowserEvents,\n (data: BrowserEvents[keyof BrowserEvents]) => {\n if (!this.subscribedEvents) return\n if (!this.subscribedEvents.has('*') && !this.subscribedEvents.has(eventName)) return\n this.send({event: eventName, data: this.sanitizeEventData(eventName, data)})\n },\n )\n this.unsubscribers.push(unsub)\n }\n }\n\n /**\n * Convert non-serializable event payloads to plain JSON.\n *\n * Track references → { trackId, trackType, trackName }\n * Error objects → string message\n * ROISet objects → set name string\n */\n private sanitizeEventData(\n eventName: string,\n data: BrowserEvents[keyof BrowserEvents],\n ): unknown {\n // Locus change — already serializable\n if (eventName === BrowserEvent.LocusChange) {\n return data\n }\n\n // ROI interaction events — ROI is serializable, strip other non-serializables\n if (eventName === BrowserEvent.ROIClick || eventName === BrowserEvent.ROIContextMenu) {\n return data\n }\n\n // ROI mutation events — { roi, set: ROISet, changes? }\n if (\n eventName === BrowserEvent.ROIAdded\n || eventName === BrowserEvent.ROIRemoved\n || eventName === BrowserEvent.ROIChanged\n ) {\n const d = data as { roi: unknown; set: { name: string }; changes?: unknown }\n return {\n roi: d.roi,\n setName: d.set.name,\n ...(d.changes ? {changes: d.changes} : {}),\n }\n }\n\n // Track order changed — { tracks: Track[] }\n if (eventName === BrowserEvent.TrackOrderChanged) {\n const d = data as { tracks: Array<{ type: string }> }\n return {\n trackIds: d.tracks.map(t => this.findTrackId(t)),\n }\n }\n\n // Track error events — { track, error }\n if (eventName === BrowserEvent.DataError || eventName === BrowserEvent.RenderError) {\n const d = data as { track: { type: string }; error: Error }\n const mt = this.findManagedTrack(d.track)\n return {\n trackId: mt?.id,\n trackType: d.track.type,\n trackName: mt?.name,\n error: d.error.message,\n }\n }\n\n // Track interaction events — { track, genomicLocation, features, ... }\n if (\n eventName === BrowserEvent.TrackClick\n || eventName === BrowserEvent.TrackHover\n || eventName === BrowserEvent.TrackContextMenu\n ) {\n const d = data as { track: { type: string }; genomicLocation: number; features: unknown[] }\n const mt = this.findManagedTrack(d.track)\n return {\n trackId: mt?.id,\n trackType: d.track.type,\n trackName: mt?.name,\n genomicLocation: d.genomicLocation,\n featureCount: d.features.length,\n }\n }\n\n // Single-track events (trackadded, trackremoved, dataloaded) — { track }\n const d = data as { track: { type: string } }\n if ('track' in d) {\n const mt = this.findManagedTrack(d.track)\n return {\n trackId: mt?.id,\n trackType: d.track.type,\n trackName: mt?.name,\n }\n }\n\n return data\n }\n\n private findManagedTrack(track: { type: string }): { id: string; name?: string } | undefined {\n return this.browser.getManagedTracks().find(m => m.track === track)\n }\n\n private findTrackId(track: { type: string }): string | undefined {\n return this.findManagedTrack(track)?.id\n }\n}\n","/**\n * Stateless axis renderers for the left-hand axis column.\n *\n * These are pure canvas renderers — they take a 2D context, axis info, and\n * dimensions, and paint the axis. No DOM, no state, no side effects.\n *\n * Two variants:\n * - renderQuantitativeAxis: tick marks + data range labels for numeric tracks (wig)\n * - renderLabelAxis: centered rotated text label for annotation tracks (gene)\n */\n\nimport type {AxisInfo} from '../../types'\n\n/** Width of the color strip indicator on the right edge of the axis. */\nconst COLOR_STRIP_WIDTH = 4\n\n/** Format a number for axis labels (ported from igv.js paintAxis.ts). */\nexport function prettyPrintNumber(n: number): string {\n if (Number.isInteger(n)) return n.toString()\n if (n % 1 === 0) return n.toString()\n if (Math.abs(n) >= 10) return n.toFixed()\n if (Math.abs(n) >= 1) return n.toFixed(1)\n if (Math.abs(n) >= 0.1) return n.toFixed(2)\n return n.toExponential(1)\n}\n\n/**\n * Paint a quantitative axis with vertical line, tick marks, and data range labels.\n *\n * Requires `info.dataRange` to be set. Renders:\n * - White background\n * - Color strip on right edge (if info.color is set)\n * - Vertical axis line with top/bottom ticks and labels (max/min)\n * - Middle tick at midpoint (if height > 60)\n */\n/** Transform a data value to log space, matching wigRenderer's computeYPixel logic. */\nfunction toLogValue(v: number): number {\n return v < 0 ? -Math.log10(Math.abs(v) + 1) : Math.log10(Math.abs(v) + 1)\n}\n\n/**\n * Map a data value to a Y pixel position in the axis.\n * When logScale is true, uses the same log transform as the wig renderer.\n */\nfunction valueToY(\n value: number,\n min: number,\n max: number,\n topY: number,\n bottomY: number,\n flip: boolean,\n logScale: boolean,\n): number {\n const lo = logScale ? toLogValue(min) : min\n const hi = logScale ? toLogValue(max) : max\n const v = logScale ? toLogValue(value) : value\n const range = hi - lo\n if (range === 0) return (topY + bottomY) / 2\n // Fraction from min to max\n const frac = (v - lo) / range\n // Top = max (or min when flipped), bottom = min (or max when flipped)\n return flip ? topY + frac * (bottomY - topY) : bottomY - frac * (bottomY - topY)\n}\n\nexport function renderQuantitativeAxis(\n ctx: CanvasRenderingContext2D,\n info: AxisInfo,\n width: number,\n height: number,\n): void {\n if (!info.dataRange || height === 0) return\n\n const {min, max} = info.dataRange\n const flip = info.flipAxis ?? false\n const logScale = info.logScale ?? false\n const shim = 0.01\n const topY = shim * height\n const bottomY = (1.0 - shim) * height\n\n // When flipped, min is at top and max is at bottom (used by GWAS/QTL tracks)\n const topValue = flip ? min : max\n const bottomValue = flip ? max : min\n\n const bg = info.backgroundColor ?? 'white'\n const fg = info.labelColor ?? 'black'\n\n // Clear with background\n ctx.fillStyle = bg\n ctx.fillRect(0, 0, width, height)\n\n // Color strip on right edge\n if (info.color) {\n ctx.fillStyle = info.color\n ctx.fillRect(width - COLOR_STRIP_WIDTH - 1, 0, COLOR_STRIP_WIDTH, height)\n }\n\n const tickEnd = width - COLOR_STRIP_WIDTH - 3\n const tickStart = tickEnd - 6\n\n ctx.strokeStyle = fg\n ctx.fillStyle = fg\n ctx.font = 'normal 9px Arial'\n ctx.textAlign = 'right'\n ctx.lineWidth = 1\n\n // Vertical axis line\n ctx.beginPath()\n ctx.moveTo(tickEnd, topY)\n ctx.lineTo(tickEnd, bottomY)\n ctx.stroke()\n\n // Top tick + label\n ctx.beginPath()\n ctx.moveTo(tickStart, topY)\n ctx.lineTo(tickEnd, topY)\n ctx.stroke()\n ctx.textBaseline = 'top'\n ctx.fillText(prettyPrintNumber(topValue), tickStart - 2, topY + 1)\n\n // Bottom tick + label\n ctx.beginPath()\n ctx.moveTo(tickStart, bottomY)\n ctx.lineTo(tickEnd, bottomY)\n ctx.stroke()\n ctx.textBaseline = 'bottom'\n ctx.fillText(prettyPrintNumber(bottomValue), tickStart - 2, bottomY - 1)\n\n // Middle tick — linear midpoint or log-space midpoint\n if (height > 60) {\n const midVal = logScale\n ? (() => {\n // Midpoint in log space, converted back to data space\n const logMid = (toLogValue(min) + toLogValue(max)) / 2\n return logMid >= 0 ? Math.pow(10, logMid) - 1 : -(Math.pow(10, -logMid) - 1)\n })()\n : (min + max) / 2\n const midY = valueToY(midVal, min, max, topY, bottomY, flip, logScale)\n ctx.beginPath()\n ctx.moveTo(tickStart + 3, midY)\n ctx.lineTo(tickEnd, midY)\n ctx.stroke()\n ctx.textBaseline = 'middle'\n ctx.fillText(prettyPrintNumber(midVal), tickStart + 1, midY)\n }\n\n}\n\n/**\n * Paint a label-only axis (e.g., gene track name).\n * Renders a vertically-rotated centered text label.\n */\nexport function renderLabelAxis(\n ctx: CanvasRenderingContext2D,\n info: AxisInfo,\n width: number,\n height: number,\n): void {\n if (!info.label || height === 0) return\n\n const bg = info.backgroundColor ?? 'white'\n const fg = info.labelColor ?? '#333'\n\n // Clear with background\n ctx.fillStyle = bg\n ctx.fillRect(0, 0, width, height)\n\n ctx.font = '10px sans-serif'\n ctx.fillStyle = fg\n ctx.textAlign = 'center'\n ctx.textBaseline = 'middle'\n\n ctx.save()\n ctx.translate(width / 2, height / 2)\n ctx.rotate(-Math.PI / 2)\n // Clip text to available height\n const maxTextWidth = height - 10\n ctx.fillText(info.label, 0, 0, maxTextWidth)\n ctx.restore()\n}\n","/**\n * DOM-attached GenomeBrowser — extends HeadlessGenomeBrowser with pointer events,\n * ResizeObserver, canvas stacking, and sweep-to-zoom.\n *\n * Coordinates multiple Track instances, stacking them vertically in a container.\n * Static rendering is the base — interactivity (drag-to-pan) is enabled by default\n * but can be disabled via `interactive: false`.\n *\n * Ruler tracks get special treatment: dragging on a ruler creates a selection\n * overlay (sweep-to-zoom) instead of panning.\n *\n * Usage:\n * const browser = new GenomeBrowser(container, {\n * locus: { chr: 'chr17', start: 7668000, end: 7688000 },\n * })\n * browser.addTrack(rulerTrack)\n * browser.addTrack(geneTrack)\n * // Drag to pan — works out of the box.\n * // Drag on ruler — sweep to zoom.\n * // Cleanup:\n * browser.dispose()\n */\n\nimport type {\n Track,\n DataSource,\n SessionConfig,\n DataSourceConfig,\n AxisInfo,\n PopupDataItem,\n ContextMenuItem,\n TrackContextMenuEvent,\n ROI,\n} from \"./types\";\nimport { HeadlessGenomeBrowser, BrowserEvent } from \"./headlessGenomeBrowser\";\nimport type { HeadlessGenomeBrowserOptions } from \"./headlessGenomeBrowser\";\nimport { RemoteConnection } from \"./remoteProtocol\";\nimport type { RemoteSocket } from \"./remoteProtocol\";\nimport { isWholeGenomeView } from \"./locusUtils\";\nimport { genomeToChromCoord } from \"./genome/chromSizes\";\nimport type { CreateTrackFromSessionOptions } from \"./session\";\nimport {\n renderQuantitativeAxis,\n renderLabelAxis,\n} from \"./tracks/axis/axisRenderer\";\nimport { BaseTrackCanvas } from \"./tracks/baseTrackCanvas\";\nimport { C2S } from \"./export/canvas2svg\";\nimport { commonContextMenuItems, numericDataMenuItems, roiContextMenuItems } from \"./contextMenu\";\nimport type { ContextMenuCallbacks, ROIMenuCallbacks } from \"./contextMenu\";\nimport type { ContextMenuProvider } from \"./contextMenuProvider\";\nimport type { PopupProvider } from \"./popupProvider\";\nimport { renderROIOverlays } from \"./roi/roiRenderer\";\n\n/**\n * Create a default ContextMenuProvider using <loom-context-menu>.\n * This avoids statically importing the Web Component class (which extends\n * HTMLElement and breaks SSR). The custom element self-registers on first\n * import of ui/components/LoomContextMenu, but GenomeBrowser is always\n * DOM-attached so we can safely trigger registration here.\n */\nfunction createDefaultContextMenuProvider(): ContextMenuProvider {\n // Ensure the custom element is registered\n if (!customElements.get(\"loom-context-menu\")) {\n // Side-effect import — registers the element\n import(\"./ui/components/LoomContextMenu\");\n }\n\n type MenuElement = HTMLElement & {\n setItems(items: ContextMenuItem[]): void;\n showAt(x: number, y: number): void;\n hide(): void;\n };\n\n let element: MenuElement | null = null;\n\n return {\n show(\n items: ContextMenuItem[],\n position: { x: number; y: number },\n container: HTMLElement,\n ): void {\n if (!element) {\n element = document.createElement(\"loom-context-menu\") as MenuElement;\n const pos = getComputedStyle(container).position;\n if (pos === \"static\") container.style.position = \"relative\";\n container.appendChild(element);\n }\n element.setItems(items);\n element.showAt(position.x, position.y);\n },\n hide(): void {\n if (element) element.hide();\n },\n dispose(): void {\n if (element) {\n element.remove();\n element = null;\n }\n },\n };\n}\n\n/**\n * Create a default PopupProvider using <loom-popup>.\n * Same lazy/SSR-safe pattern as createDefaultContextMenuProvider.\n */\nfunction createDefaultPopupProvider(): PopupProvider {\n if (!customElements.get(\"loom-popup\")) {\n import(\"./ui/components/LoomPopup\");\n }\n\n type PopupElement = HTMLElement & {\n setData(data: PopupDataItem[]): void;\n showAt(x: number, y: number): void;\n hide(): void;\n };\n\n let element: PopupElement | null = null;\n\n return {\n show(\n data: PopupDataItem[],\n position: { x: number; y: number },\n container: HTMLElement,\n ): void {\n if (!element) {\n element = document.createElement(\"loom-popup\") as PopupElement;\n const pos = getComputedStyle(container).position;\n if (pos === \"static\") container.style.position = \"relative\";\n container.appendChild(element);\n }\n element.setData(data);\n element.showAt(position.x, position.y);\n },\n hide(): void {\n if (element) element.hide();\n },\n dispose(): void {\n if (element) {\n element.remove();\n element = null;\n }\n },\n };\n}\n\n// Re-export types from headless for backward compat\nexport { BrowserEvent } from \"./headlessGenomeBrowser\";\nexport type { BrowserEvents } from \"./headlessGenomeBrowser\";\n\nexport interface GenomeBrowserOptions extends HeadlessGenomeBrowserOptions {\n /** Enable mouse/touch drag to pan. Default: true. */\n interactive?: boolean;\n /** Enable trackpad pinch and scroll-wheel zoom. Default: true when interactive. */\n wheelZoom?: boolean;\n}\n\n/** Minimum pixel drag distance to trigger a sweep-to-zoom. */\nconst SWEEP_THRESHOLD = 3;\n/** Maximum pixel movement to still count as a click (not a drag). */\nconst CLICK_THRESHOLD = 3;\n/** Throttle interval for hover events (ms). */\nconst HOVER_THROTTLE = 100;\n/** Maximum time between clicks to count as a double-click (ms). */\nconst DOUBLE_CLICK_DELAY = 500;\n/** Width of the left axis column in pixels. */\nconst AXIS_COLUMN_WIDTH = 50;\n\ninterface TrackRow {\n row: HTMLDivElement;\n axisDiv: HTMLDivElement;\n axisCanvas: HTMLCanvasElement | null;\n viewportWrapper: HTMLDivElement;\n}\n\n/** Inject hidden-scrollbar styles once per root (Document or ShadowRoot). */\nconst injectedRoots = new WeakSet<Document | ShadowRoot>();\nfunction injectScrollStyles(container: HTMLElement): void {\n const root = container.getRootNode() as Document | ShadowRoot;\n if (injectedRoots.has(root)) return;\n injectedRoots.add(root);\n const style = document.createElement(\"style\");\n style.textContent = `\n .loom-track-scroll { scrollbar-width: none; }\n .loom-track-scroll::-webkit-scrollbar { display: none; }\n `;\n if (root instanceof Document) {\n root.head.appendChild(style);\n } else {\n root.appendChild(style);\n }\n}\n\nexport class GenomeBrowser extends HeadlessGenomeBrowser {\n private container: HTMLElement;\n private interactive: boolean;\n\n // Drag state\n private isDragging = false;\n private lastPointerX = 0;\n\n // Sweep-to-zoom state\n private isSweeping = false;\n private sweepStartX = 0;\n private sweepOverlay: HTMLDivElement | null = null;\n private sweepRulerCanvas: HTMLCanvasElement | null = null;\n\n // Click detection state (distinguish click from drag)\n private pointerDownX = 0;\n private pointerDownY = 0;\n private pointerDownTarget: EventTarget | null = null;\n\n // Double-click detection\n private lastClickTime = 0;\n private lastClickX = 0;\n private lastClickY = 0;\n private singleClickTimer: ReturnType<typeof setTimeout> | null = null;\n\n // Hover throttle\n private hoverThrottleId: ReturnType<typeof setTimeout> | null = null;\n\n // rAF render batching for drag\n private _rafId: number | null = null;\n\n // Resize observer for re-rendering when container gets layout\n private resizeObserver: ResizeObserver | null = null;\n\n // Per-track flex row with axis + viewport\n private trackRows = new Map<Track, TrackRow>();\n\n // Context menu support\n private handleContextMenu: ((e: MouseEvent) => void) | null = null;\n private inputDialog:\n | (HTMLElement & {\n prompt(label: string, value: string | number): Promise<string | null>;\n })\n | null = null;\n\n // Remote connection\n private remoteConnection: RemoteConnection | null = null;\n\n // Track reorder drag state\n private reorderDragTrack: Track | null = null;\n private reorderDragRow: HTMLDivElement | null = null;\n private reorderHandlers = new Map<\n Track,\n {\n down: (e: PointerEvent) => void;\n docMove: (e: PointerEvent) => void;\n docUp: (e: PointerEvent) => void;\n }\n >();\n\n // Bound handler references for cleanup\n private handlePointerDown: ((e: PointerEvent) => void) | null = null;\n private handlePointerMove: ((e: PointerEvent) => void) | null = null;\n private handlePointerUp: ((e: PointerEvent) => void) | null = null;\n private handleMouseMove: ((e: MouseEvent) => void) | null = null;\n private handleMouseLeave: ((e: MouseEvent) => void) | null = null;\n private handleDocMouseDown: ((e: MouseEvent) => void) | null = null;\n private handleWheel: ((e: WheelEvent) => void) | null = null;\n private wheelRafId: number | null = null;\n\n // ROI overlay state\n private roiOverlayContainer: HTMLDivElement | null = null;\n private roiElements = new Map<string, HTMLDivElement>();\n\n constructor(container: HTMLElement, options: GenomeBrowserOptions) {\n // Default-on: create providers unless explicitly set to null.\n const contextMenuProvider =\n options.contextMenuProvider === null\n ? undefined\n : (options.contextMenuProvider ?? createDefaultContextMenuProvider());\n const popupProvider =\n options.popupProvider === null\n ? undefined\n : (options.popupProvider ?? createDefaultPopupProvider());\n super({\n ...options,\n contextMenuProvider,\n popupProvider,\n viewportWidth: container.clientWidth,\n });\n this.container = container;\n this.interactive = options.interactive ?? true;\n injectScrollStyles(container);\n\n container.style.userSelect = \"none\";\n container.style.touchAction = \"none\";\n if (this.interactive) {\n container.style.cursor = isWholeGenomeView(options.locus)\n ? \"default\"\n : \"grab\";\n this.setupDragHandlers();\n this.setupHoverHandlers();\n this.setupContextMenuHandler();\n if (options.wheelZoom !== false) {\n this.setupWheelHandler();\n }\n\n // Dismiss popup/context menu when clicking outside the container entirely\n if (this.popupProvider || this.contextMenuProvider) {\n this.handleDocMouseDown = (e: MouseEvent) => {\n if (!this.container.contains(e.target as Node)) {\n this.popupProvider?.hide();\n this.contextMenuProvider?.hide();\n }\n };\n document.addEventListener(\"mousedown\", this.handleDocMouseDown);\n }\n }\n\n // Re-render tracks when container resizes (e.g. first layout in Shadow DOM)\n this.resizeObserver = new ResizeObserver(() => this.render());\n this.resizeObserver.observe(container);\n\n // Axis content is updated in two places:\n // 1. After super.render() in render() — handles resize, pan, initial load\n // 2. Here on 'dataloaded' — handles async data loads where setFeatures()\n // triggers track.render() directly, bypassing GenomeBrowser.render().\n // This may repaint the axis twice on initial load (negligible for a 50px canvas).\n this.events.on(BrowserEvent.DataLoaded, ({ track }) => {\n this.updateAxisContent(track);\n });\n\n // Re-render ROI overlays when ROIs change or viewport moves\n this.events.on(BrowserEvent.ROIAdded, () => this.renderROIOverlays());\n this.events.on(BrowserEvent.ROIRemoved, () => this.renderROIOverlays());\n this.events.on(BrowserEvent.ROIChanged, () => this.renderROIOverlays());\n this.events.on(BrowserEvent.LocusChange, () => this.renderROIOverlays());\n }\n\n /** Add a track and attach its canvas to the container. */\n override addTrack<F>(\n track: Track,\n dataSource?: DataSource<F>,\n dataSourceConfig?: DataSourceConfig,\n maxTrackHeight?: number,\n ): string {\n const id = super.addTrack(track, dataSource, dataSourceConfig, maxTrackHeight);\n\n const canvas = track.canvas;\n canvas.style.display = \"block\";\n canvas.style.width = \"100%\";\n\n // Flex row: [axis (50px)] [viewport (flex: 1)]\n const row = document.createElement(\"div\");\n row.style.display = \"flex\";\n row.style.width = \"100%\";\n row.style.alignItems = \"stretch\";\n\n const axisDiv = document.createElement(\"div\");\n axisDiv.style.width = `${AXIS_COLUMN_WIDTH}px`;\n axisDiv.style.flexShrink = \"0\";\n axisDiv.style.overflow = \"hidden\";\n axisDiv.style.position = \"relative\";\n axisDiv.style.borderRight = \"1px solid #ddd\";\n axisDiv.style.boxSizing = \"border-box\";\n\n const viewportWrapper = document.createElement(\"div\");\n viewportWrapper.style.flex = \"1\";\n viewportWrapper.style.minWidth = \"0\";\n\n // Apply maxTrackHeight if set — enables native scroll for tall tracks\n const mt = this.managedTracks[this.managedTracks.length - 1];\n if (mt.maxTrackHeight != null) {\n viewportWrapper.style.maxHeight = `${mt.maxTrackHeight}px`;\n viewportWrapper.style.overflowY = \"auto\";\n viewportWrapper.style.overscrollBehaviorY = \"none\";\n viewportWrapper.style.backgroundColor =\n track.canvas.style.backgroundColor || \"#ffffff\";\n viewportWrapper.classList.add(\"loom-track-scroll\");\n }\n\n viewportWrapper.appendChild(canvas);\n row.appendChild(axisDiv);\n row.appendChild(viewportWrapper);\n this.container.appendChild(row);\n this.trackRows.set(track, {\n row,\n axisDiv,\n axisCanvas: null,\n viewportWrapper,\n });\n\n // Suppress on-canvas data range labels for wig tracks — the axis column handles it.\n // This keeps showDataRange=true as the default for standalone WigTrackCanvas users.\n if (track.type === \"wig\") {\n (track as BaseTrackCanvas<{ showDataRange: boolean }>).setConfig({\n showDataRange: false,\n });\n }\n\n this.updateAxisContent(track);\n\n // Ruler tracks: crosshair for sweep-to-zoom, pointer in WG mode (click to navigate)\n if (this.interactive && track.type === \"ruler\") {\n canvas.style.cursor = isWholeGenomeView(this._locus)\n ? \"pointer\"\n : \"crosshair\";\n }\n\n // Enable drag-to-reorder on the axis column for non-ruler tracks\n if (this.interactive && track.type !== \"ruler\") {\n this.setupReorderHandlers(track, axisDiv);\n }\n\n return id;\n }\n\n /** Remove a track and its row from the container. */\n override removeTrack(trackOrId: Track | string): void {\n const track = typeof trackOrId === 'string'\n ? this.getTrack(trackOrId)\n : trackOrId;\n if (!track) return;\n this.teardownReorderHandlers(track);\n const entry = this.trackRows.get(track);\n if (entry && entry.row.parentNode === this.container) {\n this.container.removeChild(entry.row);\n }\n this.trackRows.delete(track);\n super.removeTrack(trackOrId);\n }\n\n /** Move a track and reorder the DOM rows to match. */\n override moveTrack(track: Track, toIndex: number): void {\n super.moveTrack(track, toIndex);\n this.syncDOMOrder();\n }\n\n /**\n * Load a session, replacing all current tracks.\n * Removes existing canvases from the DOM, then delegates to the headless\n * implementation which recreates tracks. New canvases are attached via addTrack().\n */\n override loadSession(\n session: SessionConfig,\n options?: CreateTrackFromSessionOptions,\n ): void {\n // Remove existing track rows from the DOM before clearing\n for (const mt of this.managedTracks) {\n const entry = this.trackRows.get(mt.track);\n if (entry && entry.row.parentNode === this.container) {\n this.container.removeChild(entry.row);\n }\n }\n this.trackRows.clear();\n this.clearROIOverlay();\n super.loadSession(session, options);\n }\n\n /** Re-render all tracks, reading width from the DOM container. */\n override render(): void {\n const containerWidth = this.container.clientWidth;\n if (containerWidth === 0) return;\n const trackWidth = containerWidth - AXIS_COLUMN_WIDTH;\n this._viewportWidth = trackWidth;\n for (const mt of this.managedTracks) {\n mt.track.canvas.style.width = `${trackWidth}px`;\n }\n super.render();\n // Update axis content after render (autoscale may have changed data range)\n // Update cursors and axis content\n const wg = isWholeGenomeView(this._locus);\n if (this.interactive) {\n this.container.style.cursor = wg ? \"default\" : \"grab\";\n }\n for (const mt of this.managedTracks) {\n this.updateAxisContent(mt.track);\n if (this.interactive && mt.track.type === \"ruler\") {\n mt.track.canvas.style.cursor = wg ? \"pointer\" : \"crosshair\";\n }\n }\n // Re-render ROI overlays\n this.renderROIOverlays();\n }\n\n /** Clean up event listeners, remove canvases, and dispose headless core. */\n // ─── Remote connection ────────────────────────────────────────────────\n\n /**\n * Attach a remote WebSocket connection.\n * Incoming command messages are automatically dispatched.\n * Browser events are automatically forwarded.\n */\n attachRemote(socket: RemoteSocket): void {\n if (this.remoteConnection) {\n this.remoteConnection.detach();\n }\n this.remoteConnection = new RemoteConnection(this, socket, {\n supportsPNG: true,\n exportPNG: () => this.toPNG(),\n });\n }\n\n /** Detach the remote connection and stop forwarding events. */\n detachRemote(): void {\n if (this.remoteConnection) {\n this.remoteConnection.detach();\n this.remoteConnection = null;\n }\n }\n\n // ─── Dispose ────────────────────────────────────────────────────────\n\n override dispose(): void {\n this.detachRemote();\n if (this._rafId !== null) {\n cancelAnimationFrame(this._rafId);\n this._rafId = null;\n }\n if (this.resizeObserver) {\n this.resizeObserver.disconnect();\n this.resizeObserver = null;\n }\n if (this.singleClickTimer !== null) {\n clearTimeout(this.singleClickTimer);\n this.singleClickTimer = null;\n }\n this.teardownDragHandlers();\n this.teardownHoverHandlers();\n this.teardownContextMenuHandler();\n this.teardownWheelHandler();\n if (this.handleDocMouseDown) {\n document.removeEventListener(\"mousedown\", this.handleDocMouseDown);\n this.handleDocMouseDown = null;\n }\n this.removeSweepOverlay();\n this.clearROIOverlay();\n for (const mt of this.managedTracks) {\n this.teardownReorderHandlers(mt.track);\n const entry = this.trackRows.get(mt.track);\n if (entry && entry.row.parentNode === this.container) {\n this.container.removeChild(entry.row);\n }\n }\n this.reorderHandlers.clear();\n this.trackRows.clear();\n super.dispose();\n }\n\n /**\n * Update the axis content for a track based on its getAxisInfo().\n * Uses a canvas for quantitative axes (tick marks + labels) matching igv.js paintAxis,\n * and a DOM label for annotation tracks (e.g., gene track name).\n */\n private updateAxisContent(track: Track): void {\n const entry = this.trackRows.get(track);\n if (!entry) return;\n const { axisDiv } = entry;\n\n const rawInfo: AxisInfo | undefined = track.getAxisInfo?.();\n\n if (!rawInfo) {\n // No axis info — clear content and hide border (e.g., ruler tracks)\n axisDiv.innerHTML = \"\";\n axisDiv.style.borderRight = \"none\";\n entry.axisCanvas = null;\n return;\n }\n\n // Inject theme palette colors into axis info (so axis renderers respect dark themes)\n const info: AxisInfo = {\n ...rawInfo,\n backgroundColor: rawInfo.backgroundColor ?? this.theme.palette.background,\n labelColor: rawInfo.labelColor ?? this.theme.palette.foreground,\n };\n\n const borderColor = this.theme.palette.muted;\n axisDiv.style.borderRight = `1px solid ${borderColor}`;\n\n // Use visible height (capped by maxTrackHeight) not full content height\n const mt = this.managedTracks.find((m) => m.track === track);\n const visibleHeight =\n mt?.maxTrackHeight != null\n ? Math.min(track.height, mt.maxTrackHeight)\n : track.height;\n\n if (info.dataRange) {\n this.paintAxisCanvas(entry, info, visibleHeight, renderQuantitativeAxis);\n } else if (info.label) {\n this.paintAxisCanvas(entry, info, visibleHeight, renderLabelAxis);\n }\n }\n\n /**\n * Prepare an axis canvas at the correct size with DPR scaling,\n * then delegate to the given stateless render function.\n */\n private paintAxisCanvas(\n entry: TrackRow,\n info: AxisInfo,\n trackHeight: number,\n renderFn: (\n ctx: CanvasRenderingContext2D,\n info: AxisInfo,\n width: number,\n height: number,\n ) => void,\n ): void {\n const { axisDiv } = entry;\n const height = trackHeight;\n const width = AXIS_COLUMN_WIDTH;\n if (height === 0) return;\n\n axisDiv.style.height = `${height}px`;\n\n // Reuse or create axis canvas\n let canvas = entry.axisCanvas;\n if (!canvas) {\n axisDiv.innerHTML = \"\";\n canvas = document.createElement(\"canvas\");\n canvas.style.display = \"block\";\n axisDiv.appendChild(canvas);\n entry.axisCanvas = canvas;\n }\n\n // Size canvas at device pixel ratio (use canvasProvider for headless/SSR compat)\n const dpr = this.canvasProvider.devicePixelRatio;\n canvas.width = width * dpr;\n canvas.height = height * dpr;\n canvas.style.width = `${width}px`;\n canvas.style.height = `${height}px`;\n\n const ctx = canvas.getContext(\"2d\")!;\n ctx.scale(dpr, dpr);\n\n renderFn(ctx, info, width, height);\n }\n\n /** Check if a pointer event target is a ruler track canvas. */\n private isRulerCanvas(target: EventTarget | null): boolean {\n if (!(target instanceof HTMLCanvasElement)) return false;\n return this.managedTracks.some(\n (mt) => mt.track.type === \"ruler\" && mt.track.canvas === target,\n );\n }\n\n // ─── Sweep-to-zoom overlay ───────────────────────────────────────────────\n\n private createSweepOverlay(rulerCanvas: HTMLCanvasElement): HTMLDivElement {\n const overlay = document.createElement(\"div\");\n overlay.style.cssText = `\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: 0;\n pointer-events: none;\n background: rgba(68, 134, 247, 0.25);\n z-index: 99999;\n transition: none;\n `;\n // Position relative to the ruler canvas\n rulerCanvas.style.position = \"relative\";\n rulerCanvas.parentElement!.style.position = \"relative\";\n rulerCanvas.parentElement!.appendChild(overlay);\n return overlay;\n }\n\n private removeSweepOverlay(): void {\n if (this.sweepOverlay) {\n this.sweepOverlay.remove();\n this.sweepOverlay = null;\n }\n this.sweepRulerCanvas = null;\n }\n\n // ─── Pointer event handlers ──────────────────────────────────────────────\n\n private setupDragHandlers(): void {\n this.handlePointerDown = (e: PointerEvent) => {\n if (e.button !== 0) return; // left button only\n\n // Don't dismiss context menu or start drag when clicking inside the menu itself\n if (this.isOverlayTarget(e)) return;\n\n // Dismiss context menu on any left click\n this.contextMenuProvider?.hide();\n\n // Only start drag/sweep on track canvases. Clicks on other\n // elements (popup, container gap) just dismiss the popup.\n if (!(e.target instanceof HTMLCanvasElement)) {\n if (this.popupProvider) this.popupProvider.hide();\n // Clear so pointerup doesn't use stale target from previous click\n this.pointerDownTarget = null;\n return;\n }\n\n // Record position for click detection\n this.pointerDownX = e.clientX;\n this.pointerDownY = e.clientY;\n this.pointerDownTarget = e.target;\n\n // No sweep or panning in whole genome view — clicks navigate to chromosome\n if (isWholeGenomeView(this._locus)) return;\n\n // Check if drag started on a ruler canvas → sweep-to-zoom\n if (this.isRulerCanvas(e.target)) {\n const rulerCanvas = e.target as HTMLCanvasElement;\n this.isSweeping = true;\n this.isDragging = false;\n this.sweepRulerCanvas = rulerCanvas;\n\n const rect = rulerCanvas.getBoundingClientRect();\n this.sweepStartX = e.clientX - rect.left;\n\n this.sweepOverlay = this.createSweepOverlay(rulerCanvas);\n this.sweepOverlay.style.left = `${this.sweepStartX}px`;\n this.sweepOverlay.style.width = \"0px\";\n this.sweepOverlay.style.display = \"block\";\n\n this.container.setPointerCapture(e.pointerId);\n return;\n }\n\n // Normal pan drag\n this.isDragging = true;\n this.isSweeping = false;\n this.lastPointerX = e.clientX;\n this.container.setPointerCapture(e.pointerId);\n this.container.style.cursor = \"grabbing\";\n };\n\n this.handlePointerMove = (e: PointerEvent) => {\n if (this.isSweeping && this.sweepOverlay && this.sweepRulerCanvas) {\n const rect = this.sweepRulerCanvas.getBoundingClientRect();\n const currentX = Math.max(\n 0,\n Math.min(e.clientX - rect.left, rect.width),\n );\n const left = Math.min(this.sweepStartX, currentX);\n const width = Math.abs(currentX - this.sweepStartX);\n\n this.sweepOverlay.style.left = `${left}px`;\n this.sweepOverlay.style.width = `${width}px`;\n return;\n }\n\n if (!this.isDragging) return;\n\n const deltaX = this.lastPointerX - e.clientX;\n this.lastPointerX = e.clientX;\n\n const width = this.container.clientWidth;\n if (width === 0) return;\n const bpPerPixel = (this._locus.end - this._locus.start) / width;\n const deltaBP = deltaX * bpPerPixel;\n\n this._locus = this.clamp({\n chr: this._locus.chr,\n start: this._locus.start + deltaBP,\n end: this._locus.end + deltaBP,\n });\n\n // Batch renders via rAF: suspend tracks so setLocus() updates\n // the locus without painting, then flush once per animation frame.\n for (const mt of this.managedTracks) {\n mt.track.suspendRendering();\n mt.track.setLocus(this._locus);\n }\n\n if (this._rafId === null) {\n this._rafId = requestAnimationFrame(() => {\n this._rafId = null;\n for (const mt of this.managedTracks) {\n mt.track.resumeRendering();\n }\n this.loadAllTracksIfNeeded();\n });\n }\n\n // Events fire immediately for UI responsiveness\n this.events.emit(BrowserEvent.LocusChange, { locus: this._locus });\n };\n\n this.handlePointerUp = (e: PointerEvent) => {\n // Don't interfere with clicks inside the context menu / input dialog\n if (this.isOverlayTarget(e)) return;\n\n if (this.isSweeping && this.sweepOverlay && this.sweepRulerCanvas) {\n // Calculate sweep bounds and zoom\n const left = parseFloat(this.sweepOverlay.style.left);\n const width = parseFloat(this.sweepOverlay.style.width);\n\n this.removeSweepOverlay();\n this.isSweeping = false;\n\n // Only zoom if drag exceeded threshold\n if (width > SWEEP_THRESHOLD) {\n const containerWidth = this.container.clientWidth;\n if (containerWidth > 0) {\n const bpPerPixel =\n (this._locus.end - this._locus.start) / containerWidth;\n const newStart = this._locus.start + left * bpPerPixel;\n const newEnd = this._locus.start + (left + width) * bpPerPixel;\n this.setLocus({\n chr: this._locus.chr,\n start: Math.round(newStart),\n end: Math.round(newEnd),\n });\n }\n }\n return;\n }\n\n const wasDragging = this.isDragging;\n this.isDragging = false;\n this.container.style.cursor = \"grab\";\n\n // Click detection: pointer didn't move more than threshold\n const dx = e.clientX - this.pointerDownX;\n const dy = e.clientY - this.pointerDownY;\n if (\n !wasDragging ||\n dx * dx + dy * dy < CLICK_THRESHOLD * CLICK_THRESHOLD\n ) {\n this.handleClick(e);\n }\n };\n\n this.container.addEventListener(\"pointerdown\", this.handlePointerDown);\n this.container.addEventListener(\"pointermove\", this.handlePointerMove);\n this.container.addEventListener(\"pointerup\", this.handlePointerUp);\n this.container.addEventListener(\"pointercancel\", this.handlePointerUp);\n }\n\n /** Check if an event originated inside an overlay UI component (Shadow DOM) or ROI element. */\n private isOverlayTarget(e: Event): boolean {\n const path = e.composedPath();\n return path.some(\n (el) =>\n el instanceof HTMLElement &&\n (el.tagName === \"LOOM-CONTEXT-MENU\" ||\n el.tagName === \"LOOM-INPUT-DIALOG\" ||\n el.tagName === \"LOOM-POPUP\" ||\n el.classList.contains(\"loom-roi-region\")),\n );\n }\n\n /** Find the track whose canvas contains the given event target. */\n private findTrackForTarget(\n target: EventTarget | null,\n ): import(\"./types\").Track | null {\n if (!(target instanceof HTMLCanvasElement)) return null;\n const mt = this.managedTracks.find((m) => m.track.canvas === target);\n return mt?.track ?? null;\n }\n\n /** Canvas-relative coordinates from a mouse/pointer event. */\n private canvasCoords(\n e: MouseEvent | PointerEvent,\n ): { x: number; y: number } | null {\n if (!(e.target instanceof HTMLCanvasElement)) return null;\n const rect = (e.target as HTMLCanvasElement).getBoundingClientRect();\n return { x: e.clientX - rect.left, y: e.clientY - rect.top };\n }\n\n private handleClick(e: PointerEvent): void {\n const track = this.findTrackForTarget(this.pointerDownTarget);\n if (!track) return;\n\n // Use the stored pointerDownTarget canvas (not e.target) because\n // setPointerCapture redirects e.target to the container element.\n const canvas = this.pointerDownTarget as HTMLCanvasElement;\n const rect = canvas.getBoundingClientRect();\n const coords = { x: e.clientX - rect.left, y: e.clientY - rect.top };\n\n // In WG mode, clicking the ruler navigates to that chromosome\n if (\n isWholeGenomeView(this._locus) &&\n track.type === \"ruler\" &&\n this.cumulativeOffsets &&\n this.chromSizes\n ) {\n const width = canvas.clientWidth;\n if (width > 0) {\n const bpPerPixel = (this._locus.end - this._locus.start) / width;\n const genomicPos = this._locus.start + coords.x * bpPerPixel;\n const { chr } = genomeToChromCoord(genomicPos, this.cumulativeOffsets);\n const chromLength = this.chromSizes[chr];\n if (chromLength != null) {\n this.setLocus({ chr, start: 0, end: chromLength });\n }\n }\n return;\n }\n\n // Double-click detection\n const now = Date.now();\n const isDoubleClick =\n now - this.lastClickTime < DOUBLE_CLICK_DELAY &&\n Math.abs(e.clientX - this.lastClickX) < CLICK_THRESHOLD * 2 &&\n Math.abs(e.clientY - this.lastClickY) < CLICK_THRESHOLD * 2;\n this.lastClickTime = now;\n this.lastClickX = e.clientX;\n this.lastClickY = e.clientY;\n\n if (isDoubleClick) {\n // Cancel pending single-click popup\n if (this.singleClickTimer !== null) {\n clearTimeout(this.singleClickTimer);\n this.singleClickTimer = null;\n }\n this.lastClickTime = 0; // Reset so a third click doesn't re-trigger\n\n // Double-click zooms in 2x; shift+double-click zooms out 2x\n if (!isWholeGenomeView(this._locus)) {\n const viewportWidth = canvas.clientWidth;\n if (viewportWidth > 0) {\n const bpPerPixel =\n (this._locus.end - this._locus.start) / viewportWidth;\n const centerBP = this._locus.start + coords.x * bpPerPixel;\n const factor = e.shiftKey ? 2 : 0.5;\n this.zoomAroundCenter(factor, centerBP);\n }\n }\n return;\n }\n\n // Defer single-click action to allow double-click detection\n const singleClickAction = () => {\n this.singleClickTimer = null;\n const interaction = this.resolveInteraction(track, coords.x, coords.y);\n if (interaction) {\n this.events.emit(BrowserEvent.TrackClick, interaction);\n if (this.popupProvider && interaction.popupData.length > 0) {\n // Position popup relative to container\n const containerRect = this.container.getBoundingClientRect();\n const canvasRect = track.canvas.getBoundingClientRect();\n this.popupProvider.show(\n interaction.popupData,\n {\n x: canvasRect.left - containerRect.left + coords.x,\n y: canvasRect.top - containerRect.top + coords.y,\n },\n this.container,\n );\n }\n } else {\n // Clicked empty space — hide popup\n if (this.popupProvider) this.popupProvider.hide();\n }\n };\n\n this.singleClickTimer = setTimeout(singleClickAction, DOUBLE_CLICK_DELAY);\n }\n\n // ─── Hover event handlers ───────────────────────────────────────────────\n\n private setupHoverHandlers(): void {\n this.handleMouseMove = (e: MouseEvent) => {\n // Don't fire hover during drag/sweep\n if (this.isDragging || this.isSweeping) return;\n\n // Throttle hover events\n if (this.hoverThrottleId !== null) return;\n this.hoverThrottleId = setTimeout(() => {\n this.hoverThrottleId = null;\n }, HOVER_THROTTLE);\n\n const track = this.findTrackForTarget(e.target);\n if (!track) return;\n\n const coords = this.canvasCoords(e);\n if (!coords) return;\n\n const interaction = this.resolveInteraction(track, coords.x, coords.y);\n if (interaction) {\n this.events.emit(BrowserEvent.TrackHover, interaction);\n }\n };\n\n this.handleMouseLeave = (_e: MouseEvent) => {\n if (this.hoverThrottleId !== null) {\n clearTimeout(this.hoverThrottleId);\n this.hoverThrottleId = null;\n }\n };\n\n this.container.addEventListener(\"mousemove\", this.handleMouseMove);\n this.container.addEventListener(\"mouseleave\", this.handleMouseLeave);\n }\n\n private teardownHoverHandlers(): void {\n if (this.handleMouseMove) {\n this.container.removeEventListener(\"mousemove\", this.handleMouseMove);\n }\n if (this.handleMouseLeave) {\n this.container.removeEventListener(\"mouseleave\", this.handleMouseLeave);\n }\n if (this.hoverThrottleId !== null) {\n clearTimeout(this.hoverThrottleId);\n this.hoverThrottleId = null;\n }\n }\n\n // ─── Context menu handler ─────────────────────────────────────────────\n\n private setupContextMenuHandler(): void {\n this.handleContextMenu = (e: MouseEvent) => {\n e.preventDefault();\n\n const track = this.findTrackForTarget(e.target);\n if (!track) return;\n\n const canvas = e.target as HTMLCanvasElement;\n const rect = canvas.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n\n // Track-specific items\n const trackItems = track.getContextMenuItems?.(x, y) ?? [];\n\n // Common items (set height, remove)\n const callbacks: ContextMenuCallbacks = {\n setTrackHeight: (t, h) => {\n if (t instanceof BaseTrackCanvas) {\n t.setConfig({ height: h } as Partial<never>);\n }\n },\n removeTrack: (t) => this.removeTrack(t),\n promptInput: async (label, value) => {\n if (!this.inputDialog) {\n // Lazy-load to avoid SSR issues (extends HTMLElement)\n if (!customElements.get(\"loom-input-dialog\")) {\n await import(\"./ui/components/LoomInputDialog\");\n }\n const el = document.createElement(\n \"loom-input-dialog\",\n ) as HTMLElement & {\n prompt(l: string, v: string | number): Promise<string | null>;\n };\n const pos = getComputedStyle(this.container).position;\n if (pos === \"static\") this.container.style.position = \"relative\";\n this.container.appendChild(el);\n this.inputDialog = el;\n }\n return this.inputDialog.prompt(label, value);\n },\n };\n const commonItems = commonContextMenuItems(track, callbacks);\n\n // Wrap actions so axis updates after any config change\n const wrapAction = (item: ContextMenuItem): ContextMenuItem => {\n const wrapped = item.action\n ? {\n ...item,\n action: () => {\n item.action!();\n this.updateAxisContent(track);\n },\n }\n : { ...item };\n if (wrapped.children) {\n wrapped.children = wrapped.children.map(wrapAction);\n }\n return wrapped;\n };\n\n // Numeric track items (autoscale, log scale, set data range)\n // Mirrors igv.js TrackBase.numericDataMenuItems() (js/trackBase.ts)\n const numericState = track.getNumericState?.();\n const numericItems = numericState\n ? numericDataMenuItems(numericState, callbacks.promptInput)\n : [];\n\n // Merge: track items + numeric items + separator + common items\n const allItems: ContextMenuItem[] = [];\n if (trackItems.length > 0 || numericItems.length > 0) {\n allItems.push(...trackItems.map(wrapAction));\n if (numericItems.length > 0) {\n if (trackItems.length > 0) {\n allItems.push({ label: \"\", type: \"separator\" });\n }\n allItems.push(...numericItems.map(wrapAction));\n }\n allItems.push({ label: \"\", type: \"separator\" });\n }\n allItems.push(...commonItems.map(wrapAction));\n\n // Build and emit event\n const width = track.canvas.clientWidth;\n const bpPerPixel =\n width > 0 ? (this._locus.end - this._locus.start) / width : 0;\n const genomicLocation = this._locus.start + x * bpPerPixel;\n const results = track.hitTest(x, y);\n\n const event: TrackContextMenuEvent = {\n track,\n genomicLocation,\n features: results.map((r) => r.feature),\n trackItems,\n commonItems,\n x,\n y,\n };\n this.events.emit(BrowserEvent.TrackContextMenu, event);\n\n // Show via provider if available\n if (this.contextMenuProvider) {\n this.popupProvider?.hide();\n const containerRect = this.container.getBoundingClientRect();\n const canvasRect = track.canvas.getBoundingClientRect();\n this.contextMenuProvider.show(\n allItems,\n {\n x: canvasRect.left - containerRect.left + x,\n y: canvasRect.top - containerRect.top + y,\n },\n this.container,\n );\n }\n };\n\n this.container.addEventListener(\"contextmenu\", this.handleContextMenu);\n }\n\n private teardownContextMenuHandler(): void {\n if (this.handleContextMenu) {\n this.container.removeEventListener(\"contextmenu\", this.handleContextMenu);\n this.handleContextMenu = null;\n }\n if (this.inputDialog) {\n this.inputDialog.remove();\n this.inputDialog = null;\n }\n }\n\n // ─── Track reorder drag ─────────────────────────────────────────────\n\n /** Reorder DOM rows to match managedTracks order. */\n private syncDOMOrder(): void {\n for (const mt of this.managedTracks) {\n const entry = this.trackRows.get(mt.track);\n if (entry) {\n // appendChild moves the element if already in the container\n this.container.appendChild(entry.row);\n }\n }\n }\n\n /** Set up drag-to-reorder pointer handlers on an axis div. */\n private setupReorderHandlers(track: Track, axisDiv: HTMLDivElement): void {\n axisDiv.style.cursor = \"grab\";\n\n const down = (e: PointerEvent) => {\n if (e.button !== 0) return;\n e.preventDefault();\n e.stopPropagation();\n\n const entry = this.trackRows.get(track);\n if (!entry) return;\n\n this.reorderDragTrack = track;\n this.reorderDragRow = entry.row;\n entry.row.style.opacity = \"0.5\";\n axisDiv.style.cursor = \"grabbing\";\n\n document.addEventListener(\"pointermove\", move);\n document.addEventListener(\"pointerup\", up);\n };\n\n const move = (e: PointerEvent) => {\n if (!this.reorderDragTrack) return;\n\n const fromIndex = this.managedTracks.findIndex(\n (mt) => mt.track === this.reorderDragTrack,\n );\n if (fromIndex < 0) return;\n\n const pointerY = e.clientY;\n\n // Check the adjacent neighbor's midpoint — only swap when the\n // pointer has convincingly entered the neighbor's territory\n // (past its midpoint), not just barely left the dragged row.\n\n // Check neighbor above\n if (fromIndex > 0) {\n const aboveEntry = this.trackRows.get(\n this.managedTracks[fromIndex - 1].track,\n );\n if (aboveEntry) {\n const aboveRect = aboveEntry.row.getBoundingClientRect();\n const aboveThreshold = aboveRect.bottom - aboveRect.height * 0.25;\n if (pointerY < aboveThreshold) {\n const [moved] = this.managedTracks.splice(fromIndex, 1);\n this.managedTracks.splice(fromIndex - 1, 0, moved);\n this.syncDOMOrder();\n return;\n }\n }\n }\n\n // Check neighbor below\n if (fromIndex < this.managedTracks.length - 1) {\n const belowEntry = this.trackRows.get(\n this.managedTracks[fromIndex + 1].track,\n );\n if (belowEntry) {\n const belowRect = belowEntry.row.getBoundingClientRect();\n const belowThreshold = belowRect.top + belowRect.height * 0.15;\n if (pointerY > belowThreshold) {\n const [moved] = this.managedTracks.splice(fromIndex, 1);\n this.managedTracks.splice(fromIndex + 1, 0, moved);\n this.syncDOMOrder();\n return;\n }\n }\n }\n };\n\n const up = (_e: PointerEvent) => {\n document.removeEventListener(\"pointermove\", move);\n document.removeEventListener(\"pointerup\", up);\n\n if (this.reorderDragTrack && this.reorderDragRow) {\n this.reorderDragRow.style.opacity = \"\";\n const dragEntry = this.trackRows.get(this.reorderDragTrack);\n if (dragEntry) {\n dragEntry.axisDiv.style.cursor = \"grab\";\n }\n\n // Emit the final order change event\n this.events.emit(BrowserEvent.TrackOrderChanged, {\n tracks: this.managedTracks.map((mt) => mt.track),\n });\n }\n\n this.reorderDragTrack = null;\n this.reorderDragRow = null;\n };\n\n this.reorderHandlers.set(track, { down, docMove: move, docUp: up });\n axisDiv.addEventListener(\"pointerdown\", down);\n }\n\n /** Remove reorder handlers for a track. */\n private teardownReorderHandlers(track: Track): void {\n const handlers = this.reorderHandlers.get(track);\n if (!handlers) return;\n const entry = this.trackRows.get(track);\n if (entry) {\n entry.axisDiv.removeEventListener(\"pointerdown\", handlers.down);\n }\n document.removeEventListener(\"pointermove\", handlers.docMove);\n document.removeEventListener(\"pointerup\", handlers.docUp);\n this.reorderHandlers.delete(track);\n }\n\n private teardownDragHandlers(): void {\n if (this.handlePointerDown) {\n this.container.removeEventListener(\"pointerdown\", this.handlePointerDown);\n }\n if (this.handlePointerMove) {\n this.container.removeEventListener(\"pointermove\", this.handlePointerMove);\n }\n if (this.handlePointerUp) {\n this.container.removeEventListener(\"pointerup\", this.handlePointerUp);\n this.container.removeEventListener(\"pointercancel\", this.handlePointerUp);\n }\n }\n\n // ─── Wheel / pinch-to-zoom handler ─────────────────────────────────────\n\n /**\n * Set up wheel event handling for trackpad pinch-to-zoom and scroll-wheel zoom.\n *\n * Trackpad pinch gestures on macOS/Chrome are reported as `wheel` events with\n * `ctrlKey: true` and `deltaY` indicating zoom direction. Regular scroll-wheel\n * events (ctrl+scroll) use the same mechanism. Both zoom around the pointer\n * position for natural, cursor-anchored zoom behavior.\n */\n private setupWheelHandler(): void {\n this.handleWheel = (e: WheelEvent) => {\n // Only handle pinch gestures (ctrlKey) and ctrl+scroll\n if (!e.ctrlKey) return;\n\n e.preventDefault();\n\n // No zoom in whole-genome view\n if (isWholeGenomeView(this._locus)) return;\n\n // Batch with rAF — accumulate deltaY across rapid events\n if (this.wheelRafId !== null) return;\n\n // Convert deltaY to a zoom factor.\n // Pinch gestures report small deltaY (~1-5), scroll wheel reports larger (~100).\n // Clamp to prevent extreme jumps from fast scrolling.\n const clampedDelta = Math.max(-50, Math.min(50, e.deltaY));\n const factor = 1 + clampedDelta * 0.01;\n\n // Calculate the genomic position under the pointer for anchored zoom.\n // Use the viewport wrapper width (excluding axis column) for accurate mapping.\n const containerRect = this.container.getBoundingClientRect();\n const pointerX = e.clientX - containerRect.left - AXIS_COLUMN_WIDTH;\n const viewportWidth =\n this.container.clientWidth - AXIS_COLUMN_WIDTH;\n\n if (viewportWidth <= 0) return;\n\n const bpPerPixel =\n (this._locus.end - this._locus.start) / viewportWidth;\n const centerBP = this._locus.start + pointerX * bpPerPixel;\n\n this.wheelRafId = requestAnimationFrame(() => {\n this.wheelRafId = null;\n this.zoomAroundCenter(factor, centerBP);\n });\n };\n\n // Use { passive: false } so preventDefault() works on wheel events\n this.container.addEventListener(\"wheel\", this.handleWheel, {\n passive: false,\n });\n }\n\n private teardownWheelHandler(): void {\n if (this.wheelRafId !== null) {\n cancelAnimationFrame(this.wheelRafId);\n this.wheelRafId = null;\n }\n if (this.handleWheel) {\n this.container.removeEventListener(\"wheel\", this.handleWheel);\n this.handleWheel = null;\n }\n }\n\n // ─── ROI overlay rendering ──────────────────────────────────────────────\n\n /** Ensure the ROI overlay container exists and is sized correctly. */\n private ensureROIOverlayContainer(): HTMLDivElement {\n if (!this.roiOverlayContainer) {\n const overlay = document.createElement(\"div\");\n overlay.style.cssText = `\n position: absolute;\n top: 0;\n left: ${AXIS_COLUMN_WIDTH}px;\n right: 0;\n bottom: 0;\n pointer-events: none;\n z-index: 10;\n overflow: hidden;\n `;\n // Ensure container is positioned for absolute children\n const pos = getComputedStyle(this.container).position;\n if (pos === \"static\") this.container.style.position = \"relative\";\n this.container.appendChild(overlay);\n this.roiOverlayContainer = overlay;\n }\n return this.roiOverlayContainer;\n }\n\n /**\n * Render ROI overlays as DOM elements positioned over the track viewport.\n *\n * Creates/updates/removes DOM elements for each visible ROI.\n * DOM-based (not canvas) for easy hover/click interaction without\n * re-rendering track canvases.\n */\n private renderROIOverlays(): void {\n const visibleROIs = this.getVisibleROIs();\n if (visibleROIs.length === 0 && this.roiElements.size === 0) return;\n\n const overlay = this.ensureROIOverlayContainer();\n const viewportWidth = this._viewportWidth;\n if (viewportWidth <= 0) return;\n\n const bpPerPixel = (this._locus.end - this._locus.start) / viewportWidth;\n\n // Track which ROI IDs are still visible\n const visibleIds = new Set<string>();\n\n for (const roi of visibleROIs) {\n visibleIds.add(roi.id);\n\n const x = Math.round((roi.start - this._locus.start) / bpPerPixel);\n const w = Math.max(3, Math.round((roi.end - roi.start) / bpPerPixel));\n\n let el = this.roiElements.get(roi.id);\n if (!el) {\n el = this.createROIElement(roi);\n overlay.appendChild(el);\n this.roiElements.set(roi.id, el);\n }\n\n // Update position and color\n el.style.left = `${x}px`;\n el.style.width = `${w}px`;\n const color = roi.color ?? \"rgba(68, 134, 247, 0.15)\";\n el.style.backgroundColor = color;\n\n // Update border color (3x alpha of fill)\n const borderColor = color.replace(/[\\d.]+\\)$/, (m) => {\n const alpha = Math.min(1, parseFloat(m) * 3);\n return `${alpha})`;\n });\n el.style.borderLeftColor = borderColor;\n el.style.borderRightColor = borderColor;\n\n // Update header chip color (4x alpha of fill)\n const header = el.firstElementChild as HTMLDivElement;\n if (header) {\n const headerColor = color.replace(/[\\d.]+\\)$/, (m) => {\n const alpha = Math.min(1, parseFloat(m) * 4);\n return `${alpha})`;\n });\n header.style.backgroundColor = headerColor;\n }\n\n // Update label\n const label = el.querySelector(\".loom-roi-label\") as HTMLDivElement | null;\n if (label) {\n label.textContent = roi.name ?? \"\";\n label.style.display = roi.name && w > 20 ? \"block\" : \"none\";\n }\n\n // Store roi data on element for event handling\n (el as HTMLDivElement & { _roiId: string })._roiId = roi.id;\n }\n\n // Remove elements for ROIs no longer visible\n for (const [id, el] of this.roiElements) {\n if (!visibleIds.has(id)) {\n el.remove();\n this.roiElements.delete(id);\n }\n }\n }\n\n /** Create a styled DOM element for an ROI region. */\n private createROIElement(roi: ROI): HTMLDivElement {\n const el = document.createElement(\"div\");\n el.className = \"loom-roi-region\";\n el.style.cssText = `\n position: absolute;\n top: 0;\n bottom: 0;\n border-left: 1px solid transparent;\n border-right: 1px solid transparent;\n box-sizing: border-box;\n pointer-events: auto;\n cursor: pointer;\n transition: opacity 0.15s ease;\n `;\n\n // Header chip (4px colored bar at top)\n const header = document.createElement(\"div\");\n header.className = \"loom-roi-header\";\n header.style.cssText = `\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n height: 4px;\n border-radius: 2px 2px 0 0;\n `;\n el.appendChild(header);\n\n // Label\n const label = document.createElement(\"div\");\n label.className = \"loom-roi-label\";\n label.style.cssText = `\n position: absolute;\n top: 5px;\n left: 3px;\n right: 3px;\n font: 9px sans-serif;\n color: rgba(0, 0, 0, 0.7);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n pointer-events: none;\n `;\n label.textContent = roi.name ?? \"\";\n el.appendChild(label);\n\n // Hover effect\n el.addEventListener(\"mouseenter\", () => {\n el.style.opacity = \"1.3\";\n });\n el.addEventListener(\"mouseleave\", () => {\n el.style.opacity = \"\";\n });\n\n // Click → emit ROIClick event\n el.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n const roiId = (el as HTMLDivElement & { _roiId: string })._roiId;\n const clickedROI = this.getROIs().find((r) => r.id === roiId);\n if (clickedROI) {\n const containerRect = this.container.getBoundingClientRect();\n const bpPerPixel =\n this._viewportWidth > 0\n ? (this._locus.end - this._locus.start) / this._viewportWidth\n : 0;\n const relX = e.clientX - containerRect.left - AXIS_COLUMN_WIDTH;\n const genomicLocation = this._locus.start + relX * bpPerPixel;\n this.events.emit(BrowserEvent.ROIClick, {\n roi: clickedROI,\n genomicLocation,\n x: e.clientX - containerRect.left,\n y: e.clientY - containerRect.top,\n });\n }\n });\n\n // Right-click → ROI context menu\n el.addEventListener(\"contextmenu\", (e) => {\n e.preventDefault();\n e.stopPropagation();\n const roiId = (el as HTMLDivElement & { _roiId: string })._roiId;\n const clickedROI = this.getROIs().find((r) => r.id === roiId);\n if (clickedROI) {\n this.showROIContextMenu(clickedROI, e);\n }\n });\n\n return el;\n }\n\n /** Show context menu for an ROI. */\n private showROIContextMenu(roi: ROI, e: MouseEvent): void {\n if (!this.contextMenuProvider) return;\n\n const containerRect = this.container.getBoundingClientRect();\n const bpPerPixel =\n this._viewportWidth > 0\n ? (this._locus.end - this._locus.start) / this._viewportWidth\n : 0;\n const relX = e.clientX - containerRect.left - AXIS_COLUMN_WIDTH;\n const genomicLocation = this._locus.start + relX * bpPerPixel;\n\n // Emit event\n this.events.emit(BrowserEvent.ROIContextMenu, {\n roi,\n genomicLocation,\n x: e.clientX - containerRect.left,\n y: e.clientY - containerRect.top,\n });\n\n // Build menu items\n const callbacks: ROIMenuCallbacks = {\n goToRegion: (locus) => this.setLocus(locus),\n updateROI: (id, changes) => this.updateROI(id, changes),\n removeROI: (id) => this.removeROI(id),\n promptInput: async (label, value) => {\n if (!this.inputDialog) {\n if (!customElements.get(\"loom-input-dialog\")) {\n await import(\"./ui/components/LoomInputDialog\");\n }\n const el = document.createElement(\"loom-input-dialog\") as HTMLElement & {\n prompt(l: string, v: string | number): Promise<string | null>;\n };\n const pos = getComputedStyle(this.container).position;\n if (pos === \"static\") this.container.style.position = \"relative\";\n this.container.appendChild(el);\n this.inputDialog = el;\n }\n return this.inputDialog.prompt(label, value);\n },\n };\n\n const items = roiContextMenuItems(roi, callbacks);\n\n this.popupProvider?.hide();\n this.contextMenuProvider.show(\n items,\n {\n x: e.clientX - containerRect.left,\n y: e.clientY - containerRect.top,\n },\n this.container,\n );\n }\n\n /** Clean up ROI overlay elements. */\n private clearROIOverlay(): void {\n for (const el of this.roiElements.values()) {\n el.remove();\n }\n this.roiElements.clear();\n if (this.roiOverlayContainer) {\n this.roiOverlayContainer.remove();\n this.roiOverlayContainer = null;\n }\n }\n\n // ─── SVG/PNG Export ───────────────────────────────────────────────────\n\n /**\n * Export the current view as an SVG string, including axis columns.\n *\n * Overrides HeadlessGenomeBrowser.toSVG() to add axis rendering on the\n * left side of each track, matching igv.js Browser.toSVG() which calls\n * renderSVGAxis() for each TrackView (js/browser.ts lines 352-388).\n */\n override toSVG(options?: {\n width?: number;\n backdropColor?: string;\n }): string {\n const totalWidth =\n options?.width ?? this.container.clientWidth;\n const axisWidth = AXIS_COLUMN_WIDTH;\n const trackWidth = totalWidth - axisWidth;\n if (trackWidth <= 0)\n throw new Error(\"Cannot export SVG: container too narrow for axis\");\n\n // Compute total height\n let totalHeight = 0;\n const trackHeights: number[] = [];\n for (const mt of this.managedTracks) {\n const h = mt.track.height || 50;\n trackHeights.push(h);\n totalHeight += h;\n }\n\n const ctx = new C2S({\n width: totalWidth,\n height: totalHeight,\n viewbox: { x: 0, y: 0, width: totalWidth, height: totalHeight },\n backdropColor: options?.backdropColor ?? \"white\",\n });\n\n let y = 0;\n for (let i = 0; i < this.managedTracks.length; i++) {\n const track = this.managedTracks[i].track;\n const h = trackHeights[i];\n\n // Render axis (left column)\n const axisInfo = track.getAxisInfo?.();\n if (axisInfo) {\n const info: AxisInfo = {\n ...axisInfo,\n backgroundColor:\n axisInfo.backgroundColor ?? this.theme.palette.background,\n labelColor: axisInfo.labelColor ?? this.theme.palette.foreground,\n };\n const axisId = `track_${i}_${track.type}_axis`;\n ctx.saveWithTranslationAndClipRect(axisId, 0, y, axisWidth, h, 0);\n if (info.dataRange) {\n renderQuantitativeAxis(\n ctx as unknown as CanvasRenderingContext2D,\n info,\n axisWidth,\n h,\n );\n } else if (info.label) {\n renderLabelAxis(\n ctx as unknown as CanvasRenderingContext2D,\n info,\n axisWidth,\n h,\n );\n }\n ctx.restore();\n }\n\n // Render track (right of axis)\n const trackId = `track_${i}_${track.type}`;\n ctx.saveWithTranslationAndClipRect(trackId, axisWidth, y, trackWidth, h, 0);\n if (track.renderToContext) {\n track.renderToContext(\n ctx as unknown as CanvasRenderingContext2D,\n trackWidth,\n h,\n );\n }\n ctx.restore();\n\n y += h;\n }\n\n // Render ROI overlays on top of all tracks (offset by axis column)\n const visibleROIs = this.getVisibleROIs();\n if (visibleROIs.length > 0) {\n const bpPerPixel = (this._locus.end - this._locus.start) / trackWidth;\n const rc = { pixelWidth: trackWidth, bpStart: this._locus.start, bpPerPixel, viewportWidth: trackWidth };\n ctx.saveWithTranslationAndClipRect(\"roi_overlays\", axisWidth, 0, trackWidth, totalHeight, 0);\n renderROIOverlays(\n ctx as unknown as CanvasRenderingContext2D,\n visibleROIs,\n rc,\n { totalHeight },\n );\n ctx.restore();\n }\n\n ctx.setHeight(totalHeight);\n return ctx.getSerializedSvg(true);\n }\n\n /**\n * Export the current view as a PNG data URL.\n *\n * Pipeline: toSVG() → Blob → Image → Canvas (DPR-scaled) → toDataURL.\n * Matches igv.js Browser.savePNGtoFile() (js/browser.ts lines 407-440).\n *\n * Returns a promise that resolves to a `data:image/png;base64,...` string.\n */\n async toPNG(): Promise<string> {\n const svgString = this.toSVG();\n const blob = new Blob([svgString], { type: \"image/svg+xml\" });\n const url = URL.createObjectURL(blob);\n\n try {\n return await new Promise<string>((resolve, reject) => {\n const img = new Image();\n img.onload = () => {\n try {\n const dpr = this.canvasProvider.devicePixelRatio;\n const canvas = document.createElement(\"canvas\");\n const rect = this.container.getBoundingClientRect();\n const w = rect.width;\n const h = rect.height;\n canvas.width = w * dpr;\n canvas.height = h * dpr;\n const canvasCtx = canvas.getContext(\"2d\")!;\n canvasCtx.scale(dpr, dpr);\n canvasCtx.drawImage(img, 0, 0);\n resolve(canvas.toDataURL(\"image/png\"));\n } catch (err) {\n reject(err);\n }\n };\n img.onerror = () => reject(new Error(\"Failed to load SVG for PNG conversion\"));\n img.src = url;\n });\n } finally {\n URL.revokeObjectURL(url);\n }\n }\n\n /**\n * Download the current view as an SVG file.\n * Matches igv.js Browser.saveSVGtoFile() (js/browser.ts lines 390-405).\n */\n saveSVGtoFile(filename?: string): void {\n const svgString = this.toSVG();\n const blob = new Blob([svgString], { type: \"application/octet-stream\" });\n const url = URL.createObjectURL(blob);\n this.downloadURL(filename || \"igv.svg\", url);\n URL.revokeObjectURL(url);\n }\n\n /**\n * Download the current view as a PNG file.\n * Matches igv.js Browser.savePNGtoFile() (js/browser.ts lines 407-440).\n */\n async savePNGtoFile(filename?: string): Promise<void> {\n const dataURL = await this.toPNG();\n this.downloadURL(filename || \"igv.png\", dataURL);\n }\n\n /** Trigger a file download via a temporary anchor element. */\n private downloadURL(filename: string, url: string): void {\n const a = document.createElement(\"a\");\n a.download = filename;\n a.href = url;\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n }\n}\n","/**\n * Common context menu item factories.\n *\n * Stateless functions that return ContextMenuItem[] — no DOM, no side effects.\n * The ContextMenuCallbacks interface decouples menu items from browser-level\n * actions (removing tracks, showing dialogs).\n *\n * `numericDataMenuItems()` mirrors igv.js `TrackBase.numericDataMenuItems()`\n * (js/trackBase.ts lines 510-552), which is shared by WigTrack, BAMTrack,\n * QTLTrack, GCNVTrack, CNVPytorTrack, GWASTrack, InteractionTrack, and\n * MergedTrack — any track with a Y-axis data range.\n */\n\nimport type {ContextMenuItem, NumericState, Track, ROI, Locus} from './types'\n\n/**\n * Callback interface for common menu actions that require browser-level\n * coordination. GenomeBrowser provides the implementation.\n */\nexport interface ContextMenuCallbacks {\n /** Set the track's pixel height and re-render. */\n setTrackHeight(track: Track, height: number): void\n /** Remove the track from the browser. */\n removeTrack(track: Track): void\n /** Show an input dialog. Returns the entered value, or null if cancelled. */\n promptInput(label: string, currentValue: string | number): Promise<string | null>\n}\n\n// ─── Menu item factories ─────────────────────────────────────────────────────\n\n/** Common menu items that apply to all tracks (set height, remove). */\nexport function commonContextMenuItems(\n track: Track,\n callbacks: ContextMenuCallbacks,\n): ContextMenuItem[] {\n return [\n {\n label: 'Set track height',\n action: async () => {\n const value = await callbacks.promptInput('Track height (px)', track.height)\n if (value !== null) {\n const h = parseInt(value, 10)\n if (h > 0 && !isNaN(h)) callbacks.setTrackHeight(track, h)\n }\n },\n },\n {\n label: 'Remove track',\n action: () => callbacks.removeTrack(track),\n },\n ]\n}\n\n/**\n * Menu items for quantitative/numeric tracks: set data range, log scale, autoscale.\n *\n * Mirrors igv.js `TrackBase.numericDataMenuItems()` (js/trackBase.ts lines 510-552).\n * In igv.js this is a method on TrackBase used by 8 track classes. In our\n * architecture it's a stateless factory that takes the track's NumericState\n * (state + callbacks combined), matching our separation of data from DOM.\n *\n * Items produced:\n * 1. \"Set data range\" — prompts for min/max, disables autoscale when set\n * (mirrors igv.js DataRangeDialog → TrackBase.setDataRange)\n * 2. \"Log scale\" checkbox — only if logScale is supported (state.logScale !== undefined)\n * (mirrors igv.js conditional on this.logScale !== undefined)\n * 3. \"Autoscale\" checkbox\n * (mirrors igv.js autoScaleHandler)\n */\nexport function numericDataMenuItems(\n state: NumericState,\n promptInput: ContextMenuCallbacks['promptInput'],\n): ContextMenuItem[] {\n const items: ContextMenuItem[] = []\n\n // Set data range — mirrors igv.js DataRangeDialog (js/ui/components/dataRangeDialog.ts)\n items.push({\n label: 'Set data range',\n action: async () => {\n const minStr = await promptInput('Minimum', state.dataRange.min)\n if (minStr === null) return\n const maxStr = await promptInput('Maximum', state.dataRange.max)\n if (maxStr === null) return\n const min = parseFloat(minStr)\n const max = parseFloat(maxStr)\n if (!isNaN(min) && !isNaN(max) && min < max) {\n state.setDataRange(min, max)\n }\n },\n })\n\n // Log scale — conditional, matches igv.js `if (this.logScale !== undefined)`\n if (state.logScale !== undefined && state.setLogScale) {\n items.push({\n label: 'Log scale',\n type: 'checkbox',\n checked: state.logScale,\n action: () => state.setLogScale!(!state.logScale),\n })\n }\n\n // Autoscale — always shown for numeric tracks\n items.push({\n label: 'Autoscale',\n type: 'checkbox',\n checked: state.autoscale,\n action: () => state.setAutoscale(!state.autoscale),\n })\n\n return items\n}\n\n// ─── ROI menu item factories ─────────────────────────────────────────────────\n\n/**\n * Callback interface for ROI menu actions that require browser-level coordination.\n */\nexport interface ROIMenuCallbacks {\n /** Navigate the browser to the ROI's genomic region. */\n goToRegion(locus: Locus): void\n /** Update an ROI's properties. */\n updateROI(roiId: string, changes: Partial<Omit<ROI, 'id'>>): void\n /** Remove an ROI by ID. */\n removeROI(roiId: string): void\n /** Show an input dialog. Returns the entered value, or null if cancelled. */\n promptInput(label: string, currentValue: string | number): Promise<string | null>\n}\n\n/**\n * Context menu items for an ROI region.\n *\n * Mirrors igv.js ROIMenu (js/roi/ROIMenu.ts) but with stateless factory pattern.\n * Items: edit name, edit description, set color, separator, go to region, remove.\n */\nexport function roiContextMenuItems(\n roi: ROI,\n callbacks: ROIMenuCallbacks,\n): ContextMenuItem[] {\n return [\n {\n label: 'Edit name...',\n action: async () => {\n const name = await callbacks.promptInput('ROI name', roi.name ?? '')\n if (name !== null) callbacks.updateROI(roi.id, {name})\n },\n },\n {\n label: 'Edit description...',\n action: async () => {\n const desc = await callbacks.promptInput('Description', roi.description ?? '')\n if (desc !== null) callbacks.updateROI(roi.id, {description: desc})\n },\n },\n {\n label: 'Set color...',\n action: async () => {\n const color = await callbacks.promptInput('Color (CSS)', roi.color ?? 'rgba(68, 134, 247, 0.15)')\n if (color !== null) callbacks.updateROI(roi.id, {color})\n },\n },\n {label: '', type: 'separator'},\n {\n label: 'Go to region',\n action: () => callbacks.goToRegion({chr: roi.chr, start: roi.start, end: roi.end}),\n },\n {\n label: 'Remove',\n action: () => callbacks.removeROI(roi.id),\n },\n ]\n}\n","import {createContext} from 'react'\nimport type {GenomeBrowser} from '../genomeBrowser'\n\nexport interface GenomeBrowserContextValue {\n /** The underlying GenomeBrowser instance. null before initialization or during SSR. */\n browser: GenomeBrowser | null\n}\n\nexport const GenomeBrowserContext = createContext<GenomeBrowserContextValue | null>(null)\n","import {\n useRef, useEffect, useState, useImperativeHandle, forwardRef, useMemo,\n type ReactNode, type CSSProperties,\n} from 'react'\nimport type {\n Locus, Genome, SessionConfig, TrackSessionConfig, Track,\n ROI, ROISetConfig,\n} from '../types'\nimport type {RenderTheme} from '../themes/renderTheme'\nimport type {WorkerProvider} from '../workerProvider'\nimport type {PopupProvider} from '../popupProvider'\nimport type {ContextMenuProvider} from '../contextMenuProvider'\nimport type {RemoteSocket} from '../remoteProtocol'\nimport {GenomeBrowser} from '../genomeBrowser'\nimport type {GenomeBrowserOptions} from '../genomeBrowser'\nimport {BrowserEvent} from '../headlessGenomeBrowser'\nimport type {ManagedTrack} from '../headlessGenomeBrowser'\nimport type {CreateTrackFromSessionOptions} from '../session'\nimport type {TrackSelector} from '../trackSelector'\nimport {ROISet} from '../roi/roiSet'\nimport {GenomeBrowserContext} from './GenomeBrowserContext'\n\nexport interface LoomBrowserProps {\n // ─── Locus ────────────────────────────────────────────────────────────\n /** Initial locus (uncontrolled mode). */\n defaultLocus?: Locus\n /** Controlled locus. Browser navigates to this on every change. */\n locus?: Locus\n /** Called when user interaction changes the locus. Required for controlled mode. */\n onLocusChange?: (locus: Locus) => void\n\n // ─── Appearance ───────────────────────────────────────────────────────\n /** Render theme. Changes are applied via browser.setTheme(). */\n theme?: Partial<RenderTheme>\n /** Genome assembly. Default: hg38Genome. Pass null to disable. */\n genome?: Genome | null\n\n // ─── Interaction ──────────────────────────────────────────────────────\n /** Enable drag-to-pan. Default: true. */\n interactive?: boolean\n /** Enable wheel zoom. Default: true. */\n wheelZoom?: boolean\n\n // ─── Providers ────────────────────────────────────────────────────────\n /** Worker provider for off-main-thread tasks. */\n workerProvider?: WorkerProvider\n /** Popup provider. Pass null to disable. */\n popupProvider?: PopupProvider | null\n /** Context menu provider. Pass null to disable. */\n contextMenuProvider?: ContextMenuProvider | null\n\n // ─── Convenience default tracks ───────────────────────────────────────\n /** Auto-add a ruler track. Default: true. */\n ruler?: boolean\n /** Auto-add a gene annotation track (UCSC RefSeq). Default: true. */\n genes?: boolean\n /** Auto-add a sequence track. Default: true. */\n sequence?: boolean\n\n // ─── Session / track configs ──────────────────────────────────────────\n /** Load a session config on mount (tracks, ROIs, theme from session). */\n session?: SessionConfig\n /** Add tracks from config objects. Alternative to JSX children for data-driven UIs. */\n tracks?: TrackSessionConfig[]\n\n // ─── Remote protocol ──────────────────────────────────────────────────\n /** WebSocket or compatible socket to attach for remote control. */\n remoteSocket?: RemoteSocket | null\n\n // ─── DOM ──────────────────────────────────────────────────────────────\n /** CSS className for the container div. */\n className?: string\n /** CSS style for the container div. */\n style?: CSSProperties\n /** Track and other children. */\n children?: ReactNode\n}\n\nexport interface LoomBrowserHandle {\n /** The underlying GenomeBrowser instance. null during SSR. */\n readonly browser: GenomeBrowser | null\n\n // ─── Navigation ───────────────────────────────────────────────────────\n search(query: string): boolean\n zoomIn(factor?: number): void\n zoomOut(factor?: number): void\n\n // ─── Track management ─────────────────────────────────────────────────\n addTrackFromConfig(config: TrackSessionConfig): Track\n getTrackOrder(): Track[]\n getManagedTracks(): readonly ManagedTrack[]\n findTracks(selector: TrackSelector): ManagedTrack[]\n moveTrack(track: Track, toIndex: number): void\n removeTracks(selector: TrackSelector): number\n updateTrackMetadata(selector: TrackSelector, metadata: Record<string, string>): number\n getCachedFeatures<F>(track: Track): F[] | undefined\n reloadData(): void\n\n // ─── ROI ──────────────────────────────────────────────────────────────\n addROI(roi: ROI, setName?: string): ROI\n addROISet(config: ROISetConfig): ROISet\n removeROI(roiId: string): boolean\n updateROI(roiId: string, changes: Partial<Omit<ROI, 'id'>>): ROI | undefined\n clearROIs(): void\n getROIs(): ROI[]\n getROISets(): readonly ROISet[]\n findROIsAtLocus(chr: string, start: number, end: number): ROI[]\n getVisibleROIs(): ROI[]\n\n // ─── Session / export ─────────────────────────────────────────────────\n toJSON(): SessionConfig\n loadSession(session: SessionConfig, options?: CreateTrackFromSessionOptions): void\n toSVG(): string\n toPNG(): Promise<string>\n saveSVGtoFile(filename?: string): void\n savePNGtoFile(filename?: string): Promise<void>\n\n // ─── Remote ───────────────────────────────────────────────────────────\n attachRemote(socket: RemoteSocket): void\n detachRemote(): void\n}\n\nexport const LoomBrowser = forwardRef<LoomBrowserHandle, LoomBrowserProps>(\n function LoomBrowser(props, ref) {\n const {\n defaultLocus, locus, onLocusChange,\n theme, genome, interactive, wheelZoom,\n workerProvider, popupProvider, contextMenuProvider,\n ruler, genes, sequence,\n session, tracks: trackConfigs,\n remoteSocket,\n className, style, children,\n } = props\n\n const containerRef = useRef<HTMLDivElement>(null)\n const browserRef = useRef<GenomeBrowser | null>(null)\n const [browser, setBrowser] = useState<GenomeBrowser | null>(null)\n\n // Ref flag to prevent feedback loop: skip onLocusChange when we set locus from prop\n const settingLocusFromProp = useRef(false)\n // Keep onLocusChange ref current without re-subscribing\n const onLocusChangeRef = useRef(onLocusChange)\n onLocusChangeRef.current = onLocusChange\n\n // Create browser on mount\n useEffect(() => {\n const container = containerRef.current\n if (!container) return\n\n const initialLocus = locus ?? defaultLocus ?? session?.locus\n if (!initialLocus) {\n throw new Error('<LoomBrowser> requires a `locus`, `defaultLocus`, or `session` prop')\n }\n\n const options: GenomeBrowserOptions = {\n locus: initialLocus,\n interactive,\n wheelZoom,\n workerProvider,\n popupProvider,\n contextMenuProvider,\n }\n if (theme !== undefined) options.theme = theme\n if (session?.theme !== undefined && theme === undefined) options.theme = session.theme\n if (genome !== undefined) options.genome = genome\n\n const b = new GenomeBrowser(container, options)\n browserRef.current = b\n\n // Load session tracks if provided\n if (session) {\n b.loadSession(session)\n }\n\n // Add config-driven tracks\n if (trackConfigs) {\n for (const tc of trackConfigs) {\n b.addTrackFromConfig(tc)\n }\n }\n\n // Convenience default tracks (default: true)\n if (ruler !== false) b.addRuler()\n if (genes !== false) b.addGeneTrack()\n if (sequence !== false) b.addSequenceTrack()\n\n // Forward locus changes to onLocusChange (for controlled mode)\n b.on(BrowserEvent.LocusChange, ({locus: newLocus}) => {\n if (settingLocusFromProp.current) {\n settingLocusFromProp.current = false\n return\n }\n onLocusChangeRef.current?.(newLocus)\n })\n\n setBrowser(b)\n\n return () => {\n b.dispose()\n browserRef.current = null\n setBrowser(null)\n }\n // Only re-create the browser if the container element changes (shouldn't happen)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n // Controlled locus: sync prop → browser\n useEffect(() => {\n const b = browserRef.current\n if (!b || !locus) return\n const current = b.locus\n if (current.chr === locus.chr && current.start === locus.start && current.end === locus.end) return\n settingLocusFromProp.current = true\n b.setLocus(locus)\n }, [locus?.chr, locus?.start, locus?.end])\n\n // Theme changes\n useEffect(() => {\n if (!browserRef.current || theme === undefined) return\n browserRef.current.setTheme(theme)\n }, [theme])\n\n // Remote socket: attach/detach\n useEffect(() => {\n const b = browserRef.current\n if (!b) return\n if (remoteSocket) {\n b.attachRemote(remoteSocket)\n return () => { b.detachRemote() }\n } else {\n b.detachRemote()\n }\n }, [remoteSocket])\n\n // Imperative handle — exposes full API surface\n useImperativeHandle(ref, () => ({\n get browser() { return browserRef.current },\n\n // Navigation\n search(query: string) { return browserRef.current?.search(query) ?? false },\n zoomIn(factor?: number) { browserRef.current?.zoomIn(factor) },\n zoomOut(factor?: number) { browserRef.current?.zoomOut(factor) },\n\n // Track management\n addTrackFromConfig(config: TrackSessionConfig) { return browserRef.current!.addTrackFromConfig(config) },\n getTrackOrder() { return browserRef.current?.getTrackOrder() ?? [] },\n getManagedTracks() { return browserRef.current?.getManagedTracks() ?? [] },\n findTracks(selector: TrackSelector) { return browserRef.current?.findTracks(selector) ?? [] },\n moveTrack(track: Track, toIndex: number) { browserRef.current?.moveTrack(track, toIndex) },\n removeTracks(selector: TrackSelector) { return browserRef.current?.removeTracks(selector) ?? 0 },\n updateTrackMetadata(selector: TrackSelector, metadata: Record<string, string>) {\n return browserRef.current?.updateTrackMetadata(selector, metadata) ?? 0\n },\n getCachedFeatures<F>(track: Track) { return browserRef.current?.getCachedFeatures<F>(track) },\n reloadData() { browserRef.current?.reloadData() },\n\n // ROI\n addROI(roi: ROI, setName?: string) { return browserRef.current!.addROI(roi, setName) },\n addROISet(config: ROISetConfig) { return browserRef.current!.addROISet(config) },\n removeROI(roiId: string) { return browserRef.current?.removeROI(roiId) ?? false },\n updateROI(roiId: string, changes: Partial<Omit<ROI, 'id'>>) { return browserRef.current?.updateROI(roiId, changes) },\n clearROIs() { browserRef.current?.clearROIs() },\n getROIs() { return browserRef.current?.getROIs() ?? [] },\n getROISets() { return browserRef.current?.getROISets() ?? [] },\n findROIsAtLocus(chr: string, start: number, end: number) { return browserRef.current?.findROIsAtLocus(chr, start, end) ?? [] },\n getVisibleROIs() { return browserRef.current?.getVisibleROIs() ?? [] },\n\n // Session / export\n toJSON() { return browserRef.current!.toJSON() },\n loadSession(session: SessionConfig, options?: CreateTrackFromSessionOptions) { browserRef.current?.loadSession(session, options) },\n toSVG() { return browserRef.current?.toSVG() ?? '' },\n async toPNG() { return browserRef.current?.toPNG() ?? '' },\n saveSVGtoFile(filename?: string) { browserRef.current?.saveSVGtoFile(filename) },\n async savePNGtoFile(filename?: string) { await browserRef.current?.savePNGtoFile(filename) },\n\n // Remote\n attachRemote(socket: RemoteSocket) { browserRef.current?.attachRemote(socket) },\n detachRemote() { browserRef.current?.detachRemote() },\n }), [browser])\n\n const ctxValue = useMemo(() => ({browser}), [browser])\n\n return (\n <GenomeBrowserContext.Provider value={ctxValue}>\n <div ref={containerRef} className={className} style={style} />\n {browser && children}\n </GenomeBrowserContext.Provider>\n )\n }\n)\n","import {useContext} from 'react'\nimport {GenomeBrowserContext} from '../GenomeBrowserContext'\nimport type {GenomeBrowser} from '../../genomeBrowser'\n\n/**\n * Access the GenomeBrowser instance from context.\n * Returns null before the browser initializes (SSR or first render).\n * Must be used within a `<LoomBrowser>` component.\n */\nexport function useGenomeBrowser(): GenomeBrowser | null {\n const ctx = useContext(GenomeBrowserContext)\n if (ctx === null) {\n throw new Error('useGenomeBrowser must be used within a <LoomBrowser> component')\n }\n return ctx.browser\n}\n","import {useEffect, useRef} from 'react'\nimport type {BrowserEvents} from '../../headlessGenomeBrowser'\nimport {useGenomeBrowser} from './useGenomeBrowser'\n\n/**\n * Subscribe to a typed browser event. Automatically subscribes/unsubscribes\n * with the browser lifecycle. Uses a stable ref for the handler to avoid\n * re-subscribing on every render.\n */\nexport function useBrowserEvent<K extends keyof BrowserEvents>(\n event: K,\n handler: (data: BrowserEvents[K]) => void,\n): void {\n const browser = useGenomeBrowser()\n const handlerRef = useRef(handler)\n handlerRef.current = handler\n\n useEffect(() => {\n if (!browser) return\n const listener = (data: BrowserEvents[K]) => handlerRef.current(data)\n browser.on(event, listener)\n return () => { browser.off(event, listener) }\n }, [browser, event])\n}\n","import {useState, useCallback} from 'react'\nimport type {Locus} from '../../types'\nimport {BrowserEvent} from '../../headlessGenomeBrowser'\nimport {useGenomeBrowser} from './useGenomeBrowser'\nimport {useBrowserEvent} from './useBrowserEvent'\n\n/**\n * Convenience hook for locus state and navigation.\n * Tracks the current locus via the locuschange event and exposes nav helpers.\n */\nexport function useLocus(): {\n locus: Locus | null\n setLocus: (locus: Locus) => void\n zoomIn: (factor?: number) => void\n zoomOut: (factor?: number) => void\n} {\n const browser = useGenomeBrowser()\n const [locus, setLocusState] = useState<Locus | null>(() => browser?.locus ?? null)\n\n useBrowserEvent(BrowserEvent.LocusChange, ({locus: newLocus}) => {\n setLocusState(newLocus)\n })\n\n const setLocus = useCallback((l: Locus) => {\n browser?.setLocus(l)\n }, [browser])\n\n const zoomIn = useCallback((factor?: number) => {\n browser?.zoomIn(factor)\n }, [browser])\n\n const zoomOut = useCallback((factor?: number) => {\n browser?.zoomOut(factor)\n }, [browser])\n\n return {locus, setLocus, zoomIn, zoomOut}\n}\n","import {useEffect, useRef} from 'react'\nimport type {Track} from '../../types'\nimport type {GenomeBrowser} from '../../genomeBrowser'\nimport {useGenomeBrowser} from './useGenomeBrowser'\n\n/**\n * Internal hook that manages track add/remove/update lifecycle.\n *\n * @param addTrack Called to add the track. Returns the track instance.\n * @param recreationDeps When these change, the track is removed and re-added (new data source).\n * @param updateTrack Called when only updateDeps change (in-place config update).\n * @param updateDeps When these change (but recreationDeps don't), updateTrack is called.\n */\nexport function useTrackManager<T extends Track>(\n addTrack: (browser: GenomeBrowser) => T,\n recreationDeps: unknown[],\n updateTrack?: (track: T, browser: GenomeBrowser) => void,\n updateDeps?: unknown[],\n): T | null {\n const browser = useGenomeBrowser()\n const trackRef = useRef<T | null>(null)\n const prevRecreationDeps = useRef<unknown[]>(recreationDeps)\n const isFirstRender = useRef(true)\n\n // Add track on mount or when recreation deps change\n useEffect(() => {\n if (!browser) return\n\n const track = addTrack(browser)\n trackRef.current = track\n\n return () => {\n if (trackRef.current) {\n browser.removeTrack(trackRef.current)\n trackRef.current = null\n }\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [browser, ...recreationDeps])\n\n // Update track in place when only update deps change\n useEffect(() => {\n if (isFirstRender.current) {\n isFirstRender.current = false\n return\n }\n if (!browser || !trackRef.current || !updateTrack) return\n\n // Skip if recreation deps changed (the other effect handles that)\n const recreationChanged = recreationDeps.some(\n (dep, i) => dep !== prevRecreationDeps.current[i]\n )\n prevRecreationDeps.current = recreationDeps\n if (recreationChanged) return\n\n updateTrack(trackRef.current, browser)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, updateDeps)\n\n return trackRef.current\n}\n","import type {RulerRenderConfig} from '../../types'\nimport {useTrackManager} from '../hooks/useTrackManager'\n\nexport interface RulerTrackProps {\n config?: Partial<RulerRenderConfig>\n maxTrackHeight?: number\n}\n\nexport function RulerTrack({config, maxTrackHeight}: RulerTrackProps) {\n useTrackManager(\n (browser) => browser.addRuler({config, maxTrackHeight}),\n [],\n (track) => { if (config) track.setConfig(config) },\n [config],\n )\n return null\n}\n","import type {WigRenderConfig, WindowFunction} from '../../types'\nimport {useTrackManager} from '../hooks/useTrackManager'\n\nexport interface WigTrackProps {\n url: string\n config?: Partial<WigRenderConfig>\n height?: number\n background?: string\n windowFunction?: WindowFunction\n maxTrackHeight?: number\n name?: string\n metadata?: Record<string, string>\n}\n\nexport function WigTrack({url, config, height, background, windowFunction, maxTrackHeight, name, metadata}: WigTrackProps) {\n useTrackManager(\n (browser) => browser.addWigTrack(url, {config, height, background, windowFunction, maxTrackHeight, name, metadata}),\n [url, windowFunction],\n (track) => { if (config) track.setConfig(config) },\n [config, height, background, name],\n )\n return null\n}\n","import type {AnnotationRenderConfig} from '../../types'\nimport {useTrackManager} from '../hooks/useTrackManager'\n\nexport interface GeneTrackProps {\n config?: Partial<AnnotationRenderConfig>\n height?: number\n background?: string\n /** UCSC assembly name. Default: 'hg38'. */\n genome?: string\n /** UCSC track name. Default: 'ncbiRefSeq'. */\n track?: string\n maxTrackHeight?: number\n name?: string\n metadata?: Record<string, string>\n}\n\nexport function GeneTrack({config, height, background, genome, track, maxTrackHeight, name, metadata}: GeneTrackProps) {\n useTrackManager(\n (browser) => browser.addGeneTrack({config, height, background, genome, track, maxTrackHeight, name, metadata}),\n [genome, track],\n (t) => { if (config) t.setConfig(config) },\n [config, height, background, name],\n )\n return null\n}\n","import type {AnnotationRenderConfig, TextFileFormat} from '../../types'\nimport {useTrackManager} from '../hooks/useTrackManager'\n\nexport interface BedTrackProps {\n url: string\n config?: Partial<AnnotationRenderConfig>\n height?: number\n background?: string\n format?: TextFileFormat\n indexURL?: string\n indexed?: boolean\n maxTrackHeight?: number\n name?: string\n metadata?: Record<string, string>\n}\n\nexport function BedTrack({url, config, height, background, format, indexURL, indexed, maxTrackHeight, name, metadata}: BedTrackProps) {\n useTrackManager(\n (browser) => browser.addBedTrack(url, {config, height, background, format, indexURL, indexed, maxTrackHeight, name, metadata}),\n [url, format, indexURL, indexed],\n (track) => { if (config) track.setConfig(config) },\n [config, height, background, name],\n )\n return null\n}\n","import type {SequenceRenderConfig} from '../../types'\nimport {useTrackManager} from '../hooks/useTrackManager'\n\nexport interface SequenceTrackProps {\n config?: Partial<SequenceRenderConfig>\n maxTrackHeight?: number\n}\n\nexport function SequenceTrack({config, maxTrackHeight}: SequenceTrackProps) {\n useTrackManager(\n (browser) => browser.addSequenceTrack({config, maxTrackHeight}),\n [],\n (track) => { if (config) track.setConfig(config) },\n [config],\n )\n return null\n}\n","import type {InteractionRenderConfig, TextFileFormat} from '../../types'\nimport {useTrackManager} from '../hooks/useTrackManager'\n\nexport interface InteractionTrackProps {\n url: string\n config?: Partial<InteractionRenderConfig>\n background?: string\n format?: TextFileFormat\n indexURL?: string\n indexed?: boolean\n name?: string\n metadata?: Record<string, string>\n}\n\nexport function InteractionTrack({url, config, background, format, indexURL, indexed, name, metadata}: InteractionTrackProps) {\n useTrackManager(\n (browser) => browser.addInteractionTrack(url, {config, background, format, indexURL, indexed, name, metadata}),\n [url, format, indexURL, indexed],\n (track) => { if (config) track.setConfig(config) },\n [config, background, name],\n )\n return null\n}\n","import type {WigRenderConfig, WindowFunction} from '../../types'\nimport {useTrackManager} from '../hooks/useTrackManager'\n\nexport interface GtxTrackProps {\n url: string\n experimentId: string\n config?: Partial<WigRenderConfig>\n height?: number\n background?: string\n windowFunction?: WindowFunction\n maxTrackHeight?: number\n name?: string\n metadata?: Record<string, string>\n}\n\nexport function GtxTrack({url, experimentId, config, height, background, windowFunction, maxTrackHeight, name, metadata}: GtxTrackProps) {\n useTrackManager(\n (browser) => browser.addGtxTrack(url, {experimentId, config, height, background, windowFunction, maxTrackHeight, name, metadata}),\n [url, experimentId, windowFunction],\n (track) => { if (config) track.setConfig(config) },\n [config, height, background, name],\n )\n return null\n}\n","/**\n * <loom-context-menu> — Right-click context menu Web Component.\n *\n * Renders ContextMenuItem[] as a styled menu with action items, checkboxes,\n * separators, and one level of submenu nesting.\n *\n * Also exports DefaultContextMenuProvider which wraps this component and\n * implements the ContextMenuProvider interface.\n *\n * Customizable via CSS custom properties:\n * --loom-menu-bg, --loom-menu-border, --loom-menu-radius, --loom-menu-shadow,\n * --loom-menu-font, --loom-menu-color, --loom-menu-hover, --loom-menu-divider\n */\n\nimport type {ContextMenuItem} from '../../types'\nimport type {ContextMenuProvider} from '../../contextMenuProvider'\n\nconst TEMPLATE_HTML = /* html */`\n<style>\n:host {\n position: absolute;\n z-index: 100001;\n pointer-events: auto;\n display: none;\n user-select: text;\n -webkit-user-select: text;\n cursor: auto;\n}\n.menu {\n background: var(--loom-menu-bg, var(--loom-input-bg, white));\n border: var(--loom-menu-border, var(--loom-border, 1px solid #ccc));\n border-radius: var(--loom-menu-radius, var(--loom-border-radius, 4px));\n box-shadow: var(--loom-menu-shadow, 0 2px 8px rgba(0,0,0,0.18));\n padding: 4px 0;\n font: var(--loom-menu-font, var(--loom-font-small, 12px/1.4 sans-serif));\n color: var(--loom-menu-color, var(--loom-text-color, #333));\n min-width: 160px;\n}\n.item {\n padding: 6px 12px;\n cursor: pointer;\n white-space: nowrap;\n display: flex;\n align-items: center;\n gap: 6px;\n position: relative;\n}\n.item:hover {\n background: var(--loom-menu-hover, var(--loom-button-hover, #f0f0f0));\n}\n.item.disabled {\n opacity: 0.45;\n pointer-events: none;\n}\n.separator {\n height: 1px;\n background: var(--loom-menu-divider, var(--loom-button-hover, #e0e0e0));\n margin: 4px 0;\n}\n.check {\n width: 14px;\n text-align: center;\n flex-shrink: 0;\n font-size: 11px;\n}\n.label {\n flex: 1;\n}\n.arrow {\n font-size: 9px;\n color: #999;\n margin-left: 8px;\n}\n.submenu {\n position: absolute;\n left: 100%;\n top: -4px;\n display: none;\n}\n.item:hover > .submenu {\n display: block;\n}\n</style>\n<div class=\"menu\"></div>\n`\n\nexport class LoomContextMenu extends HTMLElement {\n private menuDiv!: HTMLDivElement\n\n constructor() {\n super()\n this.attachShadow({mode: 'open'})\n }\n\n connectedCallback(): void {\n const tpl = document.createElement('template')\n tpl.innerHTML = TEMPLATE_HTML\n this.shadowRoot!.appendChild(tpl.content.cloneNode(true))\n this.menuDiv = this.shadowRoot!.querySelector('.menu')!\n }\n\n /** Populate the menu from typed ContextMenuItem data. */\n setItems(items: ContextMenuItem[]): void {\n if (!this.menuDiv) return\n this.menuDiv.innerHTML = ''\n this.buildItems(items, this.menuDiv)\n }\n\n private buildItems(items: ContextMenuItem[], container: HTMLElement): void {\n for (const item of items) {\n if (item.type === 'separator') {\n const sep = document.createElement('div')\n sep.className = 'separator'\n container.appendChild(sep)\n continue\n }\n\n const div = document.createElement('div')\n div.className = 'item' + (item.disabled ? ' disabled' : '')\n\n // Checkbox indicator\n const check = document.createElement('span')\n check.className = 'check'\n check.textContent = item.type === 'checkbox' && item.checked ? '\\u2713' : ''\n div.appendChild(check)\n\n // Label text\n const label = document.createElement('span')\n label.className = 'label'\n label.textContent = item.label\n div.appendChild(label)\n\n // Submenu\n if (item.children && item.children.length > 0) {\n const arrow = document.createElement('span')\n arrow.className = 'arrow'\n arrow.textContent = '\\u25B6'\n div.appendChild(arrow)\n\n const submenu = document.createElement('div')\n submenu.className = 'submenu menu'\n this.buildItems(item.children, submenu)\n div.appendChild(submenu)\n }\n\n // Direct click handler on each item (inside shadow DOM).\n // stopPropagation prevents the container's pointer handlers from\n // interfering; the isContextMenuTarget guard in GenomeBrowser also\n // prevents the container from dismissing the menu before click fires.\n if (item.action && !item.disabled) {\n const action = item.action\n // Stop pointer/mouse events from reaching the container's drag handlers\n div.addEventListener('pointerdown', (e: Event) => { e.stopPropagation() })\n div.addEventListener('pointerup', (e: Event) => { e.stopPropagation() })\n div.addEventListener('click', (e: MouseEvent) => {\n e.stopPropagation()\n action()\n this.hide()\n })\n div.addEventListener('mousedown', (e: Event) => { e.stopPropagation() })\n div.addEventListener('mouseup', (e: Event) => { e.stopPropagation() })\n }\n\n container.appendChild(div)\n }\n }\n\n /** Position and show the menu, clamping to container bounds. */\n showAt(x: number, y: number): void {\n this.style.display = 'block'\n this.style.left = `${x}px`\n this.style.top = `${y}px`\n\n // Clamp to container after layout\n requestAnimationFrame(() => {\n const parent = this.offsetParent as HTMLElement | null\n if (!parent) return\n const parentRect = parent.getBoundingClientRect()\n const menuRect = this.getBoundingClientRect()\n\n let left = x\n let top = y\n if (left + menuRect.width > parentRect.width) left = Math.max(0, x - menuRect.width)\n if (top + menuRect.height > parentRect.height) top = Math.max(0, y - menuRect.height)\n\n this.style.left = `${left}px`\n this.style.top = `${top}px`\n })\n }\n\n hide(): void {\n this.style.display = 'none'\n }\n}\n\nif (typeof customElements !== 'undefined' && !customElements.get('loom-context-menu')) {\n customElements.define('loom-context-menu', LoomContextMenu)\n}\n\n/**\n * Default ContextMenuProvider using the <loom-context-menu> Web Component.\n * Lazily creates the element on first show() call (same pattern as DefaultPopupProvider).\n */\nexport class DefaultContextMenuProvider implements ContextMenuProvider {\n private element: LoomContextMenu | null = null\n\n show(items: ContextMenuItem[], position: {x: number; y: number}, container: HTMLElement): void {\n if (!this.element) {\n this.element = document.createElement('loom-context-menu') as LoomContextMenu\n const pos = getComputedStyle(container).position\n if (pos === 'static') container.style.position = 'relative'\n container.appendChild(this.element)\n }\n this.element.setItems(items)\n this.element.showAt(position.x, position.y)\n }\n\n hide(): void {\n if (this.element) this.element.hide()\n }\n\n dispose(): void {\n if (this.element) {\n this.element.remove()\n this.element = null\n }\n }\n}\n","/**\n * <loom-popup> — Feature popup / tooltip Web Component.\n *\n * Renders PopupDataItem[] as a name/value table. Positioned as a floating\n * element near the pointer, clamped to stay within the viewport.\n *\n * Also exports DefaultPopupProvider which wraps this component and\n * implements the PopupProvider interface.\n */\n\nimport type {PopupDataItem} from '../../types'\nimport type {PopupProvider} from '../../popupProvider'\n\nconst TEMPLATE_HTML = /* html */`\n<style>\n:host {\n position: absolute;\n z-index: 100000;\n pointer-events: auto;\n display: none;\n user-select: text;\n -webkit-user-select: text;\n cursor: auto;\n}\n.popup {\n background: var(--loom-popup-bg, var(--loom-input-bg, white));\n border: var(--loom-popup-border, var(--loom-border, 1px solid #ccc));\n border-radius: var(--loom-popup-radius, var(--loom-border-radius, 6px));\n box-shadow: var(--loom-popup-shadow, 0 2px 8px rgba(0,0,0,0.15));\n padding: 8px 12px;\n font: var(--loom-popup-font, var(--loom-font-small, 12px/1.4 sans-serif));\n color: var(--loom-popup-color, var(--loom-text-color, #333));\n max-width: 320px;\n min-width: 120px;\n}\ntable {\n border-collapse: collapse;\n width: 100%;\n}\ntd {\n padding: 2px 0;\n vertical-align: top;\n}\ntd.name {\n font-weight: 600;\n padding-right: 8px;\n white-space: nowrap;\n color: var(--loom-popup-name-color, var(--loom-text-muted, #555));\n}\ntd.value {\n word-break: break-word;\n}\ntr.border-top td {\n border-top: 1px solid var(--loom-popup-divider, var(--loom-button-hover, #e0e0e0));\n padding-top: 4px;\n}\n.close {\n position: absolute;\n top: 4px;\n right: 6px;\n background: none;\n border: none;\n cursor: pointer;\n font-size: 14px;\n color: var(--loom-popup-close-color, var(--loom-text-muted, #999));\n line-height: 1;\n padding: 0 2px;\n}\n.close:hover {\n color: var(--loom-popup-color, var(--loom-text-color, #333));\n}\n</style>\n<div class=\"popup\">\n <button class=\"close\" title=\"Close\">×</button>\n <table><tbody></tbody></table>\n</div>\n`\n\n/** Lazy template — avoids `document` access at module load time (SSR safe). */\nlet _template: HTMLTemplateElement | null = null\nfunction getTemplate(): HTMLTemplateElement {\n if (!_template) {\n _template = document.createElement('template')\n _template.innerHTML = TEMPLATE_HTML\n }\n return _template\n}\n\nexport class LoomPopup extends HTMLElement {\n constructor() {\n super()\n this.attachShadow({mode: 'open'})\n this.shadowRoot!.appendChild(getTemplate().content.cloneNode(true))\n\n this.shadowRoot!.querySelector('.close')!.addEventListener('click', () => {\n this.hide()\n })\n\n // Stop pointer events from reaching the container's drag handlers\n // so users can select text inside the popup\n const popup = this.shadowRoot!.querySelector('.popup')!\n popup.addEventListener('pointerdown', (e: Event) => { e.stopPropagation() })\n popup.addEventListener('pointerup', (e: Event) => { e.stopPropagation() })\n popup.addEventListener('mousedown', (e: Event) => { e.stopPropagation() })\n popup.addEventListener('mouseup', (e: Event) => { e.stopPropagation() })\n }\n\n /** Populate popup with data items and show it. */\n setData(data: PopupDataItem[]): void {\n const tbody = this.shadowRoot!.querySelector('tbody')!\n tbody.innerHTML = ''\n for (const item of data) {\n const tr = document.createElement('tr')\n if (item.borderTop) tr.className = 'border-top'\n const tdName = document.createElement('td')\n tdName.className = 'name'\n tdName.textContent = item.name\n const tdValue = document.createElement('td')\n tdValue.className = 'value'\n tdValue.textContent = String(item.value)\n tr.appendChild(tdName)\n tr.appendChild(tdValue)\n tbody.appendChild(tr)\n }\n }\n\n /** Position relative to a parent container and show. */\n showAt(x: number, y: number): void {\n this.style.display = 'block'\n // Offset slightly from pointer\n const offsetX = 12\n const offsetY = 12\n this.style.left = `${x + offsetX}px`\n this.style.top = `${y + offsetY}px`\n\n // Clamp to container bounds after rendering\n requestAnimationFrame(() => {\n const parent = this.offsetParent as HTMLElement | null\n if (!parent) return\n const parentRect = parent.getBoundingClientRect()\n const popupRect = this.getBoundingClientRect()\n\n let left = x + offsetX\n let top = y + offsetY\n\n if (left + popupRect.width > parentRect.width) {\n left = x - popupRect.width - offsetX\n }\n if (top + popupRect.height > parentRect.height) {\n top = y - popupRect.height - offsetY\n }\n if (left < 0) left = 0\n if (top < 0) top = 0\n\n this.style.left = `${left}px`\n this.style.top = `${top}px`\n })\n }\n\n hide(): void {\n this.style.display = 'none'\n }\n}\n\n// Register custom element\nif (typeof customElements !== 'undefined' && !customElements.get('loom-popup')) {\n customElements.define('loom-popup', LoomPopup)\n}\n\n/**\n * Default PopupProvider implementation using the <loom-popup> Web Component.\n * Creates and manages a single popup element within the browser container.\n */\nexport class DefaultPopupProvider implements PopupProvider {\n private element: LoomPopup | null = null\n\n show(data: PopupDataItem[], position: {x: number; y: number}, container: HTMLElement): void {\n if (!this.element) {\n this.element = document.createElement('loom-popup') as LoomPopup\n // Ensure container is positioned for absolute child placement\n const pos = getComputedStyle(container).position\n if (pos === 'static') container.style.position = 'relative'\n container.appendChild(this.element)\n }\n\n this.element.setData(data)\n this.element.showAt(position.x, position.y)\n }\n\n hide(): void {\n if (this.element) this.element.hide()\n }\n\n dispose(): void {\n if (this.element) {\n this.element.remove()\n this.element = null\n }\n }\n}\n","/**\n * <loom-input-dialog> — Simple modal input dialog Web Component.\n *\n * Shows a label, text input, and OK/Cancel buttons. Returns the entered\n * value via a Promise. Used by the context menu's \"Set track height\" action.\n *\n * Customizable via CSS custom properties:\n * --loom-dialog-bg, --loom-dialog-border, --loom-dialog-shadow,\n * --loom-dialog-font, --loom-dialog-color, --loom-dialog-radius,\n * --loom-dialog-btn-bg, --loom-dialog-btn-color\n */\n\nconst TEMPLATE_HTML = /* html */`\n<style>\n:host {\n position: absolute;\n z-index: 100002;\n top: 0; left: 0; right: 0; bottom: 0;\n display: none;\n align-items: center;\n justify-content: center;\n background: rgba(0, 0, 0, 0.15);\n}\n.dialog {\n background: var(--loom-dialog-bg, var(--loom-input-bg, white));\n border: var(--loom-dialog-border, var(--loom-border, 1px solid #ccc));\n border-radius: var(--loom-dialog-radius, var(--loom-border-radius, 6px));\n box-shadow: var(--loom-dialog-shadow, 0 4px 16px rgba(0,0,0,0.2));\n padding: 16px 20px;\n font: var(--loom-dialog-font, var(--loom-font, 13px/1.4 sans-serif));\n color: var(--loom-dialog-color, var(--loom-text-color, #333));\n min-width: 220px;\n}\n.dialog label {\n display: block;\n margin-bottom: 8px;\n font-weight: 600;\n font-size: 12px;\n}\n.dialog input {\n width: 100%;\n box-sizing: border-box;\n padding: 6px 8px;\n background: var(--loom-input-bg, white);\n border: var(--loom-input-border, 1px solid #ccc);\n border-radius: 4px;\n font: inherit;\n color: inherit;\n margin-bottom: 12px;\n}\n.dialog input:focus {\n outline: none;\n border-color: var(--loom-accent, #4A90D9);\n box-shadow: 0 0 0 2px rgba(74, 144, 217, 0.2);\n}\n.buttons {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n}\n.buttons button {\n padding: 5px 14px;\n border: var(--loom-button-border, 1px solid #ccc);\n border-radius: 4px;\n font: inherit;\n font-size: 12px;\n cursor: pointer;\n background: var(--loom-dialog-btn-bg, var(--loom-button-bg, #f5f5f5));\n color: var(--loom-dialog-btn-color, var(--loom-text-color, #333));\n}\n.buttons button:hover {\n background: var(--loom-button-hover, #e8e8e8);\n}\n.buttons button.primary {\n background: var(--loom-accent, #4A90D9);\n color: white;\n border-color: transparent;\n}\n.buttons button.primary:hover {\n filter: brightness(0.9);\n}\n</style>\n<div class=\"dialog\">\n <label></label>\n <input type=\"text\" />\n <div class=\"buttons\">\n <button class=\"cancel\">Cancel</button>\n <button class=\"primary ok\">OK</button>\n </div>\n</div>\n`\n\nexport class LoomInputDialog extends HTMLElement {\n private labelEl!: HTMLLabelElement\n private inputEl!: HTMLInputElement\n private okBtn!: HTMLButtonElement\n private cancelBtn!: HTMLButtonElement\n private resolve: ((value: string | null) => void) | null = null\n\n constructor() {\n super()\n this.attachShadow({mode: 'open'})\n }\n\n connectedCallback(): void {\n const tpl = document.createElement('template')\n tpl.innerHTML = TEMPLATE_HTML\n this.shadowRoot!.appendChild(tpl.content.cloneNode(true))\n\n this.labelEl = this.shadowRoot!.querySelector('label')!\n this.inputEl = this.shadowRoot!.querySelector('input')!\n this.okBtn = this.shadowRoot!.querySelector('.ok')!\n this.cancelBtn = this.shadowRoot!.querySelector('.cancel')!\n\n this.okBtn.addEventListener('click', () => this.confirm())\n this.cancelBtn.addEventListener('click', () => this.cancel())\n this.inputEl.addEventListener('keydown', (e: KeyboardEvent) => {\n if (e.key === 'Enter') this.confirm()\n if (e.key === 'Escape') this.cancel()\n })\n }\n\n /**\n * Show the dialog and return a Promise that resolves with the input value\n * (on OK/Enter) or null (on Cancel/Escape).\n */\n prompt(label: string, currentValue: string | number): Promise<string | null> {\n this.labelEl.textContent = label\n this.inputEl.value = String(currentValue)\n this.style.display = 'flex'\n\n // Focus and select input after display\n requestAnimationFrame(() => {\n this.inputEl.focus()\n this.inputEl.select()\n })\n\n return new Promise<string | null>(resolve => {\n this.resolve = resolve\n })\n }\n\n private confirm(): void {\n const value = this.inputEl.value\n this.style.display = 'none'\n if (this.resolve) {\n this.resolve(value)\n this.resolve = null\n }\n }\n\n private cancel(): void {\n this.style.display = 'none'\n if (this.resolve) {\n this.resolve(null)\n this.resolve = null\n }\n }\n}\n\nif (typeof customElements !== 'undefined' && !customElements.get('loom-input-dialog')) {\n customElements.define('loom-input-dialog', LoomInputDialog)\n}\n"],"names":["_idCounter","ROISet","constructor","config","this","_features","name","color","_a","isUserDefined","_b","features","map","f","addFeature","roi","feature","id","Date","now","toString","push","sort","a","b","start","removeFeature","idx","findIndex","splice","updateFeature","changes","find","Object","assign","findById","getFeatures","chr","end","filter","toJSON","undefined","renderROIOverlays","ctx","rois","rc","options","totalHeight","headerHeight","font","labelColor","x","Math","round","bpStart","bpPerPixel","w","max","pixelWidth","fillStyle","fillRect","strokeStyle","replace","m","min","parseFloat","lineWidth","beginPath","moveTo","lineTo","stroke","textBaseline","textAlign","labelX","labelY","fillText","format","str","args","result","key","keys","RegExp","String","randomString","holder","chars","i","floor","random","getTextAnchor","mapping","left","right","center","getDominantBaseline","alphabetic","hanging","top","bottom","middle","normalize","vector","len","sqrt","namedEntities","items","radix","lookup","parts","split","length","entity","base10","parseInt","createNamedToNumberedLookup","STYLES","svgAttr","canvas","svg","apply","lineCap","lineJoin","miterLimit","globalAlpha","shadowColor","shadowOffsetX","shadowOffsetY","shadowBlur","lineDash","SVGCanvasGradient","gradientNode","__root","__ctx","addColorStop","offset","stop","__createElement","setAttribute","indexOf","matches","exec","r","g","appendChild","SVGCanvasPattern","pattern","C2S","isSVG","__currentElementsToStyle","__ids","__stack","__groupStack","__currentDefaultPath","__currentPosition","y","globalCompositeOperation","width","height","enableMirroring","_c","__document","document","__canvas","createElement","getContext","__setDefaultStyles","__getStyleState","viewbox","vb","__defs","backdropRect","fill","backdropColor","__rootGroup","__currentElement","setWidth","setHeight","elementName","properties","resetFill","element","createElementNS","__applyStyleState","styleState","state","__applyStyleToCurrentElement","type","currentElement","currentStyleGroup","children","forEach","node","style","value","childNodes","child","getAttribute","attr","opacity","__closestGroupOrSvg","n","nodeName","parentNode","getSerializedSvg","fixNamedEntities","serialized","XMLSerializer","serializeToString","regexp","test","getSvg","saveWithTranslationAndClipRect","tx","ty","clipYOffset","clipId","clipPath","group","parent","save","restore","pop","__addTransform","t","__applyCurrentDefaultPath","transform","scale","rotate","angle","degrees","PI","cx","cy","translate","c","d","e","path","__addPathCommand","command","closePath","bezierCurveTo","cp1x","cp1y","cp2x","cp2y","quadraticCurveTo","cpx","cpy","roundRect","h","radii","maxR","abs","arcTo","x1","y1","x2","y2","radius","x0","y0","Error","unitVecP1P0","unitVecP1P2","cos","theta","acos","unitVecP1Origin","lenP1Origin","sin","unitVecOriginStartTangent","unitVecOriginEndTangent","getAngle","startAngle","endAngle","arc","rect","r2","rect1","rect2","strokeRect","strokeEllipse","rx","ry","_rotation","_startAngle","_endAngle","_isCCW","__ellipse","fillEllipse","__clearCanvas","rootGroup","removeChild","clearRect","createLinearGradient","grad","gradientUnits","createRadialGradient","r0","r1","fx","fy","__parseFont","fontPart","data","size","family","weight","decoration","href","__fontUnderline","__fontHref","__wrapTextLink","setAttributeNS","__applyText","text","action","textElement","createTextNode","strokeText","measureText","counterClockwise","endX","endY","startX","startY","sweepFlag","diff","largeArcFlag","xAxisRotation","clip","newGroup","drawImage","image","dx","dy","dw","dh","sw","sh","sx","sy","translateDirective","cloneNode","defs","originTransform","el","svgImage","srcElement","toDataURL","createPattern","_repetition","img","setLineDash","dashArray","join","getLineDash","Number","drawFocusIfNeeded","createImageData","ImageData","getImageData","putImageData","setTransform","defaultCanvasProvider","createCanvas","devicePixelRatio","window","resolveTheme","overrides","base","palette","primary","secondary","accent","background","foreground","muted","fontFamily","fontSize","nucleotideColors","A","C","G","T","N","annotation","wig","ruler","sequence","interaction","resolveAnnotationConfig","theme","displayMode","featureHeight","margin","expandedRowHeight","squishedRowHeight","arrowSpacing","altColor","labelField","drawLabels","intronColor","withTheme","resolveWigConfig","graphType","windowFunction","dataRange","autoscale","flipAxis","logScale","baselineColor","overflowColor","pointSize","showDataRange","labelFont","resolveRulerConfig","tickColor","resolveSequenceConfig","sequenceType","reversed","frameTranslate","nonDnaColor","defaultHeight","translatedHeight","sequenceHeight","frameHeight","frameBorder","frameColor1","frameColor2","stopCodonColor","startCodonColor","useFillText","frameLabelColor","frameFont","codonBorderRadius","resolveInteractionConfig","arcOrientation","showBlocks","blockHeight","thickness","alpha","useScore","EventEmitter","listeners","Map","on","event","handler","set","get","Set","add","delete","off","emit","removeAllListeners","clear","isWholeGenomeView","locus","toLowerCase","cacheCoversViewport","cache","viewport","ratio","addCaseAliases","record","upper","toUpperCase","lower","cap","charAt","slice","startsWith","substring","getNCBIName","tokens","isHumanGenome","isMouseGenome","ChromAliasDefaults","chromosomeNames","genomeId","buildAliases","getChromosomeName","alias","getAliasRecord","records","has","dotIndex","lastIndexOf","isInteger","addHumanSexAliases","addMouseSexAliases","values","MAIN_CHROM_RE","isMainChromosome","mainChromosomeNames","chromSizes","chromNumber","suffix","isNaN","MIN_QUERY_SIZE","createCachedSequence","provider","currentQuery","async","signal","interval","contains","newInterval","qstart","qend","ceil","queryLocus","promise","then","querySequence","inner","outer","shift","BUILTIN_NAMES","hg38","GenomeImpl","cumulativeOffsets","offsets","totalLength","computeCumulativeOffsets","_chromosomes","allNames","mainSet","order","bpLength","_chromAlias","getChromosome","getChromosomeLength","hg38Genome","sequenceProvider","ucscGenome","url","genome","resp","fetch","ok","status","statusText","json","dna","fetchSequence","resolveSequenceProvider","createGenomeSync","chr1","chr2","chr3","chr4","chr5","chr6","chr7","chr8","chr9","chr10","chr11","chr12","chr13","chr14","chr15","chr16","chr17","chr18","chr19","chr20","chr21","chr22","chrX","chrY","chrM","chr11_KI270721v1_random","chr14_GL000009v2_random","chr14_GL000225v1_random","chr14_KI270722v1_random","chr14_GL000194v1_random","chr14_KI270723v1_random","chr14_KI270724v1_random","chr14_KI270725v1_random","chr14_KI270726v1_random","chr15_KI270727v1_random","chr16_KI270728v1_random","chr17_GL000205v2_random","chr17_KI270729v1_random","chr17_KI270730v1_random","chr1_KI270706v1_random","chr1_KI270707v1_random","chr1_KI270708v1_random","chr1_KI270709v1_random","chr1_KI270710v1_random","chr1_KI270711v1_random","chr1_KI270712v1_random","chr1_KI270713v1_random","chr1_KI270714v1_random","chr22_KI270731v1_random","chr22_KI270732v1_random","chr22_KI270733v1_random","chr22_KI270734v1_random","chr22_KI270735v1_random","chr22_KI270736v1_random","chr22_KI270737v1_random","chr22_KI270738v1_random","chr22_KI270739v1_random","chr2_KI270715v1_random","chr2_KI270716v1_random","chr3_GL000221v1_random","chr4_GL000008v2_random","chr5_GL000208v1_random","chr9_KI270717v1_random","chr9_KI270718v1_random","chr9_KI270719v1_random","chr9_KI270720v1_random","chr1_KI270762v1_alt","chr1_KI270766v1_alt","chr1_KI270760v1_alt","chr1_KI270765v1_alt","chr1_GL383518v1_alt","chr1_GL383519v1_alt","chr1_GL383520v2_alt","chr1_KI270764v1_alt","chr1_KI270763v1_alt","chr1_KI270759v1_alt","chr1_KI270761v1_alt","chr2_KI270770v1_alt","chr2_KI270773v1_alt","chr2_KI270774v1_alt","chr2_KI270769v1_alt","chr2_GL383521v1_alt","chr2_KI270772v1_alt","chr2_KI270775v1_alt","chr2_KI270771v1_alt","chr2_KI270768v1_alt","chr2_GL582966v2_alt","chr2_GL383522v1_alt","chr2_KI270776v1_alt","chr2_KI270767v1_alt","chr3_JH636055v2_alt","chr3_KI270783v1_alt","chr3_KI270780v1_alt","chr3_GL383526v1_alt","chr3_KI270777v1_alt","chr3_KI270778v1_alt","chr3_KI270781v1_alt","chr3_KI270779v1_alt","chr3_KI270782v1_alt","chr3_KI270784v1_alt","chr4_KI270790v1_alt","chr4_GL383528v1_alt","chr4_KI270787v1_alt","chr4_GL000257v2_alt","chr4_KI270788v1_alt","chr4_GL383527v1_alt","chr4_KI270785v1_alt","chr4_KI270789v1_alt","chr4_KI270786v1_alt","chr5_KI270793v1_alt","chr5_KI270792v1_alt","chr5_KI270791v1_alt","chr5_GL383532v1_alt","chr5_GL949742v1_alt","chr5_KI270794v1_alt","chr5_GL339449v2_alt","chr5_GL383530v1_alt","chr5_KI270796v1_alt","chr5_GL383531v1_alt","chr5_KI270795v1_alt","chr6_GL000250v2_alt","chr6_KI270800v1_alt","chr6_KI270799v1_alt","chr6_GL383533v1_alt","chr6_KI270801v1_alt","chr6_KI270802v1_alt","chr6_KB021644v2_alt","chr6_KI270797v1_alt","chr6_KI270798v1_alt","chr7_KI270804v1_alt","chr7_KI270809v1_alt","chr7_KI270806v1_alt","chr7_GL383534v2_alt","chr7_KI270803v1_alt","chr7_KI270808v1_alt","chr7_KI270807v1_alt","chr7_KI270805v1_alt","chr8_KI270818v1_alt","chr8_KI270812v1_alt","chr8_KI270811v1_alt","chr8_KI270821v1_alt","chr8_KI270813v1_alt","chr8_KI270822v1_alt","chr8_KI270814v1_alt","chr8_KI270810v1_alt","chr8_KI270819v1_alt","chr8_KI270820v1_alt","chr8_KI270817v1_alt","chr8_KI270816v1_alt","chr8_KI270815v1_alt","chr9_GL383539v1_alt","chr9_GL383540v1_alt","chr9_GL383541v1_alt","chr9_GL383542v1_alt","chr9_KI270823v1_alt","chr10_GL383545v1_alt","chr10_KI270824v1_alt","chr10_GL383546v1_alt","chr10_KI270825v1_alt","chr11_KI270832v1_alt","chr11_KI270830v1_alt","chr11_KI270831v1_alt","chr11_KI270829v1_alt","chr11_GL383547v1_alt","chr11_JH159136v1_alt","chr11_JH159137v1_alt","chr11_KI270827v1_alt","chr11_KI270826v1_alt","chr12_GL877875v1_alt","chr12_GL877876v1_alt","chr12_KI270837v1_alt","chr12_GL383549v1_alt","chr12_KI270835v1_alt","chr12_GL383550v2_alt","chr12_GL383552v1_alt","chr12_GL383553v2_alt","chr12_KI270834v1_alt","chr12_GL383551v1_alt","chr12_KI270833v1_alt","chr12_KI270836v1_alt","chr13_KI270840v1_alt","chr13_KI270839v1_alt","chr13_KI270843v1_alt","chr13_KI270841v1_alt","chr13_KI270838v1_alt","chr13_KI270842v1_alt","chr14_KI270844v1_alt","chr14_KI270847v1_alt","chr14_KI270845v1_alt","chr14_KI270846v1_alt","chr15_KI270852v1_alt","chr15_KI270851v1_alt","chr15_KI270848v1_alt","chr15_GL383554v1_alt","chr15_KI270849v1_alt","chr15_GL383555v2_alt","chr15_KI270850v1_alt","chr16_KI270854v1_alt","chr16_KI270856v1_alt","chr16_KI270855v1_alt","chr16_KI270853v1_alt","chr16_GL383556v1_alt","chr16_GL383557v1_alt","chr17_GL383563v3_alt","chr17_KI270862v1_alt","chr17_KI270861v1_alt","chr17_KI270857v1_alt","chr17_JH159146v1_alt","chr17_JH159147v1_alt","chr17_GL383564v2_alt","chr17_GL000258v2_alt","chr17_GL383565v1_alt","chr17_KI270858v1_alt","chr17_KI270859v1_alt","chr17_GL383566v1_alt","chr17_KI270860v1_alt","chr18_KI270864v1_alt","chr18_GL383567v1_alt","chr18_GL383570v1_alt","chr18_GL383571v1_alt","chr18_GL383568v1_alt","chr18_GL383569v1_alt","chr18_GL383572v1_alt","chr18_KI270863v1_alt","chr19_KI270868v1_alt","chr19_KI270865v1_alt","chr19_GL383573v1_alt","chr19_GL383575v2_alt","chr19_GL383576v1_alt","chr19_GL383574v1_alt","chr19_KI270866v1_alt","chr19_KI270867v1_alt","chr19_GL949746v1_alt","chr20_GL383577v2_alt","chr20_KI270869v1_alt","chr20_KI270871v1_alt","chr20_KI270870v1_alt","chr21_GL383578v2_alt","chr21_KI270874v1_alt","chr21_KI270873v1_alt","chr21_GL383579v2_alt","chr21_GL383580v2_alt","chr21_GL383581v2_alt","chr21_KI270872v1_alt","chr22_KI270875v1_alt","chr22_KI270878v1_alt","chr22_KI270879v1_alt","chr22_KI270876v1_alt","chr22_KI270877v1_alt","chr22_GL383583v2_alt","chr22_GL383582v2_alt","chrX_KI270880v1_alt","chrX_KI270881v1_alt","chr19_KI270882v1_alt","chr19_KI270883v1_alt","chr19_KI270884v1_alt","chr19_KI270885v1_alt","chr19_KI270886v1_alt","chr19_KI270887v1_alt","chr19_KI270888v1_alt","chr19_KI270889v1_alt","chr19_KI270890v1_alt","chr19_KI270891v1_alt","chr1_KI270892v1_alt","chr2_KI270894v1_alt","chr2_KI270893v1_alt","chr3_KI270895v1_alt","chr4_KI270896v1_alt","chr5_KI270897v1_alt","chr5_KI270898v1_alt","chr6_GL000251v2_alt","chr7_KI270899v1_alt","chr8_KI270901v1_alt","chr8_KI270900v1_alt","chr11_KI270902v1_alt","chr11_KI270903v1_alt","chr12_KI270904v1_alt","chr15_KI270906v1_alt","chr15_KI270905v1_alt","chr17_KI270907v1_alt","chr17_KI270910v1_alt","chr17_KI270909v1_alt","chr17_JH159148v1_alt","chr17_KI270908v1_alt","chr18_KI270912v1_alt","chr18_KI270911v1_alt","chr19_GL949747v2_alt","chr22_KB663609v1_alt","chrX_KI270913v1_alt","chr19_KI270914v1_alt","chr19_KI270915v1_alt","chr19_KI270916v1_alt","chr19_KI270917v1_alt","chr19_KI270918v1_alt","chr19_KI270919v1_alt","chr19_KI270920v1_alt","chr19_KI270921v1_alt","chr19_KI270922v1_alt","chr19_KI270923v1_alt","chr3_KI270924v1_alt","chr4_KI270925v1_alt","chr6_GL000252v2_alt","chr8_KI270926v1_alt","chr11_KI270927v1_alt","chr19_GL949748v2_alt","chr22_KI270928v1_alt","chr19_KI270929v1_alt","chr19_KI270930v1_alt","chr19_KI270931v1_alt","chr19_KI270932v1_alt","chr19_KI270933v1_alt","chr19_GL000209v2_alt","chr3_KI270934v1_alt","chr6_GL000253v2_alt","chr19_GL949749v2_alt","chr3_KI270935v1_alt","chr6_GL000254v2_alt","chr19_GL949750v2_alt","chr3_KI270936v1_alt","chr6_GL000255v2_alt","chr19_GL949751v2_alt","chr3_KI270937v1_alt","chr6_GL000256v2_alt","chr19_GL949752v1_alt","chr6_KI270758v1_alt","chr19_GL949753v2_alt","chr19_KI270938v1_alt","chrUn_KI270302v1","chrUn_KI270304v1","chrUn_KI270303v1","chrUn_KI270305v1","chrUn_KI270322v1","chrUn_KI270320v1","chrUn_KI270310v1","chrUn_KI270316v1","chrUn_KI270315v1","chrUn_KI270312v1","chrUn_KI270311v1","chrUn_KI270317v1","chrUn_KI270412v1","chrUn_KI270411v1","chrUn_KI270414v1","chrUn_KI270419v1","chrUn_KI270418v1","chrUn_KI270420v1","chrUn_KI270424v1","chrUn_KI270417v1","chrUn_KI270422v1","chrUn_KI270423v1","chrUn_KI270425v1","chrUn_KI270429v1","chrUn_KI270442v1","chrUn_KI270466v1","chrUn_KI270465v1","chrUn_KI270467v1","chrUn_KI270435v1","chrUn_KI270438v1","chrUn_KI270468v1","chrUn_KI270510v1","chrUn_KI270509v1","chrUn_KI270518v1","chrUn_KI270508v1","chrUn_KI270516v1","chrUn_KI270512v1","chrUn_KI270519v1","chrUn_KI270522v1","chrUn_KI270511v1","chrUn_KI270515v1","chrUn_KI270507v1","chrUn_KI270517v1","chrUn_KI270529v1","chrUn_KI270528v1","chrUn_KI270530v1","chrUn_KI270539v1","chrUn_KI270538v1","chrUn_KI270544v1","chrUn_KI270548v1","chrUn_KI270583v1","chrUn_KI270587v1","chrUn_KI270580v1","chrUn_KI270581v1","chrUn_KI270579v1","chrUn_KI270589v1","chrUn_KI270590v1","chrUn_KI270584v1","chrUn_KI270582v1","chrUn_KI270588v1","chrUn_KI270593v1","chrUn_KI270591v1","chrUn_KI270330v1","chrUn_KI270329v1","chrUn_KI270334v1","chrUn_KI270333v1","chrUn_KI270335v1","chrUn_KI270338v1","chrUn_KI270340v1","chrUn_KI270336v1","chrUn_KI270337v1","chrUn_KI270363v1","chrUn_KI270364v1","chrUn_KI270362v1","chrUn_KI270366v1","chrUn_KI270378v1","chrUn_KI270379v1","chrUn_KI270389v1","chrUn_KI270390v1","chrUn_KI270387v1","chrUn_KI270395v1","chrUn_KI270396v1","chrUn_KI270388v1","chrUn_KI270394v1","chrUn_KI270386v1","chrUn_KI270391v1","chrUn_KI270383v1","chrUn_KI270393v1","chrUn_KI270384v1","chrUn_KI270392v1","chrUn_KI270381v1","chrUn_KI270385v1","chrUn_KI270382v1","chrUn_KI270376v1","chrUn_KI270374v1","chrUn_KI270372v1","chrUn_KI270373v1","chrUn_KI270375v1","chrUn_KI270371v1","chrUn_KI270448v1","chrUn_KI270521v1","chrUn_GL000195v1","chrUn_GL000219v1","chrUn_GL000220v1","chrUn_GL000224v1","chrUn_KI270741v1","chrUn_GL000226v1","chrUn_GL000213v1","chrUn_KI270743v1","chrUn_KI270744v1","chrUn_KI270745v1","chrUn_KI270746v1","chrUn_KI270747v1","chrUn_KI270748v1","chrUn_KI270749v1","chrUn_KI270750v1","chrUn_KI270751v1","chrUn_KI270752v1","chrUn_KI270753v1","chrUn_KI270754v1","chrUn_KI270755v1","chrUn_KI270756v1","chrUn_KI270757v1","chrUn_GL000214v1","chrUn_KI270742v1","chrUn_GL000216v2","chrUn_GL000218v1","chrY_KI270740v1_random","BaseTrackCanvas","_canvas","_locus","_height","_config","canvasProvider","resizeObserver","container","_renderSuspended","_renderPending","_error","_zoomedOut","setLocus","render","setConfig","suspendRendering","resumeRendering","setError","error","setZoomedOut","zoomedOut","hitTest","_x","_y","getContextMenuItems","attachTo","detach","display","ResizeObserver","observe","disconnect","clientWidth","computeHeight","dpr","getBackground","renderError","renderZoomInNotice","viewportWidth","doRender","renderToContext","defaultNucleotideColors","letterPaths","main","overlay","drawSVGPath","pathString","scaleX","scaleY","commands","match","coords","trim","drawLetterGlyph","flipVertical","backgroundColor","pathData","renderDynSeqFeature","colors","rectY","rectHeight","baseWidth","isNegative","baseX","addAlpha","rgb","rgbMatch","hexMatch","hex","parseRGB","getColor","staticColors","neg","pos","resolved","colorOrFn","resolveColor","getColorForValue","prettyPrint","toFixed","toExponential","renderWigTrack","pixelHeight","bpEnd","scaleFactor","minValue","log10","getScaleFactor","yScale","maxValue","yValue","computeYPixel","console","log","resolveStaticColors","rectEnd","renderBarGraph","lastY","lastPixelEnd","renderLineGraph","px","renderPointsGraph","renderDynSeqGraph","basepx","renderBaseline","guideLines","line","dotted","renderGuideLines","maxLabel","minLabel","maxMetrics","maxW","hPad","maxH","actualBoundingBoxDescent","vPad","pad","minMetrics","minW","minH","actualBoundingBoxAscent","minY","renderDataRangeLabels","trackName","topOffset","metrics","renderTrackNameLabel","SummaryBinData","bin","sumData","count","summarizeWigData","startBP","binSize","summaryFeatures","finishBin","description","currentBinData","startBin","endBin","consolidated","lastFeature","computeWigDataRange","MAX_VALUE","WigTrackCanvas","super","_lastDataRange","_seqAbort","fixedHeight","_name","_sequenceProvider","onWindowFunctionChange","cb","_onWindowFunctionChange","setFeatures","augmentWithSequence","wasDynseq","abort","controller","AbortController","aborted","seqStart","seqEnd","catch","_width","normalizationFactor","effectiveConfig","autoRange","featureCount","getAxisInfo","label","graphTypes","checked","gt","wf","getNumericState","setAutoscale","enabled","setLogScale","setDataRange","genomicPos","popupData","wigPopupData","setTheme","serializeConfig","defaults","hasOverrides","cfg","toLocaleString","toPrecision","fillStyledRect","borderRadius","borderColor","borderWidth","renderSingleFeature","rowLastLabelX","getColorForFeature","utrColor","strand","altUtrColor","getUtrColorForFeature","py","row","h2","py2","exonCount","exons","coord","px1","pw","calculateFeatureCoordinates","step","direction","intronArrowColor","arrowColor","exonArrowColor","arrowInExonColor","xLeft","xRight","drawArrowhead","_d","intronLineWidth","intronDash","exon","ePx","ePx1","ePw","utr","cdStart","ePxU","cdEnd","featureX","featureX1","featureY","field","labelFields","getFeatureLabel","t1","centerX","labelDisplayMode","textMetrics","xleft","xright","MAX_SAFE_INTEGER","lx","ly","lw","lh","labelBackground","renderFeatureLabel","AnnotationTrackCanvas","packedFeatures","packedReady","workerProvider","copies","execute","task","packed","maxRows","limit","rowEnds","placed","packFeatures","maxRow","reduce","rowHeight","pxEnd","pxStart","renderAnnotationTrack","mode","results","annotationPopupData","val","formatNumber","renderRulerTrack","tick","majorTick","majorUnit","unitMultiplier","nZeroes","pow","findSpacing","nTick","getBP","getX","bp","tickDelta","sampleLabel","labelLength","labelLengthShim","xTick","accumulatedTickDelta","rulerLabel","labelWidth","xLabel","minorX","RulerTrackCanvas","_cumulativeOffsets","_chromSizes","setCumulativeOffsets","setChromSizes","sizes","wg","xBP","wBP","shortName","renderWholeGenomeRuler","complements","t2","translationDict","TTT","TTC","TTA","TTG","CTT","CTC","CTA","CTG","ATT","ATC","ATA","ATG","GTT","GTC","GTA","GTG","TCT","TCC","TCA","TCG","AGT","AGC","CCT","CCC","CCA","CCG","ACT","ACC","ACA","ACG","GCT","GCC","GCA","GCG","TAT","TAC","TAA","TAG","TGA","CAT","CAC","CAA","CAG","AAT","AAC","AAA","AAG","GAT","GAC","GAA","GAG","TGT","TGC","TGG","CGT","CGC","CGA","CGG","AGA","AGG","GGT","GGC","GGA","GGG","fillColor","renderSequenceTrack","seqFeature","complementBase","sequenceBpStart","seqIdx","aPixel","baseLetter","textPixel","translatedSequence","seq","threeFrame","fNum","codon","reverse","aa","codons","aminoA","translateSequence","aaSequence","bgColor","cv","bpOffset","p0","p1","pc","aaLabel","isSpecialCodon","codonLabelColor","SequenceTrackCanvas","_sequence","_theme","shouldFetchSequence","setSequence","getSequence","toggleReversed","toggleFrameTranslate","BinaryParser","dataView","littleEndian","position","view","byteLength","setPosition","available","remLength","getByte","retValue","getUint8","getShort","getInt16","getUShort","getUint16","getInt","getInt32","getUInt","getUint32","getLong","getString","s","fromCharCode","getFixedLengthString","getFloat","getFloat32","getDouble","getFloat64","skip","readerCache","featureToWig","score","summary","minScore","maxScore","_e","_f","BigWigReader","_workerProvider","bw","reader","BigWig","filehandle","RemoteFile","getGmodReader","loadHeader","getHeader","bwVersion","version","nZoomLevels","numZoomLevels","chromTreeOffset","chromosomeTreeOffset","fullDataOffset","unzoomedDataOffset","fullIndexOffset","unzoomedIndexOffset","fieldCount","definedFieldCount","autoSqlOffset","asOffset","totalSummaryOffset","uncompressBuffSize","uncompressBufSize","extensionOffset","extHeaderOffset","getTotalSummary","totalSummary","mean","basesCovered","scoreSum","variance","scoreSumSquares","minVal","scoreMin","maxVal","scoreMax","sumSquares","stddev","readFeatures","opts","basesPerSpan","readWGFeatures","chromNames","allFeatures","BigWigDataSource","_windowFunction","setWindowFunction","setChromNameResolver","resolver","_resolveChromName","fetchWG","resolvedLocus","fetchBigWigFeatures","fetchBigWigWGFeatures","wgFeatures","fetchRange","range","headers","Range","response","redirected","contentLength","method","cl","getContentLength","clampedSize","arrayBuffer","_bytes","wasmMemory","HEAP8","HEAPU8","wasmExports","initPromise","initialized","updateMemoryViews","buffer","Int8Array","Uint8Array","timers","__emscripten_timeout","alignMemory","alignment","wasmImports","code","what","msg","WebAssembly","RuntimeError","which","timeout_ms","clearTimeout","setTimeout","performance","requestedSize","oldSize","maxHeapSize","cutDown","overGrownHeapSize","pages","grow","initZstd","binary","binaryString","atob","charCodeAt","getZstdWasmBytes","importObject","module","compile","exports","instantiate","doInit","GTX_MAGIC","STANDARD_TILE_SIZES","inferTileSize","chromLength","nTiles","ts","GtxReader","experiments","experimentIdToIndex","chromosomes","chromOrder","tileIndexCache","zoomLevels","zoomTileIndexCache","init","_signal","_doInit","err","headerBuf","header","parseHeader","DataView","metadataSize","dictionaryOffset","experimentMetadataOffset","metaDictStart","metaDictSize","dictionarySize","dirStart","chromDirectoryOffset","hasZoom","zoomDirectoryOffset","dirFetchSize","computeDirFetchSize","metaDictBuf","dirBuf","Promise","all","parseExperimentMetadata","dictionary","dctx","createDCtx","chromDirLength","parseChromDirectory","zoomStart","zoomLength","parseZoomDirectory","p","magic","genomeLen","nExperiments","resolution","payloadEncoding","readU64","groupStatsDirectoryOffset","idLen","experimentIndex","nMeta","metadata","j","keyLen","valLen","entry","nChromosomes","nameLen","tileIndexOffset","tileIndexLength","reductionLevel","nChroms","chromTileIndexes","loadTileIndex","chrom","cached","chromEntry","buf","tiles","parseTileIndex","loadZoomTileIndex","zoomIdx","cacheKey","zoomLevel","parsedNTiles","positionsOffset","positionsSize","experimentPointers","experimentIndexes","selectZoomLevel","readZoomFeatures","tileSize","firstTile","lastTile","fetchPlan","tile","expIdx","ptr","tileIdx","pointer","chunks","fetchMergedRanges","decompressed","decompress","Float32Array","byteOffset","tileStart","tileEnd","overlapStart","overlapEnd","firstBin","lastBin","binStart","binEnd","chromZoom","zoomBinSize","allValues","nZoomBins","means","subarray","getExperimentIds","getExperimentMetadata","resolveExperimentIndex","getChromosomes","bestIdx","plan","sorted","mergedRanges","item","itemEnd","last","fetches","localOffset","compressed","malloc","free","getFrameContentSize","isError","srcPtr","dictPtr","contentSize","dstCapacity","dstPtr","sizeOrError","decompressUsingDict","dispose","coordinators","GtxFetchCoordinator","pending","request","experimentId","existing","resolve","reject","batch","queueMicrotask","flush","expIndexes","idToIdx","exp","fetchGtxWGFeatures","getReader","GtxDataSource","coordinator","getCoordinator","findUTRs","parseColorString","parseStrand","decodeGenePred","decodeExons","decodeGenePredExt","cdsStartStat","cdsEndStat","decodeRefGeneJson","rec","cdsStart","cdsEnd","name2","txStart","txEnd","exonStarts","exonEnds","frameOffsets","exonFrames","fo","readingFrame","startsString","endsString","frameOffsetsString","fetchGeneFeatures","track","GeneDataSource","_bpPerPixel","promises","perChromResults","k","reservoir","reservoirSample","__classPrivateFieldGet","receiver","kind","TypeError","call","SuppressedError","NIL","Infinity","IntervalTree","root","insert","low","high","_IntervalTree_instances","_IntervalTree_createNode","_IntervalTree_treeInsert","_IntervalTree_leftRotate","_IntervalTree_rightRotate","findOverlapping","_IntervalTree_searchAll","mapIntervals","fn","applyInterval","_IntervalTree_applyUpdate","nodeMax","intervalHigh","nodeMin","intervalLow","FeatureCache","featureList","treeMap","list","chrFeatures","buildIntervalTree","buildTreeMap","containsRange","queryFeatures","tree","intervals","indexRange","findFeatures","found","getAllFeatures","chunkSize","subArray","iStart","iEnd","TabixReader","indexUrl","tabix","TabixIndexedFile","tbiFilehandle","meta","getMetadata","refNames","refNameToId","nref","colSeq","columnNumbers","ref","colBeg","colEnd","metaChar","sequenceNames","getSequenceNames","readHeaderLines","headerStr","readLines","lines","getLines","lineCallback","decodeBed","maxColumnCount","gffTags","columnCount","attrs","pairs","pair","parseGFFStyleAttributes","attributes","nameField","gffNameFields","exonSizes","eStart","eEnd","thicknessColumn","colorColumn","transcriptTypes","cdsTypes","utrTypes","exonTypes","transcriptPartTypes","cltn","isTranscript","endsWith","isTranscriptPart","isIntron","isExon","includes","isCoding","isUTR","gffEncodings","decodeGFFAttribute","decoded","parseGFFAttributes","attributeString","keyValueDelim","isGff3","kv","stripQuotes","decodeBase","_delim","phase","source","getAttributeValue","delim","assembleGFFTranscripts","filterTypes","filtered","chrIdMap","combined","idMap","arr","cf","_mergedExons","combineFeaturesById","geneMap","create","transcripts","consumed","builder","geneRecord","parents","getParents","parentId","transcript","finishTranscript","transcriptToFeature","recordToSimpleFeature","number","numberExons","combineFeaturesByType","lastStart","lastEnd","part","findExonContaining","addCDS","addUTR","cds","resolveName","mergedExons","v","fixBedPE","first","every","interChr","f1","f2","dup","start1","end1","start2","end2","getDecoder","_header","decode","bed","pValue","qValue","decodeBroadPeak","toBedHeader","delimiter","requiresAssembly","peak","decodeNarrowPeak","decodeBedGraph","keyLower","decodeGFF3","idField","parentField","decodeGTF","decodeRefflat","decodeGappedPeak","columns","hiccups","columnNames","stdColumns","strand1","strand2","extras","decodeBedpe","toBedpeHeader","postProcess","colorToken","decodeInteract","props","parseTrackLine","cd","parseColumnsDirective","parseFeatures","resolvedFormat","info","wigState","parseFixedStep","parseVariableStep","decodeHeader","assembleGFF","curr","tmp","tk","span","index","knownFileExtensions","TextFeatureSource","allFeaturesLoaded","detected","qIdx","slashIdx","ext","inferFormatFromPath","indexed","_indexed","indexURL","isLikelyIndexed","inferIndexURL","tabixReader","featureCache","fetchIndexed","fetchNonIndexed","headerLines","loadAllFeatures","globalThis","urlLower","isGzUrl","contentEncoding","ds","DecompressionStream","Response","body","pipeThrough","localeCompare","chrNames","fromEntries","chrName","allByChrom","entries","SequenceDataSource","renderInteractionTrack","computeDataRange","drawState","radiusY","m1","m2","mLeft","mRight","pixelStart","radiusX","xc","ellipse","s1","e1","s2","e2","hb","yc","pixelStart2","drawInterChrRect","drawProportional","sinTheta","cosTheta","pixelEnd","coa","thetaLeft","thetaRight","estimateTheta","autoscaleNested","drawNested","maxHeight","otherChr","alphaCache","positionString","startStr","endStr","InteractionTrackCanvas","candidates","dist","ellipseScore","tolerance","buildPopupData","cur","registry","typeAliases","registerTrackCreator","creator","registerTypeAlias","canonicalType","getTrackCreator","resolveType","knownTrackTypes","types","createDataSource","createTrackFromConfig","trackConfig","dataSource","dataSourceConfig","createTrackFromSession","dataSourceCacheKey","StateProjection","browser","snapshots","getState","project","structuredClone","prev","current","unchanged","prevIds","tracks","currentIds","added","removed","tracksAdded","tracksRemoved","changed","ct","pt","featureSummariesEqual","featureSummary","diffFeatureSummary","tracksChanged","JSON","stringify","roisChanged","deleteSnapshot","getSnapshot","snapshotKeys","clearSnapshots","raw","managedTracks","getManagedTracks","locusString","formatLocusCompact","classifyZoom","mt","projectTrack","summarizeFeatures","hasDataSource","hasCachedData","loading","summarizeWig","summarizeAnnotation","summarizeInteraction","getCachedFeatures","visible","filterByLocus","signalRange","nameSet","packingDepth","featureNames","valueRange","hasChange","ac","bc","av","bv","selectTracks","selector","where","matchesSelector","BrowserEvent","LocusChange","TrackAdded","TrackRemoved","TrackOrderChanged","DataLoaded","DataError","RenderError","TrackClick","TrackHover","TrackContextMenu","ROIAdded","ROIRemoved","ROIChanged","ROIClick","ROIContextMenu","ThemeChanged","nextTrackId","HeadlessGenomeBrowser","_viewportWidth","_state","roiSets","inflightFetches","events","clamp","popupProvider","_g","contextMenuProvider","_h","stateProjection","cumOffsets","clampLocus","setViewportWidth","loadAllTracksIfNeeded","addTrack","maxTrackHeight","abortController","loadTrackWithDedup","removeTrack","trackOrId","moveTrack","toIndex","fromIndex","clampedIndex","moved","getTrackOrder","getManagedTrack","getTrack","findTracks","removeTracks","updateTrackMetadata","search","query","trimmed","parseLocus","zoomIn","factor","zoomByFactor","zoomOut","zoomAroundCenter","centerBP","currentSpan","newSpan","frac","halfSpan","reloadData","addROI","setName","addROISet","removeROI","roiId","updateROI","updated","clearROIs","getROIs","flatMap","getROISets","findROIsAtLocus","getVisibleROIs","toSVG","trackHeights","visibleROIs","genomeConfig","loadSession","session","trackOptions","created","roiConfig","fromSession","addTrackFromConfig","addRuler","addWigTrack","addGtxTrack","addGeneTrack","ucscTrack","addBedTrack","addInteractionTrack","addSequenceTrack","resolveInteraction","genomicLocation","vw","visibilityWindow","beyondVisibilityWindow","fetchRegion","bufferLocus","dsKey","other","inflightKey","inflight","DOMException","finally","CommandError","message","toTrackSelector","wire","nameRegex","CommandDispatcher","dispatch","handleGetState","handleNavigate","handleModifyTracks","handleQueryFeatures","handleAnnotate","handleSetLayout","handleExportView","handleManageROIs","handleSubscribeEvents","zoom","actions","success","trackId","summaries","managedTrackToSummary","summarize","trackSummary","currentTracks","matched","toAdd","desired","findMatchingTrack","alreadyMatched","desiredKey","layoutMatchKey","supportsPNG","exportPNG","sets","Array","isArray","validEvents","subscribed","onSubscribeEvents","RemoteConnection","socket","unsubscribers","detached","subscribedEvents","dispatcher","messageHandler","handleMessage","closeHandler","addEventListener","subscribeToEvents","unsub","removeEventListener","isDetached","parsed","parse","commandArgs","send","readyState","eventNames","eventName","sanitizeEventData","trackIds","findTrackId","findManagedTrack","trackType","prettyPrintNumber","toLogValue","renderQuantitativeAxis","flip","topY","bottomY","topValue","bottomValue","bg","fg","tickEnd","tickStart","midVal","logMid","midY","lo","hi","valueToY","renderLabelAxis","maxTextWidth","AXIS_COLUMN_WIDTH","injectedRoots","WeakSet","GenomeBrowser","customElements","show","getComputedStyle","setItems","showAt","hide","remove","createDefaultContextMenuProvider","setData","createDefaultPopupProvider","isDragging","lastPointerX","isSweeping","sweepStartX","sweepOverlay","sweepRulerCanvas","pointerDownX","pointerDownY","pointerDownTarget","lastClickTime","lastClickX","lastClickY","singleClickTimer","hoverThrottleId","_rafId","trackRows","handleContextMenu","inputDialog","remoteConnection","reorderDragTrack","reorderDragRow","reorderHandlers","handlePointerDown","handlePointerMove","handlePointerUp","handleMouseMove","handleMouseLeave","handleDocMouseDown","handleWheel","wheelRafId","roiOverlayContainer","roiElements","interactive","getRootNode","textContent","Document","head","injectScrollStyles","userSelect","touchAction","cursor","setupDragHandlers","setupHoverHandlers","setupContextMenuHandler","wheelZoom","setupWheelHandler","target","updateAxisContent","alignItems","axisDiv","flexShrink","overflow","borderRight","boxSizing","viewportWrapper","flex","minWidth","overflowY","overscrollBehaviorY","classList","axisCanvas","setupReorderHandlers","teardownReorderHandlers","syncDOMOrder","clearROIOverlay","containerWidth","trackWidth","attachRemote","toPNG","detachRemote","cancelAnimationFrame","teardownDragHandlers","teardownHoverHandlers","teardownContextMenuHandler","teardownWheelHandler","removeSweepOverlay","rawInfo","innerHTML","visibleHeight","paintAxisCanvas","trackHeight","renderFn","isRulerCanvas","HTMLCanvasElement","some","createSweepOverlay","rulerCanvas","cssText","parentElement","button","isOverlayTarget","clientX","clientY","getBoundingClientRect","setPointerCapture","pointerId","currentX","deltaX","deltaBP","requestAnimationFrame","newStart","newEnd","wasDragging","CLICK_THRESHOLD","handleClick","composedPath","HTMLElement","tagName","findTrackForTarget","canvasCoords","genomePos","genomeToChromCoord","isDoubleClick","shiftKey","containerRect","canvasRect","preventDefault","trackItems","callbacks","setTrackHeight","promptInput","prompt","commonItems","commonContextMenuItems","wrapAction","wrapped","numericState","numericItems","minStr","maxStr","numericDataMenuItems","allItems","down","stopPropagation","move","up","pointerY","aboveEntry","aboveRect","belowEntry","belowRect","dragEntry","docMove","docUp","handlers","ctrlKey","deltaY","pointerX","passive","ensureROIOverlayContainer","visibleIds","createROIElement","borderLeftColor","borderRightColor","firstElementChild","headerColor","querySelector","_roiId","className","clickedROI","relX","showROIContextMenu","desc","goToRegion","roiContextMenuItems","totalWidth","axisWidth","axisInfo","axisId","svgString","blob","Blob","URL","createObjectURL","Image","onload","canvasCtx","onerror","src","revokeObjectURL","saveSVGtoFile","filename","downloadURL","savePNGtoFile","dataURL","download","click","GenomeBrowserContext","createContext","LoomBrowser","forwardRef","defaultLocus","onLocusChange","genes","trackConfigs","remoteSocket","containerRef","useRef","browserRef","setBrowser","useState","settingLocusFromProp","onLocusChangeRef","useEffect","initialLocus","tc","newLocus","useImperativeHandle","ctxValue","useMemo","_jsxs","Provider","_jsx","useGenomeBrowser","useContext","useBrowserEvent","handlerRef","listener","useLocus","setLocusState","useCallback","l","useTrackManager","recreationDeps","updateTrack","updateDeps","trackRef","prevRecreationDeps","isFirstRender","recreationChanged","dep","RulerTrack","WigTrack","GeneTrack","BedTrack","SequenceTrack","InteractionTrack","GtxTrack","LoomContextMenu","attachShadow","connectedCallback","tpl","shadowRoot","content","menuDiv","buildItems","sep","div","disabled","check","arrow","submenu","offsetParent","parentRect","menuRect","define","_template","LoomPopup","popup","tbody","tr","borderTop","tdName","tdValue","popupRect","LoomInputDialog","labelEl","inputEl","okBtn","cancelBtn","confirm","cancel","currentValue","focus","select"],"mappings":"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,MACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,MACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,MACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,QACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,QACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,MACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,QACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,MACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,MACrBC,oBAAqB,OACrBC,oBAAqB,MACrBC,oBAAqB,OACrBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,MACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,MACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,MACtBC,qBAAsB,MACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,MACtBC,qBAAsB,OACtBC,qBAAsB,QACtBC,qBAAsB,OACtBC,qBAAsB,QACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,MACtBC,qBAAsB,OACtBC,qBAAsB,QACtBC,qBAAsB,OACtBC,qBAAsB,MACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,QACtBC,qBAAsB,OACtBC,qBAAsB,MACtBC,qBAAsB,OACtBC,qBAAsB,QACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,MACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,MACtBC,qBAAsB,MACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,MACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,MACtBC,qBAAsB,OACtBC,qBAAsB,MACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,MACtBC,qBAAsB,OACtBC,qBAAsB,MACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,MACtBC,qBAAsB,OACtBC,oBAAqB,OACrBC,oBAAqB,OACrBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,QACrBC,oBAAqB,OACrBC,oBAAqB,QACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,OACrBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,QACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,MACtBC,qBAAsB,QACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,MACtBC,oBAAqB,OACrBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,oBAAqB,OACrBC,oBAAqB,OACrBC,oBAAqB,QACrBC,oBAAqB,OACrBC,qBAAsB,OACtBC,qBAAsB,QACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,qBAAsB,OACtBC,oBAAqB,OACrBC,oBAAqB,QACrBC,qBAAsB,QACtBC,oBAAqB,OACrBC,oBAAqB,QACrBC,qBAAsB,QACtBC,oBAAqB,OACrBC,oBAAqB,QACrBC,qBAAsB,QACtBC,oBAAqB,OACrBC,oBAAqB,QACrBC,qBAAsB,OACtBC,oBAAqB,MACrBC,qBAAsB,OACtBC,qBAAsB,QAEtBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,MAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,IAClBC,iBAAkB,MAClBC,iBAAkB,MAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,IAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,OAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,MAClBC,iBAAkB,OAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,MAClBC,iBAAkB,OAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,IAClBC,iBAAkB,MAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,MAClBC,iBAAkB,MAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,IAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAAkB,IAClBC,iBAAkB,KAClBC,iBAAkB,IAClBC,iBAAkB,KAClBC,iBAAkB,KAClBC,iBAA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"}
|