@fishka/seqio 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -33
- package/dist/abif/index.d.mts +311 -124
- package/dist/abif/index.d.ts +311 -124
- package/dist/abif/index.js +1 -1
- package/dist/abif/index.js.map +1 -1
- package/dist/abif/index.mjs +1 -1
- package/dist/abif/index.mjs.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +7 -7
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +7 -7
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/abif/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
declare function tagNameFromInt32(n: number): string;
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Low-level ABIF file model: a flat list of directory entries with raw
|
|
3
5
|
* payloads. Lossless round-trip is preserved: every entry (including unknown
|
|
@@ -7,10 +9,35 @@
|
|
|
7
9
|
interface AbifFile {
|
|
8
10
|
/** ABIF version, e.g. 101 for v1.01. */
|
|
9
11
|
version: number;
|
|
12
|
+
/** The root directory (tdir) header, exactly as read — including any directory padding it declares. */
|
|
13
|
+
tdir: AbifDirectory;
|
|
10
14
|
/** Directory entries in the original on-disk order. */
|
|
11
15
|
entries: AbifEntry[];
|
|
12
16
|
/** MacBinary preamble offset (128 if present, 0 otherwise). Preserved for diagnostics. */
|
|
13
17
|
macBinaryOffset: number;
|
|
18
|
+
/**
|
|
19
|
+
* The 128-byte MacBinary preamble, verbatim — present only when {@link macBinaryOffset} is 128.
|
|
20
|
+
* Exposed so a raw reader can reproduce the wrapper, not just note that it existed.
|
|
21
|
+
*/
|
|
22
|
+
macBinaryHeader?: Uint8Array;
|
|
23
|
+
/**
|
|
24
|
+
* Reserved header bytes [34..127] (94 bytes), verbatim. Usually zeros; exposed so a raw reader
|
|
25
|
+
* keeps the entire 128-byte header, not just magic/version/tdir.
|
|
26
|
+
*/
|
|
27
|
+
headerReserved: Uint8Array;
|
|
28
|
+
/**
|
|
29
|
+
* Physical byte ranges not covered by the header, directory, or any entry payload — orphaned
|
|
30
|
+
* blocks left by editing tools, trailing padding, etc. Empty for a tightly-packed file. Exposed
|
|
31
|
+
* so a raw reader accounts for every byte; the chromatogram never depends on these.
|
|
32
|
+
*/
|
|
33
|
+
unreferencedRanges: AbifByteRange[];
|
|
34
|
+
}
|
|
35
|
+
/** A contiguous run of file bytes at an absolute offset — used for {@link AbifFile.unreferencedRanges}. */
|
|
36
|
+
interface AbifByteRange {
|
|
37
|
+
/** Absolute offset from the start of the file (includes any MacBinary preamble). */
|
|
38
|
+
offset: number;
|
|
39
|
+
/** The bytes in this range, verbatim. `bytes.length` is the range length. */
|
|
40
|
+
bytes: Uint8Array;
|
|
14
41
|
}
|
|
15
42
|
interface AbifEntry {
|
|
16
43
|
/** 4-character tag name, e.g. "DATA", "PBAS". */
|
|
@@ -23,12 +50,75 @@ interface AbifEntry {
|
|
|
23
50
|
elementType: number;
|
|
24
51
|
/** Bytes per element. */
|
|
25
52
|
elementSize: number;
|
|
26
|
-
/** Number of elements. */
|
|
53
|
+
/** Number of elements (reconciled: clamped to what the payload holds). */
|
|
27
54
|
elementCount: number;
|
|
28
|
-
/**
|
|
55
|
+
/**
|
|
56
|
+
* Raw payload bytes. Length === the on-disk `dataSize` (the authoritative field), which for
|
|
57
|
+
* user/opaque types may differ from `elementCount * elementSize`.
|
|
58
|
+
*/
|
|
29
59
|
payload: Uint8Array;
|
|
30
60
|
/** Opaque dataHandle field, usually 0. Preserved for round-trip. */
|
|
31
61
|
dataHandle: number;
|
|
62
|
+
/**
|
|
63
|
+
* The directory fields exactly as they were on disk — present only when this entry was read from a
|
|
64
|
+
* file (absent for entries synthesized by setters/writeAbif). Lets consumers inspect the real record
|
|
65
|
+
* without our reconciliation, and lets writeAbif() reuse this entry's original directory slot/offset
|
|
66
|
+
* verbatim on an unmodified round-trip. Mutate entries only through upsertEntry() — it clears this
|
|
67
|
+
* field, since a hand-edited entry (payload/elementType/elementSize/elementCount set directly) can no
|
|
68
|
+
* longer be reproduced from its stale on-disk shape.
|
|
69
|
+
*/
|
|
70
|
+
raw?: AbifEntryRaw;
|
|
71
|
+
}
|
|
72
|
+
/** A directory entry's on-disk fields, verbatim, before any reconciliation applied by {@link readAbif}. */
|
|
73
|
+
interface AbifEntryRaw {
|
|
74
|
+
/** `elementCount` (numElements) as written on disk. */
|
|
75
|
+
elementCount: number;
|
|
76
|
+
/** `dataSize` field as written on disk, in bytes. */
|
|
77
|
+
dataSize: number;
|
|
78
|
+
/** External payload offset relative to the ABIF start, or -1 when the payload is inline. */
|
|
79
|
+
dataOffset: number;
|
|
80
|
+
/** Whether the payload was stored inline (declared dataSize ≤ 4). */
|
|
81
|
+
inline: boolean;
|
|
82
|
+
/**
|
|
83
|
+
* The 4 raw bytes of the dataOffset/data slot, verbatim. For an external entry these are the
|
|
84
|
+
* big-endian offset; for an inline entry they are the value bytes plus any padding/stale bytes
|
|
85
|
+
* beyond `dataSize` — exposed so a raw reader loses no structure.
|
|
86
|
+
*/
|
|
87
|
+
dataOffsetBytes: Uint8Array;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The root directory (`tdir`) header — the header's own directory entry, describing the directory
|
|
91
|
+
* block. Its fields are exposed like any other raw entry so a raw reader never loses them, even when
|
|
92
|
+
* `rawEntryCount` desyncs from `dataSize`.
|
|
93
|
+
*/
|
|
94
|
+
interface AbifDirectory {
|
|
95
|
+
/** Effective number of entries actually read — equals `entries.length`. */
|
|
96
|
+
entryCount: number;
|
|
97
|
+
/** tdir `numElements` verbatim, before reconciliation; the authoritative on-disk entry count. */
|
|
98
|
+
rawEntryCount: number;
|
|
99
|
+
/** tdir `elementType` (1023). */
|
|
100
|
+
elementType: number;
|
|
101
|
+
/** tdir `tagNumber` (usually 1). */
|
|
102
|
+
tagNumber: number;
|
|
103
|
+
/** Bytes per directory entry (always 28). */
|
|
104
|
+
entrySize: number;
|
|
105
|
+
/**
|
|
106
|
+
* Directory block size in bytes, from the tdir `dataSize` field. May exceed `entryCount * 28`
|
|
107
|
+
* when the file carries directory padding / extra bytes.
|
|
108
|
+
*/
|
|
109
|
+
dataSize: number;
|
|
110
|
+
/** File offset (relative to the ABIF start) where the directory block begins. */
|
|
111
|
+
dataOffset: number;
|
|
112
|
+
/** The 4 raw bytes of the tdir's dataOffset field, verbatim. */
|
|
113
|
+
dataOffsetBytes: Uint8Array;
|
|
114
|
+
/** tdir `dataHandle` field, usually 0. */
|
|
115
|
+
dataHandle: number;
|
|
116
|
+
/**
|
|
117
|
+
* The raw directory-padding bytes: everything from the end of the last entry to the end of the
|
|
118
|
+
* directory block (`dataSize - entryCount*28`). Usually zeros; exposed so a raw reader keeps the
|
|
119
|
+
* whole directory structure, not just the entries.
|
|
120
|
+
*/
|
|
121
|
+
paddingBytes: Uint8Array;
|
|
32
122
|
}
|
|
33
123
|
interface ChannelSignals {
|
|
34
124
|
A: number[];
|
|
@@ -36,6 +126,8 @@ interface ChannelSignals {
|
|
|
36
126
|
G: number[];
|
|
37
127
|
T: number[];
|
|
38
128
|
}
|
|
129
|
+
/** Spec-defined role of a DATA<n> tag — see {@link dataChannelRole}. */
|
|
130
|
+
type AbifDataChannelRole = 'trace' | 'telemetry' | 'other';
|
|
39
131
|
/** Per-base chromatogram view. */
|
|
40
132
|
interface Chromatogram {
|
|
41
133
|
/** Per-base peak position in sample points (from PLOC). */
|
|
@@ -47,7 +139,39 @@ interface Chromatogram {
|
|
|
47
139
|
/** Average peak spacing (samples per base), from SPAC. */
|
|
48
140
|
samplingRate?: number;
|
|
49
141
|
}
|
|
50
|
-
/**
|
|
142
|
+
/**
|
|
143
|
+
* One basecall version exactly as the file stores it. ABIF numbers the
|
|
144
|
+
* PBAS/PCON/PLOC tags by version, and the spec fixes what each number means:
|
|
145
|
+
*
|
|
146
|
+
* - version 2 (`role: 'called'`) — the sequence as produced by the basecaller.
|
|
147
|
+
* - version 1 (`role: 'edited'`) — the sequence after user hand-editing.
|
|
148
|
+
* - any other version (`role: 'unknown'`) — the spec only defines 1 and 2, so
|
|
149
|
+
* a vendor/future PBAS3+ is surfaced without a claimed role.
|
|
150
|
+
*
|
|
151
|
+
* A file may carry either or both, and the two can differ in content and even in
|
|
152
|
+
* length (edits insert/delete bases). {@link parseAbif} exposes every version it
|
|
153
|
+
* finds via {@link ParsedAbif.baseCallVariants} — picking which one to show or
|
|
154
|
+
* export is the consumer's call, not the parser's.
|
|
155
|
+
*/
|
|
156
|
+
type AbifBaseCallRole = 'called' | 'edited' | 'unknown';
|
|
157
|
+
interface AbifBaseCallVariant {
|
|
158
|
+
/** Tag number of the PBAS/PCON/PLOC this variant came from (1, 2, or a vendor number). */
|
|
159
|
+
version: number;
|
|
160
|
+
/** Spec-defined role by tag number: 2 = basecaller-called, 1 = user-edited, else unknown. */
|
|
161
|
+
role: AbifBaseCallRole;
|
|
162
|
+
/** Bases from PBAS<version> as stored — case preserved, trailing NULs stripped, not normalized. */
|
|
163
|
+
sequence: string;
|
|
164
|
+
/** Per-base Q-scores from PCON<version>; `[]` when that version has no PCON. */
|
|
165
|
+
confidences: number[];
|
|
166
|
+
/** Per-base peak positions (sample indices) from PLOC<version>; `[]` when absent. */
|
|
167
|
+
positions: number[];
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Convenience pointer to the preferred basecall version — the called one (PBAS2)
|
|
171
|
+
* when present, else whatever single version the file has. This is a spec-role
|
|
172
|
+
* choice (called over edited), not a quality judgement; see
|
|
173
|
+
* {@link ParsedAbif.baseCallVariants} for every version the file actually carries.
|
|
174
|
+
*/
|
|
51
175
|
interface AbifBaseCalls {
|
|
52
176
|
/** Called bases (uppercase). */
|
|
53
177
|
sequence: string;
|
|
@@ -68,34 +192,37 @@ interface AbifMetadata {
|
|
|
68
192
|
runDate?: string;
|
|
69
193
|
runTime?: string;
|
|
70
194
|
samplingRate?: number;
|
|
195
|
+
/**
|
|
196
|
+
* Value of the RevC1 flag: whether the file declares its sequence already
|
|
197
|
+
* reverse-complemented. undefined when the tag is absent. Reported as-is — the
|
|
198
|
+
* consumer decides what to do with it.
|
|
199
|
+
*/
|
|
200
|
+
reverseComplemented?: boolean;
|
|
71
201
|
comments: string[];
|
|
72
202
|
}
|
|
73
203
|
/**
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
* The
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
* Use {@link hasProcessedTraces} (data9To12 present) to detect whether
|
|
88
|
-
* DATA1..4 has already been processed and bypass your own baseline/color
|
|
89
|
-
* steps accordingly.
|
|
204
|
+
* All DATA channels plus FWO_-aware A/C/G/T views of the two dye-trace blocks.
|
|
205
|
+
*
|
|
206
|
+
* The block views are named after their on-disk tag ranges — nothing more. Which
|
|
207
|
+
* block is "raw" and which is "analyzed / processed" is an instrument-and-tool
|
|
208
|
+
* convention that the ABIF file does NOT state, so this parser refuses to label
|
|
209
|
+
* it. The consumer that needs to tell them apart has the primitives to decide:
|
|
210
|
+
* the per-block sample counts (channel lengths) and the basecall peak positions
|
|
211
|
+
* ({@link AbifBaseCalls.positions}); e.g. positions that overflow one block's
|
|
212
|
+
* length can only belong to the other.
|
|
213
|
+
*
|
|
214
|
+
* Per the ABIF spec, DATA5..8 are instrument telemetry (voltage / current / power
|
|
215
|
+
* / temperature), NOT dye traces — see {@link dataChannelRole}. They live in
|
|
216
|
+
* {@link dataChannels} but are excluded from the A/C/G/T views.
|
|
90
217
|
*/
|
|
91
218
|
interface AbifChromatogramBundle {
|
|
92
219
|
/** FWO_ value (e.g. "GATC"). */
|
|
93
220
|
baseOrder: string;
|
|
94
|
-
/** All DATA tags by tagNumber → trace. */
|
|
221
|
+
/** All DATA tags by tagNumber → trace (dye traces AND telemetry). */
|
|
95
222
|
dataChannels: Record<number, number[]>;
|
|
96
|
-
/** DATA1..4 mapped to A/C/G/T by FWO_.
|
|
223
|
+
/** DATA1..4 mapped to A/C/G/T by FWO_. */
|
|
97
224
|
data1To4: ChannelSignals;
|
|
98
|
-
/** DATA9..12 mapped to A/C/G/T by FWO_
|
|
225
|
+
/** DATA9..12 mapped to A/C/G/T by FWO_; empty when the file has no 9..12 block. */
|
|
99
226
|
data9To12: ChannelSignals;
|
|
100
227
|
}
|
|
101
228
|
/** Rich result from {@link parseAbif} — everything the typical viewer needs. */
|
|
@@ -107,7 +234,10 @@ interface ParsedAbif {
|
|
|
107
234
|
dirEntryCount: number;
|
|
108
235
|
metadata: AbifMetadata;
|
|
109
236
|
chromatogram: AbifChromatogramBundle;
|
|
237
|
+
/** Preferred basecall version (called over edited); convenience over {@link baseCallVariants}. */
|
|
110
238
|
baseCalls?: AbifBaseCalls;
|
|
239
|
+
/** Every basecall version the file carries (called and/or edited), in version order. */
|
|
240
|
+
baseCallVariants: AbifBaseCallVariant[];
|
|
111
241
|
/** All directory entries with their decoded payloads (best-effort by type). */
|
|
112
242
|
entries: AbifDirEntry[];
|
|
113
243
|
}
|
|
@@ -119,9 +249,15 @@ interface AbifDirEntry {
|
|
|
119
249
|
elementType: number;
|
|
120
250
|
elementTypeName: string;
|
|
121
251
|
elementSize: number;
|
|
252
|
+
/** Reconciled element count (clamped to the declared dataSize when it was smaller). */
|
|
122
253
|
elementCount: number;
|
|
254
|
+
/** `numElements` exactly as written on disk, before reconciliation. */
|
|
255
|
+
rawElementCount: number;
|
|
256
|
+
/** `dataSize` as written on disk, in bytes (not recomputed). */
|
|
123
257
|
dataSize: number;
|
|
258
|
+
/** External payload offset relative to the ABIF start, or -1 when the payload is inline. */
|
|
124
259
|
dataOffset: number;
|
|
260
|
+
/** Whether the payload was stored inline (declared dataSize ≤ 4). */
|
|
125
261
|
inline: boolean;
|
|
126
262
|
decoded: AbifDecodedValue;
|
|
127
263
|
preview: string;
|
|
@@ -161,14 +297,13 @@ type AbifDecodedValue = {
|
|
|
161
297
|
value: Uint8Array;
|
|
162
298
|
};
|
|
163
299
|
|
|
164
|
-
declare function tagNameFromInt32(n: number): string;
|
|
165
|
-
|
|
166
300
|
/**
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
*
|
|
301
|
+
* Raw layer: the ABIF byte<->struct codec. Every directory entry (including unknown
|
|
302
|
+
* vendor tags) is preserved as a raw payload (Uint8Array), and writeAbif() reproduces
|
|
303
|
+
* the original bytes exactly for an unmodified round-trip (see its own doc comment).
|
|
304
|
+
* The domain layer (view.ts, setters.ts, parser.ts, abif-op-*.ts) provides typed,
|
|
305
|
+
* format-aware access on top of this — this file knows nothing about what any tag
|
|
306
|
+
* means.
|
|
172
307
|
*
|
|
173
308
|
* ABIF file layout:
|
|
174
309
|
* [0..3] "ABIF" magic
|
|
@@ -184,12 +319,14 @@ declare function tagNameFromInt32(n: number): string;
|
|
|
184
319
|
* 8 2 elementType (int16)
|
|
185
320
|
* 10 2 elementSize (int16)
|
|
186
321
|
* 12 4 elementCount (int32)
|
|
187
|
-
* 16 4 dataSize (int32; total payload bytes
|
|
322
|
+
* 16 4 dataSize (int32; total payload bytes — authoritative; for
|
|
323
|
+
* well-formed entries equals count*size, but user/
|
|
324
|
+
* opaque types may differ, so we read by dataSize)
|
|
188
325
|
* 20 4 dataOffset (int32) OR inline data if dataSize <= 4
|
|
189
326
|
* 24 4 dataHandle (int32; usually 0)
|
|
190
327
|
*
|
|
191
|
-
* Inline rule (per ABIF spec): when
|
|
192
|
-
* stored directly in the dataOffset field (left-aligned, padded to 4 bytes).
|
|
328
|
+
* Inline rule (per ABIF spec): when the declared dataSize <= 4 the payload bytes
|
|
329
|
+
* are stored directly in the dataOffset field (left-aligned, padded to 4 bytes).
|
|
193
330
|
*
|
|
194
331
|
* MacBinary preamble: some ABIF files (older Mac-origin) start with a 128-byte
|
|
195
332
|
* MacBinary header before the actual ABIF magic. We detect and skip it.
|
|
@@ -198,7 +335,13 @@ declare function tagNameFromInt32(n: number): string;
|
|
|
198
335
|
declare const HEADER_SIZE = 128;
|
|
199
336
|
declare const ENTRY_SIZE = 28;
|
|
200
337
|
/**
|
|
201
|
-
* Parse an ABIF file from raw bytes.
|
|
338
|
+
* Parse an ABIF file from raw bytes into its verbatim directory structure.
|
|
339
|
+
*
|
|
340
|
+
* This is the RAW source of truth: it reads the tdir header and every entry as
|
|
341
|
+
* stored — real dataSize, dataOffset, numElements (see `entry.raw`), the 4 inline
|
|
342
|
+
* bytes, and the tdir/directory metadata — and interprets nothing. For a
|
|
343
|
+
* high-level, opinionated view (typed channels, basecalls, metadata) layer
|
|
344
|
+
* {@link parseAbif} on top.
|
|
202
345
|
*
|
|
203
346
|
* Accepts Uint8Array (works in Node and the browser). Node's Buffer extends
|
|
204
347
|
* Uint8Array, so `readAbif(buffer)` and `readAbif(new Uint8Array(arrayBuffer))`
|
|
@@ -211,15 +354,35 @@ declare function readAbif(bytes: Uint8Array): AbifFile;
|
|
|
211
354
|
/**
|
|
212
355
|
* Serialize an AbifFile back to a Uint8Array.
|
|
213
356
|
*
|
|
214
|
-
*
|
|
215
|
-
*
|
|
216
|
-
* (
|
|
357
|
+
* Byte-exact on an unmodified round-trip for well-formed records and the tolerated
|
|
358
|
+
* count/dataSize desyncs readAbif() accepts: readAbif() followed right back by
|
|
359
|
+
* writeAbif(), with nothing touched in between, reproduces the original bytes
|
|
360
|
+
* exactly (a MacBinary-wrapped input round-trips its ABIF payload byte-exact, but
|
|
361
|
+
* the preamble itself is never re-added — see the AGENTS.md note on why). The one
|
|
362
|
+
* exception is a genuinely invalid negative `dataSize`/`numElements` field (readAbif
|
|
363
|
+
* tolerates these defensively, falling back to a computed size, but never treats them
|
|
364
|
+
* as verbatim-eligible on write — see the byteLength check below) — such an entry
|
|
365
|
+
* round-trips meaning-lossless (correct payload/content) but its declared dataSize
|
|
366
|
+
* field gets normalized to the real payload length rather than reproducing the
|
|
367
|
+
* original garbage value.
|
|
217
368
|
*
|
|
218
|
-
*
|
|
219
|
-
*
|
|
220
|
-
*
|
|
369
|
+
* This works by keeping every entry whose payload size hasn't changed since it was
|
|
370
|
+
* read (`entry.raw` present — upsertEntry() clears it on any mutation — and
|
|
371
|
+
* `payload.byteLength === raw.dataSize`) at its exact original directory slot and
|
|
372
|
+
* file offset, writing the *original* on-disk numElements/dataSize/offset-or-inline-
|
|
373
|
+
* padding instead of the reconciled/current ones. A new or resized entry is appended
|
|
374
|
+
* past the highest byte offset still known to hold preserved content (every verbatim
|
|
375
|
+
* entry's span, the directory, and any unreferenced range); only its own directory
|
|
376
|
+
* record changes, so every other entry's bytes stay untouched. A resized/removed
|
|
377
|
+
* entry's *old* span is not itself reserved — nothing points at it anymore, so it is
|
|
378
|
+
* free to be reused by whatever gets appended next; the output is not padded out to
|
|
379
|
+
* the original file's true end.
|
|
221
380
|
*
|
|
222
|
-
*
|
|
381
|
+
* The directory is kept at its original file offset as long as the entry count
|
|
382
|
+
* didn't grow (removing entries just shortens it in place; the original directory
|
|
383
|
+
* padding is only reused when the count is exactly unchanged, since a shorter
|
|
384
|
+
* directory can't reuse padding sized for more entries). Only a growing entry count
|
|
385
|
+
* relocates the whole directory to freshly appended space.
|
|
223
386
|
*/
|
|
224
387
|
declare function writeAbif(file: AbifFile): Uint8Array;
|
|
225
388
|
/** Find an entry by name+number, or undefined. */
|
|
@@ -229,6 +392,11 @@ declare function findEntries(file: AbifFile, name: string): AbifEntry[];
|
|
|
229
392
|
/**
|
|
230
393
|
* Replace the payload of an existing entry, or append a new one.
|
|
231
394
|
* elementType/elementSize/elementCount must be supplied for new entries.
|
|
395
|
+
*
|
|
396
|
+
* This is the required way to mutate an entry read from a file — it clears `.raw`
|
|
397
|
+
* on replacement so writeAbif() never reuses a now-stale on-disk shape. Setting
|
|
398
|
+
* `entry.payload`/`elementType`/`elementSize`/`elementCount` directly instead
|
|
399
|
+
* leaves `.raw` behind and can corrupt the written directory record.
|
|
232
400
|
*/
|
|
233
401
|
declare function upsertEntry(file: AbifFile, name: string, number: number, payload: Uint8Array, defaults: {
|
|
234
402
|
elementType: number;
|
|
@@ -237,78 +405,36 @@ declare function upsertEntry(file: AbifFile, name: string, number: number, paylo
|
|
|
237
405
|
}): void;
|
|
238
406
|
|
|
239
407
|
/**
|
|
240
|
-
* High-level
|
|
241
|
-
*
|
|
242
|
-
* Reading helpers that interpret the raw payloads of well-known tags. For
|
|
243
|
-
* mutation helpers (setSequence, setConfidences, ...) see ./setters.
|
|
244
|
-
*/
|
|
245
|
-
|
|
246
|
-
/** Get DATA<n> as a signed-int16 array, or undefined. */
|
|
247
|
-
declare function getDataChannel(file: AbifFile, n: number): Int16Array | undefined;
|
|
248
|
-
/**
|
|
249
|
-
* Dye order, 4 ASCII chars (e.g. "GATC"). Defaults to "GATC" if FWO_ absent.
|
|
250
|
-
*
|
|
251
|
-
* GATC is the dye order produced by modern ABI 3730/3500 instruments and the
|
|
252
|
-
* dominant default in the wild. Older "ACGT" defaults caused channel
|
|
253
|
-
* mis-mapping on files where FWO_ is missing or malformed.
|
|
254
|
-
*/
|
|
255
|
-
declare function getFwo(file: AbifFile): string;
|
|
256
|
-
/**
|
|
257
|
-
* True when the file carries BOTH DATA1..4 and DATA9..12. Newer ABI-style
|
|
258
|
-
* instruments produce both: DATA1..4 is post-processed (mobility-corrected,
|
|
259
|
-
* baseline-subtracted, color-separated) and DATA9..12 is raw fluorescence.
|
|
260
|
-
* Older instruments produce only DATA1..4 (which IS the raw signal).
|
|
261
|
-
*
|
|
262
|
-
* Callers that re-process traces (basecallers) should detect this and bypass
|
|
263
|
-
* their own baseline-subtraction / color-matrix steps when DATA1..4 is
|
|
264
|
-
* already cleaned.
|
|
265
|
-
*/
|
|
266
|
-
declare function hasProcessedTraces(file: AbifFile): boolean;
|
|
267
|
-
/**
|
|
268
|
-
* Map from base letter ("A"|"C"|"G"|"T") to the DATA tag number that holds
|
|
269
|
-
* its RAW fluorescence channel.
|
|
270
|
-
*
|
|
271
|
-
* ABIF stores up to 12 DATA tags. KB-basecaller-aware instruments (3130, 3500,
|
|
272
|
-
* ...) use DATA1..4 for processed traces and DATA9..12 for raw. Older / simpler
|
|
273
|
-
* instruments produce only DATA1..8 where DATA1..4 ARE the raw traces.
|
|
274
|
-
*
|
|
275
|
-
* This helper always returns the DATA1..4 mapping (the convention used by
|
|
276
|
-
* basecallers operating on raw signal). Use {@link hasProcessedTraces} to
|
|
277
|
-
* detect whether DATA1..4 has been pre-processed and bypass baseline/color
|
|
278
|
-
* steps accordingly.
|
|
408
|
+
* High-level "parse everything" wrapper around the raw + view layers.
|
|
279
409
|
*
|
|
280
|
-
*
|
|
281
|
-
*
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
/** Get PBAS sequence (prefer PBAS2 over PBAS1). undefined if neither present. */
|
|
285
|
-
declare function getSequence(file: AbifFile): string | undefined;
|
|
286
|
-
/**
|
|
287
|
-
* Get per-base Phred-like quality scores (0..255 byte values, typically 0..60
|
|
288
|
-
* for Sanger). Prefers PCON2 over PCON1.
|
|
410
|
+
* Returns a single ParsedAbif object with metadata, the FWO_-aware
|
|
411
|
+
* DATA1..4 / DATA9..12 channel split, basecalls, and decoded directory entries
|
|
412
|
+
* for diagnostics. Mirrors what typical viewers (chromatogram UIs, sample
|
|
413
|
+
* inspectors) need from a single file.
|
|
289
414
|
*
|
|
290
|
-
*
|
|
291
|
-
*
|
|
415
|
+
* For round-trip authoring (basecallers), prefer {@link readAbif} +
|
|
416
|
+
* setters from ./setters which operate directly on the raw AbifFile.
|
|
292
417
|
*/
|
|
293
|
-
|
|
418
|
+
|
|
294
419
|
/**
|
|
295
|
-
*
|
|
420
|
+
* Parse an ABIF file into a high-level view: metadata, channels, basecalls,
|
|
421
|
+
* and decoded directory entries.
|
|
296
422
|
*
|
|
297
|
-
*
|
|
298
|
-
*
|
|
299
|
-
*
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
/**
|
|
303
|
-
* Get average peak spacing (samples per base), from SPAC/1.
|
|
423
|
+
* This is the INTERPRETING layer — it makes convenience choices (FWO_ → "GATC"
|
|
424
|
+
* fallback, derived samplingRate, preferred/upper-cased PBAS2 baseCalls). It is
|
|
425
|
+
* not the raw structural truth: for that use {@link readAbif}, which reads the
|
|
426
|
+
* directory verbatim (raw dataSize/offset/counts, tdir, inline bytes) and makes
|
|
427
|
+
* no interpretation. `parseAbif` builds on top of it.
|
|
304
428
|
*
|
|
305
|
-
*
|
|
306
|
-
*
|
|
307
|
-
*
|
|
308
|
-
*
|
|
309
|
-
* Returns undefined if SPAC is absent or non-positive.
|
|
429
|
+
* Accepts ArrayBuffer or Uint8Array (Buffer in Node works too — it extends
|
|
430
|
+
* Uint8Array). The `fileName` argument is informational only; it's preserved
|
|
431
|
+
* in the result.
|
|
310
432
|
*/
|
|
311
|
-
declare function
|
|
433
|
+
declare function parseAbif(input: ArrayBuffer | Uint8Array, fileName?: string): ParsedAbif;
|
|
434
|
+
/** True when any channel has at least one signal value. */
|
|
435
|
+
declare function hasSignals(s: ChannelSignals): boolean;
|
|
436
|
+
/** Length of the longest channel in a ChannelSignals bundle. */
|
|
437
|
+
declare function channelMaxLength(s: ChannelSignals): number;
|
|
312
438
|
|
|
313
439
|
/**
|
|
314
440
|
* Mutation helpers for AbifFile: write PBAS/PCON/PLOC/SPAC and ensure DATA9..12
|
|
@@ -359,29 +485,90 @@ declare function averagePeakSpacing(positions: ArrayLike<number>): number;
|
|
|
359
485
|
declare function ensureRawDataChannels(file: AbifFile): void;
|
|
360
486
|
|
|
361
487
|
/**
|
|
362
|
-
* High-level
|
|
363
|
-
*
|
|
364
|
-
* Returns a single ParsedAbif object with metadata, the FWO_-aware
|
|
365
|
-
* DATA1..4 / DATA9..12 channel split, basecalls, and decoded directory entries
|
|
366
|
-
* for diagnostics. Mirrors what typical viewers (chromatogram UIs, sample
|
|
367
|
-
* inspectors) need from a single file.
|
|
488
|
+
* High-level typed view over an AbifFile.
|
|
368
489
|
*
|
|
369
|
-
*
|
|
370
|
-
*
|
|
490
|
+
* Reading helpers that interpret the raw payloads of well-known tags. For
|
|
491
|
+
* mutation helpers (setSequence, setConfidences, ...) see ./setters.
|
|
371
492
|
*/
|
|
372
493
|
|
|
494
|
+
/** Get DATA<n> as a signed-int16 array, or undefined. */
|
|
495
|
+
declare function getDataChannel(file: AbifFile, n: number): Int16Array | undefined;
|
|
373
496
|
/**
|
|
374
|
-
*
|
|
375
|
-
* and decoded directory entries.
|
|
497
|
+
* Dye order, 4 ASCII chars (e.g. "GATC"). Defaults to "GATC" if FWO_ absent.
|
|
376
498
|
*
|
|
377
|
-
*
|
|
378
|
-
*
|
|
379
|
-
*
|
|
499
|
+
* GATC is the dye order produced by modern ABI 3730/3500 instruments and the
|
|
500
|
+
* dominant default in the wild. Older "ACGT" defaults caused channel
|
|
501
|
+
* mis-mapping on files where FWO_ is missing or malformed.
|
|
380
502
|
*/
|
|
381
|
-
declare function
|
|
382
|
-
/**
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
503
|
+
declare function getFwo(file: AbifFile): string;
|
|
504
|
+
/**
|
|
505
|
+
* Whether an FWO_ string is a genuine dye order: a permutation of A/C/G/T with all
|
|
506
|
+
* four bases distinct. `"GATC"` passes; `"AAAA"` (regex-valid but degenerate) does
|
|
507
|
+
* not — mapping four channels through it would collapse them onto one base.
|
|
508
|
+
*/
|
|
509
|
+
declare function isFwoPermutation(fwo: string): boolean;
|
|
510
|
+
/**
|
|
511
|
+
* Fact: the file carries a second dye-trace block, DATA9..12 (all four tags), in
|
|
512
|
+
* addition to DATA1..4. Reports presence only — it does NOT say which block is
|
|
513
|
+
* raw and which is analyzed/processed; that convention isn't stored in the file.
|
|
514
|
+
*/
|
|
515
|
+
declare function hasData9To12Block(file: AbifFile): boolean;
|
|
516
|
+
/**
|
|
517
|
+
* Spec-defined role of a DATA<n> tag, limited to the numbers the ABIF spec names:
|
|
518
|
+
*
|
|
519
|
+
* - `'trace'` — dye-signal channels: DATA1..4 (raw dyes 1-4), DATA9..12
|
|
520
|
+
* (analyzed dyes 1-4), and the two optional 5th-dye blocks
|
|
521
|
+
* DATA105 (raw dye 5) and DATA205 (analyzed dye 5).
|
|
522
|
+
* - `'telemetry'` — DATA5..8: instrument run telemetry (voltage, current,
|
|
523
|
+
* power, temperature), one value per scan — NOT dye signal.
|
|
524
|
+
* - `'other'` — any other DATA number. The spec does not enumerate higher
|
|
525
|
+
* extra-dye tags (106/206/…), so we don't claim a role for them.
|
|
526
|
+
*
|
|
527
|
+
* A fact from the ABIF specification, not an inference about content.
|
|
528
|
+
*/
|
|
529
|
+
declare function dataChannelRole(n: number): AbifDataChannelRole;
|
|
530
|
+
/**
|
|
531
|
+
* Whether the file declares its sequence already reverse-complemented, from the
|
|
532
|
+
* RevC1 flag (int16, non-zero = true). undefined when RevC1 is absent. Reported
|
|
533
|
+
* as-is; the consumer decides how to act on it.
|
|
534
|
+
*/
|
|
535
|
+
declare function getReverseComplemented(file: AbifFile): boolean | undefined;
|
|
536
|
+
/**
|
|
537
|
+
* Map from base letter ("A"|"C"|"G"|"T") to the DATA1..4 tag number that holds
|
|
538
|
+
* its channel, using the dye order declared by FWO_. If FWO_="GATC" then
|
|
539
|
+
* G→1, A→2, T→3, C→4.
|
|
540
|
+
*
|
|
541
|
+
* This follows the file's own FWO_ declaration for the DATA1..4 block; it makes
|
|
542
|
+
* no claim about whether that block is raw or processed.
|
|
543
|
+
*/
|
|
544
|
+
declare function getChannelMap(file: AbifFile): Record<'A' | 'C' | 'G' | 'T', number>;
|
|
545
|
+
/** Get PBAS sequence (prefer PBAS2 over PBAS1). undefined if neither present. */
|
|
546
|
+
declare function getSequence(file: AbifFile): string | undefined;
|
|
547
|
+
/**
|
|
548
|
+
* Get per-base Phred-like quality scores (0..255 byte values, typically 0..60
|
|
549
|
+
* for Sanger). Prefers PCON2 over PCON1.
|
|
550
|
+
*
|
|
551
|
+
* PCON is declared in the ABIF spec as elementType=2 (char) but the byte
|
|
552
|
+
* values ARE the Q-scores — we read raw bytes regardless of declared type.
|
|
553
|
+
*/
|
|
554
|
+
declare function getConfidences(file: AbifFile): number[] | undefined;
|
|
555
|
+
/**
|
|
556
|
+
* Get peak scan positions (one per base). Prefers PLOC2 over PLOC1.
|
|
557
|
+
*
|
|
558
|
+
* Read as UNSIGNED int16: PLOC indexes into the sample trace and is always
|
|
559
|
+
* non-negative, but values > 32767 (long traces) would wrap to negative
|
|
560
|
+
* if interpreted as signed.
|
|
561
|
+
*/
|
|
562
|
+
declare function getPositions(file: AbifFile): number[] | undefined;
|
|
563
|
+
/**
|
|
564
|
+
* Get average peak spacing (samples per base), from SPAC/1.
|
|
565
|
+
*
|
|
566
|
+
* ABIF spec defines SPAC as float32 (elementType=7); some legacy files
|
|
567
|
+
* mislabel it as long (type=5). Both are 4 bytes and on disk the payload
|
|
568
|
+
* is always a 32-bit float, so we read as float regardless of declared type.
|
|
569
|
+
*
|
|
570
|
+
* Returns undefined if SPAC is absent or non-positive.
|
|
571
|
+
*/
|
|
572
|
+
declare function getSamplingRate(file: AbifFile): number | undefined;
|
|
386
573
|
|
|
387
|
-
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,
|
|
574
|
+
export { type AbifBaseCallRole, type AbifBaseCallVariant, type AbifBaseCalls, type AbifByteRange, type AbifChromatogramBundle, type AbifDataChannelRole, type AbifDecodedValue, type AbifDirEntry, type AbifDirectory, type AbifEntry, type AbifEntryRaw, type AbifFile, type AbifMetadata, type ChannelSignals, type Chromatogram, ENTRY_SIZE, HEADER_SIZE, type ParsedAbif, averagePeakSpacing, channelMaxLength, dataChannelRole, ensureRawDataChannels, findEntries, findEntry, getChannelMap, getConfidences, getDataChannel, getFwo, getPositions, getReverseComplemented, getSamplingRate, getSequence, hasData9To12Block, hasSignals, isFwoPermutation, parseAbif, readAbif, setAveragePeakSpacing, setConfidences, setPositions, setSequence, tagNameFromInt32, upsertEntry, writeAbif };
|