linked-rolls 0.70.0 → 0.72.0

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.
Files changed (143) hide show
  1. package/README.md +106 -5
  2. package/lib/analysis/constraints.d.ts +7 -0
  3. package/lib/analysis/constraints.js +1 -0
  4. package/lib/analysis/ownPaper.d.ts +5 -1
  5. package/lib/analysis/ownPaper.js +5 -1
  6. package/lib/analysis/paper.d.ts +22 -4
  7. package/lib/analysis/paper.js +6 -0
  8. package/lib/analysis/reservations.d.ts +24 -1
  9. package/lib/analysis/reservations.js +15 -1
  10. package/lib/analysis/sigla.d.ts +6 -1
  11. package/lib/analysis/sigla.js +5 -1
  12. package/lib/analysis/stemma.d.ts +6 -1
  13. package/lib/analysis/stemma.js +6 -1
  14. package/lib/analysis/text.d.ts +16 -2
  15. package/lib/analysis/text.js +16 -2
  16. package/lib/analysis/witnesses.d.ts +20 -1
  17. package/lib/analysis/witnesses.js +4 -0
  18. package/lib/collation/Collation.d.ts +47 -8
  19. package/lib/collation/Collation.js +29 -5
  20. package/lib/collation/alignment.d.ts +16 -3
  21. package/lib/collation/alignment.js +15 -3
  22. package/lib/collation/scatter.d.ts +50 -9
  23. package/lib/collation/scatter.js +11 -1
  24. package/lib/collation/statistics.d.ts +39 -9
  25. package/lib/collation/statistics.js +27 -6
  26. package/lib/collation/substitution.d.ts +5 -0
  27. package/lib/collation/substitution.js +4 -0
  28. package/lib/emulation/Emulation.d.ts +16 -1
  29. package/lib/emulation/Emulation.js +10 -0
  30. package/lib/emulation/negotiation.d.ts +1 -0
  31. package/lib/emulation/negotiation.js +1 -0
  32. package/lib/filiation/adoption.d.ts +47 -0
  33. package/lib/filiation/adoption.js +190 -0
  34. package/lib/filiation/changes.d.ts +33 -0
  35. package/lib/filiation/changes.js +38 -0
  36. package/lib/filiation/index.d.ts +12 -0
  37. package/lib/filiation/index.js +12 -0
  38. package/lib/filiation/presence.d.ts +50 -0
  39. package/lib/filiation/presence.js +122 -0
  40. package/lib/filiation/proposal.d.ts +132 -0
  41. package/lib/filiation/proposal.js +376 -0
  42. package/lib/filiation/readings.d.ts +108 -0
  43. package/lib/filiation/readings.js +281 -0
  44. package/lib/filiation/search.d.ts +113 -0
  45. package/lib/filiation/search.js +268 -0
  46. package/lib/filiation/systems.d.ts +21 -0
  47. package/lib/filiation/systems.js +39 -0
  48. package/lib/filiation/trees.d.ts +20 -0
  49. package/lib/filiation/trees.js +69 -0
  50. package/lib/index.d.ts +34 -2
  51. package/lib/index.js +3 -1
  52. package/lib/io/asJsonLd.d.ts +10 -0
  53. package/lib/io/asJsonLd.js +10 -0
  54. package/lib/io/context.d.ts +16 -2
  55. package/lib/io/context.js +16 -2
  56. package/lib/io/importJsonLd.d.ts +1 -0
  57. package/lib/io/importJsonLd.js +1 -0
  58. package/lib/io/migrate.d.ts +8 -0
  59. package/lib/io/migrate.js +8 -0
  60. package/lib/lookup/lookup.d.ts +29 -5
  61. package/lib/lookup/lookup.js +29 -5
  62. package/lib/lookup/paths.d.ts +23 -3
  63. package/lib/lookup/paths.js +17 -3
  64. package/lib/model/Agent.d.ts +28 -2
  65. package/lib/model/Agent.js +15 -1
  66. package/lib/model/Assumption.d.ts +96 -7
  67. package/lib/model/Assumption.js +65 -7
  68. package/lib/model/ConditionState.d.ts +1 -0
  69. package/lib/model/Edit.d.ts +10 -0
  70. package/lib/model/Edit.js +8 -0
  71. package/lib/model/Edition.d.ts +11 -0
  72. package/lib/model/Edition.js +1 -0
  73. package/lib/model/Feature.d.ts +74 -7
  74. package/lib/model/Feature.js +41 -3
  75. package/lib/model/FeatureSource.d.ts +14 -1
  76. package/lib/model/FeatureSource.js +7 -1
  77. package/lib/model/Perforator.d.ts +10 -0
  78. package/lib/model/Perforator.js +1 -0
  79. package/lib/model/Quantity.d.ts +160 -13
  80. package/lib/model/Quantity.js +110 -6
  81. package/lib/model/RollCopy.d.ts +74 -12
  82. package/lib/model/RollCopy.js +53 -10
  83. package/lib/model/Symbol.d.ts +38 -1
  84. package/lib/model/Symbol.js +16 -0
  85. package/lib/model/TrackCalibration.d.ts +10 -2
  86. package/lib/model/TrackCalibration.js +9 -2
  87. package/lib/model/Version.d.ts +24 -4
  88. package/lib/model/Version.js +19 -4
  89. package/lib/model/notes.d.ts +15 -2
  90. package/lib/model/notes.js +9 -2
  91. package/lib/model/procedures.d.ts +5 -1
  92. package/lib/model/procedures.js +5 -1
  93. package/lib/model/vocabulary.d.ts +6 -1
  94. package/lib/model/vocabulary.js +6 -1
  95. package/lib/ops/beliefs.d.ts +23 -1
  96. package/lib/ops/beliefs.js +23 -1
  97. package/lib/ops/collation.d.ts +3 -0
  98. package/lib/ops/collation.js +3 -0
  99. package/lib/ops/commands.d.ts +17 -2
  100. package/lib/ops/commands.js +17 -2
  101. package/lib/ops/copies.d.ts +37 -6
  102. package/lib/ops/copies.js +37 -6
  103. package/lib/ops/draft.d.ts +2 -0
  104. package/lib/ops/draft.js +1 -0
  105. package/lib/ops/edits.d.ts +5 -1
  106. package/lib/ops/edits.js +5 -1
  107. package/lib/ops/features.d.ts +12 -1
  108. package/lib/ops/features.js +7 -0
  109. package/lib/ops/versions.d.ts +15 -3
  110. package/lib/ops/versions.js +15 -3
  111. package/lib/readers/phillipsEroll.d.ts +12 -1
  112. package/lib/readers/phillipsEroll.js +6 -1
  113. package/lib/readers/spencerBar.d.ts +12 -1
  114. package/lib/readers/spencerBar.js +7 -1
  115. package/lib/readers/stanfordAton.d.ts +15 -0
  116. package/lib/readers/stanfordAton.js +9 -0
  117. package/lib/schema.json +10 -0
  118. package/lib/shared/utils.d.ts +12 -0
  119. package/lib/spec/context.json +4 -0
  120. package/lib/systems/ReproducingSystem.d.ts +46 -3
  121. package/lib/systems/TrackerBar.d.ts +45 -4
  122. package/lib/systems/TrackerBar.js +20 -3
  123. package/lib/systems/index.d.ts +9 -2
  124. package/lib/systems/index.js +9 -2
  125. package/lib/systems/velocity.d.ts +1 -0
  126. package/lib/systems/velocity.js +1 -0
  127. package/lib/systems/welte.d.ts +18 -3
  128. package/lib/systems/welte.js +9 -2
  129. package/lib/systems/welteLicensee/bar.d.ts +1 -0
  130. package/lib/systems/welteLicensee/bar.js +1 -0
  131. package/lib/systems/welteLicensee/system.d.ts +18 -0
  132. package/lib/systems/welteLicensee/system.js +17 -0
  133. package/lib/systems/welteT100/bar.d.ts +8 -0
  134. package/lib/systems/welteT100/bar.js +4 -0
  135. package/lib/systems/welteT100/system.d.ts +46 -5
  136. package/lib/systems/welteT100/system.js +29 -3
  137. package/lib/systems/welteT98/bar.d.ts +6 -0
  138. package/lib/systems/welteT98/bar.js +2 -0
  139. package/lib/systems/welteT98/system.d.ts +58 -5
  140. package/lib/systems/welteT98/system.js +42 -3
  141. package/lib/validate.d.ts +16 -0
  142. package/lib/validate.js +15 -0
  143. package/package.json +2 -1
