batchalign 0.8.2.post2__tar.gz → 0.8.2.post4__tar.gz

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 (156) hide show
  1. {batchalign-0.8.2.post2/batchalign.egg-info → batchalign-0.8.2.post4}/PKG-INFO +1 -1
  2. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/cli/cli.py +5 -4
  3. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/cli/dispatch.py +8 -4
  4. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/formats/chat/generator.py +3 -0
  5. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/analysis/compare.py +33 -6
  6. batchalign-0.8.2.post4/batchalign/version +3 -0
  7. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4/batchalign.egg-info}/PKG-INFO +1 -1
  8. batchalign-0.8.2.post2/batchalign/version +0 -3
  9. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/LICENSE +0 -0
  10. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/MANIFEST.in +0 -0
  11. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/README.md +0 -0
  12. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/__init__.py +0 -0
  13. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/__main__.py +0 -0
  14. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/cli/__init__.py +0 -0
  15. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/cli/bench.py +0 -0
  16. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/cli/cache.py +0 -0
  17. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/constants.py +0 -0
  18. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/document.py +0 -0
  19. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/errors.py +0 -0
  20. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/formats/__init__.py +0 -0
  21. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/formats/base.py +0 -0
  22. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/formats/chat/__init__.py +0 -0
  23. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/formats/chat/file.py +0 -0
  24. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/formats/chat/lexer.py +0 -0
  25. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/formats/chat/parser.py +0 -0
  26. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/formats/chat/utils.py +0 -0
  27. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/formats/textgrid/__init__.py +0 -0
  28. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/formats/textgrid/file.py +0 -0
  29. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/formats/textgrid/generator.py +0 -0
  30. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/formats/textgrid/parser.py +0 -0
  31. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/models/__init__.py +0 -0
  32. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/models/audio_io.py +0 -0
  33. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/models/resolve.py +0 -0
  34. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/models/speaker/__init__.py +0 -0
  35. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/models/speaker/config.yaml +0 -0
  36. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/models/speaker/infer.py +0 -0
  37. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/models/speaker/utils.py +0 -0
  38. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/models/training/__init__.py +0 -0
  39. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/models/training/run.py +0 -0
  40. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/models/training/utils.py +0 -0
  41. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/models/utils.py +0 -0
  42. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/models/utterance/__init__.py +0 -0
  43. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/models/utterance/cantonese_infer.py +0 -0
  44. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/models/utterance/dataset.py +0 -0
  45. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/models/utterance/execute.py +0 -0
  46. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/models/utterance/infer.py +0 -0
  47. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/models/utterance/prep.py +0 -0
  48. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/models/utterance/train.py +0 -0
  49. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/models/wave2vec/__init__.py +0 -0
  50. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/models/wave2vec/infer_fa.py +0 -0
  51. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/models/whisper/__init__.py +0 -0
  52. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/models/whisper/infer_asr.py +0 -0
  53. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/models/whisper/infer_fa.py +0 -0
  54. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/__init__.py +0 -0
  55. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/analysis/__init__.py +0 -0
  56. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/analysis/eval.py +0 -0
  57. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/asr/__init__.py +0 -0
  58. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/asr/num2chinese.py +0 -0
  59. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/asr/num2lang/__init__.py +0 -0
  60. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/asr/num2lang/deu.py +0 -0
  61. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/asr/num2lang/ell.py +0 -0
  62. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/asr/num2lang/eng.py +0 -0
  63. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/asr/num2lang/eus.py +0 -0
  64. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/asr/num2lang/fra.py +0 -0
  65. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/asr/num2lang/hrv.py +0 -0
  66. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/asr/num2lang/ind.py +0 -0
  67. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/asr/num2lang/jpn.py +0 -0
  68. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/asr/num2lang/nld.py +0 -0
  69. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/asr/num2lang/por.py +0 -0
  70. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/asr/num2lang/spa.py +0 -0
  71. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/asr/num2lang/tha.py +0 -0
  72. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/asr/oai_whisper.py +0 -0
  73. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/asr/rev.py +0 -0
  74. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/asr/utils.py +0 -0
  75. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/asr/whisper.py +0 -0
  76. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/asr/whisperx.py +0 -0
  77. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/avqi/__init__.py +0 -0
  78. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/avqi/engine.py +0 -0
  79. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/base.py +0 -0
  80. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/cache.py +0 -0
  81. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/cleanup/__init__.py +0 -0
  82. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/cleanup/cleanup.py +0 -0
  83. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/cleanup/disfluencies.py +0 -0
  84. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/cleanup/parse_support.py +0 -0
  85. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/cleanup/retrace.py +0 -0
  86. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/cleanup/support/filled_pauses.eng +0 -0
  87. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/cleanup/support/replacements.eng +0 -0
  88. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/cleanup/support/test.test +0 -0
  89. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/diarization/__init__.py +0 -0
  90. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/diarization/pyannote.py +0 -0
  91. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/dispatch.py +0 -0
  92. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/fa/__init__.py +0 -0
  93. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/fa/wave2vec_fa.py +0 -0
  94. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/fa/whisper_fa.py +0 -0
  95. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/morphosyntax/__init__.py +0 -0
  96. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/morphosyntax/coref.py +0 -0
  97. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/morphosyntax/en/irr.py +0 -0
  98. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/morphosyntax/fr/apm.py +0 -0
  99. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/morphosyntax/fr/apmn.py +0 -0
  100. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/morphosyntax/fr/case.py +0 -0
  101. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/morphosyntax/ja/verbforms.py +0 -0
  102. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/morphosyntax/ud.py +0 -0
  103. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/opensmile/__init__.py +0 -0
  104. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/opensmile/engine.py +0 -0
  105. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/pipeline.py +0 -0
  106. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/speaker/__init__.py +0 -0
  107. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/speaker/nemo_speaker.py +0 -0
  108. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/translate/__init__.py +0 -0
  109. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/translate/gtrans.py +0 -0
  110. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/translate/seamless.py +0 -0
  111. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/translate/utils.py +0 -0
  112. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/utr/__init__.py +0 -0
  113. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/utr/rev_utr.py +0 -0
  114. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/utr/utils.py +0 -0
  115. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/utr/whisper_utr.py +0 -0
  116. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/utterance/__init__.py +0 -0
  117. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/pipelines/utterance/ud_utterance.py +0 -0
  118. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/tests/__init__.py +0 -0
  119. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/tests/cli/test_dispatch_memory.py +0 -0
  120. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/tests/conftest.py +0 -0
  121. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/tests/formats/chat/test_chat_file.py +0 -0
  122. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/tests/formats/chat/test_chat_generator.py +0 -0
  123. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/tests/formats/chat/test_chat_lexer.py +0 -0
  124. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/tests/formats/chat/test_chat_parser.py +0 -0
  125. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/tests/formats/chat/test_chat_utils.py +0 -0
  126. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/tests/formats/textgrid/test_textgrid.py +0 -0
  127. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/tests/models/test_audio_io.py +0 -0
  128. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/tests/models/test_audio_lazy.py +0 -0
  129. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/tests/pipelines/analysis/test_eval.py +0 -0
  130. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/tests/pipelines/asr/test_asr_pipeline.py +0 -0
  131. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/tests/pipelines/asr/test_asr_utils.py +0 -0
  132. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/tests/pipelines/cache/__init__.py +0 -0
  133. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/tests/pipelines/cache/test_cache.py +0 -0
  134. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/tests/pipelines/cleanup/test_disfluency.py +0 -0
  135. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/tests/pipelines/cleanup/test_parse_support.py +0 -0
  136. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/tests/pipelines/fa/test_fa_pipeline.py +0 -0
  137. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/tests/pipelines/fa/test_fa_short_segments.py +0 -0
  138. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/tests/pipelines/fixures.py +0 -0
  139. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/tests/pipelines/test_pipeline.py +0 -0
  140. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/tests/pipelines/test_pipeline_models.py +0 -0
  141. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/tests/test_document.py +0 -0
  142. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/utils/__init__.py +0 -0
  143. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/utils/abbrev.py +0 -0
  144. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/utils/compounds.py +0 -0
  145. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/utils/config.py +0 -0
  146. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/utils/device.py +0 -0
  147. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/utils/dp.py +0 -0
  148. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/utils/names.py +0 -0
  149. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign/utils/utils.py +0 -0
  150. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign.egg-info/SOURCES.txt +0 -0
  151. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign.egg-info/dependency_links.txt +0 -0
  152. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign.egg-info/entry_points.txt +0 -0
  153. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign.egg-info/requires.txt +0 -0
  154. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/batchalign.egg-info/top_level.txt +0 -0
  155. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/setup.cfg +0 -0
  156. {batchalign-0.8.2.post2 → batchalign-0.8.2.post4}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: batchalign
