edf2csv 0.8.55 → 0.8.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/dist/cli.js +3 -3
- package/dist/cli.js.map +1 -1
- package/dist/convert/run.d.ts +23 -0
- package/dist/convert/run.js +97 -7
- package/dist/convert/run.js.map +1 -1
- package/package.json +1 -1
package/dist/convert/run.d.ts
CHANGED
|
@@ -217,6 +217,29 @@ export declare function stdoutRefusal(file: EdfFile, plan: ConversionPlan): Conv
|
|
|
217
217
|
* on is in the file and the plan, both of which `--info` already has.
|
|
218
218
|
*/
|
|
219
219
|
export declare function noSignalFile(file: EdfFile, plan: ConversionPlan): Diagnostic | null;
|
|
220
|
+
/**
|
|
221
|
+
* The signal table an `--annotations-only` run does not write, taken out of the hints about it.
|
|
222
|
+
*
|
|
223
|
+
* That mode writes the event list and nothing else — no signal files at all — and four hints
|
|
224
|
+
* about record timing describe the rows of one. On a recording whose records run backwards it
|
|
225
|
+
* printed both of these over an annotations.csv holding its header and no rows:
|
|
226
|
+
*
|
|
227
|
+
* warning: This is a discontinuous (EDF+D) recording: its data records are not
|
|
228
|
+
* contiguous in time.
|
|
229
|
+
* Each row carries its true recording time, so gaps stay visible instead of
|
|
230
|
+
* being closed.
|
|
231
|
+
* warning: 2 data records start earlier than the record before them.
|
|
232
|
+
* Rows are written in file order, so the time column will not increase
|
|
233
|
+
* monotonically.
|
|
234
|
+
*
|
|
235
|
+
* There are no rows and no time column. The facts above the hints are about the recording and
|
|
236
|
+
* stay; what changes is the sentence describing what the conversion will do with them, which
|
|
237
|
+
* is the same surgery `withTimingPromiseKept` does to the first of these when the record
|
|
238
|
+
* starts cannot be derived.
|
|
239
|
+
*
|
|
240
|
+
* `writesSignals` rather than the option, because the plan is what settles it.
|
|
241
|
+
*/
|
|
242
|
+
export declare function withSignalTableUnwritten(diagnostics: readonly Diagnostic[], writesSignals: boolean): Diagnostic[];
|
|
220
243
|
/**
|
|
221
244
|
* The sidecar files a `--stdout` run does not write, taken out of the sentences about them.
|
|
222
245
|
*
|
package/dist/convert/run.js
CHANGED
|
@@ -98,10 +98,10 @@ export async function convert(inputPath, options = {}) {
|
|
|
98
98
|
readerHungUp,
|
|
99
99
|
annotationCount: 0,
|
|
100
100
|
// Over both lists, because the timing warnings are pushed onto the plan's.
|
|
101
|
-
diagnostics: withSidecarsNamed([
|
|
101
|
+
diagnostics: withSignalTableUnwritten(withSidecarsNamed([
|
|
102
102
|
...withTimingPromiseKept(withoutFileRateWarning(file.diagnostics), timing.starts !== null),
|
|
103
103
|
...plan.diagnostics,
|
|
104
|
-
], { toStdout: true, gzip: plan.gzip }),
|
|
104
|
+
], { toStdout: true, gzip: plan.gzip }), plan.writeSignals),
|
|
105
105
|
plan,
|
|
106
106
|
file,
|
|
107
107
|
elapsedMs: Date.now() - startedAt,
|
|
@@ -199,11 +199,11 @@ export async function convert(inputPath, options = {}) {
|
|
|
199
199
|
annotationCount: annotationsWritten,
|
|
200
200
|
// The directory path needs it too: `--gzip` changes the names, and two of these
|
|
201
201
|
// sentences are a file name and nothing else. See withSidecarsNamed.
|
|
202
|
-
diagnostics: withSidecarsNamed([
|
|
202
|
+
diagnostics: withSignalTableUnwritten(withSidecarsNamed([
|
|
203
203
|
...withTimingPromiseKept(withoutFileRateWarning(file.diagnostics), timing.starts !== null),
|
|
204
204
|
...plan.diagnostics,
|
|
205
205
|
...stale,
|
|
206
|
-
], { toStdout: false, gzip: plan.gzip }),
|
|
206
|
+
], { toStdout: false, gzip: plan.gzip }), plan.writeSignals),
|
|
207
207
|
plan,
|
|
208
208
|
file,
|
|
209
209
|
elapsedMs: Date.now() - startedAt,
|
|
@@ -1500,6 +1500,96 @@ export function noSignalFile(file, plan) {
|
|
|
1500
1500
|
`table --info prints, and in the ${outputCsvName('channels', plan.gzip)} a conversion writes.`,
|
|
1501
1501
|
};
|
|
1502
1502
|
}
|
|
1503
|
+
/**
|
|
1504
|
+
* The signal table an `--annotations-only` run does not write, taken out of the hints about it.
|
|
1505
|
+
*
|
|
1506
|
+
* That mode writes the event list and nothing else — no signal files at all — and four hints
|
|
1507
|
+
* about record timing describe the rows of one. On a recording whose records run backwards it
|
|
1508
|
+
* printed both of these over an annotations.csv holding its header and no rows:
|
|
1509
|
+
*
|
|
1510
|
+
* warning: This is a discontinuous (EDF+D) recording: its data records are not
|
|
1511
|
+
* contiguous in time.
|
|
1512
|
+
* Each row carries its true recording time, so gaps stay visible instead of
|
|
1513
|
+
* being closed.
|
|
1514
|
+
* warning: 2 data records start earlier than the record before them.
|
|
1515
|
+
* Rows are written in file order, so the time column will not increase
|
|
1516
|
+
* monotonically.
|
|
1517
|
+
*
|
|
1518
|
+
* There are no rows and no time column. The facts above the hints are about the recording and
|
|
1519
|
+
* stay; what changes is the sentence describing what the conversion will do with them, which
|
|
1520
|
+
* is the same surgery `withTimingPromiseKept` does to the first of these when the record
|
|
1521
|
+
* starts cannot be derived.
|
|
1522
|
+
*
|
|
1523
|
+
* `writesSignals` rather than the option, because the plan is what settles it.
|
|
1524
|
+
*/
|
|
1525
|
+
export function withSignalTableUnwritten(diagnostics, writesSignals) {
|
|
1526
|
+
if (writesSignals)
|
|
1527
|
+
return [...diagnostics];
|
|
1528
|
+
return diagnostics.map((diagnostic) => {
|
|
1529
|
+
/*
|
|
1530
|
+
And the three calibration warnings, whose hints are about cells.
|
|
1531
|
+
|
|
1532
|
+
Each describes what a conversion does with a channel whose header cannot map cleanly —
|
|
1533
|
+
leaves the cell empty, fills it with the one value the mapping has, keeps the inversion —
|
|
1534
|
+
and `--annotations-only` converts no samples, so none of it happens:
|
|
1535
|
+
|
|
1536
|
+
warning: Signal 0 ("flat") has digital minimum equal to digital maximum (0), so its
|
|
1537
|
+
values cannot be scaled.
|
|
1538
|
+
Its cells are left empty rather than filled with a value the header cannot
|
|
1539
|
+
justify.
|
|
1540
|
+
|
|
1541
|
+
What is wrong with the header is still worth saying, and channels.csv — which that run
|
|
1542
|
+
does write — still carries the calibration. One message also ends in the conversion:
|
|
1543
|
+
"so every sample converts to the same value", over a run converting none.
|
|
1544
|
+
*/
|
|
1545
|
+
if (diagnostic.code === 'DEGENERATE_DIGITAL_RANGE') {
|
|
1546
|
+
return {
|
|
1547
|
+
...diagnostic,
|
|
1548
|
+
hint: 'No samples are converted with --annotations-only, so there are no cells to leave ' +
|
|
1549
|
+
'empty. channels.csv still records the digital range the header gives.',
|
|
1550
|
+
};
|
|
1551
|
+
}
|
|
1552
|
+
if (diagnostic.code === 'DEGENERATE_PHYSICAL_RANGE') {
|
|
1553
|
+
return {
|
|
1554
|
+
...diagnostic,
|
|
1555
|
+
message: diagnostic.message.replace('so every sample converts to the same value.', 'so every sample would convert to the same value.'),
|
|
1556
|
+
hint: 'No samples are converted with --annotations-only. channels.csv still records the ' +
|
|
1557
|
+
'calibration, one point wide.',
|
|
1558
|
+
};
|
|
1559
|
+
}
|
|
1560
|
+
if (diagnostic.code === 'INVERTED_PHYSICAL_RANGE') {
|
|
1561
|
+
return {
|
|
1562
|
+
...diagnostic,
|
|
1563
|
+
hint: 'No samples are converted with --annotations-only. channels.csv records the ' +
|
|
1564
|
+
'physical minimum and maximum in the order the header gives them, inversion included.',
|
|
1565
|
+
};
|
|
1566
|
+
}
|
|
1567
|
+
if (diagnostic.code !== 'DISCONTINUOUS' || diagnostic.hint === undefined)
|
|
1568
|
+
return diagnostic;
|
|
1569
|
+
if (diagnostic.hint.startsWith('Each row carries its true recording time')) {
|
|
1570
|
+
return {
|
|
1571
|
+
...diagnostic,
|
|
1572
|
+
hint: '--annotations-only writes no signal rows, so nothing here is timed from the ' +
|
|
1573
|
+
"records. annotations.csv carries each event's own onset, and the record it came " +
|
|
1574
|
+
'from in record_index.',
|
|
1575
|
+
};
|
|
1576
|
+
}
|
|
1577
|
+
if (diagnostic.hint.startsWith('Rows are written in file order')) {
|
|
1578
|
+
return {
|
|
1579
|
+
...diagnostic,
|
|
1580
|
+
hint: '--annotations-only writes no signal rows, so no time column is affected. ' +
|
|
1581
|
+
"annotations.csv's record_index still names the record each event came from.",
|
|
1582
|
+
};
|
|
1583
|
+
}
|
|
1584
|
+
if (diagnostic.hint.startsWith('Sample times are written from zero')) {
|
|
1585
|
+
return {
|
|
1586
|
+
...diagnostic,
|
|
1587
|
+
hint: '--annotations-only writes no signal rows, so no sample times are written at all.',
|
|
1588
|
+
};
|
|
1589
|
+
}
|
|
1590
|
+
return diagnostic;
|
|
1591
|
+
});
|
|
1592
|
+
}
|
|
1503
1593
|
/**
|
|
1504
1594
|
* The sidecar files a `--stdout` run does not write, taken out of the sentences about them.
|
|
1505
1595
|
*
|
|
@@ -1745,12 +1835,12 @@ bom) {
|
|
|
1745
1835
|
decimals: g.channels.map((c) => c.decimals),
|
|
1746
1836
|
})),
|
|
1747
1837
|
},
|
|
1748
|
-
notes: withSidecarsNamed([
|
|
1838
|
+
notes: withSignalTableUnwritten(withSidecarsNamed([
|
|
1749
1839
|
...withTimingPromiseKept(withoutFileRateWarning(file.diagnostics), timedFromRecords),
|
|
1750
1840
|
...plan.diagnostics,
|
|
1751
1841
|
],
|
|
1752
|
-
// metadata.json is only written into a directory, so this
|
|
1753
|
-
{ toStdout: false, gzip: plan.gzip }).map((d) => ({
|
|
1842
|
+
// metadata.json is only written into a directory, so this is never the stdout case.
|
|
1843
|
+
{ toStdout: false, gzip: plan.gzip }), plan.writeSignals).map((d) => ({
|
|
1754
1844
|
code: d.code,
|
|
1755
1845
|
severity: d.severity,
|
|
1756
1846
|
message: d.message,
|