phonoscape 0.1.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.
- phonoscape/__init__.py +74 -0
- phonoscape/__main__.py +157 -0
- phonoscape/data/parse.py +500 -0
- phonoscape/data/process.py +324 -0
- phonoscape/data/spectra.py +390 -0
- phonoscape/lproc/lp_default.py +5 -0
- phonoscape/lproc/lp_export_vals.py +5 -0
- phonoscape/lproc/lp_extents.py +5 -0
- phonoscape/lproc/lp_find_gest.py +526 -0
- phonoscape/lproc/lp_peaks.py +5 -0
- phonoscape/lproc/lp_phase_ang.py +5 -0
- phonoscape/lproc/lp_snap_ex.py +5 -0
- phonoscape/lproc/protocol.py +204 -0
- phonoscape/menu/data_menu.py +103 -0
- phonoscape/menu/file_menu.py +266 -0
- phonoscape/menu/label_menu.py +235 -0
- phonoscape/menu/menu_bar.py +34 -0
- phonoscape/menu/movement_menu.py +190 -0
- phonoscape/menu/play_menu.py +44 -0
- phonoscape/menu/selection_menu.py +63 -0
- phonoscape/menu/view_menu.py +187 -0
- phonoscape/modals/common_scaling_modal.py +155 -0
- phonoscape/modals/edit_labels_modal.py +137 -0
- phonoscape/modals/label_modal.py +143 -0
- phonoscape/modals/movement_config_modal.py +87 -0
- phonoscape/modals/spatial_view_modal.py +109 -0
- phonoscape/modals/spectral_analysis_modal.py +285 -0
- phonoscape/modals/temporal_config_modal.py +600 -0
- phonoscape/state.py +201 -0
- phonoscape/views/cursor_spect_view.py +153 -0
- phonoscape/views/spatial_view_2d.py +224 -0
- phonoscape/views/spatial_view_3d.py +276 -0
- phonoscape/views/temporal_view.py +577 -0
- phonoscape/views/zoomed_audio_view.py +118 -0
- phonoscape/widgets/play_button.py +79 -0
- phonoscape/widgets/readout.py +58 -0
- phonoscape/window.py +305 -0
- phonoscape-0.1.0.dist-info/METADATA +15 -0
- phonoscape-0.1.0.dist-info/RECORD +42 -0
- phonoscape-0.1.0.dist-info/WHEEL +5 -0
- phonoscape-0.1.0.dist-info/licenses/LICENSE +21 -0
- phonoscape-0.1.0.dist-info/top_level.txt +1 -0
phonoscape/__init__.py
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Unpack
|
|
4
|
+
from PySide6.QtWidgets import QApplication
|
|
5
|
+
import matplotlib.pyplot as plt
|
|
6
|
+
|
|
7
|
+
from .data.parse import load_variables, normalize_args, import_proc_ctor, CmdArgs
|
|
8
|
+
from .window import VarWindow, WindowManager
|
|
9
|
+
from .lproc.protocol import LabelProcedure
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def phonoscape(file: str, variables: str = "*", **kwargs: Unpack[CmdArgs]) -> None:
|
|
13
|
+
plt.style.use("dark_background")
|
|
14
|
+
|
|
15
|
+
path = Path(file)
|
|
16
|
+
data, other_data, dimensions = load_variables(
|
|
17
|
+
path, variables, comps=kwargs.get("comps")
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
if not data:
|
|
21
|
+
raise ValueError(f"No matching variables found for pattern {variables!r}")
|
|
22
|
+
|
|
23
|
+
app_config, temporal_disp_specs, colors = normalize_args(
|
|
24
|
+
path, kwargs, data, other_data, dimensions
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
selected_variable = next(iter(data.keys()))
|
|
28
|
+
|
|
29
|
+
head_s = (kwargs.get("head") or 0) / 1000
|
|
30
|
+
tail_s = (kwargs.get("tail") or data[selected_variable].duration_s * 1000) / 1000
|
|
31
|
+
tail_s = min(tail_s, data[selected_variable].duration_s)
|
|
32
|
+
if head_s < 0:
|
|
33
|
+
raise ValueError(
|
|
34
|
+
f"--head must be a non-negative number of milliseconds, but got {head_s * 1000}"
|
|
35
|
+
)
|
|
36
|
+
if tail_s < 0:
|
|
37
|
+
raise ValueError(
|
|
38
|
+
f"--tail must be a non-negative number of milliseconds, but got {tail_s * 1000}"
|
|
39
|
+
)
|
|
40
|
+
if head_s >= tail_s:
|
|
41
|
+
raise ValueError(
|
|
42
|
+
f"--head must be less than --tail, but got head={head_s * 1000} and tail={tail_s * 1000}"
|
|
43
|
+
)
|
|
44
|
+
elif tail_s - head_s < 0.025:
|
|
45
|
+
raise ValueError(
|
|
46
|
+
f"The duration of the selection (tail - head) must be at least 25 milliseconds, but got head={head_s * 1000} and tail={tail_s * 1000} ({(tail_s - head_s) * 1000:.1f} ms)"
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
lproc_ctor_path = kwargs.get("lproc") or "phonoscape.lproc.lp_default"
|
|
50
|
+
lproc_ctor: type[LabelProcedure] = import_proc_ctor(lproc_ctor_path, "lp")
|
|
51
|
+
|
|
52
|
+
app = QApplication.instance()
|
|
53
|
+
owns_app = app is None
|
|
54
|
+
|
|
55
|
+
if app is None:
|
|
56
|
+
app = QApplication(sys.argv)
|
|
57
|
+
|
|
58
|
+
window_manager = WindowManager(lproc_ctor=lproc_ctor)
|
|
59
|
+
window = VarWindow(
|
|
60
|
+
window_manager=window_manager,
|
|
61
|
+
selected_variable=selected_variable,
|
|
62
|
+
temporal_disp_specs=temporal_disp_specs,
|
|
63
|
+
lproc_ctor=lproc_ctor,
|
|
64
|
+
colors=colors,
|
|
65
|
+
app_config=app_config,
|
|
66
|
+
view=kwargs.get("view") or (0, -90, 0),
|
|
67
|
+
head_s=head_s,
|
|
68
|
+
tail_s=tail_s,
|
|
69
|
+
custom={},
|
|
70
|
+
)
|
|
71
|
+
window.show()
|
|
72
|
+
|
|
73
|
+
if owns_app:
|
|
74
|
+
sys.exit(app.exec())
|
phonoscape/__main__.py
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
from typing import cast
|
|
2
|
+
from . import phonoscape
|
|
3
|
+
|
|
4
|
+
if __name__ == "__main__":
|
|
5
|
+
import argparse
|
|
6
|
+
|
|
7
|
+
# [ ] CONFIG
|
|
8
|
+
# [ ] DPROC
|
|
9
|
+
# [x] FTRAJ
|
|
10
|
+
# [x] HEAD
|
|
11
|
+
# [ ] LABELS
|
|
12
|
+
# [ ] LPROC
|
|
13
|
+
# [x] IS3D
|
|
14
|
+
# [x] MAP / TEMPMAP
|
|
15
|
+
# [x] PALATE
|
|
16
|
+
# [x] PHARYNX
|
|
17
|
+
# [ ] PPROC
|
|
18
|
+
# [x] SEX
|
|
19
|
+
# [x] SPLINE
|
|
20
|
+
# [ ] SPREAD
|
|
21
|
+
# [x] TAIL
|
|
22
|
+
# [x] SPATEX
|
|
23
|
+
# [x] VIEW
|
|
24
|
+
# [x] NAME
|
|
25
|
+
# [x] VLIST
|
|
26
|
+
# [x] VLSEL
|
|
27
|
+
# [x] SPECLIM
|
|
28
|
+
|
|
29
|
+
parser = argparse.ArgumentParser(
|
|
30
|
+
description="PhonoScape: Visualize acoustics & articulatory data."
|
|
31
|
+
)
|
|
32
|
+
parser.add_argument("file", type=str, help="Path to the .mat file to visualize.")
|
|
33
|
+
parser.add_argument(
|
|
34
|
+
"variables",
|
|
35
|
+
type=str,
|
|
36
|
+
nargs="?",
|
|
37
|
+
default="*",
|
|
38
|
+
help="Glob pattern to filter variables (default: '*').",
|
|
39
|
+
)
|
|
40
|
+
parser.add_argument(
|
|
41
|
+
"--palate",
|
|
42
|
+
type=str,
|
|
43
|
+
metavar="VAR",
|
|
44
|
+
help="Variable name for palate trace (optional).",
|
|
45
|
+
)
|
|
46
|
+
parser.add_argument(
|
|
47
|
+
"--pharynx",
|
|
48
|
+
type=str,
|
|
49
|
+
metavar="VAR",
|
|
50
|
+
help="Variable name for pharynx trace (optional).",
|
|
51
|
+
)
|
|
52
|
+
parser.add_argument(
|
|
53
|
+
"--spline",
|
|
54
|
+
type=str,
|
|
55
|
+
nargs="+",
|
|
56
|
+
metavar="TRAJ",
|
|
57
|
+
help="List of trajectory names to apply spline interpolation (default: all spatial trajectories starting with 'T').",
|
|
58
|
+
)
|
|
59
|
+
parser.add_argument(
|
|
60
|
+
"--polyline-spline",
|
|
61
|
+
action="store_true",
|
|
62
|
+
help="Connect the --spline points with a polyline instead of a smooth spline.",
|
|
63
|
+
)
|
|
64
|
+
parser.add_argument(
|
|
65
|
+
"--audio",
|
|
66
|
+
type=str,
|
|
67
|
+
metavar="TRAJ",
|
|
68
|
+
help="Variable name for audio trajectory - for spectrogram plotting and playback (default: first scalar trajectory with sampling rate > 1000 Hz).",
|
|
69
|
+
)
|
|
70
|
+
parser.add_argument(
|
|
71
|
+
"--framing",
|
|
72
|
+
type=str,
|
|
73
|
+
metavar="TRAJ",
|
|
74
|
+
help="Variable name for framing trajectory (default: --audio, or first trajectory if no audio found).",
|
|
75
|
+
)
|
|
76
|
+
parser.add_argument(
|
|
77
|
+
"--temporal-display",
|
|
78
|
+
type=str,
|
|
79
|
+
metavar="SPEC",
|
|
80
|
+
nargs="+",
|
|
81
|
+
help="List of variable names to include in temporal display (default: all plus {--audio}_SPECT).",
|
|
82
|
+
)
|
|
83
|
+
parser.add_argument(
|
|
84
|
+
"--spatial-exclude",
|
|
85
|
+
type=str,
|
|
86
|
+
nargs="+",
|
|
87
|
+
metavar="TRAJ",
|
|
88
|
+
help="List of trajectory names to exclude from the spatial view (default: none).",
|
|
89
|
+
)
|
|
90
|
+
parser.add_argument(
|
|
91
|
+
"--comps",
|
|
92
|
+
type=int,
|
|
93
|
+
nargs="+",
|
|
94
|
+
metavar=("N|COL", "COL"),
|
|
95
|
+
help="Number of dimensions for spatial trajectories, or list of column indices to use for each dimension (default: all dimensions, up to 3, are used for spatial view in x,y,z order).",
|
|
96
|
+
)
|
|
97
|
+
parser.add_argument(
|
|
98
|
+
"--view",
|
|
99
|
+
type=float,
|
|
100
|
+
nargs=3,
|
|
101
|
+
metavar=("ELEV", "AZIM", "ROLL"),
|
|
102
|
+
help="Initial view angles (degrees) for the 3D spatial display: azimuth, elevation and roll. Only has an effect when the data is 3D. Only has an effect on the first opened window; subsequent windows inherit the opening window's view (default: 0, -90, 0).",
|
|
103
|
+
)
|
|
104
|
+
parser.add_argument(
|
|
105
|
+
"--head",
|
|
106
|
+
type=float,
|
|
107
|
+
metavar="MS",
|
|
108
|
+
help="Start of selection (ms) for the temporal view (default: 0).",
|
|
109
|
+
)
|
|
110
|
+
parser.add_argument(
|
|
111
|
+
"--tail",
|
|
112
|
+
type=float,
|
|
113
|
+
metavar="MS",
|
|
114
|
+
help="End of selection (ms) for the temporal view (default: duration of the current trajectory).",
|
|
115
|
+
)
|
|
116
|
+
parser.add_argument(
|
|
117
|
+
"--sex",
|
|
118
|
+
choices=["M", "F"],
|
|
119
|
+
help="Pass 'F' for female, 'M' for male. This can be later customized in the 'Configure spectral analysis' dialog, but it affects the default LPC degree (default: M).",
|
|
120
|
+
)
|
|
121
|
+
parser.add_argument(
|
|
122
|
+
"--spect-lim",
|
|
123
|
+
type=float,
|
|
124
|
+
metavar="HZ",
|
|
125
|
+
help="Frequency upper limit (Hz) for spectrogram display (default: Nyquist frequency).",
|
|
126
|
+
)
|
|
127
|
+
parser.add_argument(
|
|
128
|
+
"--lproc",
|
|
129
|
+
type=str,
|
|
130
|
+
metavar="PROC",
|
|
131
|
+
help="Label procedure to use for labeling (default: none).",
|
|
132
|
+
)
|
|
133
|
+
args = parser.parse_args()
|
|
134
|
+
|
|
135
|
+
phonoscape(
|
|
136
|
+
args.file,
|
|
137
|
+
args.variables,
|
|
138
|
+
palate=args.palate,
|
|
139
|
+
pharynx=args.pharynx,
|
|
140
|
+
spline=args.spline,
|
|
141
|
+
polyline_spline=args.polyline_spline,
|
|
142
|
+
audio=args.audio,
|
|
143
|
+
framing=args.framing,
|
|
144
|
+
temporal_display=args.temporal_display,
|
|
145
|
+
spatial_exclude=args.spatial_exclude,
|
|
146
|
+
comps=(
|
|
147
|
+
None
|
|
148
|
+
if not args.comps
|
|
149
|
+
else args.comps[0] if len(args.comps) == 1 else args.comps
|
|
150
|
+
),
|
|
151
|
+
view=cast(tuple[float, float, float], tuple(args.view)) if args.view else None,
|
|
152
|
+
head=args.head,
|
|
153
|
+
tail=args.tail,
|
|
154
|
+
sex=args.sex,
|
|
155
|
+
spect_lim=args.spect_lim,
|
|
156
|
+
lproc=args.lproc,
|
|
157
|
+
)
|