edf2csv 0.8.5 → 0.8.7

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.
@@ -231,3 +231,20 @@ export declare function noSignalFile(file: EdfFile, plan: ConversionPlan): Diagn
231
231
  * options, which `--info` already has.
232
232
  */
233
233
  export declare function noAnnotations(file: EdfFile, options: ConvertOptions): Diagnostic | null;
234
+ /**
235
+ * `--annotations-only` that wrote no events, and why.
236
+ *
237
+ * The two causes are told apart because the answers are different. A channel holding nothing
238
+ * but timekeeping entries has nothing to export and never will; a window that excluded every
239
+ * event is a thing the caller can change, and the commonest reason is reading the window off
240
+ * a clock the recording does not use — `--start` and `--end` are on the recording's own,
241
+ * which `--info` prints as "Timed from".
242
+ *
243
+ * `NO_ANNOTATIONS` rather than a new code, since it is the same statement its other raising
244
+ * makes — there are no events to export — about the same flag, and a code is matched on by
245
+ * scripts that should not have to learn a second one for the same fact.
246
+ */
247
+ export declare function emptyAnnotations(total: number, window: {
248
+ from: number;
249
+ to: number;
250
+ }): Diagnostic;
@@ -152,6 +152,26 @@ export async function convert(inputPath, options = {}) {
152
152
  const result = await writeAnnotationsCsv(outputDir, annotationData.annotations, window, options.gzip === true, options.bom === true);
153
153
  written.push(result);
154
154
  annotationsWritten = result.rows;
155
+ /*
156
+ A run whose only table came out empty, which nothing said.
157
+
158
+ `emptyWindow`'s own docstring states the rule this was breaking: "everywhere else that
159
+ a request produces nothing this tool says so: a --channels term matching nothing is an
160
+ error, and --annotations-only on a file with no events raises NO_ANNOTATIONS." The
161
+ second half is true only of a file with no annotation *channel*. Give the flag a
162
+ recording whose channel carries nothing but timekeeping, or a window its events fall
163
+ outside, and the run writes an annotations.csv holding one header line, prints "Wrote
164
+ … annotations.csv 0 rows", exits 0 and passes --strict — which is exactly the shape
165
+ EMPTY_WINDOW exists to refuse on the signal side, arriving by the other route.
166
+
167
+ Only when there is no signal table either, so this is the whole of what the run
168
+ produced. A windowed conversion of a recording whose events sit elsewhere is
169
+ ordinary and its signals are the point; warning there would fire on most windows of
170
+ most annotated recordings, which is how a warning stops being read.
171
+ */
172
+ if (!plan.writeSignals && annotationsWritten === 0) {
173
+ plan.diagnostics.push(emptyAnnotations(annotationData.annotations.length, window));
174
+ }
155
175
  }
156
176
  written.push(await writeChannelsCsv(outputDir, file, plan, options.gzip === true, options.bom === true));
157
177
  /*
@@ -1402,6 +1422,36 @@ export function noAnnotations(file, options) {
1402
1422
  hint: 'Plain EDF files carry no annotations. Convert without --annotations-only to get the signals.',
1403
1423
  };
1404
1424
  }
1425
+ /**
1426
+ * `--annotations-only` that wrote no events, and why.
1427
+ *
1428
+ * The two causes are told apart because the answers are different. A channel holding nothing
1429
+ * but timekeeping entries has nothing to export and never will; a window that excluded every
1430
+ * event is a thing the caller can change, and the commonest reason is reading the window off
1431
+ * a clock the recording does not use — `--start` and `--end` are on the recording's own,
1432
+ * which `--info` prints as "Timed from".
1433
+ *
1434
+ * `NO_ANNOTATIONS` rather than a new code, since it is the same statement its other raising
1435
+ * makes — there are no events to export — about the same flag, and a code is matched on by
1436
+ * scripts that should not have to learn a second one for the same fact.
1437
+ */
1438
+ export function emptyAnnotations(total, window) {
1439
+ const windowed = (window.from !== -Infinity || window.to !== Infinity) && total > 0;
1440
+ return {
1441
+ code: 'NO_ANNOTATIONS',
1442
+ severity: 'warning',
1443
+ message: windowed
1444
+ ? `None of this recording's ${counted(total, 'event')} fall inside the requested ` +
1445
+ `window, so annotations.csv holds its header and no rows.`
1446
+ : `This recording's annotation channel carries no events, so annotations.csv holds ` +
1447
+ `its header and no rows.`,
1448
+ hint: windowed
1449
+ ? '--start and --end are read on the recording\'s own clock, which --info prints as ' +
1450
+ '"Timed from", and an event is kept when its onset falls inside the window.'
1451
+ : 'The channel holds only the timekeeping entries that say where each data record ' +
1452
+ 'sits, and those are never exported.',
1453
+ };
1454
+ }
1405
1455
  /** Raised when the input moved while it was being read. See where it is pushed. */
1406
1456
  function inputChanged(hadChecksum) {
1407
1457
  return {