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.
Files changed (53) hide show
  1. NCrystal/__init__.py +85 -0
  2. NCrystal/__main__.py +98 -0
  3. NCrystal/_chooks.py +854 -0
  4. NCrystal/_cli_cif2ncmat.py +269 -0
  5. NCrystal/_cli_endf2ncmat.py +503 -0
  6. NCrystal/_cli_hfg2ncmat.py +144 -0
  7. NCrystal/_cli_mcstasunion.py +74 -0
  8. NCrystal/_cli_ncmat2cpp.py +31 -0
  9. NCrystal/_cli_ncmat2hkl.py +180 -0
  10. NCrystal/_cli_nctool.py +1018 -0
  11. NCrystal/_cli_vdos2ncmat.py +463 -0
  12. NCrystal/_cli_verifyatompos.py +257 -0
  13. NCrystal/_cliimpl.py +307 -0
  14. NCrystal/_cliwrap_config.py +36 -0
  15. NCrystal/_common.py +499 -0
  16. NCrystal/_coreimpl.py +114 -0
  17. NCrystal/_hfgdata.py +546 -0
  18. NCrystal/_hklobjects.py +136 -0
  19. NCrystal/_is_std.py +0 -0
  20. NCrystal/_locatelib.py +210 -0
  21. NCrystal/_miscimpl.py +354 -0
  22. NCrystal/_mmc.py +757 -0
  23. NCrystal/_msg.py +60 -0
  24. NCrystal/_ncmat2cpp_impl.py +445 -0
  25. NCrystal/_ncmatimpl.py +2131 -0
  26. NCrystal/_numpy.py +76 -0
  27. NCrystal/_testimpl.py +579 -0
  28. NCrystal/api.py +56 -0
  29. NCrystal/atomdata.py +177 -0
  30. NCrystal/cfgstr.py +77 -0
  31. NCrystal/cifutils.py +1795 -0
  32. NCrystal/cli.py +96 -0
  33. NCrystal/constants.py +134 -0
  34. NCrystal/core.py +1910 -0
  35. NCrystal/datasrc.py +226 -0
  36. NCrystal/exceptions.py +66 -0
  37. NCrystal/hfg2ncmat.py +270 -0
  38. NCrystal/mcstasutils.py +438 -0
  39. NCrystal/misc.py +317 -0
  40. NCrystal/mmc.py +35 -0
  41. NCrystal/ncmat.py +778 -0
  42. NCrystal/ncmat2cpp.py +80 -0
  43. NCrystal/obsolete.py +67 -0
  44. NCrystal/plot.py +484 -0
  45. NCrystal/plugins.py +49 -0
  46. NCrystal/test.py +76 -0
  47. NCrystal/vdos.py +1034 -0
  48. ncrystal_python-3.9.81.dist-info/LICENSE +206 -0
  49. ncrystal_python-3.9.81.dist-info/METADATA +515 -0
  50. ncrystal_python-3.9.81.dist-info/RECORD +53 -0
  51. ncrystal_python-3.9.81.dist-info/WHEEL +5 -0
  52. ncrystal_python-3.9.81.dist-info/entry_points.txt +10 -0
  53. 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 )