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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: Anchor_annotator
3
- Version: 0.3.0
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=Jk2iAU7m-7Vx9XV1TtdD9ZoJraIncDq_4_Wd-qtUotg,411
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=jpSisbtASWnD_In1jgcvH7xA8-9HJFylY2AVGw1tqMU,95858
8
- anchor/plot.py,sha256=R0SCcK-QmkTkQRsGWRRq1M9vnmve7pyQRaYMvcKlC3Q,104473
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=nfcSBJ0_30V_uWNDFLZ48T9p9hJcu0mpbW31VMfxMZg,63518
13
+ anchor/ui_main_window.py,sha256=MYb4PtV1sHYgnc3QwPphKjU3LepzBJpxllhN4nyDook,63525
14
14
  anchor/ui_preferences.py,sha256=MOC2dY4qkViW9cUbC0DVSO7FLg-dGSbmR630WFQ6V9c,41843
15
- anchor/undo.py,sha256=PLtiAxC7U27vbega_p21vDRy4m9QBiHatDELlcNx08Y,32523
16
- anchor/widgets.py,sha256=th0zg-bgmHfwEbdfLKkt-OZUsmjy01PSAGGwcnlwwNM,158375
17
- anchor/workers.py,sha256=Uqre4W6kh9TEm72oocBitj-KT6lSR3WX7eB3wVZZYQM,171238
18
- Anchor_annotator-0.3.0.dist-info/LICENSE,sha256=C0oIsblENEgWQ7XMNdYoXyXsIA5wa3YF0I9lK3H7A1s,1076
19
- Anchor_annotator-0.3.0.dist-info/METADATA,sha256=CRpxOymwZoBYlSWMAnvByNOMEI73Nnv4vn0LyYZl36Y,1500
20
- Anchor_annotator-0.3.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
21
- Anchor_annotator-0.3.0.dist-info/top_level.txt,sha256=wX6ZKxImGRZKFQjs3f6XYw_TfbAp6Xs3SmbLfLbFAJ0,7
22
- Anchor_annotator-0.3.0.dist-info/RECORD,,
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
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '0.3.0'
16
- __version_tuple__ = version_tuple = (0, 3, 0)
15
+ __version__ = version = '0.3.2'
16
+ __version_tuple__ = version_tuple = (0, 3, 2)
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
- # self.model().changeCommandFired.connect(self.expire_current)
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
- session.query(Speaker).filter(
649
- Speaker.id.in_(self.old_speaker_ids + [self.new_speaker_id])
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
- session.query(Speaker).filter(
656
- Speaker.id.in_(self.old_speaker_ids + [self.new_speaker_id])
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.QAudio.convertVolume(
185
+ linearVolume = QtMultimedia.QtAudio.convertVolume(
187
186
  volume / 100.0,
188
- QtMultimedia.QAudio.VolumeScale.LogarithmicVolumeScale,
189
- QtMultimedia.QAudio.VolumeScale.LinearVolumeScale,
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.QAudio.convertVolume(
197
+ QtMultimedia.QtAudio.convertVolume(
199
198
  volume,
200
- QtMultimedia.QAudio.VolumeScale.LinearVolumeScale,
201
- QtMultimedia.QAudio.VolumeScale.LogarithmicVolumeScale,
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():