speechmetryflow 0.2.2__py3-none-any.whl

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 (35) hide show
  1. speechmetryflow/__init__.py +25 -0
  2. speechmetryflow/_version.py +34 -0
  3. speechmetryflow/cli.py +131 -0
  4. speechmetryflow/lexical/__init__.py +17 -0
  5. speechmetryflow/lexical/assets/__init__.py +103 -0
  6. speechmetryflow/lexical/assets/concreteness.tsv +39955 -0
  7. speechmetryflow/lexical/assets/familiarity_imageability.tsv +5554 -0
  8. speechmetryflow/lexical/assets/frequency.tsv +74289 -0
  9. speechmetryflow/lexical/assets/valence.tsv +13916 -0
  10. speechmetryflow/lexical/database.py +143 -0
  11. speechmetryflow/lexical/part_of_speech.py +172 -0
  12. speechmetryflow/lexical/utils.py +119 -0
  13. speechmetryflow/pragmatic/__init__.py +60 -0
  14. speechmetryflow/pragmatic/assets.py +62 -0
  15. speechmetryflow/pragmatic/database.py +113 -0
  16. speechmetryflow/semantic/__init__.py +23 -0
  17. speechmetryflow/semantic/assets.py +285 -0
  18. speechmetryflow/semantic/icu.py +33 -0
  19. speechmetryflow/semantic/idea_density.py +78 -0
  20. speechmetryflow/speech_production/__init__.py +62 -0
  21. speechmetryflow/speech_production/assets/__init__.py +58 -0
  22. speechmetryflow/speech_production/assets/words_fr.json +1 -0
  23. speechmetryflow/speech_production/fluency.py +42 -0
  24. speechmetryflow/speech_production/fragment.py +76 -0
  25. speechmetryflow/syntactic/__init__.py +119 -0
  26. speechmetryflow/syntactic/assets.py +40 -0
  27. speechmetryflow/syntactic/dependency.py +47 -0
  28. speechmetryflow/syntactic/sentences.py +189 -0
  29. speechmetryflow/ucsf_disfluency/__init__.py +23 -0
  30. speechmetryflow/utils.py +53 -0
  31. speechmetryflow-0.2.2.dist-info/METADATA +764 -0
  32. speechmetryflow-0.2.2.dist-info/RECORD +35 -0
  33. speechmetryflow-0.2.2.dist-info/WHEEL +4 -0
  34. speechmetryflow-0.2.2.dist-info/entry_points.txt +3 -0
  35. speechmetryflow-0.2.2.dist-info/licenses/LICENSE +674 -0
