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.
Files changed (105) hide show
  1. docs/Makefile +20 -0
  2. docs/api_reference.rst +20 -0
  3. docs/conf.py +167 -0
  4. docs/contributing.rst +1 -0
  5. docs/history.rst +1 -0
  6. docs/index.rst +4 -0
  7. docs/make.bat +36 -0
  8. docs/readme.rst +1 -0
  9. docs/resources/conventions.py +162 -0
  10. docs/resources/working_with_sofa_HRIR_lateral.png +0 -0
  11. docs/resources/working_with_sofa_source_horizontal.png +0 -0
  12. docs/resources/working_with_sofa_source_lateral.png +0 -0
  13. docs/sofar.rst +82 -0
  14. sofar/__init__.py +28 -0
  15. sofar/io.py +427 -0
  16. sofar/sofa.py +1835 -0
  17. sofar/sofa_conventions/VERSION +1 -0
  18. sofar/sofa_conventions/conventions/AnnotatedEmitterAudio_0.2.csv +46 -0
  19. sofar/sofa_conventions/conventions/AnnotatedEmitterAudio_0.2.json +353 -0
  20. sofar/sofa_conventions/conventions/AnnotatedReceiverAudio_0.2.csv +46 -0
  21. sofar/sofa_conventions/conventions/AnnotatedReceiverAudio_0.2.json +353 -0
  22. sofar/sofa_conventions/conventions/FreeFieldDirectivityTF_1.1.csv +59 -0
  23. sofar/sofa_conventions/conventions/FreeFieldDirectivityTF_1.1.json +444 -0
  24. sofar/sofa_conventions/conventions/FreeFieldHRIR_1.0.csv +43 -0
  25. sofar/sofa_conventions/conventions/FreeFieldHRIR_1.0.json +333 -0
  26. sofar/sofa_conventions/conventions/FreeFieldHRTF_1.0.csv +44 -0
  27. sofar/sofa_conventions/conventions/FreeFieldHRTF_1.0.json +340 -0
  28. sofar/sofa_conventions/conventions/GeneralFIR-E_2.0.csv +37 -0
  29. sofar/sofa_conventions/conventions/GeneralFIR-E_2.0.json +270 -0
  30. sofar/sofa_conventions/conventions/GeneralFIR_1.0.csv +40 -0
  31. sofar/sofa_conventions/conventions/GeneralFIR_1.0.json +295 -0
  32. sofar/sofa_conventions/conventions/GeneralSOS_1.0.csv +40 -0
  33. sofar/sofa_conventions/conventions/GeneralSOS_1.0.json +306 -0
  34. sofar/sofa_conventions/conventions/GeneralTF-E_1.0.csv +38 -0
  35. sofar/sofa_conventions/conventions/GeneralTF-E_1.0.json +277 -0
  36. sofar/sofa_conventions/conventions/GeneralTF_1.0.csv +38 -0
  37. sofar/sofa_conventions/conventions/GeneralTF_1.0.json +277 -0
  38. sofar/sofa_conventions/conventions/GeneralTF_2.0.csv +38 -0
  39. sofar/sofa_conventions/conventions/GeneralTF_2.0.json +277 -0
  40. sofar/sofa_conventions/conventions/SimpleFreeFieldHRIR_1.0.csv +47 -0
  41. sofar/sofa_conventions/conventions/SimpleFreeFieldHRIR_1.0.json +369 -0
  42. sofar/sofa_conventions/conventions/SimpleFreeFieldHRSOS_1.0.csv +43 -0
  43. sofar/sofa_conventions/conventions/SimpleFreeFieldHRSOS_1.0.json +349 -0
  44. sofar/sofa_conventions/conventions/SimpleFreeFieldHRTF_1.0.csv +44 -0
  45. sofar/sofa_conventions/conventions/SimpleFreeFieldHRTF_1.0.json +340 -0
  46. sofar/sofa_conventions/conventions/SimpleFreeFieldSOS_1.0.csv +43 -0
  47. sofar/sofa_conventions/conventions/SimpleFreeFieldSOS_1.0.json +349 -0
  48. sofar/sofa_conventions/conventions/SimpleHeadphoneIR_1.0.csv +51 -0
  49. sofar/sofa_conventions/conventions/SimpleHeadphoneIR_1.0.json +396 -0
  50. sofar/sofa_conventions/conventions/SingleRoomMIMOSRIR_1.0.csv +78 -0
  51. sofar/sofa_conventions/conventions/SingleRoomMIMOSRIR_1.0.json +601 -0
  52. sofar/sofa_conventions/conventions/SingleRoomSRIR_1.0.csv +78 -0
  53. sofar/sofa_conventions/conventions/SingleRoomSRIR_1.0.json +601 -0
  54. sofar/sofa_conventions/conventions/deprecated/AnnotatedEmitterAudio_0.1.csv +46 -0
  55. sofar/sofa_conventions/conventions/deprecated/AnnotatedEmitterAudio_0.1.json +351 -0
  56. sofar/sofa_conventions/conventions/deprecated/AnnotatedReceiverAudio_0.1.csv +46 -0
  57. sofar/sofa_conventions/conventions/deprecated/AnnotatedReceiverAudio_0.1.json +351 -0
  58. sofar/sofa_conventions/conventions/deprecated/FreeFieldDirectivityTF_1.0.csv +58 -0
  59. sofar/sofa_conventions/conventions/deprecated/FreeFieldDirectivityTF_1.0.json +437 -0
  60. sofar/sofa_conventions/conventions/deprecated/GeneralFIRE_1.0.csv +37 -0
  61. sofar/sofa_conventions/conventions/deprecated/GeneralFIRE_1.0.json +270 -0
  62. sofar/sofa_conventions/conventions/deprecated/MultiSpeakerBRIR_0.3.csv +48 -0
  63. sofar/sofa_conventions/conventions/deprecated/MultiSpeakerBRIR_0.3.json +376 -0
  64. sofar/sofa_conventions/conventions/deprecated/SimpleFreeFieldHRIR_0.4.csv +43 -0
  65. sofar/sofa_conventions/conventions/deprecated/SimpleFreeFieldHRIR_0.4.json +333 -0
  66. sofar/sofa_conventions/conventions/deprecated/SimpleFreeFieldTF_0.4.csv +44 -0
  67. sofar/sofa_conventions/conventions/deprecated/SimpleFreeFieldTF_0.4.json +340 -0
  68. sofar/sofa_conventions/conventions/deprecated/SimpleFreeFieldTF_1.0.csv +44 -0
  69. sofar/sofa_conventions/conventions/deprecated/SimpleFreeFieldTF_1.0.json +340 -0
  70. sofar/sofa_conventions/conventions/deprecated/SimpleHeadphoneIR_0.1.csv +51 -0
  71. sofar/sofa_conventions/conventions/deprecated/SimpleHeadphoneIR_0.1.json +396 -0
  72. sofar/sofa_conventions/conventions/deprecated/SimpleHeadphoneIR_0.2.csv +51 -0
  73. sofar/sofa_conventions/conventions/deprecated/SimpleHeadphoneIR_0.2.json +396 -0
  74. sofar/sofa_conventions/conventions/deprecated/SingleRoomDRIR_0.2.csv +47 -0
  75. sofar/sofa_conventions/conventions/deprecated/SingleRoomDRIR_0.2.json +360 -0
  76. sofar/sofa_conventions/conventions/deprecated/SingleRoomDRIR_0.3.csv +47 -0
  77. sofar/sofa_conventions/conventions/deprecated/SingleRoomDRIR_0.3.json +360 -0
  78. sofar/sofa_conventions/conventions/deprecated/SingleTrackedAudio_0.1.csv +47 -0
  79. sofar/sofa_conventions/conventions/deprecated/SingleTrackedAudio_0.1.json +366 -0
  80. sofar/sofa_conventions/conventions/deprecated/SingleTrackedAudio_0.2.csv +51 -0
  81. sofar/sofa_conventions/conventions/deprecated/SingleTrackedAudio_0.2.json +397 -0
  82. sofar/sofa_conventions/rules/deprecations.json +13 -0
  83. sofar/sofa_conventions/rules/rules.json +819 -0
  84. sofar/sofa_conventions/rules/unit_aliases.json +11 -0
  85. sofar/sofa_conventions/rules/upgrade.json +226 -0
  86. sofar/sofa_conventions/write_upgrade_rules.py +139 -0
  87. sofar/sofa_conventions/write_verification_data.py +313 -0
  88. sofar/sofa_conventions/write_verification_rules.py +356 -0
  89. sofar/sofastream.py +301 -0
  90. sofar/update_conventions.py +449 -0
  91. sofar/utils.py +316 -0
  92. sofar-1.2.1.dist-info/LICENSE +22 -0
  93. sofar-1.2.1.dist-info/METADATA +136 -0
  94. sofar-1.2.1.dist-info/RECORD +105 -0
  95. sofar-1.2.1.dist-info/WHEEL +5 -0
  96. sofar-1.2.1.dist-info/top_level.txt +3 -0
  97. tests/__init__.py +0 -0
  98. tests/conftest.py +27 -0
  99. tests/test_deprecations.py +19 -0
  100. tests/test_io.py +349 -0
  101. tests/test_sofa.py +353 -0
  102. tests/test_sofa_upgrade_conventions.py +111 -0
  103. tests/test_sofa_verify.py +480 -0
  104. tests/test_sofastream.py +127 -0
  105. tests/test_utils.py +250 -0
