sonusai 0.18.9__py3-none-any.whl → 0.19.5__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 +93 -77
  13. sonusai/genmetrics.py +59 -46
  14. sonusai/genmix.py +116 -104
  15. sonusai/genmixdb.py +194 -153
  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 +15 -17
  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 +19 -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 +52 -85
  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 +40 -27
  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.5.dist-info}/METADATA +20 -21
  113. sonusai-0.19.5.dist-info/RECORD +125 -0
  114. {sonusai-0.18.9.dist-info → sonusai-0.19.5.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.5.dist-info}/entry_points.txt +0 -0
sonusai/genft.py CHANGED
@@ -15,19 +15,20 @@ 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
28
  from dataclasses import dataclass
28
29
 
29
- from sonusai.mixture import GenFTData
30
30
  from sonusai.mixture import GeneralizedIDs
31
+ from sonusai.mixture import GenFTData
31
32
  from sonusai.mixture import MixtureDatabase
32
33
 
33
34
 
@@ -36,7 +37,7 @@ def signal_handler(_sig, _frame):
36
37
 
37
38
  from sonusai import logger
38
39
 
39
- logger.info('Canceled due to keyboard interrupt')
40
+ logger.info("Canceled due to keyboard interrupt")
40
41
  sys.exit(1)
41
42
 
42
43
 
@@ -45,81 +46,87 @@ signal.signal(signal.SIGINT, signal_handler)
45
46
 
46
47
  @dataclass
47
48
  class MPGlobal:
48
- mixdb: MixtureDatabase = None
49
- compute_truth: bool = None
50
- compute_segsnr: bool = None
51
- force: bool = None
52
- write: bool = None
49
+ mixdb: MixtureDatabase
50
+ compute_truth: bool
51
+ compute_segsnr: bool
52
+ force: bool
53
+ write: bool
53
54
 
54
55
 
55
- MP_GLOBAL = MPGlobal()
56
+ MP_GLOBAL: MPGlobal
56
57
 
57
58
 
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
66
-
67
- from sonusai.utils import pp_tqdm_imap
59
+ def genft(
60
+ mixdb: MixtureDatabase,
61
+ mixids: GeneralizedIDs = "*",
62
+ compute_truth: bool = True,
63
+ compute_segsnr: bool = False,
64
+ write: bool = False,
65
+ show_progress: bool = False,
66
+ force: bool = True,
67
+ ) -> list[GenFTData]:
68
+ from sonusai.utils import par_track
69
+ from sonusai.utils import track
68
70
 
69
71
  mixids = mixdb.mixids_to_list(mixids)
70
72
 
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)
73
+ progress = track(total=len(mixids), disable=not show_progress)
74
+ results = par_track(
75
+ _genft_kernel,
76
+ mixids,
77
+ initializer=_genft_initializer,
78
+ initargs=(mixdb.location, compute_truth, compute_segsnr, force, write),
79
+ progress=progress,
80
+ )
77
81
  progress.close()
78
82
 
79
83
  return results
80
84
 
81
85
 
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
86
+ def _genft_initializer(location: str, compute_truth: bool, compute_segsnr: bool, force: bool, write: bool) -> None:
87
+ global MP_GLOBAL
88
+
89
+ MP_GLOBAL = MPGlobal(
90
+ mixdb=MixtureDatabase(location),
91
+ compute_truth=compute_truth,
92
+ compute_segsnr=compute_segsnr,
93
+ force=force,
94
+ write=write,
95
+ )
92
96
 
93
97
 
94
98
  def _genft_kernel(m_id: int) -> GenFTData:
95
- from sonusai.mixture import write_mixture_data
99
+ from sonusai.mixture import write_cached_data
96
100
  from sonusai.mixture import write_mixture_metadata
97
101
 
102
+ global MP_GLOBAL
103
+
98
104
  mixdb = MP_GLOBAL.mixdb
99
105
  compute_truth = MP_GLOBAL.compute_truth
100
106
  compute_segsnr = MP_GLOBAL.compute_segsnr
101
107
  force = MP_GLOBAL.force
102
108
  write = MP_GLOBAL.write
