edf2csv 0.6.113 → 0.6.114

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.
@@ -21,7 +21,18 @@ export class OptionError extends Error {
21
21
  this.name = 'OptionError';
22
22
  }
23
23
  }
24
- /** The largest `toFixed` will accept, and what `--decimals` has always documented. */
24
+ /**
25
+ * The largest `--decimals` accepts, and what both documentation pages state.
26
+ *
27
+ * Not a limit of `toFixed`, whatever this comment used to say. `toFixed` takes 0 to 100 and
28
+ * throws a RangeError at 101 — which is exactly the belief `MAX_DERIVED_DECIMALS` in
29
+ * edf/scale.ts exists to correct, having once clamped the *derived* precision to 20 on the
30
+ * same wrong grounds and rounded a magnetometer channel needing 23 places onto a grid three
31
+ * digital codes wide, losing 69% of its samples in silence.
32
+ *
33
+ * Twenty is a bound on a number a person types by hand, not on what the format can express.
34
+ * The derived precision, which nobody types, runs to 100 and says so.
35
+ */
25
36
  const MAX_DECIMALS = 20;
26
37
  export function assertOptions(options) {
27
38
  const { decimals } = options;
@@ -1 +1 @@
1
- {"version":3,"file":"options.js","sourceRoot":"","sources":["../../src/convert/options.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,yFAAyF;AACzF,MAAM,OAAO,WAAY,SAAQ,KAAK;IACpC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AAED,sFAAsF;AACtF,MAAM,YAAY,GAAG,EAAE,CAAC;AAExB,MAAM,UAAU,aAAa,CAAC,OAM7B;IACC,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IAC7B,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,CAAC,IAAI,QAAQ,GAAG,YAAY,EAAE,CAAC;YAC3E,MAAM,IAAI,WAAW,CACnB,iDAAiD,YAAY,SAAS,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAC5F,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;;;;;;;;;;MAWE;IACF,KAAK,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,CAAU,EAAE,CAAC;QACzD,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,KAAK,KAAK,SAAS;YAAE,SAAS;QAClC,MAAM,QAAQ,GAAG,IAAI,KAAK,UAAU,CAAC;QACrC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,IAAI,KAAK,GAAG,CAAC,CAAC,EAAE,CAAC;YACpF,MAAM,IAAI,WAAW,CAAC,GAAG,IAAI,qCAAqC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACxF,CAAC;IACH,CAAC;IAED;;;;;;;;MAQE;IACF,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAC3B,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACnE,MAAM,IAAI,WAAW,CAAC,wCAAwC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACrF,CAAC;AACH,CAAC;AAED,2FAA2F;AAC3F,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AAC3E,CAAC","sourcesContent":["/**\n * Checking the options a caller passed, before anything is written.\n *\n * The command line has always validated these — `--decimals 1.5` is a usage error and always\n * has been — and the library did not, so the same value behaved differently depending on how\n * it arrived. `convert(file, { decimals: NaN })` resolved successfully having written whole\n * numbers into a column the caller had asked for decimals in, which is the worst of the\n * three: no error, no warning, and output that looks like a deliberate choice. `decimals: -1`\n * reached `toFixed` and came back as a bare RangeError from deep inside the formatter, naming\n * nothing the caller had written. `start: NaN` created the output directory, wrote\n * signals.csv, and then failed with a message about the input being unreadable — a partial\n * conversion, blamed on the file.\n *\n * These run at the top of `buildPlan`, which every path goes through before a directory is\n * created or a stream is opened, so a rejected option leaves nothing behind.\n */\n\n/** A problem with the options a caller passed, as opposed to a problem with the file. */\nexport class OptionError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'OptionError';\n }\n}\n\n/** The largest `toFixed` will accept, and what `--decimals` has always documented. */\nconst MAX_DECIMALS = 20;\n\nexport function assertOptions(options: {\n decimals?: number | undefined;\n start?: number | undefined;\n duration?: number | undefined;\n end?: number | undefined;\n layout?: string | undefined;\n}): void {\n const { decimals } = options;\n if (decimals !== undefined) {\n if (!Number.isInteger(decimals) || decimals < 0 || decimals > MAX_DECIMALS) {\n throw new OptionError(\n `decimals must be a whole number between 0 and ${MAX_DECIMALS}, got ${describe(decimals)}.`,\n );\n }\n }\n\n /*\n `start` and `end` are positions on the recording's own clock, `duration` is a length.\n\n All three were held above zero, which is right for a length and wrong for a position: a\n recording timed from its first record's timekeeping annotation may sit before zero, and\n -100 is then where its first sample is. So a caller could read `plan.range` back as\n `recordingStartSeconds: -100` and not be allowed to ask for it — the same wall\n `parseTimeSpec` put in front of the command line until 0.5.120.\n\n Non-finite is still refused for all three, since NaN reaches a comparison as false and\n would take the whole recording without saying so.\n */\n for (const name of ['start', 'duration', 'end'] as const) {\n const value = options[name];\n if (value === undefined) continue;\n const positive = name === 'duration';\n if (typeof value !== 'number' || !Number.isFinite(value) || (positive && value < 0)) {\n throw new OptionError(`${name} must be a number of seconds, got ${describe(value)}.`);\n }\n }\n\n /*\n Two words, and a caller who writes a third means something the tool cannot do.\n\n The command line has always rejected `--layout tall`. The library took it, put it in\n `plan.layout` for the caller to read back, and wrote the wide layout — so a programmatic\n caller with a typo got a conversion that was not the one they asked for, described by a\n plan that agreed with the typo. Every other option that has a shape is checked here; this\n one was added in 0.5.0 and never joined them.\n */\n const { layout } = options;\n if (layout !== undefined && layout !== 'wide' && layout !== 'long') {\n throw new OptionError(`layout must be \"wide\" or \"long\", got ${describe(layout)}.`);\n }\n}\n\n/** `NaN` and `-1` read better unquoted; anything else is quoted so its type is visible. */\nfunction describe(value: unknown): string {\n return typeof value === 'number' ? String(value) : JSON.stringify(value);\n}\n"]}
1
+ {"version":3,"file":"options.js","sourceRoot":"","sources":["../../src/convert/options.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,yFAAyF;AACzF,MAAM,OAAO,WAAY,SAAQ,KAAK;IACpC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AAED;;;;;;;;;;;GAWG;AACH,MAAM,YAAY,GAAG,EAAE,CAAC;AAExB,MAAM,UAAU,aAAa,CAAC,OAM7B;IACC,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IAC7B,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,CAAC,IAAI,QAAQ,GAAG,YAAY,EAAE,CAAC;YAC3E,MAAM,IAAI,WAAW,CACnB,iDAAiD,YAAY,SAAS,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAC5F,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;;;;;;;;;;MAWE;IACF,KAAK,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,CAAU,EAAE,CAAC;QACzD,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,KAAK,KAAK,SAAS;YAAE,SAAS;QAClC,MAAM,QAAQ,GAAG,IAAI,KAAK,UAAU,CAAC;QACrC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,IAAI,KAAK,GAAG,CAAC,CAAC,EAAE,CAAC;YACpF,MAAM,IAAI,WAAW,CAAC,GAAG,IAAI,qCAAqC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACxF,CAAC;IACH,CAAC;IAED;;;;;;;;MAQE;IACF,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAC3B,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACnE,MAAM,IAAI,WAAW,CAAC,wCAAwC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACrF,CAAC;AACH,CAAC;AAED,2FAA2F;AAC3F,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AAC3E,CAAC","sourcesContent":["/**\n * Checking the options a caller passed, before anything is written.\n *\n * The command line has always validated these — `--decimals 1.5` is a usage error and always\n * has been — and the library did not, so the same value behaved differently depending on how\n * it arrived. `convert(file, { decimals: NaN })` resolved successfully having written whole\n * numbers into a column the caller had asked for decimals in, which is the worst of the\n * three: no error, no warning, and output that looks like a deliberate choice. `decimals: -1`\n * reached `toFixed` and came back as a bare RangeError from deep inside the formatter, naming\n * nothing the caller had written. `start: NaN` created the output directory, wrote\n * signals.csv, and then failed with a message about the input being unreadable — a partial\n * conversion, blamed on the file.\n *\n * These run at the top of `buildPlan`, which every path goes through before a directory is\n * created or a stream is opened, so a rejected option leaves nothing behind.\n */\n\n/** A problem with the options a caller passed, as opposed to a problem with the file. */\nexport class OptionError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'OptionError';\n }\n}\n\n/**\n * The largest `--decimals` accepts, and what both documentation pages state.\n *\n * Not a limit of `toFixed`, whatever this comment used to say. `toFixed` takes 0 to 100 and\n * throws a RangeError at 101 — which is exactly the belief `MAX_DERIVED_DECIMALS` in\n * edf/scale.ts exists to correct, having once clamped the *derived* precision to 20 on the\n * same wrong grounds and rounded a magnetometer channel needing 23 places onto a grid three\n * digital codes wide, losing 69% of its samples in silence.\n *\n * Twenty is a bound on a number a person types by hand, not on what the format can express.\n * The derived precision, which nobody types, runs to 100 and says so.\n */\nconst MAX_DECIMALS = 20;\n\nexport function assertOptions(options: {\n decimals?: number | undefined;\n start?: number | undefined;\n duration?: number | undefined;\n end?: number | undefined;\n layout?: string | undefined;\n}): void {\n const { decimals } = options;\n if (decimals !== undefined) {\n if (!Number.isInteger(decimals) || decimals < 0 || decimals > MAX_DECIMALS) {\n throw new OptionError(\n `decimals must be a whole number between 0 and ${MAX_DECIMALS}, got ${describe(decimals)}.`,\n );\n }\n }\n\n /*\n `start` and `end` are positions on the recording's own clock, `duration` is a length.\n\n All three were held above zero, which is right for a length and wrong for a position: a\n recording timed from its first record's timekeeping annotation may sit before zero, and\n -100 is then where its first sample is. So a caller could read `plan.range` back as\n `recordingStartSeconds: -100` and not be allowed to ask for it — the same wall\n `parseTimeSpec` put in front of the command line until 0.5.120.\n\n Non-finite is still refused for all three, since NaN reaches a comparison as false and\n would take the whole recording without saying so.\n */\n for (const name of ['start', 'duration', 'end'] as const) {\n const value = options[name];\n if (value === undefined) continue;\n const positive = name === 'duration';\n if (typeof value !== 'number' || !Number.isFinite(value) || (positive && value < 0)) {\n throw new OptionError(`${name} must be a number of seconds, got ${describe(value)}.`);\n }\n }\n\n /*\n Two words, and a caller who writes a third means something the tool cannot do.\n\n The command line has always rejected `--layout tall`. The library took it, put it in\n `plan.layout` for the caller to read back, and wrote the wide layout — so a programmatic\n caller with a typo got a conversion that was not the one they asked for, described by a\n plan that agreed with the typo. Every other option that has a shape is checked here; this\n one was added in 0.5.0 and never joined them.\n */\n const { layout } = options;\n if (layout !== undefined && layout !== 'wide' && layout !== 'long') {\n throw new OptionError(`layout must be \"wide\" or \"long\", got ${describe(layout)}.`);\n }\n}\n\n/** `NaN` and `-1` read better unquoted; anything else is quoted so its type is visible. */\nfunction describe(value: unknown): string {\n return typeof value === 'number' ? String(value) : JSON.stringify(value);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "edf2csv",
3
- "version": "0.6.113",
3
+ "version": "0.6.114",
4
4
  "description": "Convert EDF, EDF+ and BDF biosignal recordings (European Data Format) to CSV from the command line. Local, streaming, and never resamples or alters units.",
5
5
  "keywords": [
6
6
  "edf",