edfcore 0.3.56 → 0.3.57
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 +23 -0
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -1
- package/dist/recording.d.ts.map +1 -1
- package/dist/recording.js +27 -7
- package/dist/recording.js.map +1 -1
- package/package.json +1 -1
- package/src/constants.ts +1 -1
- package/src/recording.ts +37 -7
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,29 @@ 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.3.57
|
|
10
|
+
|
|
11
|
+
- **Fixed** the zero-record chunk's start time, which was read off a segment on the wrong axis and
|
|
12
|
+
only for a record a segment BEGINS at. Both halves were introduced by 0.3.38's fix for the same
|
|
13
|
+
field.
|
|
14
|
+
- `segment.startTicks` is **rebased** — `buildSegmentation` stores `absoluteOnset - originTicks`
|
|
15
|
+
with `originTicks = timeline.startOffsetTicks` — while `readChunk` consumed it as a header-axis
|
|
16
|
+
value and subtracted the offset a second time. On an EDF+ file whose record 0 begins part-way
|
|
17
|
+
into a second, which is exactly what record 0's timekeeping TAL is for,
|
|
18
|
+
`readRecords({ start: 0, count: 0 })` reported **-0.25 s**: before the instant that defines
|
|
19
|
+
`t = 0`. At a segment boundary it reported 99.75 s while carrying a gap ending at 100 s — the
|
|
20
|
+
self-contradiction 0.3.38 existed to remove, reintroduced one line away by its own fix.
|
|
21
|
+
- The lookup matched only a segment's first record, so a mid-segment record fell through to the
|
|
22
|
+
nominal grid, which knows nothing about gaps: `{ start: 5, count: 0 }` answered **5 s** where
|
|
23
|
+
`{ start: 5, count: 1 }` answered **101 s**, for the same record of the same file.
|
|
24
|
+
- The helper now reads the segment that CONTAINS the record and adds the origin back, so both
|
|
25
|
+
forms answer identically at every record — boundary or not, offset or not.
|
|
26
|
+
- The 0.3.38 test asserted `gap.endTicks === chunk.startTicks + startOffsetTicks`. Both values are
|
|
27
|
+
on the rebased axis, so the real invariant is equality; the extra term was only ever right
|
|
28
|
+
because that fixture's offset is zero. A guard that states a relation which holds only at zero
|
|
29
|
+
would have accepted this bug back, so it now states the relation itself, and the new test gives
|
|
30
|
+
the file an offset.
|
|
31
|
+
|
|
9
32
|
## 0.3.56
|
|
10
33
|
|
|
11
34
|
- **Fixed** `trimToWindow` dropping the sample whose own start time the window was aligned to.
|
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.3.
|
|
112
|
+
export declare const VERSION = "0.3.57";
|
|
113
113
|
//# sourceMappingURL=constants.d.ts.map
|
package/dist/constants.js
CHANGED
package/dist/recording.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recording.d.ts","sourceRoot":"","sources":["../src/recording.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAUH,OAAO,KAAK,EACV,UAAU,EACV,wBAAwB,EACxB,oBAAoB,EACpB,QAAQ,EAER,MAAM,EACN,SAAS,EACT,cAAc,EACd,YAAY,EACZ,SAAS,
|
|
1
|
+
{"version":3,"file":"recording.d.ts","sourceRoot":"","sources":["../src/recording.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAUH,OAAO,KAAK,EACV,UAAU,EACV,wBAAwB,EACxB,oBAAoB,EACpB,QAAQ,EAER,MAAM,EACN,SAAS,EACT,cAAc,EACd,YAAY,EACZ,SAAS,EAET,WAAW,EACX,WAAW,EACX,WAAW,EACX,eAAe,EACf,eAAe,EAChB,MAAM,YAAY,CAAC;AAEpB;;;;;GAKG;AACH,wBAAsB,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAI9F;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,SAAS,EACjB,aAAa,EAAE,SAAS,MAAM,EAAE,GAC/B,SAAS,SAAS,EAAE,CA2BtB;AA0CD;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAQxF;AAoFD,kGAAkG;AAClG,wBAAsB,WAAW,CAC/B,SAAS,EAAE,YAAY,EACvB,SAAS,EAAE,eAAe,EAC1B,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,QAAQ,CAAC,CAEnB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,UAAU,CAC9B,SAAS,EAAE,YAAY,EACvB,SAAS,EAAE,eAAe,EAC1B,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,SAAS,QAAQ,EAAE,CAAC,CA2B9B;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,SAAS,EAAE,YAAY,EACvB,OAAO,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE,wBAAwB,GAAG,WAAW,GAC/C,OAAO,CAAC,oBAAoB,CAAC,CAU/B"}
|
package/dist/recording.js
CHANGED
|
@@ -73,14 +73,34 @@ export function resolveSignals(header, signalIndices) {
|
|
|
73
73
|
return signals;
|
|
74
74
|
}
|
|
75
75
|
/**
|
|
76
|
-
* The header-axis onset of
|
|
76
|
+
* The header-axis onset of `recordStart`, when a scanned index knows where that record is.
|
|
77
77
|
*
|
|
78
|
-
* `undefined` for a probed index,
|
|
79
|
-
*
|
|
78
|
+
* `undefined` for a probed index, where nothing better than the nominal grid is available and the
|
|
79
|
+
* caller falls back to it.
|
|
80
|
+
*
|
|
81
|
+
* Two things here are easy to get wrong, and 0.3.38 got both wrong at once.
|
|
82
|
+
*
|
|
83
|
+
* `segment.startTicks` is REBASED — `buildSegmentation` stores `absoluteOnset - originTicks` with
|
|
84
|
+
* `originTicks = timeline.startOffsetTicks` — while the caller consumes this as a header-axis
|
|
85
|
+
* value and subtracts the offset again. On a file whose record 0 begins part-way into a second,
|
|
86
|
+
* which is exactly what record 0's timekeeping TAL is for, a zero-record chunk at record 0 came
|
|
87
|
+
* back at **-0.25 s**: before the instant that defines t = 0. At a segment boundary it reported
|
|
88
|
+
* 99.75 s while carrying a gap that ends at 100 s — the self-contradiction 0.3.38 existed to
|
|
89
|
+
* remove, reintroduced one line away by the fix for it.
|
|
90
|
+
*
|
|
91
|
+
* And it matched only a segment's FIRST record, so a mid-segment record fell through to the
|
|
92
|
+
* nominal grid, which knows nothing about gaps: `readRecords({ start: 5, count: 0 })` said 5 s
|
|
93
|
+
* where `{ start: 5, count: 1 }` said 101 s, for the same record of the same file. Reading the
|
|
94
|
+
* segment that CONTAINS the record answers both the same way (fixed in 0.3.57).
|
|
80
95
|
*/
|
|
81
|
-
function
|
|
82
|
-
const segment = index.segments?.find((candidate) => candidate.records.start
|
|
83
|
-
|
|
96
|
+
function recordOnsetTicks(index, timeline, recordStart, durationTicks) {
|
|
97
|
+
const segment = index.segments?.find((candidate) => candidate.records.start <= recordStart &&
|
|
98
|
+
recordStart < candidate.records.start + candidate.records.count);
|
|
99
|
+
if (segment === undefined)
|
|
100
|
+
return undefined;
|
|
101
|
+
return (timeline.startOffsetTicks +
|
|
102
|
+
segment.startTicks +
|
|
103
|
+
BigInt(recordStart - segment.records.start) * durationTicks);
|
|
84
104
|
}
|
|
85
105
|
/**
|
|
86
106
|
* The gap immediately before `recordStart`, when the index knows where the gaps are.
|
|
@@ -137,7 +157,7 @@ async function readChunk(recording, records, signalIndices, options) {
|
|
|
137
157
|
//
|
|
138
158
|
// A scanned index knows where that record is, and `gapBefore` below already reads it from the
|
|
139
159
|
// same place. Consulting it costs nothing and makes the two fields agree (fixed in 0.3.38).
|
|
140
|
-
const nominalFirstTicks =
|
|
160
|
+
const nominalFirstTicks = recordOnsetTicks(index, timeline, records.start, durationTicks) ??
|
|
141
161
|
timeline.startOffsetTicks + BigInt(records.start) * durationTicks;
|
|
142
162
|
const firstOnsetTicks = onsets[0] ?? nominalFirstTicks;
|
|
143
163
|
const lastOnsetTicks = records.count > 0 ? (onsets[records.count - 1] ?? firstOnsetTicks) : firstOnsetTicks;
|
package/dist/recording.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recording.js","sourceRoot":"","sources":["../src/recording.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"recording.js","sourceRoot":"","sources":["../src/recording.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/constants.ts
CHANGED
package/src/recording.ts
CHANGED
|
@@ -40,6 +40,7 @@ import type {
|
|
|
40
40
|
EdfRecordIndex,
|
|
41
41
|
EdfRecording,
|
|
42
42
|
EdfSignal,
|
|
43
|
+
EdfTimeline,
|
|
43
44
|
OpenOptions,
|
|
44
45
|
ReadOptions,
|
|
45
46
|
RecordRange,
|
|
@@ -102,14 +103,43 @@ export function resolveSignals(
|
|
|
102
103
|
}
|
|
103
104
|
|
|
104
105
|
/**
|
|
105
|
-
* The header-axis onset of
|
|
106
|
+
* The header-axis onset of `recordStart`, when a scanned index knows where that record is.
|
|
106
107
|
*
|
|
107
|
-
* `undefined` for a probed index,
|
|
108
|
-
*
|
|
108
|
+
* `undefined` for a probed index, where nothing better than the nominal grid is available and the
|
|
109
|
+
* caller falls back to it.
|
|
110
|
+
*
|
|
111
|
+
* Two things here are easy to get wrong, and 0.3.38 got both wrong at once.
|
|
112
|
+
*
|
|
113
|
+
* `segment.startTicks` is REBASED — `buildSegmentation` stores `absoluteOnset - originTicks` with
|
|
114
|
+
* `originTicks = timeline.startOffsetTicks` — while the caller consumes this as a header-axis
|
|
115
|
+
* value and subtracts the offset again. On a file whose record 0 begins part-way into a second,
|
|
116
|
+
* which is exactly what record 0's timekeeping TAL is for, a zero-record chunk at record 0 came
|
|
117
|
+
* back at **-0.25 s**: before the instant that defines t = 0. At a segment boundary it reported
|
|
118
|
+
* 99.75 s while carrying a gap that ends at 100 s — the self-contradiction 0.3.38 existed to
|
|
119
|
+
* remove, reintroduced one line away by the fix for it.
|
|
120
|
+
*
|
|
121
|
+
* And it matched only a segment's FIRST record, so a mid-segment record fell through to the
|
|
122
|
+
* nominal grid, which knows nothing about gaps: `readRecords({ start: 5, count: 0 })` said 5 s
|
|
123
|
+
* where `{ start: 5, count: 1 }` said 101 s, for the same record of the same file. Reading the
|
|
124
|
+
* segment that CONTAINS the record answers both the same way (fixed in 0.3.57).
|
|
109
125
|
*/
|
|
110
|
-
function
|
|
111
|
-
|
|
112
|
-
|
|
126
|
+
function recordOnsetTicks(
|
|
127
|
+
index: EdfRecordIndex,
|
|
128
|
+
timeline: EdfTimeline,
|
|
129
|
+
recordStart: number,
|
|
130
|
+
durationTicks: bigint,
|
|
131
|
+
): bigint | undefined {
|
|
132
|
+
const segment = index.segments?.find(
|
|
133
|
+
(candidate) =>
|
|
134
|
+
candidate.records.start <= recordStart &&
|
|
135
|
+
recordStart < candidate.records.start + candidate.records.count,
|
|
136
|
+
);
|
|
137
|
+
if (segment === undefined) return undefined;
|
|
138
|
+
return (
|
|
139
|
+
timeline.startOffsetTicks +
|
|
140
|
+
segment.startTicks +
|
|
141
|
+
BigInt(recordStart - segment.records.start) * durationTicks
|
|
142
|
+
);
|
|
113
143
|
}
|
|
114
144
|
|
|
115
145
|
/**
|
|
@@ -175,7 +205,7 @@ async function readChunk(
|
|
|
175
205
|
// A scanned index knows where that record is, and `gapBefore` below already reads it from the
|
|
176
206
|
// same place. Consulting it costs nothing and makes the two fields agree (fixed in 0.3.38).
|
|
177
207
|
const nominalFirstTicks =
|
|
178
|
-
|
|
208
|
+
recordOnsetTicks(index, timeline, records.start, durationTicks) ??
|
|
179
209
|
timeline.startOffsetTicks + BigInt(records.start) * durationTicks;
|
|
180
210
|
const firstOnsetTicks = onsets[0] ?? nominalFirstTicks;
|
|
181
211
|
const lastOnsetTicks =
|