Anchor-annotator 0.0.11__py3-none-any.whl → 0.2.0__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/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, bulk_update
9
+ from montreal_forced_aligner.db import File, Pronunciation, Speaker, Utterance, Word
10
10
  from PySide6 import QtCore, QtGui
11
11
  from sqlalchemy.orm import make_transient
12
12
 
@@ -15,6 +15,7 @@ if typing.TYPE_CHECKING:
15
15
  CorpusModel,
16
16
  DiarizationModel,
17
17
  DictionaryTableModel,
18
+ FileUtterancesModel,
18
19
  SpeakerModel,
19
20
  TextFilterQuery,
20
21
  )
@@ -38,9 +39,8 @@ class CorpusCommand(QtGui.QUndoCommand):
38
39
 
39
40
  def redo(self) -> None:
40
41
  with self.corpus_model.edit_lock:
41
- with self.corpus_model.session() as session:
42
- self._redo(session)
43
- session.commit()
42
+ self._redo(self.corpus_model.session)
43
+ self.corpus_model.session.commit()
44
44
  # while True:
45
45
  # try:
46
46
  # with self.corpus_model.session.begin_nested():
@@ -53,9 +53,8 @@ class CorpusCommand(QtGui.QUndoCommand):
53
53
 
54
54
  def undo(self) -> None:
55
55
  with self.corpus_model.edit_lock:
56
- with self.corpus_model.session() as session:
57
- self._undo(session)
58
- session.commit()
56
+ self._undo(self.corpus_model.session)
57
+ self.corpus_model.session.commit()
59
58
  # while True:
60
59
  # try:
61
60
  # with self.corpus_model.session.begin_nested():
@@ -66,6 +65,12 @@ class CorpusCommand(QtGui.QUndoCommand):
66
65
  self.update_data()
67
66
 
68
67
 
68
+ class FileCommand(CorpusCommand):
69
+ def __init__(self, file_model: FileUtterancesModel):
70
+ super().__init__(file_model.corpus_model)
71
+ self.file_model = file_model
72
+
73
+
69
74
  class DictionaryCommand(QtGui.QUndoCommand):
70
75
  def __init__(self, dictionary_model: DictionaryTableModel):
71
76
  super().__init__()
@@ -127,9 +132,9 @@ class SpeakerCommand(QtGui.QUndoCommand):
127
132
  self.update_data()
128
133
 
129
134
 
130
- class DeleteUtteranceCommand(CorpusCommand):
131
- def __init__(self, deleted_utterances: list[Utterance], corpus_model: CorpusModel):
132
- super().__init__(corpus_model)
135
+ class DeleteUtteranceCommand(FileCommand):
136
+ def __init__(self, deleted_utterances: list[Utterance], file_model: FileUtterancesModel):
137
+ super().__init__(file_model)
133
138
  self.deleted_utterances = deleted_utterances
134
139
  self.resets_tier = True
