edf2csv 0.5.88 → 0.5.90

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 CHANGED
@@ -3,6 +3,67 @@
3
3
  Notable changes to edf2csv. Versions follow [semantic versioning](https://semver.org); while the
4
4
  major version is 0, a minor bump may contain breaking changes.
5
5
 
6
+ ## 0.5.90
7
+
8
+ ### Fixed: the duration warnings described rows a window had excluded
9
+
10
+ ```
11
+ $ edf2csv rec.edf --start 2 --end 3 --out out --strict
12
+ warning: 1 annotation states a duration below zero ... The value is written to annotations.csv as the file gave it ... check these rows before using the durations.
13
+ warning: 1 annotation states a duration that is not a number, so its duration_s cell is empty.
14
+ --strict: 2 warnings raised, so this run is reported as a failure.
15
+
16
+ $ cat out/annotations.csv
17
+ onset_s,duration_s,description,record_index
18
+ 2.5,0.25,clean event,2
19
+ ```
20
+
21
+ One row, with a populated, positive duration. There is no such value, no such cell and no such
22
+ rows — and `--strict` failed the run over two events it never wrote.
23
+
24
+ Both warnings are mine, from 0.5.55 and 0.5.58, and both were raised from the counts the
25
+ decoder accumulates over the whole file while `annotations.csv` is filtered to the requested
26
+ window. `--info` had the other half of it: on an EDF+D recording it printed "The value is
27
+ written to annotations.csv as the file gave it" while writing no files at all.
28
+
29
+ Counted from the events themselves now, after the same filter the writer applies, so the count
30
+ and the sentence describe the same rows. An unreadable duration is carried on the event as
31
+ `durationUnreadable`, because `duration: null` cannot say whether the file gave one — which is
32
+ the ambiguity those warnings exist to flag, and a library caller now has it too. A negative
33
+ duration needs no flag; the value is right there.
34
+
35
+ `--info` raises them against the window it was given, so it predicts what the conversion will
36
+ say rather than a different set. On a continuous EDF+ it still says nothing, because it does not
37
+ read the whole annotation channel — that is the documented limit of a header read, not a
38
+ regression.
39
+
40
+ ## 0.5.89
41
+
42
+ ### Fixed: the getting-started example asked for a channel the recording does not have
43
+
44
+ ```bash
45
+ edf2csv sleep-study.edf --start 1h --duration 5m \
46
+ --channels "EEG Fpz-Cz,ECG" --out ./epoch-42
47
+ ```
48
+
49
+ exits 2 with `No channel named "ECG"`. The `--info` table forty lines up the same page lists
50
+ that recording's five channels — EEG Fpz-Cz, EEG Pz-Oz, EOG horizontal, Resp oro-nasal, Temp
51
+ rectal — and none of them is ECG. It is the page's one example of combining a window, a filter
52
+ and a destination, and it is the third command a new reader runs.
53
+
54
+ The same pair appears on four pages: getting-started, recipes, and faq twice. The fifth is in
55
+ warnings-and-errors, demonstrating the mixed-rate warning, where the quoted rates were wrong for
56
+ this recording too — "2 different sampling rates (256 Hz, 128 Hz)" against a file whose channels
57
+ run at 100, 10 and 1 Hz. That one now pairs `EEG Fpz-Cz` with `Temp rectal` and quotes 100 Hz
58
+ and 1 Hz, which is what the file gives.
59
+
60
+ api.md's JavaScript examples have been executed against a fixture for a long time. The shell
61
+ examples were checked by nobody, and this is the part of them a test can check without a shell:
62
+ a channel named for this recording either exists in it or does not. It reads every page and the
63
+ README, and it took two attempts — the first missed getting-started's command entirely, because
64
+ that one wraps with a trailing backslash and its `--channels` is on the second line. It joins
65
+ continuations first now.
66
+
6
67
  ## 0.5.88
7
68
 
8
69
  ### Fixed: a worker killed from outside made the batch exit 2, "the command line is the problem"
package/dist/cli.js CHANGED
@@ -18,7 +18,7 @@ import process from 'node:process';
18
18
  import { EdfError } from './edf/errors.js';
19
19
  import { EdfFile } from './edf/reader.js';
20
20
  import { buildPlan, withoutFileRateWarning } from './convert/plan.js';
21
- import { ConversionError, USAGE_ERROR_CODES, convert, defaultOutputDir, stdoutRefusal, } from './convert/run.js';
21
+ import { ConversionError, USAGE_ERROR_CODES, convert, defaultOutputDir, durationDiagnostics, stdoutRefusal, } from './convert/run.js';
22
22
  import { ChannelSelectionError } from './convert/channels.js';
23
23
  // Shared with the library so a bad option is the same error whichever way it arrived.
24
24
  import { OptionError } from './convert/options.js';
@@ -687,6 +687,17 @@ async function showInfo(input, shared, asJson, jsonIndent, batch = false, toStdo
687
687
  from describing the recording — and being told the command will not work is exactly
688
688
  what was asked. The conversion's own guard supplies the words, so there is one wording.
689
689
  */
690
+ /*
691
+ What the conversion would say about the durations it would write.
692
+
693
+ Same window the conversion applies, so --info predicts the warnings rather than a
694
+ different set. Raised here rather than in the parser because the counts have to be of
695
+ the rows that reach annotations.csv — see durationDiagnostics.
696
+ */
697
+ plan.diagnostics.push(...durationDiagnostics(annotationData.annotations, {
698
+ from: plan.range.startSeconds,
699
+ to: plan.range.endSeconds,
700
+ }));
690
701
  if (toStdout) {
691
702
  const refusal = stdoutRefusal(file, plan);
692
703
  if (refusal) {