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,143 @@
1
+ import pandas as pd
2
+ import numpy as np
3
+ import importlib_resources
4
+
5
+
6
+ def load_database(tag, lang):
7
+ assets_folder = importlib_resources.files(__name__) / "assets"
8
+
9
+ if lang == "en":
10
+ tag2df = {
11
+ "concreteness": pd.read_csv(
12
+ assets_folder / "concreteness.tsv",
13
+ sep="\t",
14
+ usecols=["Word", "Conc.M"],
15
+ index_col="Word",
16
+ ).squeeze(),
17
+ "familiarity": pd.read_csv(
18
+ assets_folder / "familiarity_imageability.tsv",
19
+ sep="\t",
20
+ usecols=["Words", "FAM_M"],
21
+ index_col="Words",
22
+ ).squeeze(),
23
+ "imageability": pd.read_csv(
24
+ assets_folder / "familiarity_imageability.tsv",
25
+ sep="\t",
26
+ usecols=["Words", "IMAG_M"],
27
+ index_col="Words",
28
+ ).squeeze(),
29
+ "frequency": pd.read_csv(
30
+ assets_folder / "frequency.tsv",
31
+ sep="\t",
32
+ usecols=["Word", "SUBTLWF"],
33
+ index_col="Word",
34
+ ).squeeze(),
35
+ "valence": pd.read_csv(
36
+ assets_folder / "valence.tsv",
37
+ sep="\t",
38
+ usecols=["Word", "V.Mean.Sum"],
39
+ index_col="Word",
40
+ ).squeeze(),
41
+ }
42
+
43
+ else:
44
+ return
45
+
46
+ return tag2df.get(tag)
47
+
48
+
49
+ def compute_database(tokens, lang, tag):
50
+ """
51
+ Compute the concreteness of words in a list from a concreteness database.
52
+
53
+ Args:
54
+ tokens (list): A list of words from which the average concreteness will be calculated.
55
+ lang (str): language of the text.
56
+
57
+ Returns:
58
+ numpy.array: concreteness of the words.
59
+ """
60
+ data = load_database(tag, lang)
61
+ if data is None:
62
+ return
63
+
64
+ return np.array(list(map(data.get, tokens))).astype(float)
65
+
66
+
67
+ def compute_concreteness(tokens, lang):
68
+ """
69
+ Compute the concreteness of words in a list from a concreteness database.
70
+
71
+ Args:
72
+ tokens (list): A list of words from which the average concreteness will be calculated.
73
+ lang (str): language of the text.
74
+
75
+ Returns:
76
+ numpy.array: concreteness of the words.
77
+ """
78
+ return compute_database(tokens, lang, "concreteness")
79
+
80
+
81
+ def compute_familiarity(tokens, lang):
82
+ """
83
+ Compute the familiarity of words in a list from a familiarity database.
84
+
85
+ Args:
86
+ tokens (list): A list of words from which the average familiarity will be calculated.
87
+ lang (str): language of the text.
88
+
89
+ Returns:
90
+ numpy.array: familiarity of the words.
91
+ """
92
+ return compute_database(tokens, lang, "familiarity")
93
+
94
+
95
+ def compute_imageability(tokens, lang):
96
+ """
97
+ Compute the imageability of words in a list from a imageability database.
98
+
99
+ Args:
100
+ tokens (list): A list of words from which the average imageability will be calculated.
101
+ lang (str): language of the text.
102
+
103
+ Returns:
104
+ numpy.array: imageability of the words.
105
+ """
106
+ return compute_database(tokens, lang, "imageability")
107
+
108
+
109
+ def compute_frequency(tokens, lang):
110
+ """
111
+ Compute the frequency of words in a list from a frequency database.
112
+
113
+ Args:
114
+ tokens (list): A list of words from which the average frequency will be calculated.
115
+ lang (str): language of the text.
116
+
117
+ Returns:
118
+ numpy.array: frequency of the words.
119
+ """
120
+ return compute_database(tokens, lang, "frequency")
121
+
122
+
123
+ def compute_valence(tokens, lang):
124
+ """
125
+ Compute the valence of words in a list from a valence database.
126
+
127
+ Args:
128
+ tokens (list): A list of words from which the average valence will be calculated.
129
+ lang (str): language of the text.
130
+
131
+ Returns:
132
+ numpy.array: valence of the words.
133
+ """
134
+ return compute_database(tokens, lang, "valence")
135
+
136
+
137
+ TAG2FUNC = {
138
+ "concreteness": compute_concreteness,
139
+ "familiarity": compute_familiarity,
140
+ "imageability": compute_imageability,
141
+ "frequency": compute_frequency,
142
+ "valence": compute_valence,
143
+ }
@@ -0,0 +1,172 @@
1
+ import warnings
2
+ import numpy as np
3
+ from numpy.lib.stride_tricks import sliding_window_view
4
+ from collections import Counter
5
+
6
+ from speechmetryflow.lexical.assets import pos_mapping
7
+ from speechmetryflow.lexical.database import TAG2FUNC
8
+
9
+
10
+ class POS:
11
+ def __init__(self, doc, lang):
12
+ self.doc = doc
13
+ self.lang = lang
14
+ self.mapping = pos_mapping
15
+ self.pos = [token.pos_ for token in self.doc]
16
+ self.text = np.array([token.text for token in self.doc])
17
+ self.counts = self._counts()
18
+ self.len_text = len(doc)
19
+ self.metrics = {}
20
+ self._compute_metrics()
21
+
22
+ def _counts(self):
23
+ counts = Counter(pos_mapping.keys())
24
+ counts.subtract(pos_mapping.keys())
25
+ counts.update(self.pos)
26
+ return counts
27
+
28
+ def _compute_metrics(self):
29
+ self.counter()
30
+ self.proportions()
31
+ self.count_open_class_words()
32
+ self.count_closed_class_words()
33
+ self.count_verb_inflection()
34
+ self.count_verb_gerondif()
35
+ self.compute_ratios()
36
+ for window_shape in [10, 25, 40]:
37
+ self.compute_mattr(window_shape)
38
+ self.compute_database("concreteness")
39
+ self.compute_database("familiarity")
40
+ self.compute_database("imageability")
41
+ self.compute_database("frequency")
42
+ self.compute_database("valence")
43
+
44
+ def proportions(self):
45
+ for tag, count in self.counts.items():
46
+ self.metrics[f"pos_prop_{tag}"] = (
47
+ count / self.len_text if self.len_text > 0 else None
48
+ )
49
+
50
+ def counter(self):
51
+ for tag, count in self.counts.items():
52
+ self.metrics[f"pos_count_{tag}"] = count
53
+
54
+ def count_open_class_words(self):
55
+ open_classes = ["NOUN", "VERB", "ADJ", "ADV"]
56
+ num = sum(self.counts[pos] for pos in open_classes)
57
+ self.metrics["pos_count_open_words"] = num
58
+ self.metrics["pos_prop_open_words"] = (
59
+ num / self.len_text if self.len_text > 0 else None
60
+ )
61
+
62
+ def count_closed_class_words(self):
63
+ closed_classes = ["CONJ", "PRON", "DET", "ADP"]
64
+ num = sum(self.counts[pos] for pos in closed_classes)
65
+ self.metrics["pos_count_closed_words"] = num
66
+ self.metrics["pos_prop_closed_words"] = (
67
+ num / self.len_text if self.len_text > 0 else None
68
+ )
69
+
70
+ def count_verb_inflection(self):
71
+ """Verb inflection is the modification of a verb's form to express grammatical features such as tense."""
72
+ num = sum(
73
+ 1 for token in self.doc if token.pos_ == "VERB" and token.tag_ != "VB"
74
+ )
75
+ self.metrics["pos_count_verb_inflection"] = num
76
+ self.metrics["pos_prop_verb_inflection"] = (
77
+ num / self.len_text if self.len_text > 0 else None
78
+ )
79
+
80
+ def count_verb_gerondif(self):
81
+ """
82
+ The gérondif is a French verb form expressing an action occurring in relation to another action.
83
+ Example: Il écoute de la musique en travaillant.
84
+ """
85
+ num = sum(1 for token in self.doc if token.tag_ != "VBG")
86
+ self.metrics["pos_count_verb_gerondif"] = num
87
+ self.metrics["pos_prop_verb_gerondif"] = (
88
+ num / self.len_text if self.len_text > 0 else None
89
+ )
90
+
91
+ def compute_ratios(self):
92
+ """
93
+ Computing the following ratios:
94
+ - PRON / (NOUN + PRON)
95
+ - NOUN / (NOUN + PRON)
96
+ - NOUN / (NOUN + VERB)
97
+ - VERB / (NOUN + VERB)
98
+ - VERB_INFLECTION / VERB
99
+ - VERB_GERONDIF / VERB
100
+ """
101
+ n_verb = self.counts["VERB"]
102
+ n_noun = self.counts["NOUN"]
103
+ n_pron = self.counts["PRON"]
104
+ n_inflection = self.metrics["pos_count_verb_inflection"]
105
+ n_gerondif = self.metrics["pos_count_verb_gerondif"]
106
+ # Calcul des ratios
107
+ self.metrics["PRON/(NOUN+PRON)"] = (
108
+ n_pron / (n_noun + n_pron) if (n_noun + n_pron) > 0 else None
109
+ )
110
+ self.metrics["NOUN/(NOUN+PRON)"] = (
111
+ n_noun / (n_noun + n_pron) if (n_noun + n_pron) > 0 else None
112
+ )
113
+ self.metrics["NOUN/(NOUN+VERB)"] = (
114
+ n_noun / (n_noun + n_verb) if (n_noun + n_verb) > 0 else None
115
+ )
116
+ self.metrics["VERB/(NOUN+VERB)"] = (
117
+ n_verb / (n_noun + n_verb) if (n_noun + n_verb) > 0 else None
118
+ )
119
+ self.metrics["VERB_INFLECTION/VERB"] = (
120
+ n_inflection / n_verb if n_verb > 0 else None
121
+ )
122
+ self.metrics["VERB_GERONDIF/VERB"] = n_gerondif / n_verb if n_verb > 0 else None
123
+
124
+ def compute_mattr(self, window_shape):
125
+ """
126
+ Compute the MATTR (Moving-Average Type-Token Ratio) using a window of specified size.
127
+
128
+ Args:
129
+ window_shape (int): The size of the text window to use.
130
+
131
+ Returns:
132
+ float: MATTR value.
133
+ """
134
+ try:
135
+ windows = sliding_window_view(self.pos, window_shape=window_shape)
136
+ except ValueError:
137
+ # if window_shape is larger than input array shape
138
+ return
139
+
140
+ # Compute the TTR (Type-Token Ratio) for each window
141
+ ttr_values = [len(set(window)) / window_shape for window in windows]
142
+
143
+ self.metrics[f"pos_mattr_{window_shape}"] = np.mean(ttr_values)
144
+
145
+ def compute_database(self, tag):
146
+ """"""
147
+ scores = TAG2FUNC[tag](self.text, self.lang)
148
+
149
+ if scores is None:
150
+ for pos_type in ["NOUN", "VERB", "ADJ"]:
151
+ self.metrics[f"{tag}_mean_{pos_type}"] = None
152
+ self.metrics[f"{tag}_mean_all_tokens"] = None
153
+ return
154
+
155
+ warnings.filterwarnings("error")
156
+ for pos_type in ["NOUN", "VERB", "ADJ"]:
157
+ pos_positions = np.nonzero(np.array(self.pos) == pos_type)[0]
158
+ sub_scores = scores[pos_positions]
159
+ try:
160
+ score = np.nanmean(sub_scores)
161
+ except RuntimeWarning:
162
+ score = 0.0
163
+ self.metrics[f"{tag}_mean_{pos_type}"] = score
164
+
165
+ # For all tokens
166
+ try:
167
+ score = np.nanmean(scores)
168
+ except RuntimeWarning:
169
+ score = 0.0
170
+ self.metrics[f"{tag}_mean_all_tokens"] = score
171
+
172
+ warnings.resetwarnings()
@@ -0,0 +1,119 @@
1
+ import math
2
+
3
+ from speechmetryflow.lexical.assets import deictic_pronouns, indefinite_terms
4
+ from speechmetryflow.speech_production import compute_counts
5
+
6
+
7
+ def count_deictic_pronouns(tokens, lang):
8
+ """
9
+ Counts deictic pronouns in a text in English or French.
10
+
11
+ Args:
12
+ - tokens list[(str)]: The text to be analysed.
13
+ - lang (str): The language of the text ("fr", "en").
14
+
15
+ Returns:
16
+ - dict: A dictionary with the counts of spatial, personal, temporal pronouns and the total.
17
+ """
18
+ deictic_pronouns_data = deictic_pronouns.get(lang)
19
+
20
+ if deictic_pronouns_data is None:
21
+ return {
22
+ "n_deictic_pronouns_spatial": None,
23
+ "n_deictic_pronouns_personal": None,
24
+ "n_deictic_pronouns_temporal": None,
25
+ "n_deictic_pronouns_total": None,
26
+ "prop_deictic_pronouns_spatial": None,
27
+ "prop_deictic_pronouns_personal": None,
28
+ "prop_deictic_pronouns_temporal": None,
29
+ "prop_deictic_pronouns_total": None,
30
+ }
31
+
32
+ len_text = len(tokens)
33
+ n_spatial = sum(token in deictic_pronouns_data["spatial"] for token in tokens)
34
+ n_personal = sum(token in deictic_pronouns_data["personal"] for token in tokens)
35
+ n_temporal = sum(token in deictic_pronouns_data["temporal"] for token in tokens)
36
+ n_total = n_spatial + n_personal + n_temporal
37
+
38
+ return {
39
+ "n_deictic_pronouns_spatial": n_spatial,
40
+ "n_deictic_pronouns_personal": n_personal,
41
+ "n_deictic_pronouns_temporal": n_temporal,
42
+ "n_deictic_pronouns_total": n_total,
43
+ "prop_deictic_pronouns_spatial": n_spatial / len_text if len_text > 0 else None,
44
+ "prop_deictic_pronouns_personal": (
45
+ n_personal / len_text if len_text > 0 else None
46
+ ),
47
+ "prop_deictic_pronouns_temporal": (
48
+ n_temporal / len_text if len_text > 0 else None
49
+ ),
50
+ "prop_deictic_pronouns_total": n_total / len_text if len_text > 0 else None,
51
+ }
52
+
53
+
54
+ def count_indefinite_terms(tokens, lang):
55
+ """
56
+ Counts the number of indefinite terms in a text based on the language.
57
+
58
+ Args:
59
+ - tokens list[(str)]: The text to be analysed.
60
+ - lang (str): The language of the text ("fr", "en").
61
+
62
+ Returns:
63
+ int: The number of indefinite terms found in the text.
64
+ """
65
+ indefinite_terms_data = indefinite_terms.get(lang)
66
+
67
+ if indefinite_terms_data is None:
68
+ return
69
+
70
+ len_text = len(tokens)
71
+ num = sum(token in indefinite_terms_data for token in tokens)
72
+ return {
73
+ "n_indefinite_terms": num,
74
+ "prop_indefinite_terms": num / len_text if len_text > 0 else None,
75
+ }
76
+
77
+
78
+ def compute_honore_r_stat(stems):
79
+ """
80
+ Compute Honore's R statistic.
81
+ 100*log(N)/(1-(n_unique/n_different))
82
+
83
+ Args:
84
+ stems list(str): list of stems to compute.
85
+
86
+ Returns:
87
+ float: value of Honore's R statistic.
88
+ """
89
+ if stems is None:
90
+ return
91
+
92
+ N, n_different, n_unique, _ = compute_counts(stems)
93
+ return (100 * math.log(N)) / (1 - (n_unique / n_different)) if N else None
94
+
95
+
96
+ def compute_brunet_index(stems):
97
+ """
98
+ Compute the Brunet index
99
+ A measure of lexical diversity linking the length of the sample to the number of different words used in it.
100
+ Lower values of W correspond to richer texts.
101
+ Stemming is done on words and only the stems are considered.
102
+
103
+ Formula: W = N ^ (V ^ (-0.165))
104
+ W (float): Brunet's index.
105
+ N (int): total number of stems.
106
+ V (int): number of different stems.
107
+
108
+ Args:
109
+ stems list(str): list of stems to compute.
110
+
111
+ Returns:
112
+ float: value of Brunet index.
113
+ """
114
+ if stems is None:
115
+ return
116
+
117
+ N, n_different, _, _ = compute_counts(stems)
118
+
119
+ return math.pow(N, math.pow(n_different, -0.165)) if N else None
@@ -0,0 +1,60 @@
1
+ import numpy as np
2
+
3
+ from transformers import AutoTokenizer, AutoModelWithLMHead, pipeline
4
+
5
+ from speechmetryflow.semantic.idea_density import compute_idea_density
6
+ from speechmetryflow.pragmatic.database import compute_database
7
+
8
+
9
+ def coherence_locale(doc):
10
+ similarities = []
11
+ for sent in doc.sents:
12
+ tokens = [token for token in sent]
13
+ (similarity,) = compute_idea_density(tokens, [len(tokens)]).values()
14
+ similarities.append(similarity)
15
+ return np.nanmean(similarities)
16
+
17
+
18
+ def compute_emotion(text):
19
+ tokenizer = AutoTokenizer.from_pretrained("mrm8488/t5-base-finetuned-emotion")
20
+ model = AutoModelWithLMHead.from_pretrained("mrm8488/t5-base-finetuned-emotion")
21
+ input_ids = tokenizer.encode(text + "</s>", return_tensors="pt")
22
+ output = model.generate(input_ids=input_ids, max_length=2)
23
+ dec = [tokenizer.decode(ids) for ids in output]
24
+ label = dec[0]
25
+ # Supprimer le token <pad> de la sortie
26
+ return label.replace("<pad>", "").strip()
27
+
28
+
29
+ def compute_sentiment(text):
30
+ """
31
+ Analyses the sentiment of a text using the mrm8488/t5-base-finetuned-emotion model.
32
+ :param text: Text to be analysed.
33
+ :return: Sentiment label.
34
+ """
35
+ model_path = "cardiffnlp/twitter-xlm-roberta-base-sentiment"
36
+ # Creation of the sentiment analysis pipeline
37
+ sentiment_task = pipeline(
38
+ "sentiment-analysis",
39
+ model=model_path,
40
+ tokenizer=model_path,
41
+ max_length=512,
42
+ truncation=True,
43
+ )
44
+ # Sentiment analysis
45
+ result = sentiment_task(text)
46
+ # Sentiment label retrieval
47
+ label = result[0]["label"]
48
+ return label
49
+
50
+
51
+ def metrics(doc, lang, n_tokens):
52
+ metrics = compute_database(doc, lang, n_tokens, "uncertainty_words")
53
+ metrics.update(compute_database(doc, lang, n_tokens, "formulaic_expressions"))
54
+ metrics.update(compute_database(doc, lang, n_tokens, "modal_expressions"))
55
+ metrics.update(compute_database(doc, lang, n_tokens, "filler_expressions"))
56
+ metrics.update(compute_database(doc, lang, n_tokens, "difficulty_words"))
57
+ metrics["coherence_locale"] = coherence_locale(doc)
58
+ metrics["emotion"] = compute_emotion(doc.text)
59
+ metrics["sentiment"] = compute_sentiment(doc.text)
60
+ return metrics
@@ -0,0 +1,62 @@
1
+ """
2
+ Pragmatic characteristics
3
+ """
4
+
5
+ # Uncertainty words
6
+ uncertainty_words = {
7
+ "en": {"think", "look", "like", "kind", "seem", "maybe", "can", "something"},
8
+ "fr": {
9
+ "penser",
10
+ "sembler",
11
+ "comme",
12
+ "genre",
13
+ "peut-être",
14
+ "peut",
15
+ "quelque",
16
+ "chose",
17
+ },
18
+ }
19
+
20
+ # Formulaic expressions
21
+ formulaic_expressions = {
22
+ "en": {"well", "so", "i guess", "you know", "as it is", "as it were"},
23
+ "fr": {"bien", "alors", "je suppose", "tu sais", "comme il est", "comme il serait"},
24
+ }
25
+
26
+ # Modal expressions
27
+ modal_expressions = {
28
+ "en": {
29
+ "i think",
30
+ "in my opinion",
31
+ "of course",
32
+ "naturally",
33
+ "unsure",
34
+ "likely",
35
+ "could be that",
36
+ "unfortunately",
37
+ "surely",
38
+ },
39
+ "fr": {
40
+ "je pense",
41
+ "à mon avis",
42
+ "bien sûr",
43
+ "naturellement",
44
+ "incertain",
45
+ "probablement",
46
+ "ça pourrait être que",
47
+ "malheureusement",
48
+ "sûrement",
49
+ },
50
+ }
51
+
52
+ # Filler expressions
53
+ filler_expressions = {
54
+ "en": {"you know", "i mean"},
55
+ "fr": {"tu sais", "je veux dire"},
56
+ }
57
+
58
+ # Words indicating lexical access difficulties
59
+ difficulty_words = {
60
+ "en": {"know", "remember", "unable"},
61
+ "fr": {"savoir", "se souvenir", "incapable"},
62
+ }
@@ -0,0 +1,113 @@
1
+ from speechmetryflow.pragmatic import assets
2
+
3
+
4
+ def compute_database(doc, lang, n_tokens, tag):
5
+ """
6
+ Compute the concreteness of words in a list from a concreteness database.
7
+
8
+ Args:
9
+ tokens (list): A list of words from which the average concreteness will be calculated.
10
+ lang (str): language of the text.
11
+
12
+ Returns:
13
+ numpy.array: concreteness of the words.
14
+ """
15
+ tag2database = {
16
+ "uncertainty_words": assets.uncertainty_words,
17
+ "formulaic_expressions": assets.formulaic_expressions,
18
+ "modal_expressions": assets.modal_expressions,
19
+ "filler_expressions": assets.filler_expressions,
20
+ "difficulty_words": assets.difficulty_words,
21
+ }
22
+ data = tag2database[tag].get(lang)
23
+ if data is None:
24
+ return {
25
+ f"n_{tag}": None,
26
+ f"prop_{tag}": None,
27
+ }
28
+
29
+ text = doc.text.lower()
30
+ count = sum(text.count(expression) for expression in data)
31
+ return {
32
+ f"n_{tag}": count,
33
+ f"prop_{tag}": count / n_tokens if n_tokens else None,
34
+ }
35
+
36
+
37
+ def compute_concreteness(tokens, lang):
38
+ """
39
+ Compute the concreteness of words in a list from a concreteness database.
40
+
41
+ Args:
42
+ tokens (list): A list of words from which the average concreteness will be calculated.
43
+ lang (str): language of the text.
44
+
45
+ Returns:
46
+ numpy.array: concreteness of the words.
47
+ """
48
+ return compute_database(tokens, lang, "concreteness")
49
+
50
+
51
+ def compute_familiarity(tokens, lang):
52
+ """
53
+ Compute the familiarity of words in a list from a familiarity database.
54
+
55
+ Args:
56
+ tokens (list): A list of words from which the average familiarity will be calculated.
57
+ lang (str): language of the text.
58
+
59
+ Returns:
60
+ numpy.array: familiarity of the words.
61
+ """
62
+ return compute_database(tokens, lang, "familiarity")
63
+
64
+
65
+ def compute_imageability(tokens, lang):
66
+ """
67
+ Compute the imageability of words in a list from a imageability database.
68
+
69
+ Args:
70
+ tokens (list): A list of words from which the average imageability will be calculated.
71
+ lang (str): language of the text.
72
+
73
+ Returns:
74
+ numpy.array: imageability of the words.
75
+ """
76
+ return compute_database(tokens, lang, "imageability")
77
+
78
+
79
+ def compute_frequency(tokens, lang):
80
+ """
81
+ Compute the frequency of words in a list from a frequency database.
82
+
83
+ Args:
84
+ tokens (list): A list of words from which the average frequency will be calculated.
85
+ lang (str): language of the text.
86
+
87
+ Returns:
88
+ numpy.array: frequency of the words.
89
+ """
90
+ return compute_database(tokens, lang, "frequency")
91
+
92
+
93
+ def compute_valence(tokens, lang):
94
+ """
95
+ Compute the valence of words in a list from a valence database.
96
+
97
+ Args:
98
+ tokens (list): A list of words from which the average valence will be calculated.
99
+ lang (str): language of the text.
100
+
101
+ Returns:
102
+ numpy.array: valence of the words.
103
+ """
104
+ return compute_database(tokens, lang, "valence")
105
+
106
+
107
+ TAG2FUNC = {
108
+ "concreteness": compute_concreteness,
109
+ "familiarity": compute_familiarity,
110
+ "imageability": compute_imageability,
111
+ "frequency": compute_frequency,
112
+ "valence": compute_valence,
113
+ }
@@ -0,0 +1,23 @@
1
+ from speechmetryflow.semantic.icu import compute_icu
2
+ from speechmetryflow.semantic.idea_density import compute_idea_density
3
+
4
+
5
+ def metrics(text, tokens, lang, task, n_tokens):
6
+ metrics = compute_idea_density(tokens, [3, 10, 25, 40])
7
+
8
+ icu_data = compute_icu(text, lang, task)
9
+
10
+ # Total number of True ICU anf ICU efficacity
11
+ if icu_data is None:
12
+ n_icu_true = None
13
+ icu_efficacity = None
14
+
15
+ else:
16
+ metrics.update(icu_data)
17
+ n_icu_true = sum(icu_data.values())
18
+ icu_efficacity = n_tokens / n_icu_true if n_icu_true else None
19
+
20
+ metrics["n_icu_true"] = n_icu_true
21
+ metrics["icu_efficacity"] = icu_efficacity
22
+
23
+ return metrics