sonusai 1.0.16__cp311-abi3-macosx_10_12_x86_64.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 (150) hide show
  1. sonusai/__init__.py +170 -0
  2. sonusai/aawscd_probwrite.py +148 -0
  3. sonusai/audiofe.py +481 -0
  4. sonusai/calc_metric_spenh.py +1136 -0
  5. sonusai/config/__init__.py +0 -0
  6. sonusai/config/asr.py +21 -0
  7. sonusai/config/config.py +65 -0
  8. sonusai/config/config.yml +49 -0
  9. sonusai/config/constants.py +53 -0
  10. sonusai/config/ir.py +124 -0
  11. sonusai/config/ir_delay.py +62 -0
  12. sonusai/config/source.py +275 -0
  13. sonusai/config/spectral_masks.py +15 -0
  14. sonusai/config/truth.py +64 -0
  15. sonusai/constants.py +14 -0
  16. sonusai/data/__init__.py +0 -0
  17. sonusai/data/silero_vad_v5.1.jit +0 -0
  18. sonusai/data/silero_vad_v5.1.onnx +0 -0
  19. sonusai/data/speech_ma01_01.wav +0 -0
  20. sonusai/data/whitenoise.wav +0 -0
  21. sonusai/datatypes.py +383 -0
  22. sonusai/deprecated/gentcst.py +632 -0
  23. sonusai/deprecated/plot.py +519 -0
  24. sonusai/deprecated/tplot.py +365 -0
  25. sonusai/doc.py +52 -0
  26. sonusai/doc_strings/__init__.py +1 -0
  27. sonusai/doc_strings/doc_strings.py +531 -0
  28. sonusai/genft.py +196 -0
  29. sonusai/genmetrics.py +183 -0
  30. sonusai/genmix.py +199 -0
  31. sonusai/genmixdb.py +235 -0
  32. sonusai/ir_metric.py +551 -0
  33. sonusai/lsdb.py +141 -0
  34. sonusai/main.py +134 -0
  35. sonusai/metrics/__init__.py +43 -0
  36. sonusai/metrics/calc_audio_stats.py +42 -0
  37. sonusai/metrics/calc_class_weights.py +90 -0
  38. sonusai/metrics/calc_optimal_thresholds.py +73 -0
  39. sonusai/metrics/calc_pcm.py +45 -0
  40. sonusai/metrics/calc_pesq.py +36 -0
  41. sonusai/metrics/calc_phase_distance.py +43 -0
  42. sonusai/metrics/calc_sa_sdr.py +64 -0
  43. sonusai/metrics/calc_sample_weights.py +25 -0
  44. sonusai/metrics/calc_segsnr_f.py +82 -0
  45. sonusai/metrics/calc_speech.py +382 -0
  46. sonusai/metrics/calc_wer.py +71 -0
  47. sonusai/metrics/calc_wsdr.py +57 -0
  48. sonusai/metrics/calculate_metrics.py +395 -0
  49. sonusai/metrics/class_summary.py +74 -0
  50. sonusai/metrics/confusion_matrix_summary.py +75 -0
  51. sonusai/metrics/one_hot.py +283 -0
  52. sonusai/metrics/snr_summary.py +128 -0
  53. sonusai/metrics_summary.py +314 -0
  54. sonusai/mixture/__init__.py +15 -0
  55. sonusai/mixture/audio.py +187 -0
  56. sonusai/mixture/class_balancing.py +103 -0
  57. sonusai/mixture/constants.py +3 -0
  58. sonusai/mixture/data_io.py +173 -0
  59. sonusai/mixture/db.py +169 -0
  60. sonusai/mixture/db_datatypes.py +92 -0
  61. sonusai/mixture/effects.py +344 -0
  62. sonusai/mixture/feature.py +78 -0
  63. sonusai/mixture/generation.py +1116 -0
  64. sonusai/mixture/helpers.py +351 -0
  65. sonusai/mixture/ir_effects.py +77 -0
  66. sonusai/mixture/log_duration_and_sizes.py +23 -0
  67. sonusai/mixture/mixdb.py +1857 -0
  68. sonusai/mixture/pad_audio.py +35 -0
  69. sonusai/mixture/resample.py +7 -0
  70. sonusai/mixture/sox_effects.py +195 -0
  71. sonusai/mixture/sox_help.py +650 -0
  72. sonusai/mixture/spectral_mask.py +51 -0
  73. sonusai/mixture/truth.py +61 -0
  74. sonusai/mixture/truth_functions/__init__.py +45 -0
  75. sonusai/mixture/truth_functions/crm.py +105 -0
  76. sonusai/mixture/truth_functions/energy.py +222 -0
  77. sonusai/mixture/truth_functions/file.py +48 -0
  78. sonusai/mixture/truth_functions/metadata.py +24 -0
  79. sonusai/mixture/truth_functions/metrics.py +28 -0
  80. sonusai/mixture/truth_functions/phoneme.py +18 -0
  81. sonusai/mixture/truth_functions/sed.py +98 -0
  82. sonusai/mixture/truth_functions/target.py +142 -0
  83. sonusai/mkwav.py +135 -0
  84. sonusai/onnx_predict.py +363 -0
  85. sonusai/parse/__init__.py +0 -0
  86. sonusai/parse/expand.py +156 -0
  87. sonusai/parse/parse_source_directive.py +129 -0
  88. sonusai/parse/rand.py +214 -0
  89. sonusai/py.typed +0 -0
  90. sonusai/queries/__init__.py +0 -0
  91. sonusai/queries/queries.py +239 -0
  92. sonusai/rs.abi3.so +0 -0
  93. sonusai/rs.pyi +1 -0
  94. sonusai/rust/__init__.py +0 -0
  95. sonusai/speech/__init__.py +0 -0
  96. sonusai/speech/l2arctic.py +121 -0
  97. sonusai/speech/librispeech.py +102 -0
  98. sonusai/speech/mcgill.py +71 -0
  99. sonusai/speech/textgrid.py +89 -0
  100. sonusai/speech/timit.py +138 -0
  101. sonusai/speech/types.py +12 -0
  102. sonusai/speech/vctk.py +53 -0
  103. sonusai/speech/voxceleb.py +108 -0
  104. sonusai/utils/__init__.py +3 -0
  105. sonusai/utils/asl_p56.py +130 -0
  106. sonusai/utils/asr.py +91 -0
  107. sonusai/utils/asr_functions/__init__.py +3 -0
  108. sonusai/utils/asr_functions/aaware_whisper.py +69 -0
  109. sonusai/utils/audio_devices.py +50 -0
  110. sonusai/utils/braced_glob.py +50 -0
  111. sonusai/utils/calculate_input_shape.py +26 -0
  112. sonusai/utils/choice.py +51 -0
  113. sonusai/utils/compress.py +25 -0
  114. sonusai/utils/convert_string_to_number.py +6 -0
  115. sonusai/utils/create_timestamp.py +5 -0
  116. sonusai/utils/create_ts_name.py +14 -0
  117. sonusai/utils/dataclass_from_dict.py +27 -0
  118. sonusai/utils/db.py +16 -0
  119. sonusai/utils/docstring.py +53 -0
  120. sonusai/utils/energy_f.py +44 -0
  121. sonusai/utils/engineering_number.py +166 -0
  122. sonusai/utils/evaluate_random_rule.py +15 -0
  123. sonusai/utils/get_frames_per_batch.py +2 -0
  124. sonusai/utils/get_label_names.py +20 -0
  125. sonusai/utils/grouper.py +6 -0
  126. sonusai/utils/human_readable_size.py +7 -0
  127. sonusai/utils/keyboard_interrupt.py +12 -0
  128. sonusai/utils/load_object.py +21 -0
  129. sonusai/utils/max_text_width.py +9 -0
  130. sonusai/utils/model_utils.py +28 -0
  131. sonusai/utils/numeric_conversion.py +11 -0
  132. sonusai/utils/onnx_utils.py +155 -0
  133. sonusai/utils/parallel.py +162 -0
  134. sonusai/utils/path_info.py +7 -0
  135. sonusai/utils/print_mixture_details.py +60 -0
  136. sonusai/utils/rand.py +13 -0
  137. sonusai/utils/ranges.py +43 -0
  138. sonusai/utils/read_predict_data.py +32 -0
  139. sonusai/utils/reshape.py +154 -0
  140. sonusai/utils/seconds_to_hms.py +7 -0
  141. sonusai/utils/stacked_complex.py +82 -0
  142. sonusai/utils/stratified_shuffle_split.py +170 -0
  143. sonusai/utils/tokenized_shell_vars.py +143 -0
  144. sonusai/utils/write_audio.py +26 -0
  145. sonusai/utils/yes_or_no.py +8 -0
  146. sonusai/vars.py +47 -0
  147. sonusai-1.0.16.dist-info/METADATA +56 -0
  148. sonusai-1.0.16.dist-info/RECORD +150 -0
  149. sonusai-1.0.16.dist-info/WHEEL +4 -0
  150. sonusai-1.0.16.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,365 @@
