sonusai 0.18.9__py3-none-any.whl → 0.19.6__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 (118) hide show
  1. sonusai/__init__.py +20 -29
  2. sonusai/aawscd_probwrite.py +18 -18
  3. sonusai/audiofe.py +93 -80
  4. sonusai/calc_metric_spenh.py +395 -321
  5. sonusai/data/genmixdb.yml +5 -11
  6. sonusai/{gentcst.py → deprecated/gentcst.py} +146 -149
  7. sonusai/{plot.py → deprecated/plot.py} +177 -131
  8. sonusai/{tplot.py → deprecated/tplot.py} +124 -102
  9. sonusai/doc/__init__.py +1 -1
  10. sonusai/doc/doc.py +112 -177
  11. sonusai/doc.py +10 -10
  12. sonusai/genft.py +81 -91
  13. sonusai/genmetrics.py +51 -61
  14. sonusai/genmix.py +105 -115
  15. sonusai/genmixdb.py +201 -174
  16. sonusai/lsdb.py +56 -66
  17. sonusai/main.py +23 -20
  18. sonusai/metrics/__init__.py +2 -0
  19. sonusai/metrics/calc_audio_stats.py +29 -24
  20. sonusai/metrics/calc_class_weights.py +7 -7
  21. sonusai/metrics/calc_optimal_thresholds.py +5 -7
  22. sonusai/metrics/calc_pcm.py +3 -3
  23. sonusai/metrics/calc_pesq.py +10 -7
  24. sonusai/metrics/calc_phase_distance.py +3 -3
  25. sonusai/metrics/calc_sa_sdr.py +10 -8
  26. sonusai/metrics/calc_segsnr_f.py +16 -18
  27. sonusai/metrics/calc_speech.py +105 -47
  28. sonusai/metrics/calc_wer.py +35 -32
  29. sonusai/metrics/calc_wsdr.py +10 -7
  30. sonusai/metrics/class_summary.py +30 -27
  31. sonusai/metrics/confusion_matrix_summary.py +25 -22
  32. sonusai/metrics/one_hot.py +91 -57
  33. sonusai/metrics/snr_summary.py +53 -46
  34. sonusai/mixture/__init__.py +20 -14
  35. sonusai/mixture/audio.py +4 -6
  36. sonusai/mixture/augmentation.py +37 -43
  37. sonusai/mixture/class_count.py +5 -14
  38. sonusai/mixture/config.py +292 -225
  39. sonusai/mixture/constants.py +41 -30
  40. sonusai/mixture/data_io.py +155 -0
  41. sonusai/mixture/datatypes.py +111 -108
  42. sonusai/mixture/db_datatypes.py +54 -70
  43. sonusai/mixture/eq_rule_is_valid.py +6 -9
  44. sonusai/mixture/feature.py +40 -38
  45. sonusai/mixture/generation.py +522 -389
  46. sonusai/mixture/helpers.py +217 -272
  47. sonusai/mixture/log_duration_and_sizes.py +16 -13
  48. sonusai/mixture/mixdb.py +669 -477
  49. sonusai/mixture/soundfile_audio.py +12 -17
  50. sonusai/mixture/sox_audio.py +91 -112
  51. sonusai/mixture/sox_augmentation.py +8 -9
  52. sonusai/mixture/spectral_mask.py +4 -6
  53. sonusai/mixture/target_class_balancing.py +41 -36
  54. sonusai/mixture/targets.py +69 -67
  55. sonusai/mixture/tokenized_shell_vars.py +23 -23
  56. sonusai/mixture/torchaudio_audio.py +14 -15
  57. sonusai/mixture/torchaudio_augmentation.py +23 -27
  58. sonusai/mixture/truth.py +48 -26
  59. sonusai/mixture/truth_functions/__init__.py +26 -0
  60. sonusai/mixture/truth_functions/crm.py +56 -38
  61. sonusai/mixture/truth_functions/datatypes.py +37 -0
  62. sonusai/mixture/truth_functions/energy.py +85 -59
  63. sonusai/mixture/truth_functions/file.py +30 -30
  64. sonusai/mixture/truth_functions/phoneme.py +14 -7
  65. sonusai/mixture/truth_functions/sed.py +71 -45
  66. sonusai/mixture/truth_functions/target.py +69 -106
  67. sonusai/mkwav.py +58 -101
  68. sonusai/onnx_predict.py +46 -43
  69. sonusai/queries/__init__.py +3 -1
  70. sonusai/queries/queries.py +100 -59
  71. sonusai/speech/__init__.py +2 -0
  72. sonusai/speech/l2arctic.py +24 -23
  73. sonusai/speech/librispeech.py +16 -17
  74. sonusai/speech/mcgill.py +22 -21
  75. sonusai/speech/textgrid.py +32 -25
  76. sonusai/speech/timit.py +45 -42
  77. sonusai/speech/vctk.py +14 -13
  78. sonusai/speech/voxceleb.py +26 -20
  79. sonusai/summarize_metric_spenh.py +11 -10
  80. sonusai/utils/__init__.py +4 -3
  81. sonusai/utils/asl_p56.py +1 -1
  82. sonusai/utils/asr.py +37 -17
  83. sonusai/utils/asr_functions/__init__.py +2 -0
  84. sonusai/utils/asr_functions/aaware_whisper.py +18 -12
  85. sonusai/utils/audio_devices.py +12 -12
  86. sonusai/utils/braced_glob.py +6 -8
  87. sonusai/utils/calculate_input_shape.py +1 -4
  88. sonusai/utils/compress.py +2 -2
  89. sonusai/utils/convert_string_to_number.py +1 -3
  90. sonusai/utils/create_timestamp.py +1 -1
  91. sonusai/utils/create_ts_name.py +2 -2
  92. sonusai/utils/dataclass_from_dict.py +1 -1
  93. sonusai/utils/docstring.py +6 -6
  94. sonusai/utils/energy_f.py +9 -7
  95. sonusai/utils/engineering_number.py +56 -54
  96. sonusai/utils/get_label_names.py +8 -10
  97. sonusai/utils/human_readable_size.py +2 -2
  98. sonusai/utils/model_utils.py +3 -5
  99. sonusai/utils/numeric_conversion.py +2 -4
  100. sonusai/utils/onnx_utils.py +43 -32
  101. sonusai/utils/parallel.py +41 -30
  102. sonusai/utils/print_mixture_details.py +25 -22
  103. sonusai/utils/ranges.py +12 -12
  104. sonusai/utils/read_predict_data.py +11 -9
  105. sonusai/utils/reshape.py +19 -26
  106. sonusai/utils/seconds_to_hms.py +1 -1
  107. sonusai/utils/stacked_complex.py +8 -16
  108. sonusai/utils/stratified_shuffle_split.py +29 -27
  109. sonusai/utils/write_audio.py +2 -2
  110. sonusai/utils/yes_or_no.py +3 -3
  111. sonusai/vars.py +14 -14
  112. {sonusai-0.18.9.dist-info → sonusai-0.19.6.dist-info}/METADATA +20 -21
  113. sonusai-0.19.6.dist-info/RECORD +125 -0
  114. {sonusai-0.18.9.dist-info → sonusai-0.19.6.dist-info}/WHEEL +1 -1
  115. sonusai/mixture/truth_functions/data.py +0 -58
  116. sonusai/utils/read_mixture_data.py +0 -14
  117. sonusai-0.18.9.dist-info/RECORD +0 -125
  118. {sonusai-0.18.9.dist-info → sonusai-0.19.6.dist-info}/entry_points.txt +0 -0