sofar/utils.py ADDED
@@ -0,0 +1,316 @@
1
+ """Contains util functions to work with sofar and Sofa objects."""
2
+ import os
3
+ import glob
4
+ import numpy as np
5
+ import numpy.testing as npt
6
+ import warnings
7
+ import sofar as sf
8
+
9
+
10
+ def version():
11
+ """Return version of sofar and SOFA conventions."""
12
+
13
+ sofa_conventions = os.path.join(
14
+ os.path.dirname(__file__), "sofa_conventions", 'VERSION')
15
+ with open(sofa_conventions) as file:
16
+ sofa_conventions = file.readline().strip()
17
+
18
+ return (f"sofar v{sf.__version__} implementing "
19
+ f"SOFA standard {sofa_conventions}")
20
+
21
+
22
+ def _verify_convention_and_version(version, convention):
23
+ """
24
+ Verify if convention and version exist. Raise a Value error if it does not.
25
+
26
+ Parameters
27
+ ----------
28
+ version : str
29
+ The version to be checked
30
+ convention : str
31
+ The name of the convention to be checked
32
+ """
33
+
34
+ # check if the convention exists
35
+ if convention not in _get_conventions("name"):
36
+ raise ValueError(
37
+ f"Convention '{convention}' does not exist")
38
+
39
+ name_version = _get_conventions("name_version")
40
+
41
+ # check which version is wanted
42
+ version_exists = False
43
+ for versions in name_version:
44
+ # check if convention and version match
45
+ if versions[0] == convention \
46
+ and str(float(versions[1])) == version:
47
+ version_exists = True
48
+
49
+ if not version_exists:
50
+ raise ValueError((
51
+ f"{convention} v{version} is not a valid SOFA Convention."
52
+ "If you are trying to read the data use "
53
+ "sofar.read_sofa_as_netcdf(). Call sofar.list_conventions() for a "
54
+ "list of valid Conventions"))
55
+
56
+
57
+ def list_conventions():
58
+ """
59
+ List available SOFA conventions by printing to the console.
60
+ """
61
+ print(_get_conventions("string"))
62
+
63
+
64
+ def _get_conventions(return_type, conventions_path=None):
65
+ """
66
+ Get available SOFA conventions.
67
+
68
+ Parameters
69
+ ----------
70
+ return_type : string, optional
71
+ ``'path'``
72
+ Return a list with the full paths and filenames of the convention
73
+ files (json files)
74
+ ``'path_source'``
75
+ Return a list with the full paths and filenames of the source
76
+ convention files from API_MO (csv files)
77
+ ``'name'``
78
+ Return a list of the convention names without version
79
+ ``'name_version'``
80
+ Return a list of tuples containing the convention name and version.
81
+ ``'string'``
82
+ Returns a string that lists the names and versions of all
83
+ conventions.
84
+ conventions_path : str, optional
85
+ The path to the the `conventions` folder containing the csv and json
86
+ files.
87
+
88
+ Returns
89
+ -------
90
+ See parameter `return_type`.
91
+ """
92
+ # directory containing the SOFA conventions
93
+ if conventions_path is None:
94
+ conventions_path = os.path.join(
95
+ os.path.dirname(__file__), "sofa_conventions", 'conventions')
96
+
97
+ reg_str = "*.csv" if return_type == "path_source" else "*.json"
98
+
99
+ # SOFA convention files
100
+ standardized = list(glob.glob(os.path.join(conventions_path, reg_str)))
101
+ deprecated = list(
102
+ glob.glob(os.path.join(conventions_path, "deprecated", reg_str)))
103
+ paths = standardized + deprecated
104
+
105
+ conventions_str = "Available SOFA conventions:\n"
106
+
107
+ conventions = []
108
+ versions = []
109
+ for path in paths:
110
+ fileparts = os.path.basename(path).split(sep="_")
111
+ conventions += [fileparts[0]]
112
+ versions += [fileparts[1][:-5]]
113
+ conventions_str += f"{conventions[-1]} (Version {versions[-1]})\n"
114
+
115
+ if return_type is None:
116
+ return
117
+ elif return_type.startswith("path"):
118
+ return paths
119
+ elif return_type == "name":
120
+ return conventions
121
+ elif return_type == "name_version":
122
+ return list(zip(conventions, versions))
123
+ elif return_type == "string":
124
+ return conventions_str
125
+ else:
126
+ raise ValueError(f"return_type {return_type} is invalid")
127
+
128
+
129
+ def equals(sofa_a, sofa_b, verbose=True, exclude=None):
130
+ """
131
+ Compare two SOFA objects against each other.
132
+
133
+ Parameters
134
+ ----------
135
+ sofa_a : Sofa
136
+ SOFA object
137
+ sofa_b : Sofa
138
+ SOFA object
139
+ verbose : bool, optional
140
+ Print differences to the console. The default is True.
141
+ exclude : str, optional
142
+ Specify what fields should be excluded from the comparison
143
+
144
+ ``'GLOBAL'``
145
+ Exclude all global attributes, i.e., fields starting with 'GLOBAL:'
146
+ ``'DATE'``
147
+ Exclude date attributes, i.e., fields that contain 'Date'
148
+ ``'ATTR'``
149
+ Exclude all attributes, i.e., fields that contain ':'
150
+
151
+ The default is None, which does not exclude anything.
152
+
153
+ Returns
154
+ -------
155
+ is_identical : bool
156
+ ``True`` if sofa_a and sofa_b are identical, ``False`` otherwise.
157
+ """
158
+
159
+ is_identical = True
160
+
161
+ # get and filter keys
162
+ # ('_*' are SOFA object private variables, '__' are netCDF attributes)
163
+ keys_a = [k for k in sofa_a.__dict__.keys() if not k.startswith("_")]
164
+ keys_b = [k for k in sofa_b.__dict__.keys() if not k.startswith("_")]
165
+
166
+ if exclude is not None:
167
+ if exclude.upper() == "GLOBAL":
168
+ keys_a = [k for k in keys_a if not k.startswith("GLOBAL_")]
169
+ keys_b = [k for k in keys_b if not k.startswith("GLOBAL_")]
170
+ elif exclude.upper() == "ATTR":
171
+ keys_a = [k for k in keys_a if
172
+ sofa_a._convention[k]["type"] != "attribute"]
173
+ keys_b = [k for k in keys_b if
174
+ sofa_b._convention[k]["type"] != "attribute"]
175
+ elif exclude.upper() == "DATE":
176
+ keys_a = [k for k in keys_a if "Date" not in k]
177
+ keys_b = [k for k in keys_b if "Date" not in k]
178
+ else:
179
+ raise ValueError(
180
+ f"exclude is {exclude} but must be GLOBAL, DATE, or ATTR")
181
+
182
+ # check for equal length
183
+ if len(keys_a) != len(keys_b):
184
+ return _equals_raise_warning((
185
+ f"not identical: sofa_a has {len(keys_a)} attributes for "
186
+ f"comparison and sofa_b has {len(keys_b)}."), verbose)
187
+
188
+ # check if the keys match
189
+ if set(keys_a) != set(keys_b):
190
+ return _equals_raise_warning(
191
+ "not identical: sofa_a and sofa_b do not have the ame attributes",
192
+ verbose)
193
+
194
+ # compare the data inside the SOFA object
195
+ for key in keys_a:
196
+
197
+ # get data and types
198
+ a = getattr(sofa_a, key)
199
+ b = getattr(sofa_b, key)
200
+ type_a = sofa_a._convention[key]["type"]
201
+ type_b = sofa_b._convention[key]["type"]
202
+
203
+ # compare attributes
204
+ if type_a == "attribute" and type_b == "attribute":
205
+
206
+ # compare
207
+ if a != b:
208
+ is_identical = _equals_raise_warning(
209
+ f"not identical: different values for {key}", verbose)
210
+
211
+ # compare double variables
212
+ elif type_a == "double" and type_b == "double":
213
+
214
+ try:
215
+ npt.assert_allclose(np.squeeze(a), np.squeeze(b))
216
+ except AssertionError:
217
+ is_identical = _equals_raise_warning(
218
+ "not identical: different values for {key}", verbose)
219
+
220
+ # compare string variables
221
+ elif type_a == "string" and type_b == "string":
222
+ try:
223
+ assert np.all(
224
+ np.squeeze(a).astype("S") == np.squeeze(b).astype("S"))
225
+ except AssertionError:
226
+ is_identical = _equals_raise_warning(
227
+ "not identical: different values for {key}", verbose)
228
+ else:
229
+ is_identical = _equals_raise_warning(
230
+ (f"not identical: {key} has different data types "
231
+ f"({type_a}, {type_b})"), verbose)
232
+
233
+ return is_identical
234
+
235
+
236
+ def _equals_raise_warning(message, verbose):
237
+ if verbose:
238
+ warnings.warn(message, stacklevel=2)
239
+ return False
240
+
241
+
242
+ def _atleast_nd(array, ndim):
243
+ """
244
+ Get numpy array with specified number of dimensions. Dimensions are
245
+ appended at the end if ndim > 3.
246
+ """
247
+ try:
248
+ array = array.copy()
249
+ except AttributeError:
250
+ array = array
251
+
252
+ if ndim == 1:
253
+ array = np.atleast_1d(array)
254
+ if ndim == 2:
255
+ array = np.atleast_2d(array)
256
+ if ndim >= 3:
257
+ array = np.atleast_3d(array)
258
+ for _ in range(ndim - array.ndim):
259
+ array = array[..., np.newaxis]
260
+ return array
261
+
262
+
263
+ def _nd_newaxis(array, ndim):
264
+ """Append dimensions to the end of an array until array.ndim == ndim."""
265
+ array = np.array(array)
266
+
267
+ for _ in range(ndim - array.ndim):
268
+ array = array[..., np.newaxis]
269
+ return array
270
+
271
+
272
+ def _complete_sofa(convention="GeneralTF"):
273
+ """
274
+ Generate SOFA file with all required data for testing verification rules.
275
+ """
276
+
277
+ sofa = sf.Sofa(convention)
278
+ # Listener meta data
279
+ sofa.add_variable("ListenerView", [1, 0, 0], "double", "IC")
280
+ sofa.add_attribute("ListenerView_Type", "cartesian")
281
+ sofa.add_attribute("ListenerView_Units", "metre")
282
+ sofa.add_variable("ListenerUp", [0, 0, 1], "double", "IC")
283
+ # Receiver meta data
284
+ sofa.add_variable("ReceiverView", [1, 0, 0], "double", "IC")
285
+ sofa.add_attribute("ReceiverView_Type", "cartesian")
286
+ sofa.add_attribute("ReceiverView_Units", "metre")
287
+ sofa.add_variable("ReceiverUp", [0, 0, 1], "double", "IC")
288
+ # Source meta data
289
+ sofa.add_variable("SourceView", [1, 0, 0], "double", "IC")
290
+ sofa.add_attribute("SourceView_Type", "cartesian")
291
+ sofa.add_attribute("SourceView_Units", "metre")
292
+ sofa.add_variable("SourceUp", [0, 0, 1], "double", "IC")
293
+ # Emitter meta data
294
+ sofa.add_variable("EmitterView", [1, 0, 0], "double", "IC")
295
+ sofa.add_attribute("EmitterView_Type", "cartesian")
296
+ sofa.add_attribute("EmitterView_Units", "metre")
297
+ sofa.add_variable("EmitterUp", [0, 0, 1], "double", "IC")
298
+ sofa.add_attribute("GLOBAL_EmitterDescription", "what an emitter")
299
+ sofa.add_variable("EmitterDescriptions", ["emitter array"], "string", "MS")
300
+ # Room meta data
301
+ sofa.add_attribute("GLOBAL_RoomShortName", "Hall")
302
+ sofa.add_attribute("GLOBAL_RoomDescription", "Wooden floor")
303
+ sofa.add_attribute("GLOBAL_RoomLocation", "some where nice")
304
+ sofa.add_variable("RoomTemperature", 0, "double", "I")
305
+ sofa.add_attribute("RoomTemperature_Units", "kelvin")
306
+ sofa.add_attribute("GLOBAL_RoomGeometry", "some/file")
307
+ sofa.add_variable("RoomVolume", 200, "double", "I")
308
+ sofa.add_attribute("RoomVolume_Units", "cubic metre")
309
+ sofa.add_variable("RoomCornerA", [0, 0, 0], "double", "IC")
310
+ sofa.add_variable("RoomCornerB", [1, 1, 1], "double", "IC")
311
+ sofa.add_variable("RoomCorners", 0, "double", "I")
312
+ sofa.add_attribute("RoomCorners_Type", "cartesian")
313
+ sofa.add_attribute("RoomCorners_Units", "metre")
314
+
315
+ sofa.verify()
316
+ return sofa
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021, The pyfar developers
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
@@ -0,0 +1,136 @@
1
+ Metadata-Version: 2.1
2
+ Name: sofar
3
+ Version: 1.2.1
4
+ Summary: Maybe the most complete python package for SOFA files so far.
5
+ Author-email: The pyfar developers <info@pyfar.org>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2021, The pyfar developers
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+
29
+ Project-URL: Tracker, https://github.com/pyfar/sofar/issues
30
+ Project-URL: Documentation, https://sofar.readthedocs.io/
31
+ Project-URL: Download, https://pypi.org/project/sofar/
32
+ Project-URL: Homepage, https://pyfar.org/
33
+ Project-URL: Source, https://github.com/pyfar/sofar
34
+ Project-URL: Changelog, https://github.com/pyfar/sofar/blob/main/HISTORY.rst
35
+ Keywords: acoustics,pyfar
36
+ Classifier: Development Status :: 4 - Beta
37
+ Classifier: Intended Audience :: Science/Research
38
+ Classifier: License :: OSI Approved :: MIT License
39
+ Classifier: Natural Language :: English
40
+ Classifier: Programming Language :: Python :: 3
41
+ Classifier: Programming Language :: Python :: 3.8
42
+ Classifier: Programming Language :: Python :: 3.9
43
+ Classifier: Programming Language :: Python :: 3.10
44
+ Classifier: Programming Language :: Python :: 3.11
45
+ Classifier: Programming Language :: Python :: 3.12
46
+ Requires-Python: >=3.8
47
+ Description-Content-Type: text/markdown
48
+ License-File: LICENSE
49
+ Requires-Dist: netCDF4
50
+ Requires-Dist: numpy>=1.14.0
51
+ Requires-Dist: beautifulsoup4
52
+ Requires-Dist: requests
53
+ Provides-Extra: deploy
54
+ Requires-Dist: twine; extra == "deploy"
55
+ Requires-Dist: wheel; extra == "deploy"
56
+ Requires-Dist: build; extra == "deploy"
57
+ Requires-Dist: setuptools; extra == "deploy"
58
+ Requires-Dist: bump-my-version; extra == "deploy"
59
+ Provides-Extra: tests
60
+ Requires-Dist: pytest; extra == "tests"
61
+ Requires-Dist: pytest-cov; extra == "tests"
62
+ Requires-Dist: watchdog; extra == "tests"
63
+ Requires-Dist: ruff==0.8.2; extra == "tests"
64
+ Requires-Dist: coverage; extra == "tests"
65
+ Provides-Extra: docs
66
+ Requires-Dist: sphinx; extra == "docs"
67
+ Requires-Dist: autodocsumm>=0.2.14; extra == "docs"
68
+ Requires-Dist: pydata-sphinx-theme; extra == "docs"
69
+ Requires-Dist: sphinx_mdinclude; extra == "docs"
70
+ Requires-Dist: sphinx-design; extra == "docs"
71
+ Requires-Dist: sphinx-favicon; extra == "docs"
72
+ Requires-Dist: sphinx-reredirects; extra == "docs"
73
+ Provides-Extra: dev
74
+ Requires-Dist: sofar[deploy,docs,tests]; extra == "dev"
75
+
76
+ <h1 align="center">
77
+ <img src="https://github.com/pyfar/gallery/raw/main/docs/resources/logos/pyfar_logos_fixed_size_sofar.png" width="300">
78
+ </h1><br>
79
+
80
+ [![PyPI version](https://badge.fury.io/py/sofar.svg)](https://badge.fury.io/py/sofar)
81
+ [![Documentation Status](https://readthedocs.org/projects/sofar/badge/?version=latest)](https://sofar.readthedocs.io/en/latest/?badge=latest)
82
+ [![CircleCI](https://circleci.com/gh/pyfar/sofar.svg?style=shield)](https://circleci.com/gh/pyfar/sofar)
83
+ [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/pyfar/gallery/main?labpath=docs/gallery/interactive/sofar_introduction.ipynb)
84
+
85
+ Sofar is maybe the most complete Python package for the SOFA file format so
86
+ far. SOFA files store spatially distributed acoustic data such as impulse
87
+ responses or transfer functions. They are defined by the AES69-2022 standard
88
+ (see references). These are the key features of sofar
89
+
90
+ - Read, edit, and write SOFA files
91
+ - Add custom attributes to SOFA files
92
+ - Full Verification of the content of a SOFA files against AES69-2022
93
+ - Upgrade data that uses outdated SOFA conventions
94
+ - Open license allows unrestricted use
95
+ - sofar is tested using continuous integration on
96
+ - Uses a complete definition of the AES69-2022 standard (see references) maintained at [sofa_conventions](https://github.com/pyfar/sofa_conventions)
97
+
98
+ Getting Started
99
+ ===============
100
+
101
+ The [sofar and SOFA notebook](https://pyfar-gallery.readthedocs.io/en/latest/gallery/interactive/sofar_introduction.html)
102
+ gives an overview of the most important sofar functionality and is a good starting point. For processing and visualizing data
103
+ inside SOFA files, we recommend the [pyfar package](https://pyfar.readthedocs.io) that can read SOFA files through
104
+ `pyfar.io.read_sofa` and the in-depth examples contained in the
105
+ [pyfar example gallery](https://pyfar-gallery.readthedocs.io/en/latest/examples_gallery.html). Check out
106
+ [read the docs](https://sofar.readthedocs.io) for a complete documentation of sofar. A more detailed introduction to the SOFA
107
+ file format is given by Majdak et. al. 2022 (see references below). All information is also bundled at [pyfar.org](https://pyfar.org).
108
+
109
+ Installation
110
+ ============
111
+
112
+ Use pip to install sofar
113
+
114
+ pip install sofar
115
+
116
+
117
+ (Requires Python >= 3.8)
118
+
119
+ If the installation fails, please check out the [help section](https://pyfar-gallery.readthedocs.io/en/latest/help).
120
+
121
+ Contributing
122
+ ============
123
+
124
+ Refer to the [contribution guidelines](https://sofar.readthedocs.io/en/stable/contributing.html) for more information.
125
+
126
+ References
127
+ ==========
128
+
129
+ AES69-2022: *AES standard for file exchange - Spatial acoustic data file
130
+ format*, Audio Engineering Society, Inc., New York, NY, USA.
131
+ (https://www.aes.org/publications/standards/search.cfm?docID=99)
132
+
133
+ P. Majdak, F. Zotter, F. Brinkmann, J. De Muynke, M. Mihocic, and M.
134
+ Noisternig, "Spatially Oriented Format for Acoustics 2.1: Introduction and
135
+ Recent Advances", *J. Audio Eng. Soc.*, vol. 70, no. 7/8, pp. 565-584,
136
+ Jul. 2022. DOI: https://doi.org/10.17743/jaes.2022.0026
@@ -0,0 +1,105 @@
1
+ docs/Makefile,sha256=OYY1k1pc-qybE8cc8J65Uumpst0kiq55ct3gjLaWeJU,606
2
+ docs/api_reference.rst,sha256=s3tvYCr2vktN05sSyIhzt1BNktV13SnfU-Cz4fDmf5o,705
3
+ docs/conf.py,sha256=JLiZhmxpMXTnK3KPposuhV96J5smR5xzgONt-aTCn_M,5299
4
+ docs/contributing.rst,sha256=h9XHQ0lx_ySKgXQmwqhJQLPD7VElHdyu1ruKfYWvrYA,33
5
+ docs/history.rst,sha256=6GtKybnFdujxXakMcb0LHcrFsWwqRh8JJ_xhO_Qxqdg,28
6
+ docs/index.rst,sha256=TNHSWTiFrI_R7vn1E2XM2RTx3YEg8KuSzwAY9ttDdWc,37
7
+ docs/make.bat,sha256=wLZX2GGllVCJQSJ93BGGGHkLEsy6JC_I7u6xRKG3CtA,803
8
+ docs/readme.rst,sha256=ctYl-VOckbYAd-QhoWKIKS2C1kErl9plJWaPraZkfjY,28
9
+ docs/sofar.rst,sha256=uJ_NCeXUJKFURnuQCZbKON7JwbbTdAFSlrb--symugo,1479
10
+ docs/resources/conventions.py,sha256=4ewEa-AGBkem-VWbfUbXWMy6UUv3DFu2cGETPo89GCc,6052
11
+ docs/resources/working_with_sofa_HRIR_lateral.png,sha256=VpNNtT52Jsl6ymrY9bs1mbNWyCg9S0Ewi1I0CSHB4aE,42425
12
+ docs/resources/working_with_sofa_source_horizontal.png,sha256=rKvTCt4j_JtR1JGHPSu1pIySNTAH-PRog0hMOjBQXLM,125698
13
+ docs/resources/working_with_sofa_source_lateral.png,sha256=H1VhLtBOjJV6m62fN2vrMzoq6NTOYLmLUfIQLHqL49I,140443
14
+ sofar/__init__.py,sha256=ADa6pEg3ehw9Zy6ExRztvtCjrcwDkU4DUBrlQ3v12jE,688
15
+ sofar/io.py,sha256=kN8BcofSYb2Ew5NfBEN-C72wxep9Qw9s5Dmpypprnp8,16053
16
+ sofar/sofa.py,sha256=yIl00ekMthqJPmpiujfM-Hlb4IuqOpcGPQcIRJA8DW0,69887
17
+ sofar/sofastream.py,sha256=OAHC4nzzR7a4uksUeMawYGMzCNBQQg2gk7PK20Rn6xo,9988
18
+ sofar/update_conventions.py,sha256=XKylP9n7vRiJUOg4HBZXmDut_MbgNZ9-HZUs52xACtc,18137
19
+ sofar/utils.py,sha256=_3dH_fUBLmVlD6DD4Zc7akXk-lTY0DAPJzS4DnX0iyo,10838
20
+ sofar/sofa_conventions/VERSION,sha256=IuQRql5P3qfPUQuJwuh-RX5TvI_Wd4bDdSm8VLNQqds,34
21
+ sofar/sofa_conventions/write_upgrade_rules.py,sha256=7I2UlOwtuYfpV3L14zehZH0TZ2Kz9cxYz1fxgfg124w,4805
22
+ sofar/sofa_conventions/write_verification_data.py,sha256=vIE7UQRGlUziCeNv3kwV5CtELXh9h-_AWFsbEsn-g1M,10767
23
+ sofar/sofa_conventions/write_verification_rules.py,sha256=oOrgDA7tOgnymtXmDih7s7XiRj28Xkj--A8ihaOFRM0,13871
24
+ sofar/sofa_conventions/conventions/AnnotatedEmitterAudio_0.2.csv,sha256=q1fOy9QqskNjsV2b-rn9GDTThOo-AUKGORMmXSgp83w,2348
25
+ sofar/sofa_conventions/conventions/AnnotatedEmitterAudio_0.2.json,sha256=lznoLbG6HYvPAZ-alVoWgfBXHFDeMb0PNnyOWoag3-Y,8420
26
+ sofar/sofa_conventions/conventions/AnnotatedReceiverAudio_0.2.csv,sha256=MHBEkaSfiHm-d-8EAqL40M-0wt8couJfO2Q-Ff4SoEs,2360
27
+ sofar/sofa_conventions/conventions/AnnotatedReceiverAudio_0.2.json,sha256=2Wf1XgP4BNhI1lNlgnFabX6mUC2pT0IGLW92mjY82hY,8432
28
+ sofar/sofa_conventions/conventions/FreeFieldDirectivityTF_1.1.csv,sha256=Wait37FTh6ROKgpX7-JsVM-ohtKfsdHjxVL5vN7uTTs,5510
29
+ sofar/sofa_conventions/conventions/FreeFieldDirectivityTF_1.1.json,sha256=sm8Pj_Z1n1tW2jYlu00eikR3yCcANEm_Kw5Eq9jrbw4,13138
30
+ sofar/sofa_conventions/conventions/FreeFieldHRIR_1.0.csv,sha256=C_fc7wHjBLc2krPja33sQaDSZDvlr80GSsgOj904GBY,2479
31
+ sofar/sofa_conventions/conventions/FreeFieldHRIR_1.0.json,sha256=-777Wo-fgKq844AwxIlompmIF9rHLRXWIAJjgaqADdU,8127
32
+ sofar/sofa_conventions/conventions/FreeFieldHRTF_1.0.csv,sha256=BbE417cDQ6eQ8UFl3MVWv9SatQ2OHZ7UF7u_ZCfCoBk,2222
33
+ sofar/sofa_conventions/conventions/FreeFieldHRTF_1.0.json,sha256=aN7x7UU-HkT5a-cVmJ29IXP1h_8DFsyInsbWFm65oVk,7996
34
+ sofar/sofa_conventions/conventions/GeneralFIR-E_2.0.csv,sha256=daSPbImANSYn5rIHQkn6fdD3kE0Z-wq9iyCGfMEroGY,1998
35
+ sofar/sofa_conventions/conventions/GeneralFIR-E_2.0.json,sha256=ERs0oQrZL2JLQOcFE7umPIOIMqm2pQy_lOA8UPtLg18,6615
36
+ sofar/sofa_conventions/conventions/GeneralFIR_1.0.csv,sha256=HInvJ980U9wtu2QUT9JZ3rUlR7Qfi2yzgZb4j3q6n58,2011
37
+ sofar/sofa_conventions/conventions/GeneralFIR_1.0.json,sha256=dmVz1aTMv-9EKO9NwzTbWq-QU-uOa9d-zhS4ScKhDLU,7054
38
+ sofar/sofa_conventions/conventions/GeneralSOS_1.0.csv,sha256=3JzYYRULpd8WmCC0Mze6wTzr7PluwEjy6lxt74VDsow,2130
39
+ sofar/sofa_conventions/conventions/GeneralSOS_1.0.json,sha256=3FYXzhcb2jJFjlKFlF60Uv_82boZUNbfSVlS54It8xM,7357
40
+ sofar/sofa_conventions/conventions/GeneralTF-E_1.0.csv,sha256=lztME1Skiac-Bj1OctWuQ05_THozrPzil6a01F9PufI,2015
41
+ sofar/sofa_conventions/conventions/GeneralTF-E_1.0.json,sha256=bQZn8O67anSvZJgo7PkIP9TaPprBlhqPmzpp6dy8LQY,6757
42
+ sofar/sofa_conventions/conventions/GeneralTF_1.0.csv,sha256=RD1aXHuRIECKkHDZm0cLyRp-m32-hg_hRxNegdJnttc,1956
43
+ sofar/sofa_conventions/conventions/GeneralTF_1.0.json,sha256=mPbpQcfEeJt2lKJODGgEgusDOzLU3HbmD3Fr6LbXnt0,6696
44
+ sofar/sofa_conventions/conventions/GeneralTF_2.0.csv,sha256=8fpM1wnY4YL9DbIwstrU5UCokh9rheiookSJYSMqKR8,1957
45
+ sofar/sofa_conventions/conventions/GeneralTF_2.0.json,sha256=pn6V2AVJum8y0L0cpn3Kt5ostsmErjcF41_XeiPdk88,6699
46
+ sofar/sofa_conventions/conventions/SimpleFreeFieldHRIR_1.0.csv,sha256=gZ_jA2hAdetCxgV3P-I9T3QTG7hNwogon0r1pKpv8iM,2239
47
+ sofar/sofa_conventions/conventions/SimpleFreeFieldHRIR_1.0.json,sha256=ScZn_Jf9AI1o6gyFcdl5xFzdnvSfuMcdyG9GH5eOdDc,8446
48
+ sofar/sofa_conventions/conventions/SimpleFreeFieldHRSOS_1.0.csv,sha256=YXI6K_HiGH6wVTr3QIUhhtKQRKD3uUaj56D6xzCYUzE,2303
49
+ sofar/sofa_conventions/conventions/SimpleFreeFieldHRSOS_1.0.json,sha256=dG_O9QiWYrB8IkZD-z3W1GUJw8E_c7NT5CN4xOmhhwk,8254
50
+ sofar/sofa_conventions/conventions/SimpleFreeFieldHRTF_1.0.csv,sha256=x7fyeLrub2clGMszUtv6v9lg2cF8hI-FzeAqJEimXyc,2015
51
+ sofar/sofa_conventions/conventions/SimpleFreeFieldHRTF_1.0.json,sha256=HFNW4_1A3t1M6geUTUVLZrf7sAmhy59T47d__YXdylM,7791
52
+ sofar/sofa_conventions/conventions/SimpleFreeFieldSOS_1.0.csv,sha256=YphFfFEwTSosaYOTbUv2gz-Pb5yrQv7AFVZuXh-WUjM,2298
53
+ sofar/sofa_conventions/conventions/SimpleFreeFieldSOS_1.0.json,sha256=SILNWPWs3JFVtnDvKDpyZ3RBGboD8SWaqmaT83EUb7w,8249
54
+ sofar/sofa_conventions/conventions/SimpleHeadphoneIR_1.0.csv,sha256=7B_ijKN7AVftugYTvCCM8n76ofs8gCWkBvFc_9D-STk,3103
55
+ sofar/sofa_conventions/conventions/SimpleHeadphoneIR_1.0.json,sha256=pUUme-CuoipR06Yi26yfntWwMMWs7wrriqseg6NPK2M,9863
56
+ sofar/sofa_conventions/conventions/SingleRoomMIMOSRIR_1.0.csv,sha256=2OzG5t9rYzDrywP__99ylHmyAM9Mjx758jO5dudv0Jc,4053
57
+ sofar/sofa_conventions/conventions/SingleRoomMIMOSRIR_1.0.json,sha256=5tjPriXZk8WEIr15i41L7hQRwAxzw_gA0nxWkZfe_7g,14346
58
+ sofar/sofa_conventions/conventions/SingleRoomSRIR_1.0.csv,sha256=l7aeLNxbOyXgfQIjCo3QzpRpBonMp9ssfhps4fejHxc,4199
59
+ sofar/sofa_conventions/conventions/SingleRoomSRIR_1.0.json,sha256=gVwyzGni9e3w5wehnxe6Oe5knO2Np5doHYLzRsfrlfc,14491
60
+ sofar/sofa_conventions/conventions/deprecated/AnnotatedEmitterAudio_0.1.csv,sha256=pHwICgmCtMNdGBHPItuydYuX32myAEqCWtGSKBJR8_s,2355
61
+ sofar/sofa_conventions/conventions/deprecated/AnnotatedEmitterAudio_0.1.json,sha256=p-WppnTuOaEFj0WlKxiM47H92pmHkIFZ9jX6TV0iLQE,8403
62
+ sofar/sofa_conventions/conventions/deprecated/AnnotatedReceiverAudio_0.1.csv,sha256=A8doF2goKhvf1QumQOx-k_MsZKVJRHZiRbYCAXjxrTI,2367
63
+ sofar/sofa_conventions/conventions/deprecated/AnnotatedReceiverAudio_0.1.json,sha256=dzSUPEqXT0BG0TeTa7r4zZJS01le1dJTdftBOgUXV18,8415
64
+ sofar/sofa_conventions/conventions/deprecated/FreeFieldDirectivityTF_1.0.csv,sha256=Ha6178_LxRod-L2UcI7SX3o6Cf1YRFs1zgIpn0kd0rA,5125
65
+ sofar/sofa_conventions/conventions/deprecated/FreeFieldDirectivityTF_1.0.json,sha256=GcOb3cbv63C7S4cJ7IVvU7NAAd1h8mA7RHaAFQ_jqz8,12627
66
+ sofar/sofa_conventions/conventions/deprecated/GeneralFIRE_1.0.csv,sha256=2_ed7Y0CGJmCx9V3X7L4gipJ94nLzH7Jl9fXXtI7rLQ,1988
67
+ sofar/sofa_conventions/conventions/deprecated/GeneralFIRE_1.0.json,sha256=y3A1fhyS4XUAIbEGv92pwrYp01HutgIKajI4WmJYYKQ,6603
68
+ sofar/sofa_conventions/conventions/deprecated/MultiSpeakerBRIR_0.3.csv,sha256=E_jW15CNWUsp5W9Uw2EbNNyvDxDMFvs-CAELDmYtp0I,2560
69
+ sofar/sofa_conventions/conventions/deprecated/MultiSpeakerBRIR_0.3.json,sha256=PBC2SOliEORqJpuSweO77_tePFBVVoJ6zZ_COUNrZME,8884
70
+ sofar/sofa_conventions/conventions/deprecated/SimpleFreeFieldHRIR_0.4.csv,sha256=WQRiDw51jZK9yGyfCtUVGpKbi0FMl-BtG2yn-5s5AME,2093
71
+ sofar/sofa_conventions/conventions/deprecated/SimpleFreeFieldHRIR_0.4.json,sha256=sGWA33puXRpPmoMOZfBT0SgbLGIJIACNcxsJdACmKKY,7704
72
+ sofar/sofa_conventions/conventions/deprecated/SimpleFreeFieldTF_0.4.csv,sha256=lHINbpcuvHBNsAOL6KGWPy3SMEHorFcovgafXivBt0w,1989
73
+ sofar/sofa_conventions/conventions/deprecated/SimpleFreeFieldTF_0.4.json,sha256=RIAUjtb5QvLn3dny_b4uxdsHXD0nkxbK49w4RiJslJI,7770
74
+ sofar/sofa_conventions/conventions/deprecated/SimpleFreeFieldTF_1.0.csv,sha256=nzm1DDWj3blCljLFQZ1K2OU_GKgkW9x0Ow638aL_cys,2028
75
+ sofar/sofa_conventions/conventions/deprecated/SimpleFreeFieldTF_1.0.json,sha256=aXc5prNxJslNt6ESYACRHhzUxMWa80rDhvChRxGSoDM,7770
76
+ sofar/sofa_conventions/conventions/deprecated/SimpleHeadphoneIR_0.1.csv,sha256=eADQZ2qv5odeUMQsgc8YZQQA5sRN-2M3Ym5LnGrbI_E,3153
77
+ sofar/sofa_conventions/conventions/deprecated/SimpleHeadphoneIR_0.1.json,sha256=5AUrkT4s-FMFkqbVEiak7YKugtzwb0iU7o3XuYbNtYs,9870
78
+ sofar/sofa_conventions/conventions/deprecated/SimpleHeadphoneIR_0.2.csv,sha256=sBlw9J3Clix0b7aPRo-uQntM43pqBlqSG00OHJ_i7OM,3153
79
+ sofar/sofa_conventions/conventions/deprecated/SimpleHeadphoneIR_0.2.json,sha256=fHK0c3DUTvAUxOAKC1LuJZlxSyKoSjF0HpJkkpUYCyA,9870
80
+ sofar/sofa_conventions/conventions/deprecated/SingleRoomDRIR_0.2.csv,sha256=JsPEm-KgQ_b_2nGzVys4jnJTSedSQtcoOk1x31ycqLE,2045
81
+ sofar/sofa_conventions/conventions/deprecated/SingleRoomDRIR_0.2.json,sha256=oR-qubagKs28ICI7243Ep2zX0AFn_8lvYPNPseg16O8,8097
82
+ sofar/sofa_conventions/conventions/deprecated/SingleRoomDRIR_0.3.csv,sha256=l6PAKjsNuaFHVUlT4rVdZY9Pj7nh_jF8d82i5YSbkss,1999
83
+ sofar/sofa_conventions/conventions/deprecated/SingleRoomDRIR_0.3.json,sha256=ccCvFNWYwATIRCPxQke73ckogc2Y3hBP97_JOtPusns,8097
84
+ sofar/sofa_conventions/conventions/deprecated/SingleTrackedAudio_0.1.csv,sha256=Vjx7u0MaYsUFbzKPKgAWxeT9iqqNC5gF_P6RqG-dd78,2397
85
+ sofar/sofa_conventions/conventions/deprecated/SingleTrackedAudio_0.1.json,sha256=XE2ai8ybHxzrWKDUooE7LpBoiFS3pf-5RiG17Jy08E0,8650
86
+ sofar/sofa_conventions/conventions/deprecated/SingleTrackedAudio_0.2.csv,sha256=svRCzuJl_wR8Y1LUS7O_N1KkWtxTB8lrhQXBi7uif60,2727
87
+ sofar/sofa_conventions/conventions/deprecated/SingleTrackedAudio_0.2.json,sha256=g64b-uuzPlm_nXvoRgMxcydDTq5LSsX3mmeFN-tl6-w,9531
88
+ sofar/sofa_conventions/rules/deprecations.json,sha256=adYMivYOicwuAUFAsoiDcGHdhre5ZqNOhIe9BX2mM7M,534
89
+ sofar/sofa_conventions/rules/rules.json,sha256=45fbAzUczWYSpZZj7A15psx2Rh77xz56eT2CagKrwts,23096
90
+ sofar/sofa_conventions/rules/unit_aliases.json,sha256=QXgOfpe8bnmUybVhSSj3nIUYw50CAVehh7sdFNPFl0k,212
91
+ sofar/sofa_conventions/rules/upgrade.json,sha256=0o9sTQELnEUXl_teZLjO1Azx7yqrTHmYzT8_7VB9LtM,6025
92
+ tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
93
+ tests/conftest.py,sha256=3J_BsyJ-_L5145UY_17pb56AptLZr62QFt-zhzE0OE8,738
94
+ tests/test_deprecations.py,sha256=mIlI1utzIiisKrerd9gZjxVLy2N5l2Jtg9dpWuJ0o7M,610
95
+ tests/test_io.py,sha256=Xpg9Or9z-91lm6n9-fZXVoyx5CZpgWZ7unJ0wtN3-0Q,12112
96
+ tests/test_sofa.py,sha256=YcG1BlA2_6IrE9RvcHcUh2k_XtoRP8nWjLiMbgkqUK0,11450
97
+ tests/test_sofa_upgrade_conventions.py,sha256=bZbatBojTSRkJDFK-VCohkZqvVV7j8cOBC2qVzNFYU4,3726
98
+ tests/test_sofa_verify.py,sha256=D0_mcv5h-4OE198URWWOuFrp4bpqrLWQZ7wOP80PbYI,16074
99
+ tests/test_sofastream.py,sha256=tdTX6qxaUY3bX5pVcHpJxASuLj2k2aqtL1Qyu7hPc24,3905
100
+ tests/test_utils.py,sha256=edpDH6AqwlBp3l8hw_4THLN4yhHfp8Ih61pVyIAiAVU,8825
101
+ sofar-1.2.1.dist-info/LICENSE,sha256=OOdX8H69BDppTN8KCBp8l2_yDbH6sW-YuSEKDgZPuL4,1079
102
+ sofar-1.2.1.dist-info/METADATA,sha256=WXrHLyWVmwqHGsDP-wVZFcAsSa6o_bHUey9GkQzx4kQ,6433
103
+ sofar-1.2.1.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
104
+ sofar-1.2.1.dist-info/top_level.txt,sha256=5YyQsRMOJOaaykMzffbmmHklMAiAw8g1BWOcLxiN110,17
105
+ sofar-1.2.1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (75.6.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,3 @@
1
+ docs
2
+ sofar
3
+ tests
tests/__init__.py ADDED
File without changes
tests/conftest.py ADDED
@@ -0,0 +1,27 @@
1
+ import pytest
2
+ import numpy as np
3
+ import sofar as sf
4
+
5
+
6
+ # Temporary SOFA-file
7
+ @pytest.fixture
8
+ def temp_sofa_file(tmp_path_factory):
9
+ """
10
+ Temporary small SOFA file.
11
+ To be used when data needs to be read from a SOFA file for testing.
12
+ Contains custom data for "Data_IR", "GLOBAL_RoomType" and
13
+ "Data_SamplingRate_Units".
14
+
15
+ Returns
16
+ -------
17
+ filename : SOFA file
18
+ Filename of temporary SOFA file
19
+ """
20
+
21
+ filename = tmp_path_factory.mktemp("data") / "test_sofastream.sofa"
22
+ sofa = sf.Sofa("SimpleFreeFieldHRIR")
23
+ sofa.Data_IR = np.array([[0, 1], [2, 3], [4, 5]])
24
+ sofa.GLOBAL_RoomType = "free field"
25
+ sofa.Data_SamplingRate_Units = "hertz"
26
+ sf.write_sofa(filename, sofa)
27
+ return filename
@@ -0,0 +1,19 @@
1
+ import pytest
2
+ from packaging import version
3
+ import re
4
+ import sofar as sf
5
+
6
+
7
+ # deprecate in 1.3.0 ----------------------------------------------------------
8
+ def test_pad_zero_modi():
9
+ with pytest.warns(
10
+ UserWarning,
11
+ match=re.escape('Sofa.info() will be deprecated in sofar 1.3.0')):
12
+ sofa = sf.Sofa('GeneralTF')
13
+ sofa.info()
14
+
15
+ if version.parse(sf.__version__) >= version.parse('1.3.0'):
16
+ sofa = sf.Sofa('GeneralTF')
17
+ with pytest.raises(AttributeError, match='has no attribute'):
18
+ # remove Sofa.info() from pyfar 1.3.0!
19
+ sofa.info()