1
+ # mypy: ignore-errors
2
+ """sonusai tplot
3
+
4
+ usage: tplot [-hv] [-r ROOT] [-c CONFIG] [-t TARGET] [-m MODEL] [-f FEATURE] [--sedthr SEDTHR]
5
+
6
+ options:
7
+ -h, --help
8
+ -v, --verbose Be verbose.
9
+ -r, --root ROOT Root of a gentcst tree.
10
+ -c, --config CONFIG YAML config file.
11
+ -t, --target TARGET Target .wav or .txt, else use target section in CONFIG.
12
+ -m, --model MODEL Aaware ONNX model file.
13
+ -f, --feature FEATURE Feature override, e.g., gfh64to128.
14
+ --sedthr SEDTHR SED thresholds override, e.g., '[-24, -27, -30]'.
15
+
16
+ CONFIG is used to override the default configuration, thus it does not need to be a complete
17
+ genmixdb config parameter set, only desired overrides like truth function and truth config.
18
+
19
+ A TARGET .txt file supports the same format as SonusAI genmixdb which is a list of regexes
20
+ for finding sound files.
21
+
22
+ ROOT, CONFIG, and TARGET are optional, but at least one of them must be specified.
23
+ Behavior is as follows in order of precedence:
24
+
25
+ 1) If ROOT is provided, use the given directory as the root directory of
26
+ a gentcst tree. The config will be generated from the top down to the current leaf.
27
+ 2) If CONFIG is provided, use the given YAML file to override the config.
28
+ 3) If TARGET is provided, use the given .wav or .txt file to override the target
29
+ section of the config.
30
+ 4) If FEATURE and/or SEDTHR are provided, use them to override the config.
31
+
32
+ If TARGET is given without a CONFIG, look for a corresponding YAML file to use as a
33
+ config. For example,
34
+
35
+ sonusai tplot -t 4-esc50-dogbark.txt
36
+
37
+ will first look for '4-esc50-dogbark.yml' and then for 'config.yml'. If neither
38
+ candidate was found and ROOT was also not specified then give an error. If
39
+ ROOT was specified then use the hierarchical config.
40
+
41
+ A multi-page plot TARGET-tplot.pdf or CONFIG-tplot.pdf is generated.
42
+
43
+ """
44
+
45
+ import signal
46
+
47
+
48
+ def signal_handler(_sig, _frame):
49
+ import sys
50
+
51
+ from sonusai import logger
52
+
53
+ logger.info("Canceled due to keyboard interrupt")
54
+ sys.exit(1)
55
+
56
+
57
+ signal.signal(signal.SIGINT, signal_handler)
58
+
59
+
60
+ # TODO: re-work for modern mixdb API
61
+ def tplot(
62
+ root: str | None = None,
63
+ config_file: str | None = None,
64
+ target_file: str | None = None,
65
+ model_file: str | None = None,
66
+ feature: str | None = None,
67
+ thresholds: str | None = None,
68
+ verbose: bool = False,
69
+ ) -> None:
70
+ import json
71
+ import os
72
+
73
+ import matplotlib.pyplot as plt
74
+ import numpy as np
75
+ import yaml
76
+ from matplotlib.backends.backend_pdf import PdfPages
77
+ from pyaaware import Predict
78
+
79
+ import sonusai
80
+ from sonusai import SonusAIError
81
+ from sonusai import logger
82
+ from sonusai.genft import genft
83
+ from sonusai.genmix import genmix
84
+ from sonusai.genmixdb import genmixdb
85
+ from sonusai.mixture import get_default_config
86
+ from sonusai.mixture import update_config_from_file
87
+ from sonusai.mixture import update_config_from_hierarchy
88
+
89
+ figsize = (11, 8.5)
90
+
91
+ if config_file is None and target_file is None and root is None:
92
+ raise SonusAIError("Error: No config provided.")
93
+
94
+ target_path = ""
95
+ config = get_default_config()
96
+
97
+ if root is not None:
98
+ leaf = os.getcwd()
99
+ target_path = os.path.basename(leaf)
100
+ config = update_config_from_hierarchy(root=root, leaf=leaf, config=config)
101
+ logger.debug(f"Hierarchical config for {leaf} using {root} as the root")
102
+
103
+ if config_file is not None:
104
+ target_path = config_file
105
+ config = update_config_from_file(config_file, config)
106
+ logger.debug(f"Config from {config_file}")
107
+
108
+ if target_file is not None:
109
+ target_path = target_file
110
+ if not os.path.exists(target_file):
111
+ raise SonusAIError(f"{target_file} does not exist.")
112
+
113
+ config["targets"] = [{"name": target_file}]
114
+ logger.debug(f"Targets from {target_file}")
115
+
116
+ if config_file is None:
117
+ target_config = f"{os.path.splitext(target_file)[0]}.yml"
118
+ if os.path.exists(target_config):
119
+ config = update_config_from_file(target_config, config)
120
+ logger.debug(f"Config from {target_config}")
121
+ else:
122
+ target_config = "config.yml"
123
+ if os.path.exists(target_config):
124
+ config = update_config_from_file(target_config, config)
125
+ logger.debug(f"Config from {target_config}")
126
+ elif root is None:
127
+ raise SonusAIError(f"Error: Could not determine config for {target_file}.")
128
+
129
+ file_base = os.path.splitext(target_path)[0]
130
+ file_name = os.path.split(file_base)[1]
131
+ output = f"./{file_name}-tplot.pdf"
132
+
133
+ if len(config["truth_settings"]) > 1:
134
+ raise SonusAIError("Number of truth_settings is more than one. This is not supported yet.")
135
+
136
+ if thresholds is not None:
137
+ thresholds = json.loads(thresholds)
138
+ if thresholds != config["truth_settings"][0]["config"]["thresholds"]:
139
+ config["truth_settings"][0]["config"]["thresholds"] = thresholds
140
+ logger.debug(f"Override SED thresholds with {thresholds}")
141
+
142
+ if feature is not None and feature != config["feature"]:
143
+ config["feature"] = feature
144
+ logger.debug(f"Override feature with {feature}")
145
+
146
+ logger.debug("")
147
+
148
+ # Run genmixdb, genmix, and genft
149
+ mixdb = genmixdb(config=config, logging=verbose)
150
+ num_mixtures = mixdb.num_mixtures # Number of mixtures
151
+ logger.info(f"Generating data for {num_mixtures} mixture plots")
152
+ audio_data = genmix(
153
+ mixdb=mixdb,
154
+ compute_segsnr=False,
155
+ compute_truth=False,
156
+ )
157
+ feature_data = genft(mixdb=mixdb, compute_segsnr=False)
158
+
159
+ # If model provided, read and check it
160
+ predict_data = np.zeros(0)
161
+ if model_file is not None:
162
+ import onnx
163
+
164
+ # model is an in-memory ModelProto
165
+ model = onnx.load(model_file)
166
+ if len(model.metadata_props) < 5:
167
+ logger.warn("Model metadata indicates this is not an Aaware model, ignoring.")
168
+ else:
169
+ if model.metadata_props[4].key != "feature":
170
+ logger.warn("Model metadata does not have Aaware feature, ignoring.")
171
+ else:
172
+ model_feature = model.metadata_props[4].value
173
+ logger.debug(f"Model feature is {model_feature}")
174
+ # TODO Check and read other params, flatten, addch, etc.
175
+ logger.info(f"Running prediction with {model_file}")
176
+ predict = Predict(model_file)
177
+ predict_data = predict.execute(feature_data.feature)
178
+
179
+ num_samples = audio_data.mixture.shape[0] # Total number of samples over all mixtures
180
+ num_features = feature_data.feature.shape[0] # Total number of feature frames over all mixtures
181
+
182
+ logger.info(f"Plotting {num_mixtures} target-truth results to {output}")
183
+ pdf = PdfPages(f"{output}")
184
+ for m in range(num_mixtures):
185
+ mixture_begin = mixdb["mixtures"][m]["i_sample_offset"]
186
+ feature_begin = mixdb["mixtures"][m]["o_frame_offset"]
187
+ # For each target/mixture, get index endpoint (mix,noise,target sample,...)
188
+ if m == num_mixtures - 1:
189
+ mixture_end = num_samples
190
+ feature_end = num_features
191
+ else:
192
+ mixture_end = mixdb["mixtures"][m + 1]["i_sample_offset"]
193
+ # out frames are possibly decimated/stride-combined
194
+ feature_end = mixdb["mixtures"][m + 1]["o_frame_offset"]
195
+
196
+ # Trim waveform data
197
+ mixture_trimmed = audio_data.mixture[mixture_begin:mixture_end]
198
+ target_trimmed = sum(audio_data.targets)[mixture_begin:mixture_end]
199
+
200
+ # Provide subset defined by mixture using truth_index array of indices (multichannel truth)
201
+ target_record = mixdb["targets"][mixdb["mixtures"][m]["target_id"]]
202
+ truth_settings = target_record["truth_settings"]
203
+ if len(truth_settings) > 1:
204
+ raise SonusAIError("Number of truth_settings is more than one. This is not supported yet.")
205
+
206
+ truth_index = np.array(truth_settings[0]["index"]) - 1
207
+ truth_f_trimmed = feature_data.truth_f[feature_begin:feature_end, truth_index]
208
+
209
+ if predict_data.shape[0] > 0:
210
+ predict_data_trimmed = predict_data[feature_begin:feature_end, :]
211
+ # Prediction Activity analysis to select top prediction class
212
+ # true if active in any frame
213
+ predict_activity = np.any(predict_data_trimmed >= mixdb["class_weights_threshold"], axis=0)
214
+ predict_activity_index = np.array([i for i, x in enumerate(predict_activity) if x]) + 1
215
+ logger.info(
216
+ f'Prediction active in classes based on threshold {mixdb["class_weights_threshold"]}:\n'
217
+ f'{predict_activity_index}'
218
+ )
219
+ predict_mean = np.mean(predict_data_trimmed, axis=0)
220
+ top_active_classes = np.argsort(predict_mean)[::-1] + 1
221
+ logger.info(f"Top 10 active prediction classes by mean:\n{top_active_classes[0:10]}")
222
+ # plot most active prediction
223
+ predict_data_trimmed = predict_data_trimmed[:, top_active_classes[0] - 1]
224
+ logger.info(f"Plotting prediction class {top_active_classes[0]}")
225
+
226
+ # Setup plot of target waveform with truth on top
227
+ # TODO
228
+ # Make a function w/args mixture_trimmed, target_trimmed, truth_f, pr, mixdat, m, truth_index, target_path
229
+ # calculate number of samples per frame for plotting
230
+ num_plot_features = truth_f_trimmed.shape[0]
231
+ num_plot_samples_per_feature = len(target_trimmed) // num_plot_features
232
+ # number of plot samples multiple of frames
233
+ num_plot_samples = num_plot_samples_per_feature * num_plot_features
234
+ # x-axis in sec
235
+ x_seconds = np.arange(num_plot_samples, dtype=np.float32) / sonusai.mixture.SAMPLE_RATE
236
+ # Reshape/extend truth to #samples in waveform
237
+ num_plot_classes = truth_f_trimmed.shape[1] # Number of plot truth classes
238
+ y_truth_f = np.reshape(
239
+ np.tile(np.expand_dims(truth_f_trimmed, 1), [1, num_plot_samples_per_feature, 1]),
240
+ [num_plot_samples, num_plot_classes],
241
+ )
242
+
243
+ fig, ax0 = plt.subplots(1, 1, constrained_layout=True, figsize=figsize)
244
+ ax = np.array([ax0], dtype=object)
245
+ plots = []
246
+
247
+ # Plot the time-domain waveforms then truth/prediction on second axis
248
+ if mixture_trimmed.shape[0] > 0:
249
+ color = "mistyrose"
250
+ (mix_plot,) = ax[0].plot(x_seconds, mixture_trimmed[0:num_plot_samples], color=color, label="MIX")
251
+ ax[0].tick_params(axis="y", labelcolor="red")
252
+ plots.append(mix_plot)
253
+
254
+ if target_trimmed.shape[0] > 0:
255
+ color = "tab:blue"
256
+ (tt_plot,) = ax[0].plot(x_seconds, target_trimmed[0:num_plot_samples], color=color, label="TAR")
257
+ ax[0].set_ylabel("ampl", color=color)
258
+ ax[0].tick_params(axis="y", labelcolor=color)
259
+ plots.append(tt_plot)
260
+
261
+ ax2 = ax[0].twinx() # instantiate 2nd y-axis that shares the same x-axis
262
+
263
+ # Plot first truth
264
+ # TODO Support multi-channel
265
+ if truth_f_trimmed.shape[0] > 0:
266
+ color = "tab:green"
267
+ label2 = f"truth{truth_index[0] + 1}"
268
+ # we already handled the x-label with ax1
269
+ ax2.set_ylabel(label2, color=color)
270
+ # logger.info(f'Mixture num {m}, truth_index={truth_index}')
271
+ (tr_plot,) = ax2.plot(x_seconds, y_truth_f[:, 0], color=color, label=label2)
272
+ ax2.set_ylim([-0.05, 1.05])
273
+ ax2.tick_params(axis="y", labelcolor=color)
274
+ plots.append(tr_plot)
275
+
276
+ if predict_data.shape[0] > 0:
277
+ color = "tab:brown"
278
+ label2 = f"prcl{top_active_classes[0]}"
279
+ # we already handled the x-label with ax1
280
+ ax2.set_ylabel(label2, color=color)
281
+ predict_extended = np.reshape(
282
+ np.tile(
283
+ np.expand_dims(predict_data_trimmed, 1),
284
+ [1, num_plot_samples_per_feature, 1],
285
+ ),
286
+ [num_plot_samples, num_plot_classes],
287
+ )
288
+ (pr_plot,) = ax2.plot(x_seconds, predict_extended, color=color, label=label2)
289
+ ax2.set_ylim([-0.05, 1.05])
290
+ ax2.tick_params(axis="y", labelcolor=color)
291
+ plots.append(pr_plot)
292
+
293
+ ax[0].set_xlabel("time (s)") # set only on last/bottom plot
294
+
295
+ # Get actual mixture target config parameters
296
+ target_augmentations = mixdb["target_augmentations"][mixdb["mixtures"][m]["target_augmentation_index"]]
297
+ fig.suptitle(
298
+ f'{m + 1} of {num_mixtures}: {target_path}\n'
299
+ f'{target_record["name"]}\n'
300
+ f'Target augmentations: {target_augmentations}\n'
301
+ f'Truth indices: {truth_settings[0]["index"]}\n'
302
+ f'Global Truth Function:Config {truth_settings[0]["function"]} : {truth_settings[0]["config"]}',
303
+ fontsize=10,
304
+ )
305
+ pdf.savefig(fig)
306
+ plt.close(fig)
307
+
308
+ # open config file read in as text, then print to last page
309
+ last_page = plt.figure(figsize=figsize)
310
+ last_page.clf()
311
+
312
+ option_text = (
313
+ f"Function parameters:\n"
314
+ f" root {root}\n"
315
+ f" config {config_file}\n"
316
+ f" target {target_file}\n"
317
+ f" model {model_file}\n"
318
+ f" feature {feature}\n"
319
+ f" sedthr {thresholds}\n\n"
320
+ f"----------------------------------------\n\n"
321
+ )
322
+ last_page.text(
323
+ 0.05,
324
+ 0.95,
325
+ option_text + yaml.dump(config),
326
+ transform=last_page.transFigure,
327
+ family="monospace",
328
+ size=10,
329
+ ha="left",
330
+ va="top",
331
+ )
332
+ pdf.savefig()
333
+ plt.close()
334
+ pdf.close()
335
+
336
+
337
+ def main() -> None:
338
+ from docopt import docopt
339
+
340
+ import sonusai
341
+ from sonusai import create_file_handler
342
+ from sonusai import initial_log_messages
343
+ from sonusai import update_console_handler
344
+ from sonusai.utils.docstring import trim_docstring
345
+
346
+ args = docopt(trim_docstring(__doc__), version=sonusai.__version__, options_first=True)
347
+
348
+ verbose = args["--verbose"]
349
+ create_file_handler("tplot.log")
350
+ update_console_handler(verbose)
351
+ initial_log_messages("tplot")
352
+
353
+ tplot(
354
+ root=args["--root"],
355
+ config_file=args["--config"],
356
+ target_file=args["--target"],
357
+ model_file=args["--model"],
358
+ feature=args["--feature"],
359
+ thresholds=args["--sedthr"],
360
+ verbose=verbose,
361
+ )
362
+
363
+
364
+ if __name__ == "__main__":
365
+ main()
sonusai/doc.py ADDED
@@ -0,0 +1,52 @@
1
+ """sonusai doc
2
+
3
+ usage: doc [-h] [TOPIC]
4
+
5
+ options:
6
+ -h, --help Display this help.
7
+
8
+ Show SonusAI documentation.
9
+
10
+ """
11
+
12
+
13
+ def main() -> None:
14
+ from docopt import docopt
15
+
16
+ from sonusai import __version__ as sai_version
17
+ from sonusai.utils.docstring import trim_docstring
18
+
19
+ args = docopt(trim_docstring(__doc__), version=sai_version, options_first=True)
20
+
21
+ from sonusai import doc_strings
22
+
23
+ topic = args["TOPIC"]
24
+
25
+ print(f"SonusAI {sai_version} Documentation")
26
+ print("")
27
+
28
+ topics = sorted([item[4:] for item in dir(doc_strings) if item.startswith("doc_")])
29
+
30
+ if topic not in topics:
31
+ if topic is not None:
32
+ print(f"Unknown topic: {topic}")
33
+ print("")
34
+
35
+ print("Available topics:")
36
+ for item in topics:
37
+ print(f" {item}")
38
+ return
39
+
40
+ text = getattr(doc_strings, "doc_" + topic)()
41
+ print(text[1:])
42
+
43
+
44
+ if __name__ == "__main__":
45
+ from sonusai import exception_handler
46
+ from sonusai.utils.keyboard_interrupt import register_keyboard_interrupt
47
+
48
+ register_keyboard_interrupt()
49
+ try:
50
+ main()
51
+ except Exception as e:
52
+ exception_handler(e)
@@ -0,0 +1 @@
1
+ from .doc_strings import * # noqa: F403