sonusai/genft.py CHANGED
@@ -15,20 +15,19 @@ Inputs:
15
15
  MIXID A glob of mixture ID(s) to generate.
16
16
 
17
17
  Outputs the following to the mixture database directory:
18
- <id>.h5:
19
- dataset: feature
20
- dataset: truth_f
21
- dataset: segsnr (optional)
22
- <id>.txt
18
+ <id>
19
+ feature.pkl
20
+ truth_f.pkl
21
+ segsnr.pkl (optional)
22
+ metadata.txt
23
23
  genft.log
24
24
 
25
25
  """
26
+
26
27
  import signal
27
- from dataclasses import dataclass
28
28
 
29
- from sonusai.mixture import GenFTData
30
29
  from sonusai.mixture import GeneralizedIDs
31
- from sonusai.mixture import MixtureDatabase
30
+ from sonusai.mixture import GenFTData
32
31
 
33
32
 
34
33
  def signal_handler(_sig, _frame):
@@ -36,90 +35,71 @@ def signal_handler(_sig, _frame):
36
35
 
37
36
  from sonusai import logger
38
37
 
39
- logger.info('Canceled due to keyboard interrupt')
38
+ logger.info("Canceled due to keyboard interrupt")
40
39
  sys.exit(1)
41
40
 
42
41
 
43
42
  signal.signal(signal.SIGINT, signal_handler)
44
43
 
45
44
 
46
- @dataclass
47
- class MPGlobal:
48
- mixdb: MixtureDatabase = None
49
- compute_truth: bool = None
50
- compute_segsnr: bool = None
51
- force: bool = None
52
- write: bool = None
53
-
54
-
55
- MP_GLOBAL = MPGlobal()
56
-
57
-
58
- def genft(mixdb: MixtureDatabase,
59
- mixids: GeneralizedIDs = None,
60
- compute_truth: bool = True,
61
- compute_segsnr: bool = False,
62
- write: bool = False,
63
- show_progress: bool = False,
64
- force: bool = True) -> list[GenFTData]:
65
- from tqdm import tqdm
45
+ def genft(
46
+ location: str,
47
+ mixids: GeneralizedIDs = "*",
48
+ compute_truth: bool = True,
49
+ compute_segsnr: bool = False,
50
+ write: bool = False,
51
+ show_progress: bool = False,
52
+ force: bool = True,
53
+ ) -> list[GenFTData]:
54
+ from functools import partial
66
55
 
67
- from sonusai.utils import pp_tqdm_imap
56
+ from sonusai.mixture import MixtureDatabase
57
+ from sonusai.utils import par_track
58
+ from sonusai.utils import track
68
59
 
60
+ mixdb = MixtureDatabase(location)
69
61
  mixids = mixdb.mixids_to_list(mixids)
70
62
 
71
- progress = tqdm(total=len(mixids), disable=not show_progress)
72
- results = pp_tqdm_imap(_genft_kernel,
73
- mixids,
74
- initializer=_genft_initializer,
75
- initargs=(mixdb.location, compute_truth, compute_segsnr, force, write),
76
- progress=progress)
63
+ progress = track(total=len(mixids), disable=not show_progress)
64
+ results = par_track(
65
+ partial(_genft_kernel, location=location, compute_truth=compute_truth, compute_segsnr=compute_segsnr, force=force, write=write),
66
+ mixids,
67
+ progress=progress,
68
+ )
77
69
  progress.close()
78
70
 
79
71
  return results
80
72
 
81
73
 
82
- def _genft_initializer(location: str,
83
- compute_truth: bool,
84
- compute_segsnr: bool,
85
- force: bool,
86
- write: bool) -> None:
87
- MP_GLOBAL.mixdb = MixtureDatabase(location)
88
- MP_GLOBAL.compute_truth = compute_truth
89
- MP_GLOBAL.compute_segsnr = compute_segsnr
90
- MP_GLOBAL.force = force
91
- MP_GLOBAL.write = write
92
-
74
+ def _genft_kernel(m_id: int, location: str, compute_truth: bool, compute_segsnr: bool, force: bool, write: bool) -> GenFTData:
75
+ from typing import Any
93
76
 
94
- def _genft_kernel(m_id: int) -> GenFTData:
95
- from sonusai.mixture import write_mixture_data
77
+ from sonusai.mixture import MixtureDatabase
78
+ from sonusai.mixture import write_cached_data
96
79
  from sonusai.mixture import write_mixture_metadata
97
80
 
98
- mixdb = MP_GLOBAL.mixdb
99
- compute_truth = MP_GLOBAL.compute_truth
100
- compute_segsnr = MP_GLOBAL.compute_segsnr
101
- force = MP_GLOBAL.force
102
- write = MP_GLOBAL.write
81
+ mixdb = MixtureDatabase(location)
82
+
83
+ result = GenFTData()
103
84
 
104
85
  feature, truth_f = mixdb.mixture_ft(m_id=m_id, force=force)
105
- write_data = [('feature', feature)]
86
+ write_data: list[tuple[str, Any]] = [("feature", feature)]
87
+ result.feature = feature
106
88
 
107
89
  if compute_truth:
108
- write_data.append(('truth_f', truth_f))
109
- else:
110
- truth_f = None
90
+ write_data.append(("truth_f", truth_f))
91
+ result.truth_f = truth_f
111
92
 
112
93
  if compute_segsnr:
113
94
  segsnr = mixdb.mixture_segsnr(m_id=m_id, force=force)
114
- write_data.append(('segsnr', segsnr))
115
- else:
116
- segsnr = None
95
+ write_data.append(("segsnr", segsnr))
96
+ result.segsnr = segsnr
117
97
 
118
98
  if write:
119
- write_mixture_data(mixdb, mixdb.mixture(m_id), write_data)
99
+ write_cached_data(mixdb.location, "mixture", mixdb.mixture(m_id).name, write_data)
120
100
  write_mixture_metadata(mixdb, mixdb.mixture(m_id))
121
101
 
122
- return GenFTData(feature=feature, truth_f=truth_f, segsnr=segsnr)
102
+ return result
123
103
 
124
104
 
125
105
  def main() -> None:
@@ -137,57 +117,67 @@ def main() -> None:
137
117
  from sonusai import initial_log_messages
138
118
  from sonusai import logger
139
119
  from sonusai import update_console_handler
120
+ from sonusai.mixture import MixtureDatabase
140
121
  from sonusai.mixture import check_audio_files_exist
141
122
  from sonusai.utils import human_readable_size
142
123
  from sonusai.utils import seconds_to_hms
143
124
 
144
- verbose = args['--verbose']
145
- mixids = args['--mixid']
146
- compute_segsnr = args['--segsnr']
147
- location = args['LOC']
125
+ verbose = args["--verbose"]
126
+ mixids = args["--mixid"]
127
+ compute_segsnr = args["--segsnr"]
128
+ location = args["LOC"]
148
129
 
149
130
  start_time = time.monotonic()
150
131
 
151
- create_file_handler(join(location, 'genft.log'))
132
+ create_file_handler(join(location, "genft.log"))
152
133
  update_console_handler(verbose)
153
- initial_log_messages('genft')
134
+ initial_log_messages("genft")
154
135
 
155
- logger.info(f'Load mixture database from {location}')
136
+ logger.info(f"Load mixture database from {location}")
156
137
  mixdb = MixtureDatabase(location)
157
138
  mixids = mixdb.mixids_to_list(mixids)
158
139
 
159
140
  total_samples = mixdb.total_samples(mixids)
160
141
  duration = total_samples / sonusai.mixture.SAMPLE_RATE
161
- total_transform_frames = total_samples // mixdb.ft_config.R
142
+ total_transform_frames = total_samples // mixdb.ft_config.overlap
162
143
  total_feature_frames = total_samples // mixdb.feature_step_samples
163
144
 
164
- logger.info('')
165
- logger.info(f'Found {len(mixids):,} mixtures to process')
166
- logger.info(f'{total_samples:,} samples, '
167
- f'{total_transform_frames:,} transform frames, '
168
- f'{total_feature_frames:,} feature frames')
145
+ logger.info("")
146
+ logger.info(f"Found {len(mixids):,} mixtures to process")
147
+ logger.info(
148
+ f"{total_samples:,} samples, "
149
+ f"{total_transform_frames:,} transform frames, "
150
+ f"{total_feature_frames:,} feature frames"
151
+ )
169
152
 
170
153
  check_audio_files_exist(mixdb)
171
154
 
172
- genft(mixdb=mixdb,
173
- mixids=mixids,
174
- compute_segsnr=compute_segsnr,
175
- write=True,
176
- show_progress=True)
177
-
178
- logger.info(f'Wrote {len(mixids)} mixtures to {location}')
179
- logger.info('')
180
- logger.info(f'Duration: {seconds_to_hms(seconds=duration)}')
155
+ try:
156
+ genft(
157
+ location=location,
158
+ mixids=mixids,
159
+ compute_segsnr=compute_segsnr,
160
+ write=True,
161
+ show_progress=True,
162
+ )
163
+ except Exception as e:
164
+ logger.debug(e)
165
+ raise
166
+
167
+ logger.info(f"Wrote {len(mixids)} mixtures to {location}")
168
+ logger.info("")
169
+ logger.info(f"Duration: {seconds_to_hms(seconds=duration)}")
181
170
  logger.info(
182
- f'feature: {human_readable_size(total_feature_frames * mixdb.fg_stride * mixdb.feature_parameters * 4, 1)}')
183
- logger.info(f'truth_f: {human_readable_size(total_feature_frames * mixdb.num_classes * 4, 1)}')
171
+ f"feature: {human_readable_size(total_feature_frames * mixdb.fg_stride * mixdb.feature_parameters * 4, 1)}"
172
+ )
173
+ logger.info(f"truth_f: {human_readable_size(total_feature_frames * mixdb.num_classes * 4, 1)}")
184
174
  if compute_segsnr:
185
- logger.info(f'segsnr: {human_readable_size(total_transform_frames * 4, 1)}')
175
+ logger.info(f"segsnr: {human_readable_size(total_transform_frames * 4, 1)}")
186
176
 
187
177
  end_time = time.monotonic()
188
- logger.info(f'Completed in {seconds_to_hms(seconds=end_time - start_time)}')
189
- logger.info('')
178
+ logger.info(f"Completed in {seconds_to_hms(seconds=end_time - start_time)}")
179
+ logger.info("")
190
180
 
191
181
 
192
- if __name__ == '__main__':
182
+ if __name__ == "__main__":
193
183
  main()
sonusai/genmetrics.py CHANGED
@@ -32,10 +32,8 @@ Generate all available metrics except for mxwer.faster:
32
32
  > sonusai genmetrics -x"mxwer.faster" mixdb_loc
33
33
 
34
34
  """
