edfcore 0.2.46 → 0.2.48
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/CHANGELOG.md +46 -10
- package/README.md +13 -3
- package/dist/cli-run.js +1 -1
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -1
- package/package.json +1 -1
- package/src/cli-run.ts +1 -1
- package/src/constants.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,7 +6,37 @@ 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.2.
|
|
9
|
+
## 0.2.48
|
|
10
|
+
|
|
11
|
+
- **Added** bit-for-bit parity against pyEDFlib on the REAL corpus — the last thing the README
|
|
12
|
+
withheld. A 22-hour clinical polysomnogram from sleep-edfx and the three teuniz generator files
|
|
13
|
+
in EDF, EDF+ and 24-bit BDF+, compared with `Object.is` per sample.
|
|
14
|
+
- These files matter because nobody here chose them: they were written by other people's software
|
|
15
|
+
and hardware, years ago. `corpus.test.ts` already read them, but it checked that the output was
|
|
16
|
+
BELIEVABLE — a rectal temperature near 37 degrees, an 8.5 Hz channel oscillating at 8.5 Hz — and
|
|
17
|
+
a check like that would pass for a reader that was slightly wrong everywhere, which is exactly
|
|
18
|
+
the failure the pinned scaling expression exists to prevent. A test in the new file demonstrates
|
|
19
|
+
that directly: on the PSG's temperature channel the textbook expression produces a believable
|
|
20
|
+
body temperature for every sample AND disagrees with pyEDFlib, so the old check could not have
|
|
21
|
+
told the two apart and the new one can.
|
|
22
|
+
- Sampled at the start, the middle and the END of each signal rather than whole files — the PSG
|
|
23
|
+
alone is 48 MB. The end window is the one that earns its place: a reader whose record arithmetic
|
|
24
|
+
drifts does so with distance from the start.
|
|
25
|
+
- Skips without the corpus, like every other test in that directory, so a fresh clone stays green
|
|
26
|
+
and offline.
|
|
27
|
+
|
|
28
|
+
## 0.2.47
|
|
29
|
+
|
|
30
|
+
- **Fixed** this changelog. Every heading from `0.2.36` down to `0.2.45` named a version one lower
|
|
31
|
+
than the release that actually shipped it: `0.2.36` was consumed by a release run that failed its
|
|
32
|
+
typecheck after bumping the version, and I kept writing the next entry against the number I
|
|
33
|
+
expected rather than the tag that got cut. So the `cachedSource` fix was labelled `0.2.36` and
|
|
34
|
+
shipped in `0.2.37`, and everything after it was off by one — including the MNE claim in the
|
|
35
|
+
README, which named `0.2.43` for work that is in `0.2.44`. Verified against the tags rather than
|
|
36
|
+
reasoned about: `git show <tag>:CHANGELOG.md` for each. `0.2.36` is now listed as never released,
|
|
37
|
+
the way `0.2.29` already was.
|
|
38
|
+
|
|
39
|
+
## 0.2.46
|
|
10
40
|
|
|
11
41
|
- **Added** `scripts/golden/README.md`: how to regenerate every parity fixture, and — more usefully
|
|
12
42
|
— what each of the three harnesses actually claims and how strong that claim is. Bit-for-bit for
|
|
@@ -18,7 +48,7 @@ defect; those are called out below.
|
|
|
18
48
|
- **Documented** the same table on the physical-values page, so a reader who never opens the
|
|
19
49
|
repository sees which claims are load-bearing and which are approximate.
|
|
20
50
|
|
|
21
|
-
## 0.2.
|
|
51
|
+
## 0.2.45
|
|
22
52
|
|
|
23
53
|
- **Added** annotation parity against pyEDFlib — the other axis, and the one edfcore has got wrong
|
|
24
54
|
most. The scaling harness checks arithmetic; this checks WHICH AXIS an onset is on. Six releases
|
|
@@ -33,7 +63,7 @@ defect; those are called out below.
|
|
|
33
63
|
recorded from that would have made the parity test compare an incomplete set and pass while doing
|
|
34
64
|
it.
|
|
35
65
|
|
|
36
|
-
## 0.2.
|
|
66
|
+
## 0.2.44
|
|
37
67
|
|
|
38
68
|
- **Added** parity against MNE — a second, independent reader. pyEDFlib and edfcore both descend
|
|
39
69
|
from EDFlib's arithmetic, so agreement between them shows edfcore copied it correctly rather than
|
|
@@ -49,7 +79,7 @@ defect; those are called out below.
|
|
|
49
79
|
other. Channels MNE does not rescale — it leaves `degC` alone — are excluded rather than pushed
|
|
50
80
|
through a factor that would make the comparison an artefact of the test.
|
|
51
81
|
|
|
52
|
-
## 0.2.
|
|
82
|
+
## 0.2.43
|
|
53
83
|
|
|
54
84
|
- **Added** three cases to the pyEDFlib parity harness, chosen for where the two scaling
|
|
55
85
|
expressions diverge most or where a mistake would be least visible:
|
|
@@ -61,7 +91,7 @@ defect; those are called out below.
|
|
|
61
91
|
set.
|
|
62
92
|
- **a full 16-bit range** mapped to one millivolt — the finest.
|
|
63
93
|
|
|
64
|
-
## 0.2.
|
|
94
|
+
## 0.2.42
|
|
65
95
|
|
|
66
96
|
- **Added** a `samplesPerRecord` column to `edfcore signals`, and **fixed** the documentation,
|
|
67
97
|
which claimed the command emitted it when it emitted `kind` instead. That left the authoritative
|
|
@@ -72,7 +102,7 @@ defect; those are called out below.
|
|
|
72
102
|
five columns by position moved. The full six-column list is now pinned by a test, not only
|
|
73
103
|
described.
|
|
74
104
|
|
|
75
|
-
## 0.2.
|
|
105
|
+
## 0.2.41
|
|
76
106
|
|
|
77
107
|
- **Added** the types `edfcore/validate`'s own signatures mention to that subpath's exports:
|
|
78
108
|
`EdfHeader`, `EdfDiagnostic`, `EdfDiagnosticCode`, `EdfSeverity`, `EdfSignal`, `EdfRecordIndex`
|
|
@@ -83,7 +113,7 @@ defect; those are called out below.
|
|
|
83
113
|
of anything they passed or got back. A type-only test now pins the set, so it fails at
|
|
84
114
|
`npm run typecheck` rather than in a consumer's project.
|
|
85
115
|
|
|
86
|
-
## 0.2.
|
|
116
|
+
## 0.2.40
|
|
87
117
|
|
|
88
118
|
- **Added** tests pinning which date defect produces which diagnostic. `DATE_IMPLAUSIBLE` is
|
|
89
119
|
documented as covering two conditions with only the second reachable, and that was prose about an
|
|
@@ -94,7 +124,7 @@ defect; those are called out below.
|
|
|
94
124
|
dead. The branch itself is kept, with the reason written next to it — a missing guard is harder
|
|
95
125
|
to notice than an idle one.
|
|
96
126
|
|
|
97
|
-
## 0.2.
|
|
127
|
+
## 0.2.39
|
|
98
128
|
|
|
99
129
|
- **Fixed** `onsetSecondsFromFirstRecord` and `onsetTicksFromFirstRecord` disagreeing about the
|
|
100
130
|
same event at the edge of the int64 tick range. The exact field saturated and the float field was
|
|
@@ -103,7 +133,7 @@ defect; those are called out below.
|
|
|
103
133
|
with the exact field in 0.2.10. Both are now derived from one rebased value, which is what the
|
|
104
134
|
float field was always documented to be: the lossy view of the exact one.
|
|
105
135
|
|
|
106
|
-
## 0.2.
|
|
136
|
+
## 0.2.38
|
|
107
137
|
|
|
108
138
|
- **Fixed** `fileHandleSource` and `fileSource` ignoring an abort signal that flipped while a read
|
|
109
139
|
was in flight. The abort check ran at the top of each loop iteration, and the common case is one
|
|
@@ -112,7 +142,7 @@ defect; those are called out below.
|
|
|
112
142
|
test saying why; one adapter honouring a signal that another quietly ignores is worse than either
|
|
113
143
|
rule alone.
|
|
114
144
|
|
|
115
|
-
## 0.2.
|
|
145
|
+
## 0.2.37
|
|
116
146
|
|
|
117
147
|
- **Fixed** `cachedSource` repopulating itself after `close()`. A read already in flight when close
|
|
118
148
|
was called still resolves, and its continuation still runs — after `blocks.clear()` — so the
|
|
@@ -126,6 +156,12 @@ defect; those are called out below.
|
|
|
126
156
|
cache entirely and retains nothing. The path is exactly as safe as calling the wrapped source
|
|
127
157
|
directly, which is what it does.
|
|
128
158
|
|
|
159
|
+
## 0.2.36
|
|
160
|
+
|
|
161
|
+
Never released. A release run failed its typecheck after bumping the version, which consumed the
|
|
162
|
+
number before a tag was cut — the same way `0.2.29` was lost earlier. The `cachedSource` fix that
|
|
163
|
+
carried this heading while it was being written shipped in `0.2.37`, and is listed there.
|
|
164
|
+
|
|
129
165
|
## 0.2.35
|
|
130
166
|
|
|
131
167
|
- **Fixed** `byteSource` building a source over an argument that is not bytes, so the caller's
|
package/README.md
CHANGED
|
@@ -299,15 +299,25 @@ back with pyEDFlib, and records every sample as its exact IEEE-754 bit pattern;
|
|
|
299
299
|
`tests/corpus/golden/` was produced by edfcore. Substituting the numerically better textbook
|
|
300
300
|
expression fails it on 140 of 256 samples — which is why the EDFlib form is pinned.
|
|
301
301
|
|
|
302
|
-
**MNE, as of 0.2.
|
|
302
|
+
**MNE, as of 0.2.44.** edfcore agrees with MNE to within 1e-12 relative — a weaker claim than the
|
|
303
303
|
one above, and deliberately so. MNE returns SI units, so a microvolt channel arrives divided by
|
|
304
304
|
1e6, and that division is lossy; the residue is MNE's unit conversion rather than a disagreement
|
|
305
305
|
about the sample. Bit-parity is claimed for pyEDFlib alone. Both readers also agree with the file's
|
|
306
306
|
own declaration about POLARITY on a negative-gain channel, which a value comparison alone could not
|
|
307
307
|
establish.
|
|
308
308
|
|
|
309
|
-
**
|
|
310
|
-
|
|
309
|
+
**The public corpora, as of 0.2.48.** The bit-for-bit claim above also holds on files nobody here
|
|
310
|
+
chose: a **22-hour clinical polysomnogram** from sleep-edfx, and the teuniz generator files in EDF,
|
|
311
|
+
EDF+ and 24-bit BDF+. Sampled at the start, the middle and the end of every signal — the end window
|
|
312
|
+
being the one that catches record arithmetic drifting with distance, which a sample near record 0
|
|
313
|
+
cannot. Those tests need the corpus and skip without it:
|
|
314
|
+
|
|
315
|
+
```bash
|
|
316
|
+
npm run corpus:fetch
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
**Still open before 1.0.** CHB-MIT, and the edfplus.info conformance files. Those are not claimed
|
|
320
|
+
here until a test produces them.
|
|
311
321
|
|
|
312
322
|
**Shipped since 0.1.6.** Min/max envelope decimation (`readEnvelope`,
|
|
313
323
|
`readEnvelopeAtResolution`). BioSemi Status-byte helpers (`readTriggers`). Streaming iteration
|
package/dist/cli-run.js
CHANGED
|
@@ -221,7 +221,7 @@ export async function runCli(args, io) {
|
|
|
221
221
|
case 'signals': {
|
|
222
222
|
// Tab-separated and one line per signal: `header` is for reading, this is for piping.
|
|
223
223
|
//
|
|
224
|
-
// `samplesPerRecord` is last and was missing until 0.2.
|
|
224
|
+
// `samplesPerRecord` is last and was missing until 0.2.42. It is the AUTHORITATIVE field —
|
|
225
225
|
// `sampleRateHz` is derived from it and the record duration, and is empty for the legal
|
|
226
226
|
// zero-duration file — so a listing meant for a script that omitted it forced the reader
|
|
227
227
|
// back to `json` for the one number they could safely index by. Appended rather than
|
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.2.
|
|
112
|
+
export declare const VERSION = "0.2.48";
|
|
113
113
|
//# sourceMappingURL=constants.d.ts.map
|
package/dist/constants.js
CHANGED
package/package.json
CHANGED
package/src/cli-run.ts
CHANGED
|
@@ -263,7 +263,7 @@ export async function runCli(args: Args, io: CliIo): Promise<number> {
|
|
|
263
263
|
case 'signals': {
|
|
264
264
|
// Tab-separated and one line per signal: `header` is for reading, this is for piping.
|
|
265
265
|
//
|
|
266
|
-
// `samplesPerRecord` is last and was missing until 0.2.
|
|
266
|
+
// `samplesPerRecord` is last and was missing until 0.2.42. It is the AUTHORITATIVE field —
|
|
267
267
|
// `sampleRateHz` is derived from it and the record duration, and is empty for the legal
|
|
268
268
|
// zero-duration file — so a listing meant for a script that omitted it forced the reader
|
|
269
269
|
// back to `json` for the one number they could safely index by. Appended rather than
|
package/src/constants.ts
CHANGED