135
140
  self.channels = [
@@ -145,11 +150,26 @@ class DeleteUtteranceCommand(CorpusCommand):
145
150
 
146
151
  def _undo(self, session) -> None:
147
152
  for i, utt in enumerate(self.deleted_utterances):
153
+ try:
154
+ del utt.duration
155
+ except AttributeError:
156
+ pass
157
+ try:
158
+ del utt.kaldi_id
159
+ except AttributeError:
160
+ pass
148
161
  make_transient(utt)
149
162
  for x in utt.phone_intervals:
150
- x.duration = None
163
+ try:
164
+ del x.duration
165
+ except AttributeError:
166
+ pass
151
167
  make_transient(x)
152
168
  for x in utt.word_intervals:
169
+ try:
170
+ del x.duration
171
+ except AttributeError:
172
+ pass
153
173
  make_transient(x)
154
174
  if utt.channel is None:
155
175
  utt.channel = self.channels[i]
@@ -158,95 +178,112 @@ class DeleteUtteranceCommand(CorpusCommand):
158
178
  def redo(self) -> None:
159
179
  super().redo()
160
180
  self.corpus_model.delete_table_utterances(self.deleted_utterances)
181
+ self.file_model.delete_table_utterances(self.deleted_utterances)
161
182
  self.corpus_model.changeCommandFired.emit()
162
183
 
163
184
  def undo(self) -> None:
164
185
  super().undo()
165
186
  self.corpus_model.add_table_utterances(self.deleted_utterances)
187
+ self.file_model.add_table_utterances(self.deleted_utterances)
166
188
  self.corpus_model.changeCommandFired.emit()
167
189
 
168
190
 
169
- class SplitUtteranceCommand(CorpusCommand):
191
+ class SplitUtteranceCommand(FileCommand):
170
192
  def __init__(
171
193
  self,
172
- split_utterances: list[list[Utterance, ...]],
173
- corpus_model: CorpusModel,
194
+ merged_utterance: Utterance,
195
+ split_utterances: list[Utterance],
196
+ file_model: FileUtterancesModel,
174
197
  update_table: bool = True,
175
198
  ):
176
- super().__init__(corpus_model)
199
+ super().__init__(file_model)
200
+ self.merged_utterance = merged_utterance
177
201
  self.split_utterances = split_utterances
178
202
  self.resets_tier = True
179
203
  self.update_table = update_table
180
- self.channels = [
181
- x[0].channel if x[0].channel is not None else 0 for x in self.split_utterances
182
- ]
204
+ self.channels = [x.channel if x.channel is not None else 0 for x in self.split_utterances]
183
205
  self.setText(
184
206
  QtCore.QCoreApplication.translate("SplitUtteranceCommand", "Split utterances")
185
207
  )
186
208
 
187
209
  def _redo(self, session) -> None:
188
- for i, splits in enumerate(self.split_utterances):
189
- old_utt = splits[0]
190
- split_utts = splits[1:]
191
- session.delete(old_utt)
192
- for u in split_utts:
193
- if u.id is not None:
194
- make_transient(u)
195
- for x in u.phone_intervals:
196
- x.duration = None
197
- make_transient(x)
198
- for x in u.word_intervals:
199
- make_transient(x)
200
- if u.channel is None:
201
- u.channel = self.channels[i]
202
- u.duration = None
203
- u.kaldi_id = None
204
- session.add(u)
205
-
206
- def _undo(self, session) -> None:
207
- for i, splits in enumerate(self.split_utterances):
208
- old_utt = splits[0]
209
- split_utts = splits[1:]
210
- if old_utt.channel is None:
211
- old_utt.channel = self.channels[i]
212
- old_utt.duration = None
213
- old_utt.kaldi_id = None
214
- make_transient(old_utt)
215
- for x in old_utt.phone_intervals:
216
- x.duration = None
210
+ session.delete(self.merged_utterance)
211
+ for u in self.split_utterances:
212
+ if u.id is not None:
213
+ make_transient(u)
214
+ for x in u.phone_intervals:
215
+ try:
216
+ del x.duration
217
+ except AttributeError:
218
+ pass
217
219
  make_transient(x)
218
- for x in old_utt.word_intervals:
220
+ for x in u.word_intervals:
221
+ try:
222
+ del x.duration
223
+ except AttributeError:
224
+ pass
219
225
  make_transient(x)
220
- session.add(old_utt)
221
- for u in split_utts:
222
- session.delete(u)
226
+ if u.channel is None:
227
+ u.channel = self.merged_utterance.channel
228
+ try:
229
+ del u.duration
230
+ except AttributeError:
231
+ pass
232
+ try:
233
+ del u.kaldi_id
234
+ except AttributeError:
235
+ pass
236
+ session.add(u)
237
+
238
+ def _undo(self, session) -> None:
239
+ if self.merged_utterance.channel is None:
240
+ self.merged_utterance.channel = self.split_utterances[0].channel
241
+ try:
242
+ del self.merged_utterance.duration
243
+ except AttributeError:
244
+ pass
245
+ try:
246
+ del self.merged_utterance.kaldi_id
247
+ except AttributeError:
248
+ pass
249
+ make_transient(self.merged_utterance)
250
+ for x in self.merged_utterance.phone_intervals:
251
+ try:
252
+ del x.duration
253
+ except AttributeError:
254
+ pass
255
+ make_transient(x)
256
+ for x in self.merged_utterance.word_intervals:
257
+ try:
258
+ del x.duration
259
+ except AttributeError:
260
+ pass
261
+ make_transient(x)
262
+ session.add(self.merged_utterance)
263
+ for u in self.split_utterances:
264
+ session.delete(u)
223
265
 
224
266
  def redo(self) -> None:
225
267
  super().redo()
226
- for splits in self.split_utterances:
227
- old_utt = splits[0]
228
- split_utts = splits[1:]
229
- if self.update_table:
230
- self.corpus_model.split_table_utterances(old_utt, split_utts)
268
+ self.corpus_model.split_table_utterances(self.merged_utterance, self.split_utterances)
269
+ self.file_model.split_table_utterances(self.merged_utterance, self.split_utterances)
231
270
  self.corpus_model.changeCommandFired.emit()
232
271
 
233
272
  def undo(self) -> None:
234
273
  super().undo()
235
- for splits in self.split_utterances:
236
- old_utt = splits[0]
237
- split_utts = splits[1:]
238
- self.corpus_model.merge_table_utterances(old_utt, split_utts)
274
+ self.corpus_model.merge_table_utterances(self.merged_utterance, self.split_utterances)
275
+ self.file_model.merge_table_utterances(self.merged_utterance, self.split_utterances)
239
276
  self.corpus_model.changeCommandFired.emit()
240
277
 
241
278
 
242
- class MergeUtteranceCommand(CorpusCommand):
279
+ class MergeUtteranceCommand(FileCommand):
243
280
  def __init__(
244
281
  self,
245
282
  unmerged_utterances: list[Utterance],
246
283
  merged_utterance: Utterance,
247
- corpus_model: CorpusModel,
284
+ file_model: FileUtterancesModel,
248
285
  ):
249
- super().__init__(corpus_model)
286
+ super().__init__(file_model)
250
287
  self.unmerged_utterances = unmerged_utterances
251
288
  self.merged_utterance = merged_utterance
252
289
  self.resets_tier = True
@@ -264,7 +301,6 @@ class MergeUtteranceCommand(CorpusCommand):
264
301
  if self.merged_utterance.channel is None:
265
302
  self.merged_utterance.channel = self.channel
266
303
  self.merged_utterance.kaldi_id = None
267
- self.merged_utterance.duration = None
268
304
  session.add(self.merged_utterance)
269
305
 
270
306
  def _undo(self, session) -> None:
@@ -280,17 +316,18 @@ class MergeUtteranceCommand(CorpusCommand):
280
316
  old_utt.duration = None
281
317
  old_utt.kaldi_id = None
282
318
  session.add(old_utt)
283
- # session.refresh(self.merged_utterance)
284
319
  session.delete(self.merged_utterance)
285
320
 
286
321
  def redo(self) -> None:
287
322
  super().redo()
288
323
  self.corpus_model.merge_table_utterances(self.merged_utterance, self.unmerged_utterances)
324
+ self.file_model.merge_table_utterances(self.merged_utterance, self.unmerged_utterances)
289
325
  self.corpus_model.changeCommandFired.emit()
290
326
 
291
327
  def undo(self) -> None:
292
328
  super().undo()
293
329
  self.corpus_model.split_table_utterances(self.merged_utterance, self.unmerged_utterances)
330
+ self.file_model.split_table_utterances(self.merged_utterance, self.unmerged_utterances)
294
331
  self.corpus_model.changeCommandFired.emit()
295
332
 
296
333
 
@@ -350,11 +387,10 @@ class MergeSpeakersCommand(CorpusCommand):
350
387
  ).update({Speaker.modified: True})