35
- import signal
36
- from dataclasses import dataclass
37
35
 
38
- from sonusai.mixture import MixtureDatabase
36
+ import signal
39
37
 
40
38
 
41
39
  def signal_handler(_sig, _frame):
@@ -43,132 +41,124 @@ def signal_handler(_sig, _frame):
43
41
 
44
42
  from sonusai import logger
45
43
 
46
- logger.info('Canceled due to keyboard interrupt')
44
+ logger.info("Canceled due to keyboard interrupt")
47
45
  sys.exit(1)
48
46
 
49
47
 
50
48
  signal.signal(signal.SIGINT, signal_handler)
51
49
 
52
50
 
53
- @dataclass
54
- class MPGlobal:
55
- mixdb: MixtureDatabase = None
56
- metrics: set[str] = None
57
-
58
-
59
- MP_GLOBAL = MPGlobal()
60
-
51
+ def _process_mixture(mixid: int, location: str, metrics: list[str]) -> None:
52
+ from sonusai.mixture import MixtureDatabase
53
+ from sonusai.mixture import write_cached_data
61
54
 
62
- def _initializer(location: str, metrics: set[str]) -> None:
63
- MP_GLOBAL.mixdb = MixtureDatabase(location)
64
- MP_GLOBAL.metrics = metrics
65
-
66
-
67
- def _process_mixture(mixid: int) -> None:
68
- from sonusai.mixture import write_mixture_data
69
-
70
- mixdb = MP_GLOBAL.mixdb
71
- metrics = list(MP_GLOBAL.metrics)
55
+ mixdb = MixtureDatabase(location)
72
56
 