package/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # linked-rolls
2
2
 
3
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.23270944.svg)](https://doi.org/10.5281/zenodo.23270944)
4
+
3
5
  A TypeScript library for digital editions of piano rolls. It reads roll
4
6
  copies from scans and analysis files, collates them into versions,
5
7
  records editorial assumptions together with the beliefs behind them,
@@ -39,6 +41,13 @@ const symbols = snapshotOf(edition, childId)
39
41
  const document = asJsonLd(edition)
40
42
  ```
41
43
 
44
+ The [API reference](https://pfefferniels.github.io/linked-rolls/api/)
45
+ documents the public interface, and the
46
+ [recipes](https://pfefferniels.github.io/linked-rolls/api/documents/Recipes.html)
47
+ show how to read an edition, get the text of a version, see what a
48
+ version changed, play it and write a change back. What the reference
49
+ leaves out is internal and may change in any release.
50
+
42
51
  What is read off an edition, such as `snapshotOf`, `placeOf`,
43
52
  `versionIn` or `pathIn`, is worked out once for each state of it and
44
53
  kept for as long as the state is. Every change through `produce` yields
@@ -88,14 +97,50 @@ const midi = midiOf(events, welteT100System.name, welteT100System.defaultOptions
88
97
  The systems are `linked-rolls/welte-t100` (red Welte),
89
98
  `linked-rolls/welte-t98` (green Welte) and `linked-rolls/welte-licensee`.
90
99
 
100
+ ## Proposing a stemma
101
+
102
+ Which versions there are, lost ones included, how they derive from each
103
+ other and which edits belong to which can be proposed from the copies
104
+ alone. `proposeStemma` collates the transcribed copies all at once,
105
+ notes which copies have, lack or cannot show each reading, and scores
106
+ every stemma the copies admit, up to seven copies. A reading arising
107
+ costs ten times a reading lost. Losses count for less where the
108
+ editorial principles of an edition say they are weak evidence: a
109
+ redundancy cleaned up, or what a re-cut for another system lacks. On
110
+ the best stemma, each reading arises in the latest version all copies
111
+ carrying it descend from.
112
+
113
+ ```ts
114
+ import { produce } from 'immer'
115
+ import { adoptStemma, proposeStemma, stemmaChanges } from 'linked-rolls'
116
+
117
+ const proposal = proposeStemma(edition)
118
+ proposal.notation // '*(St1(*(Ne1,St2(Bo1,Ch1))),Wi1)' for WM 225
119
+ proposal.supports // by how much the copies decide each grouping
120
+
121
+ const adopted = produce(edition, adoptStemma(proposal))
122
+ const changes = stemmaChanges(edition, adopted)
123
+ ```
124
+
125
+ Adopting keeps what the edition holds wherever the proposal stands for
126
+ it: the ids of versions and symbols, a derivation's belief, and the
127
+ edits the editor wrote, which hold their versions to what they insert
128
+ and delete. Motivations, beliefs and versions known only from a
129
+ recording remain the editor's to state.
130
+
131
+ The costs are those with which the stemma of WM 225 comes out of its
132
+ six copies. They were found by searching for such values, so they show
133
+ that the stemma is consistent with these principles, not that the
134
+ principles confirm it.
135
+
91
136
  ## Format
92
137
 
93
138
  The export uses the Roll Edition Ontology (REO), namespace
94
139
  `https://w3id.org/reo/`, together with CIDOC CRM, LRMoo and CRMinf. The
95
140
  ontology is in `ontology/`. It is published with its context and the
96
141
  documentation of the format at
97
- https://pfefferniels.github.io/linked-rolls/ (the w3id.org identifiers are
98
- not registered yet).
142
+ https://pfefferniels.github.io/linked-rolls/, to which the w3id.org
143
+ identifiers redirect.
99
144
 
