edfcore 0.6.25 → 0.6.26

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.
@@ -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.6.25";
112
+ export declare const VERSION = "0.6.26";
113
113
  //# sourceMappingURL=constants.d.ts.map
package/dist/constants.js CHANGED
@@ -79,5 +79,5 @@ export const SIGNAL_FIELD_BLOCK_OFFSETS = {
79
79
  reserved: 224,
80
80
  };
81
81
  /** Published package version. Kept in sync with package.json by a test. */
82
- export const VERSION = '0.6.25';
82
+ export const VERSION = '0.6.26';
83
83
  //# sourceMappingURL=constants.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"variant.d.ts","sourceRoot":"","sources":["../../src/header/variant.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAcH,OAAO,EAAE,KAAK,cAAc,EAAc,MAAM,6BAA6B,CAAC;AAC9E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAW9C;;;;GAIG;AACH,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,KAAK,CAAC;AAEtC,8FAA8F;AAC9F,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAUhF;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,qFAAqF;IACrF,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,cAAc,EAAE,CAAC,GAAG,CAAC,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,YAAY,GAAG,eAAe,CAAC;IACpD;uFACmF;IACnF,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB;wBACoB;IACpB,QAAQ,CAAC,cAAc,EAAE,iBAAiB,GAAG,SAAS,CAAC;IACvD,gEAAgE;IAChE,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,kFAAkF;IAClF,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;CACtC;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,UAAU,GAAG,OAAO,CAOnE;AAED,iGAAiG;AACjG,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,UAAU,GAAG,OAAO,CAMnE;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS,CAKhF;AAgBD;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,UAAU,EAAE,IAAI,EAAE,cAAc,GAAG,cAAc,CAgG3F"}
1
+ {"version":3,"file":"variant.d.ts","sourceRoot":"","sources":["../../src/header/variant.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAcH,OAAO,EAAE,KAAK,cAAc,EAAc,MAAM,6BAA6B,CAAC;AAC9E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAW9C;;;;GAIG;AACH,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,KAAK,CAAC;AAEtC,8FAA8F;AAC9F,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAUhF;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,qFAAqF;IACrF,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,cAAc,EAAE,CAAC,GAAG,CAAC,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,YAAY,GAAG,eAAe,CAAC;IACpD;uFACmF;IACnF,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB;wBACoB;IACpB,QAAQ,CAAC,cAAc,EAAE,iBAAiB,GAAG,SAAS,CAAC;IACvD,gEAAgE;IAChE,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,kFAAkF;IAClF,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;CACtC;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,UAAU,GAAG,OAAO,CAOnE;AAED,iGAAiG;AACjG,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,UAAU,GAAG,OAAO,CAMnE;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS,CAKhF;AA8CD;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,UAAU,EAAE,IAAI,EAAE,cAAc,GAAG,cAAc,CAqG3F"}
@@ -70,6 +70,35 @@ export function reservedMarkerOf(reserved) {
70
70
  }
71
71
  return undefined;
72
72
  }
73
+ /**
74
+ * The containers whose first bytes are already in hand when `NOT_AN_EDF_FILE` is thrown.
75
+ *
76
+ * That message's `Next:` clause has always said "a gzip, zip or vendor container has to be
77
+ * unpacked before edfcore sees it" — a menu, offered while holding the two bytes that say which
78
+ * one it is. `1f 8b` is a gzip and nothing else, and a reader who has just been handed the hex is
79
+ * being asked to look it up.
80
+ *
81
+ * Only the archive formats, and only by their magic number. Naming a container is a fact about the
82
+ * first bytes; guessing at a vendor's binary EEG format from the same two bytes would be a claim
83
+ * about the whole file, and the generic clause still covers those.
84
+ */
85
+ const CONTAINERS = [
86
+ ['a gzip', [0x1f, 0x8b]],
87
+ ['a zip', [0x50, 0x4b, 0x03, 0x04]],
88
+ ['an empty zip', [0x50, 0x4b, 0x05, 0x06]],
89
+ ['a bzip2', [0x42, 0x5a, 0x68]],
90
+ ['an xz', [0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00]],
91
+ ['a zstd', [0x28, 0xb5, 0x2f, 0xfd]],
92
+ ['a 7-Zip archive', [0x37, 0x7a, 0xbc, 0xaf, 0x27, 0x1c]],
93
+ ];
94
+ /** The container these bytes begin with, or `undefined` — which is most files. */
95
+ function containerAt(bytes) {
96
+ for (const [name, magic] of CONTAINERS) {
97
+ if (magic.every((byte, at) => bytes[at] === byte))
98
+ return name;
99
+ }
100
+ return undefined;
101
+ }
73
102
  function markerFamily(marker) {
74
103
  return marker === 'EDF+C' || marker === 'EDF+D' ? 'EDF' : 'BDF';
75
104
  }
