Anchor-annotator 0.3.0__py3-none-any.whl → 0.3.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.
- {Anchor_annotator-0.3.0.dist-info → Anchor_annotator-0.3.2.dist-info}/METADATA +1 -1
- {Anchor_annotator-0.3.0.dist-info → Anchor_annotator-0.3.2.dist-info}/RECORD +12 -12
- anchor/_version.py +2 -2
- anchor/models.py +11 -33
- anchor/plot.py +10 -5
- anchor/ui_main_window.py +1 -1
- anchor/undo.py +7 -7
- anchor/widgets.py +7 -8
- anchor/workers.py +0 -3
- {Anchor_annotator-0.3.0.dist-info → Anchor_annotator-0.3.2.dist-info}/LICENSE +0 -0
- {Anchor_annotator-0.3.0.dist-info → Anchor_annotator-0.3.2.dist-info}/WHEEL +0 -0
- {Anchor_annotator-0.3.0.dist-info → Anchor_annotator-0.3.2.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: Anchor_annotator
|
3
|
-
Version: 0.3.
|
3
|
+
Version: 0.3.2
|
4
4
|
Summary: Anchor annotator is a program for inspecting corpora for the Montreal Forced Aligner and correcting transcriptions and pronunciations.
|
5
5
|
Home-page: https://github.com/MontrealCorpusTools/Anchor-annotator
|
6
6
|
Author: Montreal Corpus Tools
|
@@ -1,22 +1,22 @@
|
|
1
1
|
anchor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
2
|
anchor/__main__.py,sha256=5ufG8lcx2x1am-04xI991AG7saJd24dxPw5JzjmB878,45
|
3
|
-
anchor/_version.py,sha256=
|
3
|
+
anchor/_version.py,sha256=9jP8Fo8egXoMs_T3DFqSuJYg4n9o9mnwYubl_hnut4k,411
|
4
4
|
anchor/command_line.py,sha256=EucG805HyWk_zkMO9RXv9Yj0I0JVdDLZb1_DX2_ISjM,503
|
5
5
|
anchor/db.py,sha256=ef4lO6HtCKoxC9CorIc0ZbPxKpjHa576a0ZIBOWNU9E,4956
|
6
6
|
anchor/main.py,sha256=eazWSZC94_nyBx_6rJ85hxC9wkCJYVP5FN_t9vnRm44,120658
|
7
|
-
anchor/models.py,sha256=
|
8
|
-
anchor/plot.py,sha256=
|
7
|
+
anchor/models.py,sha256=sCZf5wF6g1KorMgb0AifmqhaxZp5fiYmlmaJoow-tFI,95230
|
8
|
+
anchor/plot.py,sha256=eNVG9sDdRA9_KKrHKSb2TF66bIluJsJzVnTGN3q-Brk,104878
|
9
9
|
anchor/resources_rc.py,sha256=94wgxDTpP4Oy55Br7CZ_YnmvaqzHr4n-AydBPhZc-es,8427242
|
10
10
|
anchor/settings.py,sha256=QdfBtJowHpkBLzJ_3bZRKxF1rJDBW9Z5kp83sJVz0pA,46965
|
11
11
|
anchor/ui_corpus_manager.py,sha256=e3ybOd4UdYarrLBATxI8vIFnioa4R_BHrbsEz5mJ5eA,8564
|
12
12
|
anchor/ui_error_dialog.py,sha256=c_QS0s1VaJEV9AhcrQZQyWHHpUPudWjJY1NI7Ytipio,3832
|
13
|
-
anchor/ui_main_window.py,sha256=
|
13
|
+
anchor/ui_main_window.py,sha256=MYb4PtV1sHYgnc3QwPphKjU3LepzBJpxllhN4nyDook,63525
|
14
14
|
anchor/ui_preferences.py,sha256=MOC2dY4qkViW9cUbC0DVSO7FLg-dGSbmR630WFQ6V9c,41843
|
15
|
-
anchor/undo.py,sha256=
|
16
|
-
anchor/widgets.py,sha256=
|
17
|
-
anchor/workers.py,sha256=
|
18
|
-
Anchor_annotator-0.3.
|
19
|
-
Anchor_annotator-0.3.
|
20
|
-
Anchor_annotator-0.3.
|
21
|
-
Anchor_annotator-0.3.
|
22
|
-
Anchor_annotator-0.3.
|
15
|
+
anchor/undo.py,sha256=HXhrzV-T2JKwPd28KCaR9S6GWmi2Wr2Xk7IBEonRRCs,32564
|
16
|
+
anchor/widgets.py,sha256=arL006v_cOGWudEF4Adbh_wRjiyFRGHP9BXOtfCr0h0,158301
|
17
|
+
anchor/workers.py,sha256=iWLBGCg6jJr_OmVFJCRGMgF5Rw5G9IhpdNiqDv8ZBxU,171083
|
18
|
+
Anchor_annotator-0.3.2.dist-info/LICENSE,sha256=C0oIsblENEgWQ7XMNdYoXyXsIA5wa3YF0I9lK3H7A1s,1076
|
19
|
+
Anchor_annotator-0.3.2.dist-info/METADATA,sha256=YcbnBTVx6O59V8W-6t9wu5GVrQBvGcXWDK3fCWHhkvE,1500
|
20
|
+
Anchor_annotator-0.3.2.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
21
|
+
Anchor_annotator-0.3.2.dist-info/top_level.txt,sha256=wX6ZKxImGRZKFQjs3f6XYw_TfbAp6Xs3SmbLfLbFAJ0,7
|
22
|
+
Anchor_annotator-0.3.2.dist-info/RECORD,,
|
anchor/_version.py
CHANGED
anchor/models.py
CHANGED
@@ -68,18 +68,20 @@ class TextFilterQuery:
|
|
68
68
|
if not self.regex:
|
69
69
|
text = re.escape(text)
|
70
70
|
word_break_set = r"\b"
|
71
|
-
if posix:
|
72
|
-
word_break_set = r"\y"
|
73
|
-
text = text.replace(r"\b", word_break_set)
|
74
71
|
if self.word:
|
75
72
|
if not text.startswith(word_break_set):
|
76
73
|
text = word_break_set + text
|
77
74
|
if not text.endswith(word_break_set):
|
78
75
|
text += word_break_set
|
76
|
+
if posix:
|
77
|
+
text = text.replace(r"\b", word_break_set)
|
78
|
+
if text.startswith(r"\b"):
|
79
|
+
text = r"((?<=\s)|(?<=^))" + text[2:]
|
80
|
+
if text.endswith(r"\b"):
|
81
|
+
text = text[:-2] + r"((?=\s)|(?=$))"
|
79
82
|
if self.regex or self.word:
|
80
83
|
if not self.case_sensitive:
|
81
84
|
text = "(?i)" + text
|
82
|
-
|
83
85
|
return text
|
84
86
|
|
85
87
|
|
@@ -164,6 +166,7 @@ class FileUtterancesModel(QtCore.QAbstractListModel):
|
|
164
166
|
|
165
167
|
waveformReady = QtCore.Signal()
|
166
168
|
utterancesReady = QtCore.Signal()
|
169
|
+
speakersChanged = QtCore.Signal()
|
167
170
|
|
168
171
|
def __init__(self, *args, **kwargs):
|
169
172
|
super().__init__(*args, **kwargs)
|
@@ -323,6 +326,7 @@ class FileUtterancesModel(QtCore.QAbstractListModel):
|
|
323
326
|
if utterance.speaker_id not in self.speakers:
|
324
327
|
self.speakers.append(utterance.speaker_id)
|
325
328
|
self.speaker_channel_mapping[utterance.speaker_id] = utterance.channel
|
329
|
+
self.speakersChanged.emit()
|
326
330
|
self._speaker_indices[index] = utterance.speaker_id
|
327
331
|
|
328
332
|
def merge_table_utterances(
|
@@ -846,6 +850,8 @@ class FileSelectionModel(QtCore.QItemSelectionModel):
|
|
846
850
|
except sqlalchemy.orm.exc.DetachedInstanceError:
|
847
851
|
new_file = True
|
848
852
|
self.requested_utterance_id = utterance_id
|
853
|
+
self.selected_min_time = None
|
854
|
+
self.selected_max_time = None
|
849
855
|
if new_file:
|
850
856
|
self.fileAboutToChange.emit()
|
851
857
|
self.model().set_file(file_id)
|
@@ -941,8 +947,7 @@ class CorpusSelectionModel(QtCore.QItemSelectionModel):
|
|
941
947
|
self.currentRowChanged.connect(self.switch_utterance)
|
942
948
|
# self.selectionChanged.connect(self.update_selection_audio)
|
943
949
|
# self.selectionChanged.connect(self.update_selection_audio)
|
944
|
-
|
945
|
-
self.model().layoutChanged.connect(self.check_selection)
|
950
|
+
self.model().newResults.connect(self.check_selection)
|
946
951
|
self.model().unlockCorpus.connect(self.fileChanged.emit)
|
947
952
|
|
948
953
|
def set_current_utterance(self, utterance_id):
|
@@ -2273,32 +2278,6 @@ class CorpusModel(TableModel):
|
|
2273
2278
|
self._speaker_indices[row],
|
2274
2279
|
)
|
2275
2280
|
|
2276
|
-
def fileAt(self, index) -> int:
|
2277
|
-
if not isinstance(index, int):
|
2278
|
-
if not index.isValid():
|
2279
|
-
return None
|
2280
|
-
index = index.row()
|
2281
|
-
return self._file_indices[index]
|
2282
|
-
|
2283
|
-
def indexForUtterance(self, utterance_id: int, column: int = 1):
|
2284
|
-
return self.createIndex(self.reversed_indices[utterance_id], column)
|
2285
|
-
|
2286
|
-
def rollback_changes(self):
|
2287
|
-
self.unsaved_files = set()
|
2288
|
-
self.session.rollback()
|
2289
|
-
# self.query_session.expire_all()
|
2290
|
-
self.databaseSynced.emit(False)
|
2291
|
-
self.update_data()
|
2292
|
-
|
2293
|
-
def commit_changes(self):
|
2294
|
-
self.session.bulk_update_mappings(
|
2295
|
-
File, [{"id": x, "modified": True} for x in self.unsaved_files]
|
2296
|
-
)
|
2297
|
-
|
2298
|
-
self.unsaved_files = set()
|
2299
|
-
self.session.commit()
|
2300
|
-
self.databaseSynced.emit(True)
|
2301
|
-
|
2302
2281
|
def finish_export_files(self):
|
2303
2282
|
self.filesSaved.emit()
|
2304
2283
|
|
@@ -2584,7 +2563,6 @@ class CorpusTableModel(QtCore.QAbstractTableModel):
|
|
2584
2563
|
self.session.commit()
|
2585
2564
|
corpus_name = os.path.basename(corpus_directory)
|
2586
2565
|
c = anchor.db.AnchorCorpus(name=corpus_name, path=corpus_directory, current=True, **kwargs)
|
2587
|
-
print(c.current)
|
2588
2566
|
self.session.add(c)
|
2589
2567
|
self.session.commit()
|
2590
2568
|
self.corpora.append(c)
|
anchor/plot.py
CHANGED
@@ -11,7 +11,6 @@ import numpy as np
|
|
11
11
|
import pyqtgraph as pg
|
12
12
|
import sqlalchemy
|
13
13
|
from Bio import pairwise2
|
14
|
-
from line_profiler_pycharm import profile
|
15
14
|
from montreal_forced_aligner.data import CtmInterval
|
16
15
|
from montreal_forced_aligner.db import Speaker, Utterance
|
17
16
|
from PySide6 import QtCore, QtGui, QtWidgets
|
@@ -1457,7 +1456,6 @@ class MfaRegion(pg.LinearRegionItem):
|
|
1457
1456
|
|
1458
1457
|
settings = AnchorSettings()
|
1459
1458
|
|
1460
|
-
@profile
|
1461
1459
|
def __init__(
|
1462
1460
|
self,
|
1463
1461
|
item: CtmInterval,
|
@@ -1566,7 +1564,6 @@ class MfaRegion(pg.LinearRegionItem):
|
|
1566
1564
|
|
1567
1565
|
|
1568
1566
|
class AlignmentRegion(MfaRegion):
|
1569
|
-
@profile
|
1570
1567
|
def __init__(
|
1571
1568
|
self,
|
1572
1569
|
phone_interval: CtmInterval,
|
@@ -1681,7 +1678,6 @@ class WordRegion(AlignmentRegion):
|
|
1681
1678
|
|
1682
1679
|
|
1683
1680
|
class UtteranceRegion(MfaRegion):
|
1684
|
-
@profile
|
1685
1681
|
def __init__(
|
1686
1682
|
self,
|
1687
1683
|
utterance: workers.UtteranceData,
|
@@ -2514,6 +2510,16 @@ class SpeakerTier(pg.GraphicsObject):
|
|
2514
2510
|
self.corpus_model.refreshUtteranceText.connect(self.refreshTexts)
|
2515
2511
|
self.selection_model.selectionChanged.connect(self.update_select)
|
2516
2512
|
self.selection_model.model().utterancesReady.connect(self.refresh)
|
2513
|
+
self.file_model.speakersChanged.connect(self.update_available_speakers)
|
2514
|
+
self.available_speakers = {}
|
2515
|
+
|
2516
|
+
def update_available_speakers(self):
|
2517
|
+
self.available_speakers = {}
|
2518
|
+
for speaker_id in self.file_model.speakers:
|
2519
|
+
speaker_name = self.corpus_model.get_speaker_name(speaker_id)
|
2520
|
+
self.available_speakers[speaker_name] = speaker_id
|
2521
|
+
for reg in self.visible_utterances.values():
|
2522
|
+
reg.available_speakers = self.available_speakers
|
2517
2523
|
|
2518
2524
|
def wheelEvent(self, ev):
|
2519
2525
|
self.receivedWheelEvent.emit(ev)
|
@@ -2573,7 +2579,6 @@ class SpeakerTier(pg.GraphicsObject):
|
|
2573
2579
|
reg.scene().removeItem(reg)
|
2574
2580
|
self.visible_utterances = {}
|
2575
2581
|
|
2576
|
-
@profile
|
2577
2582
|
def refresh(self, *args):
|
2578
2583
|
self.hide()
|
2579
2584
|
if self.selection_model.plot_min is None:
|
anchor/ui_main_window.py
CHANGED
@@ -8,7 +8,6 @@
|
|
8
8
|
## WARNING! All changes made in this file will be lost when recompiling UI file!
|
9
9
|
################################################################################
|
10
10
|
|
11
|
-
import resources_rc
|
12
11
|
from PySide6.QtCore import (
|
13
12
|
QCoreApplication,
|
14
13
|
QDate,
|
@@ -55,6 +54,7 @@ from PySide6.QtWidgets import (
|
|
55
54
|
QWidget,
|
56
55
|
)
|
57
56
|
|
57
|
+
import anchor.resources_rc
|
58
58
|
from anchor.widgets import (
|
59
59
|
AcousticModelWidget,
|
60
60
|
AlignmentWidget,
|
anchor/undo.py
CHANGED
@@ -6,7 +6,7 @@ import typing
|
|
6
6
|
import pynini.lib
|
7
7
|
import sqlalchemy
|
8
8
|
from montreal_forced_aligner.data import WordType
|
9
|
-
from montreal_forced_aligner.db import File, Pronunciation, Speaker, Utterance, Word
|
9
|
+
from montreal_forced_aligner.db import File, Pronunciation, Speaker, Utterance, Word, bulk_update
|
10
10
|
from PySide6 import QtCore, QtGui
|
11
11
|
from sqlalchemy.orm import make_transient
|
12
12
|
|
@@ -643,18 +643,18 @@ class UpdateUtteranceSpeakerCommand(FileCommand):
|
|
643
643
|
)
|
644
644
|
)
|
645
645
|
session.flush()
|
646
|
+
mappings = []
|
646
647
|
for u in self.utterances:
|
647
648
|
u.speaker_id = self.new_speaker_id
|
648
|
-
|
649
|
-
|
650
|
-
).update({Speaker.modified: True})
|
649
|
+
mappings.append({"id": u.id, "speaker_id": self.new_speaker_id})
|
650
|
+
bulk_update(self.corpus_model.session, Utterance, mappings)
|
651
651
|
|
652
652
|
def _undo(self, session) -> None:
|
653
|
+
mappings = []
|
653
654
|
for i, u in enumerate(self.utterances):
|
654
655
|
u.speaker_id = self.old_speaker_ids[i]
|
655
|
-
|
656
|
-
|
657
|
-
).update({Speaker.modified: True})
|
656
|
+
mappings.append({"id": u.id, "speaker_id": self.old_speaker_ids[i]})
|
657
|
+
bulk_update(self.corpus_model.session, Utterance, mappings)
|
658
658
|
|
659
659
|
def update_data(self):
|
660
660
|
super().update_data()
|
anchor/widgets.py
CHANGED
@@ -125,6 +125,7 @@ class MediaPlayer(QtMultimedia.QMediaPlayer): # pragma: no cover
|
|
125
125
|
or self.currentTime() >= self.maxTime()
|
126
126
|
):
|
127
127
|
self.setCurrentTime(self.startTime())
|
128
|
+
self.timer.start()
|
128
129
|
super(MediaPlayer, self).play()
|
129
130
|
if fade_in:
|
130
131
|
self.fade_in_anim.start()
|
@@ -155,8 +156,6 @@ class MediaPlayer(QtMultimedia.QMediaPlayer): # pragma: no cover
|
|
155
156
|
self.timer.stop()
|
156
157
|
self.setCurrentTime(self.startTime())
|
157
158
|
self.timeChanged.emit(self.currentTime())
|
158
|
-
elif state == QtMultimedia.QMediaPlayer.PlaybackState.PlayingState:
|
159
|
-
self.timer.start()
|
160
159
|
elif state == QtMultimedia.QMediaPlayer.PlaybackState.PausedState:
|
161
160
|
self.timer.stop()
|
162
161
|
|
@@ -183,10 +182,10 @@ class MediaPlayer(QtMultimedia.QMediaPlayer): # pragma: no cover
|
|
183
182
|
def set_volume(self, volume: int):
|
184
183
|
if self.audioOutput() is None:
|
185
184
|
return
|
186
|
-
linearVolume = QtMultimedia.
|
185
|
+
linearVolume = QtMultimedia.QtAudio.convertVolume(
|
187
186
|
volume / 100.0,
|
188
|
-
QtMultimedia.
|
189
|
-
QtMultimedia.
|
187
|
+
QtMultimedia.QtAudio.VolumeScale.LogarithmicVolumeScale,
|
188
|
+
QtMultimedia.QtAudio.VolumeScale.LinearVolumeScale,
|
190
189
|
)
|
191
190
|
self.audioOutput().setVolume(linearVolume)
|
192
191
|
|
@@ -195,10 +194,10 @@ class MediaPlayer(QtMultimedia.QMediaPlayer): # pragma: no cover
|
|
195
194
|
return 100
|
196
195
|
volume = self.audioOutput().volume()
|
197
196
|
volume = int(
|
198
|
-
QtMultimedia.
|
197
|
+
QtMultimedia.QtAudio.convertVolume(
|
199
198
|
volume,
|
200
|
-
QtMultimedia.
|
201
|
-
QtMultimedia.
|
199
|
+
QtMultimedia.QtAudio.VolumeScale.LinearVolumeScale,
|
200
|
+
QtMultimedia.QtAudio.VolumeScale.LogarithmicVolumeScale,
|
202
201
|
)
|
203
202
|
* 100
|
204
203
|
)
|
anchor/workers.py
CHANGED
@@ -29,7 +29,6 @@ from _kalpy.feat import compute_pitch
|
|
29
29
|
from _kalpy.ivector import Plda, ivector_normalize_length
|
30
30
|
from _kalpy.matrix import DoubleVector, FloatVector
|
31
31
|
from kalpy.feat.pitch import PitchComputer
|
32
|
-
from line_profiler_pycharm import profile
|
33
32
|
from montreal_forced_aligner import config
|
34
33
|
from montreal_forced_aligner.alignment import PretrainedAligner
|
35
34
|
from montreal_forced_aligner.config import IVECTOR_DIMENSION, XVECTOR_DIMENSION
|
@@ -3151,7 +3150,6 @@ class SpectrogramWorker(FunctionWorker): # pragma: no cover
|
|
3151
3150
|
self.end = end
|
3152
3151
|
self.channel = channel
|
3153
3152
|
|
3154
|
-
@profile
|
3155
3153
|
def run(self):
|
3156
3154
|
self.stopped.clear()
|
3157
3155
|
dynamic_range = self.settings.value(self.settings.SPEC_DYNAMIC_RANGE)
|
@@ -3173,7 +3171,6 @@ class SpectrogramWorker(FunctionWorker): # pragma: no cover
|
|
3173
3171
|
self.y = scipy.signal.resample(
|
3174
3172
|
self.y, int(self.y.shape[0] * max_sr / self.sample_rate)
|
3175
3173
|
)
|
3176
|
-
# self.y = resampy.resample(self.y, self.sample_rate, max_sr, filter='kaiser_fast')
|
3177
3174
|
self.sample_rate = max_sr
|
3178
3175
|
self.y = librosa.effects.preemphasis(self.y, coef=pre_emph_coeff)
|
3179
3176
|
if self.stopped.is_set():
|
File without changes
|
File without changes
|
File without changes
|