73
57
  values = mixdb.mixture_metrics(m_id=mixid, metrics=metrics, force=True)
74
- write_data = list(zip(metrics, values))
58
+ write_data = list(zip(metrics, values, strict=False))
75
59
 
76
- write_mixture_data(mixdb, mixdb.mixture(mixid), write_data)
60
+ write_cached_data(mixdb.location, "mixture", mixdb.mixture(mixid).name, write_data)
77
61
 
78
62
 
79
63
  def main() -> None:
80
64
  from docopt import docopt
81
65
 
82
66
  import sonusai
67
+ from sonusai.mixture import MixtureDatabase
83
68
  from sonusai.utils import trim_docstring
84
69
 
85
70
  args = docopt(trim_docstring(__doc__), version=sonusai.__version__, options_first=True)
86
71
 
87
- verbose = args['--verbose']
88
- mixids = args['--mixid']
89
- includes = [x.strip() for x in args['--include'].lower().split(',')]
90
- excludes = [x.strip() for x in args['--exclude'].lower().split(',')]
91
- show_supported = args['--supported']
92
- location = args['LOC']
72
+ verbose = args["--verbose"]
73
+ mixids = args["--mixid"]
74
+ includes = [x.strip() for x in args["--include"].lower().split(",")]
75
+ excludes = [x.strip() for x in args["--exclude"].lower().split(",")]
76
+ show_supported = args["--supported"]
77
+ location = args["LOC"]
93
78
 
