edfcore 0.6.33 → 0.6.35
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-report.d.ts.map +1 -1
- package/dist/format-report.js +30 -7
- package/dist/format-report.js.map +1 -1
- package/docs/CHANGELOG.md +37 -0
- package/package.json +1 -1
- package/src/constants.ts +1 -1
- package/src/format-report.ts +32 -8
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.6.
|
|
112
|
+
export declare const VERSION = "0.6.35";
|
|
113
113
|
//# sourceMappingURL=constants.d.ts.map
|
package/dist/constants.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format-report.d.ts","sourceRoot":"","sources":["../src/format-report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH,OAAO,KAAK,EAAE,SAAS,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAKnF;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,gBAAgB,EACxB,OAAO,CAAC,EAAE,mBAAmB,GAC5B,MAAM,
|
|
1
|
+
{"version":3,"file":"format-report.d.ts","sourceRoot":"","sources":["../src/format-report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH,OAAO,KAAK,EAAE,SAAS,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAKnF;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,gBAAgB,EACxB,OAAO,CAAC,EAAE,mBAAmB,GAC5B,MAAM,CAuGR;AAED,qFAAqF;AACrF,YAAY,EAAE,SAAS,EAAE,CAAC"}
|
package/dist/format-report.js
CHANGED
|
@@ -63,18 +63,41 @@ export function formatValidationReport(report, options) {
|
|
|
63
63
|
if (report.signalStats.length > 0) {
|
|
64
64
|
lines.push('');
|
|
65
65
|
lines.push('observed sample ranges:');
|
|
66
|
-
|
|
66
|
+
/*
|
|
67
|
+
* The range and the count are sized from the rows, not left to fall where they land.
|
|
68
|
+
*
|
|
69
|
+
* An observed range is as wide as the numbers in it, and those differ per channel: on the
|
|
70
|
+
* PhysioNet polysomnogram the seven rows read `-2048..1819`, `-54..1905` and `136..980`, so
|
|
71
|
+
* the word `over` sat at three different columns in one block and the sample counts under it
|
|
72
|
+
* at three more. It is the same defect as the sample rate (0.6.23), the signal index (0.6.24)
|
|
73
|
+
* and the event clock (0.6.25) — a value wider than the space it was given — in the fourth
|
|
74
|
+
* formatter, and the same fix: measure the rows first.
|
|
75
|
+
*
|
|
76
|
+
* The count is right-aligned because it is a number and the eye compares magnitudes down a
|
|
77
|
+
* column. A single-signal file has one row, so its widths are its own and its output does not
|
|
78
|
+
* move.
|
|
79
|
+
*/
|
|
80
|
+
const rows = report.signalStats.map((stats) => {
|
|
67
81
|
const signal = header?.signals[stats.signalIndex];
|
|
68
82
|
// Through `printable` for the reason `formatHeader` does it: a label is arbitrary bytes
|
|
69
83
|
// from the file, and one holding a newline would open a row naming a signal that does not
|
|
70
84
|
// exist — in a conformance report, which is read precisely because the file is suspect.
|
|
71
85
|
const name = signal === undefined ? `signal ${stats.signalIndex}` : printable(signal.label);
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
:
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
86
|
+
return {
|
|
87
|
+
name: name.slice(0, 20).padEnd(21),
|
|
88
|
+
range: `${stats.observedDigitalMin}..${stats.observedDigitalMax}`,
|
|
89
|
+
count: stats.sampleCount.toLocaleString('en-US'),
|
|
90
|
+
noun: plural('sample', stats.sampleCount),
|
|
91
|
+
overflow: stats.outOfDigitalRangeCount > 0
|
|
92
|
+
? ` ${stats.outOfDigitalRangeCount} outside the declared range`
|
|
93
|
+
: '',
|
|
94
|
+
};
|
|
95
|
+
});
|
|
96
|
+
const rangeWidth = Math.max(...rows.map((row) => row.range.length));
|
|
97
|
+
const countWidth = Math.max(...rows.map((row) => row.count.length));
|
|
98
|
+
for (const row of rows) {
|
|
99
|
+
lines.push(` ${row.name}${row.range.padEnd(rangeWidth)} over ${row.count.padStart(countWidth)} ` +
|
|
100
|
+
`${row.noun}${row.overflow}`);
|
|
78
101
|
}
|
|
79
102
|
}
|
|
80
103
|
if (report.diagnostics.length > 0) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format-report.js","sourceRoot":"","sources":["../src/format-report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACpF,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGhD,+EAA+E;AAC/E,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAE7B;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CACpC,MAAwB,EACxB,OAA6B;IAE7B,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,CAAC;IAE/B,+FAA+F;IAC/F,iGAAiG;IACjG,0DAA0D;IAC1D,sBAAsB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IAE9C,8EAA8E;IAC9E,MAAM,OAAO,GAAG,oBAAoB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAEzD,MAAM,OAAO,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;IAC5C,MAAM,UAAU,GACd,OAAO,CAAC,KAAK,KAAK,CAAC;QACjB,CAAC,CAAC,gBAAgB;QAClB,CAAC,CACG;YACE,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC;YACzB,CAAC,OAAO,CAAC,QAAQ,EAAE,SAAS,CAAC;YAC7B,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC;SAE1B;aACE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC;YAC/B,qFAAqF;YACrF,4DAA4D;YAC5D,oFAAoF;YACpF,oFAAoF;YACpF,wFAAwF;aACvF,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;aACtD,IAAI,CAAC,IAAI,CAAC,CAAC;IACpB,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,MAAM,UAAU,EAAE,CAAC,CAAC;IACzC,KAAK,CAAC,IAAI,CACR,WAAW,SAAS,CAAC,MAAM,CAAC,cAAc,EAAE,QAAQ,CAAC,IAAI;QACvD,QAAQ,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,SAAS,CAAC,EAAE,CACzF,CAAC;IAEF,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACvB,gFAAgF;QAChF,KAAK,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YAC7C,KAAK,CAAC,IAAI,CAAC,KAAK,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;QACtC,
|
|
1
|
+
{"version":3,"file":"format-report.js","sourceRoot":"","sources":["../src/format-report.ts"],"names":[],"mappings":"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"}
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,43 @@ 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.35
|
|
10
|
+
|
|
11
|
+
- **Added** the census that closes the class four releases in a row have been fixing. A sample rate
|
|
12
|
+
of `68.96551724137932` in a nine-character column (0.6.23), a signal index of 1000 in three
|
|
13
|
+
(0.6.24), a negative or hundred-hour clock in twelve (0.6.25), an observed range and sample count
|
|
14
|
+
that were not padded at all (0.6.34) — the same mistake in four formatters, each found by looking
|
|
15
|
+
at output rather than by anything failing.
|
|
16
|
+
- `every-column-knows-its-width.test.ts` lists every `padStart` and `padEnd` in `src/` that lays
|
|
17
|
+
out a column, with one of three reasons its width is safe: MEASURED from the rows being printed,
|
|
18
|
+
bounded by the FILE FORMAT (a label is 16 bytes, `kind` is one of two words, a rate is rounded to
|
|
19
|
+
fit), or bounded by an ARGUMENT no test can build.
|
|
20
|
+
- Two are in that last group and are named rather than assumed: the per-code diagnostic count and
|
|
21
|
+
the event count, with the arithmetic written out — seven digits is 9,999,999 of one code, and the
|
|
22
|
+
record count field is eight characters, so a per-record code on the largest file the format can
|
|
23
|
+
describe would need eight. They are not measured because no test can construct the report that
|
|
24
|
+
would show it, and saying so is better than a floor nobody can justify.
|
|
25
|
+
- A new width fails until it says which of the three it is. Zero-padding is excluded by pattern: a
|
|
26
|
+
clock digit spelling itself is not a place in a table.
|
|
27
|
+
- No behaviour changed.
|
|
28
|
+
|
|
29
|
+
## 0.6.34
|
|
30
|
+
|
|
31
|
+
- **Fixed** the observed-ranges block in `edfcore validate` falling where the numbers left it. The
|
|
32
|
+
range went straight after the padded label and the sample count straight after that, so both
|
|
33
|
+
columns moved per row. On the PhysioNet polysomnogram that is seven rows and three offsets:
|
|
34
|
+
`-2048..1819 over 7,950,000 samples`, `-54..1905 over 79,500 samples`, `136..980 over 79,500
|
|
35
|
+
samples`.
|
|
36
|
+
- That block exists so a reader can compare channels down a column — it is called "observed sample
|
|
37
|
+
ranges" — and it was the one output where comparing meant re-finding the number on every line.
|
|
38
|
+
- Same defect as the sample rate (0.6.23), the signal index (0.6.24) and the event clock (0.6.25),
|
|
39
|
+
in the fourth and last formatter that lays out a table: a value wider than the space it was
|
|
40
|
+
given. Same fix: measure the rows first. The count is right-aligned, because it is a number and
|
|
41
|
+
magnitudes compare down a column; the range is left-aligned, because `min..max` has no single
|
|
42
|
+
place to hang.
|
|
43
|
+
- A single-signal file has one row, so its widths are its own and its report is byte for byte what
|
|
44
|
+
it was.
|
|
45
|
+
|
|
9
46
|
## 0.6.33
|
|
10
47
|
|
|
11
48
|
- **Added** a sixteenth shape to the `AWKWARD` matrix: BDF+D, 24-bit samples and a discontinuity in
|
package/package.json
CHANGED
package/src/constants.ts
CHANGED
package/src/format-report.ts
CHANGED
|
@@ -80,20 +80,44 @@ export function formatValidationReport(
|
|
|
80
80
|
if (report.signalStats.length > 0) {
|
|
81
81
|
lines.push('');
|
|
82
82
|
lines.push('observed sample ranges:');
|
|
83
|
-
|
|
83
|
+
/*
|
|
84
|
+
* The range and the count are sized from the rows, not left to fall where they land.
|
|
85
|
+
*
|
|
86
|
+
* An observed range is as wide as the numbers in it, and those differ per channel: on the
|
|
87
|
+
* PhysioNet polysomnogram the seven rows read `-2048..1819`, `-54..1905` and `136..980`, so
|
|
88
|
+
* the word `over` sat at three different columns in one block and the sample counts under it
|
|
89
|
+
* at three more. It is the same defect as the sample rate (0.6.23), the signal index (0.6.24)
|
|
90
|
+
* and the event clock (0.6.25) — a value wider than the space it was given — in the fourth
|
|
91
|
+
* formatter, and the same fix: measure the rows first.
|
|
92
|
+
*
|
|
93
|
+
* The count is right-aligned because it is a number and the eye compares magnitudes down a
|
|
94
|
+
* column. A single-signal file has one row, so its widths are its own and its output does not
|
|
95
|
+
* move.
|
|
96
|
+
*/
|
|
97
|
+
const rows = report.signalStats.map((stats) => {
|
|
84
98
|
const signal = header?.signals[stats.signalIndex];
|
|
85
99
|
// Through `printable` for the reason `formatHeader` does it: a label is arbitrary bytes
|
|
86
100
|
// from the file, and one holding a newline would open a row naming a signal that does not
|
|
87
101
|
// exist — in a conformance report, which is read precisely because the file is suspect.
|
|
88
102
|
const name = signal === undefined ? `signal ${stats.signalIndex}` : printable(signal.label);
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
103
|
+
return {
|
|
104
|
+
name: name.slice(0, 20).padEnd(21),
|
|
105
|
+
range: `${stats.observedDigitalMin}..${stats.observedDigitalMax}`,
|
|
106
|
+
count: stats.sampleCount.toLocaleString('en-US'),
|
|
107
|
+
noun: plural('sample', stats.sampleCount),
|
|
108
|
+
overflow:
|
|
109
|
+
stats.outOfDigitalRangeCount > 0
|
|
110
|
+
? ` ${stats.outOfDigitalRangeCount} outside the declared range`
|
|
111
|
+
: '',
|
|
112
|
+
};
|
|
113
|
+
});
|
|
114
|
+
const rangeWidth = Math.max(...rows.map((row) => row.range.length));
|
|
115
|
+
const countWidth = Math.max(...rows.map((row) => row.count.length));
|
|
116
|
+
|
|
117
|
+
for (const row of rows) {
|
|
93
118
|
lines.push(
|
|
94
|
-
` ${name.
|
|
95
|
-
|
|
96
|
-
`${plural('sample', stats.sampleCount)}${overflow}`,
|
|
119
|
+
` ${row.name}${row.range.padEnd(rangeWidth)} over ${row.count.padStart(countWidth)} ` +
|
|
120
|
+
`${row.noun}${row.overflow}`,
|
|
97
121
|
);
|
|
98
122
|
}
|
|
99
123
|
}
|