edfcore 0.1.6 → 0.1.8

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/src/index.ts CHANGED
@@ -43,12 +43,15 @@ export type {
43
43
  EdfClockTime,
44
44
  EdfDiagnostic,
45
45
  EdfDiagnosticCode,
46
+ EdfEnvelopeChunk,
47
+ EdfEnvelopeSignal,
46
48
  EdfGap,
47
49
  EdfHeader,
48
50
  EdfInspection,
49
51
  EdfKnownDiagnosticCode,
50
52
  EdfLocation,
51
53
  EdfPatientId,
54
+ EdfPhysicalEnvelope,
52
55
  EdfRawHeaderFields,
53
56
  EdfRawSignalFields,
54
57
  EdfRecordIndex,
@@ -59,8 +62,11 @@ export type {
59
62
  EdfSeverity,
60
63
  EdfSignal,
61
64
  EdfStartTime,
65
+ EdfStatusWord,
62
66
  EdfTimeline,
67
+ EdfTriggerEvent,
63
68
  EdfVariant,
69
+ EnvelopeSelection,
64
70
  FetchLike,
65
71
  HttpResponseLike,
66
72
  HttpSourceOptions,
@@ -69,6 +75,7 @@ export type {
69
75
  ReadOptions,
70
76
  RecordRange,
71
77
  RecordSelection,
78
+ TriggerSelection,
72
79
  WindowSelection,
73
80
  } from './types.js';
74
81
 
@@ -147,5 +154,7 @@ export { buildRecordIndex, buildTimeline } from './record-index.js';
147
154
  // Convenience layer
148
155
  // ===========================================================================
149
156
 
157
+ export { decodeStatusWord, getStatusSignal, readTriggers } from './biosemi.js';
158
+ export { envelopeOfSamples, readEnvelope, toPhysicalEnvelope } from './envelope.js';
150
159
  export { inspectEdf } from './inspect.js';
151
160
  export { openEdf, readAnnotations, readRecords, readWindow } from './recording.js';
package/src/types.ts CHANGED
@@ -367,6 +367,85 @@ export interface EdfChunk {
367
367
  readonly diagnostics: readonly EdfDiagnostic[];
368
368
  }
369
369
 
370
+ /**
371
+ * One signal's min/max envelope over a window, at a resolution the caller chose.
372
+ *
373
+ * The unit is the bucket, not the sample: `min[i]` and `max[i]` are the extremes of every sample
374
+ * that fell in bucket `i`. Drawing a twelve-hour recording into a thousand pixels needs exactly
375
+ * this and nothing else — the peaks are what a reader of an EEG trace is looking at, and they
376
+ * are the first thing naive subsampling throws away.
377
+ */
378
+ export interface EdfEnvelopeSignal {
379
+ readonly signalIndex: number;
380
+ /** Digital extremes per bucket. Convert with `toPhysicalEnvelope`, never with `toPhysical`. */
381
+ readonly min: Int32Array;
382
+ readonly max: Int32Array;
383
+ /** Samples that landed in each bucket. Zero where the window had no samples to cover it. */
384
+ readonly counts: Int32Array;
385
+ /** Total samples reduced, i.e. the sum of `counts`. */
386
+ readonly sampleCount: number;
387
+ readonly firstSampleIndex: number;
388
+ readonly startSeconds: number;
389
+ readonly outOfDigitalRangeCount: number;
390
+ }
391
+
392
+ /** A contiguous run of records, reduced to buckets. One per run, exactly as `readWindow` splits. */
393
+ export interface EdfEnvelopeChunk {
394
+ readonly records: RecordRange;
395
+ readonly startSeconds: number;
396
+ readonly durationSeconds: number;
397
+ /** Buckets actually filled. Never more than requested, and fewer for a short run. */
398
+ readonly bucketCount: number;
399
+ readonly secondsPerBucket: number;
400
+ readonly byteLength: number;
401
+ readonly signals: readonly EdfEnvelopeSignal[];
402
+ readonly precededByGap: EdfGap | undefined;
403
+ readonly diagnostics: readonly EdfDiagnostic[];
404
+ }
405
+
406
+ export interface EnvelopeSelection extends WindowSelection {
407
+ /**
408
+ * How many buckets to reduce the window into — in a viewer, the pixel width of the plot.
409
+ *
410
+ * A bucket per pixel is the point: asking for more buckets than the window has samples wastes
411
+ * work and yields empty buckets, so the count is clamped to the sample count of the densest
412
+ * signal in the run.
413
+ */
414
+ readonly buckets: number;
415
+ }
416
+
417
+ /** A physical-unit envelope. Separate from the digital one for the same reason `toPhysical` is. */
418
+ export interface EdfPhysicalEnvelope {
419
+ readonly min: Float64Array;
420
+ readonly max: Float64Array;
421
+ }
422
+
423
+ /** One decoded BioSemi Status sample. Only the bits BioSemi documents are named. */
424
+ export interface EdfStatusWord {
425
+ /** All 24 bits, unsigned. Decode rig-specific conventions from this. */
426
+ readonly raw: number;
427
+ /** The parallel trigger input: the low 16 bits. */
428
+ readonly trigger: number;
429
+ readonly newEpoch: boolean;
430
+ readonly cmsInRange: boolean;
431
+ readonly batteryLow: boolean;
432
+ }
433
+
434
+ /** A change of the trigger word, timed on the Status channel's own sample grid. */
435
+ export interface EdfTriggerEvent {
436
+ readonly sampleIndex: number;
437
+ readonly seconds: number;
438
+ /** Exact, in 100 ns units. Compare with this, never with the float. */
439
+ readonly ticks: bigint;
440
+ readonly trigger: number;
441
+ readonly status: EdfStatusWord;
442
+ }
443
+
444
+ export interface TriggerSelection {
445
+ readonly startSeconds: number;
446
+ readonly durationSeconds: number;
447
+ }
448
+
370
449
  export interface EdfAnnotation {
371
450
  /** Verbatim on-disk value, relative to the header startdate/starttime (EDF+ 2.2.4). */
372
451
  readonly onsetSecondsFromHeaderStart: number;