94
79
  import sys
95
80
  import time
81
+ from functools import partial
96
82
  from os.path import join
97
83
 
98
84
  from sonusai import create_file_handler
99
85
  from sonusai import initial_log_messages
100
86
  from sonusai import logger
101
87
  from sonusai import update_console_handler
102
- from sonusai.utils import pp_tqdm_imap
88
+ from sonusai.utils import par_track
103
89
  from sonusai.utils import seconds_to_hms
104
- from tqdm import tqdm
90
+ from sonusai.utils import track
91
+
92
+ # TODO: Check config.yml for changes to asr_configs and update mixdb
93
+ # TODO: Support globs for metrics (includes and excludes)
105
94
 
106
95
  start_time = time.monotonic()
107
96
 
108
97
  # Setup logging file
109
- create_file_handler(join(location, 'genmetrics.log'))
98
+ create_file_handler(join(location, "genmetrics.log"))
110
99
  update_console_handler(verbose)
111
- initial_log_messages('genmetrics')
100
+ initial_log_messages("genmetrics")
112
101
 
113
- logger.info(f'Load mixture database from {location}')
102
+ logger.info(f"Load mixture database from {location}")
114
103
 
115
104
  mixdb = MixtureDatabase(location)
116
105
  supported = mixdb.supported_metrics