103
109
 
110
+ result = GenFTData()
111
+
104
112
  feature, truth_f = mixdb.mixture_ft(m_id=m_id, force=force)
105
- write_data = [('feature', feature)]
113
+ write_data = [("feature", feature)]
114
+ result.feature = feature
106
115
 
107
116
  if compute_truth:
108
- write_data.append(('truth_f', truth_f))
109
- else:
110
- truth_f = None
117
+ write_data.append(("truth_f", truth_f))
118
+ result.truth_f = truth_f
111
119
 
112
120
  if compute_segsnr:
113
121
  segsnr = mixdb.mixture_segsnr(m_id=m_id, force=force)
114
- write_data.append(('segsnr', segsnr))
115
- else:
116
- segsnr = None
122
+ write_data.append(("segsnr", segsnr))
123
+ result.segsnr = segsnr
117
124
 
118
125
  if write:
119
- write_mixture_data(mixdb, mixdb.mixture(m_id), write_data)
126
+ write_cached_data(mixdb.location, "mixture", mixdb.mixture(m_id).name, write_data)
120
127
  write_mixture_metadata(mixdb, mixdb.mixture(m_id))
121
128
 
122
- return GenFTData(feature=feature, truth_f=truth_f, segsnr=segsnr)
129
+ return result
123
130
 
124
131
 
125
132
  def main() -> None:
@@ -141,53 +148,62 @@ def main() -> None:
141
148
  from sonusai.utils import human_readable_size
142
149
  from sonusai.utils import seconds_to_hms
143
150
 
144
- verbose = args['--verbose']
145
- mixids = args['--mixid']
146
- compute_segsnr = args['--segsnr']
147
- location = args['LOC']
151
+ verbose = args["--verbose"]
152
+ mixids = args["--mixid"]
153
+ compute_segsnr = args["--segsnr"]
154
+ location = args["LOC"]
148
155
 
149
156
  start_time = time.monotonic()
150
157
 
151
- create_file_handler(join(location, 'genft.log'))
158
+ create_file_handler(join(location, "genft.log"))
152
159
  update_console_handler(verbose)
153
- initial_log_messages('genft')
160
+ initial_log_messages("genft")
154
161
 
155
- logger.info(f'Load mixture database from {location}')
162
+ logger.info(f"Load mixture database from {location}")
156
163
  mixdb = MixtureDatabase(location)
157
164
  mixids = mixdb.mixids_to_list(mixids)
158
165
 
159
166
  total_samples = mixdb.total_samples(mixids)
160
167
  duration = total_samples / sonusai.mixture.SAMPLE_RATE
161
- total_transform_frames = total_samples // mixdb.ft_config.R
168
+ total_transform_frames = total_samples // mixdb.ft_config.overlap
162
169
  total_feature_frames = total_samples // mixdb.feature_step_samples
163
170
 
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')
171
+ logger.info("")
172
+ logger.info(f"Found {len(mixids):,} mixtures to process")
173
+ logger.info(
174
+ f"{total_samples:,} samples, "
175
+ f"{total_transform_frames:,} transform frames, "
176
+ f"{total_feature_frames:,} feature frames"
177
+ )
169
178
 
170
179
  check_audio_files_exist(mixdb)
171
180
 
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)}')
181
+ try:
182
+ genft(
183
+ mixdb=mixdb,
184
+ mixids=mixids,
185
+ compute_segsnr=compute_segsnr,
186
+ write=True,
187
+ show_progress=True,
188
+ )
189
+ except Exception as e:
190
+ logger.debug(e)
191
+ raise
192
+
193
+ logger.info(f"Wrote {len(mixids)} mixtures to {location}")
194
+ logger.info("")
195
+ logger.info(f"Duration: {seconds_to_hms(seconds=duration)}")
181
196
  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)}')
197
+ f"feature: {human_readable_size(total_feature_frames * mixdb.fg_stride * mixdb.feature_parameters * 4, 1)}"
198
+ )
199
+ logger.info(f"truth_f: {human_readable_size(total_feature_frames * mixdb.num_classes * 4, 1)}")
184
200
  if compute_segsnr:
