Co-occurrence¶
Which annotation layers coincide, and by how much.
Which annotation layers coincide, and by how much.
A timeline showing motion on one line and speech on another lets a reader see that the two coincide. It does not let them count it, filter by it, or ask for every gesture made in silence --- and combinations are what a qualitative annotator works in. This turns coincidence from something visible into something addressable: a label on each span, and a table of how the recording divides.
Not restricted to speech and motion. Any two layers: laughter against gesture, gesture against a rehearsal segmentation, one annotator's tier against another's. The names are arguments, not assumptions.
Overlapping reference spans are merged before anything is counted. Two detections that touch describe one region. Counting them separately would credit a gesture with twice the accompaniment it had, and detectors emit touching spans routinely --- so the union is taken first, every time, rather than trusting the caller to have tidied up.
merge_spans ¶
merge_spans(spans)
The union of a set of spans, as disjoint (start, end) pairs in time order.
Source code in musicalgestures/_cooccurrence.py
27 28 29 30 31 32 33 34 35 36 37 38 | |
overlap_seconds ¶
overlap_seconds(span, others)
How many seconds of span are covered by any of others.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
span
|
The Action being asked about. |
required | |
others
|
The reference layer. Order and overlap do not matter; the union is taken. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
float |
float
|
Seconds of overlap, never more than |
Source code in musicalgestures/_cooccurrence.py
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | |
label_by_overlap ¶
label_by_overlap(spans, others, name, threshold=0.5, present='with', absent='without')
Label each span by whether it coincides with a reference layer.
Returns new Actions rather than modifying the ones passed in: the same gestures get labelled against several layers in turn --- speech, then laughter, then someone else's segmentation --- and a function that mutated its input would make the second call depend on the first.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spans
|
The Actions to label. |
required | |
others
|
The reference layer to compare against. |
required | |
name
|
str
|
What the reference layer is called. Becomes the label key, and
|
required |
threshold
|
float
|
Fraction of a span that must be covered for |
0.5
|
present
|
str
|
Label for spans at or above the threshold. Defaults to |
'with'
|
absent
|
str
|
Label for spans below it. Defaults to |
'without'
|
Returns:
| Name | Type | Description |
|---|---|---|
list |
list[Action]
|
New Actions carrying the label and the exact overlap fraction. The fraction |
list[Action]
|
is kept because a threshold is a decision and the number underneath it should stay |
|
list[Action]
|
visible. |
Source code in musicalgestures/_cooccurrence.py
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | |
cooccurrence_table ¶
cooccurrence_table(a_spans, b_spans, duration_s)
How a recording divides between two annotation layers, in seconds.
Four cells, and every instant of the recording is in exactly one of them, so they sum
to duration_s. That invariant is the point: a table whose cells do not add up is
reporting an overlap that was counted twice or a gap that was lost.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
a_spans
|
The first layer, for example gestures. |
required | |
b_spans
|
The second layer, for example speech. |
required | |
duration_s
|
float
|
Length of the recording. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
dict |
dict
|
Seconds in |
dict
|
as percentages of |
Source code in musicalgestures/_cooccurrence.py
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | |