surfacetopography 0.91.2__py3.6-linux-x86_64.egg

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 (129) hide show
  1. EGG-INFO/PKG-INFO +11 -0
  2. EGG-INFO/SOURCES.txt +96 -0
  3. EGG-INFO/dependency_links.txt +1 -0
  4. EGG-INFO/native_libs.txt +1 -0
  5. EGG-INFO/not-zip-safe +1 -0
  6. EGG-INFO/requires.txt +6 -0
  7. EGG-INFO/top_level.txt +3 -0
  8. SurfaceTopography/ChangeLog.md +358 -0
  9. SurfaceTopography/Converters.py +197 -0
  10. SurfaceTopography/Generation.py +440 -0
  11. SurfaceTopography/HeightContainer.py +315 -0
  12. SurfaceTopography/IO/DI.py +261 -0
  13. SurfaceTopography/IO/FromFile.py +802 -0
  14. SurfaceTopography/IO/H5.py +79 -0
  15. SurfaceTopography/IO/IBW.py +176 -0
  16. SurfaceTopography/IO/MI.py +307 -0
  17. SurfaceTopography/IO/Matlab.py +106 -0
  18. SurfaceTopography/IO/NC.py +228 -0
  19. SurfaceTopography/IO/NPY.py +139 -0
  20. SurfaceTopography/IO/OPDx.py +885 -0
  21. SurfaceTopography/IO/Reader.py +389 -0
  22. SurfaceTopography/IO/__init__.py +241 -0
  23. SurfaceTopography/IO/__pycache__/DI.cpython-36.pyc +0 -0
  24. SurfaceTopography/IO/__pycache__/FromFile.cpython-36.pyc +0 -0
  25. SurfaceTopography/IO/__pycache__/H5.cpython-36.pyc +0 -0
  26. SurfaceTopography/IO/__pycache__/IBW.cpython-36.pyc +0 -0
  27. SurfaceTopography/IO/__pycache__/MI.cpython-36.pyc +0 -0
  28. SurfaceTopography/IO/__pycache__/Matlab.cpython-36.pyc +0 -0
  29. SurfaceTopography/IO/__pycache__/NC.cpython-36.pyc +0 -0
  30. SurfaceTopography/IO/__pycache__/NPY.cpython-36.pyc +0 -0
  31. SurfaceTopography/IO/__pycache__/OPDx.cpython-36.pyc +0 -0
  32. SurfaceTopography/IO/__pycache__/Reader.cpython-36.pyc +0 -0
  33. SurfaceTopography/IO/__pycache__/__init__.cpython-36.pyc +0 -0
  34. SurfaceTopography/Interpolation.py +30 -0
  35. SurfaceTopography/Nonuniform/Autocorrelation.py +161 -0
  36. SurfaceTopography/Nonuniform/Detrending.py +87 -0
  37. SurfaceTopography/Nonuniform/PowerSpectrum.py +178 -0
  38. SurfaceTopography/Nonuniform/ScalarParameters.py +140 -0
  39. SurfaceTopography/Nonuniform/VariableBandwidth.py +155 -0
  40. SurfaceTopography/Nonuniform/__init__.py +28 -0
  41. SurfaceTopography/Nonuniform/__pycache__/Autocorrelation.cpython-36.pyc +0 -0
  42. SurfaceTopography/Nonuniform/__pycache__/Detrending.cpython-36.pyc +0 -0
  43. SurfaceTopography/Nonuniform/__pycache__/PowerSpectrum.cpython-36.pyc +0 -0
  44. SurfaceTopography/Nonuniform/__pycache__/ScalarParameters.cpython-36.pyc +0 -0
  45. SurfaceTopography/Nonuniform/__pycache__/VariableBandwidth.cpython-36.pyc +0 -0
  46. SurfaceTopography/Nonuniform/__pycache__/__init__.cpython-36.pyc +0 -0
  47. SurfaceTopography/Nonuniform/__pycache__/common.cpython-36.pyc +0 -0
  48. SurfaceTopography/Nonuniform/common.py +95 -0
  49. SurfaceTopography/NonuniformLineScan.py +310 -0
  50. SurfaceTopography/Special.py +225 -0
  51. SurfaceTopography/Tools/__init__.py +28 -0
  52. SurfaceTopography/Tools/__pycache__/__init__.cpython-36.pyc +0 -0
  53. SurfaceTopography/Tools/__pycache__/common.cpython-36.pyc +0 -0
  54. SurfaceTopography/Tools/common.py +75 -0
  55. SurfaceTopography/Uniform/Autocorrelation.py +211 -0
  56. SurfaceTopography/Uniform/Detrending.py +155 -0
  57. SurfaceTopography/Uniform/Filtering.py +226 -0
  58. SurfaceTopography/Uniform/Interpolation.py +159 -0
  59. SurfaceTopography/Uniform/PowerSpectrum.py +197 -0
  60. SurfaceTopography/Uniform/ScalarParameters.py +173 -0
  61. SurfaceTopography/Uniform/VariableBandwidth.py +169 -0
  62. SurfaceTopography/Uniform/__init__.py +28 -0
  63. SurfaceTopography/Uniform/__pycache__/Autocorrelation.cpython-36.pyc +0 -0
  64. SurfaceTopography/Uniform/__pycache__/Detrending.cpython-36.pyc +0 -0
  65. SurfaceTopography/Uniform/__pycache__/Filtering.cpython-36.pyc +0 -0
  66. SurfaceTopography/Uniform/__pycache__/Interpolation.cpython-36.pyc +0 -0
  67. SurfaceTopography/Uniform/__pycache__/PowerSpectrum.cpython-36.pyc +0 -0
  68. SurfaceTopography/Uniform/__pycache__/ScalarParameters.cpython-36.pyc +0 -0
  69. SurfaceTopography/Uniform/__pycache__/VariableBandwidth.cpython-36.pyc +0 -0
  70. SurfaceTopography/Uniform/__pycache__/__init__.cpython-36.pyc +0 -0
  71. SurfaceTopography/Uniform/__pycache__/common.cpython-36.pyc +0 -0
  72. SurfaceTopography/Uniform/common.py +260 -0
  73. SurfaceTopography/UniformLineScanAndTopography.py +887 -0
  74. SurfaceTopography/__init__.py +62 -0
  75. SurfaceTopography/__pycache__/Converters.cpython-36.pyc +0 -0
  76. SurfaceTopography/__pycache__/Generation.cpython-36.pyc +0 -0
  77. SurfaceTopography/__pycache__/HeightContainer.cpython-36.pyc +0 -0
  78. SurfaceTopography/__pycache__/Interpolation.cpython-36.pyc +0 -0
  79. SurfaceTopography/__pycache__/NonuniformLineScan.cpython-36.pyc +0 -0
  80. SurfaceTopography/__pycache__/Special.cpython-36.pyc +0 -0
  81. SurfaceTopography/__pycache__/UniformLineScanAndTopography.cpython-36.pyc +0 -0
  82. SurfaceTopography/__pycache__/__init__.cpython-36.pyc +0 -0
  83. SurfaceTopography/__pycache__/common.cpython-36.pyc +0 -0
  84. SurfaceTopography/common.py +111 -0
  85. _SurfaceTopography.cpython-36m-x86_64-linux-gnu.so +0 -0
  86. _SurfaceTopography.py +8 -0
  87. __pycache__/_SurfaceTopography.cpython-36.pyc +0 -0
  88. test/IO/__init__.py +28 -0
  89. test/IO/__pycache__/__init__.cpython-36.pyc +0 -0
  90. test/IO/__pycache__/test_ibw.cpython-36.pyc +0 -0
  91. test/IO/__pycache__/test_io.cpython-36.pyc +0 -0
  92. test/IO/__pycache__/test_mi.cpython-36.pyc +0 -0
  93. test/IO/__pycache__/test_netcdf.cpython-36.pyc +0 -0
  94. test/IO/__pycache__/test_npy.cpython-36.pyc +0 -0
  95. test/IO/__pycache__/test_opdx.cpython-36.pyc +0 -0
  96. test/IO/test_ibw.py +178 -0
  97. test/IO/test_io.py +401 -0
  98. test/IO/test_mi.py +103 -0
  99. test/IO/test_netcdf.py +134 -0
  100. test/IO/test_npy.py +135 -0
  101. test/IO/test_opdx.py +441 -0
  102. test/__init__.py +26 -0
  103. test/__pycache__/__init__.cpython-36.pyc +0 -0
  104. test/__pycache__/compare-orientation-with-gwyddion.cpython-36.pyc +0 -0
  105. test/__pycache__/conftest.cpython-36.pyc +0 -0
  106. test/__pycache__/test_autocorrelation.cpython-36.pyc +0 -0
  107. test/__pycache__/test_bicubic.cpython-36.pyc +0 -0
  108. test/__pycache__/test_filtering.cpython-36.pyc +0 -0
  109. test/__pycache__/test_generation.cpython-36.pyc +0 -0
  110. test/__pycache__/test_import.cpython-36.pyc +0 -0
  111. test/__pycache__/test_make_sphere.cpython-36.pyc +0 -0
  112. test/__pycache__/test_power_spectrum.cpython-36.pyc +0 -0
  113. test/__pycache__/test_scalar_parameters.cpython-36.pyc +0 -0
  114. test/__pycache__/test_topography1.cpython-36.pyc +0 -0
  115. test/__pycache__/test_topography2.cpython-36.pyc +0 -0
  116. test/__pycache__/test_variable_bandwidth.cpython-36.pyc +0 -0
  117. test/compare-orientation-with-gwyddion.py +102 -0
  118. test/conftest.py +80 -0
  119. test/test_autocorrelation.py +311 -0
  120. test/test_bicubic.py +190 -0
  121. test/test_filtering.py +69 -0
  122. test/test_generation.py +259 -0
  123. test/test_import.py +54 -0
  124. test/test_make_sphere.py +108 -0
  125. test/test_power_spectrum.py +259 -0
  126. test/test_scalar_parameters.py +176 -0
  127. test/test_topography1.py +1287 -0
  128. test/test_topography2.py +328 -0
  129. test/test_variable_bandwidth.py +107 -0
@@ -0,0 +1,389 @@
1
+ #
2
+ # Copyright 2019-2020 Lars Pastewka
3
+ # 2019-2020 Antoine Sanner
4
+ # 2019-2020 Michael Röttger
5
+ # 2019 Kai Haase
6
+ #
7
+ # ### MIT license
8
+ #
9
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
10
+ # of this software and associated documentation files (the "Software"), to deal
11
+ # in the Software without restriction, including without limitation the rights
12
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ # copies of the Software, and to permit persons to whom the Software is
14
+ # furnished to do so, subject to the following conditions:
15
+ #
16
+ # The above copyright notice and this permission notice shall be included in
17
+ # all copies or substantial portions of the Software.
18
+ #
19
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
+ # SOFTWARE.
26
+ #
27
+
28
+ import abc
29
+ import warnings
30
+
31
+ import numpy as np
32
+
33
+
34
+ class ChannelInfo:
35
+ """
36
+ Information on topography channels contained within a file. The interface
37
+ is identical to :obj:`HeightContainer` and subclasses.
38
+ """
39
+
40
+ def __init__(self, reader, index, name=None, dim=None, nb_grid_pts=None,
41
+ physical_sizes=None, periodic=None,
42
+ info={}):
43
+ """
44
+ Initialize the channel. Use as many information from the file as
45
+ possible by passing it in the keyword arguments.
46
+
47
+ Arguments
48
+ ---------
49
+ reader: ReaderBase
50
+ Reader instance this channel is coming from.
51
+ index: int
52
+ Index of channel in the file, where zero is the first channel.
53
+ name: str
54
+ Name of the channel. If no name is given, "channel <index>" will
55
+ be used, where "<index>" is replaced with the index.
56
+ dim: int
57
+ Number of dimensions.
58
+ nb_grid_pts: tuple of ints
59
+ Number grid points in each dimension.
60
+ physical_sizes: tuple of floats
61
+ Physical dimensions.
62
+ periodic: bool
63
+ Wether the SurfaceTopography should be interpreted as one period of
64
+ a periodic surface. This will affect the PSD and autocorrelation
65
+ calculations (windowing).
66
+ info: dict
67
+ Meta data found in the file.
68
+ """
69
+ self._reader = reader
70
+ self._index = int(index)
71
+ self._name = "channel {}".format(self._index) \
72
+ if name is None else str(name)
73
+ self._dim = dim
74
+ self._nb_grid_pts = None \
75
+ if nb_grid_pts is None else tuple(np.ravel(nb_grid_pts))
76
+ self._physical_sizes = None \
77
+ if physical_sizes is None else tuple(np.ravel(physical_sizes))
78
+ self._periodic = periodic
79
+ self._info = info.copy()
80
+
81
+ def topography(self, physical_sizes=None,
82
+ height_scale_factor=None, info={},
83
+ periodic=False,
84
+ subdomain_locations=None, nb_subdomain_grid_pts=None):
85
+ """
86
+ Returns an instance of a subclass of :obj:`HeightContainer` that
87
+ contains the topography data. The method allows to override data
88
+ found in the data file.
89
+
90
+ Arguments
91
+ ---------
92
+ physical_sizes : tuple of floats
93
+ Physical size of the topography. It is necessary to specify this
94
+ if no physical size is found in the data file. If there is a
95
+ physical size, then this parameter will override the physical
96
+ size found in the data file.
97
+ height_scale_factor : float
98
+ Override height scale factor found in the data file.
99
+ info : dict
100
+ This dictionary will be appended to the info dictionary returned
101
+ by the reader.
102
+ periodic: bool
103
+ Wether the SurfaceTopography should be interpreted as one period of
104
+ a periodic surface. This will affect the PSD and autocorrelation
105
+ calculations (windowing)
106
+ subdomain_locations : tuple of ints
107
+ Origin (location) of the subdomain handled by the present MPI
108
+ process.
109
+ nb_subdomain_grid_pts : tuple of ints
110
+ Number of grid points within the subdomain handled by the present
111
+ MPI process.
112
+
113
+ Returns
114
+ -------
115
+ topography : subclass of :obj:`HeightContainer`
116
+ The object containing the actual topography data.
117
+ """
118
+ return self._reader.topography(
119
+ channel_index=self._index,
120
+ physical_sizes=physical_sizes,
121
+ height_scale_factor=height_scale_factor,
122
+ info=info,
123
+ periodic=periodic,
124
+ subdomain_locations=subdomain_locations,
125
+ nb_subdomain_grid_pts=nb_subdomain_grid_pts)
126
+
127
+ @property
128
+ def index(self):
129
+ """Unique integer channel index."""
130
+ return self._index
131
+
132
+ @property
133
+ def name(self):
134
+ '''
135
+ Name of the channel.
136
+ Can be used in a UI for identifying a channel.
137
+ '''
138
+ return self._name
139
+
140
+ @property
141
+ def dim(self):
142
+ """
143
+ 1 for line scans and 2 for topography maps.
144
+ """
145
+ return self._dim
146
+
147
+ @property
148
+ def nb_grid_pts(self):
149
+ """
150
+ Number of grid points in each direction, either 1 or 2 elements
151
+ depending on the dimension of the topography.
152
+ """
153
+ return self._nb_grid_pts
154
+
155
+ @property
156
+ def physical_sizes(self):
157
+ """
158
+ If the physical size can be determined from the file, a tuple is
159
+ returned. The tuple has 1 or 2 elements (size_x, size_y), depending
160
+ on the dimension of the topography.
161
+
162
+ If the physical size can not be determined from the file, then
163
+ None is returned.
164
+
165
+ Note that the physical sizes obtained from the file can be
166
+ overwritten by passing a `physical_sizes` argument to the
167
+ `topography` method that returns the topography object.
168
+ """
169
+ return self._physical_sizes
170
+
171
+ @property
172
+ def is_periodic(self):
173
+ """
174
+ Return whether the topography is periodically repeated at the
175
+ boundaries.
176
+ """
177
+ return self._periodic
178
+
179
+ @property
180
+ def pixel_size(self):
181
+ """
182
+ The pixel size is returned as the phyiscal size divided by the number
183
+ of grid points. If the physical size can be determined from the file,
184
+ a tuple is returned. The tuple has 1 or 2 elements (size_x, size_y),
185
+ depending on the dimension of the topography.
186
+
187
+ If the physical size can not be determined from the file, then
188
+ None is returned.
189
+
190
+ Note that the physical sizes obtained from the file can be overwritten
191
+ by passing a `physical_sizes` argument to the `topography` method that
192
+ returns the topography object. Overriding the physical size will also
193
+ affect the pixel size.
194
+ """
195
+ if self._physical_sizes is None or self._nb_grid_pts is None:
196
+ return None
197
+ else:
198
+ return tuple(np.array(self._physical_sizes) /
199
+ np.array(self._nb_grid_pts))
200
+
201
+ @property
202
+ def area_per_pt(self):
203
+ """
204
+ The area per point is returned as the product over the pixel size
205
+ tuple. If `pixel_size` returns None, than also `area_per_pt` returns
206
+ None.s
207
+ """
208
+ if self.pixel_size is None:
209
+ return None
210
+ else:
211
+ return np.prod(self.pixel_size)
212
+
213
+ @property
214
+ def info(self):
215
+ """
216
+ A dictionary containing additional information (metadata) not used by
217
+ PyCo itself, but required by third-party application.
218
+
219
+ Presently, the following entries have been standardized:
220
+ 'unit':
221
+ This is the unit of the physical size (if given in the file) and
222
+ the units of the heights.
223
+ 'height_scale_factor':
224
+ Factor which was used to scale the raw numbers from file (which
225
+ can be voltages or some other quantity actually acquired in the
226
+ measurement technique) to heights with the given 'unit'.
227
+ """
228
+ return self._info
229
+
230
+
231
+ class ReaderBase(metaclass=abc.ABCMeta):
232
+ """
233
+ Base class for topography readers. These are object that allow to open a
234
+ file (from filename or stream object), inspect its metadata and then
235
+ request to load a topography from it. Metadata is typically extracted
236
+ without reading the full file.
237
+ """
238
+
239
+ _format = None
240
+ _name = None
241
+ _description = None
242
+
243
+ _default_channel_index = 0
244
+
245
+ @classmethod
246
+ def format(cls):
247
+ """
248
+ String identifier for this file format. Identifier must be unique and
249
+ is typically equal to the file extension of this format.
250
+ """
251
+ if cls._format is None:
252
+ raise RuntimeError('Reader does not provide a format string')
253
+ return cls._format
254
+
255
+ @classmethod
256
+ def name(cls):
257
+ """
258
+ Short name of this file format.
259
+ """
260
+ if cls._name is None:
261
+ raise RuntimeError('Reader does not provide a name')
262
+ return cls._name
263
+
264
+ @classmethod
265
+ def description(cls):
266
+ """
267
+ Long description of this file format. Should be formatted as markdown.
268
+ """
269
+ if cls._description is None:
270
+ raise RuntimeError('Reader does not provide a description string')
271
+ return cls._description
272
+
273
+ def __enter__(self):
274
+ return self
275
+
276
+ def __exit__(self, exc_type, exc_value, traceback):
277
+ self.close()
278
+
279
+ def close(self):
280
+ pass
281
+
282
+ @property
283
+ @abc.abstractmethod
284
+ def channels(self):
285
+ """
286
+ Returns a list of :obj:`ChannelInfo`s describing the available data
287
+ channels.
288
+ """
289
+ raise NotImplementedError
290
+
291
+ @property
292
+ def default_channel(self):
293
+ """Return the default channel. This is often the first channel with
294
+ height information."""
295
+ return self.channels[self._default_channel_index]
296
+
297
+ @classmethod
298
+ def _check_physical_sizes(self, physical_sizes_from_arg,
299
+ physical_sizes=None):
300
+ if physical_sizes is None:
301
+ if physical_sizes_from_arg is None:
302
+ raise ValueError("physical_sizes could not be extracted from "
303
+ "file, you should provide it")
304
+ else:
305
+ if physical_sizes_from_arg is None:
306
+ physical_sizes_from_arg = physical_sizes
307
+ elif tuple(physical_sizes_from_arg) != tuple(physical_sizes):
308
+ warnings.warn(
309
+ "A physical size different from the value specified when "
310
+ "calling the reader was present in the file. We will "
311
+ "ignore the value given in the file. Specified values: "
312
+ "{}; Values from file: {}".format(
313
+ physical_sizes,
314
+ physical_sizes_from_arg))
315
+ return physical_sizes_from_arg
316
+
317
+ @abc.abstractmethod
318
+ def topography(self, channel_index=None, physical_sizes=None,
319
+ height_scale_factor=None, info={},
320
+ periodic=False,
321
+ subdomain_locations=None, nb_subdomain_grid_pts=None):
322
+ """
323
+ Returns an instance of a subclass of :obj:`HeightContainer` that
324
+ contains the topography data. The method allows to override data
325
+ found in the data file.
326
+
327
+ Arguments
328
+ ---------
329
+ channel_index : int
330
+ Index of the channel to load. See also `channels` method.
331
+ (Default: None, which load the default channel)
332
+ physical_sizes : tuple of floats
333
+ Physical size of the topography. It is necessary to specify this
334
+ if no physical size is found in the data file. If there is a
335
+ physical size, then this parameter will override the physical
336
+ size found in the data file.
337
+ height_scale_factor : float
338
+ Override height scale factor found in the data file.
339
+ info : dict
340
+ This dictionary will be appended to the info dictionary returned
341
+ by the reader.
342
+ periodic: bool
343
+ Wether the SurfaceTopography should be interpreted as one period of
344
+ a periodic surface. This will affect the PSD and autocorrelation
345
+ calculations (windowing)
346
+ subdomain_locations : tuple of ints
347
+ Origin (location) of the subdomain handled by the present MPI
348
+ process.
349
+ nb_subdomain_grid_pts : tuple of ints
350
+ Number of grid points within the subdomain handled by the present
351
+ MPI process.
352
+
353
+ Returns
354
+ -------
355
+ topography : subclass of :obj:`HeightContainer`
356
+ The object containing the actual topography data.
357
+ """
358
+ raise NotImplementedError
359
+
360
+
361
+ class ReadFileError(Exception):
362
+ pass
363
+
364
+
365
+ class UnknownFileFormatGiven(ReadFileError):
366
+ pass
367
+
368
+
369
+ class CannotDetectFileFormat(ReadFileError):
370
+ """
371
+ Raised when no reader is able to open_topography the file
372
+ """
373
+ pass
374
+
375
+
376
+ class FileFormatMismatch(ReadFileError):
377
+ """
378
+ Raised when the reader cannot interpret the file at all
379
+ (obvious for txt vs binary, but holds also for a header)
380
+ """
381
+ pass
382
+
383
+
384
+ class CorruptFile(ReadFileError):
385
+ """
386
+ Raised when the reader identifies the file format as matching,
387
+ but there is a mistake, for example the number of points doesn't match
388
+ """
389
+ pass
@@ -0,0 +1,241 @@
1
+ #
2
+ # Copyright 2019-2020 Lars Pastewka
3
+ # 2020 Michael Röttger
4
+ # 2019 Kai Haase
5
+ # 2019 Antoine Sanner
6
+ #
7
+ # ### MIT license
8
+ #
9
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
10
+ # of this software and associated documentation files (the "Software"), to deal
11
+ # in the Software without restriction, including without limitation the rights
12
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ # copies of the Software, and to permit persons to whom the Software is
14
+ # furnished to do so, subject to the following conditions:
15
+ #
16
+ # The above copyright notice and this permission notice shall be included in
17
+ # all copies or substantial portions of the Software.
18
+ #
19
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
+ # SOFTWARE.
26
+ #
27
+
28
+ import os
29
+
30
+ # Old-style readers
31
+ from .FromFile import AscReader, HGTReader, OPDReader, X3PReader, XYZReader
32
+
33
+ # New-style readers
34
+ from .DI import DIReader
35
+ from .H5 import H5Reader
36
+ from .IBW import IBWReader
37
+ from .Matlab import MatReader
38
+ from .MI import MIReader
39
+ from .NC import NCReader
40
+ from .NPY import NPYReader
41
+ from .OPDx import OPDxReader
42
+
43
+ from .Reader import UnknownFileFormatGiven, CannotDetectFileFormat, \
44
+ FileFormatMismatch, CorruptFile, ReaderBase # noqa: F401
45
+
46
+ readers = [
47
+ AscReader,
48
+ DIReader,
49
+ MatReader,
50
+ OPDReader,
51
+ OPDxReader,
52
+ X3PReader,
53
+ XYZReader,
54
+ IBWReader,
55
+ MIReader,
56
+ NCReader,
57
+ # NCReader must come before H5Reader, because NC4 *is* a specialized form
58
+ # of HDF5
59
+ H5Reader,
60
+ NPYReader,
61
+ HGTReader,
62
+ ]
63
+
64
+ lookup_reader_by_format = {}
65
+ for reader in readers:
66
+ lookup_reader_by_format[reader.format()] = reader
67
+
68
+
69
+ def detect_format(fobj, comm=None):
70
+ """
71
+ Detect file format based on its content.
72
+
73
+ Arguments
74
+ ---------
75
+ fobj : filename or file object
76
+ comm : mpi communicator, optional
77
+ """
78
+ msg = ""
79
+ for reader in readers:
80
+ try:
81
+ if comm is not None:
82
+ reader(fobj, comm)
83
+ else:
84
+ reader(fobj)
85
+ return reader.format()
86
+ except Exception as err:
87
+ msg += "tried {}: \n {}\n\n".format(reader.__name__, err)
88
+ finally:
89
+ if hasattr(fobj, 'seek'):
90
+ # if the reader crashes the cursor in the file-like object
91
+ # has to be set back to the top of the file
92
+ fobj.seek(0)
93
+ raise CannotDetectFileFormat(msg)
94
+
95
+
96
+ def open_topography(fobj, format=None, communicator=None):
97
+ r"""
98
+ Returns a reader object for the file `fobj`. The reader interface mirrors
99
+ the topography interface and can be used to extract meta data (number of
100
+ grid points, physical sizes, etc.) without reading the full topography in
101
+ memory.
102
+
103
+ Parameters
104
+ ----------
105
+ fobj : str or filelike object
106
+ path of the file or filelike object
107
+ format : str, optional
108
+ specify in which format the file should be interpreted
109
+ communicator : mpi4py or NuMPI communicator object
110
+ MPI communicator handling inter-process communication
111
+
112
+ Returns
113
+ -------
114
+ Instance of a :obj:`ReaderBase` subclass according to the format.
115
+
116
+ Examples
117
+ --------
118
+ Simplest read workflow:
119
+
120
+ >>> reader = open_topography("filename")
121
+ >>> top = reader.topography()
122
+
123
+ The first topography in file is returned, independently of whether
124
+ the file has multiple channels or not.
125
+
126
+ You can always check the channels and their metadata with
127
+ `reader.channels()`. This returns a list of dicts containing attributes `name`,
128
+ `physical_sizes`, `nb_grid_pts`, ``unit` and `height_scale_factor:
129
+
130
+ >>> reader.channels
131
+ [{'name': 'ZSensor',
132
+ 'nb_grid_pts': (256, 256),
133
+ 'physical_sizes': (9999.999999999998, 9999.999999999998),
134
+ 'unit': 'nm',
135
+ 'height_scale_factor': 0.29638271279074097},
136
+ {'name': 'AmplitudeError',
137
+ 'nb_grid_pts': (256, 256),
138
+ 'physical_sizes': (10.0, 10.0),
139
+ 'unit': ('µm', None),
140
+ 'height_scale_factor': 0.04577566528320313}]
141
+
142
+ Here the channel 'ZSensor' offers a topography with sizes of
143
+ 10000 nm in each dimension.
144
+
145
+ You can choose it by giving the index 0 to channel
146
+ (you would use `channel=1` for the second):
147
+
148
+ >>> top = reader.topography(channel=0)
149
+
150
+ The returned topography has the physical sizes found in the file.
151
+
152
+ You can also prescribe some attributes when reading the topography:
153
+
154
+ >>> top = reader.topography(channel=0, physical_sizes=(10.,10.), info={"unit":"µm"})
155
+
156
+ In order to plot the topography with matplotlib, you can use
157
+
158
+ >>> plt.pcolormesh(*top.positions_and_heights())
159
+
160
+ with origin in the lower left and correct tick labels at x and y axes, or
161
+
162
+ >>> plt.imshow(top.heights().T)
163
+
164
+ with origin in the upper left (inverted y axis).
165
+ """ # noqa: E501
166
+ if communicator is not None:
167
+ kwargs = {"communicator": communicator}
168
+ else:
169
+ kwargs = {}
170
+
171
+ if not hasattr(fobj, 'read'): # fobj is a path
172
+ if not os.path.isfile(fobj):
173
+ raise FileExistsError("file {} not found".format(fobj))
174
+
175
+ if format is None:
176
+ msg = ""
177
+ for reader in readers:
178
+ try:
179
+ return reader(fobj, **kwargs)
180
+ except Exception as err:
181
+ msg += "tried {}: \n {}\n\n".format(reader.__name__, err)
182
+ finally:
183
+ if hasattr(fobj, 'seek'):
184
+ # if the reader crashes the cursor in the file-like object
185
+ # has to be set back to the top of the file
186
+ fobj.seek(0)
187
+ raise CannotDetectFileFormat(msg)
188
+ else:
189
+ if format not in lookup_reader_by_format.keys():
190
+ raise UnknownFileFormatGiven(
191
+ "{} not in registered file formats {}".format(
192
+ fobj, lookup_reader_by_format.keys()))
193
+ return lookup_reader_by_format[format](fobj, **kwargs)
194
+
195
+
196
+ def read_topography(fn, format=None, communicator=None, **kwargs):
197
+ r"""
198
+ Returns a topography object representing the topograpgy in the file `fobj`.
199
+ If there are multiple data channels within this file, the default channel
200
+ is returned. The default channel depends on the file format; see
201
+ documentation of the respective reader on this.
202
+
203
+ Parameters
204
+ ----------
205
+ fobj : str or filelike object
206
+ path of the file or filelike object
207
+ format : str, optional
208
+ specify in which format the file should be interpreted
209
+ communicator : mpi4py or NuMPI communicator object
210
+ MPI communicator handling inter-process communication
211
+ channel : int
212
+ Number of the channel to load. See also `channels` method.
213
+ physical_sizes : tuple of floats
214
+ Physical size of the topography. It is necessary to specify this
215
+ if no physical size is found in the data file. If there is a
216
+ physical size, then this parameter will override the physical
217
+ size found in the data file.
218
+ height_scale_factor : float
219
+ Override height scale factor found in the data file.
220
+ info : dict
221
+ This dictionary will be appended to the info dictionary returned
222
+ by the reader.
223
+ periodic: bool
224
+ Wether the SurfaceTopography should be interpreted as one period of a
225
+ periodic surface. This will affect the PSD and autocorrelation
226
+ calculations (windowing)
227
+ subdomain_locations : tuple of ints
228
+ Origin (location) of the subdomain handled by the present MPI process.
229
+ nb_subdomain_grid_pts : tuple of ints
230
+ Number of grid points within the subdomain handled by the present
231
+ MPI process.
232
+
233
+ Returns
234
+ -------
235
+ topography : subclass of :obj:`HeightContainer`
236
+ The object containing the actual topography data.
237
+ """
238
+ with open_topography(fn, format=format,
239
+ communicator=communicator) as reader:
240
+ t = reader.topography(**kwargs)
241
+ return t
@@ -0,0 +1,30 @@
1
+ #
2
+ # Copyright 2020 Lars Pastewka
3
+ # 2019 Antoine Sanner
4
+ #
5
+ # ### MIT license
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ # of this software and associated documentation files (the "Software"), to deal
9
+ # in the Software without restriction, including without limitation the rights
10
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ # copies of the Software, and to permit persons to whom the Software is
12
+ # furnished to do so, subject to the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be included in
15
+ # all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ # SOFTWARE.
24
+ #
25
+
26
+ """
27
+ Interpolation module
28
+ """
29
+
30
+ from _SurfaceTopography import Bicubic # noqa: F401