edfcore 0.4.508 → 0.4.510
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/decode/physical.d.ts.map +1 -1
- package/dist/decode/physical.js +35 -3
- package/dist/decode/physical.js.map +1 -1
- package/docs/CHANGELOG.md +42 -0
- package/package.json +1 -1
- package/src/constants.ts +1 -1
- package/src/decode/physical.ts +40 -4
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.4.
|
|
112
|
+
export declare const VERSION = "0.4.510";
|
|
113
113
|
//# sourceMappingURL=constants.d.ts.map
|
package/dist/constants.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"physical.d.ts","sourceRoot":"","sources":["../../src/decode/physical.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAkB,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/D,OAAO,KAAK,EAAqB,SAAS,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEvD,YAAY,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"physical.d.ts","sourceRoot":"","sources":["../../src/decode/physical.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAkB,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/D,OAAO,KAAK,EAAqB,SAAS,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEvD,YAAY,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AA0JvD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,SAAS,EACjB,IAAI,CAAC,EAAE;IAAE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GACnE,eAAe,CAkBjB;AA+CD;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,CACxB,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,SAAS,CAAC,MAAM,CAAC,EAC1B,GAAG,CAAC,EAAE,YAAY,EAClB,OAAO,CAAC,EAAE,kBAAkB,GAC3B,YAAY,CAad;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,GAAG;IAClD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB,CAaA;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,UAAU,EACnB,GAAG,CAAC,EAAE,UAAU,EAChB,OAAO,CAAC,EAAE,kBAAkB,GAC3B,UAAU,CAsBZ"}
|
package/dist/decode/physical.js
CHANGED
|
@@ -27,7 +27,7 @@ function assertWithinBudget(requiredBytes, what, options) {
|
|
|
27
27
|
* Why `signal.scale` is `undefined`, re-derived from the signal itself.
|
|
28
28
|
*
|
|
29
29
|
* The header records the matching diagnostic at parse time, but a bare `EdfSignal` does not
|
|
30
|
-
* carry it, and `toPhysical` takes a signal. These
|
|
30
|
+
* carry it, and `toPhysical` takes a signal. These five tests are the same ones `header/scale.ts`
|
|
31
31
|
* applies, IN THE SAME ORDER — a signal can fail two of them at once, and the order is what
|
|
32
32
|
* decides which cause is named, so the code reported here is the code the header reported.
|
|
33
33
|
* `buildScale` owns that order; this function follows it. A signal that fails none
|
|
@@ -35,8 +35,9 @@ function assertWithinBudget(requiredBytes, what, options) {
|
|
|
35
35
|
* naming the wrong cause is worse than admitting the cause is not on hand.
|
|
36
36
|
*/
|
|
37
37
|
function describeScalingFailure(signal) {
|
|
38
|
-
const
|
|
39
|
-
|
|
38
|
+
const rangeSpec = 'EDF+ additional specification 5';
|
|
39
|
+
const digitalSpec = `${rangeSpec}: "Digital maximum must be larger than Digital minimum"`;
|
|
40
|
+
// FIRST, and ahead of the five re-derived tests. `parseSignalHeaders` deliberately does not run
|
|
40
41
|
// `buildScale` over an annotations channel — its physical and digital fields describe nothing a
|
|
41
42
|
// caller may use, and checking them "would report a defect about a number nobody may use". So
|
|
42
43
|
// such a signal has no scale AND no diagnostic, and re-running the four tests over those unused
|
|
@@ -90,6 +91,37 @@ function describeScalingFailure(signal) {
|
|
|
90
91
|
specReference: 'EDFlib edffloat.html',
|
|
91
92
|
};
|
|
92
93
|
}
|
|
94
|
+
// FIFTH, and the reason this function re-derives arithmetic rather than only reading fields:
|
|
95
|
+
// four finite fields can still imply a gain that is not finite. `buildScale` reports
|
|
96
|
+
// DEGENERATE_PHYSICAL_RANGE for that, and until 0.4.509 this fell through to the
|
|
97
|
+
// `SCALE_UNAVAILABLE` fallback below — whose text says the header holds the reason, while the
|
|
98
|
+
// header was in fact holding a different code. That is the same divergence 0.3.111 fixed
|
|
99
|
+
// between the two entry points, in the one arm nobody mirrored.
|
|
100
|
+
//
|
|
101
|
+
// Guarded on all four being finite, because a field that failed its grammar arrives here as
|
|
102
|
+
// NaN, and NaN would satisfy the non-finite test below and claim the gain as the cause. Its
|
|
103
|
+
// cause belongs to the field, was reported against the field, and is exactly the case the
|
|
104
|
+
// fallback's wording is true of.
|
|
105
|
+
if (Number.isFinite(signal.physicalMinimum) &&
|
|
106
|
+
Number.isFinite(signal.physicalMaximum) &&
|
|
107
|
+
Number.isFinite(signal.digitalMinimum) &&
|
|
108
|
+
Number.isFinite(signal.digitalMaximum)) {
|
|
109
|
+
// `buildScale`'s expression, not a simplification of it: the two must agree on which ranges
|
|
110
|
+
// are refused, and the pinned form is what decides the edge cases.
|
|
111
|
+
const bitValue = (signal.physicalMaximum - signal.physicalMinimum) /
|
|
112
|
+
(signal.digitalMaximum - signal.digitalMinimum);
|
|
113
|
+
const offset = signal.physicalMaximum / bitValue - signal.digitalMaximum;
|
|
114
|
+
if (bitValue === 0 || !Number.isFinite(bitValue) || !Number.isFinite(offset)) {
|
|
115
|
+
return {
|
|
116
|
+
code: 'DEGENERATE_PHYSICAL_RANGE',
|
|
117
|
+
reason: `declares the physical range ${signal.physicalMinimum}..${signal.physicalMaximum} ` +
|
|
118
|
+
`over the digital range ${signal.digitalMinimum}..${signal.digitalMaximum}, and the ` +
|
|
119
|
+
`gain those imply is not a usable float64 number (bitValue ${bitValue}, offset ` +
|
|
120
|
+
`${offset}), so every converted sample would be NaN or infinite`,
|
|
121
|
+
specReference: rangeSpec,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
}
|
|
93
125
|
return {
|
|
94
126
|
code: 'SCALE_UNAVAILABLE',
|
|
95
127
|
reason: 'has no usable scale, and the header recorded the reason rather than the signal',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"physical.js","sourceRoot":"","sources":["../../src/decode/physical.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAMzD,MAAM,iBAAiB,GAAG,CAAC,CAAC;AAC5B,MAAM,eAAe,GAAG,CAAC,CAAC;AAE1B,2FAA2F;AAC3F,MAAM,yBAAyB,GAAG,UAAU,CAAC;AAe7C,SAAS,kBAAkB,CACzB,aAAqB,EACrB,IAAY,EACZ,OAAuC;IAEvC,MAAM,WAAW,GAAG,wBAAwB,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;IAC3E,IAAI,aAAa,IAAI,WAAW;QAAE,OAAO;IACzC,MAAM,IAAI,cAAc,CACtB,aAAa,IAAI,YAAY,aAAa,0BAA0B,WAAW,QAAQ;QACrF,qFAAqF;QACrF,uEAAuE;QACvE,8BAA8B,EAChC,EAAE,aAAa,EAAE,WAAW,EAAE,CAC/B,CAAC;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAS,sBAAsB,CAAC,MAAiB;IAC/C,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"physical.js","sourceRoot":"","sources":["../../src/decode/physical.ts"],"names":[],"mappings":"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"}
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,48 @@ 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.4.510
|
|
10
|
+
|
|
11
|
+
- **Added** the one claim every diagnostic makes at once, as a property test: `raw` quotes the
|
|
12
|
+
bytes `byteOffset` names. `EdfDiagnostic.raw` is documented as "those bytes as text, exactly as
|
|
13
|
+
written including padding" — the bytes AT the offset the same diagnostic reports — and it is the
|
|
14
|
+
only evidence a reader has that a diagnosis is about the field in front of them.
|
|
15
|
+
- It had gone wrong three times, three different ways, each found by eye rather than by a test:
|
|
16
|
+
0.3.26, where `NON_ASCII_HEADER_FIELD` quoted bytes contradicting its own claim; 0.3.68, where a
|
|
17
|
+
TAL diagnostic put the escaped message preview in `raw` and returned a 13-character string for
|
|
18
|
+
four bytes; and 0.3.73, where `PARTIAL_FINAL_RECORD` pointed into the data section while carrying
|
|
19
|
+
the record-count field's eight bytes. Nothing checked the pair, which is how one defect appeared
|
|
20
|
+
in three places.
|
|
21
|
+
- Both sides are damaged at random and checked, because they derive the offset differently: a
|
|
22
|
+
header field's comes from a fixed table, a TAL's is recomputed as
|
|
23
|
+
`headerByteLength + recordIndex * recordByteLength + signal.recordByteOffset` while the bytes are
|
|
24
|
+
sliced from a record buffer that starts at neither. Dropping the last term of that sum, or adding
|
|
25
|
+
one to a header field's offset, each fail the run.
|
|
26
|
+
- Roughly 15,000 diagnostics across 24 codes satisfy it today, and the run asserts the counts as
|
|
27
|
+
well as the property: a change that stopped producing diagnostics under damage would otherwise
|
|
28
|
+
pass by having nothing to check.
|
|
29
|
+
|
|
30
|
+
## 0.4.509
|
|
31
|
+
|
|
32
|
+
- **Fixed** `toPhysical` naming a different cause than the header for one class of unscalable
|
|
33
|
+
signal. `header/scale.ts` refuses to build a scale in five places; `decode/physical.ts`
|
|
34
|
+
re-derives which one applied, from the signal alone, because `toPhysical` never sees the header.
|
|
35
|
+
It re-derived four of the five. The missing one is the case where all four scale fields are
|
|
36
|
+
finite but the gain they imply is not — `-9.9E307`..`9.9E307` over `-32768`..`32767` gives a
|
|
37
|
+
bitValue of `Infinity` — which the header reports as `DEGENERATE_PHYSICAL_RANGE`.
|
|
38
|
+
- The cost was a message that pointed at nothing. Such a signal threw `SCALE_UNAVAILABLE`, whose
|
|
39
|
+
text reads "the header recorded the reason rather than the signal", so a caller who catches the
|
|
40
|
+
error and goes looking through `header.diagnostics` for `SCALE_UNAVAILABLE` finds no entry —
|
|
41
|
+
the entry is there under the other code. Both `error.code` and the reason are now the header's,
|
|
42
|
+
and the message quotes the bitValue and offset it computed.
|
|
43
|
+
- The re-derivation is guarded on all four fields being finite, because a field that failed its
|
|
44
|
+
grammar arrives as `NaN`, and `NaN` satisfies a non-finite test. That signal's cause belongs to
|
|
45
|
+
the field, was already reported against the field, and is the case the `SCALE_UNAVAILABLE`
|
|
46
|
+
wording is true of — so the fallback stays reachable and stays honest.
|
|
47
|
+
- This is the same divergence 0.3.111 fixed between the two entry points, in the one arm nobody
|
|
48
|
+
mirrored, so the count is now checked rather than trusted: a test reads `header/scale.ts` and
|
|
49
|
+
asserts it abandons a scale in exactly five places, against the five cases the contract covers.
|
|
50
|
+
|
|
9
51
|
## 0.4.508
|
|
10
52
|
|
|
11
53
|
- **Added** an enforcement of the `grid` prefix rule. `migrating-to-0-3.md` explains why three
|
package/package.json
CHANGED
package/src/constants.ts
CHANGED
package/src/decode/physical.ts
CHANGED
|
@@ -55,7 +55,7 @@ function assertWithinBudget(
|
|
|
55
55
|
* Why `signal.scale` is `undefined`, re-derived from the signal itself.
|
|
56
56
|
*
|
|
57
57
|
* The header records the matching diagnostic at parse time, but a bare `EdfSignal` does not
|
|
58
|
-
* carry it, and `toPhysical` takes a signal. These
|
|
58
|
+
* carry it, and `toPhysical` takes a signal. These five tests are the same ones `header/scale.ts`
|
|
59
59
|
* applies, IN THE SAME ORDER — a signal can fail two of them at once, and the order is what
|
|
60
60
|
* decides which cause is named, so the code reported here is the code the header reported.
|
|
61
61
|
* `buildScale` owns that order; this function follows it. A signal that fails none
|
|
@@ -63,9 +63,9 @@ function assertWithinBudget(
|
|
|
63
63
|
* naming the wrong cause is worse than admitting the cause is not on hand.
|
|
64
64
|
*/
|
|
65
65
|
function describeScalingFailure(signal: EdfSignal): ScalingFailure {
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
// FIRST, and ahead of the
|
|
66
|
+
const rangeSpec = 'EDF+ additional specification 5';
|
|
67
|
+
const digitalSpec = `${rangeSpec}: "Digital maximum must be larger than Digital minimum"`;
|
|
68
|
+
// FIRST, and ahead of the five re-derived tests. `parseSignalHeaders` deliberately does not run
|
|
69
69
|
// `buildScale` over an annotations channel — its physical and digital fields describe nothing a
|
|
70
70
|
// caller may use, and checking them "would report a defect about a number nobody may use". So
|
|
71
71
|
// such a signal has no scale AND no diagnostic, and re-running the four tests over those unused
|
|
@@ -125,6 +125,42 @@ function describeScalingFailure(signal: EdfSignal): ScalingFailure {
|
|
|
125
125
|
specReference: 'EDFlib edffloat.html',
|
|
126
126
|
};
|
|
127
127
|
}
|
|
128
|
+
// FIFTH, and the reason this function re-derives arithmetic rather than only reading fields:
|
|
129
|
+
// four finite fields can still imply a gain that is not finite. `buildScale` reports
|
|
130
|
+
// DEGENERATE_PHYSICAL_RANGE for that, and until 0.4.509 this fell through to the
|
|
131
|
+
// `SCALE_UNAVAILABLE` fallback below — whose text says the header holds the reason, while the
|
|
132
|
+
// header was in fact holding a different code. That is the same divergence 0.3.111 fixed
|
|
133
|
+
// between the two entry points, in the one arm nobody mirrored.
|
|
134
|
+
//
|
|
135
|
+
// Guarded on all four being finite, because a field that failed its grammar arrives here as
|
|
136
|
+
// NaN, and NaN would satisfy the non-finite test below and claim the gain as the cause. Its
|
|
137
|
+
// cause belongs to the field, was reported against the field, and is exactly the case the
|
|
138
|
+
// fallback's wording is true of.
|
|
139
|
+
if (
|
|
140
|
+
Number.isFinite(signal.physicalMinimum) &&
|
|
141
|
+
Number.isFinite(signal.physicalMaximum) &&
|
|
142
|
+
Number.isFinite(signal.digitalMinimum) &&
|
|
143
|
+
Number.isFinite(signal.digitalMaximum)
|
|
144
|
+
) {
|
|
145
|
+
// `buildScale`'s expression, not a simplification of it: the two must agree on which ranges
|
|
146
|
+
// are refused, and the pinned form is what decides the edge cases.
|
|
147
|
+
const bitValue =
|
|
148
|
+
(signal.physicalMaximum - signal.physicalMinimum) /
|
|
149
|
+
(signal.digitalMaximum - signal.digitalMinimum);
|
|
150
|
+
const offset = signal.physicalMaximum / bitValue - signal.digitalMaximum;
|
|
151
|
+
if (bitValue === 0 || !Number.isFinite(bitValue) || !Number.isFinite(offset)) {
|
|
152
|
+
return {
|
|
153
|
+
code: 'DEGENERATE_PHYSICAL_RANGE',
|
|
154
|
+
reason:
|
|
155
|
+
`declares the physical range ${signal.physicalMinimum}..${signal.physicalMaximum} ` +
|
|
156
|
+
`over the digital range ${signal.digitalMinimum}..${signal.digitalMaximum}, and the ` +
|
|
157
|
+
`gain those imply is not a usable float64 number (bitValue ${bitValue}, offset ` +
|
|
158
|
+
`${offset}), so every converted sample would be NaN or infinite`,
|
|
159
|
+
specReference: rangeSpec,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
128
164
|
return {
|
|
129
165
|
code: 'SCALE_UNAVAILABLE',
|
|
130
166
|
reason: 'has no usable scale, and the header recorded the reason rather than the signal',
|