185
- logger.info(f'segsnr: {human_readable_size(total_transform_frames * 4, 1)}')
201
+ logger.info(f"segsnr: {human_readable_size(total_transform_frames * 4, 1)}")
186
202
 
187
203
  end_time = time.monotonic()
188
- logger.info(f'Completed in {seconds_to_hms(seconds=end_time - start_time)}')
189
- logger.info('')
204
+ logger.info(f"Completed in {seconds_to_hms(seconds=end_time - start_time)}")
205
+ logger.info("")
190
206
 
191
207
 
192
- if __name__ == '__main__':
208
+ if __name__ == "__main__":
193
209
  main()
sonusai/genmetrics.py CHANGED
@@ -32,6 +32,7 @@ Generate all available metrics except for mxwer.faster:
32
32
  > sonusai genmetrics -x"mxwer.faster" mixdb_loc
33
33
 
34
34
  """
35
+
35
36
  import signal
36
37
  from dataclasses import dataclass
37
38
 
@@ -43,7 +44,7 @@ def signal_handler(_sig, _frame):
43
44
 
44
45
  from sonusai import logger
45
46
 
46
- logger.info('Canceled due to keyboard interrupt')
47
+ logger.info("Canceled due to keyboard interrupt")
47
48
  sys.exit(1)
48
49
 
49
50
 
@@ -52,28 +53,34 @@ signal.signal(signal.SIGINT, signal_handler)
52
53
 
53
54
  @dataclass
54
55
  class MPGlobal:
55
- mixdb: MixtureDatabase = None
56
- metrics: set[str] = None
56
+ mixdb: MixtureDatabase
57
+ metrics: set[str]
57
58
 
58
59
 
59
- MP_GLOBAL = MPGlobal()
60
+ MP_GLOBAL: MPGlobal
60
61
 
61
62
 
62
63
  def _initializer(location: str, metrics: set[str]) -> None:
63
- MP_GLOBAL.mixdb = MixtureDatabase(location)
64
- MP_GLOBAL.metrics = metrics
64
+ global MP_GLOBAL
65
+
66
+ MP_GLOBAL = MPGlobal(
67
+ mixdb=MixtureDatabase(location),
68
+ metrics=metrics,
69
+ )
65
70
 
66
71
 
67
72
  def _process_mixture(mixid: int) -> None:
68
- from sonusai.mixture import write_mixture_data
73
+ from sonusai.mixture import write_cached_data
74
+
75
+ global MP_GLOBAL
69
76
 
70
77
  mixdb = MP_GLOBAL.mixdb
71
78
  metrics = list(MP_GLOBAL.metrics)
72
79
 
73
80
  values = mixdb.mixture_metrics(m_id=mixid, metrics=metrics, force=True)
74
- write_data = list(zip(metrics, values))
81
+ write_data = list(zip(metrics, values, strict=False))
75
82
 
76
- write_mixture_data(mixdb, mixdb.mixture(mixid), write_data)
83
+ write_cached_data(mixdb.location, "mixture", mixdb.mixture(mixid).name, write_data)
77
84
 
78
85
 
79
86
  def main() -> None:
@@ -84,12 +91,12 @@ def main() -> None:
84
91
 
85
92
  args = docopt(trim_docstring(__doc__), version=sonusai.__version__, options_first=True)
86
93
 
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']
94
+ verbose = args["--verbose"]
95
+ mixids = args["--mixid"]
96
+ includes = [x.strip() for x in args["--include"].lower().split(",")]
97
+ excludes = [x.strip() for x in args["--exclude"].lower().split(",")]
98
+ show_supported = args["--supported"]
99
+ location = args["LOC"]
93
100
 
94
101
  import sys
95
102
  import time
@@ -99,76 +106,82 @@ def main() -> None:
99
106
  from sonusai import initial_log_messages
100
107
  from sonusai import logger
101
108
  from sonusai import update_console_handler
102
- from sonusai.utils import pp_tqdm_imap
109
+ from sonusai.utils import par_track
103
110
  from sonusai.utils import seconds_to_hms
104
- from tqdm import tqdm
111
+ from sonusai.utils import track
112
+
113
+ # TODO: Check config.yml for changes to asr_configs and update mixdb
114
+ # TODO: Support globs for metrics (includes and excludes)
105
115
 
106
116
  start_time = time.monotonic()
107
117
 
108
118
  # Setup logging file
109
- create_file_handler(join(location, 'genmetrics.log'))
119
+ create_file_handler(join(location, "genmetrics.log"))
110
120
  update_console_handler(verbose)
111
- initial_log_messages('genmetrics')
121
+ initial_log_messages("genmetrics")
112
122
 
113
- logger.info(f'Load mixture database from {location}')
123
+ logger.info(f"Load mixture database from {location}")
114
124
 
115
125
  mixdb = MixtureDatabase(location)
116
126
  supported = mixdb.supported_metrics
117
127
  if show_supported:
118
- logger.info(f'\nSupported metrics:\n\n{supported.pretty}')
128
+ logger.info(f"\nSupported metrics:\n\n{supported.pretty}")
119
129
  sys.exit(0)
120
130
 
121
- if includes is None or 'all' in includes:
131
+ if includes is None or "all" in includes:
122
132
  metrics = supported.names
123
133
  else:
124
134
  metrics = set(includes)
125
- if 'mxwer' in metrics:
126
- metrics.remove('mxwer')
135
+ if "mxwer" in metrics:
136
+ metrics.remove("mxwer")
127
137
  for name in mixdb.asr_configs:
128
- metrics.add(f'mxwer.{name}')
138
+ metrics.add(f"mxwer.{name}")
129
139
 
130
140
  diff = metrics.difference(supported.names)
131
141
  if diff:
132
- logger.error(f'Unrecognized metric: {", ".join(diff)}')
142
+ logger.error(f"Unrecognized metric: {', '.join(diff)}")
133
143
  sys.exit(1)
134
144
 
135
- if excludes is None or 'none' in excludes:
136
- _excludes = set([])
145
+ if excludes is None or "none" in excludes:
146
+ _excludes = set()
137
147
  else:
138
148
  _excludes = set(excludes)
139
- if 'mxwer' in _excludes:
140
- _excludes.remove('mxwer')
149
+ if "mxwer" in _excludes:
150
+ _excludes.remove("mxwer")
141
151
  for name in mixdb.asr_configs:
142
- _excludes.add(f'mxwer.{name}')
152
+ _excludes.add(f"mxwer.{name}")
143
153
 
144
154
  diff = _excludes.difference(supported.names)
145
155
  if diff:
146
- logger.error(f'Unrecognized metric: {", ".join(diff)}')
156
+ logger.error(f"Unrecognized metric: {', '.join(diff)}")
147
157
  sys.exit(1)
148
158
 
149
159
  for exclude in _excludes:
150
160
  metrics.discard(exclude)
151
161
 
152
- logger.info(f'Generating metrics: {", ".join(metrics)}')
162
+ logger.info(f"Generating metrics: {', '.join(metrics)}")
153
163
 
154
164
  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))
165
+ logger.info("")
166
+ logger.info(f"Found {len(mixids):,} mixtures to process")
167
+
168
+ progress = track(total=len(mixids), desc="genmetrics")
169
+ par_track(
170
+ _process_mixture,
171
+ mixids,
172
+ progress=progress,
173
+ initializer=_initializer,
174
+ initargs=(location, metrics),
175
+ )
163
176
  progress.close()
164
177
 
165
- logger.info(f'Wrote metrics for {len(mixids)} mixtures to {location}')
166
- logger.info('')
178
+ logger.info(f"Wrote metrics for {len(mixids)} mixtures to {location}")
179
+ logger.info("")
167
180
 
168
181
  end_time = time.monotonic()
169
- logger.info(f'Completed in {seconds_to_hms(seconds=end_time - start_time)}')
170
- logger.info('')
182
+ logger.info(f"Completed in {seconds_to_hms(seconds=end_time - start_time)}")
183
+ logger.info("")
171
184
 
172
185
 
173
- if __name__ == '__main__':
186
+ if __name__ == "__main__":
174
187
  main()