linked-rolls 0.57.0 → 0.59.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.
- package/README.md +54 -367
- package/lib/{constraints.d.ts → analysis/constraints.d.ts} +1 -1
- package/lib/{constraints.js → analysis/constraints.js} +8 -7
- package/lib/analysis/ownPaper.d.ts +26 -0
- package/lib/analysis/ownPaper.js +41 -0
- package/lib/{reservations.d.ts → analysis/reservations.d.ts} +3 -3
- package/lib/{reservations.js → analysis/reservations.js} +3 -3
- package/lib/{sigla.d.ts → analysis/sigla.d.ts} +2 -2
- package/lib/{sigla.js → analysis/sigla.js} +4 -4
- package/lib/{witnesses.d.ts → analysis/witnesses.d.ts} +2 -2
- package/lib/{witnesses.js → analysis/witnesses.js} +2 -2
- package/lib/{Collation.d.ts → collation/Collation.d.ts} +4 -4
- package/lib/{Collation.js → collation/Collation.js} +4 -4
- package/lib/{alignment.d.ts → collation/alignment.d.ts} +4 -4
- package/lib/{alignment.js → collation/alignment.js} +10 -16
- package/lib/{scatter.d.ts → collation/scatter.d.ts} +4 -4
- package/lib/{scatter.js → collation/scatter.js} +3 -3
- package/lib/{statistics.d.ts → collation/statistics.d.ts} +1 -1
- package/lib/{statistics.js → collation/statistics.js} +2 -2
- package/lib/{substitution.d.ts → collation/substitution.d.ts} +9 -24
- package/lib/{substitution.js → collation/substitution.js} +13 -37
- package/lib/emulation/Emulation.d.ts +64 -0
- package/lib/emulation/Emulation.js +282 -0
- package/lib/emulation/negotiation.d.ts +14 -0
- package/lib/emulation/negotiation.js +20 -0
- package/lib/index.d.ts +43 -35
- package/lib/index.js +36 -35
- package/lib/{asJsonLd.d.ts → io/asJsonLd.d.ts} +1 -1
- package/lib/{asJsonLd.js → io/asJsonLd.js} +3 -3
- package/lib/{context.d.ts → io/context.d.ts} +4 -4
- package/lib/{context.js → io/context.js} +4 -4
- package/lib/{importJsonLd.d.ts → io/importJsonLd.d.ts} +1 -1
- package/lib/io/importJsonLd.js +128 -0
- package/lib/{migrate.js → io/migrate.js} +59 -55
- package/lib/{Agent.d.ts → model/Agent.d.ts} +1 -1
- package/lib/{Assumption.d.ts → model/Assumption.d.ts} +1 -1
- package/lib/{Edit.d.ts → model/Edit.d.ts} +1 -1
- package/lib/{Edition.d.ts → model/Edition.d.ts} +2 -2
- package/lib/{Feature.d.ts → model/Feature.d.ts} +1 -1
- package/lib/{FeatureSource.d.ts → model/FeatureSource.d.ts} +1 -1
- package/lib/{Perforator.d.ts → model/Perforator.d.ts} +1 -1
- package/lib/{RollCopy.d.ts → model/RollCopy.d.ts} +3 -10
- package/lib/{RollCopy.js → model/RollCopy.js} +3 -5
- package/lib/{Symbol.d.ts → model/Symbol.d.ts} +1 -1
- package/lib/{Version.d.ts → model/Version.d.ts} +10 -2
- package/lib/{Version.js → model/Version.js} +24 -1
- package/lib/{vocabulary.js → model/vocabulary.js} +2 -2
- package/lib/ops/beliefs.d.ts +9 -0
- package/lib/ops/beliefs.js +31 -0
- package/lib/ops/collation.d.ts +62 -0
- package/lib/ops/collation.js +228 -0
- package/lib/ops/commands.d.ts +9 -0
- package/lib/ops/commands.js +29 -0
- package/lib/ops/copies.d.ts +74 -0
- package/lib/ops/copies.js +135 -0
- package/lib/ops/draft.d.ts +59 -0
- package/lib/ops/draft.js +81 -0
- package/lib/ops/edits.d.ts +10 -0
- package/lib/ops/edits.js +82 -0
- package/lib/ops/features.d.ts +84 -0
- package/lib/ops/features.js +296 -0
- package/lib/ops/forget.d.ts +31 -0
- package/lib/ops/forget.js +110 -0
- package/lib/ops/immutable.d.ts +16 -0
- package/lib/ops/immutable.js +46 -0
- package/lib/ops/index.d.ts +13 -0
- package/lib/ops/index.js +7 -0
- package/lib/ops/versions.d.ts +33 -0
- package/lib/ops/versions.js +95 -0
- package/lib/readers/AtonParser.js +5 -7
- package/lib/readers/phillipsEroll.d.ts +3 -3
- package/lib/readers/phillipsEroll.js +4 -5
- package/lib/readers/spencerBar.d.ts +2 -2
- package/lib/readers/spencerBar.js +2 -3
- package/lib/readers/stanfordAton.d.ts +3 -3
- package/lib/readers/stanfordAton.js +2 -3
- package/lib/schema.json +0 -13
- package/lib/{ReproducingSystem.d.ts → systems/ReproducingSystem.d.ts} +3 -3
- package/lib/{TrackerBar.d.ts → systems/TrackerBar.d.ts} +48 -8
- package/lib/{TrackerBar.js → systems/TrackerBar.js} +11 -2
- package/lib/systems/index.d.ts +8 -2
- package/lib/systems/index.js +7 -1
- package/lib/systems/welte.d.ts +100 -0
- package/lib/systems/welte.js +119 -0
- package/lib/systems/welteLicensee/bar.d.ts +1 -1
- package/lib/systems/welteLicensee/bar.js +5 -2
- package/lib/systems/welteLicensee/system.d.ts +1 -1
- package/lib/systems/welteLicensee/system.js +1 -1
- package/lib/systems/welteT100/bar.d.ts +27 -1
- package/lib/systems/welteT100/bar.js +44 -2
- package/lib/systems/welteT100/system.d.ts +6 -39
- package/lib/systems/welteT100/system.js +19 -128
- package/lib/systems/welteT98/bar.d.ts +1 -1
- package/lib/systems/welteT98/bar.js +18 -2
- package/lib/systems/welteT98/system.d.ts +20 -38
- package/lib/systems/welteT98/system.js +20 -121
- package/lib/validate.d.ts +1 -1
- package/lib/{EditionView.d.ts → view/EditionView.d.ts} +17 -41
- package/lib/{EditionView.js → view/EditionView.js} +26 -75
- package/package.json +7 -2
- package/lib/Emulation.d.ts +0 -36
- package/lib/Emulation.js +0 -250
- package/lib/editionOps.d.ts +0 -260
- package/lib/editionOps.js +0 -1079
- package/lib/importJsonLd.js +0 -57
- /package/lib/{migrate.d.ts → io/migrate.d.ts} +0 -0
- /package/lib/{Agent.js → model/Agent.js} +0 -0
- /package/lib/{Assumption.js → model/Assumption.js} +0 -0
- /package/lib/{ConditionState.d.ts → model/ConditionState.d.ts} +0 -0
- /package/lib/{ConditionState.js → model/ConditionState.js} +0 -0
- /package/lib/{Edit.js → model/Edit.js} +0 -0
- /package/lib/{Edition.js → model/Edition.js} +0 -0
- /package/lib/{Feature.js → model/Feature.js} +0 -0
- /package/lib/{FeatureSource.js → model/FeatureSource.js} +0 -0
- /package/lib/{Perforator.js → model/Perforator.js} +0 -0
- /package/lib/{Quantity.d.ts → model/Quantity.d.ts} +0 -0
- /package/lib/{Quantity.js → model/Quantity.js} +0 -0
- /package/lib/{Symbol.js → model/Symbol.js} +0 -0
- /package/lib/{TrackCalibration.d.ts → model/TrackCalibration.d.ts} +0 -0
- /package/lib/{TrackCalibration.js → model/TrackCalibration.js} +0 -0
- /package/lib/{notes.d.ts → model/notes.d.ts} +0 -0
- /package/lib/{notes.js → model/notes.js} +0 -0
- /package/lib/{procedures.d.ts → model/procedures.d.ts} +0 -0
- /package/lib/{procedures.js → model/procedures.js} +0 -0
- /package/lib/{vocabulary.d.ts → model/vocabulary.d.ts} +0 -0
- /package/lib/{sorted.d.ts → shared/sorted.d.ts} +0 -0
- /package/lib/{sorted.js → shared/sorted.js} +0 -0
- /package/lib/{utils.d.ts → shared/utils.d.ts} +0 -0
- /package/lib/{utils.js → shared/utils.js} +0 -0
- /package/lib/{ReproducingSystem.js → systems/ReproducingSystem.js} +0 -0
package/README.md
CHANGED
|
@@ -1,402 +1,89 @@
|
|
|
1
1
|
# linked-rolls
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
A TypeScript library for digital editions of piano rolls. It reads roll
|
|
4
|
+
copies from scans and analysis files, collates them into versions,
|
|
5
|
+
records editorial assumptions together with the beliefs behind them,
|
|
6
|
+
exports the edition as JSON-LD, and plays a version through an emulated
|
|
7
|
+
reproducing piano.
|
|
5
8
|
|
|
6
|
-
|
|
7
|
-
as SUPRA's roll analysis files, DSP, etc.)
|
|
8
|
-
- collate differing piano roll copies
|
|
9
|
-
- create an manipulate editorial assumptions
|
|
10
|
-
- export the edition as JSON-LD (based on the
|
|
11
|
-
[Roll Edition Format](https://pfefferniels.github.io/linked-rolls/))
|
|
9
|
+
It is the foundation of the [Roll Desk](https://github.com/pfefferniels/roll-desk).
|
|
12
10
|
|
|
13
|
-
|
|
14
|
-
[Roll Desk](https://github.com/pfefferniels/roll-desk).
|
|
11
|
+
## Install
|
|
15
12
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
`https://w3id.org/reo/`, prefix `reo`, alongside CIDOC CRM, LRMoo and
|
|
20
|
-
CRMinf. The ontology lives in `ontology/`, and the context every
|
|
21
|
-
export references is `https://w3id.org/reo/context.jsonld`. The
|
|
22
|
-
ontology, its type vocabulary and the context are published at
|
|
23
|
-
https://pfefferniels.github.io/linked-rolls/reo/; the w3id.org
|
|
24
|
-
identifiers are not registered yet. `ontology/README.md` records the
|
|
25
|
-
naming decisions.
|
|
26
|
-
|
|
27
|
-
Beliefs travel as JSON-LD-star annotations (`@annotation`), which state
|
|
28
|
-
the triple they annotate. A reference the edition holds possible,
|
|
29
|
-
unlikely or false is therefore written as an embedded node beside the
|
|
30
|
-
document: RDF names the statement without stating it, and
|
|
31
|
-
`importJsonLd` puts it back where it stood. A doubted value, such as a
|
|
32
|
-
date or an attribution, stays annotated in place for now. Reading the
|
|
33
|
-
beliefs needs a processor that implements JSON-LD-star, such as the
|
|
34
|
-
Ruby `json-ld` gem; jsonld.js ignores `@annotation`, and every belief
|
|
35
|
-
with it.
|
|
36
|
-
|
|
37
|
-
## Format revisions
|
|
38
|
-
|
|
39
|
-
Files written by linked-rolls 0.1 load unchanged: `importJsonLd`
|
|
40
|
-
recognises their shapes and brings them to the current format, in
|
|
41
|
-
which versions and conditions carry a typology key beside their type,
|
|
42
|
-
the keeper and the production metadata are nodes with a name and
|
|
43
|
-
authority links, and the roll names its reproducing system. A date
|
|
44
|
-
written as a value of its own is read as the day the event falls
|
|
45
|
-
within. A copy that held its features in one list, naming by id what a
|
|
46
|
-
modification had added, has each feature put into the act that brought
|
|
47
|
-
it about, and a feature a patch bears that was left unnamed is named
|
|
48
|
-
after the patch. Exports are always in the current format.
|
|
49
|
-
|
|
50
|
-
## How a date is stated
|
|
51
|
-
|
|
52
|
-
A date is the time-span of the event rather than a value on it.
|
|
53
|
-
`within` gives the day it falls within, and `after` and `before` give
|
|
54
|
-
the bounds where nobody can give the day. A bound the edition does not
|
|
55
|
-
know is left out, so `after` alone says "not before". In RDF the three
|
|
56
|
-
become `P82 at some time within`, `P82a begin of the begin` and `P82b
|
|
57
|
-
end of the end` on the `E52 Time-Span` the event has. `assignDate`,
|
|
58
|
-
`notBefore` and `notAfter` build the three shapes, and `dateOf`,
|
|
59
|
-
`earliestOf` and `latestOf` read them.
|
|
60
|
-
|
|
61
|
-
Note that `before` and `after` mean something else on a command,
|
|
62
|
-
where they order two onsets. The context defines them for a date
|
|
63
|
-
within the date itself, so the two never meet.
|
|
64
|
-
|
|
65
|
-
## What a version derives from
|
|
66
|
-
|
|
67
|
-
A version names the versions it is held to derive from in `basedOn`,
|
|
68
|
-
each under the belief it rests on. Its text is read against the
|
|
69
|
-
principal derivation, the first of those held most certain, and one
|
|
70
|
-
held unlikely or false never gives the text. The others stand as
|
|
71
|
-
hypotheses, such as a contamination: `stateDerivation` adds one and
|
|
72
|
-
`clearDerivation` takes it back. A version may leave out its `edits`
|
|
73
|
-
where nobody can state them, as for a text that only a recording hints
|
|
74
|
-
at. It then reads as the version it derives from, and
|
|
75
|
-
`reservationsAboutVersion` says so. A file that names a single
|
|
76
|
-
derivation loads as a list of one.
|
|
77
|
-
|
|
78
|
-
What a version is called is not stored with it. `siglaOf` reads the
|
|
79
|
-
sigla off the stemma as it stands, so a label never outlives the
|
|
80
|
-
arrangement it describes, and nothing should cite one without saying
|
|
81
|
-
which state of the edition it belongs to.
|
|
82
|
-
|
|
83
|
-
Handed an `EditionView`, which knows the copies as well, `siglaOf`
|
|
84
|
-
lowercases the versions no copy's features carry at first hand, as
|
|
85
|
-
editions mark a state nothing surviving shows: r3 stands to R3 as a
|
|
86
|
-
reconstructed state stands to a witnessed one. A version reached only
|
|
87
|
-
through the versions derived from it is lowercased, and so is one a
|
|
88
|
-
copy does no more than state it carries, since a statement gives no
|
|
89
|
-
readings. `attestedVersions` reports the same fact on its own. Handed
|
|
90
|
-
the versions alone, `siglaOf` cannot tell and leaves every siglum in
|
|
91
|
-
capitals.
|
|
92
|
-
|
|
93
|
-
## The tolerance a derivation was collated at
|
|
94
|
-
|
|
95
|
-
`collationTolerance` on a derivation is the window two readings of one
|
|
96
|
-
symbol must fall in to be collated: how far apart they may lie at
|
|
97
|
-
either end, and, since two copies differ by a systematic offset as well
|
|
98
|
-
as by scatter, where that window is centred. A window naming no offset
|
|
99
|
-
is centred on nothing, which is what every window written before the
|
|
100
|
-
offset was held here means.
|
|
101
|
-
|
|
102
|
-
The number decides what counts as a reading at all, so it is worth
|
|
103
|
-
measuring rather than picking. `scatterOfCopy` measures how far one
|
|
104
|
-
copy puts each symbol from where the copies collated with it put it,
|
|
105
|
-
and `scatterOf` describes that sample: its median, its scatter as a
|
|
106
|
-
median absolute deviation scaled to a standard deviation, a histogram
|
|
107
|
-
with the normal curve to lay over it, and the readings the curve does
|
|
108
|
-
not account for. The scatter is taken from the median because the
|
|
109
|
-
displacements an editor is looking for are in the sample, and a
|
|
110
|
-
standard deviation would grow towards them until they no longer stood
|
|
111
|
-
out.
|
|
112
|
-
|
|
113
|
-
The copies named are one **side** of the comparison and the rest are
|
|
114
|
-
the other, so which copies to name is the first question and the
|
|
115
|
-
edition no longer answers it: a collation hands a child's carriers up
|
|
116
|
-
to the parent's symbols, so a descendant's copies come to bear an
|
|
117
|
-
ancestor's readings and look like its own. `sidesOf` reads the sides
|
|
118
|
-
off the edits instead, the copies bearing what a version inserts
|
|
119
|
-
standing for the reading it moves to and those bearing what it strikes
|
|
120
|
-
for the reading it moves from. Naming a set that is not a side measures
|
|
121
|
-
one copy's noise against a mixture of both sides, which is wider than
|
|
122
|
-
the truth.
|
|
123
|
-
|
|
124
|
-
The tolerance that follows is the scatter times a threshold fixed by
|
|
125
|
-
the size of the sample, the point beyond which fewer than one reading
|
|
126
|
-
is expected to fall by chance (`departureThreshold`). For the few
|
|
127
|
-
hundred readings an edge of a stemma yields this lands a little above
|
|
128
|
-
three. `toleranceAcross` covers several samples with one window, since
|
|
129
|
-
a derivation states one tolerance while notes and expressions scatter
|
|
130
|
-
differently. It asks which side was measured, because a window is
|
|
131
|
-
signed: the offset runs from the parent to the child, and one stored
|
|
132
|
-
the other way round has the right width and the wrong centre, so it
|
|
133
|
-
separates readings that belong together and merges readings that do
|
|
134
|
-
not while nothing in the number looks wrong. `inferredTolerance` builds
|
|
135
|
-
the belief the number rests on, to annotate `collationTolerance` with. It is held likely and not
|
|
136
|
-
true: the tolerance follows from the sample only as far as the sample
|
|
137
|
-
is normal, which is what the reported excess kurtosis and tail counts
|
|
138
|
-
are there to show.
|
|
139
|
-
|
|
140
|
-
Two limits are worth naming. Notes and expressions are estimated apart
|
|
141
|
-
by default, which is a stopgap standing in for a skew across the width
|
|
142
|
-
of the paper rather than a distinction in the model, so the grouping is
|
|
143
|
-
a parameter of the estimator and appears nowhere in the format. And the
|
|
144
|
-
method screens: it says which readings the curve does not account for,
|
|
145
|
-
and an editor says which of those are editorial acts.
|
|
146
|
-
|
|
147
|
-
A separation reports which end made it (`separatedBy`, and
|
|
148
|
-
`admittedAtEnds` for a collation). The two ends answer different
|
|
149
|
-
questions: the onset, with the kind, decides whether two copies read one
|
|
150
|
-
command, and the end decides whether that command was lengthened or
|
|
151
|
-
shortened. On welte225.org the end alone decides 24 collations of 2839
|
|
152
|
-
and the onset alone 39, so neither test is idle, but a difference at the
|
|
153
|
-
end is as often a punch measured badly as a punch genuinely prolonged,
|
|
154
|
-
and the two are not worth confusing.
|
|
155
|
-
|
|
156
|
-
## What a reader adds to a chain of holes
|
|
157
|
-
|
|
158
|
-
A copy read pneumatically rather than scanned reports how long a valve
|
|
159
|
-
stayed open, and a valve is held on past the perforation that opened it,
|
|
160
|
-
so the chains it reports run longer than the punched ones while their
|
|
161
|
-
onsets agree. Left in, that is not a difference between copies: a
|
|
162
|
-
collation comparing such a copy's chain ends against a scanned copy's
|
|
163
|
-
compares an on-time with a slot, and reads the one as a lengthening of
|
|
164
|
-
the other.
|
|
165
|
-
|
|
166
|
-
`shortenChains` takes the extension off and records it on the copy,
|
|
167
|
-
`revertShortening` puts it back, and `readFromPhillipsEroll` will take
|
|
168
|
-
it off at import. Only chains of holes are touched, what a writing spans
|
|
169
|
-
being no valve. The figure is measured against the other copies rather than
|
|
170
|
-
derived from the bar, since Phillips gives only the difference between
|
|
171
|
-
two bars and not the absolute.
|
|
172
|
-
|
|
173
|
-
On welte225.org that figure is about 1.6 mm, and its shape is simple. It
|
|
174
|
-
does not grow with the length of the perforation: the ratio of the read
|
|
175
|
-
length to the true one falls from 1.34 on the shortest punches to 1.01
|
|
176
|
-
on the longest, which is what a constant added to everything does. There
|
|
177
|
-
is no shortest on-time the valve cannot fall below. It shows no run
|
|
178
|
-
along the roll, though one roll's span of paper speed is too narrow to
|
|
179
|
-
tell a constant in millimetres from a constant in time. What it does
|
|
180
|
-
vary with is the port that read it, by about half a millimetre either
|
|
181
|
-
way and with no gradient across the bar, which is measured but too
|
|
182
|
-
coarse to model from a single roll.
|
|
183
|
-
|
|
184
|
-
## Collating a derivation a second time
|
|
185
|
-
|
|
186
|
-
A collated symbol is one symbol carrying every copy that reads it, so a
|
|
187
|
-
collation cannot simply be run again: there is no second symbol left to
|
|
188
|
-
match. `separateReadings` is the inverse. It takes the carriers of one
|
|
189
|
-
side back off the symbols it shares, gives them to new symbols of the
|
|
190
|
-
version's own, and states the exchange, leaving the edition in the state
|
|
191
|
-
a collation would have produced had nothing joined. `connectVersions` at
|
|
192
|
-
a new tolerance then re-collates, joining again whatever the new window
|
|
193
|
-
admits.
|
|
194
|
-
|
|
195
|
-
It takes a side and not a copy, the same side `sidesOf` names and a
|
|
196
|
-
window is measured over. Naming one copy of a side that has several does
|
|
197
|
-
not separate that side: the rest of it stays behind on the other side's
|
|
198
|
-
symbol, and a collation then compares one copy against that mixture
|
|
199
|
-
rather than the two texts against each other.
|
|
200
|
-
|
|
201
|
-
Nothing an editor established is lost by that. `connectVersions`
|
|
202
|
-
rewrites only what a collation wrote (`isCollationsOwn`): a bare
|
|
203
|
-
insertion or deletion, or an equivalence between two systems' spellings.
|
|
204
|
-
An edit naming what the change is, why it was made, or what it rests on
|
|
205
|
-
stays, and the symbols it speaks for are left out of the collation. An
|
|
206
|
-
equivalence counts as the collation's own, since it is derived from the
|
|
207
|
-
two systems' vocabularies rather than read off the paper and freezing it
|
|
208
|
-
would leave the transfers uncollatable, but one drawn a second time over
|
|
209
|
-
the very same symbols is kept as it stands, identifier and motivation
|
|
210
|
-
and all. Readings already separated by hand are carried by one copy
|
|
211
|
-
alone, so `separateReadings` passes over them and they keep their
|
|
212
|
-
identifiers.
|
|
213
|
-
|
|
214
|
-
## What brought a feature about
|
|
215
|
-
|
|
216
|
-
A copy states no list of features. Each feature stands in the act that
|
|
217
|
-
brought it about: the copy's own production for what the punching made,
|
|
218
|
-
an `Alteration` for what a later hand made, an `Attachment` for a patch
|
|
219
|
-
glued on. A `Removal` names by id what was taken off, which stood there
|
|
220
|
-
before the act.
|
|
13
|
+
```
|
|
14
|
+
npm i linked-rolls
|
|
15
|
+
```
|
|
221
16
|
|
|
222
|
-
|
|
223
|
-
hand, and says nothing about what kind of feature it is. A hole may be
|
|
224
|
-
punched by hand long after the roll was cut, and a mark may come from
|
|
225
|
-
the factory, rarely though that happens. A feature no later act is
|
|
226
|
-
known to have made belongs to the punching, which is where a reading of
|
|
227
|
-
a scan puts every chain of holes it finds.
|
|
17
|
+
## Usage
|
|
228
18
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
not: drawing, writing and punching bring a feature into being and are
|
|
233
|
-
productions (E12), which state what they made with `reo:produced`, a
|
|
234
|
-
subproperty of P108 has produced.
|
|
19
|
+
An edition is plain data. Operations are functions applied to an
|
|
20
|
+
[immer](https://immerjs.github.io/immer/) draft, so each one is a
|
|
21
|
+
single undo step.
|
|
235
22
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
rather than a feature) follows from property chains in `reo.ttl`, all
|
|
240
|
-
within OWL 2 RL. The chain for the punching runs over `reo:produced`
|
|
241
|
-
rather than P108, because R28 produced is itself a subproperty of P108
|
|
242
|
-
(LRMoo 1.0, p. 44), and a chain over P108 would have the copy bear
|
|
243
|
-
itself. That an attachment augments the copy and a removal diminishes
|
|
244
|
-
it depends on the class of the act, which no chain can test. These two
|
|
245
|
-
keys are derived on the way out and read off again on the way in, so
|
|
246
|
-
they are no part of the edition, and they are the one place where the
|
|
247
|
-
JSON tree and the graph differ in shape.
|
|
23
|
+
```ts
|
|
24
|
+
import { produce } from 'immer'
|
|
25
|
+
import { asJsonLd, connectVersions, createVersion, EditionView, importJsonLd, readFromStanfordAton } from 'linked-rolls'
|
|
248
26
|
|
|
249
|
-
|
|
27
|
+
let edition = importJsonLd(json)
|
|
250
28
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
scan, a `reading` of the timed switches of a roll reader, an
|
|
254
|
-
`emulation` in which the roll has already been read into notes and
|
|
255
|
-
commands, or a `recording` of the copy being played on an instrument.
|
|
256
|
-
Beside the kind it holds who carried the capture out, on what device,
|
|
257
|
-
with what software, on which instrument a recorded copy was played,
|
|
258
|
-
when, and a note. What is not known is left out.
|
|
29
|
+
// Add a copy read from a SUPRA analysis file, with a version of its own
|
|
30
|
+
edition = produce(edition, createVersion(readFromStanfordAton(aton)))
|
|
259
31
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
file it produced is `crmdig:L11 had output`, the machine it ran on
|
|
264
|
-
`crmdig:L12 happened on device`, the software `crmdig:L23 used
|
|
265
|
-
software or firmware`, the instrument `crm:P16 used specific object`.
|
|
32
|
+
// Collate that version against another one
|
|
33
|
+
const view = new EditionView(edition)
|
|
34
|
+
edition = produce(edition, connectVersions(view, childId, parentId))
|
|
266
35
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
that it names no source, that the making of its source is
|
|
270
|
-
undocumented, that no software or instrument is named for an
|
|
271
|
-
emulation or a recording, that its features are somebody else's
|
|
272
|
-
reading, that its source bears no physical evidence, that no measuring
|
|
273
|
-
software is recorded, that it is not calibrated, that nobody is known
|
|
274
|
-
to hold it. A reservation goes away when the gap it names is filled.
|
|
36
|
+
const document = asJsonLd(edition)
|
|
37
|
+
```
|
|
275
38
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
which versions it is held to carry, in `carries`, each under a belief
|
|
279
|
-
that says how certainly and why. `witnessesOf` gathers the copies of a
|
|
280
|
-
version, whether their features carry its symbols or they state that
|
|
281
|
-
they carry it, a statement with the belief it rests on;
|
|
282
|
-
`versionsWitnessedBy` gathers the same from the side of a copy.
|
|
283
|
-
`carriageProblems` reports a statement made beside features that carry
|
|
284
|
-
symbols already, or one naming a version the edition lacks. A copy may
|
|
285
|
-
carry a `siglum`, which is given by hand and not read off anything;
|
|
286
|
-
one without is named by its keeper.
|
|
39
|
+
Documents written by earlier releases are brought up to date on import.
|
|
40
|
+
To check a document against the schema:
|
|
287
41
|
|
|
288
42
|
```ts
|
|
289
|
-
import {
|
|
290
|
-
|
|
291
|
-
const next = produce(edition, stateSource(copyId, {
|
|
292
|
-
kind: 'emulation',
|
|
293
|
-
output: 'https://example.org/wm225.mid',
|
|
294
|
-
note: 'MIDI from a third party; the emulator is not named.'
|
|
295
|
-
}))
|
|
296
|
-
|
|
297
|
-
reservationsAbout(next.copies[0]).map(reservation => reservation.note)
|
|
43
|
+
import { validate } from 'linked-rolls/validate'
|
|
298
44
|
```
|
|
299
45
|
|
|
300
46
|
## Emulation
|
|
301
47
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
pedal step labelled by the symbol it performs. A reproducing system is a
|
|
307
|
-
tracker bar and a `perform` function; the core does not depend on any one
|
|
308
|
-
instrument's model.
|
|
309
|
-
|
|
310
|
-
The first system is the red Welte, `linked-rolls/welte-t100`, built on
|
|
311
|
-
[welte-mignon-emulator](https://github.com/pfefferniels/welte-t100): the
|
|
312
|
-
take-up spool sets the time axis, the Nuancierbälge fill through their
|
|
313
|
-
conduits and are arrested by the Mezzoforte pin, and the two pedals travel
|
|
314
|
-
rather than switch. The nuancing constants come as `instruments`: the
|
|
315
|
-
consensus fitted across the hand-drawn nuance lines of six rolls, which
|
|
316
|
-
is the default, and the setting that drew each of those rolls, named by
|
|
317
|
-
its Welte number, all with the terms that describe the drawing apparatus
|
|
318
|
-
switched off. The pedals leave no drawn line, so their constants
|
|
319
|
-
come as two readings, `pedalPresets.damping`, under which every lift the
|
|
320
|
-
rolls punch damps, and `pedalPresets.brushing`, under which the quick runs
|
|
321
|
-
of latch changes brush the strings without damping. What the emulator does
|
|
322
|
-
not determine is how bellows travel maps onto MIDI velocity;
|
|
323
|
-
`WelteT100Options.velocity` anchors that map at the open rail, the
|
|
324
|
-
Mezzoforte pin and the closed rail, and its defaults are midi2exp's.
|
|
48
|
+
A version can be played through a reproducing system and written out
|
|
49
|
+
as MIDI. The Welte-Mignon systems use
|
|
50
|
+
[welte-mignon-emulator](https://github.com/pfefferniels/welte-t100), an
|
|
51
|
+
optional peer dependency that you install only if you need playback.
|
|
325
52
|
|
|
326
53
|
```ts
|
|
327
|
-
import {
|
|
54
|
+
import { emulate, midiOf } from 'linked-rolls'
|
|
328
55
|
import { welteT100System } from 'linked-rolls/welte-t100'
|
|
329
56
|
|
|
330
|
-
const
|
|
331
|
-
|
|
332
|
-
const midi = emulation.asMIDI()
|
|
57
|
+
const { events, source } = emulate(welteT100System, version, view)
|
|
58
|
+
const midi = midiOf(events, welteT100System.name, welteT100System.defaultOptions, source)
|
|
333
59
|
```
|
|
334
60
|
|
|
335
|
-
The
|
|
336
|
-
|
|
337
|
-
unit built the same for both tracker scales (p. 96) — and what differs is
|
|
338
|
-
in front of it: each function lasts exactly as long as its own perforation
|
|
339
|
-
runs over the glide block rather than latching until a cancel line is read,
|
|
340
|
-
four conduits stand on one bellows and their drives add as flows, the
|
|
341
|
-
crescendo's ceiling is the balance of its throttle against a permanently
|
|
342
|
-
open bleed rather than a cap, the two pedals sit on the opposite edges of
|
|
343
|
-
the paper, and a long perforation on the bass sforzando-piano line sends
|
|
344
|
-
the roll back. Its constants are **not fitted**: `instruments.genuine` and
|
|
345
|
-
`instruments.derived` are empty until their fits are run, and until then a
|
|
346
|
-
playback runs on unfitted starting values, which every curve says in its
|
|
347
|
-
own `instrument` field.
|
|
348
|
-
|
|
349
|
-
Both systems share one velocity map, and `DynamicsCurve.travel` means the
|
|
350
|
-
same thing on both: the position on the printed ordinate of Welte's own
|
|
351
|
-
ruled band, 0 at that half's P.P. gridline and 1 at the shared F.F. line.
|
|
352
|
-
That is what lets a red issue and a green issue of one recording be
|
|
353
|
-
compared at all, since the band is ruled the same way on both.
|
|
61
|
+
The systems are `linked-rolls/welte-t100` (red Welte),
|
|
62
|
+
`linked-rolls/welte-t98` (green Welte) and `linked-rolls/welte-licensee`.
|
|
354
63
|
|
|
355
|
-
|
|
356
|
-
import { welteT98System } from 'linked-rolls/welte-t98'
|
|
357
|
-
```
|
|
64
|
+
## Format
|
|
358
65
|
|
|
359
|
-
The
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
66
|
+
The export uses the Roll Edition Ontology (REO), namespace
|
|
67
|
+
`https://w3id.org/reo/`, together with CIDOC CRM, LRMoo and CRMinf. The
|
|
68
|
+
ontology is in `ontology/`. It is published with its context and the
|
|
69
|
+
documentation of the format at
|
|
70
|
+
https://pfefferniels.github.io/linked-rolls/ (the w3id.org identifiers are
|
|
71
|
+
not registered yet).
|
|
365
72
|
|
|
366
|
-
|
|
73
|
+
Beliefs are written as JSON-LD-star annotations (`@annotation`), so you
|
|
74
|
+
need a processor that supports JSON-LD-star to read them.
|
|
367
75
|
|
|
368
|
-
|
|
369
|
-
fields on a command let an editor state where the measurement should
|
|
370
|
-
give way. `alignedWith` names another command whose onset this one takes
|
|
371
|
-
in the performance, as a "crescendo off" is meant to fall on the note
|
|
372
|
-
it belongs to. `before` and `after` name a command whose onset this
|
|
373
|
-
one precedes or follows, without saying by how much: where the copies
|
|
374
|
-
disagree on which side of a note an expression falls, the statement
|
|
375
|
-
settles the order. A command the measurement already has on the
|
|
376
|
-
stated side keeps its place. One it does not is put on that side, as
|
|
377
|
-
far from the reference as the copies that agree with the statement put
|
|
378
|
-
it, and a punch diameter away where none does. A command makes one
|
|
379
|
-
of these three statements at most. `pairedWith` names a partner whose
|
|
380
|
-
distance to this one is fixed, as a "forzando on" belongs with its
|
|
381
|
-
"forzando off": whatever displaces the one displaces the other. Any two
|
|
382
|
-
commands may be paired, the relation is symmetric, and it is stated
|
|
383
|
-
on one side only. All are applied when a version is emulated.
|
|
384
|
-
`constraintProblems` lists, version by version, the cases in which the
|
|
385
|
-
statements cannot hold: a reference or partner that is absent, a
|
|
386
|
-
command placed relative to itself or in several ways at once, one
|
|
387
|
-
claimed by several pairs, or a pair whose members are both placed.
|
|
76
|
+
## Development
|
|
388
77
|
|
|
389
|
-
## Building
|
|
390
78
|
```
|
|
391
|
-
|
|
392
|
-
|
|
79
|
+
npm ci
|
|
80
|
+
npm test
|
|
81
|
+
npm run lint
|
|
82
|
+
npm run build
|
|
393
83
|
```
|
|
394
84
|
|
|
395
85
|
## Releasing
|
|
396
86
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
workflow builds, runs the tests and publishes with provenance through
|
|
401
|
-
npm's trusted publishing, so no token is stored. It checks out the
|
|
402
|
-
emulator beside this repository to build the T-100 entry point.
|
|
87
|
+
Raise the version in `package.json`, commit, and push a tag
|
|
88
|
+
`v<version>`. The `publish.yml` workflow builds, tests and publishes to
|
|
89
|
+
npm.
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
1
|
+
import { speedScalesIn } from "./ownPaper.js";
|
|
2
|
+
import { idOf } from "../model/Assumption.js";
|
|
3
|
+
import { isCommand, pairsAmong, placementsOf } from "../model/Symbol.js";
|
|
4
|
+
import { keyOf } from "../systems/TrackerBar.js";
|
|
5
|
+
import { trackerBarOf } from "../systems/index.js";
|
|
6
|
+
import { barOf } from "../model/RollCopy.js";
|
|
7
|
+
import { deletedBy, insertedBy } from "../model/Version.js";
|
|
7
8
|
const missingReference = {
|
|
8
9
|
alignedWith: 'alignment-reference-missing',
|
|
9
10
|
before: 'before-reference-missing',
|
|
@@ -98,7 +99,7 @@ const carriersOffTheirMeaning = (view, version, commands) => {
|
|
|
98
99
|
* is evidence about the copies, and averaging it away would hide both
|
|
99
100
|
* the disagreement and the fact that the playback rests on a guess.
|
|
100
101
|
*/
|
|
101
|
-
const paperDisagreed = (view, version) =>
|
|
102
|
+
const paperDisagreed = (view, version) => speedScalesIn(view, version).length > 1
|
|
102
103
|
? [{ version: version.id, symbol: version.id, problem: 'copies-disagree-on-the-paper' }]
|
|
103
104
|
: [];
|
|
104
105
|
/**
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { EditionView } from "../view/EditionView.js";
|
|
2
|
+
import type { Version } from "../model/Version.js";
|
|
3
|
+
import { RollCopy } from "../model/RollCopy.js";
|
|
4
|
+
/** The copies of the version's own system that carry any of its symbols. */
|
|
5
|
+
export declare const copiesOwning: (view: EditionView, version: Readonly<Version>) => Readonly<RollCopy>[];
|
|
6
|
+
/** The scales of the version's own copies that are not their own paper stretch. */
|
|
7
|
+
export declare const speedScalesIn: (view: EditionView, version: Readonly<Version>) => number[];
|
|
8
|
+
/**
|
|
9
|
+
* How a place on the edition's shared axis relates to the paper of
|
|
10
|
+
* this version: place × factor = millimetres of its own paper.
|
|
11
|
+
*
|
|
12
|
+
* Copies cut for different systems are scaled onto one axis so that
|
|
13
|
+
* they can be collated at all, which leaves a version of another
|
|
14
|
+
* system carrying places in the axis copy's millimetres. A
|
|
15
|
+
* performance needs the paper the roll actually ran on, and the
|
|
16
|
+
* factor is the inverse of the scale `alignCopy` recorded.
|
|
17
|
+
*
|
|
18
|
+
* It is read only from the copies of the version's own system, since
|
|
19
|
+
* under the shared axis a green version's notes are carried by red
|
|
20
|
+
* copies too and those say nothing about green paper. A copy whose
|
|
21
|
+
* scale is put down to its own paper having stretched is left out as
|
|
22
|
+
* well: that is a fact about the one exemplar, not about the speed
|
|
23
|
+
* the system's rolls were cut at. Where what remains disagrees,
|
|
24
|
+
* `constraintProblems` reports it rather than averaging it away.
|
|
25
|
+
*/
|
|
26
|
+
export declare const toOwnPaperOf: (view: EditionView, version: Readonly<Version>) => number | undefined;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { idsOf } from "../model/Assumption.js";
|
|
2
|
+
import { isPaperStretch } from "../model/RollCopy.js";
|
|
3
|
+
import { systemIdOf } from "../systems/TrackerBar.js";
|
|
4
|
+
/** The copies of the version's own system that carry any of its symbols. */
|
|
5
|
+
export const copiesOwning = (view, version) => {
|
|
6
|
+
const system = systemIdOf(version.system);
|
|
7
|
+
const carrying = new Set(view.snapshot(version.id)
|
|
8
|
+
.flatMap(symbol => idsOf(symbol.carriers))
|
|
9
|
+
.flatMap(id => {
|
|
10
|
+
const copy = view.copyOf(id);
|
|
11
|
+
return copy ? [copy.id] : [];
|
|
12
|
+
}));
|
|
13
|
+
return view.edition.copies.filter(copy => carrying.has(copy.id) && systemIdOf(copy.production?.system) === system);
|
|
14
|
+
};
|
|
15
|
+
/** The scales of the version's own copies that are not their own paper stretch. */
|
|
16
|
+
export const speedScalesIn = (view, version) => [...new Set(copiesOwning(view, version)
|
|
17
|
+
.filter(copy => !copy.conditions.some(isPaperStretch))
|
|
18
|
+
.map(copy => copy.measurements.scale)
|
|
19
|
+
.filter((scale) => scale !== undefined && scale > 0))];
|
|
20
|
+
/**
|
|
21
|
+
* How a place on the edition's shared axis relates to the paper of
|
|
22
|
+
* this version: place × factor = millimetres of its own paper.
|
|
23
|
+
*
|
|
24
|
+
* Copies cut for different systems are scaled onto one axis so that
|
|
25
|
+
* they can be collated at all, which leaves a version of another
|
|
26
|
+
* system carrying places in the axis copy's millimetres. A
|
|
27
|
+
* performance needs the paper the roll actually ran on, and the
|
|
28
|
+
* factor is the inverse of the scale `alignCopy` recorded.
|
|
29
|
+
*
|
|
30
|
+
* It is read only from the copies of the version's own system, since
|
|
31
|
+
* under the shared axis a green version's notes are carried by red
|
|
32
|
+
* copies too and those say nothing about green paper. A copy whose
|
|
33
|
+
* scale is put down to its own paper having stretched is left out as
|
|
34
|
+
* well: that is a fact about the one exemplar, not about the speed
|
|
35
|
+
* the system's rolls were cut at. Where what remains disagrees,
|
|
36
|
+
* `constraintProblems` reports it rather than averaging it away.
|
|
37
|
+
*/
|
|
38
|
+
export const toOwnPaperOf = (view, version) => {
|
|
39
|
+
const scales = speedScalesIn(view, version);
|
|
40
|
+
return scales.length === 1 ? 1 / scales[0] : undefined;
|
|
41
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { RollCopy } from "
|
|
2
|
-
import { Version } from "
|
|
3
|
-
import { EditionView } from "
|
|
1
|
+
import { RollCopy } from "../model/RollCopy.js";
|
|
2
|
+
import { Version } from "../model/Version.js";
|
|
3
|
+
import { EditionView } from "../view/EditionView.js";
|
|
4
4
|
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'];
|
|
5
5
|
export type ReservationType = typeof reservationTypes[number];
|
|
6
6
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { bearsPhysicalEvidence, isMeasured, sourceLabels } from "
|
|
2
|
-
import { calibrationOf, featuresOf } from "
|
|
3
|
-
import { trackerBarOf } from "
|
|
1
|
+
import { bearsPhysicalEvidence, isMeasured, sourceLabels } from "../model/FeatureSource.js";
|
|
2
|
+
import { calibrationOf, featuresOf } from "../model/RollCopy.js";
|
|
3
|
+
import { trackerBarOf } from "../systems/index.js";
|
|
4
4
|
import { witnessesOf } from "./witnesses.js";
|
|
5
5
|
export const reservationTypes = [
|
|
6
6
|
'source-not-stated',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Edition } from '
|
|
2
|
-
import { EditionView } from '
|
|
1
|
+
import { Edition } from '../model/Edition.js';
|
|
2
|
+
import { EditionView } from '../view/EditionView.js';
|
|
3
3
|
/**
|
|
4
4
|
* What the sigla are read off: the versions alone, or a view, which knows
|
|
5
5
|
* the copies as well and so can tell which versions a witness shows.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { idOf } from '
|
|
2
|
-
import { systemIdOf } from '
|
|
3
|
-
import { trackerBarOf } from '
|
|
4
|
-
import { principalDerivationOf } from '
|
|
1
|
+
import { idOf } from '../model/Assumption.js';
|
|
2
|
+
import { systemIdOf } from '../systems/TrackerBar.js';
|
|
3
|
+
import { trackerBarOf } from '../systems/index.js';
|
|
4
|
+
import { principalDerivationOf } from '../model/Version.js';
|
|
5
5
|
import { attestedVersions } from './witnesses.js';
|
|
6
6
|
/** The letter the versions of a system are labelled with. */
|
|
7
7
|
const letters = new Map([
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Belief, Certainty } from "
|
|
2
|
-
import { EditionView } from "
|
|
1
|
+
import { Belief, Certainty } from "../model/Assumption.js";
|
|
2
|
+
import { EditionView } from "../view/EditionView.js";
|
|
3
3
|
export type WitnessBy = 'carriers' | 'statement';
|
|
4
4
|
/** A copy that bears witness to a version, and how. */
|
|
5
5
|
export interface Witness {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { certaintyOf, idOf, idsOf } from "
|
|
2
|
-
import { insertedBy } from "
|
|
1
|
+
import { certaintyOf, idOf, idsOf } from "../model/Assumption.js";
|
|
2
|
+
import { insertedBy } from "../model/Version.js";
|
|
3
3
|
/** The copies whose features carry any of the symbols. */
|
|
4
4
|
const copiesCarrying = (view, symbols) => new Set(symbols
|
|
5
5
|
.flatMap(symbol => idsOf(symbol.carriers))
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Edit } from "
|
|
2
|
-
import { HorizontalSpan } from "
|
|
3
|
-
import { AnySymbol } from "
|
|
4
|
-
import { Millimeters } from "
|
|
1
|
+
import { Edit } from "../model/Edit.js";
|
|
2
|
+
import { HorizontalSpan } from "../model/Feature.js";
|
|
3
|
+
import { AnySymbol } from "../model/Symbol.js";
|
|
4
|
+
import { Millimeters } from "../model/Quantity.js";
|
|
5
5
|
/** A value taken at each end of a feature: where it begins and where it stops. */
|
|
6
6
|
export interface BothEnds<T> {
|
|
7
7
|
from: T;
|