117
106
  if show_supported:
118
- logger.info(f'\nSupported metrics:\n\n{supported.pretty}')
107
+ logger.info(f"\nSupported metrics:\n\n{supported.pretty}")
119
108
  sys.exit(0)
120
109
 
121
- if includes is None or 'all' in includes:
110
+ if includes is None or "all" in includes:
122
111
  metrics = supported.names
123
112
  else:
124
113
  metrics = set(includes)
125
- if 'mxwer' in metrics:
126
- metrics.remove('mxwer')
114
+ if "mxwer" in metrics:
115
+ metrics.remove("mxwer")
127
116
  for name in mixdb.asr_configs:
128
- metrics.add(f'mxwer.{name}')
117
+ metrics.add(f"mxwer.{name}")
129
118
 
130
119
  diff = metrics.difference(supported.names)
131
120
  if diff:
132
- logger.error(f'Unrecognized metric: {", ".join(diff)}')
121
+ logger.error(f"Unrecognized metric: {', '.join(diff)}")
133
122
  sys.exit(1)
134
123
 
135
- if excludes is None or 'none' in excludes:
136
- _excludes = set([])
124
+ if excludes is None or "none" in excludes:
125
+ _excludes = set()
137
126
  else:
138
127
  _excludes = set(excludes)
139
- if 'mxwer' in _excludes:
140
- _excludes.remove('mxwer')
128
+ if "mxwer" in _excludes:
129
+ _excludes.remove("mxwer")
141
130
  for name in mixdb.asr_configs:
142
- _excludes.add(f'mxwer.{name}')
131
+ _excludes.add(f"mxwer.{name}")
143
132
 
144
133
  diff = _excludes.difference(supported.names)
145
134
  if diff:
146
- logger.error(f'Unrecognized metric: {", ".join(diff)}')
135
+ logger.error(f"Unrecognized metric: {', '.join(diff)}")
147
136
  sys.exit(1)
148
137
 
149
138
  for exclude in _excludes:
150
139
  metrics.discard(exclude)
151
140
 
152
- logger.info(f'Generating metrics: {", ".join(metrics)}')
141
+ logger.info(f"Generating metrics: {', '.join(metrics)}")
153
142
 
154
143
  mixids = mixdb.mixids_to_list(mixids)
155
- logger.info('')
156
- logger.info(f'Found {len(mixids):,} mixtures to process')
157
-
158
- progress = tqdm(total=len(mixids), desc='genmetrics')
159
- pp_tqdm_imap(_process_mixture, mixids,
160
- progress=progress,
161
- initializer=_initializer,
162
- initargs=(location, metrics))
144
+ logger.info("")
145
+ logger.info(f"Found {len(mixids):,} mixtures to process")
146
+
147
+ progress = track(total=len(mixids), desc="genmetrics")
148
+ par_track(
149
+ partial(_process_mixture, location=location, metrics=list(metrics)),
150
+ mixids,
151
+ progress=progress,
152
+ )
163
153
  progress.close()
164
154
 
165
- logger.info(f'Wrote metrics for {len(mixids)} mixtures to {location}')
166
- logger.info('')
155
+ logger.info(f"Wrote metrics for {len(mixids)} mixtures to {location}")
156
+ logger.info("")
167
157
 
168
158
  end_time = time.monotonic()
169
- logger.info(f'Completed in {seconds_to_hms(seconds=end_time - start_time)}')
170
- logger.info('')
159
+ logger.info(f"Completed in {seconds_to_hms(seconds=end_time - start_time)}")
160
+ logger.info("")
171
161
 
172
162
 
173
- if __name__ == '__main__':
163
+ if __name__ == "__main__":
174
164
  main()