edfcore 0.1.10 → 0.1.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -1
- package/dist/format-header.d.ts +23 -0
- package/dist/format-header.d.ts.map +1 -0
- package/dist/format-header.js +87 -0
- package/dist/format-header.js.map +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/sample-grid.d.ts +43 -0
- package/dist/sample-grid.d.ts.map +1 -0
- package/dist/sample-grid.js +97 -0
- package/dist/sample-grid.js.map +1 -0
- package/dist/types.d.ts +10 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/constants.ts +1 -1
- package/src/format-header.ts +104 -0
- package/src/index.ts +8 -0
- package/src/sample-grid.ts +123 -0
- package/src/types.ts +12 -0
package/dist/constants.d.ts
CHANGED
|
@@ -109,5 +109,5 @@ export declare const SIGNAL_FIELD_BLOCK_OFFSETS: {
|
|
|
109
109
|
readonly reserved: 224;
|
|
110
110
|
};
|
|
111
111
|
/** Published package version. Kept in sync with package.json by a test. */
|
|
112
|
-
export declare const VERSION = "0.1.
|
|
112
|
+
export declare const VERSION = "0.1.12";
|
|
113
113
|
//# sourceMappingURL=constants.d.ts.map
|
package/dist/constants.js
CHANGED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A header as text.
|
|
3
|
+
*
|
|
4
|
+
* Layer 7, and pure. `formatDiagnostics` already turns problems into something a human reads;
|
|
5
|
+
* this does the same for the header itself — the thing that goes into a bug report, a CLI, or a
|
|
6
|
+
* log line when a file behaves oddly.
|
|
7
|
+
*
|
|
8
|
+
* Two rules keep it useful rather than decorative. It never invents a value: a field edfcore
|
|
9
|
+
* could not resolve prints as `unknown` rather than as a plausible default, because the whole
|
|
10
|
+
* point of pasting this somewhere is that the reader can trust it. And it prints no patient
|
|
11
|
+
* identification unless asked — a header carries a name and a birth date, and a summary that
|
|
12
|
+
* lands in a chat log or an issue tracker should not carry them by default.
|
|
13
|
+
*/
|
|
14
|
+
import type { EdfHeader, FormatHeaderOptions } from './types.js';
|
|
15
|
+
/**
|
|
16
|
+
* A multi-line summary of a header.
|
|
17
|
+
*
|
|
18
|
+
* Patient identification is omitted unless `includePatientId` is set. That is not a privacy
|
|
19
|
+
* feature — the data is still in `header.patient` for anyone who wants it — it is a default
|
|
20
|
+
* chosen so that the obvious thing to do with this string is also the safe one.
|
|
21
|
+
*/
|
|
22
|
+
export declare function formatHeader(header: EdfHeader, options?: FormatHeaderOptions): string;
|
|
23
|
+
//# sourceMappingURL=format-header.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format-header.d.ts","sourceRoot":"","sources":["../src/format-header.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAmB,SAAS,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAwBlF;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,MAAM,CA0DrF"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A header as text.
|
|
3
|
+
*
|
|
4
|
+
* Layer 7, and pure. `formatDiagnostics` already turns problems into something a human reads;
|
|
5
|
+
* this does the same for the header itself — the thing that goes into a bug report, a CLI, or a
|
|
6
|
+
* log line when a file behaves oddly.
|
|
7
|
+
*
|
|
8
|
+
* Two rules keep it useful rather than decorative. It never invents a value: a field edfcore
|
|
9
|
+
* could not resolve prints as `unknown` rather than as a plausible default, because the whole
|
|
10
|
+
* point of pasting this somewhere is that the reader can trust it. And it prints no patient
|
|
11
|
+
* identification unless asked — a header carries a name and a birth date, and a summary that
|
|
12
|
+
* lands in a chat log or an issue tracker should not carry them by default.
|
|
13
|
+
*/
|
|
14
|
+
function formatDate(date) {
|
|
15
|
+
if (date === undefined)
|
|
16
|
+
return 'unknown';
|
|
17
|
+
const month = String(date.month).padStart(2, '0');
|
|
18
|
+
const day = String(date.day).padStart(2, '0');
|
|
19
|
+
return `${date.year}-${month}-${day}`;
|
|
20
|
+
}
|
|
21
|
+
function formatDuration(seconds) {
|
|
22
|
+
if (!Number.isFinite(seconds) || seconds < 0)
|
|
23
|
+
return 'unknown';
|
|
24
|
+
const whole = Math.floor(seconds);
|
|
25
|
+
const hours = Math.floor(whole / 3600);
|
|
26
|
+
const minutes = Math.floor((whole % 3600) / 60);
|
|
27
|
+
const rest = whole % 60;
|
|
28
|
+
const pad = (n) => String(n).padStart(2, '0');
|
|
29
|
+
return `${pad(hours)}:${pad(minutes)}:${pad(rest)}`;
|
|
30
|
+
}
|
|
31
|
+
function formatRate(signal) {
|
|
32
|
+
// undefined is the honest answer for a zero record duration, which is legal EDF.
|
|
33
|
+
return signal.sampleRateHz === undefined ? '—' : `${signal.sampleRateHz} Hz`;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* A multi-line summary of a header.
|
|
37
|
+
*
|
|
38
|
+
* Patient identification is omitted unless `includePatientId` is set. That is not a privacy
|
|
39
|
+
* feature — the data is still in `header.patient` for anyone who wants it — it is a default
|
|
40
|
+
* chosen so that the obvious thing to do with this string is also the safe one.
|
|
41
|
+
*/
|
|
42
|
+
export function formatHeader(header, options) {
|
|
43
|
+
const lines = [];
|
|
44
|
+
const start = header.startTime;
|
|
45
|
+
lines.push(`${header.variant} · ${header.signals.length} signals · ${header.recordCount} records`);
|
|
46
|
+
lines.push(`start ${formatDate(start.resolvedDate)} ${String(start.clock.hour).padStart(2, '0')}:` +
|
|
47
|
+
`${String(start.clock.minute).padStart(2, '0')}:${String(start.clock.second).padStart(2, '0')}` +
|
|
48
|
+
` (local, no timezone)`);
|
|
49
|
+
lines.push(`record ${header.recordDurationSeconds} s · ${header.recordByteLength} bytes · ` +
|
|
50
|
+
`${header.bytesPerSample} bytes/sample`);
|
|
51
|
+
lines.push(`duration ${formatDuration(header.recordCount * header.recordDurationSeconds)} ` +
|
|
52
|
+
`(${header.recordCount} × ${header.recordDurationSeconds} s)`);
|
|
53
|
+
if (header.recordCountSource === 'sourceByteLength') {
|
|
54
|
+
// Worth saying out loud: the count came from the file size, not from the header field.
|
|
55
|
+
lines.push(' record count recovered from the source length');
|
|
56
|
+
}
|
|
57
|
+
if (options?.includePatientId === true) {
|
|
58
|
+
lines.push(`patient ${header.patient.raw.trim() || 'unknown'}`);
|
|
59
|
+
lines.push(`recording ${header.recording.raw.trim() || 'unknown'}`);
|
|
60
|
+
}
|
|
61
|
+
lines.push('');
|
|
62
|
+
lines.push(' # label kind rate range');
|
|
63
|
+
for (const signal of header.signals) {
|
|
64
|
+
const index = String(signal.index).padStart(3);
|
|
65
|
+
const label = signal.label.slice(0, 20).padEnd(21);
|
|
66
|
+
const kind = signal.kind.padEnd(12);
|
|
67
|
+
const rate = formatRate(signal).padEnd(9);
|
|
68
|
+
const range = signal.kind === 'annotations'
|
|
69
|
+
? '—'
|
|
70
|
+
: signal.scale === undefined
|
|
71
|
+
? 'no usable scale'
|
|
72
|
+
: `${signal.physicalMinimum}..${signal.physicalMaximum} ${signal.physicalDimension}`;
|
|
73
|
+
lines.push(`${index} ${label}${kind}${rate} ${range}`);
|
|
74
|
+
}
|
|
75
|
+
if (header.diagnostics.length > 0) {
|
|
76
|
+
lines.push('');
|
|
77
|
+
const counts = new Map();
|
|
78
|
+
for (const diagnostic of header.diagnostics) {
|
|
79
|
+
counts.set(diagnostic.severity, (counts.get(diagnostic.severity) ?? 0) + 1);
|
|
80
|
+
}
|
|
81
|
+
const summary = [...counts].map(([severity, count]) => `${count} ${severity}`).join(', ');
|
|
82
|
+
lines.push(`${header.diagnostics.length} diagnostic(s): ${summary}`);
|
|
83
|
+
lines.push('Call formatDiagnostics(header.diagnostics) for the detail.');
|
|
84
|
+
}
|
|
85
|
+
return lines.join('\n');
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=format-header.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format-header.js","sourceRoot":"","sources":["../src/format-header.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
/** The trailing `options` argument shared by every primitive that can allocate. */
|
|
23
23
|
export type { MaterializeOptions } from './decode/digital.js';
|
|
24
24
|
export type { FormatDiagnosticsOptions } from './diagnostics/format.js';
|
|
25
|
-
export type { AbortSignalLike, BlobLike, BuildIndexOptions, ByteSource, CacheOptions, DecodeAnnotationsOptions, EdfAnnotation, EdfAnnotationsResult, EdfAnnotationWindow, EdfCalendarDate, EdfChunk, EdfChunkSignal, EdfClockTime, EdfDiagnostic, EdfDiagnosticCode, EdfEnvelopeChunk, EdfEnvelopeSignal, EdfGap, EdfHeader, EdfInspection, EdfKnownDiagnosticCode, EdfLocation, EdfPatientId, EdfPhysicalEnvelope, EdfRawHeaderFields, EdfRawSignalFields, EdfRecordIndex, EdfRecording, EdfRecordingId, EdfScale, EdfSegment, EdfSeverity, EdfSignal, EdfStartTime, EdfStatusWord, EdfTimeline, EdfTriggerEvent, EdfVariant, EnvelopeSelection, FetchLike, HttpResponseLike, HttpSourceOptions, OpenOptions, ParseOptions, ReadOptions, RecordRange, RecordSelection, StreamSelection, TriggerSelection, WindowSelection, } from './types.js';
|
|
25
|
+
export type { AbortSignalLike, BlobLike, BuildIndexOptions, ByteSource, CacheOptions, DecodeAnnotationsOptions, EdfAnnotation, EdfAnnotationsResult, EdfAnnotationWindow, EdfCalendarDate, EdfChunk, EdfChunkSignal, EdfClockTime, EdfDiagnostic, EdfDiagnosticCode, EdfEnvelopeChunk, EdfEnvelopeSignal, EdfGap, EdfHeader, EdfInspection, EdfKnownDiagnosticCode, EdfLocation, EdfPatientId, EdfPhysicalEnvelope, EdfRawHeaderFields, EdfRawSignalFields, EdfRecordIndex, EdfRecording, EdfRecordingId, EdfSampleLocation, EdfScale, EdfSegment, EdfSeverity, EdfSignal, EdfStartTime, EdfStatusWord, EdfTimeline, EdfTriggerEvent, EdfVariant, EnvelopeSelection, FetchLike, FormatHeaderOptions, HttpResponseLike, HttpSourceOptions, OpenOptions, ParseOptions, ReadOptions, RecordRange, RecordSelection, StreamSelection, TriggerSelection, WindowSelection, } from './types.js';
|
|
26
26
|
export type { AnyEdfError, EdfErrorKind, EdfFormatErrorInit } from './errors.js';
|
|
27
27
|
export { EdfAmbiguousChannelError, EdfBudgetError, EdfChannelNotFoundError, EdfError, EdfFormatError, EdfRangeError, EdfScalingError, EdfSourceError, isEdfError, } from './errors.js';
|
|
28
28
|
export { BDF_ANNOTATIONS_LABEL, BDF_DIGITAL_MAX, BDF_DIGITAL_MIN, EDF_ANNOTATIONS_LABEL, EDF_DIGITAL_MAX, EDF_DIGITAL_MIN, EDF_HEADER_BLOCK_BYTES, EDF_RECOMMENDED_MAX_RECORD_BYTES, TICKS_PER_SECOND, VERSION, } from './constants.js';
|
|
@@ -44,7 +44,9 @@ export { buildRecordIndex, buildTimeline } from './record-index.js';
|
|
|
44
44
|
export { countAnnotationsByText, filterAnnotationsByText, filterAnnotationsByTime, } from './annotations-query.js';
|
|
45
45
|
export { decodeStatusWord, getStatusSignal, readTriggers } from './biosemi.js';
|
|
46
46
|
export { envelopeOfSamples, readEnvelope, toPhysicalEnvelope } from './envelope.js';
|
|
47
|
+
export { formatHeader } from './format-header.js';
|
|
47
48
|
export { inspectEdf } from './inspect.js';
|
|
48
49
|
export { openEdf, readAnnotations, readRecords, readWindow } from './recording.js';
|
|
50
|
+
export { sampleIndexAt, sampleStartSeconds, sampleStartTicks, } from './sample-grid.js';
|
|
49
51
|
export { streamRecords } from './stream.js';
|
|
50
52
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -57,7 +57,9 @@ export { buildRecordIndex, buildTimeline } from './record-index.js';
|
|
|
57
57
|
export { countAnnotationsByText, filterAnnotationsByText, filterAnnotationsByTime, } from './annotations-query.js';
|
|
58
58
|
export { decodeStatusWord, getStatusSignal, readTriggers } from './biosemi.js';
|
|
59
59
|
export { envelopeOfSamples, readEnvelope, toPhysicalEnvelope } from './envelope.js';
|
|
60
|
+
export { formatHeader } from './format-header.js';
|
|
60
61
|
export { inspectEdf } from './inspect.js';
|
|
61
62
|
export { openEdf, readAnnotations, readRecords, readWindow } from './recording.js';
|
|
63
|
+
export { sampleIndexAt, sampleStartSeconds, sampleStartTicks, } from './sample-grid.js';
|
|
62
64
|
export { streamRecords } from './stream.js';
|
|
63
65
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AA0EH,OAAO,EACL,wBAAwB,EACxB,cAAc,EACd,uBAAuB,EACvB,QAAQ,EACR,cAAc,EACd,aAAa,EACb,eAAe,EACf,cAAc,EACd,UAAU,GACX,MAAM,aAAa,CAAC;AAErB,8EAA8E;AAC9E,YAAY;AACZ,8EAA8E;AAE9E,OAAO,EACL,qBAAqB,EACrB,eAAe,EACf,eAAe,EACf,qBAAqB,EACrB,eAAe,EACf,eAAe,EACf,sBAAsB,EACtB,gCAAgC,EAChC,gBAAgB,EAChB,OAAO,GACR,MAAM,gBAAgB,CAAC;AAExB,8EAA8E;AAC9E,2EAA2E;AAC3E,2CAA2C;AAC3C,8EAA8E;AAE9E,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC/E,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEnE,8EAA8E;AAC9E,yEAAyE;AACzE,2EAA2E;AAC3E,6CAA6C;AAC7C,8EAA8E;AAE9E,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,8EAA8E;AAC9E,uCAAuC;AACvC,8EAA8E;AAE9E,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEpE,8EAA8E;AAC9E,oBAAoB;AACpB,8EAA8E;AAE9E,OAAO,EACL,sBAAsB,EACtB,uBAAuB,EACvB,uBAAuB,GACxB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC/E,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACpF,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACnF,OAAO,EACL,aAAa,EACb,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Time to sample index, and back.
|
|
3
|
+
*
|
|
4
|
+
* Layer 7, and pure. Every viewer needs this and the obvious spelling is wrong:
|
|
5
|
+
* `Math.round(seconds * signal.sampleRateHz)`.
|
|
6
|
+
*
|
|
7
|
+
* Three things break it. `sampleRateHz` is `samplesPerRecord / recordDurationSeconds`, so for a
|
|
8
|
+
* record duration that is not a power of ten it is a float with no exact representation —
|
|
9
|
+
* 128 samples over 0.3 s is 426.666..., and multiplying by a large `seconds` accumulates the
|
|
10
|
+
* error until the index is off by one. `sampleRateHz` is also `undefined` when the record
|
|
11
|
+
* duration is zero, which is legal EDF and which a real sleep-staging file relies on, so the
|
|
12
|
+
* expression silently yields `NaN`. And a recording does not start at zero: onsets are relative
|
|
13
|
+
* to record 0's own start, which is what every other time in edfcore is measured from.
|
|
14
|
+
*
|
|
15
|
+
* These do the arithmetic in integers on `(record, sampleWithinRecord)` instead, which is the
|
|
16
|
+
* same rule `trimToWindow` follows.
|
|
17
|
+
*/
|
|
18
|
+
import type { EdfSampleLocation, EdfSignal } from './types.js';
|
|
19
|
+
/**
|
|
20
|
+
* The sample covering `seconds` elapsed from the start of the recording.
|
|
21
|
+
*
|
|
22
|
+
* Floor, not round: a sample covers the half-open interval from its own start to the next one's,
|
|
23
|
+
* so the sample "at" a time is the one whose interval contains it. Rounding would return the
|
|
24
|
+
* NEXT sample for anything past the halfway point, which puts a window boundary one sample late.
|
|
25
|
+
*/
|
|
26
|
+
export declare function sampleIndexAt(signal: EdfSignal, seconds: number, recordDurationTicks: bigint): EdfSampleLocation;
|
|
27
|
+
/**
|
|
28
|
+
* The exact start time of a sample, in 100 ns ticks, elapsed from the start of the recording.
|
|
29
|
+
*
|
|
30
|
+
* Ticks rather than seconds because this is the value worth comparing: a float64 second loses
|
|
31
|
+
* precision past about 28.5 years, and more importantly two times that should be equal can fail
|
|
32
|
+
* to be once both have been divided by ten million.
|
|
33
|
+
*
|
|
34
|
+
* Rounded UP to a whole tick, which matters more than it looks. A sample boundary need not fall
|
|
35
|
+
* on one: 128 samples over 0.3 s puts sample 1 at 23,437.5 ticks, and 100 ns is the finest unit
|
|
36
|
+
* edfcore has. Truncating would return 23,437 — a tick that lies inside sample 0 — so
|
|
37
|
+
* `sampleIndexAt` would send it straight back to the previous sample. Taking the first whole
|
|
38
|
+
* tick at or after the exact start keeps the two functions inverse for every index.
|
|
39
|
+
*/
|
|
40
|
+
export declare function sampleStartTicks(signal: EdfSignal, sampleIndex: number, recordDurationTicks: bigint): bigint;
|
|
41
|
+
/** `sampleStartTicks` in seconds, for display. Compare ticks, not this. */
|
|
42
|
+
export declare function sampleStartSeconds(signal: EdfSignal, sampleIndex: number, recordDurationTicks: bigint): number;
|
|
43
|
+
//# sourceMappingURL=sample-grid.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sample-grid.d.ts","sourceRoot":"","sources":["../src/sample-grid.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AA0B/D;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,MAAM,EACf,mBAAmB,EAAE,MAAM,GAC1B,iBAAiB,CAoBnB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,MAAM,EACnB,mBAAmB,EAAE,MAAM,GAC1B,MAAM,CAcR;AAED,2EAA2E;AAC3E,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,MAAM,EACnB,mBAAmB,EAAE,MAAM,GAC1B,MAAM,CAKR"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Time to sample index, and back.
|
|
3
|
+
*
|
|
4
|
+
* Layer 7, and pure. Every viewer needs this and the obvious spelling is wrong:
|
|
5
|
+
* `Math.round(seconds * signal.sampleRateHz)`.
|
|
6
|
+
*
|
|
7
|
+
* Three things break it. `sampleRateHz` is `samplesPerRecord / recordDurationSeconds`, so for a
|
|
8
|
+
* record duration that is not a power of ten it is a float with no exact representation —
|
|
9
|
+
* 128 samples over 0.3 s is 426.666..., and multiplying by a large `seconds` accumulates the
|
|
10
|
+
* error until the index is off by one. `sampleRateHz` is also `undefined` when the record
|
|
11
|
+
* duration is zero, which is legal EDF and which a real sleep-staging file relies on, so the
|
|
12
|
+
* expression silently yields `NaN`. And a recording does not start at zero: onsets are relative
|
|
13
|
+
* to record 0's own start, which is what every other time in edfcore is measured from.
|
|
14
|
+
*
|
|
15
|
+
* These do the arithmetic in integers on `(record, sampleWithinRecord)` instead, which is the
|
|
16
|
+
* same rule `trimToWindow` follows.
|
|
17
|
+
*/
|
|
18
|
+
import { TICKS_PER_SECOND } from './constants.js';
|
|
19
|
+
import { secondsToTicks } from './tal/ticks.js';
|
|
20
|
+
function assertGrid(signal, recordDurationTicks) {
|
|
21
|
+
if (signal.kind === 'annotations') {
|
|
22
|
+
throw new RangeError(`signal ${signal.index} (${JSON.stringify(signal.label)}) is an annotations channel, ` +
|
|
23
|
+
'whose region holds TAL text rather than samples, so it has no sample grid. Next: use ' +
|
|
24
|
+
'onsetTicks on the annotations themselves.');
|
|
25
|
+
}
|
|
26
|
+
if (signal.samplesPerRecord <= 0) {
|
|
27
|
+
throw new RangeError(`signal ${signal.index} (${JSON.stringify(signal.label)}) declares ` +
|
|
28
|
+
`${signal.samplesPerRecord} samples per record, so it has no sample grid to index. ` +
|
|
29
|
+
'Next: check header.diagnostics for ZERO_SAMPLES_PER_RECORD.');
|
|
30
|
+
}
|
|
31
|
+
if (recordDurationTicks <= 0n) {
|
|
32
|
+
throw new RangeError('this file declares a record duration of zero, so records do not advance in time and no ' +
|
|
33
|
+
'elapsed time maps to a sample. This is legal EDF and a scoring file relies on it. ' +
|
|
34
|
+
'Next: index by record with readRecords().');
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* The sample covering `seconds` elapsed from the start of the recording.
|
|
39
|
+
*
|
|
40
|
+
* Floor, not round: a sample covers the half-open interval from its own start to the next one's,
|
|
41
|
+
* so the sample "at" a time is the one whose interval contains it. Rounding would return the
|
|
42
|
+
* NEXT sample for anything past the halfway point, which puts a window boundary one sample late.
|
|
43
|
+
*/
|
|
44
|
+
export function sampleIndexAt(signal, seconds, recordDurationTicks) {
|
|
45
|
+
assertGrid(signal, recordDurationTicks);
|
|
46
|
+
const ticks = secondsToTicks(seconds);
|
|
47
|
+
const perRecord = BigInt(signal.samplesPerRecord);
|
|
48
|
+
// Exact integer arithmetic throughout: ticks * samplesPerRecord / recordDurationTicks, floored
|
|
49
|
+
// toward negative infinity so a time before the start yields a negative index rather than
|
|
50
|
+
// truncating toward zero and colliding with sample 0.
|
|
51
|
+
const numerator = ticks * perRecord;
|
|
52
|
+
let index = numerator / recordDurationTicks;
|
|
53
|
+
if (numerator % recordDurationTicks !== 0n && numerator < 0n)
|
|
54
|
+
index -= 1n;
|
|
55
|
+
const recordIndex = index >= 0n ? index / perRecord : (index - perRecord + 1n) / perRecord;
|
|
56
|
+
const sampleWithinRecord = index - recordIndex * perRecord;
|
|
57
|
+
return {
|
|
58
|
+
sampleIndex: Number(index),
|
|
59
|
+
recordIndex: Number(recordIndex),
|
|
60
|
+
sampleWithinRecord: Number(sampleWithinRecord),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* The exact start time of a sample, in 100 ns ticks, elapsed from the start of the recording.
|
|
65
|
+
*
|
|
66
|
+
* Ticks rather than seconds because this is the value worth comparing: a float64 second loses
|
|
67
|
+
* precision past about 28.5 years, and more importantly two times that should be equal can fail
|
|
68
|
+
* to be once both have been divided by ten million.
|
|
69
|
+
*
|
|
70
|
+
* Rounded UP to a whole tick, which matters more than it looks. A sample boundary need not fall
|
|
71
|
+
* on one: 128 samples over 0.3 s puts sample 1 at 23,437.5 ticks, and 100 ns is the finest unit
|
|
72
|
+
* edfcore has. Truncating would return 23,437 — a tick that lies inside sample 0 — so
|
|
73
|
+
* `sampleIndexAt` would send it straight back to the previous sample. Taking the first whole
|
|
74
|
+
* tick at or after the exact start keeps the two functions inverse for every index.
|
|
75
|
+
*/
|
|
76
|
+
export function sampleStartTicks(signal, sampleIndex, recordDurationTicks) {
|
|
77
|
+
assertGrid(signal, recordDurationTicks);
|
|
78
|
+
if (!Number.isSafeInteger(sampleIndex)) {
|
|
79
|
+
throw new RangeError(`sampleStartTicks(): sampleIndex must be a whole number, received ${sampleIndex}.`);
|
|
80
|
+
}
|
|
81
|
+
const perRecord = BigInt(signal.samplesPerRecord);
|
|
82
|
+
const numerator = BigInt(sampleIndex) * recordDurationTicks;
|
|
83
|
+
const quotient = numerator / perRecord;
|
|
84
|
+
// Ceiling for an exact division is the quotient itself; otherwise step to the next tick, and
|
|
85
|
+
// only in the direction away from zero for a negative index.
|
|
86
|
+
if (numerator % perRecord === 0n)
|
|
87
|
+
return quotient;
|
|
88
|
+
return numerator > 0n ? quotient + 1n : quotient;
|
|
89
|
+
}
|
|
90
|
+
/** `sampleStartTicks` in seconds, for display. Compare ticks, not this. */
|
|
91
|
+
export function sampleStartSeconds(signal, sampleIndex, recordDurationTicks) {
|
|
92
|
+
const ticks = sampleStartTicks(signal, sampleIndex, recordDurationTicks);
|
|
93
|
+
const whole = ticks / TICKS_PER_SECOND;
|
|
94
|
+
const remainder = ticks % TICKS_PER_SECOND;
|
|
95
|
+
return Number(whole) + Number(remainder) / Number(TICKS_PER_SECOND);
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=sample-grid.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sample-grid.js","sourceRoot":"","sources":["../src/sample-grid.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -356,6 +356,16 @@ export interface EdfPhysicalEnvelope {
|
|
|
356
356
|
readonly min: Float64Array;
|
|
357
357
|
readonly max: Float64Array;
|
|
358
358
|
}
|
|
359
|
+
export interface FormatHeaderOptions {
|
|
360
|
+
/** Off by default: a header carries a name and a birth date, and a summary gets pasted around. */
|
|
361
|
+
readonly includePatientId?: boolean;
|
|
362
|
+
}
|
|
363
|
+
/** Where a time lands on a signal's own sample grid. */
|
|
364
|
+
export interface EdfSampleLocation {
|
|
365
|
+
readonly sampleIndex: number;
|
|
366
|
+
readonly recordIndex: number;
|
|
367
|
+
readonly sampleWithinRecord: number;
|
|
368
|
+
}
|
|
359
369
|
/** A time window for narrowing annotations already in hand. */
|
|
360
370
|
export interface EdfAnnotationWindow {
|
|
361
371
|
readonly startSeconds: number;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE7E,YAAY,EACV,iBAAiB,EACjB,sBAAsB,EACtB,WAAW,GACZ,MAAM,wBAAwB,CAAC;AAWhC,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC9C,WAAW,IAAI,OAAO,CAAC,WAAW,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE;QAAE,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IACvD,WAAW,IAAI,OAAO,CAAC,WAAW,CAAC,CAAC;CACrC;AAED;;;;;;GAMG;AACH,MAAM,MAAM,SAAS,GAAG,CACtB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,KACvD,OAAO,CAAC,gBAAgB,CAAC,CAAC;AAM/B,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,eAAe,CAAC;IAClC,6EAA6E;IAC7E,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;CACvC;AAED,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,WAAW,CAAC;AAErD;;;;;;GAMG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACjF,KAAK,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,iBAAkB,SAAQ,WAAW;IACpD,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACpD,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC;0DACsD;IACtD,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;CACtC;AAED,MAAM,WAAW,YAAY;IAC3B;;;yDAGqD;IACrD,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,kCAAkC;IAClC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAMD,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,OAAO,GAAG,OAAO,GAAG,KAAK,GAAG,OAAO,GAAG,OAAO,CAAC;AAE/E,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,0CAA0C;IAC1C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,oEAAoE;IACpE,QAAQ,CAAC,UAAU,EAAE,eAAe,GAAG,SAAS,CAAC;IACjD;uDACmD;IACnD,QAAQ,CAAC,eAAe,EAAE,eAAe,GAAG,SAAS,CAAC;IACtD,QAAQ,CAAC,YAAY,EAAE,eAAe,GAAG,SAAS,CAAC;IACnD,QAAQ,CAAC,UAAU,EAAE,aAAa,GAAG,kBAAkB,GAAG,MAAM,CAAC;IACjE,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;CACvC;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,SAAS,EAAE,eAAe,GAAG,SAAS,CAAC;IAChD,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5C;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,eAAe,GAAG,SAAS,CAAC;IAChD,QAAQ,CAAC,iBAAiB,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/C,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5C;AAED;;;;;;GAMG;AACH,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,yEAAyE;AACzE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CAAC;IACtC,8CAA8C;IAC9C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,8EAA8E;IAC9E,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,qFAAqF;IACrF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC;oCACgC;IAChC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,8DAA8D;IAC9D,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC;+BAC2B;IAC3B,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B;;mEAE+D;IAC/D,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,SAAS,CAAC;IACrC,iEAAiE;IACjE,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,GAAG,EAAE,kBAAkB,CAAC;CAClC;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,YAAY,GAAG,eAAe,CAAC;IACpD,QAAQ,CAAC,cAAc,EAAE,CAAC,GAAG,CAAC,CAAC;IAC/B,sEAAsE;IACtE,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,4EAA4E;IAC5E,QAAQ,CAAC,wBAAwB,EAAE,MAAM,CAAC;IAC1C,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,uDAAuD;IACvD,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,iCAAiC;IACjC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,6DAA6D;IAC7D,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,iBAAiB,EAAE,aAAa,GAAG,kBAAkB,CAAC;IAC/D,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAC;IACnC,QAAQ,CAAC,OAAO,EAAE,SAAS,SAAS,EAAE,CAAC;IACvC,QAAQ,CAAC,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9C,QAAQ,CAAC,uBAAuB,EAAE,SAAS,MAAM,EAAE,CAAC;IACpD,4CAA4C;IAC5C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,GAAG,EAAE,kBAAkB,CAAC;IACjC,sDAAsD;IACtD,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,SAAS,aAAa,EAAE,CAAC;CAChD;AAMD,yFAAyF;AACzF,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CAClC;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;CACxC;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC,yEAAyE;IACzE,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,+DAA+D;IAC/D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,yFAAyF;IACzF,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,WAAW,EAAE,SAAS,aAAa,EAAE,CAAC;CAChD;AAED,MAAM,WAAW,cAAc;IAC7B,wFAAwF;IACxF,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,UAAU,CAAC;IACzC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B;iFAC6E;IAC7E,QAAQ,CAAC,QAAQ,EAAE,SAAS,UAAU,EAAE,GAAG,SAAS,CAAC;IACrD,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IAC7C,sEAAsE;IACtE,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACxE,wFAAwF;IACxF,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAAC;CAClF;AAED,MAAM,WAAW,iBAAkB,SAAQ,YAAY,EAAE,WAAW;IAClE,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7D;AAMD,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,iDAAiD;IACjD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,kEAAkE;IAClE,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC;;oFAEgF;IAChF,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B;4DACwD;IACxD,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;CACzC;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,wFAAwF;IACxF,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,SAAS,cAAc,EAAE,CAAC;IAC5C,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,QAAQ,CAAC,WAAW,EAAE,SAAS,aAAa,EAAE,CAAC;CAChD;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,+FAA+F;IAC/F,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC;IACzB,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC;IACzB,4FAA4F;IAC5F,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,uDAAuD;IACvD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;CACzC;AAED,oGAAoG;AACpG,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,qFAAqF;IACrF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC/C,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,QAAQ,CAAC,WAAW,EAAE,SAAS,aAAa,EAAE,CAAC;CAChD;AAED,MAAM,WAAW,iBAAkB,SAAQ,eAAe;IACxD;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,mGAAmG;AACnG,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC;IAC3B,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC;CAC5B;AAED,+DAA+D;AAC/D,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CAClC;AAED,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,8FAA8F;IAC9F,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,oFAAoF;AACpF,MAAM,WAAW,aAAa;IAC5B,wEAAwE;IACxE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,mDAAmD;IACnD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;CAC9B;AAED,mFAAmF;AACnF,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,uEAAuE;IACvE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;CAChC;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CAClC;AAED,MAAM,WAAW,aAAa;IAC5B,uFAAuF;IACvF,QAAQ,CAAC,2BAA2B,EAAE,MAAM,CAAC;IAC7C,qFAAqF;IACrF,QAAQ,CAAC,2BAA2B,EAAE,MAAM,CAAC;IAC7C,oFAAoF;IACpF,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,uEAAuE;IACvE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7C,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,kDAAkD;IAClD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,uDAAuD;IACvD,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,YAAY,EAAE,OAAO,GAAG,kBAAkB,CAAC;CACrD;AAED,MAAM,WAAW,oBAAoB;IACnC;yDACqD;IACrD,QAAQ,CAAC,WAAW,EAAE,SAAS,aAAa,EAAE,CAAC;IAC/C;sBACkB;IAClB,QAAQ,CAAC,gBAAgB,EAAE,aAAa,CAAC;IACzC,QAAQ,CAAC,WAAW,EAAE,SAAS,aAAa,EAAE,CAAC;CAChD;AAMD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,wFAAwF;IACxF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,QAAQ,EAAE,UAAU,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC;sDACkD;IAClD,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5C;AAMD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;CAChC;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B;qDACiD;IACjD,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3C;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3C;AAED,MAAM,WAAW,wBAAyB,SAAQ,YAAY;IAC5D,+EAA+E;IAC/E,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,uFAAuF;AACvF,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,UAAU,GAAG,SAAS,CAAC;IAC7C,QAAQ,CAAC,WAAW,EAAE,SAAS,aAAa,EAAE,CAAC;CAChD;AAMD,MAAM,WAAW,eAAgB,SAAQ,WAAW;IAClD,2EAA2E;IAC3E,QAAQ,CAAC,KAAK,CAAC,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7D;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;IACxC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,WAAW,EAAE,SAAS,aAAa,EAAE,CAAC;IAC/C,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,SAAS,mBAAmB,EAAE,CAAC;CACtD"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/constants.ts
CHANGED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A header as text.
|
|
3
|
+
*
|
|
4
|
+
* Layer 7, and pure. `formatDiagnostics` already turns problems into something a human reads;
|
|
5
|
+
* this does the same for the header itself — the thing that goes into a bug report, a CLI, or a
|
|
6
|
+
* log line when a file behaves oddly.
|
|
7
|
+
*
|
|
8
|
+
* Two rules keep it useful rather than decorative. It never invents a value: a field edfcore
|
|
9
|
+
* could not resolve prints as `unknown` rather than as a plausible default, because the whole
|
|
10
|
+
* point of pasting this somewhere is that the reader can trust it. And it prints no patient
|
|
11
|
+
* identification unless asked — a header carries a name and a birth date, and a summary that
|
|
12
|
+
* lands in a chat log or an issue tracker should not carry them by default.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import type { EdfCalendarDate, EdfHeader, FormatHeaderOptions } from './types.js';
|
|
16
|
+
|
|
17
|
+
function formatDate(date: EdfCalendarDate | undefined): string {
|
|
18
|
+
if (date === undefined) return 'unknown';
|
|
19
|
+
const month = String(date.month).padStart(2, '0');
|
|
20
|
+
const day = String(date.day).padStart(2, '0');
|
|
21
|
+
return `${date.year}-${month}-${day}`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function formatDuration(seconds: number): string {
|
|
25
|
+
if (!Number.isFinite(seconds) || seconds < 0) return 'unknown';
|
|
26
|
+
const whole = Math.floor(seconds);
|
|
27
|
+
const hours = Math.floor(whole / 3600);
|
|
28
|
+
const minutes = Math.floor((whole % 3600) / 60);
|
|
29
|
+
const rest = whole % 60;
|
|
30
|
+
const pad = (n: number): string => String(n).padStart(2, '0');
|
|
31
|
+
return `${pad(hours)}:${pad(minutes)}:${pad(rest)}`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function formatRate(signal: EdfHeader['signals'][number]): string {
|
|
35
|
+
// undefined is the honest answer for a zero record duration, which is legal EDF.
|
|
36
|
+
return signal.sampleRateHz === undefined ? '—' : `${signal.sampleRateHz} Hz`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* A multi-line summary of a header.
|
|
41
|
+
*
|
|
42
|
+
* Patient identification is omitted unless `includePatientId` is set. That is not a privacy
|
|
43
|
+
* feature — the data is still in `header.patient` for anyone who wants it — it is a default
|
|
44
|
+
* chosen so that the obvious thing to do with this string is also the safe one.
|
|
45
|
+
*/
|
|
46
|
+
export function formatHeader(header: EdfHeader, options?: FormatHeaderOptions): string {
|
|
47
|
+
const lines: string[] = [];
|
|
48
|
+
const start = header.startTime;
|
|
49
|
+
|
|
50
|
+
lines.push(
|
|
51
|
+
`${header.variant} · ${header.signals.length} signals · ${header.recordCount} records`,
|
|
52
|
+
);
|
|
53
|
+
lines.push(
|
|
54
|
+
`start ${formatDate(start.resolvedDate)} ${String(start.clock.hour).padStart(2, '0')}:` +
|
|
55
|
+
`${String(start.clock.minute).padStart(2, '0')}:${String(start.clock.second).padStart(2, '0')}` +
|
|
56
|
+
` (local, no timezone)`,
|
|
57
|
+
);
|
|
58
|
+
lines.push(
|
|
59
|
+
`record ${header.recordDurationSeconds} s · ${header.recordByteLength} bytes · ` +
|
|
60
|
+
`${header.bytesPerSample} bytes/sample`,
|
|
61
|
+
);
|
|
62
|
+
lines.push(
|
|
63
|
+
`duration ${formatDuration(header.recordCount * header.recordDurationSeconds)} ` +
|
|
64
|
+
`(${header.recordCount} × ${header.recordDurationSeconds} s)`,
|
|
65
|
+
);
|
|
66
|
+
if (header.recordCountSource === 'sourceByteLength') {
|
|
67
|
+
// Worth saying out loud: the count came from the file size, not from the header field.
|
|
68
|
+
lines.push(' record count recovered from the source length');
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (options?.includePatientId === true) {
|
|
72
|
+
lines.push(`patient ${header.patient.raw.trim() || 'unknown'}`);
|
|
73
|
+
lines.push(`recording ${header.recording.raw.trim() || 'unknown'}`);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
lines.push('');
|
|
77
|
+
lines.push(' # label kind rate range');
|
|
78
|
+
for (const signal of header.signals) {
|
|
79
|
+
const index = String(signal.index).padStart(3);
|
|
80
|
+
const label = signal.label.slice(0, 20).padEnd(21);
|
|
81
|
+
const kind = signal.kind.padEnd(12);
|
|
82
|
+
const rate = formatRate(signal).padEnd(9);
|
|
83
|
+
const range =
|
|
84
|
+
signal.kind === 'annotations'
|
|
85
|
+
? '—'
|
|
86
|
+
: signal.scale === undefined
|
|
87
|
+
? 'no usable scale'
|
|
88
|
+
: `${signal.physicalMinimum}..${signal.physicalMaximum} ${signal.physicalDimension}`;
|
|
89
|
+
lines.push(`${index} ${label}${kind}${rate} ${range}`);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (header.diagnostics.length > 0) {
|
|
93
|
+
lines.push('');
|
|
94
|
+
const counts = new Map<string, number>();
|
|
95
|
+
for (const diagnostic of header.diagnostics) {
|
|
96
|
+
counts.set(diagnostic.severity, (counts.get(diagnostic.severity) ?? 0) + 1);
|
|
97
|
+
}
|
|
98
|
+
const summary = [...counts].map(([severity, count]) => `${count} ${severity}`).join(', ');
|
|
99
|
+
lines.push(`${header.diagnostics.length} diagnostic(s): ${summary}`);
|
|
100
|
+
lines.push('Call formatDiagnostics(header.diagnostics) for the detail.');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return lines.join('\n');
|
|
104
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -58,6 +58,7 @@ export type {
|
|
|
58
58
|
EdfRecordIndex,
|
|
59
59
|
EdfRecording,
|
|
60
60
|
EdfRecordingId,
|
|
61
|
+
EdfSampleLocation,
|
|
61
62
|
EdfScale,
|
|
62
63
|
EdfSegment,
|
|
63
64
|
EdfSeverity,
|
|
@@ -69,6 +70,7 @@ export type {
|
|
|
69
70
|
EdfVariant,
|
|
70
71
|
EnvelopeSelection,
|
|
71
72
|
FetchLike,
|
|
73
|
+
FormatHeaderOptions,
|
|
72
74
|
HttpResponseLike,
|
|
73
75
|
HttpSourceOptions,
|
|
74
76
|
OpenOptions,
|
|
@@ -163,6 +165,12 @@ export {
|
|
|
163
165
|
} from './annotations-query.js';
|
|
164
166
|
export { decodeStatusWord, getStatusSignal, readTriggers } from './biosemi.js';
|
|
165
167
|
export { envelopeOfSamples, readEnvelope, toPhysicalEnvelope } from './envelope.js';
|
|
168
|
+
export { formatHeader } from './format-header.js';
|
|
166
169
|
export { inspectEdf } from './inspect.js';
|
|
167
170
|
export { openEdf, readAnnotations, readRecords, readWindow } from './recording.js';
|
|
171
|
+
export {
|
|
172
|
+
sampleIndexAt,
|
|
173
|
+
sampleStartSeconds,
|
|
174
|
+
sampleStartTicks,
|
|
175
|
+
} from './sample-grid.js';
|
|
168
176
|
export { streamRecords } from './stream.js';
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Time to sample index, and back.
|
|
3
|
+
*
|
|
4
|
+
* Layer 7, and pure. Every viewer needs this and the obvious spelling is wrong:
|
|
5
|
+
* `Math.round(seconds * signal.sampleRateHz)`.
|
|
6
|
+
*
|
|
7
|
+
* Three things break it. `sampleRateHz` is `samplesPerRecord / recordDurationSeconds`, so for a
|
|
8
|
+
* record duration that is not a power of ten it is a float with no exact representation —
|
|
9
|
+
* 128 samples over 0.3 s is 426.666..., and multiplying by a large `seconds` accumulates the
|
|
10
|
+
* error until the index is off by one. `sampleRateHz` is also `undefined` when the record
|
|
11
|
+
* duration is zero, which is legal EDF and which a real sleep-staging file relies on, so the
|
|
12
|
+
* expression silently yields `NaN`. And a recording does not start at zero: onsets are relative
|
|
13
|
+
* to record 0's own start, which is what every other time in edfcore is measured from.
|
|
14
|
+
*
|
|
15
|
+
* These do the arithmetic in integers on `(record, sampleWithinRecord)` instead, which is the
|
|
16
|
+
* same rule `trimToWindow` follows.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { TICKS_PER_SECOND } from './constants.js';
|
|
20
|
+
import { secondsToTicks } from './tal/ticks.js';
|
|
21
|
+
import type { EdfSampleLocation, EdfSignal } from './types.js';
|
|
22
|
+
|
|
23
|
+
function assertGrid(signal: EdfSignal, recordDurationTicks: bigint): void {
|
|
24
|
+
if (signal.kind === 'annotations') {
|
|
25
|
+
throw new RangeError(
|
|
26
|
+
`signal ${signal.index} (${JSON.stringify(signal.label)}) is an annotations channel, ` +
|
|
27
|
+
'whose region holds TAL text rather than samples, so it has no sample grid. Next: use ' +
|
|
28
|
+
'onsetTicks on the annotations themselves.',
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
if (signal.samplesPerRecord <= 0) {
|
|
32
|
+
throw new RangeError(
|
|
33
|
+
`signal ${signal.index} (${JSON.stringify(signal.label)}) declares ` +
|
|
34
|
+
`${signal.samplesPerRecord} samples per record, so it has no sample grid to index. ` +
|
|
35
|
+
'Next: check header.diagnostics for ZERO_SAMPLES_PER_RECORD.',
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
if (recordDurationTicks <= 0n) {
|
|
39
|
+
throw new RangeError(
|
|
40
|
+
'this file declares a record duration of zero, so records do not advance in time and no ' +
|
|
41
|
+
'elapsed time maps to a sample. This is legal EDF and a scoring file relies on it. ' +
|
|
42
|
+
'Next: index by record with readRecords().',
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* The sample covering `seconds` elapsed from the start of the recording.
|
|
49
|
+
*
|
|
50
|
+
* Floor, not round: a sample covers the half-open interval from its own start to the next one's,
|
|
51
|
+
* so the sample "at" a time is the one whose interval contains it. Rounding would return the
|
|
52
|
+
* NEXT sample for anything past the halfway point, which puts a window boundary one sample late.
|
|
53
|
+
*/
|
|
54
|
+
export function sampleIndexAt(
|
|
55
|
+
signal: EdfSignal,
|
|
56
|
+
seconds: number,
|
|
57
|
+
recordDurationTicks: bigint,
|
|
58
|
+
): EdfSampleLocation {
|
|
59
|
+
assertGrid(signal, recordDurationTicks);
|
|
60
|
+
|
|
61
|
+
const ticks = secondsToTicks(seconds);
|
|
62
|
+
const perRecord = BigInt(signal.samplesPerRecord);
|
|
63
|
+
// Exact integer arithmetic throughout: ticks * samplesPerRecord / recordDurationTicks, floored
|
|
64
|
+
// toward negative infinity so a time before the start yields a negative index rather than
|
|
65
|
+
// truncating toward zero and colliding with sample 0.
|
|
66
|
+
const numerator = ticks * perRecord;
|
|
67
|
+
let index = numerator / recordDurationTicks;
|
|
68
|
+
if (numerator % recordDurationTicks !== 0n && numerator < 0n) index -= 1n;
|
|
69
|
+
|
|
70
|
+
const recordIndex = index >= 0n ? index / perRecord : (index - perRecord + 1n) / perRecord;
|
|
71
|
+
const sampleWithinRecord = index - recordIndex * perRecord;
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
sampleIndex: Number(index),
|
|
75
|
+
recordIndex: Number(recordIndex),
|
|
76
|
+
sampleWithinRecord: Number(sampleWithinRecord),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* The exact start time of a sample, in 100 ns ticks, elapsed from the start of the recording.
|
|
82
|
+
*
|
|
83
|
+
* Ticks rather than seconds because this is the value worth comparing: a float64 second loses
|
|
84
|
+
* precision past about 28.5 years, and more importantly two times that should be equal can fail
|
|
85
|
+
* to be once both have been divided by ten million.
|
|
86
|
+
*
|
|
87
|
+
* Rounded UP to a whole tick, which matters more than it looks. A sample boundary need not fall
|
|
88
|
+
* on one: 128 samples over 0.3 s puts sample 1 at 23,437.5 ticks, and 100 ns is the finest unit
|
|
89
|
+
* edfcore has. Truncating would return 23,437 — a tick that lies inside sample 0 — so
|
|
90
|
+
* `sampleIndexAt` would send it straight back to the previous sample. Taking the first whole
|
|
91
|
+
* tick at or after the exact start keeps the two functions inverse for every index.
|
|
92
|
+
*/
|
|
93
|
+
export function sampleStartTicks(
|
|
94
|
+
signal: EdfSignal,
|
|
95
|
+
sampleIndex: number,
|
|
96
|
+
recordDurationTicks: bigint,
|
|
97
|
+
): bigint {
|
|
98
|
+
assertGrid(signal, recordDurationTicks);
|
|
99
|
+
if (!Number.isSafeInteger(sampleIndex)) {
|
|
100
|
+
throw new RangeError(
|
|
101
|
+
`sampleStartTicks(): sampleIndex must be a whole number, received ${sampleIndex}.`,
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
const perRecord = BigInt(signal.samplesPerRecord);
|
|
105
|
+
const numerator = BigInt(sampleIndex) * recordDurationTicks;
|
|
106
|
+
const quotient = numerator / perRecord;
|
|
107
|
+
// Ceiling for an exact division is the quotient itself; otherwise step to the next tick, and
|
|
108
|
+
// only in the direction away from zero for a negative index.
|
|
109
|
+
if (numerator % perRecord === 0n) return quotient;
|
|
110
|
+
return numerator > 0n ? quotient + 1n : quotient;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** `sampleStartTicks` in seconds, for display. Compare ticks, not this. */
|
|
114
|
+
export function sampleStartSeconds(
|
|
115
|
+
signal: EdfSignal,
|
|
116
|
+
sampleIndex: number,
|
|
117
|
+
recordDurationTicks: bigint,
|
|
118
|
+
): number {
|
|
119
|
+
const ticks = sampleStartTicks(signal, sampleIndex, recordDurationTicks);
|
|
120
|
+
const whole = ticks / TICKS_PER_SECOND;
|
|
121
|
+
const remainder = ticks % TICKS_PER_SECOND;
|
|
122
|
+
return Number(whole) + Number(remainder) / Number(TICKS_PER_SECOND);
|
|
123
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -420,6 +420,18 @@ export interface EdfPhysicalEnvelope {
|
|
|
420
420
|
readonly max: Float64Array;
|
|
421
421
|
}
|
|
422
422
|
|
|
423
|
+
export interface FormatHeaderOptions {
|
|
424
|
+
/** Off by default: a header carries a name and a birth date, and a summary gets pasted around. */
|
|
425
|
+
readonly includePatientId?: boolean;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/** Where a time lands on a signal's own sample grid. */
|
|
429
|
+
export interface EdfSampleLocation {
|
|
430
|
+
readonly sampleIndex: number;
|
|
431
|
+
readonly recordIndex: number;
|
|
432
|
+
readonly sampleWithinRecord: number;
|
|
433
|
+
}
|
|
434
|
+
|
|
423
435
|
/** A time window for narrowing annotations already in hand. */
|
|
424
436
|
export interface EdfAnnotationWindow {
|
|
425
437
|
readonly startSeconds: number;
|