351
388
 
352
389
 
353
- class CreateUtteranceCommand(CorpusCommand):
354
- def __init__(self, new_utterance: Utterance, corpus_model: CorpusModel):
355
- super().__init__(corpus_model)
390
+ class CreateUtteranceCommand(FileCommand):
391
+ def __init__(self, new_utterance: Utterance, file_model: FileUtterancesModel):
392
+ super().__init__(file_model)
356
393
  self.new_utterance = new_utterance
357
- self.resets_tier = True
358
394
  self.channel = self.new_utterance.channel
359
395
  if self.channel is None:
360
396
  self.channel = 0
@@ -366,6 +402,14 @@ class CreateUtteranceCommand(CorpusCommand):
366
402
  make_transient(self.new_utterance)
367
403
  if self.new_utterance.channel is None:
368
404
  self.new_utterance.channel = self.channel
405
+ try:
406
+ del self.new_utterance.duration
407
+ except AttributeError:
408
+ pass
409
+ try:
410
+ del self.new_utterance.kaldi_id
411
+ except AttributeError:
412
+ pass
369
413
  session.add(self.new_utterance)
370
414
 
371
415
  def _undo(self, session) -> None:
@@ -377,18 +421,22 @@ class CreateUtteranceCommand(CorpusCommand):
377
421
  def redo(self) -> None:
378
422
  super().redo()
379
423
  self.corpus_model.add_table_utterances([self.new_utterance])
424
+ self.file_model.add_table_utterances([self.new_utterance])
380
425
  self.corpus_model.changeCommandFired.emit()
381
426
 
382
427
  def undo(self) -> None:
383
428
  super().undo()
384
429
  self.corpus_model.delete_table_utterances([self.new_utterance])
