md2reflect 3.1.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.
@@ -0,0 +1,4 @@
1
+ # SPDX-FileCopyrightText: 2020-present Jean-François Moulin <jean-francois.moulin@hereon.de>
2
+ #
3
+ # SPDX-License-Identifier: GPL-3.0-or-later
4
+ __version__ = "3.1.1"
md2reflect/__init__.py ADDED
@@ -0,0 +1,310 @@
1
+ # SPDX-FileCopyrightText: 2020-present Jean-François Moulin <jean-francois.moulin@hereon.de>
2
+ #
3
+ # SPDX-License-Identifier: GPL-3.0-or-later
4
+
5
+ """
6
+ MD2Reflect - Molecular Dynamics to Reflectivity
7
+
8
+ A package for calculating neutron and X-ray
9
+ reflectivity from molecular dynamics simulations.
10
+
11
+ Submodules and public names are resolved lazily (PEP 562). Python
12
+ executes a package's ``__init__`` before any of its submodules, so
13
+ while this module imported everything eagerly, *any* import from the
14
+ package paid for the whole tree -- ``import md2reflect.erf_profile``
15
+ pulled in matplotlib, scipy.optimize and the plotting stack even
16
+ though ``erf_profile`` itself needs only numpy and ``scipy.special``.
17
+ Reaching a name now imports just the module that defines it.
18
+
19
+ Nothing changes for callers: ``from md2reflect import Sample``,
20
+ ``import md2reflect; md2reflect.Sample``, ``from md2reflect import *``
21
+ and ``import md2reflect.sample`` all behave exactly as before. The one
22
+ visible difference is *when* an error surfaces -- a broken or missing
23
+ optional dependency now raises on first use of the name that needs it,
24
+ rather than at ``import md2reflect``.
25
+ """
26
+
27
+ from __future__ import annotations
28
+
29
+ import importlib
30
+ from typing import TYPE_CHECKING, Any
31
+
32
+ # Eager, not lazy, and deliberately so: `md2reflect.__version__` is the
33
+ # first thing a bug report, a notebook header or a provenance record
34
+ # asks for, and it must never depend on which optional stack happens to
35
+ # be installed. `__about__` imports nothing, so this costs nothing.
36
+ # The `as __version__` spelling is the explicit re-export form (PEP
37
+ # 484): it tells ruff and mypy --strict that this name is deliberately
38
+ # part of this module's surface, rather than an unused import.
39
+ from .__about__ import __version__ as __version__
40
+
41
+ # Submodules reachable as attributes of the package.
42
+ _SUBMODULES = frozenset(
43
+ {
44
+ "abeles_minimal",
45
+ "api_overview",
46
+ "backends",
47
+ "bornagain_export",
48
+ "convolution",
49
+ "erf_profile",
50
+ "exceptions",
51
+ "export",
52
+ "materials",
53
+ "md_reader",
54
+ "reflectometer",
55
+ "region",
56
+ "sample",
57
+ "stepify",
58
+ "visualization",
59
+ }
60
+ )
61
+
62
+ # Public name -> the submodule that defines it. Kept explicit rather
63
+ # than discovered by scanning: a lazy loader that has to import
64
+ # something to find out where a name lives would defeat its own
65
+ # purpose.
66
+ _ATTR_SOURCES = {
67
+ # API discovery
68
+ "api_table": "api_overview",
69
+ "load_api": "api_overview",
70
+ "show_api": "api_overview",
71
+ # Backend factory
72
+ "get_reflectivity_backend": "backends",
73
+ # BornAgain export (optional dependency)
74
+ "to_bornagain": "bornagain_export",
75
+ # Exceptions
76
+ "Error": "exceptions",
77
+ "HomogeneousLayerError": "exceptions",
78
+ "NevotCroceAccuracyWarning": "exceptions",
79
+ "ReflectometerError": "exceptions",
80
+ "SampleError": "exceptions",
81
+ "SimReaderError": "exceptions",
82
+ "SimulatedRegionError": "exceptions",
83
+ "WavelengthMissingError": "exceptions",
84
+ # Materials
85
+ "Material": "materials",
86
+ "MaterialsLibrary": "materials",
87
+ "PACKAGED_LIBRARY": "materials",
88
+ "default_library": "materials",
89
+ "homogeneous_layer_from_material": "materials",
90
+ # Core classes
91
+ "Reflectometer": "reflectometer",
92
+ "CU_K_ALPHA": "region",
93
+ "ISOTOPE_ALIASES": "region",
94
+ "HomogeneousLayer": "region",
95
+ "Region": "region",
96
+ "SimulatedRegion": "region",
97
+ "SLDSet": "region",
98
+ "mixed_b_c": "region",
99
+ "Sample": "sample",
100
+ "SampleDesc": "sample",
101
+ "StepifiedProfile": "sample",
102
+ # State management
103
+ "CachedProperty": "state_management",
104
+ "InvalidatingProperty": "state_management",
105
+ "ManagedStateMixin": "state_management",
106
+ "cached_property": "state_management",
107
+ # Types
108
+ "FM_TO_ANGSTROM": "typing_defs",
109
+ "SLD": "typing_defs",
110
+ "Angstrom": "typing_defs",
111
+ "Angstrom3": "typing_defs",
112
+ "AngstromArray1D": "typing_defs",
113
+ "BeamDirection": "typing_defs",
114
+ "BoolArr1D": "typing_defs",
115
+ "Element": "typing_defs",
116
+ "FloatArr1D": "typing_defs",
117
+ "FloatArr2D": "typing_defs",
118
+ "IntArr1D": "typing_defs",
119
+ "InverseAngstrom": "typing_defs",
120
+ "NanoMeter": "typing_defs",
121
+ "Probe": "typing_defs",
122
+ "RegionRole": "typing_defs",
123
+ "ResolutionMethod": "typing_defs",
124
+ "RoughnessMethod": "typing_defs",
125
+ }
126
+
127
+ if TYPE_CHECKING:
128
+ # Never executed. Restated here so type checkers, IDEs and
129
+ # autocompletion see the real objects instead of the ``Any`` a
130
+ # module-level ``__getattr__`` would otherwise hand them.
131
+ from . import (
132
+ abeles_minimal,
133
+ api_overview,
134
+ backends,
135
+ bornagain_export,
136
+ convolution,
137
+ erf_profile,
138
+ exceptions,
139
+ export,
140
+ materials,
141
+ md_reader,
142
+ reflectometer,
143
+ region,
144
+ sample,
145
+ stepify,
146
+ visualization,
147
+ )
148
+ from .api_overview import api_table, load_api, show_api
149
+ from .backends import get_reflectivity_backend
150
+ from .bornagain_export import to_bornagain
151
+ from .exceptions import (
152
+ Error,
153
+ HomogeneousLayerError,
154
+ NevotCroceAccuracyWarning,
155
+ ReflectometerError,
156
+ SampleError,
157
+ SimReaderError,
158
+ SimulatedRegionError,
159
+ WavelengthMissingError,
160
+ )
161
+ from .materials import (
162
+ PACKAGED_LIBRARY,
163
+ Material,
164
+ MaterialsLibrary,
165
+ default_library,
166
+ homogeneous_layer_from_material,
167
+ )
168
+ from .reflectometer import Reflectometer
169
+ from .region import (
170
+ CU_K_ALPHA,
171
+ ISOTOPE_ALIASES,
172
+ HomogeneousLayer,
173
+ Region,
174
+ SimulatedRegion,
175
+ SLDSet,
176
+ mixed_b_c,
177
+ )
178
+ from .sample import Sample, SampleDesc, StepifiedProfile
179
+ from .state_management import (
180
+ CachedProperty,
181
+ InvalidatingProperty,
182
+ ManagedStateMixin,
183
+ cached_property,
184
+ )
185
+ from .typing_defs import (
186
+ FM_TO_ANGSTROM,
187
+ SLD,
188
+ Angstrom,
189
+ Angstrom3,
190
+ AngstromArray1D,
191
+ BeamDirection,
192
+ BoolArr1D,
193
+ Element,
194
+ FloatArr1D,
195
+ FloatArr2D,
196
+ IntArr1D,
197
+ InverseAngstrom,
198
+ NanoMeter,
199
+ Probe,
200
+ RegionRole,
201
+ ResolutionMethod,
202
+ RoughnessMethod,
203
+ )
204
+
205
+
206
+ def __getattr__(name: str) -> Any:
207
+ """Import the module behind *name* on first access (PEP 562).
208
+
209
+ The resolved object is written into the module globals, so this
210
+ runs once per name and every later lookup is an ordinary attribute
211
+ read.
212
+ """
213
+ source = _ATTR_SOURCES.get(name)
214
+ if source is not None:
215
+ module = importlib.import_module(f".{source}", __name__)
216
+ value: Any = getattr(module, name)
217
+ elif name in _SUBMODULES:
218
+ value = importlib.import_module(f".{name}", __name__)
219
+ else:
220
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
221
+ globals()[name] = value
222
+ return value
223
+
224
+
225
+ def __dir__() -> list[str]:
226
+ """Public names, without importing anything to list them."""
227
+ return sorted(set(__all__) | set(globals()))
228
+
229
+
230
+ __all__ = [
231
+ # NB: `__version__` is deliberately absent. `__all__` lists the
232
+ # lazily-resolved names, and the tests assert that every entry is
233
+ # reachable through _SUBMODULES or _ATTR_SOURCES -- `__version__` is
234
+ # neither, being imported eagerly above. It is also a dunder, which
235
+ # `from md2reflect import *` has no business binding. It remains
236
+ # available as `md2reflect.__version__`.
237
+ # Submodules
238
+ "abeles_minimal",
239
+ "api_overview",
240
+ "backends",
241
+ "bornagain_export",
242
+ "convolution",
243
+ "erf_profile",
244
+ "exceptions",
245
+ "export",
246
+ "materials",
247
+ "md_reader",
248
+ "reflectometer",
249
+ "region",
250
+ "sample",
251
+ "stepify",
252
+ "visualization",
253
+ # API discovery
254
+ "api_table",
255
+ "load_api",
256
+ "show_api",
257
+ # Backend factory
258
+ "get_reflectivity_backend",
259
+ # Materials
260
+ "PACKAGED_LIBRARY",
261
+ "Material",
262
+ "MaterialsLibrary",
263
+ "default_library",
264
+ "homogeneous_layer_from_material",
265
+ # Core classes
266
+ "CU_K_ALPHA",
267
+ "HomogeneousLayer",
268
+ "ISOTOPE_ALIASES",
269
+ "Reflectometer",
270
+ "Region",
271
+ "SLDSet",
272
+ "Sample",
273
+ "SampleDesc",
274
+ "SimulatedRegion",
275
+ "StepifiedProfile",
276
+ "mixed_b_c",
277
+ "to_bornagain",
278
+ # Exceptions
279
+ "Error",
280
+ "HomogeneousLayerError",
281
+ "NevotCroceAccuracyWarning",
282
+ "ReflectometerError",
283
+ "SampleError",
284
+ "SimReaderError",
285
+ "SimulatedRegionError",
286
+ "WavelengthMissingError",
287
+ # State management
288
+ "CachedProperty",
289
+ "InvalidatingProperty",
290
+ "ManagedStateMixin",
291
+ "cached_property",
292
+ # Types
293
+ "Angstrom",
294
+ "Angstrom3",
295
+ "AngstromArray1D",
296
+ "BeamDirection",
297
+ "BoolArr1D",
298
+ "Element",
299
+ "FM_TO_ANGSTROM",
300
+ "FloatArr1D",
301
+ "FloatArr2D",
302
+ "IntArr1D",
303
+ "InverseAngstrom",
304
+ "NanoMeter",
305
+ "Probe",
306
+ "RegionRole",
307
+ "ResolutionMethod",
308
+ "RoughnessMethod",
309
+ "SLD",
310
+ ]