Commentary

Published

June 12, 2024

A CitableCommentary records annotations by one text on another text. Each text is identified by a CtsUrn. In general, therefore, when you use CitableAnnotations you’ll also want to include both the CitableBase and CitableText package, where the Urn abstraction and CtsUrn type are defined.

using CitableBase, CitableText, CitableAnnotations

Loading a commentary from CEX

A CitableCommentary can be serialized to and instantiated from CEX source that includes a citerelationset block and declares a data model for it. Here is an example:

cexdata = """
#!datamodels
Collection|Model|Label|Description
urn:cite2:hmt:commentary.v1:all|urn:cite2:cite:datamodels.v1:commentarymodel|Relation of commentary to text passages commented on.


#!citerelationset
urn|urn:cite2:hmt:commentary.v1:all
label|Index of scholia to *Iliad* passages they comment on
scholion|iliad

urn:cts:greekLit:tlg5026.msAint.hmt:1.27|urn:cts:greekLit:tlg0012.tlg001.msA:1.8
urn:cts:greekLit:tlg5026.msAint.hmt:1.28|urn:cts:greekLit:tlg0012.tlg001.msA:1.13-1.16
urn:cts:greekLit:tlg5026.msAint.hmt:1.29|urn:cts:greekLit:tlg0012.tlg001.msA:1.13-1.14
urn:cts:greekLit:tlg5026.msAint.hmt:1.30|urn:cts:greekLit:tlg0012.tlg001.msA:1.13-1.14
urn:cts:greekLit:tlg5026.msAint.hmt:1.31|urn:cts:greekLit:tlg0012.tlg001.msA:1.13-1.14
urn:cts:greekLit:tlg5026.msAint.hmt:1.32|urn:cts:greekLit:tlg0012.tlg001.msA:1.20
urn:cts:greekLit:tlg5026.msAint.hmt:1.55|urn:cts:greekLit:tlg0012.tlg001.msA:1.30
urn:cts:greekLit:tlg5026.msAint.hmt:1.56|urn:cts:greekLit:tlg0012.tlg001.msA:1.39
urn:cts:greekLit:tlg5026.msAint.hmt:1.57|urn:cts:greekLit:tlg0012.tlg001.msA:1.41
"""

Use the fromcex function (from CitableBase) to create a Vector of CitableCommentary objects. In this example, we already know our CEX only has one commentary, so we’ll take the first element from the Vector.

citcomm = fromcex(cexdata, CitableCommentary)[1]
urn:cite2:hmt:commentary.v1:all Index of scholia to *Iliad* passages they comment on

A citable object

A commentary satisfies the definition of a citable object in CitableBase, as you can verify with the citable function:

citable(citcomm)
true

This means it has a human-readable label, and is identified by a URN of a specified type.

label(citcomm)
"Index of scholia to *Iliad* passages they comment on"
urntype(citcomm)
CitableObject.Cite2Urn
urn(citcomm)
urn:cite2:hmt:commentary.v1:all
Note

Note that the URN identifies the set of relations as a group, not individual annotations within the set.

Metadata about a commentary

Use the generic functions applicable to any CitableAnnotation to see the structure of the commentary. We can see that it consists of CtsUrns commenting on other CtsUrns.

annotatingtype(citcomm)
CtsUrn
annotatedtype(citcomm)
CtsUrn

Find what texts annotate other texts and what texts are annotated (that is, find the unique sets of CTS URNs, without their passage references, on each side of the relation). In this small example, a single annotating document (interior scholia from the Venetus A manuscript, urn:cts:greekLit:tlg5026.msAint.hmt:) comments on a single annotated document (the Iliad, urn:cts:greekLit:tlg0012.tlg001.msA:).

annotators(citcomm)
Set{CtsUrn} with 1 element:
  urn:cts:greekLit:tlg5026.msAint.hmt:
annotated(citcomm)
Set{CtsUrn} with 1 element:
  urn:cts:greekLit:tlg0012.tlg001.msA:

Working with a commentary

You can use the CitableCommentary type with dozens of generic Julia functions. Here are examples of a few commonly used functions.

Tip

The documentation for CitableBase includes several dozen functions that are available to use with citable collections, including CitableCommentary.

The number of annotations in your commentary:

length(citcomm)
9

The structure in Julia for an individual comment is a Tuple of CtsUrns:

eltype(citcomm)
Tuple{CtsUrn, CtsUrn}

Find what Iliad passages are annotated with the map function.

map(pr -> passagecomponent(pr[2]), citcomm)
9-element Vector{SubString{String}}:
 "1.8"
 "1.13-1.16"
 "1.13-1.14"
 "1.13-1.14"
 "1.13-1.14"
 "1.20"
 "1.30"
 "1.39"
 "1.41"

Find what annotations that comment on a range of Iliad with the filter function. Filtering a commentary returns an iterator; we’ll collect the results here.

filter(pr -> isrange(pr[2]), citcomm) |> collect
4-element Vector{Tuple{CtsUrn, CtsUrn}}:
 (urn:cts:greekLit:tlg5026.msAint.hmt:1.28, urn:cts:greekLit:tlg0012.tlg001.msA:1.13-1.16)
 (urn:cts:greekLit:tlg5026.msAint.hmt:1.29, urn:cts:greekLit:tlg0012.tlg001.msA:1.13-1.14)
 (urn:cts:greekLit:tlg5026.msAint.hmt:1.30, urn:cts:greekLit:tlg0012.tlg001.msA:1.13-1.14)
 (urn:cts:greekLit:tlg5026.msAint.hmt:1.31, urn:cts:greekLit:tlg0012.tlg001.msA:1.13-1.14)

Iterate through the commentary to pair scholia commenting on a range of Iliad lines with the first line they comment on.

rangecomments = []
for comment in citcomm
    if isrange(comment[2])
        push!(rangecomments, (comment[1], range_begin(comment[2])))
    end
end
rangecomments
4-element Vector{Any}:
 (urn:cts:greekLit:tlg5026.msAint.hmt:1.28, "1.13")
 (urn:cts:greekLit:tlg5026.msAint.hmt:1.29, "1.13")
 (urn:cts:greekLit:tlg5026.msAint.hmt:1.30, "1.13")
 (urn:cts:greekLit:tlg5026.msAint.hmt:1.31, "1.13")