430
+ self.file_model.delete_table_utterances([self.new_utterance])
385
431
  self.corpus_model.changeCommandFired.emit()
386
432
 
387
433
 
388
- class UpdateUtteranceTimesCommand(CorpusCommand):
389
- def __init__(self, utterance: Utterance, begin: float, end: float, corpus_model: CorpusModel):
390
- super().__init__(corpus_model)
391
- self.utterance_id = utterance.id
434
+ class UpdateUtteranceTimesCommand(FileCommand):
435
+ def __init__(
436
+ self, utterance: Utterance, begin: float, end: float, file_model: FileUtterancesModel
437
+ ):
438
+ super().__init__(file_model)
439
+ self.utterance = utterance
392
440
  self.new_begin = begin
393
441
  self.old_begin = utterance.begin
394
442
  self.new_end = end
@@ -400,37 +448,39 @@ class UpdateUtteranceTimesCommand(CorpusCommand):
400
448
  )
401
449
 
402
450
  def _redo(self, session) -> None:
403
- session.query(Utterance).filter(Utterance.id == self.utterance_id).update(
404
- {
405
- Utterance.begin: self.new_begin,
406
- Utterance.end: self.new_end,
407
- Utterance.xvector: None,
408
- Utterance.ivector: None,
409
- Utterance.features: None,
410
- }
411
- )
451
+ self.utterance.begin = self.new_begin
452
+ self.utterance.end = self.new_end
453
+ self.utterance.xvector = None
454
+ self.utterance.ivector = None
455
+ self.utterance.features = None
456
+ try:
457
+ del self.utterance.duration
458
+ except AttributeError:
459
+ pass
460
+ session.merge(self.utterance)
412
461
 
413
462
  def _undo(self, session) -> None:
414
- session.query(Utterance).filter(Utterance.id == self.utterance_id).update(
415
- {
416
- Utterance.begin: self.old_begin,
417
- Utterance.end: self.old_end,
418
- Utterance.xvector: None,
419
- Utterance.ivector: None,
420
- Utterance.features: None,
421
- }
422
- )
463
+ self.utterance.begin = self.old_begin
464
+ self.utterance.end = self.old_end
465
+ self.utterance.xvector = None
466
+ self.utterance.ivector = None
467
+ self.utterance.features = None
468
+ try:
469
+ del self.utterance.duration
470
+ except AttributeError:
471
+ pass
472
+ session.merge(self.utterance)
423
473
 
424
474
  def update_data(self):
425
475
  super().update_data()
426
476
  self.corpus_model.changeCommandFired.emit()
427
- self.corpus_model.update_utterance_table_row(self.utterance_id)
477
+ self.corpus_model.update_utterance_table_row(self.utterance)
428
478
 
429
479
 
430
- class UpdateUtteranceTextCommand(CorpusCommand):
431
- def __init__(self, utterance: Utterance, new_text: str, corpus_model: CorpusModel):
432
- super().__init__(corpus_model)
433
- self.utterance_id = utterance.id
480
+ class UpdateUtteranceTextCommand(FileCommand):
481
+ def __init__(self, utterance: Utterance, new_text: str, file_model: FileUtterancesModel):
482
+ super().__init__(file_model)
483
+ self.utterance = utterance
434
484
  self.speaker_id = utterance.speaker_id
435
485
  self.old_text = utterance.text
436
486
  self.new_text = new_text
@@ -445,40 +495,36 @@ class UpdateUtteranceTextCommand(CorpusCommand):
445
495
  for w in self.new_text.split():
446
496
  if not self.corpus_model.dictionary_model.check_word(w, self.speaker_id):
447
497
  oovs.add(w)
448
- session.query(Utterance).filter(Utterance.id == self.utterance_id).update(
449
- {
450
- Utterance.text: self.new_text,
451
- Utterance.normalized_text: self.new_text, # FIXME: Update this
452
- Utterance.oovs: " ".join(oovs),
453
- Utterance.ignored: not self.new_text,
454
- }
455
- )
498
+ try:
499
+ del self.utterance.duration
500
+ except AttributeError:
501
+ pass
502
+ self.utterance.text = self.new_text
503
+ self.utterance.normalized_text = self.new_text # FIXME: Update this
504
+ self.utterance.oovs = " ".join(oovs)
505
+ self.utterance.ignored = not self.new_text
506
+ session.merge(self.utterance)
456
507
 
457
508
  def _undo(self, session) -> None:
458
509
  oovs = set()
459
510
  for w in self.new_text.split():
460
511
  if not self.corpus_model.dictionary_model.check_word(w, self.speaker_id):
