@fishka/seqio 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,370 @@
1
+ /**
2
+ * Low-level ABIF file model: a flat list of directory entries with raw
3
+ * payloads. Lossless round-trip is preserved: every entry (including unknown
4
+ * vendor tags) is kept as a raw payload, so a subsequent writeAbif() reproduces
5
+ * the same meaning.
6
+ */
7
+ interface AbifFile {
8
+ /** ABIF version, e.g. 101 for v1.01. */
9
+ version: number;
10
+ /** Directory entries in the original on-disk order. */
11
+ entries: AbifEntry[];
12
+ /** MacBinary preamble offset (128 if present, 0 otherwise). Preserved for diagnostics. */
13
+ macBinaryOffset: number;
14
+ }
15
+ interface AbifEntry {
16
+ /** 4-character tag name, e.g. "DATA", "PBAS". */
17
+ tagName: string;
18
+ /** Tag number, e.g. 1 or 2 for PBAS1 / PBAS2. */
19
+ tagNumber: number;
20
+ /** ABIF element type code (1=byte, 2=char, 3=word, 4=short, 5=long, 7=float,
21
+ * 8=double, 10=date, 11=time, 13=bool, 18=pString, 19=cString,
22
+ * 1023=tdir, ≥1024=user-defined). */
23
+ elementType: number;
24
+ /** Bytes per element. */
25
+ elementSize: number;
26
+ /** Number of elements. */
27
+ elementCount: number;
28
+ /** Raw payload bytes (length === elementCount * elementSize). */
29
+ payload: Uint8Array;
30
+ /** Opaque dataHandle field, usually 0. Preserved for round-trip. */
31
+ dataHandle: number;
32
+ }
33
+ interface ChannelSignals {
34
+ A: number[];
35
+ C: number[];
36
+ G: number[];
37
+ T: number[];
38
+ }
39
+ /** Per-base chromatogram view. */
40
+ interface Chromatogram {
41
+ /** Per-base peak position in sample points (from PLOC). */
42
+ positions: number[];
43
+ /** Four channels of signal values, aligned with sample points. */
44
+ signals: ChannelSignals;
45
+ /** Per-base Phred-like quality scores (0..100), from PCON. */
46
+ confidences?: number[];
47
+ /** Average peak spacing (samples per base), from SPAC. */
48
+ samplingRate?: number;
49
+ }
50
+ /** Basecalls extracted from PBAS/PCON/PLOC under the chosen version. */
51
+ interface AbifBaseCalls {
52
+ /** Called bases (uppercase). */
53
+ sequence: string;
54
+ /** Per-base Q-score / confidence (PCON). */
55
+ confidences: number[];
56
+ /** Per-base peak positions in sample points (PLOC). */
57
+ positions: number[];
58
+ /** Which PBAS version was selected (1 or 2). */
59
+ pbasVersion: number;
60
+ }
61
+ /** Optional metadata extracted from well-known tags. */
62
+ interface AbifMetadata {
63
+ sampleName?: string;
64
+ laneNumber?: number;
65
+ tube?: string;
66
+ machineName?: string;
67
+ machineModel?: string;
68
+ runDate?: string;
69
+ runTime?: string;
70
+ samplingRate?: number;
71
+ comments: string[];
72
+ }
73
+ /** Full chromatogram bundle: all DATA channels, plus FWO_-aware A/C/G/T views. */
74
+ interface AbifChromatogramBundle {
75
+ /** FWO_ value (e.g. "GATC"). */
76
+ baseOrder: string;
77
+ /** All DATA tags by tagNumber → trace. */
78
+ dataChannels: Record<number, number[]>;
79
+ /** Basecalled traces (DATA9..12) mapped to A/C/G/T by FWO_. */
80
+ basecalled: ChannelSignals;
81
+ /** Raw traces (DATA1..4) mapped to A/C/G/T by FWO_. */
82
+ raw: ChannelSignals;
83
+ }
84
+ /** Rich result from {@link parseAbif} — everything the typical viewer needs. */
85
+ interface ParsedAbif {
86
+ fileName: string;
87
+ fileSize: number;
88
+ abifVersion: number;
89
+ macBinaryOffset: number;
90
+ dirEntryCount: number;
91
+ metadata: AbifMetadata;
92
+ chromatogram: AbifChromatogramBundle;
93
+ baseCalls?: AbifBaseCalls;
94
+ /** All directory entries with their decoded payloads (best-effort by type). */
95
+ entries: AbifDirEntry[];
96
+ }
97
+ /** A directory entry with a typed decoded value alongside the raw payload. */
98
+ interface AbifDirEntry {
99
+ /** 4-character tag name, e.g. "DATA". */
100
+ tag: string;
101
+ tagNumber: number;
102
+ elementType: number;
103
+ elementTypeName: string;
104
+ elementSize: number;
105
+ elementCount: number;
106
+ dataSize: number;
107
+ dataOffset: number;
108
+ inline: boolean;
109
+ decoded: AbifDecodedValue;
110
+ preview: string;
111
+ }
112
+ type AbifDecodedValue = {
113
+ kind: 'number';
114
+ value: number;
115
+ } | {
116
+ kind: 'numbers';
117
+ value: number[];
118
+ } | {
119
+ kind: 'string';
120
+ value: string;
121
+ } | {
122
+ kind: 'bools';
123
+ value: boolean[];
124
+ } | {
125
+ kind: 'date';
126
+ value: {
127
+ year: number;
128
+ month: number;
129
+ day: number;
130
+ };
131
+ } | {
132
+ kind: 'time';
133
+ value: {
134
+ hour: number;
135
+ minute: number;
136
+ second: number;
137
+ hsec: number;
138
+ };
139
+ } | {
140
+ kind: 'bytes';
141
+ value: Uint8Array;
142
+ } | {
143
+ kind: 'unknown';
144
+ value: Uint8Array;
145
+ };
146
+
147
+ declare function tagNameFromInt32(n: number): string;
148
+
149
+ /**
150
+ * Low-level ABIF reader/writer.
151
+ *
152
+ * Round-trip without loss: every directory entry (including unknown vendor
153
+ * tags) is preserved as a raw payload (Uint8Array). The high-level layer
154
+ * (view.ts, parser.ts) provides typed access on top of this.
155
+ *
156
+ * ABIF file layout:
157
+ * [0..3] "ABIF" magic
158
+ * [4..5] version (int16 BE; 101 = v1.01)
159
+ * [6..33] TdirEntry describing the directory itself
160
+ * [34..127] reserved (94 bytes, zero-filled)
161
+ * [...] directory block (N * 28-byte entries) and payload blocks
162
+ *
163
+ * TdirEntry (28 bytes, big-endian):
164
+ * off size field
165
+ * 0 4 tagName (ASCII)
166
+ * 4 4 tagNumber (int32)
167
+ * 8 2 elementType (int16)
168
+ * 10 2 elementSize (int16)
169
+ * 12 4 elementCount (int32)
170
+ * 16 4 dataSize (int32; total payload bytes; spec says count*size)
171
+ * 20 4 dataOffset (int32) OR inline data if dataSize <= 4
172
+ * 24 4 dataHandle (int32; usually 0)
173
+ *
174
+ * Inline rule (per ABIF spec): when count*size <= 4 the payload bytes are
175
+ * stored directly in the dataOffset field (left-aligned, padded to 4 bytes).
176
+ *
177
+ * MacBinary preamble: some ABIF files (older Mac-origin) start with a 128-byte
178
+ * MacBinary header before the actual ABIF magic. We detect and skip it.
179
+ */
180
+
181
+ declare const HEADER_SIZE = 128;
182
+ declare const ENTRY_SIZE = 28;
183
+ /**
184
+ * Parse an ABIF file from raw bytes.
185
+ *
186
+ * Accepts Uint8Array (works in Node and the browser). Node's Buffer extends
187
+ * Uint8Array, so `readAbif(buffer)` and `readAbif(new Uint8Array(arrayBuffer))`
188
+ * both work.
189
+ *
190
+ * Throws if the magic header is missing. Does NOT require any specific tags
191
+ * (PBAS, DATA, ...) to be present — raw pre-basecalled files are supported.
192
+ */
193
+ declare function readAbif(bytes: Uint8Array): AbifFile;
194
+ /**
195
+ * Serialize an AbifFile back to a Uint8Array.
196
+ *
197
+ * Layout produced: header (128 B) + directory (N*28 B) + payload block.
198
+ * External payloads are packed tightly in entry order. Inline payloads
199
+ * (count*size <= 4) live entirely inside their directory entry.
200
+ *
201
+ * The output is not bit-identical to the input if the original had a different
202
+ * physical layout (e.g. payloads before directory), but the *meaning*
203
+ * round-trips: readAbif(writeAbif(f)) reproduces the same entries structurally.
204
+ *
205
+ * MacBinary preamble is not preserved by writeAbif.
206
+ */
207
+ declare function writeAbif(file: AbifFile): Uint8Array;
208
+ /** Find an entry by name+number, or undefined. */
209
+ declare function findEntry(file: AbifFile, name: string, number: number): AbifEntry | undefined;
210
+ /** Find all entries with the given tag name. */
211
+ declare function findEntries(file: AbifFile, name: string): AbifEntry[];
212
+ /**
213
+ * Replace the payload of an existing entry, or append a new one.
214
+ * elementType/elementSize/elementCount must be supplied for new entries.
215
+ */
216
+ declare function upsertEntry(file: AbifFile, name: string, number: number, payload: Uint8Array, defaults: {
217
+ elementType: number;
218
+ elementSize: number;
219
+ elementCount: number;
220
+ }): void;
221
+
222
+ /**
223
+ * High-level typed view over an AbifFile.
224
+ *
225
+ * Reading helpers that interpret the raw payloads of well-known tags. For
226
+ * mutation helpers (setSequence, setConfidences, ...) see ./setters.
227
+ */
228
+
229
+ /** Get DATA<n> as a signed-int16 array, or undefined. */
230
+ declare function getDataChannel(file: AbifFile, n: number): Int16Array | undefined;
231
+ /**
232
+ * Dye order, 4 ASCII chars (e.g. "GATC"). Defaults to "GATC" if FWO_ absent.
233
+ *
234
+ * GATC is the dye order produced by modern ABI 3730/3500 instruments and the
235
+ * dominant default in the wild. Older "ACGT" defaults caused channel
236
+ * mis-mapping on files where FWO_ is missing or malformed.
237
+ */
238
+ declare function getFwo(file: AbifFile): string;
239
+ /**
240
+ * True when the file carries BOTH DATA1..4 and DATA9..12. Newer ABI-style
241
+ * instruments produce both: DATA1..4 is post-processed (mobility-corrected,
242
+ * baseline-subtracted, color-separated) and DATA9..12 is raw fluorescence.
243
+ * Older instruments produce only DATA1..4 (which IS the raw signal).
244
+ *
245
+ * Callers that re-process traces (basecallers) should detect this and bypass
246
+ * their own baseline-subtraction / color-matrix steps when DATA1..4 is
247
+ * already cleaned.
248
+ */
249
+ declare function hasProcessedTraces(file: AbifFile): boolean;
250
+ /**
251
+ * Map from base letter ("A"|"C"|"G"|"T") to the DATA tag number that holds
252
+ * its RAW fluorescence channel.
253
+ *
254
+ * ABIF stores up to 12 DATA tags. KB-basecaller-aware instruments (3130, 3500,
255
+ * ...) use DATA1..4 for processed traces and DATA9..12 for raw. Older / simpler
256
+ * instruments produce only DATA1..8 where DATA1..4 ARE the raw traces.
257
+ *
258
+ * This helper always returns the DATA1..4 mapping (the convention used by
259
+ * basecallers operating on raw signal). Use {@link hasProcessedTraces} to
260
+ * detect whether DATA1..4 has been pre-processed and bypass baseline/color
261
+ * steps accordingly.
262
+ *
263
+ * The dye-to-channel order within each block is given by FWO_. If
264
+ * FWO_="GATC" then G→1, A→2, T→3, C→4.
265
+ */
266
+ declare function getRawChannelMap(file: AbifFile): Record<'A' | 'C' | 'G' | 'T', number>;
267
+ /** Get PBAS sequence (prefer PBAS2 over PBAS1). undefined if neither present. */
268
+ declare function getSequence(file: AbifFile): string | undefined;
269
+ /**
270
+ * Get per-base Phred-like quality scores (0..255 byte values, typically 0..60
271
+ * for Sanger). Prefers PCON2 over PCON1.
272
+ *
273
+ * PCON is declared in the ABIF spec as elementType=2 (char) but the byte
274
+ * values ARE the Q-scores — we read raw bytes regardless of declared type.
275
+ */
276
+ declare function getConfidences(file: AbifFile): number[] | undefined;
277
+ /**
278
+ * Get peak scan positions (one per base). Prefers PLOC2 over PLOC1.
279
+ *
280
+ * Read as UNSIGNED int16: PLOC indexes into the sample trace and is always
281
+ * non-negative, but values > 32767 (long traces) would wrap to negative
282
+ * if interpreted as signed.
283
+ */
284
+ declare function getPositions(file: AbifFile): number[] | undefined;
285
+ /**
286
+ * Get average peak spacing (samples per base), from SPAC/1.
287
+ *
288
+ * ABIF spec defines SPAC as float32 (elementType=7); some legacy files
289
+ * mislabel it as long (type=5). Both are 4 bytes and on disk the payload
290
+ * is always a 32-bit float, so we read as float regardless of declared type.
291
+ *
292
+ * Returns undefined if SPAC is absent or non-positive.
293
+ */
294
+ declare function getSamplingRate(file: AbifFile): number | undefined;
295
+
296
+ /**
297
+ * Mutation helpers for AbifFile: write PBAS/PCON/PLOC/SPAC and ensure DATA9..12
298
+ * are present. Used by basecallers to author ABIF output.
299
+ */
300
+
301
+ /** Set PBAS2 (replaces if present). */
302
+ declare function setSequence(file: AbifFile, sequence: string): void;
303
+ /** Set PCON2 (replaces if present). Values clamped to [0, 255]. */
304
+ declare function setConfidences(file: AbifFile, q: ArrayLike<number>): void;
305
+ /**
306
+ * Set PLOC2 (replaces if present).
307
+ *
308
+ * Written as UNSIGNED int16 so positions up to 65535 are preserved on disk
309
+ * (signed int16 would wrap on traces with > 32k scans).
310
+ */
311
+ declare function setPositions(file: AbifFile, positions: ArrayLike<number>): void;
312
+ /**
313
+ * Set SPAC/1, SPAC/2, SPAC/3 — the standard ABIF "average peak spacing" trio
314
+ * that KB-basecaller writes and downstream tools (BioPython, Sequencher,
315
+ * KB-aware viewers) expect:
316
+ *
317
+ * - SPAC/1 (float32) — average peak spacing used in last analysis.
318
+ * - SPAC/2 (pString) — basecaller name / identifier.
319
+ * - SPAC/3 (float32) — average peak spacing computed by the basecaller.
320
+ *
321
+ * Both float fields are written with the same value.
322
+ */
323
+ declare function setAveragePeakSpacing(file: AbifFile, spacing: number, basecallerName: string): void;
324
+ /**
325
+ * Mean consecutive peak-to-peak distance in scans, from a positions array.
326
+ * Returns 0 when fewer than 2 positions are present.
327
+ */
328
+ declare function averagePeakSpacing(positions: ArrayLike<number>): number;
329
+ /**
330
+ * Ensure DATA9..12 are present in the file. Many downstream consumers
331
+ * (BioPython-style readers, viewers) read the chromatogram signal from
332
+ * DATA9..12 by convention — these tags are the raw fluorescence on newer
333
+ * instruments. Older files that only carry DATA1..8 break those consumers
334
+ * with a "no signal" error after re-basecalling.
335
+ *
336
+ * We populate DATA9..12 by copying DATA1..4 (which on DATA1..8-only files IS
337
+ * the raw signal). The DATA1..4 tags are left untouched so any tool that
338
+ * reads them keeps working.
339
+ *
340
+ * No-op when DATA9..12 already exist.
341
+ */
342
+ declare function ensureRawDataChannels(file: AbifFile): void;
343
+
344
+ /**
345
+ * High-level "parse everything" wrapper around the raw + view layers.
346
+ *
347
+ * Returns a single ParsedAbif object with metadata, the FWO_-aware
348
+ * basecalled / raw channel split, basecalls, and decoded directory entries
349
+ * for diagnostics. Mirrors what typical viewers (chromatogram UIs, sample
350
+ * inspectors) need from a single file.
351
+ *
352
+ * For round-trip authoring (basecallers), prefer {@link readAbif} +
353
+ * setters from ./setters which operate directly on the raw AbifFile.
354
+ */
355
+
356
+ /**
357
+ * Parse an ABIF file into a high-level view: metadata, channels, basecalls,
358
+ * and decoded directory entries.
359
+ *
360
+ * Accepts ArrayBuffer or Uint8Array (Buffer in Node works too — it extends
361
+ * Uint8Array). The `fileName` argument is informational only; it's preserved
362
+ * in the result.
363
+ */
364
+ declare function parseAbif(input: ArrayBuffer | Uint8Array, fileName?: string): ParsedAbif;
365
+ /** True when any channel has at least one signal value. */
366
+ declare function hasSignals(s: ChannelSignals): boolean;
367
+ /** Length of the longest channel in a ChannelSignals bundle. */
368
+ declare function channelMaxLength(s: ChannelSignals): number;
369
+
370
+ export { type AbifBaseCalls, type AbifChromatogramBundle, type AbifDecodedValue, type AbifDirEntry, type AbifEntry, type AbifFile, type AbifMetadata, type ChannelSignals, type Chromatogram, ENTRY_SIZE, HEADER_SIZE, type ParsedAbif, averagePeakSpacing, channelMaxLength, ensureRawDataChannels, findEntries, findEntry, getConfidences, getDataChannel, getFwo, getPositions, getRawChannelMap, getSamplingRate, getSequence, hasProcessedTraces, hasSignals, parseAbif, readAbif, setAveragePeakSpacing, setConfidences, setPositions, setSequence, tagNameFromInt32, upsertEntry, writeAbif };
@@ -0,0 +1,2 @@
1
+ 'use strict';function y(e){let t="";for(let n=0;n<e.length;n++)t+=String.fromCharCode(e[n]);return t}function x(e){let t=new Uint8Array(e.length);for(let n=0;n<e.length;n++)t[n]=e.charCodeAt(n)&255;return t}function p(e){return new DataView(e.buffer,e.byteOffset,e.byteLength)}function C(e,t,n){return e.subarray(t,t+n)}function P(e){return String.fromCharCode(e>>>24&255,e>>>16&255,e>>>8&255,e&255)}var F=128,w=28;function U(e){if(e.byteLength<F)throw new Error(`ABIF too small: ${e.byteLength} bytes`);let t=0;if(y(C(e,0,4))!=="ABIF")if(e.byteLength>=132&&y(C(e,128,4))==="ABIF")t=128;else throw new Error('Not an ABIF file: missing "ABIF" magic.');let n=t,r=p(e),a=r.getInt16(n+4,false),i=k(e,r,n+6);if(i.tagName!=="tdir")throw new Error(`Expected "tdir" header entry, got "${i.tagName}"`);if(i.elementSize!==w)throw new Error(`Expected dir element size ${w}, got ${i.elementSize}`);let c=i.elementCount,m=r.getInt32(n+6+20,false);if(m<0||m+c*w>e.byteLength-n)throw new Error(`Directory out of bounds: offset=${m}, entries=${c}, file=${e.byteLength-n}`);let h=[];for(let o=0;o<c;o++)h.push(k(e,r,n+m+o*w));return {version:a,entries:h,macBinaryOffset:t}}function k(e,t,n){let r=y(C(e,n,4)),a=t.getInt32(n+4,false),i=t.getInt16(n+8,false),c=t.getInt16(n+10,false),m=t.getInt32(n+12,false),h=t.getInt32(n+16,false),o=t.getInt32(n+24,false),g=Math.max(0,m*Math.max(0,c)),b=Math.min(g,Math.max(0,h)),N=g<=4,$=c>0&&h>=0&&h<g?Math.floor(h/c):m,S;if(N)S=new Uint8Array(C(e,n+20,b));else {let A=t.getInt32(n+20,false);if(A<0||A+b>e.byteLength)throw new Error(`Entry ${r}${a}: payload out of bounds (offset=${A}, size=${b})`);S=new Uint8Array(C(e,A,b));}return {tagName:r,tagNumber:a,elementType:i,elementSize:c,elementCount:$,payload:S,dataHandle:o}}function H(e){let t=e.entries.length,n=F,r=t*w,a=n+r,i=new Array(t);for(let o=0;o<t;o++){let g=e.entries[o],b=g.elementCount*g.elementSize;if(g.payload.byteLength!==b)throw new Error(`Entry ${g.tagName}${g.tagNumber}: payload length ${g.payload.byteLength} != dataSize ${b}`);b>4?(i[o]=a,a+=b):i[o]=-1;}let c=a,m=new Uint8Array(c),h=p(m);m.set(x("ABIF"),0),h.setInt16(4,e.version,false),z({tagName:"tdir",tagNumber:1,elementType:1023,elementSize:w,elementCount:t,payload:new Uint8Array(0),dataHandle:0},m,h,6,-1,r,n);for(let o=0;o<t;o++){let g=e.entries[o];z(g,m,h,n+o*w,i[o]);}for(let o=0;o<t;o++){let g=i[o];g>=0&&m.set(e.entries[o].payload,g);}return m}function z(e,t,n,r,a,i,c){if(e.tagName.length!==4)throw new Error(`tagName must be 4 chars: "${e.tagName}"`);t.set(x(e.tagName),r),n.setInt32(r+4,e.tagNumber,false),n.setInt16(r+8,e.elementType,false),n.setInt16(r+10,e.elementSize,false),n.setInt32(r+12,e.elementCount,false);let m=i??e.elementCount*e.elementSize;if(n.setInt32(r+16,m,false),c!==void 0)n.setInt32(r+20,c,false);else if(m<=4)t.fill(0,r+20,r+24),t.set(e.payload.subarray(0,m),r+20);else {if(a<0)throw new Error(`External payload requires offset for ${e.tagName}${e.tagNumber}`);n.setInt32(r+20,a,false);}n.setInt32(r+24,e.dataHandle,false);}function d(e,t,n){return e.entries.find(r=>r.tagName===t&&r.tagNumber===n)}function _(e,t){return e.entries.filter(n=>n.tagName===t)}function v(e,t,n,r,a){if(r.byteLength!==a.elementCount*a.elementSize)throw new Error(`upsertEntry ${t}${n}: payload length ${r.byteLength} != count*size`);let i=d(e,t,n);i?(i.elementType=a.elementType,i.elementSize=a.elementSize,i.elementCount=a.elementCount,i.payload=r):e.entries.push({tagName:t,tagNumber:n,elementType:a.elementType,elementSize:a.elementSize,elementCount:a.elementCount,payload:r,dataHandle:0});}function Z(e,t){let n=d(e,"DATA",t);if(!n)return;if(n.elementSize!==2)throw new Error(`DATA${t}: expected elementSize=2, got ${n.elementSize}`);let r=new Int16Array(n.elementCount),a=p(n.payload);for(let i=0;i<n.elementCount;i++)r[i]=a.getInt16(i*2,false);return r}function E(e){let t=d(e,"FWO_",1);return t?y(t.payload):"GATC"}function I(e){return !!(d(e,"DATA",9)&&d(e,"DATA",10)&&d(e,"DATA",11)&&d(e,"DATA",12))}function J(e){let t=E(e);if(!/^[ACGT]{4}$/.test(t))throw new Error(`FWO_ malformed: "${t}"`);return {[t[0]]:1,[t[1]]:2,[t[2]]:3,[t[3]]:4}}function K(e){let t=d(e,"PBAS",2);if(t)return y(t.payload);let n=d(e,"PBAS",1);if(n)return y(n.payload)}function Q(e){let t=d(e,"PCON",2)??d(e,"PCON",1);if(!t)return;let n=new Array(t.elementCount);for(let r=0;r<t.elementCount;r++)n[r]=t.payload[r];return n}function X(e){let t=d(e,"PLOC",2)??d(e,"PLOC",1);if(!t)return;if(t.elementSize!==2)throw new Error(`PLOC: expected elementSize=2, got ${t.elementSize}`);let n=p(t.payload),r=new Array(t.elementCount);for(let a=0;a<t.elementCount;a++)r[a]=n.getUint16(a*2,false);return r}function ee(e){let t=d(e,"SPAC",1);if(!t||t.elementSize!==4||t.payload.byteLength<4)return;let n=p(t.payload).getFloat32(0,false);return Number.isFinite(n)&&n>0?n:void 0}function ie(e,t){v(e,"PBAS",2,x(t),{elementType:2,elementSize:1,elementCount:t.length});}function oe(e,t){let n=new Uint8Array(t.length);for(let r=0;r<t.length;r++)n[r]=Math.max(0,Math.min(255,Math.round(t[r])));v(e,"PCON",2,n,{elementType:2,elementSize:1,elementCount:t.length});}function se(e,t){let n=new Uint8Array(t.length*2),r=p(n);for(let a=0;a<t.length;a++)r.setUint16(a*2,Math.max(0,Math.min(65535,t[a])),false);v(e,"PLOC",2,n,{elementType:4,elementSize:2,elementCount:t.length});}function le(e,t,n){let r=new Uint8Array(4);p(r).setFloat32(0,t,false),v(e,"SPAC",1,r,{elementType:7,elementSize:4,elementCount:1});let a=x(n),i=Math.min(255,a.length),c=new Uint8Array(1+i);c[0]=i,c.set(a.subarray(0,i),1),v(e,"SPAC",2,c,{elementType:18,elementSize:1,elementCount:1+i});let m=new Uint8Array(4);p(m).setFloat32(0,t,false),v(e,"SPAC",3,m,{elementType:7,elementSize:4,elementCount:1});}function ue(e){return e.length<2?0:(e[e.length-1]-e[0])/(e.length-1)}function me(e){if(!I(e))for(let t=1;t<=4;t++){let n=d(e,"DATA",t);if(!n)continue;let r=8+t;d(e,"DATA",r)||e.entries.push({tagName:"DATA",tagNumber:r,elementType:n.elementType,elementSize:n.elementSize,elementCount:n.elementCount,payload:new Uint8Array(n.payload),dataHandle:0});}}var B={1:"byte",2:"char",3:"word",4:"short",5:"long",7:"float",8:"double",10:"date",11:"time",12:"thumb",13:"bool",18:"pString",19:"cString",1023:"tdir"};function T(e){return B[e]??(e>=1024?`user${e}`:`type${e}`)}function M(e,t=10){return e.length<=t?`[${e.join(", ")}]`:`[${e.slice(0,t).join(", ")}, \u2026 +${e.length-t}] (n=${e.length})`}function O(e,t=80){return e.length>t?e.slice(0,t)+"\u2026":e}function D(e){let t=e.subarray(0,16),n=Array.from(t,r=>r.toString(16).padStart(2,"0")).join(" ");return `${e.byteLength}B [${n}${e.byteLength>16?" \u2026":""}]`}function R(e,t,n){let r=p(n);switch(e){case 1:return {kind:"numbers",value:Array.from(n.subarray(0,t))};case 2:case 19:return {kind:"string",value:y(n.subarray(0,t)).replace(/\0+$/g,"")};case 3:{let a=[];for(let i=0;i<t;i++)a.push(r.getUint16(i*2,false));return a.length===1?{kind:"number",value:a[0]}:{kind:"numbers",value:a}}case 4:{let a=[];for(let i=0;i<t;i++)a.push(r.getInt16(i*2,false));return a.length===1?{kind:"number",value:a[0]}:{kind:"numbers",value:a}}case 5:{let a=[];for(let i=0;i<t;i++)a.push(r.getInt32(i*4,false));return a.length===1?{kind:"number",value:a[0]}:{kind:"numbers",value:a}}case 7:{let a=[];for(let i=0;i<t;i++)a.push(r.getFloat32(i*4,false));return a.length===1?{kind:"number",value:a[0]}:{kind:"numbers",value:a}}case 8:{let a=[];for(let i=0;i<t;i++)a.push(r.getFloat64(i*8,false));return a.length===1?{kind:"number",value:a[0]}:{kind:"numbers",value:a}}case 10:{let a=r.getInt16(0,false),i=r.getUint8(2),c=r.getUint8(3);return {kind:"date",value:{year:a,month:i,day:c}}}case 11:return {kind:"time",value:{hour:r.getUint8(0),minute:r.getUint8(1),second:r.getUint8(2),hsec:r.getUint8(3)}};case 13:{let a=[];for(let i=0;i<t;i++)a.push(r.getUint8(i)!==0);return {kind:"bools",value:a}}case 18:{let a=r.getUint8(0);return {kind:"string",value:y(C(n,1,Math.min(a,Math.max(0,t-1))))}}default:return {kind:"unknown",value:n}}}function G(e,t){switch(e.kind){case "number":return String(e.value);case "numbers":return M(e.value);case "string":return O(JSON.stringify(e.value));case "bools":return e.value.length===1?String(e.value[0]):`[${e.value.join(", ")}]`;case "date":{let{year:n,month:r,day:a}=e.value;return `${n}-${String(r).padStart(2,"0")}-${String(a).padStart(2,"0")}`}case "time":{let{hour:n,minute:r,second:a}=e.value;return `${String(n).padStart(2,"0")}:${String(r).padStart(2,"0")}:${String(a).padStart(2,"0")}`}case "bytes":return `${T(t)} ${D(e.value)}`;case "unknown":return `${T(t)} ${D(e.value)}`}}function be(e,t=""){let n=e instanceof Uint8Array?e:new Uint8Array(e),r=U(n),a=r.entries.map(u=>{let s=R(u.elementType,u.elementCount,u.payload);return {tag:u.tagName,tagNumber:u.tagNumber,elementType:u.elementType,elementTypeName:T(u.elementType),elementSize:u.elementSize,elementCount:u.elementCount,dataSize:u.elementCount*u.elementSize,dataOffset:0,inline:u.elementCount*u.elementSize<=4,decoded:s,preview:G(s,u.elementType)}}),i=E(r);/^[ACGT]{4}$/.test(i)||(i="GATC");let c={},m={A:[],C:[],G:[],T:[]},h={A:[],C:[],G:[],T:[]},o={comments:[]},g={},b={},N={},$=u=>i[u];for(let u=0;u<r.entries.length;u++){let s=r.entries[u],l=a[u].decoded;if(s.tagName==="DATA"&&l.kind==="numbers")c[s.tagNumber]=l.value,s.tagNumber>=1&&s.tagNumber<=4?h[$(s.tagNumber-1)]=l.value:s.tagNumber>=9&&s.tagNumber<=12&&(m[$(s.tagNumber-9)]=l.value);else if(s.tagName==="PBAS"&&l.kind==="string")g[s.tagNumber]=l.value;else if(s.tagName==="PCON")l.kind==="numbers"?b[s.tagNumber]=l.value:l.kind==="string"&&(b[s.tagNumber]=Array.from(l.value,f=>f.charCodeAt(0)));else if(s.tagName==="PLOC"&&l.kind==="numbers")N[s.tagNumber]=l.value.map(f=>f<0?f+65536:f);else if(s.tagName==="SPAC")if(s.elementSize===4&&s.payload.byteLength>=4){let f=p(s.payload).getFloat32(0,false);Number.isFinite(f)&&f>0&&(o.samplingRate=f);}else l.kind==="number"&&(o.samplingRate=l.value);else if(s.tagName==="SMPL"&&l.kind==="string")o.sampleName=l.value;else if(s.tagName==="LANE"&&l.kind==="number")o.laneNumber=l.value;else if(s.tagName==="TUBE"&&l.kind==="string")o.tube=l.value;else if(s.tagName==="MCHN"&&l.kind==="string")o.machineName=l.value;else if(s.tagName==="MODL"&&l.kind==="string")o.machineModel=l.value;else if(s.tagName==="RUND"&&l.kind==="date"){let f=l.value;o.runDate=`${f.year}-${String(f.month).padStart(2,"0")}-${String(f.day).padStart(2,"0")}`;}else if(s.tagName==="RUNT"&&l.kind==="time"){let f=l.value;o.runTime=`${String(f.hour).padStart(2,"0")}:${String(f.minute).padStart(2,"0")}:${String(f.second).padStart(2,"0")}`;}else s.tagName==="CMNT"&&l.kind==="string"&&o.comments.push(l.value);}let S,A=g[2]?2:g[1]?1:Object.keys(g).map(Number)[0];if(A!==void 0&&g[A]){let u=g[A].toUpperCase(),s=b[A]??[];if(s.length===0){for(let f of Object.keys(b).map(Number))if(b[f].length===u.length){s=b[f];break}}let l=N[A]??[];if(l.length===0){for(let f of Object.keys(N).map(Number))if(N[f].length===u.length){l=N[f];break}}S={sequence:u,confidences:s,positions:l,pbasVersion:A};}if(!Number.isFinite(o.samplingRate)||(o.samplingRate??0)<=0){let u=S?.positions,s=Math.max(m.A.length,m.C.length,m.G.length,m.T.length);u&&u.length>1?o.samplingRate=(u[u.length-1]-u[0])/(u.length-1):S&&S.sequence.length>0&&s>0&&(o.samplingRate=s/S.sequence.length);}let L={baseOrder:i,dataChannels:c,basecalled:m,raw:h};return {fileName:t,fileSize:n.byteLength,abifVersion:r.version,macBinaryOffset:r.macBinaryOffset,dirEntryCount:r.entries.length,metadata:o,chromatogram:L,baseCalls:S,entries:a}}function he(e){return e.A.length>0||e.C.length>0||e.G.length>0||e.T.length>0}function pe(e){return Math.max(e.A.length,e.C.length,e.G.length,e.T.length)}exports.ENTRY_SIZE=w;exports.HEADER_SIZE=F;exports.averagePeakSpacing=ue;exports.channelMaxLength=pe;exports.ensureRawDataChannels=me;exports.findEntries=_;exports.findEntry=d;exports.getConfidences=Q;exports.getDataChannel=Z;exports.getFwo=E;exports.getPositions=X;exports.getRawChannelMap=J;exports.getSamplingRate=ee;exports.getSequence=K;exports.hasProcessedTraces=I;exports.hasSignals=he;exports.parseAbif=be;exports.readAbif=U;exports.setAveragePeakSpacing=le;exports.setConfidences=oe;exports.setPositions=se;exports.setSequence=ie;exports.tagNameFromInt32=P;exports.upsertEntry=v;exports.writeAbif=H;//# sourceMappingURL=index.js.map
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/abif/bytes.ts","../../src/abif/raw.ts","../../src/abif/view.ts","../../src/abif/setters.ts","../../src/abif/parser.ts"],"names":["asciiString","bytes","s","i","asciiBytes","out","asDataView","subview","start","length","tagNameFromInt32","n","HEADER_SIZE","ENTRY_SIZE","readAbif","macBinaryOffset","base","view","version","dirEntry","decodeEntry","numEntries","dirOffset","entries","off","tagName","tagNumber","elementType","elementSize","rawElementCount","declaredDataSize","dataHandle","computedDataSize","effectiveDataSize","inline","elementCount","payload","dataOffset","writeAbif","file","dirSize","payloadCursor","externalOffsets","e","dataSize","totalSize","outView","writeEntry","externalOffset","externalDataSize","explicitDirOffset","findEntry","name","number","findEntries","upsertEntry","defaults","existing","getDataChannel","arr","getFwo","hasProcessedTraces","getRawChannelMap","fwo","getSequence","e2","e1","getConfidences","getPositions","getSamplingRate","v","setSequence","sequence","setConfidences","q","buf","setPositions","positions","setAveragePeakSpacing","spacing","basecallerName","f1","nameBytes","len","p","f3","averagePeakSpacing","ensureRawDataChannels","src","target","TYPE_NAMES","typeName","t","previewNumbers","max","truncate","previewBytes","slice","hex","b","decodePayload","year","month","day","previewDecoded","d","hour","minute","second","parseAbif","input","fileName","decoded","baseOrder","dataChannels","basecalled","raw","metadata","pbas","pcon","ploc","channelKey","idx","c","baseCalls","pbasVersion","seq","confidences","pos","data9Len","chromatogram","hasSignals","channelMaxLength"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Tiny binary helpers used across the ABIF reader/writer.\n *\n * Everything here operates on Uint8Array + DataView so the same code runs in\n * Node (where Buffer extends Uint8Array) and the browser.\n */\n\nexport function asciiString(bytes: Uint8Array): string {\n let s = '';\n for (let i = 0; i < bytes.length; i++) s += String.fromCharCode(bytes[i]);\n return s;\n}\n\nexport function asciiBytes(s: string): Uint8Array {\n const out = new Uint8Array(s.length);\n for (let i = 0; i < s.length; i++) out[i] = s.charCodeAt(i) & 0xff;\n return out;\n}\n\n/** Returns a DataView over the given bytes, regardless of input shape. */\nexport function asDataView(bytes: Uint8Array): DataView {\n return new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n}\n\n/** Returns a Uint8Array view over a slice; never copies. */\nexport function subview(bytes: Uint8Array, start: number, length: number): Uint8Array {\n return bytes.subarray(start, start + length);\n}\n\n/** Tag name encoded as a big-endian uint32 (e.g. \"DATA\" → 0x44415441). */\nexport function tagNameToInt32(tag: string): number {\n return (\n ((tag.charCodeAt(0) & 0xff) << 24) |\n ((tag.charCodeAt(1) & 0xff) << 16) |\n ((tag.charCodeAt(2) & 0xff) << 8) |\n (tag.charCodeAt(3) & 0xff)\n );\n}\n\nexport function tagNameFromInt32(n: number): string {\n return String.fromCharCode((n >>> 24) & 0xff, (n >>> 16) & 0xff, (n >>> 8) & 0xff, n & 0xff);\n}\n","/**\n * Low-level ABIF reader/writer.\n *\n * Round-trip without loss: every directory entry (including unknown vendor\n * tags) is preserved as a raw payload (Uint8Array). The high-level layer\n * (view.ts, parser.ts) provides typed access on top of this.\n *\n * ABIF file layout:\n * [0..3] \"ABIF\" magic\n * [4..5] version (int16 BE; 101 = v1.01)\n * [6..33] TdirEntry describing the directory itself\n * [34..127] reserved (94 bytes, zero-filled)\n * [...] directory block (N * 28-byte entries) and payload blocks\n *\n * TdirEntry (28 bytes, big-endian):\n * off size field\n * 0 4 tagName (ASCII)\n * 4 4 tagNumber (int32)\n * 8 2 elementType (int16)\n * 10 2 elementSize (int16)\n * 12 4 elementCount (int32)\n * 16 4 dataSize (int32; total payload bytes; spec says count*size)\n * 20 4 dataOffset (int32) OR inline data if dataSize <= 4\n * 24 4 dataHandle (int32; usually 0)\n *\n * Inline rule (per ABIF spec): when count*size <= 4 the payload bytes are\n * stored directly in the dataOffset field (left-aligned, padded to 4 bytes).\n *\n * MacBinary preamble: some ABIF files (older Mac-origin) start with a 128-byte\n * MacBinary header before the actual ABIF magic. We detect and skip it.\n */\n\nimport { asciiBytes, asciiString, asDataView, subview, tagNameFromInt32 } from './bytes';\nimport { AbifEntry, AbifFile } from './types';\n\nexport const HEADER_SIZE = 128;\nexport const ENTRY_SIZE = 28;\n\n/**\n * Parse an ABIF file from raw bytes.\n *\n * Accepts Uint8Array (works in Node and the browser). Node's Buffer extends\n * Uint8Array, so `readAbif(buffer)` and `readAbif(new Uint8Array(arrayBuffer))`\n * both work.\n *\n * Throws if the magic header is missing. Does NOT require any specific tags\n * (PBAS, DATA, ...) to be present — raw pre-basecalled files are supported.\n */\nexport function readAbif(bytes: Uint8Array): AbifFile {\n if (bytes.byteLength < HEADER_SIZE) {\n throw new Error(`ABIF too small: ${bytes.byteLength} bytes`);\n }\n\n // MacBinary wrap support: skip 128 bytes if magic is at offset 128.\n let macBinaryOffset = 0;\n if (asciiString(subview(bytes, 0, 4)) !== 'ABIF') {\n if (bytes.byteLength >= 128 + 4 && asciiString(subview(bytes, 128, 4)) === 'ABIF') {\n macBinaryOffset = 128;\n } else {\n throw new Error('Not an ABIF file: missing \"ABIF\" magic.');\n }\n }\n const base = macBinaryOffset;\n const view = asDataView(bytes);\n\n const version = view.getInt16(base + 4, false);\n\n // Header bytes [base+6 .. base+34) are a TdirEntry describing the directory itself.\n const dirEntry = decodeEntry(bytes, view, base + 6);\n if (dirEntry.tagName !== 'tdir') {\n throw new Error(`Expected \"tdir\" header entry, got \"${dirEntry.tagName}\"`);\n }\n if (dirEntry.elementSize !== ENTRY_SIZE) {\n throw new Error(`Expected dir element size ${ENTRY_SIZE}, got ${dirEntry.elementSize}`);\n }\n\n const numEntries = dirEntry.elementCount;\n // tdir.dataSize is always > 4 (28*N), so the dataOffset field is an external offset.\n const dirOffset = view.getInt32(base + 6 + 20, false);\n if (dirOffset < 0 || dirOffset + numEntries * ENTRY_SIZE > bytes.byteLength - base) {\n throw new Error(\n `Directory out of bounds: offset=${dirOffset}, entries=${numEntries}, file=${bytes.byteLength - base}`,\n );\n }\n\n const entries: AbifEntry[] = [];\n for (let i = 0; i < numEntries; i++) {\n entries.push(decodeEntry(bytes, view, base + dirOffset + i * ENTRY_SIZE));\n }\n\n return { version, entries, macBinaryOffset };\n}\n\n/**\n * Decode a 28-byte TdirEntry at the given absolute byte offset.\n *\n * Two robustness measures applied here that BioPython also uses and that real\n * ABIF files in the wild require:\n *\n * 1. The inline rule uses `elementCount * elementSize` (the structural size),\n * not the declared `dataSize` field — they should agree, but the writer\n * sometimes desynced them.\n *\n * 2. When the declared `dataSize` is smaller than `count*size`, trust the\n * smaller value for payload reading. Some older instruments and edited\n * files (e.g. BioPython A_forward.ab1) have `dataSize` set to the actual\n * written size while `elementCount` was left at the original (larger)\n * value, so reading the full count*size range would land in adjacent data.\n */\nfunction decodeEntry(bytes: Uint8Array, view: DataView, off: number): AbifEntry {\n const tagName = asciiString(subview(bytes, off, 4));\n const tagNumber = view.getInt32(off + 4, false);\n const elementType = view.getInt16(off + 8, false);\n const elementSize = view.getInt16(off + 10, false);\n const rawElementCount = view.getInt32(off + 12, false);\n const declaredDataSize = view.getInt32(off + 16, false);\n const dataHandle = view.getInt32(off + 24, false);\n\n const computedDataSize = Math.max(0, rawElementCount * Math.max(0, elementSize));\n const effectiveDataSize = Math.min(computedDataSize, Math.max(0, declaredDataSize));\n // Inline is a structural property of the on-disk record: based on RAW count*size.\n const inline = computedDataSize <= 4;\n // For iteration we use the smaller of declared and computed, clamped to size\n // boundaries, so we don't over-read past the real payload.\n const elementCount =\n elementSize > 0 && declaredDataSize >= 0 && declaredDataSize < computedDataSize\n ? Math.floor(declaredDataSize / elementSize)\n : rawElementCount;\n\n let payload: Uint8Array;\n if (inline) {\n payload = new Uint8Array(subview(bytes, off + 20, effectiveDataSize));\n } else {\n const dataOffset = view.getInt32(off + 20, false);\n if (dataOffset < 0 || dataOffset + effectiveDataSize > bytes.byteLength) {\n throw new Error(\n `Entry ${tagName}${tagNumber}: payload out of bounds (offset=${dataOffset}, size=${effectiveDataSize})`,\n );\n }\n payload = new Uint8Array(subview(bytes, dataOffset, effectiveDataSize));\n }\n\n return { tagName, tagNumber, elementType, elementSize, elementCount, payload, dataHandle };\n}\n\n/**\n * Serialize an AbifFile back to a Uint8Array.\n *\n * Layout produced: header (128 B) + directory (N*28 B) + payload block.\n * External payloads are packed tightly in entry order. Inline payloads\n * (count*size <= 4) live entirely inside their directory entry.\n *\n * The output is not bit-identical to the input if the original had a different\n * physical layout (e.g. payloads before directory), but the *meaning*\n * round-trips: readAbif(writeAbif(f)) reproduces the same entries structurally.\n *\n * MacBinary preamble is not preserved by writeAbif.\n */\nexport function writeAbif(file: AbifFile): Uint8Array {\n const numEntries = file.entries.length;\n const dirOffset = HEADER_SIZE;\n const dirSize = numEntries * ENTRY_SIZE;\n\n // Compute external payload offsets.\n let payloadCursor = dirOffset + dirSize;\n const externalOffsets: number[] = new Array(numEntries);\n for (let i = 0; i < numEntries; i++) {\n const e = file.entries[i];\n const dataSize = e.elementCount * e.elementSize;\n if (e.payload.byteLength !== dataSize) {\n throw new Error(\n `Entry ${e.tagName}${e.tagNumber}: payload length ${e.payload.byteLength} != dataSize ${dataSize}`,\n );\n }\n if (dataSize > 4) {\n externalOffsets[i] = payloadCursor;\n payloadCursor += dataSize;\n } else {\n externalOffsets[i] = -1; // inline\n }\n }\n\n const totalSize = payloadCursor;\n const out = new Uint8Array(totalSize);\n const outView = asDataView(out);\n\n // Header: \"ABIF\" + version (int16 BE) + tdir entry + zeros.\n out.set(asciiBytes('ABIF'), 0);\n outView.setInt16(4, file.version, false);\n // The tdir entry's dataOffset is the directory offset (explicit, not from\n // the AbifEntry payload — the tdir is structural).\n writeEntry(\n {\n tagName: 'tdir',\n tagNumber: 1,\n elementType: 1023,\n elementSize: ENTRY_SIZE,\n elementCount: numEntries,\n payload: new Uint8Array(0),\n dataHandle: 0,\n },\n out,\n outView,\n 6,\n /* externalOffset */ -1,\n /* externalDataSize */ dirSize,\n /* explicitDirOffset */ dirOffset,\n );\n\n // Directory entries.\n for (let i = 0; i < numEntries; i++) {\n const e = file.entries[i];\n writeEntry(e, out, outView, dirOffset + i * ENTRY_SIZE, externalOffsets[i]);\n }\n\n // Payload block.\n for (let i = 0; i < numEntries; i++) {\n const off = externalOffsets[i];\n if (off >= 0) {\n out.set(file.entries[i].payload, off);\n }\n }\n\n return out;\n}\n\nfunction writeEntry(\n e: AbifEntry,\n out: Uint8Array,\n outView: DataView,\n off: number,\n externalOffset: number,\n externalDataSize?: number,\n explicitDirOffset?: number,\n): void {\n if (e.tagName.length !== 4) {\n throw new Error(`tagName must be 4 chars: \"${e.tagName}\"`);\n }\n out.set(asciiBytes(e.tagName), off);\n outView.setInt32(off + 4, e.tagNumber, false);\n outView.setInt16(off + 8, e.elementType, false);\n outView.setInt16(off + 10, e.elementSize, false);\n outView.setInt32(off + 12, e.elementCount, false);\n const dataSize = externalDataSize ?? e.elementCount * e.elementSize;\n outView.setInt32(off + 16, dataSize, false);\n\n if (explicitDirOffset !== undefined) {\n outView.setInt32(off + 20, explicitDirOffset, false);\n } else if (dataSize <= 4) {\n // Inline: clear 4 bytes then place payload at off+20.\n out.fill(0, off + 20, off + 24);\n out.set(e.payload.subarray(0, dataSize), off + 20);\n } else {\n if (externalOffset < 0) {\n throw new Error(`External payload requires offset for ${e.tagName}${e.tagNumber}`);\n }\n outView.setInt32(off + 20, externalOffset, false);\n }\n outView.setInt32(off + 24, e.dataHandle, false);\n}\n\n// =====================================================================\n// Lookup / mutation helpers\n// =====================================================================\n\n/** Find an entry by name+number, or undefined. */\nexport function findEntry(file: AbifFile, name: string, number: number): AbifEntry | undefined {\n return file.entries.find(e => e.tagName === name && e.tagNumber === number);\n}\n\n/** Find all entries with the given tag name. */\nexport function findEntries(file: AbifFile, name: string): AbifEntry[] {\n return file.entries.filter(e => e.tagName === name);\n}\n\n/**\n * Replace the payload of an existing entry, or append a new one.\n * elementType/elementSize/elementCount must be supplied for new entries.\n */\nexport function upsertEntry(\n file: AbifFile,\n name: string,\n number: number,\n payload: Uint8Array,\n defaults: { elementType: number; elementSize: number; elementCount: number },\n): void {\n if (payload.byteLength !== defaults.elementCount * defaults.elementSize) {\n throw new Error(\n `upsertEntry ${name}${number}: payload length ${payload.byteLength} != count*size`,\n );\n }\n const existing = findEntry(file, name, number);\n if (existing) {\n existing.elementType = defaults.elementType;\n existing.elementSize = defaults.elementSize;\n existing.elementCount = defaults.elementCount;\n existing.payload = payload;\n } else {\n file.entries.push({\n tagName: name,\n tagNumber: number,\n elementType: defaults.elementType,\n elementSize: defaults.elementSize,\n elementCount: defaults.elementCount,\n payload,\n dataHandle: 0,\n });\n }\n}\n\n/** Re-export for users who want to interpret raw tag bytes themselves. */\nexport { tagNameFromInt32 };\n","/**\n * High-level typed view over an AbifFile.\n *\n * Reading helpers that interpret the raw payloads of well-known tags. For\n * mutation helpers (setSequence, setConfidences, ...) see ./setters.\n */\n\nimport { asciiString, asDataView } from './bytes';\nimport { findEntry } from './raw';\nimport { AbifFile } from './types';\n\n/** Get DATA<n> as a signed-int16 array, or undefined. */\nexport function getDataChannel(file: AbifFile, n: number): Int16Array | undefined {\n const e = findEntry(file, 'DATA', n);\n if (!e) return undefined;\n if (e.elementSize !== 2) {\n throw new Error(`DATA${n}: expected elementSize=2, got ${e.elementSize}`);\n }\n const arr = new Int16Array(e.elementCount);\n const view = asDataView(e.payload);\n for (let i = 0; i < e.elementCount; i++) {\n arr[i] = view.getInt16(i * 2, false);\n }\n return arr;\n}\n\n/**\n * Dye order, 4 ASCII chars (e.g. \"GATC\"). Defaults to \"GATC\" if FWO_ absent.\n *\n * GATC is the dye order produced by modern ABI 3730/3500 instruments and the\n * dominant default in the wild. Older \"ACGT\" defaults caused channel\n * mis-mapping on files where FWO_ is missing or malformed.\n */\nexport function getFwo(file: AbifFile): string {\n const e = findEntry(file, 'FWO_', 1);\n if (!e) return 'GATC';\n return asciiString(e.payload);\n}\n\n/**\n * True when the file carries BOTH DATA1..4 and DATA9..12. Newer ABI-style\n * instruments produce both: DATA1..4 is post-processed (mobility-corrected,\n * baseline-subtracted, color-separated) and DATA9..12 is raw fluorescence.\n * Older instruments produce only DATA1..4 (which IS the raw signal).\n *\n * Callers that re-process traces (basecallers) should detect this and bypass\n * their own baseline-subtraction / color-matrix steps when DATA1..4 is\n * already cleaned.\n */\nexport function hasProcessedTraces(file: AbifFile): boolean {\n return !!(\n findEntry(file, 'DATA', 9) &&\n findEntry(file, 'DATA', 10) &&\n findEntry(file, 'DATA', 11) &&\n findEntry(file, 'DATA', 12)\n );\n}\n\n/**\n * Map from base letter (\"A\"|\"C\"|\"G\"|\"T\") to the DATA tag number that holds\n * its RAW fluorescence channel.\n *\n * ABIF stores up to 12 DATA tags. KB-basecaller-aware instruments (3130, 3500,\n * ...) use DATA1..4 for processed traces and DATA9..12 for raw. Older / simpler\n * instruments produce only DATA1..8 where DATA1..4 ARE the raw traces.\n *\n * This helper always returns the DATA1..4 mapping (the convention used by\n * basecallers operating on raw signal). Use {@link hasProcessedTraces} to\n * detect whether DATA1..4 has been pre-processed and bypass baseline/color\n * steps accordingly.\n *\n * The dye-to-channel order within each block is given by FWO_. If\n * FWO_=\"GATC\" then G→1, A→2, T→3, C→4.\n */\nexport function getRawChannelMap(file: AbifFile): Record<'A' | 'C' | 'G' | 'T', number> {\n const fwo = getFwo(file);\n if (!/^[ACGT]{4}$/.test(fwo)) {\n throw new Error(`FWO_ malformed: \"${fwo}\"`);\n }\n return {\n [fwo[0]]: 1,\n [fwo[1]]: 2,\n [fwo[2]]: 3,\n [fwo[3]]: 4,\n } as Record<'A' | 'C' | 'G' | 'T', number>;\n}\n\n/** Get PBAS sequence (prefer PBAS2 over PBAS1). undefined if neither present. */\nexport function getSequence(file: AbifFile): string | undefined {\n const e2 = findEntry(file, 'PBAS', 2);\n if (e2) return asciiString(e2.payload);\n const e1 = findEntry(file, 'PBAS', 1);\n if (e1) return asciiString(e1.payload);\n return undefined;\n}\n\n/**\n * Get per-base Phred-like quality scores (0..255 byte values, typically 0..60\n * for Sanger). Prefers PCON2 over PCON1.\n *\n * PCON is declared in the ABIF spec as elementType=2 (char) but the byte\n * values ARE the Q-scores — we read raw bytes regardless of declared type.\n */\nexport function getConfidences(file: AbifFile): number[] | undefined {\n const e = findEntry(file, 'PCON', 2) ?? findEntry(file, 'PCON', 1);\n if (!e) return undefined;\n const out: number[] = new Array(e.elementCount);\n for (let i = 0; i < e.elementCount; i++) out[i] = e.payload[i];\n return out;\n}\n\n/**\n * Get peak scan positions (one per base). Prefers PLOC2 over PLOC1.\n *\n * Read as UNSIGNED int16: PLOC indexes into the sample trace and is always\n * non-negative, but values > 32767 (long traces) would wrap to negative\n * if interpreted as signed.\n */\nexport function getPositions(file: AbifFile): number[] | undefined {\n const e = findEntry(file, 'PLOC', 2) ?? findEntry(file, 'PLOC', 1);\n if (!e) return undefined;\n if (e.elementSize !== 2) {\n throw new Error(`PLOC: expected elementSize=2, got ${e.elementSize}`);\n }\n const view = asDataView(e.payload);\n const out: number[] = new Array(e.elementCount);\n for (let i = 0; i < e.elementCount; i++) out[i] = view.getUint16(i * 2, false);\n return out;\n}\n\n/**\n * Get average peak spacing (samples per base), from SPAC/1.\n *\n * ABIF spec defines SPAC as float32 (elementType=7); some legacy files\n * mislabel it as long (type=5). Both are 4 bytes and on disk the payload\n * is always a 32-bit float, so we read as float regardless of declared type.\n *\n * Returns undefined if SPAC is absent or non-positive.\n */\nexport function getSamplingRate(file: AbifFile): number | undefined {\n const e = findEntry(file, 'SPAC', 1);\n if (!e || e.elementSize !== 4 || e.payload.byteLength < 4) return undefined;\n const v = asDataView(e.payload).getFloat32(0, false);\n return Number.isFinite(v) && v > 0 ? v : undefined;\n}\n","/**\n * Mutation helpers for AbifFile: write PBAS/PCON/PLOC/SPAC and ensure DATA9..12\n * are present. Used by basecallers to author ABIF output.\n */\n\nimport { asciiBytes, asDataView } from './bytes';\nimport { findEntry, upsertEntry } from './raw';\nimport { hasProcessedTraces } from './view';\nimport { AbifFile } from './types';\n\n/** Set PBAS2 (replaces if present). */\nexport function setSequence(file: AbifFile, sequence: string): void {\n upsertEntry(file, 'PBAS', 2, asciiBytes(sequence), {\n elementType: 2, // char\n elementSize: 1,\n elementCount: sequence.length,\n });\n}\n\n/** Set PCON2 (replaces if present). Values clamped to [0, 255]. */\nexport function setConfidences(file: AbifFile, q: ArrayLike<number>): void {\n const buf = new Uint8Array(q.length);\n for (let i = 0; i < q.length; i++) {\n buf[i] = Math.max(0, Math.min(255, Math.round(q[i])));\n }\n upsertEntry(file, 'PCON', 2, buf, {\n elementType: 2,\n elementSize: 1,\n elementCount: q.length,\n });\n}\n\n/**\n * Set PLOC2 (replaces if present).\n *\n * Written as UNSIGNED int16 so positions up to 65535 are preserved on disk\n * (signed int16 would wrap on traces with > 32k scans).\n */\nexport function setPositions(file: AbifFile, positions: ArrayLike<number>): void {\n const buf = new Uint8Array(positions.length * 2);\n const view = asDataView(buf);\n for (let i = 0; i < positions.length; i++) {\n view.setUint16(i * 2, Math.max(0, Math.min(0xffff, positions[i])), false);\n }\n upsertEntry(file, 'PLOC', 2, buf, {\n elementType: 4,\n elementSize: 2,\n elementCount: positions.length,\n });\n}\n\n/**\n * Set SPAC/1, SPAC/2, SPAC/3 — the standard ABIF \"average peak spacing\" trio\n * that KB-basecaller writes and downstream tools (BioPython, Sequencher,\n * KB-aware viewers) expect:\n *\n * - SPAC/1 (float32) — average peak spacing used in last analysis.\n * - SPAC/2 (pString) — basecaller name / identifier.\n * - SPAC/3 (float32) — average peak spacing computed by the basecaller.\n *\n * Both float fields are written with the same value.\n */\nexport function setAveragePeakSpacing(file: AbifFile, spacing: number, basecallerName: string): void {\n const f1 = new Uint8Array(4);\n asDataView(f1).setFloat32(0, spacing, false);\n upsertEntry(file, 'SPAC', 1, f1, { elementType: 7, elementSize: 4, elementCount: 1 });\n\n const nameBytes = asciiBytes(basecallerName);\n const len = Math.min(255, nameBytes.length);\n const p = new Uint8Array(1 + len);\n p[0] = len;\n p.set(nameBytes.subarray(0, len), 1);\n upsertEntry(file, 'SPAC', 2, p, { elementType: 18, elementSize: 1, elementCount: 1 + len });\n\n const f3 = new Uint8Array(4);\n asDataView(f3).setFloat32(0, spacing, false);\n upsertEntry(file, 'SPAC', 3, f3, { elementType: 7, elementSize: 4, elementCount: 1 });\n}\n\n/**\n * Mean consecutive peak-to-peak distance in scans, from a positions array.\n * Returns 0 when fewer than 2 positions are present.\n */\nexport function averagePeakSpacing(positions: ArrayLike<number>): number {\n if (positions.length < 2) return 0;\n return (positions[positions.length - 1] - positions[0]) / (positions.length - 1);\n}\n\n/**\n * Ensure DATA9..12 are present in the file. Many downstream consumers\n * (BioPython-style readers, viewers) read the chromatogram signal from\n * DATA9..12 by convention — these tags are the raw fluorescence on newer\n * instruments. Older files that only carry DATA1..8 break those consumers\n * with a \"no signal\" error after re-basecalling.\n *\n * We populate DATA9..12 by copying DATA1..4 (which on DATA1..8-only files IS\n * the raw signal). The DATA1..4 tags are left untouched so any tool that\n * reads them keeps working.\n *\n * No-op when DATA9..12 already exist.\n */\nexport function ensureRawDataChannels(file: AbifFile): void {\n if (hasProcessedTraces(file)) return;\n for (let i = 1; i <= 4; i++) {\n const src = findEntry(file, 'DATA', i);\n if (!src) continue;\n const target = 8 + i;\n if (findEntry(file, 'DATA', target)) continue;\n file.entries.push({\n tagName: 'DATA',\n tagNumber: target,\n elementType: src.elementType,\n elementSize: src.elementSize,\n elementCount: src.elementCount,\n payload: new Uint8Array(src.payload),\n dataHandle: 0,\n });\n }\n}\n","/**\n * High-level \"parse everything\" wrapper around the raw + view layers.\n *\n * Returns a single ParsedAbif object with metadata, the FWO_-aware\n * basecalled / raw channel split, basecalls, and decoded directory entries\n * for diagnostics. Mirrors what typical viewers (chromatogram UIs, sample\n * inspectors) need from a single file.\n *\n * For round-trip authoring (basecallers), prefer {@link readAbif} +\n * setters from ./setters which operate directly on the raw AbifFile.\n */\n\nimport { asciiString, asDataView, subview } from './bytes';\nimport { readAbif } from './raw';\nimport { getFwo } from './view';\nimport {\n AbifBaseCalls,\n AbifChromatogramBundle,\n AbifDecodedValue,\n AbifDirEntry,\n AbifEntry,\n AbifMetadata,\n ChannelSignals,\n ParsedAbif,\n} from './types';\n\nconst TYPE_NAMES: Record<number, string> = {\n 1: 'byte',\n 2: 'char',\n 3: 'word',\n 4: 'short',\n 5: 'long',\n 7: 'float',\n 8: 'double',\n 10: 'date',\n 11: 'time',\n 12: 'thumb',\n 13: 'bool',\n 18: 'pString',\n 19: 'cString',\n 1023: 'tdir',\n};\n\nfunction typeName(t: number): string {\n return TYPE_NAMES[t] ?? (t >= 1024 ? `user${t}` : `type${t}`);\n}\n\nfunction previewNumbers(arr: number[], max = 10): string {\n if (arr.length <= max) return `[${arr.join(', ')}]`;\n return `[${arr.slice(0, max).join(', ')}, … +${arr.length - max}] (n=${arr.length})`;\n}\n\nfunction truncate(s: string, n = 80): string {\n return s.length > n ? s.slice(0, n) + '…' : s;\n}\n\nfunction previewBytes(bytes: Uint8Array): string {\n const slice = bytes.subarray(0, 16);\n const hex = Array.from(slice, b => b.toString(16).padStart(2, '0')).join(' ');\n return `${bytes.byteLength}B [${hex}${bytes.byteLength > 16 ? ' …' : ''}]`;\n}\n\n/**\n * Decode a payload best-effort by ABIF element type.\n *\n * Strings have trailing NULs stripped (cString/pString convention).\n * pString (type 18) is decoded as `length-prefix + chars`.\n */\nfunction decodePayload(elementType: number, elementCount: number, payload: Uint8Array): AbifDecodedValue {\n const view = asDataView(payload);\n switch (elementType) {\n case 1: {\n const arr = Array.from(payload.subarray(0, elementCount));\n return { kind: 'numbers', value: arr };\n }\n case 2:\n case 19: {\n const s = asciiString(payload.subarray(0, elementCount)).replace(/\\0+$/g, '');\n return { kind: 'string', value: s };\n }\n case 3: {\n const arr: number[] = [];\n for (let i = 0; i < elementCount; i++) arr.push(view.getUint16(i * 2, false));\n return arr.length === 1 ? { kind: 'number', value: arr[0] } : { kind: 'numbers', value: arr };\n }\n case 4: {\n const arr: number[] = [];\n for (let i = 0; i < elementCount; i++) arr.push(view.getInt16(i * 2, false));\n return arr.length === 1 ? { kind: 'number', value: arr[0] } : { kind: 'numbers', value: arr };\n }\n case 5: {\n const arr: number[] = [];\n for (let i = 0; i < elementCount; i++) arr.push(view.getInt32(i * 4, false));\n return arr.length === 1 ? { kind: 'number', value: arr[0] } : { kind: 'numbers', value: arr };\n }\n case 7: {\n const arr: number[] = [];\n for (let i = 0; i < elementCount; i++) arr.push(view.getFloat32(i * 4, false));\n return arr.length === 1 ? { kind: 'number', value: arr[0] } : { kind: 'numbers', value: arr };\n }\n case 8: {\n const arr: number[] = [];\n for (let i = 0; i < elementCount; i++) arr.push(view.getFloat64(i * 8, false));\n return arr.length === 1 ? { kind: 'number', value: arr[0] } : { kind: 'numbers', value: arr };\n }\n case 10: {\n const year = view.getInt16(0, false);\n const month = view.getUint8(2);\n const day = view.getUint8(3);\n return { kind: 'date', value: { year, month, day } };\n }\n case 11: {\n return {\n kind: 'time',\n value: {\n hour: view.getUint8(0),\n minute: view.getUint8(1),\n second: view.getUint8(2),\n hsec: view.getUint8(3),\n },\n };\n }\n case 13: {\n const arr: boolean[] = [];\n for (let i = 0; i < elementCount; i++) arr.push(view.getUint8(i) !== 0);\n return { kind: 'bools', value: arr };\n }\n case 18: {\n const len = view.getUint8(0);\n const s = asciiString(subview(payload, 1, Math.min(len, Math.max(0, elementCount - 1))));\n return { kind: 'string', value: s };\n }\n default:\n return { kind: 'unknown', value: payload };\n }\n}\n\nfunction previewDecoded(d: AbifDecodedValue, elementType: number): string {\n switch (d.kind) {\n case 'number':\n return String(d.value);\n case 'numbers':\n return previewNumbers(d.value);\n case 'string':\n return truncate(JSON.stringify(d.value));\n case 'bools':\n return d.value.length === 1 ? String(d.value[0]) : `[${d.value.join(', ')}]`;\n case 'date': {\n const { year, month, day } = d.value;\n return `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`;\n }\n case 'time': {\n const { hour, minute, second } = d.value;\n return `${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}:${String(second).padStart(2, '0')}`;\n }\n case 'bytes':\n return `${typeName(elementType)} ${previewBytes(d.value)}`;\n case 'unknown':\n return `${typeName(elementType)} ${previewBytes(d.value)}`;\n }\n}\n\n/**\n * Parse an ABIF file into a high-level view: metadata, channels, basecalls,\n * and decoded directory entries.\n *\n * Accepts ArrayBuffer or Uint8Array (Buffer in Node works too — it extends\n * Uint8Array). The `fileName` argument is informational only; it's preserved\n * in the result.\n */\nexport function parseAbif(input: ArrayBuffer | Uint8Array, fileName = ''): ParsedAbif {\n const bytes = input instanceof Uint8Array ? input : new Uint8Array(input);\n const file = readAbif(bytes);\n\n const entries: AbifDirEntry[] = file.entries.map(e => {\n const decoded = decodePayload(e.elementType, e.elementCount, e.payload);\n return {\n tag: e.tagName,\n tagNumber: e.tagNumber,\n elementType: e.elementType,\n elementTypeName: typeName(e.elementType),\n elementSize: e.elementSize,\n elementCount: e.elementCount,\n dataSize: e.elementCount * e.elementSize,\n // Effective offset within the file is not tracked here (we already\n // resolved it during read); inline detection uses the structural rule.\n dataOffset: 0,\n inline: e.elementCount * e.elementSize <= 4,\n decoded,\n preview: previewDecoded(decoded, e.elementType),\n };\n });\n\n // FWO_ → base order.\n let baseOrder = getFwo(file);\n if (!/^[ACGT]{4}$/.test(baseOrder)) baseOrder = 'GATC';\n\n const dataChannels: Record<number, number[]> = {};\n const basecalled: ChannelSignals = { A: [], C: [], G: [], T: [] };\n const raw: ChannelSignals = { A: [], C: [], G: [], T: [] };\n const metadata: AbifMetadata = { comments: [] };\n const pbas: Record<number, string> = {};\n const pcon: Record<number, number[]> = {};\n const ploc: Record<number, number[]> = {};\n\n const channelKey = (i: number): keyof ChannelSignals => baseOrder[i] as keyof ChannelSignals;\n\n for (let idx = 0; idx < file.entries.length; idx++) {\n const e = file.entries[idx];\n const decoded = entries[idx].decoded;\n\n if (e.tagName === 'DATA' && decoded.kind === 'numbers') {\n dataChannels[e.tagNumber] = decoded.value;\n if (e.tagNumber >= 1 && e.tagNumber <= 4) raw[channelKey(e.tagNumber - 1)] = decoded.value;\n else if (e.tagNumber >= 9 && e.tagNumber <= 12) basecalled[channelKey(e.tagNumber - 9)] = decoded.value;\n } else if (e.tagName === 'PBAS' && decoded.kind === 'string') {\n pbas[e.tagNumber] = decoded.value;\n } else if (e.tagName === 'PCON') {\n // PCON Q-scores are stored as elementType=2 (char) — char codes ARE the values.\n if (decoded.kind === 'numbers') pcon[e.tagNumber] = decoded.value;\n else if (decoded.kind === 'string') {\n pcon[e.tagNumber] = Array.from(decoded.value, c => c.charCodeAt(0));\n }\n } else if (e.tagName === 'PLOC' && decoded.kind === 'numbers') {\n // PLOC sample indices are always non-negative — reinterpret int16 as uint16.\n ploc[e.tagNumber] = decoded.value.map(v => (v < 0 ? v + 0x10000 : v));\n } else if (e.tagName === 'SPAC') {\n // ABIF spec defines SPAC as float (elementType=7). Some legacy files mislabel\n // it as long (type=5); both are 4 bytes and the payload is always a float.\n if (e.elementSize === 4 && e.payload.byteLength >= 4) {\n const v = asDataView(e.payload).getFloat32(0, false);\n if (Number.isFinite(v) && v > 0) metadata.samplingRate = v;\n } else if (decoded.kind === 'number') {\n metadata.samplingRate = decoded.value;\n }\n } else if (e.tagName === 'SMPL' && decoded.kind === 'string') {\n metadata.sampleName = decoded.value;\n } else if (e.tagName === 'LANE' && decoded.kind === 'number') {\n metadata.laneNumber = decoded.value;\n } else if (e.tagName === 'TUBE' && decoded.kind === 'string') {\n metadata.tube = decoded.value;\n } else if (e.tagName === 'MCHN' && decoded.kind === 'string') {\n metadata.machineName = decoded.value;\n } else if (e.tagName === 'MODL' && decoded.kind === 'string') {\n metadata.machineModel = decoded.value;\n } else if (e.tagName === 'RUND' && decoded.kind === 'date') {\n const d = decoded.value;\n metadata.runDate = `${d.year}-${String(d.month).padStart(2, '0')}-${String(d.day).padStart(2, '0')}`;\n } else if (e.tagName === 'RUNT' && decoded.kind === 'time') {\n const t = decoded.value;\n metadata.runTime = `${String(t.hour).padStart(2, '0')}:${String(t.minute).padStart(2, '0')}:${String(t.second).padStart(2, '0')}`;\n } else if (e.tagName === 'CMNT' && decoded.kind === 'string') {\n metadata.comments.push(decoded.value);\n }\n }\n\n // Basecalls: prefer PBAS2 (BioPython convention).\n let baseCalls: AbifBaseCalls | undefined;\n const pbasVersion = pbas[2] ? 2 : pbas[1] ? 1 : Object.keys(pbas).map(Number)[0];\n if (pbasVersion !== undefined && pbas[pbasVersion]) {\n // Don't .trim(): keep length aligned with PCON/PLOC (trailing nulls already stripped).\n const seq = pbas[pbasVersion].toUpperCase();\n // Fall back to whichever PCON has a length matching the chosen PBAS — some\n // files ship PCON only under one tagNumber even when PBAS exists under both.\n let confidences = pcon[pbasVersion] ?? [];\n if (confidences.length === 0) {\n for (const v of Object.keys(pcon).map(Number)) {\n if (pcon[v].length === seq.length) {\n confidences = pcon[v];\n break;\n }\n }\n }\n let positions = ploc[pbasVersion] ?? [];\n if (positions.length === 0) {\n for (const v of Object.keys(ploc).map(Number)) {\n if (ploc[v].length === seq.length) {\n positions = ploc[v];\n break;\n }\n }\n }\n baseCalls = { sequence: seq, confidences, positions, pbasVersion };\n }\n\n // SPAC fallback: derive from PLOC positions or DATA9 length when missing.\n if (!Number.isFinite(metadata.samplingRate) || (metadata.samplingRate ?? 0) <= 0) {\n const pos = baseCalls?.positions;\n const data9Len = Math.max(\n basecalled.A.length,\n basecalled.C.length,\n basecalled.G.length,\n basecalled.T.length,\n );\n if (pos && pos.length > 1) {\n metadata.samplingRate = (pos[pos.length - 1] - pos[0]) / (pos.length - 1);\n } else if (baseCalls && baseCalls.sequence.length > 0 && data9Len > 0) {\n metadata.samplingRate = data9Len / baseCalls.sequence.length;\n }\n }\n\n const chromatogram: AbifChromatogramBundle = { baseOrder, dataChannels, basecalled, raw };\n\n return {\n fileName,\n fileSize: bytes.byteLength,\n abifVersion: file.version,\n macBinaryOffset: file.macBinaryOffset,\n dirEntryCount: file.entries.length,\n metadata,\n chromatogram,\n baseCalls,\n entries,\n };\n}\n\n/** True when any channel has at least one signal value. */\nexport function hasSignals(s: ChannelSignals): boolean {\n return s.A.length > 0 || s.C.length > 0 || s.G.length > 0 || s.T.length > 0;\n}\n\n/** Length of the longest channel in a ChannelSignals bundle. */\nexport function channelMaxLength(s: ChannelSignals): number {\n return Math.max(s.A.length, s.C.length, s.G.length, s.T.length);\n}\n\n// Quiet unused-import for the AbifEntry type if it isn't reachable elsewhere.\nexport type { AbifEntry };\n"]}
@@ -0,0 +1,2 @@
1
+ function y(e){let t="";for(let n=0;n<e.length;n++)t+=String.fromCharCode(e[n]);return t}function x(e){let t=new Uint8Array(e.length);for(let n=0;n<e.length;n++)t[n]=e.charCodeAt(n)&255;return t}function p(e){return new DataView(e.buffer,e.byteOffset,e.byteLength)}function C(e,t,n){return e.subarray(t,t+n)}function P(e){return String.fromCharCode(e>>>24&255,e>>>16&255,e>>>8&255,e&255)}var F=128,w=28;function U(e){if(e.byteLength<F)throw new Error(`ABIF too small: ${e.byteLength} bytes`);let t=0;if(y(C(e,0,4))!=="ABIF")if(e.byteLength>=132&&y(C(e,128,4))==="ABIF")t=128;else throw new Error('Not an ABIF file: missing "ABIF" magic.');let n=t,r=p(e),a=r.getInt16(n+4,false),i=k(e,r,n+6);if(i.tagName!=="tdir")throw new Error(`Expected "tdir" header entry, got "${i.tagName}"`);if(i.elementSize!==w)throw new Error(`Expected dir element size ${w}, got ${i.elementSize}`);let c=i.elementCount,m=r.getInt32(n+6+20,false);if(m<0||m+c*w>e.byteLength-n)throw new Error(`Directory out of bounds: offset=${m}, entries=${c}, file=${e.byteLength-n}`);let h=[];for(let o=0;o<c;o++)h.push(k(e,r,n+m+o*w));return {version:a,entries:h,macBinaryOffset:t}}function k(e,t,n){let r=y(C(e,n,4)),a=t.getInt32(n+4,false),i=t.getInt16(n+8,false),c=t.getInt16(n+10,false),m=t.getInt32(n+12,false),h=t.getInt32(n+16,false),o=t.getInt32(n+24,false),g=Math.max(0,m*Math.max(0,c)),b=Math.min(g,Math.max(0,h)),N=g<=4,$=c>0&&h>=0&&h<g?Math.floor(h/c):m,S;if(N)S=new Uint8Array(C(e,n+20,b));else {let A=t.getInt32(n+20,false);if(A<0||A+b>e.byteLength)throw new Error(`Entry ${r}${a}: payload out of bounds (offset=${A}, size=${b})`);S=new Uint8Array(C(e,A,b));}return {tagName:r,tagNumber:a,elementType:i,elementSize:c,elementCount:$,payload:S,dataHandle:o}}function H(e){let t=e.entries.length,n=F,r=t*w,a=n+r,i=new Array(t);for(let o=0;o<t;o++){let g=e.entries[o],b=g.elementCount*g.elementSize;if(g.payload.byteLength!==b)throw new Error(`Entry ${g.tagName}${g.tagNumber}: payload length ${g.payload.byteLength} != dataSize ${b}`);b>4?(i[o]=a,a+=b):i[o]=-1;}let c=a,m=new Uint8Array(c),h=p(m);m.set(x("ABIF"),0),h.setInt16(4,e.version,false),z({tagName:"tdir",tagNumber:1,elementType:1023,elementSize:w,elementCount:t,payload:new Uint8Array(0),dataHandle:0},m,h,6,-1,r,n);for(let o=0;o<t;o++){let g=e.entries[o];z(g,m,h,n+o*w,i[o]);}for(let o=0;o<t;o++){let g=i[o];g>=0&&m.set(e.entries[o].payload,g);}return m}function z(e,t,n,r,a,i,c){if(e.tagName.length!==4)throw new Error(`tagName must be 4 chars: "${e.tagName}"`);t.set(x(e.tagName),r),n.setInt32(r+4,e.tagNumber,false),n.setInt16(r+8,e.elementType,false),n.setInt16(r+10,e.elementSize,false),n.setInt32(r+12,e.elementCount,false);let m=i??e.elementCount*e.elementSize;if(n.setInt32(r+16,m,false),c!==void 0)n.setInt32(r+20,c,false);else if(m<=4)t.fill(0,r+20,r+24),t.set(e.payload.subarray(0,m),r+20);else {if(a<0)throw new Error(`External payload requires offset for ${e.tagName}${e.tagNumber}`);n.setInt32(r+20,a,false);}n.setInt32(r+24,e.dataHandle,false);}function d(e,t,n){return e.entries.find(r=>r.tagName===t&&r.tagNumber===n)}function _(e,t){return e.entries.filter(n=>n.tagName===t)}function v(e,t,n,r,a){if(r.byteLength!==a.elementCount*a.elementSize)throw new Error(`upsertEntry ${t}${n}: payload length ${r.byteLength} != count*size`);let i=d(e,t,n);i?(i.elementType=a.elementType,i.elementSize=a.elementSize,i.elementCount=a.elementCount,i.payload=r):e.entries.push({tagName:t,tagNumber:n,elementType:a.elementType,elementSize:a.elementSize,elementCount:a.elementCount,payload:r,dataHandle:0});}function Z(e,t){let n=d(e,"DATA",t);if(!n)return;if(n.elementSize!==2)throw new Error(`DATA${t}: expected elementSize=2, got ${n.elementSize}`);let r=new Int16Array(n.elementCount),a=p(n.payload);for(let i=0;i<n.elementCount;i++)r[i]=a.getInt16(i*2,false);return r}function E(e){let t=d(e,"FWO_",1);return t?y(t.payload):"GATC"}function I(e){return !!(d(e,"DATA",9)&&d(e,"DATA",10)&&d(e,"DATA",11)&&d(e,"DATA",12))}function J(e){let t=E(e);if(!/^[ACGT]{4}$/.test(t))throw new Error(`FWO_ malformed: "${t}"`);return {[t[0]]:1,[t[1]]:2,[t[2]]:3,[t[3]]:4}}function K(e){let t=d(e,"PBAS",2);if(t)return y(t.payload);let n=d(e,"PBAS",1);if(n)return y(n.payload)}function Q(e){let t=d(e,"PCON",2)??d(e,"PCON",1);if(!t)return;let n=new Array(t.elementCount);for(let r=0;r<t.elementCount;r++)n[r]=t.payload[r];return n}function X(e){let t=d(e,"PLOC",2)??d(e,"PLOC",1);if(!t)return;if(t.elementSize!==2)throw new Error(`PLOC: expected elementSize=2, got ${t.elementSize}`);let n=p(t.payload),r=new Array(t.elementCount);for(let a=0;a<t.elementCount;a++)r[a]=n.getUint16(a*2,false);return r}function ee(e){let t=d(e,"SPAC",1);if(!t||t.elementSize!==4||t.payload.byteLength<4)return;let n=p(t.payload).getFloat32(0,false);return Number.isFinite(n)&&n>0?n:void 0}function ie(e,t){v(e,"PBAS",2,x(t),{elementType:2,elementSize:1,elementCount:t.length});}function oe(e,t){let n=new Uint8Array(t.length);for(let r=0;r<t.length;r++)n[r]=Math.max(0,Math.min(255,Math.round(t[r])));v(e,"PCON",2,n,{elementType:2,elementSize:1,elementCount:t.length});}function se(e,t){let n=new Uint8Array(t.length*2),r=p(n);for(let a=0;a<t.length;a++)r.setUint16(a*2,Math.max(0,Math.min(65535,t[a])),false);v(e,"PLOC",2,n,{elementType:4,elementSize:2,elementCount:t.length});}function le(e,t,n){let r=new Uint8Array(4);p(r).setFloat32(0,t,false),v(e,"SPAC",1,r,{elementType:7,elementSize:4,elementCount:1});let a=x(n),i=Math.min(255,a.length),c=new Uint8Array(1+i);c[0]=i,c.set(a.subarray(0,i),1),v(e,"SPAC",2,c,{elementType:18,elementSize:1,elementCount:1+i});let m=new Uint8Array(4);p(m).setFloat32(0,t,false),v(e,"SPAC",3,m,{elementType:7,elementSize:4,elementCount:1});}function ue(e){return e.length<2?0:(e[e.length-1]-e[0])/(e.length-1)}function me(e){if(!I(e))for(let t=1;t<=4;t++){let n=d(e,"DATA",t);if(!n)continue;let r=8+t;d(e,"DATA",r)||e.entries.push({tagName:"DATA",tagNumber:r,elementType:n.elementType,elementSize:n.elementSize,elementCount:n.elementCount,payload:new Uint8Array(n.payload),dataHandle:0});}}var B={1:"byte",2:"char",3:"word",4:"short",5:"long",7:"float",8:"double",10:"date",11:"time",12:"thumb",13:"bool",18:"pString",19:"cString",1023:"tdir"};function T(e){return B[e]??(e>=1024?`user${e}`:`type${e}`)}function M(e,t=10){return e.length<=t?`[${e.join(", ")}]`:`[${e.slice(0,t).join(", ")}, \u2026 +${e.length-t}] (n=${e.length})`}function O(e,t=80){return e.length>t?e.slice(0,t)+"\u2026":e}function D(e){let t=e.subarray(0,16),n=Array.from(t,r=>r.toString(16).padStart(2,"0")).join(" ");return `${e.byteLength}B [${n}${e.byteLength>16?" \u2026":""}]`}function R(e,t,n){let r=p(n);switch(e){case 1:return {kind:"numbers",value:Array.from(n.subarray(0,t))};case 2:case 19:return {kind:"string",value:y(n.subarray(0,t)).replace(/\0+$/g,"")};case 3:{let a=[];for(let i=0;i<t;i++)a.push(r.getUint16(i*2,false));return a.length===1?{kind:"number",value:a[0]}:{kind:"numbers",value:a}}case 4:{let a=[];for(let i=0;i<t;i++)a.push(r.getInt16(i*2,false));return a.length===1?{kind:"number",value:a[0]}:{kind:"numbers",value:a}}case 5:{let a=[];for(let i=0;i<t;i++)a.push(r.getInt32(i*4,false));return a.length===1?{kind:"number",value:a[0]}:{kind:"numbers",value:a}}case 7:{let a=[];for(let i=0;i<t;i++)a.push(r.getFloat32(i*4,false));return a.length===1?{kind:"number",value:a[0]}:{kind:"numbers",value:a}}case 8:{let a=[];for(let i=0;i<t;i++)a.push(r.getFloat64(i*8,false));return a.length===1?{kind:"number",value:a[0]}:{kind:"numbers",value:a}}case 10:{let a=r.getInt16(0,false),i=r.getUint8(2),c=r.getUint8(3);return {kind:"date",value:{year:a,month:i,day:c}}}case 11:return {kind:"time",value:{hour:r.getUint8(0),minute:r.getUint8(1),second:r.getUint8(2),hsec:r.getUint8(3)}};case 13:{let a=[];for(let i=0;i<t;i++)a.push(r.getUint8(i)!==0);return {kind:"bools",value:a}}case 18:{let a=r.getUint8(0);return {kind:"string",value:y(C(n,1,Math.min(a,Math.max(0,t-1))))}}default:return {kind:"unknown",value:n}}}function G(e,t){switch(e.kind){case "number":return String(e.value);case "numbers":return M(e.value);case "string":return O(JSON.stringify(e.value));case "bools":return e.value.length===1?String(e.value[0]):`[${e.value.join(", ")}]`;case "date":{let{year:n,month:r,day:a}=e.value;return `${n}-${String(r).padStart(2,"0")}-${String(a).padStart(2,"0")}`}case "time":{let{hour:n,minute:r,second:a}=e.value;return `${String(n).padStart(2,"0")}:${String(r).padStart(2,"0")}:${String(a).padStart(2,"0")}`}case "bytes":return `${T(t)} ${D(e.value)}`;case "unknown":return `${T(t)} ${D(e.value)}`}}function be(e,t=""){let n=e instanceof Uint8Array?e:new Uint8Array(e),r=U(n),a=r.entries.map(u=>{let s=R(u.elementType,u.elementCount,u.payload);return {tag:u.tagName,tagNumber:u.tagNumber,elementType:u.elementType,elementTypeName:T(u.elementType),elementSize:u.elementSize,elementCount:u.elementCount,dataSize:u.elementCount*u.elementSize,dataOffset:0,inline:u.elementCount*u.elementSize<=4,decoded:s,preview:G(s,u.elementType)}}),i=E(r);/^[ACGT]{4}$/.test(i)||(i="GATC");let c={},m={A:[],C:[],G:[],T:[]},h={A:[],C:[],G:[],T:[]},o={comments:[]},g={},b={},N={},$=u=>i[u];for(let u=0;u<r.entries.length;u++){let s=r.entries[u],l=a[u].decoded;if(s.tagName==="DATA"&&l.kind==="numbers")c[s.tagNumber]=l.value,s.tagNumber>=1&&s.tagNumber<=4?h[$(s.tagNumber-1)]=l.value:s.tagNumber>=9&&s.tagNumber<=12&&(m[$(s.tagNumber-9)]=l.value);else if(s.tagName==="PBAS"&&l.kind==="string")g[s.tagNumber]=l.value;else if(s.tagName==="PCON")l.kind==="numbers"?b[s.tagNumber]=l.value:l.kind==="string"&&(b[s.tagNumber]=Array.from(l.value,f=>f.charCodeAt(0)));else if(s.tagName==="PLOC"&&l.kind==="numbers")N[s.tagNumber]=l.value.map(f=>f<0?f+65536:f);else if(s.tagName==="SPAC")if(s.elementSize===4&&s.payload.byteLength>=4){let f=p(s.payload).getFloat32(0,false);Number.isFinite(f)&&f>0&&(o.samplingRate=f);}else l.kind==="number"&&(o.samplingRate=l.value);else if(s.tagName==="SMPL"&&l.kind==="string")o.sampleName=l.value;else if(s.tagName==="LANE"&&l.kind==="number")o.laneNumber=l.value;else if(s.tagName==="TUBE"&&l.kind==="string")o.tube=l.value;else if(s.tagName==="MCHN"&&l.kind==="string")o.machineName=l.value;else if(s.tagName==="MODL"&&l.kind==="string")o.machineModel=l.value;else if(s.tagName==="RUND"&&l.kind==="date"){let f=l.value;o.runDate=`${f.year}-${String(f.month).padStart(2,"0")}-${String(f.day).padStart(2,"0")}`;}else if(s.tagName==="RUNT"&&l.kind==="time"){let f=l.value;o.runTime=`${String(f.hour).padStart(2,"0")}:${String(f.minute).padStart(2,"0")}:${String(f.second).padStart(2,"0")}`;}else s.tagName==="CMNT"&&l.kind==="string"&&o.comments.push(l.value);}let S,A=g[2]?2:g[1]?1:Object.keys(g).map(Number)[0];if(A!==void 0&&g[A]){let u=g[A].toUpperCase(),s=b[A]??[];if(s.length===0){for(let f of Object.keys(b).map(Number))if(b[f].length===u.length){s=b[f];break}}let l=N[A]??[];if(l.length===0){for(let f of Object.keys(N).map(Number))if(N[f].length===u.length){l=N[f];break}}S={sequence:u,confidences:s,positions:l,pbasVersion:A};}if(!Number.isFinite(o.samplingRate)||(o.samplingRate??0)<=0){let u=S?.positions,s=Math.max(m.A.length,m.C.length,m.G.length,m.T.length);u&&u.length>1?o.samplingRate=(u[u.length-1]-u[0])/(u.length-1):S&&S.sequence.length>0&&s>0&&(o.samplingRate=s/S.sequence.length);}let L={baseOrder:i,dataChannels:c,basecalled:m,raw:h};return {fileName:t,fileSize:n.byteLength,abifVersion:r.version,macBinaryOffset:r.macBinaryOffset,dirEntryCount:r.entries.length,metadata:o,chromatogram:L,baseCalls:S,entries:a}}function he(e){return e.A.length>0||e.C.length>0||e.G.length>0||e.T.length>0}function pe(e){return Math.max(e.A.length,e.C.length,e.G.length,e.T.length)}export{w as ENTRY_SIZE,F as HEADER_SIZE,ue as averagePeakSpacing,pe as channelMaxLength,me as ensureRawDataChannels,_ as findEntries,d as findEntry,Q as getConfidences,Z as getDataChannel,E as getFwo,X as getPositions,J as getRawChannelMap,ee as getSamplingRate,K as getSequence,I as hasProcessedTraces,he as hasSignals,be as parseAbif,U as readAbif,le as setAveragePeakSpacing,oe as setConfidences,se as setPositions,ie as setSequence,P as tagNameFromInt32,v as upsertEntry,H as writeAbif};//# sourceMappingURL=index.mjs.map
2
+ //# sourceMappingURL=index.mjs.map