ncrystal-python 3.9.81__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.
- NCrystal/__init__.py +85 -0
- NCrystal/__main__.py +98 -0
- NCrystal/_chooks.py +854 -0
- NCrystal/_cli_cif2ncmat.py +269 -0
- NCrystal/_cli_endf2ncmat.py +503 -0
- NCrystal/_cli_hfg2ncmat.py +144 -0
- NCrystal/_cli_mcstasunion.py +74 -0
- NCrystal/_cli_ncmat2cpp.py +31 -0
- NCrystal/_cli_ncmat2hkl.py +180 -0
- NCrystal/_cli_nctool.py +1018 -0
- NCrystal/_cli_vdos2ncmat.py +463 -0
- NCrystal/_cli_verifyatompos.py +257 -0
- NCrystal/_cliimpl.py +307 -0
- NCrystal/_cliwrap_config.py +36 -0
- NCrystal/_common.py +499 -0
- NCrystal/_coreimpl.py +114 -0
- NCrystal/_hfgdata.py +546 -0
- NCrystal/_hklobjects.py +136 -0
- NCrystal/_is_std.py +0 -0
- NCrystal/_locatelib.py +210 -0
- NCrystal/_miscimpl.py +354 -0
- NCrystal/_mmc.py +757 -0
- NCrystal/_msg.py +60 -0
- NCrystal/_ncmat2cpp_impl.py +445 -0
- NCrystal/_ncmatimpl.py +2131 -0
- NCrystal/_numpy.py +76 -0
- NCrystal/_testimpl.py +579 -0
- NCrystal/api.py +56 -0
- NCrystal/atomdata.py +177 -0
- NCrystal/cfgstr.py +77 -0
- NCrystal/cifutils.py +1795 -0
- NCrystal/cli.py +96 -0
- NCrystal/constants.py +134 -0
- NCrystal/core.py +1910 -0
- NCrystal/datasrc.py +226 -0
- NCrystal/exceptions.py +66 -0
- NCrystal/hfg2ncmat.py +270 -0
- NCrystal/mcstasutils.py +438 -0
- NCrystal/misc.py +317 -0
- NCrystal/mmc.py +35 -0
- NCrystal/ncmat.py +778 -0
- NCrystal/ncmat2cpp.py +80 -0
- NCrystal/obsolete.py +67 -0
- NCrystal/plot.py +484 -0
- NCrystal/plugins.py +49 -0
- NCrystal/test.py +76 -0
- NCrystal/vdos.py +1034 -0
- ncrystal_python-3.9.81.dist-info/LICENSE +206 -0
- ncrystal_python-3.9.81.dist-info/METADATA +515 -0
- ncrystal_python-3.9.81.dist-info/RECORD +53 -0
- ncrystal_python-3.9.81.dist-info/WHEEL +5 -0
- ncrystal_python-3.9.81.dist-info/entry_points.txt +10 -0
- ncrystal_python-3.9.81.dist-info/top_level.txt +1 -0
NCrystal/misc.py
ADDED
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
|
|
2
|
+
################################################################################
|
|
3
|
+
## ##
|
|
4
|
+
## This file is part of NCrystal (see https://mctools.github.io/ncrystal/) ##
|
|
5
|
+
## ##
|
|
6
|
+
## Copyright 2015-2024 NCrystal developers ##
|
|
7
|
+
## ##
|
|
8
|
+
## Licensed under the Apache License, Version 2.0 (the "License"); ##
|
|
9
|
+
## you may not use this file except in compliance with the License. ##
|
|
10
|
+
## You may obtain a copy of the License at ##
|
|
11
|
+
## ##
|
|
12
|
+
## http://www.apache.org/licenses/LICENSE-2.0 ##
|
|
13
|
+
## ##
|
|
14
|
+
## Unless required by applicable law or agreed to in writing, software ##
|
|
15
|
+
## distributed under the License is distributed on an "AS IS" BASIS, ##
|
|
16
|
+
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ##
|
|
17
|
+
## See the License for the specific language governing permissions and ##
|
|
18
|
+
## limitations under the License. ##
|
|
19
|
+
## ##
|
|
20
|
+
################################################################################
|
|
21
|
+
|
|
22
|
+
"""Various utility functions and classes that do not fit elsewhere.
|
|
23
|
+
|
|
24
|
+
Of particular note, this module provides several type-erasure classes which can
|
|
25
|
+
facilitate the coding of rich and convenient interfaces able to accept many
|
|
26
|
+
input formats. For instance, the concept of "a material" in NCrystal could be
|
|
27
|
+
either an .ncmat file, a cfg-str, an in-memory string or an NCrystal.TextData
|
|
28
|
+
instance with NCMAT data, or even pre-loaded objects like Info, Scatter,
|
|
29
|
+
Absorption, or LoadedMaterial objects. Writing a function which works on "a
|
|
30
|
+
material" could therefore be quite cumbersome, but by passing the input through
|
|
31
|
+
the MaterialSource type erasure class from this module, all of these inputs can
|
|
32
|
+
be handled using a single interface.
|
|
33
|
+
|
|
34
|
+
Similar type-erasure classes exists for other types of data as well (e.g. VDOS
|
|
35
|
+
curves, generic text data, ...).
|
|
36
|
+
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
#For client code checking all types of components:
|
|
40
|
+
standard_comp_types = ('coh_elas','incoh_elas','inelas','sans')
|
|
41
|
+
|
|
42
|
+
def detect_scattering_components( material ):
|
|
43
|
+
"""Detect which scattering components are present in the material.
|
|
44
|
+
|
|
45
|
+
More precisely, the component names listed in the standard_comp_types
|
|
46
|
+
variable will be checked, and a list of those present will be returned. Note
|
|
47
|
+
they are suitable for subsequent usage in the "comp" cfg-string
|
|
48
|
+
parameter.
|
|
49
|
+
|
|
50
|
+
Note: This detection only works for material sources which are not
|
|
51
|
+
preloaded. Trying to use this function with a preloaded material sources
|
|
52
|
+
(e.g. an NCrystal.Scatter object) will result in an error.
|
|
53
|
+
"""
|
|
54
|
+
from ._miscimpl import detect_scatcomps as _
|
|
55
|
+
return _( standard_comp_types, MaterialSource( material ) )
|
|
56
|
+
|
|
57
|
+
class MaterialSource:
|
|
58
|
+
"""
|
|
59
|
+
Generic type-erasure class for NCrystal materials in a general sence. It can
|
|
60
|
+
be used to wrap cfg-strings, NCMAT data, TextData, LoadedMaterial objects,
|
|
61
|
+
or even individual Info / Scatter / Absorption objects, etc.
|
|
62
|
+
|
|
63
|
+
The most important feature of a MaterialSource object is that it has a
|
|
64
|
+
.load(..) method which can be used to load the material into a
|
|
65
|
+
LoadedMaterial object. Some MaterialSource objects will "preloaded", in the
|
|
66
|
+
sense that they wrap already loaded objects (Info, Scatter, Absorption, or
|
|
67
|
+
LoadedMaterial objects). MaterialSource objects that are NOT "preloaded"
|
|
68
|
+
will have to do some work when the .load(..) method is invoked, but can on
|
|
69
|
+
the other hand also offer a bit more flexibility (in particular the
|
|
70
|
+
possiblity for loading with extra cfg-string parameters "appended").
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
def __init__( self, data, *,
|
|
74
|
+
fmt = None,
|
|
75
|
+
cfg_params = None,
|
|
76
|
+
plotlabel = None ):
|
|
77
|
+
"""Wrap data object. If the data object is not a preloaded physics
|
|
78
|
+
object, it is also allowed to specify cfg_params like
|
|
79
|
+
cfg_params="temp=200K;vdoslux=2". Finally, the fmt string will be
|
|
80
|
+
detected automatically, unless the fmt parameter is provided.
|
|
81
|
+
"""
|
|
82
|
+
from . import _miscimpl
|
|
83
|
+
self.__d = _miscimpl.matsrc_init( MaterialSource,
|
|
84
|
+
lambda matsrc : matsrc.__d,
|
|
85
|
+
data,cfg_params=cfg_params,fmt=fmt)
|
|
86
|
+
if plotlabel is not None:
|
|
87
|
+
self.set_plotlabel(plotlabel)
|
|
88
|
+
|
|
89
|
+
@property
|
|
90
|
+
def description( self ):
|
|
91
|
+
"""Returns a string with a MaterialSource description."""
|
|
92
|
+
return self.__d['description']
|
|
93
|
+
|
|
94
|
+
@property
|
|
95
|
+
def plotlabel( self ):
|
|
96
|
+
"""Returns a string with either a specific plotlabel or otherwise just
|
|
97
|
+
the usual description."""
|
|
98
|
+
return self.__d.get('plotlabel') or self.__d['description']
|
|
99
|
+
|
|
100
|
+
def set_plotlabel( self, lbl ):
|
|
101
|
+
"""Modify the plotting label."""
|
|
102
|
+
if self.__d.get('plotlabel') != lbl:
|
|
103
|
+
import copy
|
|
104
|
+
self.__d = copy.deepcopy(self.__d)
|
|
105
|
+
self.__d['plotlabel'] = lbl
|
|
106
|
+
|
|
107
|
+
def __str__(self):
|
|
108
|
+
return 'MaterialSource(%s)'%self.description
|
|
109
|
+
|
|
110
|
+
def __repr__(self):
|
|
111
|
+
return str(self)
|
|
112
|
+
|
|
113
|
+
@property
|
|
114
|
+
def is_preloaded( self ):
|
|
115
|
+
"""
|
|
116
|
+
Check if material is already loaded into NCrystal physics
|
|
117
|
+
objects. If so, the .load() function will be very cheap to call, but can not
|
|
118
|
+
accept any extra_cfg_params.
|
|
119
|
+
"""
|
|
120
|
+
return bool( self.__d.get('preloaded') )
|
|
121
|
+
|
|
122
|
+
def load( self, extra_cfg_params = None, doInfo = True, doScatter = True, doAbsorption = True ):
|
|
123
|
+
"""
|
|
124
|
+
Loads material (if not preloaded) and in any case returns a
|
|
125
|
+
LoadedMaterial object. If material is preloaded, extra_cfg_params can
|
|
126
|
+
NOT be provided, and the doInfo/doScatter/doAbsorption flags will have
|
|
127
|
+
no effect.
|
|
128
|
+
"""
|
|
129
|
+
ecp = (extra_cfg_params or '').strip()
|
|
130
|
+
preloaded = self.__d.get('preloaded')
|
|
131
|
+
if ecp and preloaded:
|
|
132
|
+
from .exceptions import NCBadInput
|
|
133
|
+
raise NCBadInput( 'Can not accept extra_cfg_params on a'
|
|
134
|
+
' MaterialSource which is preloaded.' )
|
|
135
|
+
if preloaded:
|
|
136
|
+
return preloaded
|
|
137
|
+
return self.__d['loadfct']( extra_cfg = extra_cfg_params,
|
|
138
|
+
doInfo = doInfo,
|
|
139
|
+
doScatter = doScatter,
|
|
140
|
+
doAbsorption = doAbsorption )
|
|
141
|
+
|
|
142
|
+
class AnyTextData:
|
|
143
|
+
"""
|
|
144
|
+
Immutable type-erasure class for text data (possibly named).
|
|
145
|
+
Be aware, that this class will always keep the entire content in memory.
|
|
146
|
+
"""
|
|
147
|
+
|
|
148
|
+
def __init__( self, data, is_path = None, name = None ):
|
|
149
|
+
"""
|
|
150
|
+
Initialise from data, which can be either in-memory text data (str
|
|
151
|
+
or NCrystal.TextData) or a file path (str or pathlib.Path) from which
|
|
152
|
+
data will be loaded. Data of type bytes will simply be attempted decoded
|
|
153
|
+
as a string.
|
|
154
|
+
|
|
155
|
+
A string containing no new-line characters is assumed to be a file-path,
|
|
156
|
+
otherwise it will be interpreted as in-memory data. Set is_path to True
|
|
157
|
+
or False to override this logic.
|
|
158
|
+
|
|
159
|
+
The "name" parameter can be used to specify or override the "name" of
|
|
160
|
+
the file source.
|
|
161
|
+
"""
|
|
162
|
+
if isinstance(data,AnyTextData):
|
|
163
|
+
_ = ( name or data.__name ), data.__content, data.__keepalive
|
|
164
|
+
else:
|
|
165
|
+
from . import _miscimpl
|
|
166
|
+
_ = _miscimpl.anytextdata_init( data, is_path=is_path, name=name )
|
|
167
|
+
self.__name, self.__content, self.__keepalive = _
|
|
168
|
+
self.__hash = None
|
|
169
|
+
|
|
170
|
+
@property
|
|
171
|
+
def name( self ):
|
|
172
|
+
"""Access a name of the text data (could for instance be the file
|
|
173
|
+
name). None if not available."""
|
|
174
|
+
return self.__name
|
|
175
|
+
|
|
176
|
+
@property
|
|
177
|
+
def content( self ):
|
|
178
|
+
"""Access the contents (always type str)."""
|
|
179
|
+
return self.__content
|
|
180
|
+
|
|
181
|
+
def __lt__( self, o ):
|
|
182
|
+
if self.name != o.name:
|
|
183
|
+
return self.name < o.name
|
|
184
|
+
if len(self.content) != len(o.content):
|
|
185
|
+
return self.content < o.content
|
|
186
|
+
if self.hash_hexdigest != o.hash_hexdigest:
|
|
187
|
+
return self.hash_hexdigest < o.hash_hexdigest
|
|
188
|
+
return self.content < o.content
|
|
189
|
+
|
|
190
|
+
def __eq__( self, o ):
|
|
191
|
+
if self.name != o.name:
|
|
192
|
+
return False
|
|
193
|
+
if len(self.content) != len(o.content):
|
|
194
|
+
return False
|
|
195
|
+
if self.hash_hexdigest != o.hash_hexdigest:
|
|
196
|
+
return False
|
|
197
|
+
return self.content == o.content
|
|
198
|
+
|
|
199
|
+
def __str__( self ):
|
|
200
|
+
n = repr(self.name) if self.name is not None else 'Anonymous'
|
|
201
|
+
return f'AnyTextData({n}, {len(self.content)} chars, MD5={self.hash_hexdigest})'
|
|
202
|
+
|
|
203
|
+
def __repr__( self ):
|
|
204
|
+
return self.__str__()
|
|
205
|
+
|
|
206
|
+
@property
|
|
207
|
+
def hash_hexdigest(self):
|
|
208
|
+
"""Returns md5 checksum of content as hexdigest"""
|
|
209
|
+
if self.__hash is None:
|
|
210
|
+
from ._common import _calc_md5hexdigest
|
|
211
|
+
self.__hash = _calc_md5hexdigest( self.content )
|
|
212
|
+
return self.__hash
|
|
213
|
+
|
|
214
|
+
class AnyVDOS:
|
|
215
|
+
"""
|
|
216
|
+
Immutable type-erasure class for phonon DOS (VDOS) curves.
|
|
217
|
+
"""
|
|
218
|
+
|
|
219
|
+
def __init__( self, data, fmt = None, label = None ):
|
|
220
|
+
"""Initialise from data in various formats. Currently, input data can
|
|
221
|
+
either be raw curves in the form of two arrays (egrid,density), DI_VDOS
|
|
222
|
+
objects, or DI_VDOSDebye objects. Raw curves with egrid[0]>0 will be
|
|
223
|
+
extended with a parabola towards (0,0). Furthermore egrid values
|
|
224
|
+
consisting of just two points will be assumed to be a linearly spaced
|
|
225
|
+
grid with those endpoints.
|
|
226
|
+
|
|
227
|
+
The label parameter can be used to assign a label to the curves, which
|
|
228
|
+
might for instance be used in utilities dumping or plotting the curves.
|
|
229
|
+
|
|
230
|
+
Finally, some curves (notably those from DI_VDOS) will have the notion
|
|
231
|
+
of "original" and processed curves. By default, the processed curves are
|
|
232
|
+
displayed, although several methods have an "orig" parameter which can
|
|
233
|
+
be set to True, in order to access the original curves instead.
|
|
234
|
+
"""
|
|
235
|
+
from . import _miscimpl
|
|
236
|
+
self.__d = _miscimpl._anyvdos_init( AnyVDOS, lambda x : x.__d,
|
|
237
|
+
data, fmt, label )
|
|
238
|
+
|
|
239
|
+
def __choice( self, orig ):
|
|
240
|
+
return '_orig' if ( orig and 'dos_orig' in self.__d ) else ''
|
|
241
|
+
|
|
242
|
+
def integral( self, *, orig = False ):
|
|
243
|
+
"""Get the integral of the VDOS curve. Note that this includes the area
|
|
244
|
+
under the parabola between (0,0) and the first positive grid point. Any
|
|
245
|
+
non-positive grid points are ignored for the purposes of calculating the
|
|
246
|
+
integral."""
|
|
247
|
+
return self.__d['derived']['dos%s_integral'%self.__choice(orig)]
|
|
248
|
+
|
|
249
|
+
def egrid( self, *, orig = False ):
|
|
250
|
+
"""Access the energy grid values. Note that this is always the full
|
|
251
|
+
energy grid, even if just a tuple "(emin,emax)" was used to construct
|
|
252
|
+
the object.
|
|
253
|
+
"""
|
|
254
|
+
choice = self.__choice(orig)
|
|
255
|
+
eg = self.__d['derived'].get('dos%s_expandedegrid'%choice)
|
|
256
|
+
return eg if eg is not None else self.__d['dos%s'%choice][0]
|
|
257
|
+
|
|
258
|
+
def dos( self, *, orig = False, norm = True ):
|
|
259
|
+
"""Access the tabulated DOS values. Unless norm=False, this will
|
|
260
|
+
actually be the normalised DOS, i.e. the DOS values divided by the
|
|
261
|
+
integral (c.f. the .integral property)."""
|
|
262
|
+
choice = self.__choice(orig)
|
|
263
|
+
dos = self.__d['dos%s'%choice][1]
|
|
264
|
+
return ( dos / self.__d['derived']['dos%s_integral'%choice] ) if norm else dos
|
|
265
|
+
|
|
266
|
+
@property
|
|
267
|
+
def has_orig( self ):
|
|
268
|
+
"""Whether or not this particular object has both processed and original curves."""
|
|
269
|
+
return 'dos_orig' in self.__d
|
|
270
|
+
|
|
271
|
+
@property
|
|
272
|
+
def label( self ):
|
|
273
|
+
"""A string label describing the curve."""
|
|
274
|
+
return self.__d['label']
|
|
275
|
+
|
|
276
|
+
@property
|
|
277
|
+
def debye_temperature( self ):
|
|
278
|
+
"""
|
|
279
|
+
The Debye temperature in kelvin, if any is associated with the
|
|
280
|
+
curve. Otherwise it will be None. This is usually only set for
|
|
281
|
+
DI_VDOSDebye objects, or when a single floating point value (the Debye
|
|
282
|
+
temperature itself) was used to initialise the AnyVDOS object.
|
|
283
|
+
"""
|
|
284
|
+
return self.__d.get('debyetemp')
|
|
285
|
+
|
|
286
|
+
def _benchloadcfg( cfgstr, do_scatter=True, nrepeat = 1 ):
|
|
287
|
+
"""
|
|
288
|
+
Get time in seconds to load the cfg in question (if not doScatter it will
|
|
289
|
+
only create Info objects). Caches are cleared as a side effect.
|
|
290
|
+
"""
|
|
291
|
+
from . import _chooks as ch
|
|
292
|
+
_rawfct = ch._get_raw_cfcts()
|
|
293
|
+
return _rawfct['benchloadcfg'](cfgstr = cfgstr,
|
|
294
|
+
do_scatter = do_scatter,
|
|
295
|
+
nrepeat = nrepeat )
|
|
296
|
+
|
|
297
|
+
def cfgstr_detect_components( cfgstr ):
|
|
298
|
+
"""
|
|
299
|
+
Helper function which can detect which physics components are present
|
|
300
|
+
once a given cfg-string is loaded, and provide derived cfg-strings suitable
|
|
301
|
+
for picking out those components. The return value is a list of component
|
|
302
|
+
names (e.g. "inelas", "cohelas", "sans", etc.) and the associated
|
|
303
|
+
cfg-strings: [(cfgstr1,compname1), (cfgstr2,compname2),...].
|
|
304
|
+
|
|
305
|
+
"""
|
|
306
|
+
#Normalise original cfg (so syntax errors will refer to the cfgstr as
|
|
307
|
+
#originally specified), and add flags which cause initialisation speedup
|
|
308
|
+
#without affecting which components are present:
|
|
309
|
+
from .cfgstr import normaliseCfg
|
|
310
|
+
from .core import createScatter
|
|
311
|
+
probecfgstr = normaliseCfg(cfgstr) + ';vdoslux=0'
|
|
312
|
+
res=[]
|
|
313
|
+
for ct in standard_comp_types:
|
|
314
|
+
extracfg = f';comp={ct}'
|
|
315
|
+
if not createScatter( probecfgstr + extracfg ).isNull():
|
|
316
|
+
res.append( ( normaliseCfg(cfgstr+extracfg), ct.replace('_','') ) )
|
|
317
|
+
return res
|
NCrystal/mmc.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
|
|
2
|
+
################################################################################
|
|
3
|
+
## ##
|
|
4
|
+
## This file is part of NCrystal (see https://mctools.github.io/ncrystal/) ##
|
|
5
|
+
## ##
|
|
6
|
+
## Copyright 2015-2024 NCrystal developers ##
|
|
7
|
+
## ##
|
|
8
|
+
## Licensed under the Apache License, Version 2.0 (the "License"); ##
|
|
9
|
+
## you may not use this file except in compliance with the License. ##
|
|
10
|
+
## You may obtain a copy of the License at ##
|
|
11
|
+
## ##
|
|
12
|
+
## http://www.apache.org/licenses/LICENSE-2.0 ##
|
|
13
|
+
## ##
|
|
14
|
+
## Unless required by applicable law or agreed to in writing, software ##
|
|
15
|
+
## distributed under the License is distributed on an "AS IS" BASIS, ##
|
|
16
|
+
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ##
|
|
17
|
+
## See the License for the specific language governing permissions and ##
|
|
18
|
+
## limitations under the License. ##
|
|
19
|
+
## ##
|
|
20
|
+
################################################################################
|
|
21
|
+
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
Highly experimental "Mini-MC" framework for transforming NCrystal materials into
|
|
25
|
+
actual scattering patterns.
|
|
26
|
+
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
__all__ = ['runsim_diffraction_pattern',
|
|
30
|
+
'quick_diffraction_pattern',
|
|
31
|
+
'quick_diffraction_pattern_autoparams']
|
|
32
|
+
|
|
33
|
+
from ._mmc import ( runsim_diffraction_pattern,
|
|
34
|
+
quick_diffraction_pattern,
|
|
35
|
+
quick_diffraction_pattern_autoparams )
|