3
- Version: 0.8.2.post2
3
+ Version: 0.8.2.post4
4
4
  Summary: Python Speech Language Sample Analysis
5
5
  Author: Brian MacWhinney, Houjun Liu
6
6
  Author-email: macw@cmu.edu, houjun@cmu.edu
@@ -415,10 +415,11 @@ def benchmark(ctx, in_dir, out_dir, lang, num_speakers, whisper, whisper_oai, **
415
415
  def compare(ctx, in_dir, out_dir, lang, **kwargs):
416
416
  """Compare transcripts against gold-standard references.
417
417
 
418
- For each FILE.cha in IN_DIR, expects a companion FILE.gold.cha in the
419
- same directory. Runs morphosyntax analysis on the main transcript, then
420
- produces a word-level diff stored as %%xsrep / %%xsmor tiers and writes
421
- error metrics to a .compare.csv file in OUT_DIR.
418
+ For each FILE.cha in IN_DIR, looks for a companion FILE.gold.cha in the
419
+ same directory. If not found, falls back to template.gold.cha as the
420
+ default gold for all files. Runs morphosyntax analysis on the main
421
+ transcript, then produces a word-level diff stored as %%xsrep / %%xsmor
422
+ tiers and writes error metrics to a .compare.csv file in OUT_DIR.
422
423
  """
423
424
 
424
425
  _dispatch("compare", lang, 1, ["cha"], ctx,
@@ -204,19 +204,23 @@ def _run_pipeline_for_file(command, pipeline, file, output, loader_info, writer_
204
204
  if file.endswith(".gold.cha"):
205
205
  return
206
206
 
207
- # Find companion gold file
207
+ # Find companion gold file: FILE.gold.cha overrides, then
208
+ # template.gold.cha serves as the default for the whole directory
208
209
  p = P(file)
209
210
  gold_path = p.parent / (p.stem + ".gold.cha")
211
+ if not gold_path.exists():
212
+ gold_path = p.parent / "template.gold.cha"
210
213
  if not gold_path.exists():
211
214
  raise FileNotFoundError(
212
215
  f"No gold .cha file found for comparison. "
213
- f"main: {p.name}, expected: {gold_path.name}, looked in: {str(gold_path)}"
216
+ f"main: {p.name}, expected: {p.stem}.gold.cha or template.gold.cha, "
217
+ f"looked in: {str(p.parent)}"
214
218
  )
215
219
 
216
220
  main_doc = CHATFile(path=str(p)).doc
217
221
  gold_doc = CHATFile(path=str(gold_path), special_mor_=True).doc
218
222
 
219
- # Pipeline: morphosyntax(main) -> compare -> compare_analysis
223
+ # Pipeline: compare (runs morphosyntax internally) -> compare_analysis
220
224
  result = pipeline(main_doc, callback=progress_callback, gold=gold_doc)
221
225
 
222
226
  # Write annotated CHAT
@@ -384,7 +388,7 @@ Cmd2Task = {
384
388
  "coref": "coref",
385
389
  "translate": "translate",
386
390
  "opensmile": "opensmile",
387
- "compare": "morphosyntax,compare,compare_analysis",
391
+ "compare": "compare,compare_analysis",
388
392
  }
389
393
 
390
394
  # this is the main runner used by all functions
@@ -131,6 +131,9 @@ def generate_chat_utterance(utterance: Utterance, special_mor=False, write_wor=T
131
131
  prefix = "+" if tok.status == "extra_main" else ("-" if tok.status == "extra_gold" else "")
132
132
  xsrep_parts.append(f"{prefix}{tok.text}")
133
133
  xsmor_parts.append(f"{prefix}{tok.pos or '?'}")
134
+ # Strip PUNCT POS from final element, keep the delimiter char (same as %mor)
135
+ if xsmor_parts and xsrep_parts and xsmor_parts[-1] == "PUNCT":
136
+ xsmor_parts[-1] = xsrep_parts[-1]
134
137
  result.append(f"%xsrep:\t" + " ".join(xsrep_parts))
135
138
  result.append(f"%xsmor:\t" + " ".join(xsmor_parts))
136
139
 
@@ -4,7 +4,7 @@ Engines for transcript comparison against gold-standard references.
4
4
 
5
5
  CompareEngine (PROCESSING): Aligns main vs gold transcripts word-by-word
6
6
  using the same conform/match_fn logic as WER evaluation, then annotates
7
- each main utterance with comparison tokens (%xsrep / %xsmor).
7
+ each gold utterance with comparison tokens (%xsrep / %xsmor).
8
8
 
9
9
  CompareAnalysisEngine (ANALYSIS): Reads the comparison annotations and
10
10
  computes error-rate metrics for CSV output.
@@ -208,6 +208,11 @@ def _find_best_segment(gold_tokens, main_tokens, mfn):
208
208
  elif len_delta == best_len_delta and end > best[1]:
209
209
  best = (start, end)
210
210
 
211
+ # If no tokens overlap at all, return an empty window so the caller
212
+ # doesn't consume main tokens that belong to a later gold utterance.
213
+ if best_score <= 0:
214
+ return 0, 0
215
+
211
216
  return best
212
217
 
213
218
 
@@ -249,6 +254,15 @@ def conform_with_mapping(words, conform_fn):
249
254
  class CompareEngine(BatchalignEngine):
250
255
  tasks = [Task.COMPARE]
251
256
 
257
+ def __init__(self):
258
+ self._stanza = None
259
+
260
+ def _get_stanza(self):
261
+ if self._stanza is None:
262
+ from batchalign.pipelines.morphosyntax import StanzaEngine
263
+ self._stanza = StanzaEngine()
264
+ return self._stanza
265
+
252
266
  def process(self, doc, **kwargs):
253
267
  gold = kwargs.get("gold")
254
268
  if not gold or not isinstance(gold, Document):
@@ -256,6 +270,12 @@ class CompareEngine(BatchalignEngine):
256
270
  f"CompareEngine requires a 'gold' Document kwarg, got '{type(gold)}'"
257
271
  )
258
272
 
273
+ # --- 0. Run morphosyntax on both docs ---
274
+ stanza = self._get_stanza()
275
+ non_gold_kwargs = {k: v for k, v in kwargs.items() if k != "gold"}
276
+ doc = stanza.process(doc, **non_gold_kwargs)
277
+ gold = stanza.process(gold, **non_gold_kwargs)
278
+
259
279
  # --- 1. Extract words from main utterances ---
260
280
  main_utterances = [
261
281
  u for u in doc.content if isinstance(u, Utterance)
@@ -343,16 +363,14 @@ class CompareEngine(BatchalignEngine):
343
363
  gold_form = gold_info[orig_gold_idx][2]
344
364
  last_gold_form_idx = gold_form_idx
345
365
 
366
+ # Copy timing from main; keep gold's own morphology
346
367
  if main_form.time is not None:
347
368
  gold_form.time = main_form.time
348
- if main_form.morphology is not None:
349
- gold_form.morphology = main_form.morphology
350
- if main_form.dependency is not None:
351
- gold_form.dependency = main_form.dependency
369
+ gold_form.dependency = None
352
370
 
353
371
  utt_positioned[utt_idx].append((gold_form_idx, CompareToken(
354
372
  text=item.key,
355
- pos=_get_pos(main_form),
373
+ pos=_get_pos(gold_form),
356
374
  status="match"
357
375
  )))
358
376
  local_main_cursor += 1
@@ -365,6 +383,8 @@ class CompareEngine(BatchalignEngine):
365
383
  gold_form = gold_info[orig_gold_idx][2]
366
384
  last_gold_form_idx = gold_form_idx
367
385
 
386
+ gold_form.dependency = None
387
+
368
388
  utt_positioned[utt_idx].append((gold_form_idx, CompareToken(
369
389
  text=item.key,
370
390
  pos=_get_pos(gold_form),
@@ -395,6 +415,13 @@ class CompareEngine(BatchalignEngine):
395
415
  pos="PUNCT",
396
416
  status="match"
397
417
  )))
418
+ # Ensure punctuation forms have morphology so %mor includes
419
+ # the final delimiter (matches generator's PUNCT|<char> logic)
420
+ if form.morphology is None:
421
+ form.morphology = [Morphology(
422
+ pos="PUNCT", lemma=form.text.strip(), feats=""
423
+ )]
424
+ form.dependency = None
398
425
  utt_positioned[utt_idx].sort(key=lambda x: x[0])
399
426
 
400
427
  # --- 7. Set comparison on each gold utterance ---
@@ -0,0 +1,3 @@
1
+ 0.8.2-post.4
2
+ March 30 2026
3
+ More compare bug fixes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: batchalign
3
- Version: 0.8.2.post2
3
+ Version: 0.8.2.post4
4
4
  Summary: Python Speech Language Sample Analysis
5
5
  Author: Brian MacWhinney, Houjun Liu
6
6
  Author-email: macw@cmu.edu, houjun@cmu.edu
@@ -1,3 +0,0 @@
1
- 0.8.2-post.2
2
- Feb 27th 2026
3
- adds new feature regarding compare