461
512
  oovs.add(w)
462
- session.query(Utterance).filter(Utterance.id == self.utterance_id).update(
463
- {
464
- Utterance.text: self.old_text,
465
- Utterance.oovs: " ".join(oovs),
466
- Utterance.ignored: not self.old_text,
467
- }
468
- )
469
-
470
- def update_data(self):
471
- super().update_data()
472
513
  try:
473
- self.corpus_model.update_utterance_table_row(self.utterance_id)
474
- except KeyError:
514
+ del self.utterance.duration
515
+ except AttributeError:
475
516
  pass
517
+ self.utterance.text = self.old_text
518
+ self.utterance.normalized_text = self.old_text # FIXME: Update this
519
+ self.utterance.oovs = " ".join(oovs)
520
+ self.utterance.ignored = not self.old_text
521
+ session.merge(self.utterance)
476
522
 
477
523
  def id(self) -> int:
478
524
  return 1
479
525
 
480
526
  def mergeWith(self, other: UpdateUtteranceTextCommand) -> bool:
481
- if other.id() != self.id() or other.utterance_id != self.utterance_id:
527
+ if other.id() != self.id() or other.utterance.id != self.utterance.id:
482
528
  return False
483
529
  self.new_text = other.new_text
484
530
  return True
@@ -627,16 +673,17 @@ class UpdateSpeakerCommand(SpeakerCommand):
627
673
  )
628
674
 
629
675
 
630
- class UpdateUtteranceSpeakerCommand(CorpusCommand):
676
+ class UpdateUtteranceSpeakerCommand(FileCommand):
631
677
  def __init__(
632
678
  self,
633
679
  utterances: typing.Union[Utterance, typing.List[Utterance]],
634
680
  new_speaker: typing.Union[Speaker, int],
635
- corpus_model: CorpusModel,
681
+ file_model: FileUtterancesModel,
636
682
  ):
637
- super().__init__(corpus_model)
683
+ super().__init__(file_model)
638
684
  if not isinstance(utterances, list):
639
685
  utterances = [utterances]
686
+ self.utterances = utterances
640
687
  self.utterance_ids = [x.id for x in utterances]
641
688
  self.file_ids = set([x.file_id for x in utterances])
642
689
  self.old_speaker_ids = [x.speaker_id for x in utterances]
@@ -644,7 +691,6 @@ class UpdateUtteranceSpeakerCommand(CorpusCommand):
644
691
  self.new_speaker_id = new_speaker
645
692
  else:
646
693
  self.new_speaker_id = new_speaker.id
647
- self.resets_tier = True
648
694
  self.setText(
649
695
  QtCore.QCoreApplication.translate(
650
696
  "UpdateUtteranceSpeakerCommand", "Update utterance speaker"
@@ -673,18 +719,15 @@ class UpdateUtteranceSpeakerCommand(CorpusCommand):
673
719
  )
674
720
  )
675
721
  session.flush()
676
- session.query(Utterance).filter(Utterance.id.in_(self.utterance_ids)).update(
677
- {Utterance.speaker_id: self.new_speaker_id}
678
- )
722
+ for u in self.utterances:
723
+ u.speaker_id = self.new_speaker_id
679
724
  session.query(Speaker).filter(
680
725
  Speaker.id.in_(self.old_speaker_ids + [self.new_speaker_id])
681
726
  ).update({Speaker.modified: True})
682
727
 
683
728
  def _undo(self, session) -> None:
684
- update_mappings = []
685
- for i, u_id in enumerate(self.utterance_ids):
686
- update_mappings.append({"id": u_id, "speaker_id": self.old_speaker_ids[i]})
687
- bulk_update(self.corpus_model.session, Utterance, update_mappings)
729
+ for i, u in enumerate(self.utterances):
730
+ u.speaker_id = self.old_speaker_ids[i]
688
731
  session.query(Speaker).filter(
689
732
  Speaker.id.in_(self.old_speaker_ids + [self.new_speaker_id])
690
733
  ).update({Speaker.modified: True})
@@ -692,6 +735,8 @@ class UpdateUtteranceSpeakerCommand(CorpusCommand):
692
735
  def update_data(self):
693
736
  super().update_data()
694
737
  self.corpus_model.set_file_modified(self.file_ids)
738
+ self.corpus_model.change_speaker_table_utterances(self.utterances)
739
+ self.file_model.change_speaker_table_utterances(self.utterances)
695
740
  self.corpus_model.changeCommandFired.emit()
696
741
  self.corpus_model.update_data()
697
742
  self.corpus_model.runFunction.emit(