100
145
  Beliefs are written as JSON-LD-star annotations (`@annotation`), so you
101
146
  need a processor that supports JSON-LD-star to read them.
@@ -107,10 +152,66 @@ npm ci
107
152
  npm test
108
153
  npm run lint
109
154
  npm run build
155
+ npm run build:api # the API reference, into docs/api
110
156
  ```
111
157
 
158
+ TypeDoc runs from `tools/typedoc` with a TypeScript 5 of its own, as
159
+ TypeScript 7 no longer has the compiler API it reads the source with.
160
+
112
161
  ## Releasing
113
162
 
114
- Raise the version in `package.json`, commit, and push a tag
115
- `v<version>`. The `publish.yml` workflow builds, tests and publishes to
116
- npm.
163
+ Raise the version in `package.json` and in `CITATION.cff`, there with
164
+ the day as `date-released`, commit, and push a tag `v<version>`. The
165
+ `publish.yml` workflow builds, tests and publishes to npm, then makes a
166
+ GitHub release of the tag, which Zenodo archives with a DOI. A test fails
167
+ while the two versions differ.
168
+
169
+ ## About
170
+
171
+ linked-rolls grew out of the dissertation *Grünfelds Geist.
172
+ Rekonstruktion einer Welte-Mignon-Klavierrollenaufnahme* (Niels
173
+ Pfeffer, Eberhard Karls Universität Tübingen, Musikwissenschaftliches
174
+ Institut, 2026), which edits Alfred Grünfeld's 1905 recording of
175
+ Schumann's *Träumerei*, Welte-Mignon roll 225, from its surviving
176
+ copies. That edition is published at https://welte225.org/ and can be
177
+ read in the [Roll Desk](https://rolldesk.welte225.org/).
178
+
179
+ Its aim is a scholarly edition of a piano roll that treats the roll the
180
+ way a critical edition treats a text: every copy is a witness, the
181
+ differences between copies are collated into versions, and every
182
+ editorial decision is recorded together with the evidence and the
183
+ beliefs behind it, so that a reader can retrace and contest it. The
184
+ data are meant to be reused outside the library, which is why the
185
+ format is linked data built on CIDOC CRM rather than a file format of
186
+ its own.
187
+
188
+ ### Related formats
189
+
190
+ Several formats have been developed or used to represent piano rolls at
191
+ different stages of processing:
192
+
193
+ - **Scan images:** CIS and MRS, often accompanied by ANN metadata.
194
+ - **Event lists:** Wayne Stahnke's RAW, WEB and BAR, PRF, SCN, ROL, and
195
+ the e-roll MIDI files of pneumatic readers.
196
+ - **Symbolic descriptions:** the Roll Analysis files of the Stanford
197
+ University Piano Roll Archive, serialised as ATON.
198
+
199
+ None of them is concerned with what a critical edition needs: an
200
+ apparatus of the variants between copies, the traces a copy carries
201
+ (handwritten notes, patches, perforations added later), a record of how
202
+ and on what assumptions each reading came about, and identifiers by
203
+ which all of this can be referred to and annotated. The dissertation
204
+ surveys these formats in its chapter on variants.
205
+
206
+ Editions of texts and of notated music are mostly encoded in TEI and
207
+ MEI. A roll edition, however, is less a nested text document than a
208
+ flat structure of roll events described in numbers, and its data should
209
+ link to other domains, which is why the Roll Edition Format is JSON-LD
210
+ built on CIDOC CRM and LRMoo.
211
+
212
+ ### Maintenance
213
+
214
+ The library is maintained by Niels Pfeffer
215
+ ([ORCID 0000-0002-6210-7255](https://orcid.org/0000-0002-6210-7255)). It
216
+ is released under the MIT licence, the ontology and its documentation
217
+ under CC BY 4.0.
@@ -1,4 +1,10 @@
1
1
  import { Edition } from "../model/Edition.js";
2
+ /**
3
+ * Where the edition cannot hold as stated, as `constraintProblems`
4
+ * reports it: the version and the symbol concerned, and what is wrong
5
+ * with it.
6
+ * @category Analysis
7
+ */
2
8
  export type ConstraintProblem = {
3
9
  version: string;
4
10
  symbol: string;
@@ -13,5 +19,6 @@ export type ConstraintProblem = {
13
19
  * expression the version's own bar cannot read, a carrier sitting on a
14
20
  * track that does not say what its symbol says, and a strike that takes
15
21
  * nothing out.
22
+ * @category Analysis
16
23
  */
17
24
  export declare const constraintProblems: (edition: Edition) => ConstraintProblem[];
@@ -137,6 +137,7 @@ const strikesBitingNothing = (edition, version) => {
137
137
  * expression the version's own bar cannot read, a carrier sitting on a
138
138
  * track that does not say what its symbol says, and a strike that takes
139
139
  * nothing out.
140
+ * @category Analysis
140
141
  */
141
142
  export const constraintProblems = (edition) => {
142
143
  // What a symbol's carriers and the copies' paper say holds whichever
@@ -1,7 +1,10 @@
1
1
  import type { Version } from "../model/Version.js";
2
2
  import { PaperOfSystem } from "./paper.js";
3
3
  import { Edition } from "../model/Edition.js";
4
- /** What the alignments say about the paper of the version's own system, where they say anything. */
4
+ /**
5
+ * What the alignments say about the paper of the version's own system, where they say anything.
6
+ * @category Analysis
7
+ */
5
8
  export declare const paperOfVersion: (edition: Edition, version: Readonly<Version>) => PaperOfSystem | undefined;
6
9
  /**
7
10
  * How a place on the edition's shared axis relates to the paper of
@@ -17,5 +20,6 @@ export declare const paperOfVersion: (edition: Edition, version: Readonly<Versio
17
20
  *
18
21
  * Nothing where no copy of the version's system measures its paper,
19
22
  * which leaves the performance on the axis.
23
+ * @category Analysis
20
24
  */
21
25
  export declare const toOwnPaperOf: (edition: Edition, version: Readonly<Version>) => number | undefined;
@@ -1,6 +1,9 @@
1
1
  import { defaultTrackerBar, trackerBarOf } from "../systems/index.js";
2
2
  import { paperOf } from "./paper.js";
3
- /** What the alignments say about the paper of the version's own system, where they say anything. */
3
+ /**
4
+ * What the alignments say about the paper of the version's own system, where they say anything.
5
+ * @category Analysis
6
+ */
4
7
  export const paperOfVersion = (edition, version) => {
5
8
  const system = (trackerBarOf(version.system) ?? defaultTrackerBar).id;
6
9
  return paperOf(edition)?.systems.find(paper => paper.system === system);
@@ -19,5 +22,6 @@ export const paperOfVersion = (edition, version) => {
19
22
  *
20
23
  * Nothing where no copy of the version's system measures its paper,
21
24
  * which leaves the performance on the axis.
25
+ * @category Analysis
22
26
  */
23
27
  export const toOwnPaperOf = (edition, version) => paperOfVersion(edition, version)?.toOwnPaper;
@@ -8,15 +8,20 @@ import { MetersPerMinute, Percent } from "../model/Quantity.js";
8
8
  * copies of one system to say: the three red copies of Welte 225 spread
9
9
  * by 0.19 %. It includes the scanner's error along the roll, which the
10
10
  * alignment cannot tell from the paper's.
11
+ * @category Analysis
11
12
  */
12
13
  export declare const PAPER_SPREAD: Percent;
13
14
  /**
14
15
  * How far a paper speed a label or the literature states is taken to be
15
16
  * from the speed a copy was cut at: the literature gives the red roll's
16
17
  * three metres a minute as 2.9 as well (Bärtsch 2020), which is 3.4 %.
18
+ * @category Analysis
17
19
  */
18
20
  export declare const SPEED_TOLERANCE = 0.035;
19
- /** What the alignments say about one copy's paper. */
21
+ /**
22
+ * What the alignments say about one copy's paper.
23
+ * @category Analysis
24
+ */
20
25
  export interface PaperOfCopy {
21
26
  copy: string;
22
27
  /** The system the copy was cut for, by the id of its bar. */
@@ -26,7 +31,10 @@ export interface PaperOfCopy {
26
31
  /** Whether a strain measured on the copy went into it, rather than the spread of paper alone. */
27
32
  measured: boolean;
28
33
  }
29
- /** What the alignments say about the paper the copies of one system were cut on. */
34
+ /**
35
+ * What the alignments say about the paper the copies of one system were cut on.
36
+ * @category Analysis
37
+ */
30
38
  export interface PaperOfSystem {
31
39
  /** The system, by the id of its bar. */
32
40
  system: string;
@@ -50,7 +58,10 @@ export interface PaperOfSystem {
50
58
  /** The copies of the system it rests on. */
51
59
  copies: string[];
52
60
  }
53
- /** What the alignments of an edition say about the paper of its copies, and how surely. */
61
+ /**
62
+ * What the alignments of an edition say about the paper of its copies, and how surely.
63
+ * @category Analysis
64
+ */
54
65
  export interface PaperReading {
55
66
  /** The copy whose millimetres are the axis. */
56
67
  reference: string;
@@ -93,9 +104,13 @@ export interface PaperReading {
93
104
  * Copies whose places are not places on the paper, such as a roll
94
105
  * reader's, say nothing about the paper and are left out. Nothing is
95
106
  * said where the edition has no reference copy.
107
+ * @category Analysis
96
108
  */
97
109
  export declare const paperOf: (edition: Pick<Edition, 'copies' | 'referenceCopy'>) => PaperReading | undefined;
98
- /** Where the alignments of the copies, or what they say about the paper, want looking into. */
110
+ /**
111
+ * Where the alignments of the copies, or what they say about the paper, want looking into.
112
+ * @category Analysis
113
+ */
99
114
  export type AlignmentProblem = {
100
115
  copy: string;
101
116
  problem:
@@ -129,6 +144,7 @@ export type AlignmentProblem = {
129
144
  * where no such copy states one; in particular, a copy that reaches the
130
145
  * version only through a later one says nothing about it, since the later
131
146
  * one may have been cut for another speed.
147
+ * @category Analysis
132
148
  */
133
149
  export declare const paperSpeedOf: (edition: Edition, versionId: string) => MetersPerMinute | undefined;
134
150
  /**
@@ -136,6 +152,7 @@ export declare const paperSpeedOf: (edition: Edition, versionId: string) => Mete
136
152
  * the paper, want looking into. None of it is recomputed, so it is cheap
137
153
  * to ask; whether an alignment would come out otherwise if found again
138
154
  * is `alignmentFor`'s to say.
155
+ * @category Analysis
139
156
  */
140
157
  export declare const alignmentProblems: (edition: Pick<Edition, 'copies' | 'referenceCopy'>) => AlignmentProblem[];
141
158
  /**
@@ -152,5 +169,6 @@ export declare const alignmentProblems: (edition: Pick<Edition, 'copies' | 'refe
152
169
  * two versions re-cut for one system, the ratio is theirs together.
153
170
  * Nothing is given for a version that derives from none, or from one on
154
171
  * its own system, whose paper it keeps.
172
+ * @category Analysis
155
173
  */
156
174
  export declare const lengthRatioOf: (edition: Edition, versionId: string) => LengthRatio | undefined;
@@ -12,12 +12,14 @@ import { defaultTrackerBar, trackerBarOf } from "../systems/index.js";
12
12
  * copies of one system to say: the three red copies of Welte 225 spread
13
13
  * by 0.19 %. It includes the scanner's error along the roll, which the
14
14
  * alignment cannot tell from the paper's.
15
+ * @category Analysis
15
16
  */
16
17
  export const PAPER_SPREAD = percent(0.2);
17
18
  /**
18
19
  * How far a paper speed a label or the literature states is taken to be
19
20
  * from the speed a copy was cut at: the literature gives the red roll's
20
21
  * three metres a minute as 2.9 as well (Bärtsch 2020), which is 3.4 %.
22
+ * @category Analysis
21
23
  */
22
24
  export const SPEED_TOLERANCE = 0.035;
23
25
  /** The kinds of source that give places on the paper, so that the length between two of them is the paper's. */
@@ -116,6 +118,7 @@ const inverse = (matrix) => {
116
118
  * Copies whose places are not places on the paper, such as a roll
117
119
  * reader's, say nothing about the paper and are left out. Nothing is
118
120
  * said where the edition has no reference copy.
121
+ * @category Analysis
119
122
  */
120
123
  export const paperOf = (edition) => {
121
124
  const reference = referenceCopyOf(edition);
@@ -225,6 +228,7 @@ const statedSpeed = (copy) => {
225
228
  * where no such copy states one; in particular, a copy that reaches the
226
229
  * version only through a later one says nothing about it, since the later
227
230
  * one may have been cut for another speed.
231
+ * @category Analysis
228
232
  */
229
233
  export const paperSpeedOf = (edition, versionId) => {
230
234
  const version = versionIn(edition, versionId);
@@ -248,6 +252,7 @@ const referenceSpeed = (reference) => {
248
252
  * the paper, want looking into. None of it is recomputed, so it is cheap
249
253
  * to ask; whether an alignment would come out otherwise if found again
250
254
  * is `alignmentFor`'s to say.
255
+ * @category Analysis
251
256
  */
252
257
  export const alignmentProblems = (edition) => {
253
258
  const reference = referenceCopyOf(edition);
@@ -297,6 +302,7 @@ export const alignmentProblems = (edition) => {
297
302
  * two versions re-cut for one system, the ratio is theirs together.
298
303
  * Nothing is given for a version that derives from none, or from one on
299
304
  * its own system, whose paper it keeps.
305
+ * @category Analysis
300
306
  */
301
307
  export const lengthRatioOf = (edition, versionId) => {
302
308
  const version = versionIn(edition, versionId);
@@ -1,7 +1,16 @@
1
1
  import { RollCopy } from "../model/RollCopy.js";
2
2
  import { Version } from "../model/Version.js";
3
3
  import { Edition } from "../model/Edition.js";
4
+ /**
5
+ * The kinds of reservation the edition can have about a copy, in the
6
+ * order `reservationsAbout` checks for them.
7
+ * @category Analysis
8
+ */
4
9
  export declare const reservationTypes: readonly ['source-not-stated', 'source-undocumented', 'software-not-named', 'instrument-not-named', 'features-interpreted', 'no-physical-evidence', 'measurement-undocumented', 'not-calibrated', 'system-unknown', 'keeper-unknown'];
10
+ /**
11
+ * A kind of reservation about a copy.
12
+ * @category Analysis
13
+ */
5
14
  export type ReservationType = typeof reservationTypes[number];
6
15
  /**
7
16
  * Something an edition cannot vouch for in one of its copies or
@@ -12,6 +21,7 @@ export type ReservationType = typeof reservationTypes[number];
12
21
  * knowledge of it is incomplete, so filling in what is missing makes it
13
22
  * go away. Nothing here describes the state of the paper, which is a
14
23
  * condition of the copy.
24
+ * @category Analysis
15
25
  */
16
26
  export interface Reservation<T extends string = ReservationType> {
17
27
  type: T;
@@ -22,9 +32,22 @@ export interface Reservation<T extends string = ReservationType> {
22
32
  * What the edition cannot vouch for in a copy, in the order the
23
33
  * checks are listed: where its features came from first, then what
24
34
  * the measurement leaves open, then who holds it.
35
+ * @category Analysis
25
36
  */
26
37
  export declare const reservationsAbout: (copy: RollCopy) => Reservation[];
38
+ /**
39
+ * The kinds of reservation the edition can have about a version, in the
40
+ * order `reservationsAboutVersion` checks for them.
41
+ * @category Analysis
42
+ */
27
43
  export declare const versionReservationTypes: readonly ['text-not-stated', 'witnessed-by-statement-only', 'no-direct-witness'];
44
+ /**
45
+ * A kind of reservation about a version.
46
+ * @category Analysis
47
+ */
28
48
  export type VersionReservationType = typeof versionReservationTypes[number];
29
- /** What the edition cannot vouch for in a version, in the order the checks are listed. */
49
+ /**
50
+ * What the edition cannot vouch for in a version, in the order the checks are listed.
51
+ * @category Analysis
52
+ */
30
53
  export declare const reservationsAboutVersion: (edition: Edition, version: Readonly<Version>) => Reservation<VersionReservationType>[];
@@ -2,6 +2,11 @@ import { bearsPhysicalEvidence, isMeasured, sourceLabels } from "../model/Featur
2
2
  import { calibrationOf, featuresOf, measuringSoftwareOf } from "../model/RollCopy.js";
3
3
  import { trackerBarOf } from "../systems/index.js";
4
4
  import { witnessesOf } from "./witnesses.js";
5
+ /**
6
+ * The kinds of reservation the edition can have about a copy, in the
7
+ * order `reservationsAbout` checks for them.
8
+ * @category Analysis
9
+ */
5
10
  export const reservationTypes = [
6
11
  'source-not-stated',
7
12
  'source-undocumented',
@@ -98,8 +103,14 @@ const checks = [
98
103
  * What the edition cannot vouch for in a copy, in the order the
99
104
  * checks are listed: where its features came from first, then what
100
105
  * the measurement leaves open, then who holds it.
106
+ * @category Analysis
101
107
  */
102
108
  export const reservationsAbout = (copy) => checks.flatMap(check => check(copy) ?? []);
109
+ /**
110
+ * The kinds of reservation the edition can have about a version, in the
111
+ * order `reservationsAboutVersion` checks for them.
112
+ * @category Analysis
113
+ */
103
114
  export const versionReservationTypes = [
104
115
  'text-not-stated',
105
116
  'witnessed-by-statement-only',
@@ -129,5 +140,8 @@ const witnessedAtFirstHand = (edition, version) => {
129
140
  } : undefined;
130
141
  };
131
142
  const versionChecks = [textStated, witnessedByFeatures, witnessedAtFirstHand];
132
- /** What the edition cannot vouch for in a version, in the order the checks are listed. */
143
+ /**
144
+ * What the edition cannot vouch for in a version, in the order the checks are listed.
145
+ * @category Analysis
146
+ */
133
147
  export const reservationsAboutVersion = (edition, version) => versionChecks.flatMap(check => check(edition, version) ?? []);
@@ -2,6 +2,7 @@ import { Edition } from '../model/Edition.js';
2
2
  /**
3
3
  * What the sigla are read off: the versions alone, or the edition, whose
4
4
  * copies tell which versions a witness shows.
5
+ * @category Versions and stemma
5
6
  */
6
7
  export type Stemma = Pick<Edition, 'versions'> | Edition;
7
8
  /**
@@ -17,7 +18,11 @@ export type Stemma = Pick<Edition, 'versions'> | Edition;
17
18
  *
18
19
  * A siglum is computed anew when the stemma or the copies change, so
19
20
  * nothing should cite one without saying which state it belongs to.
21
+ * @category Versions and stemma
20
22
  */
21
23
  export declare const siglaOf: (stemma: Stemma) => ReadonlyMap<string, string>;
22
- /** The siglum of one version as the stemma stands, or nothing where the edition holds no such version. */
24
+ /**
25
+ * The siglum of one version as the stemma stands, or nothing where the edition holds no such version.
26
+ * @category Versions and stemma
27
+ */
23
28
  export declare const siglumOf: (stemma: Stemma, versionId: string) => string | undefined;
@@ -111,9 +111,13 @@ const marking = (sigla, attested) => new Map([...sigla].map(([id, siglum]) => [i
111
111
  *
112
112
  * A siglum is computed anew when the stemma or the copies change, so
113
113
  * nothing should cite one without saying which state it belongs to.
114
+ * @category Versions and stemma
114
115
  */
115
116
  export const siglaOf = (stemma) => holdsCopies(stemma)
116
117
  ? marking(alongTheStemma(stemma.versions), attestedVersions(stemma))
117
118
  : alongTheStemma(stemma.versions);
118
- /** The siglum of one version as the stemma stands, or nothing where the edition holds no such version. */
119
+ /**
120
+ * The siglum of one version as the stemma stands, or nothing where the edition holds no such version.
121
+ * @category Versions and stemma
122
+ */
119
123
  export const siglumOf = (stemma, versionId) => siglaOf(stemma).get(versionId);
@@ -6,9 +6,13 @@ import { Version } from "../model/Version.js";
6
6
  * version up to the root. A stemma that loops back on itself is walked
7
7
  * once round, so that an edition in that state can still be read and
8
8
  * repaired.
9
+ * @category Versions and stemma
9
10
  */
10
11
  export declare const lineageOf: (edition: Pick<Edition, 'versions'>, versionId: string) => Readonly<Version>[];
11
- /** The version the given one's text is read against, by its principal derivation. */
12
+ /**
13
+ * The version the given one's text is read against, by its principal derivation.
14
+ * @category Versions and stemma
15
+ */
12
16
  export declare const predecessorOf: (edition: Pick<Edition, 'versions'>, versionId: string) => Readonly<Version> | undefined;
13
17
  /**
14
18
  * Every version with its generation: how many principal derivations
@@ -16,6 +20,7 @@ export declare const predecessorOf: (edition: Pick<Edition, 'versions'>, version
16
20
  * not hold counts as a root. In a stemma that loops, the loop is walked
17
21
  * once round, as `lineageOf` walks it, so that the stemma of an edition
18
22
  * in that state can still be drawn and repaired.
23
+ * @category Versions and stemma
19
24
  */
20
25
  export declare const withGenerations: (edition: Pick<Edition, 'versions'>) => Array<Version & {
21
26
  generation: number;
@@ -6,6 +6,7 @@ import { versionIn } from "../lookup/lookup.js";
6
6
  * version up to the root. A stemma that loops back on itself is walked
7
7
  * once round, so that an edition in that state can still be read and
8
8
  * repaired.
9
+ * @category Versions and stemma
9
10
  */
10
11
  export const lineageOf = (edition, versionId) => {
11
12
  const lineage = [];
@@ -19,7 +20,10 @@ export const lineageOf = (edition, versionId) => {
19
20
  }
20
21
  return lineage;
21
22
  };
22
- /** The version the given one's text is read against, by its principal derivation. */
23
+ /**
24
+ * The version the given one's text is read against, by its principal derivation.
25
+ * @category Versions and stemma
26
+ */
23
27
  export const predecessorOf = (edition, versionId) => {
24
28
  const v = versionIn(edition, versionId);
25
29
  const principal = v && principalDerivationOf(v);
@@ -31,6 +35,7 @@ export const predecessorOf = (edition, versionId) => {
31
35
  * not hold counts as a root. In a stemma that loops, the loop is walked
32
36
  * once round, as `lineageOf` walks it, so that the stemma of an edition
33
37
  * in that state can still be drawn and repaired.
38
+ * @category Versions and stemma
34
39
  */
35
40
  export const withGenerations = (edition) => edition.versions.map(version => ({
36
41
  ...version,
@@ -3,8 +3,17 @@ import { Edition } from "../model/Edition.js";
3
3
  import { FeatureOrPatch, HorizontalSpan, NestedFeature } from "../model/Feature.js";
4
4
  import { AnySymbol } from "../model/Symbol.js";
5
5
  import { Millimeters } from "../model/Quantity.js";
6
+ /**
7
+ * The features carrying the symbol, on whichever copy they sit, those a
8
+ * patch bears included. A carrier the edition holds no feature for is
9
+ * left out.
10
+ * @category Lookups
11
+ */
6
12
  export declare const carriersOf: (edition: Pick<Edition, 'copies'>, symbol: AnySymbol) => Readonly<NestedFeature>[];
7
- /** The carriers that state a place of their own, which a feature on a patch does not. */
13
+ /**
14
+ * The carriers that state a place of their own, which a feature on a patch does not.
15
+ * @category Lookups
16
+ */
8
17
  export declare const placedCarriersOf: (edition: Pick<Edition, 'copies'>, symbol: AnySymbol) => Readonly<FeatureOrPatch>[];
9
18
  /**
10
19
  * Where along the roll the symbol lies, as its carriers put it, or
@@ -23,14 +32,19 @@ export declare const placedCarriersOf: (edition: Pick<Edition, 'copies'>, symbol
23
32
  * symbol may be carried by copies of both — averaging a red carrier
24
33
  * on track 47 with a green one on 45 would give 46, a legal
25
34
  * position a semitone away on either bar.
35
+ * @category Lookups
26
36
  */
27
37
  export declare const placeOf: (edition: Pick<Edition, 'copies'>, symbol: AnySymbol) => Readonly<HorizontalSpan> | undefined;
28
- /** Where the symbol begins, as the median onset of its carriers, or nothing for a symbol without a place. */
38
+ /**
39
+ * Where the symbol begins, as the median onset of its carriers, or nothing for a symbol without a place.
40
+ * @category Lookups
41
+ */
29
42
  export declare const onsetOf: (edition: Pick<Edition, 'copies'>, symbol: AnySymbol) => Millimeters | undefined;
30
43
  /**
31
44
  * The symbols the version shows: what it and its ancestors insert,
32
45
  * each version's deletions striking what it or its ancestors inserted.
33
46
  * They are worked out once for each state of the edition, and the list
34
47
  * is frozen, since everyone who asks is handed the same one.
48
+ * @category Lookups
35
49
  */
36
50
  export declare const snapshotOf: (edition: Edition, versionId: string) => readonly Readonly<AnySymbol>[];
@@ -5,8 +5,17 @@ import { medianOf } from "../collation/statistics.js";
5
5
  import { featuresIn } from "../lookup/lookup.js";
6
6
  import { perState } from "../lookup/perState.js";
7
7
  import { lineageOf } from "./stemma.js";
8
+ /**
9
+ * The features carrying the symbol, on whichever copy they sit, those a
10
+ * patch bears included. A carrier the edition holds no feature for is
11
+ * left out.
12
+ * @category Lookups
13
+ */
8
14
  export const carriersOf = (edition, symbol) => featuresIn(edition, idsOf(symbol.carriers));
9
- /** The carriers that state a place of their own, which a feature on a patch does not. */
15
+ /**
16
+ * The carriers that state a place of their own, which a feature on a patch does not.
17
+ * @category Lookups
18
+ */
10
19
  export const placedCarriersOf = (edition, symbol) => carriersOf(edition, symbol).filter(isPlaced);
11
20
  /**
12
21
  * Where along the roll the symbol lies, as its carriers put it, or
@@ -25,6 +34,7 @@ export const placedCarriersOf = (edition, symbol) => carriersOf(edition, symbol)
25
34
  * symbol may be carried by copies of both — averaging a red carrier
26
35
  * on track 47 with a green one on 45 would give 46, a legal
27
36
  * position a semitone away on either bar.
37
+ * @category Lookups
28
38
  */
29
39
  export const placeOf = (edition, symbol) => {
30
40
  const carriers = placedCarriersOf(edition, symbol);
@@ -34,7 +44,10 @@ export const placeOf = (edition, symbol) => {
34
44
  return;
35
45
  return { unit: 'mm', from, to };
36
46
  };
37
- /** Where the symbol begins, as the median onset of its carriers, or nothing for a symbol without a place. */
47
+ /**
48
+ * Where the symbol begins, as the median onset of its carriers, or nothing for a symbol without a place.
49
+ * @category Lookups
50
+ */
38
51
  export const onsetOf = (edition, symbol) => placeOf(edition, symbol)?.from;
39
52
  /** The symbols by onset, those without a place first; symbols at one place keep their order. */
40
53
  const inOrderOfPlace = (edition, symbols) => symbols
@@ -48,6 +61,7 @@ const snapshotsIn = perState((_) => new Map());
48
61
  * each version's deletions striking what it or its ancestors inserted.
49
62
  * They are worked out once for each state of the edition, and the list
50
63
  * is frozen, since everyone who asks is handed the same one.
64
+ * @category Lookups
51
65
  */
52
66
  export const snapshotOf = (edition, versionId) => {
53
67
  const known = snapshotsIn(edition);
@@ -1,7 +1,16 @@
1
1
  import { Belief, Certainty } from "../model/Assumption.js";
2
2
  import { Edition } from "../model/Edition.js";
3
+ /**
4
+ * How a copy bears witness to a version: its features carry what the
5
+ * version inserts (`carriers`), or it states that it carries the
6
+ * version (`statement`).
7
+ * @category Analysis
8
+ */
3
9
  export type WitnessBy = 'carriers' | 'statement';
4
- /** A copy that bears witness to a version, and how. */
10
+ /**
11
+ * A copy that bears witness to a version, and how.
12
+ * @category Analysis
13
+ */
5
14
  export interface Witness {
6
15
  /** The copy, by id. */
7
16
  copy: string;
@@ -24,6 +33,7 @@ export interface Witness {
24
33
  * the latest state it bears. A version left out is reached only through
25
34
  * the versions derived from it, or is attested by statement alone, and
26
35
  * its text is a reconstruction rather than a reading.
36
+ * @category Analysis
27
37
  */
28
38
  export declare const attestedVersions: (edition: Edition) => ReadonlySet<string>;
29
39
  /**
@@ -43,15 +53,23 @@ export declare const attestedVersions: (edition: Edition) => ReadonlySet<string>
43
53
  * A statement is the editor's own about the version it names and is
44
54
  * reported as it stands. A version whose edits are not stated inserts
45
55
  * nothing and is witnessed by statement alone.
56
+ * @category Analysis
46
57
  */
47
58
  export declare const witnessesOf: (edition: Edition, versionId: string) => Witness[];
48
59
  /**
49
60
  * The versions the copy bears witness to, each with how, in the order the
50
61
  * edition lists its versions.
62
+ * @category Analysis
51
63
  */
52
64
  export declare const versionsWitnessedBy: (edition: Edition, copyId: string) => (Witness & {
53
65
  version: string;
54
66
  })[];
67
+ /**
68
+ * A copy's statement that it carries a version, where the statement
69
+ * cannot stand (`carriageProblems`): it is made beside features that
70
+ * carry symbols, or it names a version the edition lacks.
71
+ * @category Analysis
72
+ */
55
73
  export type CarriageProblem = {
56
74
  copy: string;
57
75
  version: string;
@@ -61,5 +79,6 @@ export type CarriageProblem = {
61
79
  * Where a copy's statement that it carries a version cannot stand: one
62
80
  * made although the copy's features carry symbols, which say by
63
81
  * themselves what it carries, and one naming a version the edition lacks.
82
+ * @category Analysis
64
83
  */
65
84
  export declare const carriageProblems: (edition: Edition) => CarriageProblem[];