sofar 1.2.1__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.
- docs/Makefile +20 -0
- docs/api_reference.rst +20 -0
- docs/conf.py +167 -0
- docs/contributing.rst +1 -0
- docs/history.rst +1 -0
- docs/index.rst +4 -0
- docs/make.bat +36 -0
- docs/readme.rst +1 -0
- docs/resources/conventions.py +162 -0
- docs/resources/working_with_sofa_HRIR_lateral.png +0 -0
- docs/resources/working_with_sofa_source_horizontal.png +0 -0
- docs/resources/working_with_sofa_source_lateral.png +0 -0
- docs/sofar.rst +82 -0
- sofar/__init__.py +28 -0
- sofar/io.py +427 -0
- sofar/sofa.py +1835 -0
- sofar/sofa_conventions/VERSION +1 -0
- sofar/sofa_conventions/conventions/AnnotatedEmitterAudio_0.2.csv +46 -0
- sofar/sofa_conventions/conventions/AnnotatedEmitterAudio_0.2.json +353 -0
- sofar/sofa_conventions/conventions/AnnotatedReceiverAudio_0.2.csv +46 -0
- sofar/sofa_conventions/conventions/AnnotatedReceiverAudio_0.2.json +353 -0
- sofar/sofa_conventions/conventions/FreeFieldDirectivityTF_1.1.csv +59 -0
- sofar/sofa_conventions/conventions/FreeFieldDirectivityTF_1.1.json +444 -0
- sofar/sofa_conventions/conventions/FreeFieldHRIR_1.0.csv +43 -0
- sofar/sofa_conventions/conventions/FreeFieldHRIR_1.0.json +333 -0
- sofar/sofa_conventions/conventions/FreeFieldHRTF_1.0.csv +44 -0
- sofar/sofa_conventions/conventions/FreeFieldHRTF_1.0.json +340 -0
- sofar/sofa_conventions/conventions/GeneralFIR-E_2.0.csv +37 -0
- sofar/sofa_conventions/conventions/GeneralFIR-E_2.0.json +270 -0
- sofar/sofa_conventions/conventions/GeneralFIR_1.0.csv +40 -0
- sofar/sofa_conventions/conventions/GeneralFIR_1.0.json +295 -0
- sofar/sofa_conventions/conventions/GeneralSOS_1.0.csv +40 -0
- sofar/sofa_conventions/conventions/GeneralSOS_1.0.json +306 -0
- sofar/sofa_conventions/conventions/GeneralTF-E_1.0.csv +38 -0
- sofar/sofa_conventions/conventions/GeneralTF-E_1.0.json +277 -0
- sofar/sofa_conventions/conventions/GeneralTF_1.0.csv +38 -0
- sofar/sofa_conventions/conventions/GeneralTF_1.0.json +277 -0
- sofar/sofa_conventions/conventions/GeneralTF_2.0.csv +38 -0
- sofar/sofa_conventions/conventions/GeneralTF_2.0.json +277 -0
- sofar/sofa_conventions/conventions/SimpleFreeFieldHRIR_1.0.csv +47 -0
- sofar/sofa_conventions/conventions/SimpleFreeFieldHRIR_1.0.json +369 -0
- sofar/sofa_conventions/conventions/SimpleFreeFieldHRSOS_1.0.csv +43 -0
- sofar/sofa_conventions/conventions/SimpleFreeFieldHRSOS_1.0.json +349 -0
- sofar/sofa_conventions/conventions/SimpleFreeFieldHRTF_1.0.csv +44 -0
- sofar/sofa_conventions/conventions/SimpleFreeFieldHRTF_1.0.json +340 -0
- sofar/sofa_conventions/conventions/SimpleFreeFieldSOS_1.0.csv +43 -0
- sofar/sofa_conventions/conventions/SimpleFreeFieldSOS_1.0.json +349 -0
- sofar/sofa_conventions/conventions/SimpleHeadphoneIR_1.0.csv +51 -0
- sofar/sofa_conventions/conventions/SimpleHeadphoneIR_1.0.json +396 -0
- sofar/sofa_conventions/conventions/SingleRoomMIMOSRIR_1.0.csv +78 -0
- sofar/sofa_conventions/conventions/SingleRoomMIMOSRIR_1.0.json +601 -0
- sofar/sofa_conventions/conventions/SingleRoomSRIR_1.0.csv +78 -0
- sofar/sofa_conventions/conventions/SingleRoomSRIR_1.0.json +601 -0
- sofar/sofa_conventions/conventions/deprecated/AnnotatedEmitterAudio_0.1.csv +46 -0
- sofar/sofa_conventions/conventions/deprecated/AnnotatedEmitterAudio_0.1.json +351 -0
- sofar/sofa_conventions/conventions/deprecated/AnnotatedReceiverAudio_0.1.csv +46 -0
- sofar/sofa_conventions/conventions/deprecated/AnnotatedReceiverAudio_0.1.json +351 -0
- sofar/sofa_conventions/conventions/deprecated/FreeFieldDirectivityTF_1.0.csv +58 -0
- sofar/sofa_conventions/conventions/deprecated/FreeFieldDirectivityTF_1.0.json +437 -0
- sofar/sofa_conventions/conventions/deprecated/GeneralFIRE_1.0.csv +37 -0
- sofar/sofa_conventions/conventions/deprecated/GeneralFIRE_1.0.json +270 -0
- sofar/sofa_conventions/conventions/deprecated/MultiSpeakerBRIR_0.3.csv +48 -0
- sofar/sofa_conventions/conventions/deprecated/MultiSpeakerBRIR_0.3.json +376 -0
- sofar/sofa_conventions/conventions/deprecated/SimpleFreeFieldHRIR_0.4.csv +43 -0
- sofar/sofa_conventions/conventions/deprecated/SimpleFreeFieldHRIR_0.4.json +333 -0
- sofar/sofa_conventions/conventions/deprecated/SimpleFreeFieldTF_0.4.csv +44 -0
- sofar/sofa_conventions/conventions/deprecated/SimpleFreeFieldTF_0.4.json +340 -0
- sofar/sofa_conventions/conventions/deprecated/SimpleFreeFieldTF_1.0.csv +44 -0
- sofar/sofa_conventions/conventions/deprecated/SimpleFreeFieldTF_1.0.json +340 -0
- sofar/sofa_conventions/conventions/deprecated/SimpleHeadphoneIR_0.1.csv +51 -0
- sofar/sofa_conventions/conventions/deprecated/SimpleHeadphoneIR_0.1.json +396 -0
- sofar/sofa_conventions/conventions/deprecated/SimpleHeadphoneIR_0.2.csv +51 -0
- sofar/sofa_conventions/conventions/deprecated/SimpleHeadphoneIR_0.2.json +396 -0
- sofar/sofa_conventions/conventions/deprecated/SingleRoomDRIR_0.2.csv +47 -0
- sofar/sofa_conventions/conventions/deprecated/SingleRoomDRIR_0.2.json +360 -0
- sofar/sofa_conventions/conventions/deprecated/SingleRoomDRIR_0.3.csv +47 -0
- sofar/sofa_conventions/conventions/deprecated/SingleRoomDRIR_0.3.json +360 -0
- sofar/sofa_conventions/conventions/deprecated/SingleTrackedAudio_0.1.csv +47 -0
- sofar/sofa_conventions/conventions/deprecated/SingleTrackedAudio_0.1.json +366 -0
- sofar/sofa_conventions/conventions/deprecated/SingleTrackedAudio_0.2.csv +51 -0
- sofar/sofa_conventions/conventions/deprecated/SingleTrackedAudio_0.2.json +397 -0
- sofar/sofa_conventions/rules/deprecations.json +13 -0
- sofar/sofa_conventions/rules/rules.json +819 -0
- sofar/sofa_conventions/rules/unit_aliases.json +11 -0
- sofar/sofa_conventions/rules/upgrade.json +226 -0
- sofar/sofa_conventions/write_upgrade_rules.py +139 -0
- sofar/sofa_conventions/write_verification_data.py +313 -0
- sofar/sofa_conventions/write_verification_rules.py +356 -0
- sofar/sofastream.py +301 -0
- sofar/update_conventions.py +449 -0
- sofar/utils.py +316 -0
- sofar-1.2.1.dist-info/LICENSE +22 -0
- sofar-1.2.1.dist-info/METADATA +136 -0
- sofar-1.2.1.dist-info/RECORD +105 -0
- sofar-1.2.1.dist-info/WHEEL +5 -0
- sofar-1.2.1.dist-info/top_level.txt +3 -0
- tests/__init__.py +0 -0
- tests/conftest.py +27 -0
- tests/test_deprecations.py +19 -0
- tests/test_io.py +349 -0
- tests/test_sofa.py +353 -0
- tests/test_sofa_upgrade_conventions.py +111 -0
- tests/test_sofa_verify.py +480 -0
- tests/test_sofastream.py +127 -0
- tests/test_utils.py +250 -0
@@ -0,0 +1,226 @@
|
|
1
|
+
{
|
2
|
+
"AnnotatedEmitterAudio": {
|
3
|
+
"from_to": [
|
4
|
+
[
|
5
|
+
[
|
6
|
+
"0.1"
|
7
|
+
],
|
8
|
+
[
|
9
|
+
"AnnotatedEmitterAudio_0.2"
|
10
|
+
],
|
11
|
+
"1"
|
12
|
+
]
|
13
|
+
],
|
14
|
+
"1": {
|
15
|
+
"move": {},
|
16
|
+
"remove": [],
|
17
|
+
"message": "The data in the variable 'Response' might have to be updated."
|
18
|
+
}
|
19
|
+
},
|
20
|
+
"AnnotatedReceiverAudio": {
|
21
|
+
"from_to": [
|
22
|
+
[
|
23
|
+
[
|
24
|
+
"0.1"
|
25
|
+
],
|
26
|
+
[
|
27
|
+
"AnnotatedReceiverAudio_0.2"
|
28
|
+
],
|
29
|
+
"1"
|
30
|
+
]
|
31
|
+
],
|
32
|
+
"1": {
|
33
|
+
"move": {},
|
34
|
+
"remove": [],
|
35
|
+
"message": "The data in the variable 'Response' might have to be updated."
|
36
|
+
}
|
37
|
+
},
|
38
|
+
"FreeFieldDirectivityTF": {
|
39
|
+
"from_to": [
|
40
|
+
[
|
41
|
+
[
|
42
|
+
"1.0"
|
43
|
+
],
|
44
|
+
[
|
45
|
+
"FreeFieldDirectivityTF_1.1"
|
46
|
+
],
|
47
|
+
"1"
|
48
|
+
]
|
49
|
+
],
|
50
|
+
"1": {
|
51
|
+
"move": {
|
52
|
+
"EmitterPosition": {
|
53
|
+
"target": "EmitterPosition",
|
54
|
+
"moveaxis": null,
|
55
|
+
"deprecated_dimensions": [
|
56
|
+
"IC",
|
57
|
+
"MC"
|
58
|
+
]
|
59
|
+
},
|
60
|
+
"EmitterDescription": {
|
61
|
+
"target": "EmitterDescriptions",
|
62
|
+
"moveaxis": null,
|
63
|
+
"deprecated_dimensions": [
|
64
|
+
"IS"
|
65
|
+
]
|
66
|
+
}
|
67
|
+
},
|
68
|
+
"remove": [],
|
69
|
+
"message": "Consider to add the optional data 'GLOBAL_EmitterDescription'introduced in convention version 1.1.\nWARNING: Adding 'GLOBAL_EmitterDescription' is required if 'EmitterDescriptions' is contained in the SOFA object."
|
70
|
+
}
|
71
|
+
},
|
72
|
+
"SimpleFreeFieldHRIR": {
|
73
|
+
"from_to": [
|
74
|
+
[
|
75
|
+
[
|
76
|
+
"0.4"
|
77
|
+
],
|
78
|
+
[
|
79
|
+
"SimpleFreeFieldHRIR_1.0"
|
80
|
+
],
|
81
|
+
"1"
|
82
|
+
]
|
83
|
+
],
|
84
|
+
"1": {
|
85
|
+
"move": {},
|
86
|
+
"remove": [],
|
87
|
+
"message": "Consider to add the optional data 'SourceUp', 'SourceView', 'SourceView:Type', and 'SourceView:Units' with default values that were introduced in convention version 1.0"
|
88
|
+
}
|
89
|
+
},
|
90
|
+
"SimpleFreeFieldTF": {
|
91
|
+
"from_to": [
|
92
|
+
[
|
93
|
+
[
|
94
|
+
"0.4",
|
95
|
+
"1.0"
|
96
|
+
],
|
97
|
+
[
|
98
|
+
"SimpleFreeFieldHRTF_1.0"
|
99
|
+
],
|
100
|
+
"1"
|
101
|
+
]
|
102
|
+
],
|
103
|
+
"1": {
|
104
|
+
"move": {},
|
105
|
+
"remove": [],
|
106
|
+
"message": null
|
107
|
+
}
|
108
|
+
},
|
109
|
+
"SimpleHeadphoneIR": {
|
110
|
+
"from_to": [
|
111
|
+
[
|
112
|
+
[
|
113
|
+
"0.1",
|
114
|
+
"0.2"
|
115
|
+
],
|
116
|
+
[
|
117
|
+
"SimpleHeadphoneIR_1.0"
|
118
|
+
],
|
119
|
+
"1"
|
120
|
+
]
|
121
|
+
],
|
122
|
+
"1": {
|
123
|
+
"move": {
|
124
|
+
"ReceiverDescription": {
|
125
|
+
"target": "ReceiverDescriptions",
|
126
|
+
"moveaxis": null,
|
127
|
+
"deprecated_dimensions": null
|
128
|
+
},
|
129
|
+
"EmitterDescription": {
|
130
|
+
"target": "EmitterDescriptions",
|
131
|
+
"moveaxis": null,
|
132
|
+
"deprecated_dimensions": null
|
133
|
+
}
|
134
|
+
},
|
135
|
+
"remove": [],
|
136
|
+
"message": null
|
137
|
+
}
|
138
|
+
},
|
139
|
+
"SingleRoomDRIR": {
|
140
|
+
"from_to": [
|
141
|
+
[
|
142
|
+
[
|
143
|
+
"0.2",
|
144
|
+
"0.3"
|
145
|
+
],
|
146
|
+
[
|
147
|
+
"SingleRoomSRIR_1.0"
|
148
|
+
],
|
149
|
+
"1"
|
150
|
+
]
|
151
|
+
],
|
152
|
+
"1": {
|
153
|
+
"move": {},
|
154
|
+
"remove": [],
|
155
|
+
"message": "Consider providing optional data that was introduced in SingleRoomSRIR version 1.0"
|
156
|
+
}
|
157
|
+
},
|
158
|
+
"MultiSpeakerBRIR": {
|
159
|
+
"from_to": [
|
160
|
+
[
|
161
|
+
[
|
162
|
+
"0.3"
|
163
|
+
],
|
164
|
+
[
|
165
|
+
"SingleRoomMIMOSRIR_1.0"
|
166
|
+
],
|
167
|
+
"1"
|
168
|
+
]
|
169
|
+
],
|
170
|
+
"1": {
|
171
|
+
"move": {
|
172
|
+
"Data.IR": {
|
173
|
+
"target": "Data.IR",
|
174
|
+
"moveaxis": [
|
175
|
+
3,
|
176
|
+
2
|
177
|
+
],
|
178
|
+
"deprecated_dimensions": null
|
179
|
+
},
|
180
|
+
"Data.Delay": {
|
181
|
+
"target": "Data.Delay",
|
182
|
+
"moveaxis": null,
|
183
|
+
"deprecated_dimensions": [
|
184
|
+
"IRE"
|
185
|
+
]
|
186
|
+
}
|
187
|
+
},
|
188
|
+
"remove": [],
|
189
|
+
"message": "Consider providing optional data that was introduced in SingleRoomSRIR version 1.0"
|
190
|
+
}
|
191
|
+
},
|
192
|
+
"GeneralFIRE": {
|
193
|
+
"from_to": [
|
194
|
+
[
|
195
|
+
[
|
196
|
+
"1.0"
|
197
|
+
],
|
198
|
+
[
|
199
|
+
"GeneralFIR-E_2.0"
|
200
|
+
],
|
201
|
+
"1"
|
202
|
+
]
|
203
|
+
],
|
204
|
+
"1": {
|
205
|
+
"move": {
|
206
|
+
"Data.IR": {
|
207
|
+
"target": "Data.IR",
|
208
|
+
"moveaxis": [
|
209
|
+
3,
|
210
|
+
2
|
211
|
+
],
|
212
|
+
"deprecated_dimensions": null
|
213
|
+
},
|
214
|
+
"EmitterPosition": {
|
215
|
+
"target": "EmitterPosition",
|
216
|
+
"moveaxis": null,
|
217
|
+
"deprecated_dimensions": [
|
218
|
+
"ECI"
|
219
|
+
]
|
220
|
+
}
|
221
|
+
},
|
222
|
+
"remove": [],
|
223
|
+
"message": "Consider providing optional data that was introduced in SingleRoomSRIR version 1.0"
|
224
|
+
}
|
225
|
+
}
|
226
|
+
}
|
@@ -0,0 +1,139 @@
|
|
1
|
+
"""
|
2
|
+
Write rules for upgrading outdated SOFA files.
|
3
|
+
|
4
|
+
Writes the following json files:
|
5
|
+
upgrade.json
|
6
|
+
|
7
|
+
For a more detailed information about the json files refer to _readme.txt
|
8
|
+
"""
|
9
|
+
# %%
|
10
|
+
import json
|
11
|
+
import os
|
12
|
+
|
13
|
+
upgrade = {
|
14
|
+
"AnnotatedEmitterAudio": {
|
15
|
+
"from_to": [[["0.1"], ["AnnotatedEmitterAudio_0.2"], "1"]],
|
16
|
+
"1": {
|
17
|
+
"move": {},
|
18
|
+
"remove": [],
|
19
|
+
"message": ("The data in the variable 'Response' "
|
20
|
+
"might have to be updated."),
|
21
|
+
},
|
22
|
+
},
|
23
|
+
"AnnotatedReceiverAudio": {
|
24
|
+
"from_to": [[["0.1"], ["AnnotatedReceiverAudio_0.2"], "1"]],
|
25
|
+
"1": {
|
26
|
+
"move": {},
|
27
|
+
"remove": [],
|
28
|
+
"message": ("The data in the variable 'Response' "
|
29
|
+
"might have to be updated."),
|
30
|
+
},
|
31
|
+
},
|
32
|
+
"FreeFieldDirectivityTF": {
|
33
|
+
"from_to": [[["1.0"], ["FreeFieldDirectivityTF_1.1"], "1"]],
|
34
|
+
"1": {
|
35
|
+
"move": {
|
36
|
+
"EmitterPosition": {
|
37
|
+
"target": "EmitterPosition",
|
38
|
+
"moveaxis": None,
|
39
|
+
"deprecated_dimensions": ["IC", "MC"]},
|
40
|
+
"EmitterDescription": {
|
41
|
+
"target": "EmitterDescriptions",
|
42
|
+
"moveaxis": None,
|
43
|
+
"deprecated_dimensions": ["IS"]},
|
44
|
+
},
|
45
|
+
"remove": [],
|
46
|
+
"message": ("Consider to add the optional data "
|
47
|
+
"'GLOBAL_EmitterDescription'"
|
48
|
+
"introduced in convention version 1.1.\n"
|
49
|
+
"WARNING: Adding 'GLOBAL_EmitterDescription' is "
|
50
|
+
"required if 'EmitterDescriptions' is contained in "
|
51
|
+
"the SOFA object."),
|
52
|
+
},
|
53
|
+
},
|
54
|
+
"SimpleFreeFieldHRIR": {
|
55
|
+
"from_to": [[["0.4"], ["SimpleFreeFieldHRIR_1.0"], "1"]],
|
56
|
+
"1": {
|
57
|
+
"move": {},
|
58
|
+
"remove": [],
|
59
|
+
"message": ("Consider to add the optional data 'SourceUp', "
|
60
|
+
"'SourceView', 'SourceView:Type', and "
|
61
|
+
"'SourceView:Units' with default values that were "
|
62
|
+
"introduced in convention version 1.0"),
|
63
|
+
},
|
64
|
+
},
|
65
|
+
"SimpleFreeFieldTF": {
|
66
|
+
"from_to": [[["0.4", "1.0"], ["SimpleFreeFieldHRTF_1.0"], "1"]],
|
67
|
+
"1": {
|
68
|
+
"move": {},
|
69
|
+
"remove": [],
|
70
|
+
"message": None,
|
71
|
+
},
|
72
|
+
},
|
73
|
+
"SimpleHeadphoneIR": {
|
74
|
+
"from_to": [[["0.1", "0.2"], ["SimpleHeadphoneIR_1.0"], "1"]],
|
75
|
+
"1": {
|
76
|
+
"move": {
|
77
|
+
"ReceiverDescription": {
|
78
|
+
"target": "ReceiverDescriptions",
|
79
|
+
"moveaxis": None,
|
80
|
+
"deprecated_dimensions": None},
|
81
|
+
"EmitterDescription": {
|
82
|
+
"target": "EmitterDescriptions",
|
83
|
+
"moveaxis": None,
|
84
|
+
"deprecated_dimensions": None},
|
85
|
+
},
|
86
|
+
"remove": [],
|
87
|
+
"message": None,
|
88
|
+
},
|
89
|
+
},
|
90
|
+
"SingleRoomDRIR": {
|
91
|
+
"from_to": [[["0.2", "0.3"], ["SingleRoomSRIR_1.0"], "1"]],
|
92
|
+
"1": {
|
93
|
+
"move": {},
|
94
|
+
"remove": [],
|
95
|
+
"message": ("Consider providing optional data that was introduced "
|
96
|
+
"in SingleRoomSRIR version 1.0"),
|
97
|
+
},
|
98
|
+
},
|
99
|
+
"MultiSpeakerBRIR": {
|
100
|
+
"from_to": [[["0.3"], ["SingleRoomMIMOSRIR_1.0"], "1"]],
|
101
|
+
"1": {
|
102
|
+
"move": {
|
103
|
+
"Data.IR": {
|
104
|
+
"target": "Data.IR",
|
105
|
+
"moveaxis": [3, 2],
|
106
|
+
"deprecated_dimensions": None},
|
107
|
+
"Data.Delay": {
|
108
|
+
"target": "Data.Delay",
|
109
|
+
"moveaxis": None,
|
110
|
+
"deprecated_dimensions": ["IRE"]},
|
111
|
+
},
|
112
|
+
"remove": [],
|
113
|
+
"message": ("Consider providing optional data that was introduced "
|
114
|
+
"in SingleRoomSRIR version 1.0"),
|
115
|
+
},
|
116
|
+
},
|
117
|
+
"GeneralFIRE": {
|
118
|
+
"from_to": [[["1.0"], ["GeneralFIR-E_2.0"], "1"]],
|
119
|
+
"1": {
|
120
|
+
"move": {
|
121
|
+
"Data.IR": {
|
122
|
+
"target": "Data.IR",
|
123
|
+
"moveaxis": [3, 2],
|
124
|
+
"deprecated_dimensions": None},
|
125
|
+
"EmitterPosition": {
|
126
|
+
"target": "EmitterPosition",
|
127
|
+
"moveaxis": None,
|
128
|
+
"deprecated_dimensions": ["ECI"]},
|
129
|
+
},
|
130
|
+
"remove": [],
|
131
|
+
"message": ("Consider providing optional data that was introduced "
|
132
|
+
"in SingleRoomSRIR version 1.0"),
|
133
|
+
},
|
134
|
+
},
|
135
|
+
}
|
136
|
+
|
137
|
+
json_file = os.path.join(os.path.dirname(__file__), "rules", "upgrade.json")
|
138
|
+
with open(json_file, 'w') as file:
|
139
|
+
json.dump(upgrade, file, indent=4)
|
@@ -0,0 +1,313 @@
|
|
1
|
+
# %%
|
2
|
+
"""Write verification data to SOFA files."""
|
3
|
+
import sofar as sf
|
4
|
+
from sofar.utils import _complete_sofa
|
5
|
+
import os
|
6
|
+
import numpy as np
|
7
|
+
|
8
|
+
rules, unit_aliases, deprecations, _ = sf.Sofa._verification_rules()
|
9
|
+
|
10
|
+
|
11
|
+
# -----------------------------------------------------------------------------
|
12
|
+
# Rules that restrict SOFA attributes to certain values
|
13
|
+
print("Write data to test SOFA attributes with restricted values")
|
14
|
+
print("---------------------------------------------------------")
|
15
|
+
|
16
|
+
# key: name of variable or attribute for testing the rule
|
17
|
+
for key in rules:
|
18
|
+
# check if rule exists
|
19
|
+
if "value" not in rules[key] or rules[key]["value"] is None:
|
20
|
+
continue
|
21
|
+
|
22
|
+
# get blank SOFA file
|
23
|
+
key_sf = key.replace(".", "_").replace(":", "_")
|
24
|
+
filename = f"{key_sf}=invalid-value.sofa"
|
25
|
+
print(filename)
|
26
|
+
sofa = _complete_sofa()
|
27
|
+
|
28
|
+
# write invalid value
|
29
|
+
sofa.protected = False
|
30
|
+
setattr(sofa, key_sf, "invalid-value")
|
31
|
+
sofa.protected = True
|
32
|
+
|
33
|
+
# write invalid SOFA file
|
34
|
+
sf.io._write_sofa(
|
35
|
+
os.path.join("data", "restricted_values", filename),
|
36
|
+
sofa, compression=4, verify=False)
|
37
|
+
|
38
|
+
del key, key_sf, sofa, filename
|
39
|
+
|
40
|
+
|
41
|
+
# -----------------------------------------------------------------------------
|
42
|
+
# Rules that require conditional Attributes or Variables to be existing
|
43
|
+
print("\nWrite data to test general dependencies")
|
44
|
+
print("---------------------------------------")
|
45
|
+
|
46
|
+
# key: name of variable or attribute for testing the rule
|
47
|
+
for key in rules:
|
48
|
+
|
49
|
+
# check if rule applies
|
50
|
+
if "general" not in rules[key]:
|
51
|
+
continue
|
52
|
+
|
53
|
+
key_sf = key.replace(".", "_").replace(":", "_")
|
54
|
+
|
55
|
+
for sub in rules[key]["general"]:
|
56
|
+
|
57
|
+
# get blank SOFA file
|
58
|
+
sub_sf = sub.replace(".", "_").replace(":", "_")
|
59
|
+
filename = f"{key_sf}.{sub_sf}=missing.sofa"
|
60
|
+
print(filename)
|
61
|
+
sofa = _complete_sofa()
|
62
|
+
|
63
|
+
# delete conditional dependency
|
64
|
+
sofa.delete(sub_sf)
|
65
|
+
|
66
|
+
# write invalid SOFA file
|
67
|
+
sf.io._write_sofa(os.path.join(
|
68
|
+
"data", "general_dependencies", filename),
|
69
|
+
sofa, compression=4, verify=False)
|
70
|
+
|
71
|
+
del key, key_sf, sub, sub_sf, sofa, filename
|
72
|
+
|
73
|
+
|
74
|
+
# -----------------------------------------------------------------------------
|
75
|
+
# Specific rules except for GLOBAL:DataType and GLOBAL:SOFAConventions.
|
76
|
+
# Specific rules require certain variables or attributes to exist depending
|
77
|
+
# on a parent variable or attribute and sometimes also restrict the value for
|
78
|
+
# the child.
|
79
|
+
print("\nWrite data to test specific dependencies")
|
80
|
+
print("----------------------------------------")
|
81
|
+
|
82
|
+
keys = [k for k in rules.keys() if "specific" in rules[k] and k not in
|
83
|
+
["GLOBAL:DataType", "GLOBAL:SOFAConventions"]]
|
84
|
+
|
85
|
+
# key: name of variable or attribute for testing specific dependency
|
86
|
+
for key in keys:
|
87
|
+
key_sf = key.replace(".", "_").replace(":", "_")
|
88
|
+
|
89
|
+
# key_value: value of the variable or attribute that triggers the
|
90
|
+
# specific dependency
|
91
|
+
for value_key in rules[key]["specific"]:
|
92
|
+
|
93
|
+
# sub: name of variable or attribute for which a specific
|
94
|
+
# dependency is checked
|
95
|
+
for sub in rules[key]["specific"][value_key]:
|
96
|
+
|
97
|
+
if sub.startswith("_"):
|
98
|
+
continue
|
99
|
+
|
100
|
+
sub_sf = sub.replace(".", "_").replace(":", "_")
|
101
|
+
sofa = _complete_sofa()
|
102
|
+
|
103
|
+
# set key to correct value
|
104
|
+
sofa.protected = False
|
105
|
+
setattr(sofa, key_sf, value_key)
|
106
|
+
sofa.protected = False
|
107
|
+
|
108
|
+
# test a wrong value sor sub
|
109
|
+
value_sub = rules[key]["specific"][value_key][sub]
|
110
|
+
if value_sub is not None:
|
111
|
+
setattr(sofa, sub_sf, "invalid-value")
|
112
|
+
filename = f"{key_sf}={value_key}.{sub_sf}=invalid-value.sofa"
|
113
|
+
print(filename)
|
114
|
+
sf.io._write_sofa(os.path.join(
|
115
|
+
"data", "specific_dependencies", filename),
|
116
|
+
sofa, compression=4, verify=False)
|
117
|
+
|
118
|
+
# test deleting sub
|
119
|
+
sofa.protected = False
|
120
|
+
delattr(sofa, sub_sf)
|
121
|
+
sofa.protected = True
|
122
|
+
filename = f"{key_sf}={value_key}.{sub_sf}=missing.sofa"
|
123
|
+
print(filename)
|
124
|
+
sf.io._write_sofa(os.path.join(
|
125
|
+
"data", "specific_dependencies", filename),
|
126
|
+
sofa, compression=4, verify=False)
|
127
|
+
|
128
|
+
del keys, key, key_sf, value_key, sub, sub_sf, sofa, value_sub, filename
|
129
|
+
|
130
|
+
|
131
|
+
# -----------------------------------------------------------------------------
|
132
|
+
# specific rules for GLOBAL:DataType
|
133
|
+
for data_type in rules["GLOBAL:DataType"]["specific"]:
|
134
|
+
|
135
|
+
if data_type in ["FIR", "FIR-E", "FIRE", "TF", "TF-E"]:
|
136
|
+
convention = "General" + data_type
|
137
|
+
elif data_type == "SOS":
|
138
|
+
convention = "SimpleFreeFieldHRSOS"
|
139
|
+
elif data_type == "FIRE":
|
140
|
+
convention = "MultiSpeakerBRIR"
|
141
|
+
elif data_type == "Audio":
|
142
|
+
convention = "AnnotatedEmitterAudio"
|
143
|
+
|
144
|
+
for key in rules["GLOBAL:DataType"]["specific"][data_type]:
|
145
|
+
if key.startswith("_"):
|
146
|
+
continue
|
147
|
+
|
148
|
+
key_sf = key.replace(".", "_").replace(":", "_")
|
149
|
+
sofa = sf.Sofa(convention)
|
150
|
+
if sofa.GLOBAL_SOFAConventionsVersion.startswith('0.'):
|
151
|
+
sofa.verify(mode="read")
|
152
|
+
|
153
|
+
# test a wrong value
|
154
|
+
value = rules["GLOBAL:DataType"]["specific"][data_type][key]
|
155
|
+
if value is not None:
|
156
|
+
setattr(sofa, key_sf, "invalid-value")
|
157
|
+
filename = \
|
158
|
+
f"GLOBAL_DataType={data_type}.{key_sf}=invalid-value.sofa"
|
159
|
+
print(filename)
|
160
|
+
sf.io._write_sofa(os.path.join(
|
161
|
+
"data", "specific_dependencies", filename),
|
162
|
+
sofa, compression=4, verify=False)
|
163
|
+
|
164
|
+
# test deleting the attribute
|
165
|
+
sofa.protected = False
|
166
|
+
delattr(sofa, key_sf)
|
167
|
+
sofa.protected = True
|
168
|
+
filename = f"GLOBAL_DataType={data_type}.{key_sf}=missing.sofa"
|
169
|
+
print(filename)
|
170
|
+
sf.io._write_sofa(os.path.join(
|
171
|
+
"data", "specific_dependencies", filename),
|
172
|
+
sofa, compression=4, verify=False)
|
173
|
+
|
174
|
+
del data_type, convention, key, key_sf, sofa, value, filename
|
175
|
+
|
176
|
+
|
177
|
+
# -----------------------------------------------------------------------------
|
178
|
+
# specific rules for GLOBAL:SOFAConventions
|
179
|
+
for convention in rules["GLOBAL:SOFAConventions"]["specific"]:
|
180
|
+
for key in rules["GLOBAL:SOFAConventions"]["specific"][convention]:
|
181
|
+
if key.startswith("_"):
|
182
|
+
continue
|
183
|
+
|
184
|
+
key_sf = key.replace(".", "_").replace(":", "_")
|
185
|
+
sofa = sf.Sofa(convention)
|
186
|
+
if sofa.GLOBAL_SOFAConventionsVersion.startswith('0.'):
|
187
|
+
sofa.verify(mode="read")
|
188
|
+
|
189
|
+
# test a wrong value
|
190
|
+
value = rules["GLOBAL:SOFAConventions"]["specific"][convention][key]
|
191
|
+
if value is not None:
|
192
|
+
sofa.protected = False
|
193
|
+
setattr(sofa, key_sf, "invalid-value")
|
194
|
+
sofa.protected = True
|
195
|
+
|
196
|
+
filename = (f"GLOBAL_SOFAConventions={convention}."
|
197
|
+
f"{key_sf}=invalid-value.sofa")
|
198
|
+
print(filename)
|
199
|
+
|
200
|
+
sf.io._write_sofa(os.path.join(
|
201
|
+
"data", "specific_dependencies", filename),
|
202
|
+
sofa, compression=4, verify=False)
|
203
|
+
|
204
|
+
# test deleting the attribute
|
205
|
+
sofa.protected = False
|
206
|
+
delattr(sofa, key_sf)
|
207
|
+
sofa.protected = True
|
208
|
+
|
209
|
+
filename = f"GLOBAL_SOFAConventions={convention}.{key_sf}=missing.sofa"
|
210
|
+
print(filename)
|
211
|
+
|
212
|
+
sf.io._write_sofa(os.path.join(
|
213
|
+
"data", "specific_dependencies", filename),
|
214
|
+
sofa, compression=4, verify=False)
|
215
|
+
|
216
|
+
del convention, key, key_sf, sofa, filename
|
217
|
+
|
218
|
+
|
219
|
+
# -----------------------------------------------------------------------------
|
220
|
+
# restrictions on dimensions
|
221
|
+
print("\nWrite data to test restrictions on dimensions")
|
222
|
+
print("---------------------------------------------")
|
223
|
+
|
224
|
+
# test dimensions for spherical harmonics coordinates
|
225
|
+
sofa = sf.Sofa("GeneralFIR-E")
|
226
|
+
sofa.ReceiverPosition_Type = "spherical harmonics"
|
227
|
+
sofa.ReceiverPosition_Units = "degree, degree, metre"
|
228
|
+
sofa.Data_IR = np.zeros((1, 2, 1, 1))
|
229
|
+
sofa.Data_Delay = np.zeros((1, 2, 1))
|
230
|
+
|
231
|
+
filename = "ReceiverPosition_Type=spherical harmonics.R=2.sofa"
|
232
|
+
print(filename)
|
233
|
+
|
234
|
+
sofa.verify(issue_handling="ignore")
|
235
|
+
sf.io._write_sofa(os.path.join(
|
236
|
+
"data", "restricted_dimensions", filename),
|
237
|
+
sofa, compression=4, verify=False)
|
238
|
+
|
239
|
+
sofa = sf.Sofa("GeneralFIR-E")
|
240
|
+
sofa.EmitterPosition_Type = "spherical harmonics"
|
241
|
+
sofa.EmitterPosition_Units = "degree, degree, metre"
|
242
|
+
sofa.Data_IR = np.zeros((1, 1, 1, 2))
|
243
|
+
sofa.Data_Delay = np.zeros((1, 1, 2))
|
244
|
+
|
245
|
+
filename = "EmitterPosition_Type=spherical harmonics.E=2.sofa"
|
246
|
+
print(filename)
|
247
|
+
|
248
|
+
sofa.verify(issue_handling="ignore")
|
249
|
+
sf.io._write_sofa(os.path.join(
|
250
|
+
"data", "restricted_dimensions", filename),
|
251
|
+
sofa, compression=4, verify=False)
|
252
|
+
|
253
|
+
# test dimensions for SOS data type
|
254
|
+
sofa = sf.Sofa("SimpleFreeFieldHRSOS")
|
255
|
+
sofa.Data_SOS = np.zeros((1, 2, 1))
|
256
|
+
|
257
|
+
filename = "GLOBAL_DataType_Type=SOS.N=1.sofa"
|
258
|
+
print(filename)
|
259
|
+
|
260
|
+
sofa.verify(issue_handling="ignore")
|
261
|
+
sf.io._write_sofa(os.path.join(
|
262
|
+
"data", "restricted_dimensions", filename),
|
263
|
+
sofa, compression=4, verify=False)
|
264
|
+
|
265
|
+
# test dimensions for SimpleFreeFieldHRIR
|
266
|
+
for convention in ["SimpleFreeFieldHRIR",
|
267
|
+
"SimpleFreeFieldHRTF",
|
268
|
+
"SimpleFreeFieldHRSOS"]:
|
269
|
+
sofa = sf.Sofa(convention)
|
270
|
+
sofa.EmitterPosition = [[1, 0, 0], [0, 1, 0]]
|
271
|
+
|
272
|
+
filename = f"GLOBAL_SOFAConventions={convention}.E=2.sofa"
|
273
|
+
print(filename)
|
274
|
+
|
275
|
+
sofa.verify(issue_handling="ignore")
|
276
|
+
sf.io._write_sofa(os.path.join(
|
277
|
+
"data", "restricted_dimensions", filename),
|
278
|
+
sofa, compression=4, verify=False)
|
279
|
+
|
280
|
+
del sofa, filename, convention
|
281
|
+
|
282
|
+
|
283
|
+
# -----------------------------------------------------------------------------
|
284
|
+
# deprecations
|
285
|
+
print("\nWrite data to test deprecations")
|
286
|
+
print("-------------------------------")
|
287
|
+
|
288
|
+
conventions = sf.utils._get_conventions("name")
|
289
|
+
|
290
|
+
for deprecated, substitute in deprecations["GLOBAL:SOFAConventions"].items():
|
291
|
+
"""
|
292
|
+
Test if deprecations raise warnings in read mode and errors in write mode.
|
293
|
+
"""
|
294
|
+
|
295
|
+
# check if deprecated and substitute convention exist in sofar
|
296
|
+
if deprecated in conventions:
|
297
|
+
|
298
|
+
if deprecated == "SingleTrackedAudio":
|
299
|
+
# This convention was never used and does not define the dimension
|
300
|
+
# 'R'. Thus test files can not be written in this case
|
301
|
+
continue
|
302
|
+
|
303
|
+
sofa = sf.Sofa(deprecated, verify=False)
|
304
|
+
|
305
|
+
filename = f"GLOBAL_SOFAConventions={deprecated}.{substitute}.sofa"
|
306
|
+
print(filename)
|
307
|
+
|
308
|
+
sofa.verify(issue_handling="ignore")
|
309
|
+
sf.io._write_sofa(os.path.join(
|
310
|
+
"data", "deprecations", filename),
|
311
|
+
sofa, compression=4, verify=False)
|
312
|
+
|
313
|
+
del conventions, deprecated, substitute, sofa, filename
|