@@ -0,0 +1,285 @@
1
+ # ICU dictionaries for both languages
2
+ ICU_cookie_fr = {
3
+ "mère": ["mère", "maman", "mamie", "mam", "mamma", "momma", "ma", "mama", "femme"],
4
+ "garçon": [
5
+ "garçon",
6
+ "gamin",
7
+ "mec",
8
+ "gosse",
9
+ "fils",
10
+ "écolier",
11
+ "jeune homme",
12
+ "jeune garçon",
13
+ "enfant mâle",
14
+ ],
15
+ "fille": [
16
+ "fille",
17
+ "fille",
18
+ "jeune fille",
19
+ "écolière",
20
+ "jeune dame",
21
+ "jeune fille",
22
+ "enfant femelle",
23
+ ],
24
+ "cuisine": [
25
+ "cuisine",
26
+ ],
27
+ "extérieur": ["extérieur", "dehors", "à l'air libre", "en plein air"],
28
+ "robinet": ["robinet", "évacuation", "mitigeur"],
29
+ "eau": [
30
+ "eau",
31
+ ],
32
+ "évier": [
33
+ "évier",
34
+ ],
35
+ "sol": ["sol", "terre", "plancher"],
36
+ "assiette": ["assiette", "plat", "plateau", "soucoupe"],
37
+ "vaisselle_sur_comptoir": ["posée sur", "placée sur", "étalée sur"],
38
+ "comptoir": ["comptoir", "plan de travail"],
39
+ "cookies": ["cookies", "biscuit", "biscuits"],
40
+ "bocal": ["bocal", "pot", "boîte"],
41
+ "placard": ["placard", "armoire", "placards", "armoires"],
42
+ "tabouret": ["tabouret", "escabeau"],
43
+ "fenêtre": [
44
+ "fenêtre",
45
+ ],
46
+ "rideau": ["rideau", "store", "écran", "volet"],
47
+ "garçon_prenant_cookie": [
48
+ "prenant",
49
+ "saisissant",
50
+ "atteignant",
51
+ "prendre",
52
+ "saisir",
53
+ "atteindre",
54
+ "se saisir",
55
+ ],
56
+ "garçon_tabouret_tombant": ["tombant", "basculant", "tomber", "basculer"],
57
+ "mère_séchant_lavant_vaisselle": [
58
+ "sécher",
59
+ "séchant",
60
+ "laver",
61
+ "lavant",
62
+ "nettoyer",
63
+ "nettoyant",
64
+ "frotter",
65
+ "frottant",
66
+ "essuyant",
67
+ "faire la vaisselle",
68
+ ],
69
+ "eau_débordant": [
70
+ "déborder",
71
+ "débordant",
72
+ "renverser",
73
+ "renversant",
74
+ "cascader",
75
+ "évier débordant",
76
+ "débordement",
77
+ ],
78
+ "fille_demandant_cookie": [
79
+ "demander",
80
+ "demandant",
81
+ "vouloir",
82
+ "veut",
83
+ "solliciter",
84
+ "sollicite",
85
+ ],
86
+ "mère_indifférente_au_débordement": [
87
+ "indifférente",
88
+ "pas dérangée",
89
+ "se soucier",
90
+ "pas dérangé",
91
+ "remarqué",
92
+ "déranger",
93
+ ],
94
+ "mère_ne_remarquant_pas_les_enfants": [
95
+ "inconsciente",
96
+ "remarqué",
97
+ "pas remarqué",
98
+ "pas prendre garde",
99
+ "pas dérangée",
100
+ "pas dérangé",
101
+ ],
102
+ }
103
+
104
+ ICU_cookie_en = {
105
+ "mother": [
106
+ "mother",
107
+ "mom",
108
+ "mum",
109
+ "mommy",
110
+ "mummy",
111
+ "mamma",
112
+ "momma",
113
+ "ma",
114
+ "mama",
115
+ "woman",
116
+ ],
117
+ "boy": [
118
+ "boy",
119
+ "guy",
120
+ "dude",
121
+ "lad",
122
+ "son",
123
+ "schoolboy",
124
+ "young man",
125
+ "son",
126
+ "young boy",
127
+ "male child",
128
+ ],
129
+ "girl": [
130
+ "girl",
131
+ "daughter",
132
+ "lass",
133
+ "schoolgirl",
134
+ "young lady",
135
+ "young girl",
136
+ "female child",
137
+ ],
138
+ "kitchen": [
139
+ "kitchen",
140
+ ],
141
+ "exterior": ["exterior", "outside", "outdoor", "outdoors"],
142
+ "faucet": ["faucet", "drain", "tap"],
143
+ "water": [
144
+ "water",
145
+ ],
146
+ "sink": [
147
+ "sink",
148
+ ],
149
+ "floor": ["floor", "ground", "flooring"],
150
+ "plate": ["plate", "dish", "platter", "saucer"],
151
+ "dishes on counter": ["laying on", "placed on", "spread on"],
152
+ "counter": ["counter", "worktop", "counter top", "countertop"],
153
+ "cookies": ["cookies", "cookie", "biscuits", "biscuit"],
154
+ "jar": ["jar", "pot", "tin"],
155
+ "cabinet": ["cabinet", "cupboard", "cabinets", "cupboards"],
156
+ "stool": ["stool", "footstool"],
157
+ "window": [
158
+ "window",
159
+ ],
160
+ "curtain": ["curtain", "blind", "screen", "shutter"],
161
+ "boy_taking_cookie": [
162
+ "taking",
163
+ "grabbing",
164
+ "reaching",
165
+ "take",
166
+ "grab",
167
+ "reach",
168
+ "get hold",
169
+ ],
170
+ "boy_stool_falling": ["falling", "tipping", "fall", "tip"],
171
+ "mother_drying_washing_dishes": [
172
+ "dry",
173
+ "drying",
174
+ "wash",
175
+ "washing",
176
+ "clean",
177
+ "cleaning",
178
+ "scrub",
179
+ "scrubbing",
180
+ "wiping",
181
+ "doing dishes",
182
+ "doing the dishes",
183
+ ],
184
+ "water_overflowing": [
185
+ "overflow",
186
+ "overflowing",
187
+ "spill",
188
+ "spilling",
189
+ "cascading",
190
+ "sink running over",
191
+ "overrunning",
192
+ ],
193
+ "girl_asking_for_cookie": [
194
+ "ask",
195
+ "asking",
196
+ "want",
197
+ "wants",
198
+ "requesting",
199
+ "requests",
200
+ ],
201
+ "mother_unconcerned_about_overflowing": [
202
+ "unconcerned",
203
+ "unbothered",
204
+ "care",
205
+ "not bothered",
206
+ "noticed",
207
+ "bother",
208
+ ],
209
+ "mother_not_noticing_children": [
210
+ "unnoticing",
211
+ "noticed",
212
+ "not noticed",
213
+ "not take notice",
214
+ "unbothered",
215
+ "not bothered",
216
+ ],
217
+ }
218
+
219
+ # define Information Content Units (ICU) with the grid from Jensen, Chenery, Copland (2006) J Comm Dis
220
+ ICU_picnic_en = {
221
+ "father": ["father", "husband", "daddy", "Dad", "dad"],
222
+ "mother": ["mother", "wife", "mom", "mommy", "girl"],
223
+ "couple": ["couple", "parents", "owners"],
224
+ "child": [
225
+ "child",
226
+ ],
227
+ "boy": ["boy", "brother"],
228
+ "fisherman": ["fisherman", "fisher", "rod"],
229
+ "sailors": ["sailors", "people", "people sailing"],
230
+ "dog": ["dog", "doggy", "animal"],
231
+ "garage": [
232
+ "garage",
233
+ ],
234
+ "water": [
235
+ "water",
236
+ "lake",
237
+ "river",
238
+ "sea",
239
+ "ocean",
240
+ "bank",
241
+ "edge",
242
+ "shore",
243
+ "riverside",
244
+ ],
245
+ "beach": ["beach", "sand"],
246
+ #'pail': ['pail', 'blanket'], this one is not in Jensen
247
+ "jetty": ["jetty", "wharf", "dock"],
248
+ "kite": [
249
+ "kite",
250
+ ],
251
+ "book": ["book", "novel"],
252
+ "bucket": [
253
+ "bucket",
254
+ ],
255
+ "spade": ["spade", "shovel"],
256
+ "car": ["car", "vehicle", "automobile", "sedan", "wagon"],
257
+ "boat": ["boat", "sailboat", "yacht", "vessel", "slinghy", "sloop"],
258
+ "flag": ["flag", "pole"],
259
+ "radio": ["radio", "transistor"],
260
+ "sandals": ["sandals", "shoes", "shoe", "flip", "flops"],
261
+ "tree": ["tree", "oak"],
262
+ "basket": ["basket"],
263
+ "drink": ["drink", "bottle", "wine", "soda", "beer", "liquor", "coffee", "tea"],
264
+ "house": ["house", "cottage", "shack", "cottage"],
265
+ "reading": ["reading", "read"],
266
+ "fishing": ["fishing", "fish", "catch"],
267
+ "pouring": ["pouring", "pour", "serve"],
268
+ "flying": ["flying", "fly"], # flag #kite
269
+ "playing": [
270
+ "playing",
271
+ "play",
272
+ "build",
273
+ "building",
274
+ "blasting",
275
+ ], # child on the beach # radio
276
+ "picnicking": ["picnic", "picnicking"],
277
+ "sailing": ["sailing", "sail", "boating"],
278
+ "parking": ["parking", "parked", "park"],
279
+ }
280
+
281
+ ICU_references = {
282
+ "cookie_en": ICU_cookie_en,
283
+ "cookie_fr": ICU_cookie_fr,
284
+ "picnic_en": ICU_picnic_en,
285
+ }
@@ -0,0 +1,33 @@
1
+ from speechmetryflow.semantic.assets import ICU_references
2
+
3
+
4
+ def compute_icu(text, lang, task):
5
+ """
6
+ Analyses the text to detect the presence of ICUs (Information Content Unique)
7
+ associated with specific subjects, places, objects, and actions.
8
+
9
+ Args:
10
+ text (str): The text to be analysed.
11
+ language (str): The language of the text ("fr" or "en").
12
+ task (str): Image used to generate the text ("cookie" or "picnic").
13
+
14
+ Returns:
15
+ dict: A dictionary containing information about the presence of ICUs. Each ICU is associated with a key
16
+ and the corresponding value is True if the ICU is found in the text, otherwise False.
17
+ """
18
+ ICU_dict = ICU_references.get(f"{task}_{lang}")
19
+
20
+ if ICU_dict is None:
21
+ return
22
+
23
+ # Initialising the results dictionary
24
+ icu_data = {f"icu_{icu}": False for icu in ICU_dict.keys()}
25
+
26
+ # Verification of the presence of each ICU in the text
27
+ for icu, words in ICU_dict.items():
28
+ for word in words:
29
+ if word in text:
30
+ icu_data[f"icu_{icu}"] = True
31
+ break # Move to the next ICU as soon as a match is found
32
+
33
+ return icu_data
@@ -0,0 +1,78 @@
1
+ import itertools
2
+ import numpy as np
3
+ import torch
4
+
5
+ from numpy.lib.stride_tricks import sliding_window_view
6
+ from torch.nn.functional import cosine_similarity
7
+
8
+
9
+ def compute_idea_density(tokens, window_shapes):
10
+ """
11
+ Compute average cosine similarities between token embeddings across
12
+ different sliding window sizes.
13
+
14
+ This function measures how semantically similar nearby tokens are,
15
+ for multiple window lengths (e.g. 3, 5, 7). For each window shape,
16
+ all pairwise cosine similarities are computed between embeddings in
17
+ that window, and the mean similarity is recorded.
18
+
19
+ To optimize performance, previously computed pairwise similarities
20
+ are cached in `cosine_similarity_data` so that redundant comparisons
21
+ across overlapping windows are not recomputed.
22
+
23
+ Parameters
24
+ ----------
25
+ tokens : list
26
+ A list of token objects, each exposing a `.vector` attribute
27
+ (NumPy array) representing its embedding.
28
+ window_shapes : iterable of int
29
+ A list or sequence of integer window sizes to apply
30
+ (e.g., [3, 10, 25, 40]).
31
+
32
+ Returns
33
+ -------
34
+ dict
35
+ A dictionary mapping each window size key
36
+ (e.g., "idea_density_3") to the mean cosine similarity
37
+ of all windows of that size. If a window shape is larger
38
+ than the number of tokens, the value is `None`.
39
+ """
40
+ # Convert all token vectors to PyTorch tensors
41
+ embeddings = [torch.from_numpy(token.vector) for token in tokens]
42
+ embeddings_index = list(range(len(embeddings)))
43
+ cosine_similarity_data = {}
44
+
45
+ results = {}
46
+ for window_shape in window_shapes:
47
+ results_key = f"idea_density_{window_shape}"
48
+
49
+ try:
50
+ # Generate sliding windows of token indices
51
+ windows = sliding_window_view(embeddings_index, window_shape=window_shape)
52
+ except ValueError:
53
+ # if window_shape is larger than embeddings
54
+ results[results_key] = None
55
+ continue
56
+
57
+ similarities = []
58
+ for window in windows:
59
+ window_cosine_similarities = []
60
+
61
+ # Compute all pairwise cosine similarities in the window
62
+ # cosine similarities are stored in cosine_similarity_data cache
63
+ # in order to avoid multiple computing
64
+ for col1, col2 in itertools.combinations(window, 2):
65
+ col_pairs = (col1, col2)
66
+ if col_pairs not in cosine_similarity_data:
67
+ cosine_similarity_data[col_pairs] = float(
68
+ cosine_similarity(embeddings[col1], embeddings[col2], dim=0)
69
+ )
70
+ window_cosine_similarities.append(cosine_similarity_data[col_pairs])
71
+
72
+ # Average similarity for this window
73
+ similarities.append(np.mean(window_cosine_similarities))
74
+
75
+ # Mean similarity across all windows of this shape
76
+ results[results_key] = np.mean(similarities)
77
+
78
+ return results
@@ -0,0 +1,62 @@
1
+ from speechmetryflow.speech_production import fluency
2
+ from speechmetryflow.speech_production.fragment import Fragment
3
+
4
+ from collections import Counter
5
+
6
+
7
+ def compute_counts(words):
8
+ """
9
+ Compute various count statistics for a list of words.
10
+
11
+ Parameters
12
+ ----------
13
+ words (list of str): The list of words to analyze.
14
+
15
+ Returns
16
+ -------
17
+ n (int): Total number of words in the list.
18
+ n_different (int): Number of distinct words (vocabulary size).
19
+ n_unique (int): Number of words that occur exactly once.
20
+ n_repetition (int): Number of distinct words that occur more than once
21
+
22
+ Examples
23
+ --------
24
+ >>> compute_counts(["cat", "dog", "cat", "mouse"])
25
+ (4, 3, 2, 1)
26
+ """
27
+ n = len(words)
28
+ counter = Counter(words)
29
+ n_different = len(counter)
30
+ n_unique = len([word for word, count in counter.items() if count == 1])
31
+ n_repetition = n_different - n_unique
32
+ return n, n_different, n_unique, n_repetition
33
+
34
+
35
+ def metrics(raw_text, tokens, lemmas, lang, task):
36
+ fragment = Fragment(lang, task)
37
+
38
+ n_tokens, n_different_tokens, n_unique_tokens, n_repetition_tokens = compute_counts(
39
+ tokens
40
+ )
41
+ n_lemmas, n_different_lemmas, n_unique_lemmas, n_repetition_lemmas = compute_counts(
42
+ lemmas
43
+ )
44
+
45
+ return {
46
+ "n_tokens": n_tokens,
47
+ "n_different_tokens": n_different_tokens,
48
+ "n_unique_tokens": n_unique_tokens,
49
+ "n_repetition_tokens": n_repetition_tokens,
50
+ "n_lemmas": n_lemmas,
51
+ "n_different_lemmas": n_different_lemmas,
52
+ "n_unique_lemmas": n_unique_lemmas,
53
+ "n_repetition_lemmas": n_repetition_lemmas,
54
+ "n_fragments": fragment.counter(tokens),
55
+ "n_fragments_context": fragment.context(tokens),
56
+ "n_silent_pauses": fluency.count_silent_pauses(raw_text, lang),
57
+ "n_filled_pauses": fluency.count_filled_pauses(raw_text, lang),
58
+ "n_ucsf_silent_pauses": fluency.count_silent_pauses(
59
+ raw_text, pause_marker="..."
60
+ ),
61
+ "n_ucsf_filled_pauses": fluency.count_filled_pauses(raw_text, "ucsf"),
62
+ }
@@ -0,0 +1,58 @@
1
+ # Fluency
2
+ filled_pauses = {
3
+ "en": [
4
+ "uhm",
5
+ "uh",
6
+ "uhummm",
7
+ "hum",
8
+ "hummmm",
9
+ "humm",
10
+ "mm",
11
+ "mmm",
12
+ "Mm",
13
+ "um",
14
+ "hmmm",
15
+ "hmm",
16
+ "hm",
17
+ "eh",
18
+ "err",
19
+ ],
20
+ "fr": ["euh", "hum", "heu", "hm", "öhm", "uhm", "mmh", "mh"],
21
+ "ucsf": ["um", "er", "uh", "ah", "hmm", "erm", "like", "so", "well"],
22
+ }
23
+
24
+ # context fragments computation
25
+ target_words = {
26
+ "en": [
27
+ ("the", "there"),
28
+ ("dry", "or"),
29
+ ("out", "outside"),
30
+ ("wash", "drying"),
31
+ ("curt", "the"),
32
+ ("is", "spill"),
33
+ ("wash", "is"),
34
+ ("bow", "Cup"),
35
+ ("tap", "taps"),
36
+ ("spill", "is"),
37
+ ("kit", "the"),
38
+ ("stand", "standing"),
39
+ ("go", "reaching"),
40
+ ("dish", "The"),
41
+ ("look", "uh"),
42
+ ("dry", "or"),
43
+ ("watch", "washing"),
44
+ ("sleeve", "sleeveless"),
45
+ ("cook", "cookie"),
46
+ ("a", "an"),
47
+ ("day", "daytime"),
48
+ ("curt", "the"),
49
+ ("look", "reaching"),
50
+ ("sister", "reach"),
51
+ ("cab", "the"),
52
+ ("cook", "the"),
53
+ ("stand", "climbing"),
54
+ ("her", "ask"),
55
+ ("ask", "asking"),
56
+ ("up", "upper"),
57
+ ],
58
+ }