@@ -98,14 +127,19 @@ export function detectVariant(headerBytes, sink) {
98
127
  const isEdf = !isBdf && isEdfVersionBlock(versionBytes);
99
128
  if (!isBdf && !isEdf) {
100
129
  const raw = readAsciiField(headerBytes, HEADER_FIELDS.version.offset, HEADER_FIELDS.version.length);
130
+ const container = containerAt(headerBytes);
101
131
  throw fatalError({
102
132
  code: 'NOT_AN_EDF_FILE',
103
133
  message: `version field (8 bytes at offset ${HEADER_FIELDS.version.offset}) is ` +
104
134
  `${JSON.stringify(raw)}, bytes ${hexBytes(versionBytes)}: this is neither EDF's ` +
105
135
  `"0" followed by seven spaces nor BDF's 0xff followed by "BIOSEMI". ` +
136
+ (container === undefined ? '' : `Those first bytes are ${container}. `) +
106
137
  'EDF specification, header record bytes 0-7 (version of this data format). ' +
107
- 'Next: confirm the bytes are an uncompressed EDF or BDF recording — a gzip, zip or ' +
108
- 'vendor container has to be unpacked before edfcore sees it.',
138
+ (container === undefined
139
+ ? 'Next: confirm the bytes are an uncompressed EDF or BDF recording — a gzip, zip or ' +
140
+ 'vendor container has to be unpacked before edfcore sees it.'
141
+ : `Next: unpack ${container} and open the EDF or BDF file inside it — edfcore reads ` +
142
+ 'recordings, not archives.'),
109
143
  field: 'version',
110
144
  byteOffset: HEADER_FIELDS.version.offset,
111
145
  byteLength: HEADER_FIELDS.version.length,
@@ -1 +1 @@
1
- {"version":3,"file":"variant.js","sourceRoot":"","sources":["../../src/header/variant.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"variant.js","sourceRoot":"","sources":["../../src/header/variant.ts"],"names":[],"mappings":"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"}
package/docs/CHANGELOG.md CHANGED
@@ -6,6 +6,24 @@ alone does not tell you whether you were affected.
6
6
  edfcore is pre-1.0. Patch releases have carried behaviour changes where the old behaviour was a
7
7
  defect; those are called out below.
8
8
 
9
+ ## 0.6.26
10
+
11
+ - **Changed** `NOT_AN_EDF_FILE` to say which archive it was handed, when the first bytes say so.
12
+ That message's `Next:` clause has always read "a gzip, zip or vendor container has to be unpacked
13
+ before edfcore sees it" — a menu, offered on the same line as the hex that answers it. `1f 8b` is
14
+ a gzip and nothing else, and the message printed those bytes and asked the reader to look them up.
15
+ - It is also the likeliest first meeting with this package. Recordings travel compressed —
16
+ PhysioNet ships `.zip`, teuniz.net ships `.zip`, a shared study arrives as `.gz` — so pointing
17
+ edfcore at the download rather than at what is inside it is the ordinary mistake, not an exotic
18
+ one. `edfcore header study.edf.gz` now says it is a gzip and to unpack it.
19
+ - Seven magic numbers: gzip, zip, an empty zip, bzip2, xz, zstd and 7-Zip. Archive formats only,
20
+ and only by magic number — naming a container is a fact about the first bytes, while guessing a
21
+ vendor's binary EEG format from two of them would be a claim about the whole file. Everything
22
+ unrecognised keeps the general advice, which `it-says-which-container.test.ts` checks with bytes
23
+ chosen to sit one value away from a magic number, because a table that matched everything would
24
+ be worse than the menu.
25
+ - Same code, same field, same bytes, same `Next:` shape. A program branching on `code` sees nothing.
26
+
9
27
  ## 0.6.25
10
28
 
11
29
  - **Fixed** an event listing losing its columns to a time wider than twelve characters.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "edfcore",
3
- "version": "0.6.25",
3
+ "version": "0.6.26",
4
4
  "description": "Modern, typed, zero-dependency reader for EDF, EDF+, BDF and BDF+ biosignal files. Works in browsers and Node with true random access.",
5
5
  "keywords": [
6
6
  "edf",
package/src/constants.ts CHANGED
@@ -93,4 +93,4 @@ export const SIGNAL_FIELD_BLOCK_OFFSETS = {
93
93
  } as const;
94
94
 
95
95
  /** Published package version. Kept in sync with package.json by a test. */
96
- export const VERSION = '0.6.25';
96
+ export const VERSION = '0.6.26';
@@ -116,6 +116,36 @@ export function reservedMarkerOf(reserved: string): EdfReservedMarker | undefine
116
116
  return undefined;
117
117
  }
118
118
 
119
+ /**
120
+ * The containers whose first bytes are already in hand when `NOT_AN_EDF_FILE` is thrown.
121
+ *
122
+ * That message's `Next:` clause has always said "a gzip, zip or vendor container has to be
123
+ * unpacked before edfcore sees it" — a menu, offered while holding the two bytes that say which
124
+ * one it is. `1f 8b` is a gzip and nothing else, and a reader who has just been handed the hex is
125
+ * being asked to look it up.
126
+ *
127
+ * Only the archive formats, and only by their magic number. Naming a container is a fact about the
128
+ * first bytes; guessing at a vendor's binary EEG format from the same two bytes would be a claim
129
+ * about the whole file, and the generic clause still covers those.
130
+ */
131
+ const CONTAINERS: ReadonlyArray<readonly [string, readonly number[]]> = [
132
+ ['a gzip', [0x1f, 0x8b]],
133
+ ['a zip', [0x50, 0x4b, 0x03, 0x04]],
134
+ ['an empty zip', [0x50, 0x4b, 0x05, 0x06]],
135
+ ['a bzip2', [0x42, 0x5a, 0x68]],
136
+ ['an xz', [0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00]],
137
+ ['a zstd', [0x28, 0xb5, 0x2f, 0xfd]],
138
+ ['a 7-Zip archive', [0x37, 0x7a, 0xbc, 0xaf, 0x27, 0x1c]],
139
+ ];
140
+
141
+ /** The container these bytes begin with, or `undefined` — which is most files. */
142
+ function containerAt(bytes: Uint8Array): string | undefined {
143
+ for (const [name, magic] of CONTAINERS) {
144
+ if (magic.every((byte, at) => bytes[at] === byte)) return name;
145
+ }
146
+ return undefined;
147
+ }
148
+
119
149
  function markerFamily(marker: EdfReservedMarker): EdfFamily {
120
150
  return marker === 'EDF+C' || marker === 'EDF+D' ? 'EDF' : 'BDF';
121
151
  }
@@ -157,15 +187,20 @@ export function detectVariant(headerBytes: Uint8Array, sink: DiagnosticSink): Ed
157
187
  HEADER_FIELDS.version.offset,
158
188
  HEADER_FIELDS.version.length,
159
189
  );
190
+ const container = containerAt(headerBytes);
160
191
  throw fatalError({
161
192
  code: 'NOT_AN_EDF_FILE',
162
193
  message:
163
194
  `version field (8 bytes at offset ${HEADER_FIELDS.version.offset}) is ` +
164
195
  `${JSON.stringify(raw)}, bytes ${hexBytes(versionBytes)}: this is neither EDF's ` +
165
196
  `"0" followed by seven spaces nor BDF's 0xff followed by "BIOSEMI". ` +
197
+ (container === undefined ? '' : `Those first bytes are ${container}. `) +
166
198
  'EDF specification, header record bytes 0-7 (version of this data format). ' +
167
- 'Next: confirm the bytes are an uncompressed EDF or BDF recording — a gzip, zip or ' +
168
- 'vendor container has to be unpacked before edfcore sees it.',
199
+ (container === undefined
200
+ ? 'Next: confirm the bytes are an uncompressed EDF or BDF recording — a gzip, zip or ' +
201
+ 'vendor container has to be unpacked before edfcore sees it.'
202
+ : `Next: unpack ${container} and open the EDF or BDF file inside it — edfcore reads ` +
203
+ 'recordings, not archives.'),
169
204
  field: 'version',
170
205
  byteOffset: HEADER_FIELDS.version.offset,
171
206
  byteLength: HEADER_FIELDS.version.length,