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/_miscimpl.py ADDED
@@ -0,0 +1,354 @@
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
+ Internal implementation details for utilities in ncmat.py
25
+
26
+ """
27
+
28
+ __all__ = []
29
+
30
+ def matsrc_detect_fmt( class_MaterialSource, data ):
31
+ if isinstance(data,class_MaterialSource):
32
+ return 'NCrystal.MaterialSource'
33
+ from . import core as _nc_core
34
+ for c in ('Info','Scatter','Absorption','LoadedMaterial','TextData'):
35
+ if isinstance(data,getattr(_nc_core,c)):
36
+ return f'NCrystal.{c}'
37
+ if hasattr(data,'__fspath__'):
38
+ return 'filepath'
39
+ if isinstance(data,bytes) or isinstance(data,str):
40
+ compat_str = (lambda s : s.encode()) if isinstance(data,bytes) else (lambda s : s)
41
+ if compat_str('\n') in data and data.startswith(compat_str('NCMAT')):
42
+ return 'ncmat'
43
+ else:
44
+ return 'cfgstr'
45
+ if hasattr(data,'load') and hasattr(data,'create_ncmat'):
46
+ from .ncmat import NCMATComposer as _composer
47
+ if isinstance(data,_composer):
48
+ return 'NCrystal.NCMATComposer'
49
+
50
+ def matsrc_allfmts( as_str = False ):
51
+ _= ('cfgstr','filepath','ncmat','NCrystal.TextData','NCrystal.NCMATComposer',
52
+ 'NCrystal.Info','NCrystal.Scatter','NCrystal.Absorption',
53
+ 'NCrystal.LoadedMaterial','NCrystal.MaterialSource')
54
+ return _ if not as_str else '"%s"'%('", "'.join(_))
55
+
56
+ def matsrc_initfmt( data, fmt, cfg_params ):
57
+ from .exceptions import NCBadInput
58
+ cfg_params = (cfg_params or '').strip() or None
59
+ from . import core as _nc_core
60
+ def to_str(s):
61
+ return s.decode() if hasattr(s,'decode') else s
62
+ def cfgcombine( cfgstr, extra_params ):
63
+ ll = list( e.strip()
64
+ for e in (to_str(cfgstr),to_str(extra_params))
65
+ if (e or '').strip() )
66
+ return ';'.join(ll) if ll else None
67
+ if fmt == 'NCrystal.MaterialSource':
68
+ if not cfg_params:
69
+ return data
70
+ wrapped_loadfct = data.get('loadfct')
71
+ if not wrapped_loadfct:
72
+ raise NCBadInput('Can not add cfg_params to MaterialSource'
73
+ ' which is of "preloaded" type.')
74
+ def loadfct( extra_cfg, doInfo, doScatter, doAbsorption ):
75
+ return wrapped_loadfct( cfgcombine(cfg_params,extra_cfg), doInfo, doScatter, doAbsorption )
76
+ descr = data.get('description')
77
+ plotlabel = data.get('plotlabel')
78
+ if plotlabel:
79
+ plotlabel+=f'+ ";{cfg_params}"'
80
+ return dict( description = f'{descr} + ";{cfg_params}"',
81
+ plotlabel = plotlabel,
82
+ loadfct = loadfct )
83
+ if fmt == 'filepath':
84
+ import pathlib
85
+ p = pathlib.Path(data)
86
+ if not p.exists():
87
+ raise NCBadInput(f'Missing file: {p}')
88
+ try:
89
+ _textdata = p.read_text()
90
+ except OSError:
91
+ raise NCBadInput(f'Could not read data from file: {p}')
92
+ except UnicodeDecodeError:
93
+ raise NCBadInput(f'Problems interpreting data in file as text: {p}')
94
+ if _textdata.startswith('NCMAT'):
95
+ _dtype = 'ncmat'
96
+ else:
97
+ _ = p.suffix
98
+ if _ and _.startswith('.'):
99
+ _ = _[1:]
100
+ _dtype = _ or None
101
+ descr = p.name
102
+ if cfg_params:
103
+ descr += ';' + cfg_params
104
+ def loadfct( extra_cfg, doInfo, doScatter, doAbsorption ):
105
+ return _nc_core.directMultiCreate( _textdata,
106
+ cfg_params = cfgcombine(cfg_params,extra_cfg),
107
+ dtype = _dtype,
108
+ doInfo = doInfo,
109
+ doScatter = doScatter,
110
+ doAbsorption = doAbsorption )
111
+ return dict( description = descr, loadfct = loadfct )
112
+ if fmt=='cfgstr':
113
+ cfgstr = to_str(data)
114
+ if cfg_params:
115
+ cfgstr += ';'+to_str(cfg_params)
116
+ from .cfgstr import normaliseCfg
117
+ cfgstr = normaliseCfg( cfgstr )
118
+ def loadfct( extra_cfg, doInfo, doScatter, doAbsorption ):
119
+ cs = cfgcombine(cfgstr,extra_cfg)
120
+ i = _nc_core.createInfo(cs) if doInfo else None
121
+ s = _nc_core.createScatter(cs) if doScatter else None
122
+ a = _nc_core.createAbsorption(cs) if doAbsorption else None
123
+ return _nc_core.LoadedMaterial.fromExistingObjects(info=i,scatter=s,absorption=a)
124
+ return dict( description = cfgstr, loadfct = loadfct )
125
+ if fmt=='NCrystal.TextData':
126
+ descr = data.dataSourceName or 'Anonymous TextData'
127
+ if cfg_params:
128
+ descr += ';' + cfg_params
129
+ def loadfct( extra_cfg, doInfo, doScatter, doAbsorption ):
130
+ return _nc_core.directMultiCreate( data,
131
+ cfg_params = cfgcombine(cfg_params,extra_cfg),
132
+ doInfo = doInfo,
133
+ doScatter = doScatter,
134
+ doAbsorption = doAbsorption )
135
+ return dict( description = descr, loadfct = loadfct )
136
+ if fmt=='ncmat':
137
+ data = to_str(data)
138
+ def loadfct( extra_cfg, doInfo, doScatter, doAbsorption ):
139
+ return _nc_core.directMultiCreate( data,
140
+ dtype = 'ncmat',
141
+ cfg_params = cfgcombine(cfg_params,extra_cfg),
142
+ doInfo = doInfo,
143
+ doScatter = doScatter,
144
+ doAbsorption = doAbsorption )
145
+ return dict( description = 'Anonymous NCMAT data', loadfct = loadfct )
146
+ if fmt=='NCrystal.NCMATComposer':
147
+ txtdata = data.create_ncmat()# NCMATComposer is not immutable so we simply
148
+ # capture the state by invoking create_ncmat
149
+ # already.
150
+ plotlabel = data.plotlabel
151
+ def loadfct( extra_cfg, doInfo, doScatter, doAbsorption ):
152
+ return _nc_core.directMultiCreate( txtdata,
153
+ dtype = 'ncmat',
154
+ cfg_params = cfgcombine(cfg_params,extra_cfg),
155
+ doInfo = doInfo,
156
+ doScatter = doScatter,
157
+ doAbsorption = doAbsorption )
158
+ return dict( description = 'NCMATComposer object', loadfct = loadfct, plotlabel = plotlabel )
159
+ if fmt=='NCrystal.LoadedMaterial':
160
+ return dict( description = 'NCrystal.LoadedMaterial object',
161
+ preloaded = data )
162
+ if fmt=='NCrystal.Info':
163
+ return dict( description = 'NCrystal.Info object',
164
+ preloaded = _nc_core.LoadedMaterial.fromExistingObjects( info = data ) )
165
+ if fmt=='NCrystal.Scatter':
166
+ return dict( description = 'NCrystal.Scatter object',
167
+ preloaded = _nc_core.LoadedMaterial.fromExistingObjects( scatter = data ) )
168
+ if fmt=='NCrystal.Absorption':
169
+ return dict( description = 'NCrystal.Absorption object',
170
+ preloaded = _nc_core.LoadedMaterial.fromExistingObjects( absorption = data ) )
171
+ raise _nc_core.NCLogicError(f'unhandled fmt option: {fmt}')
172
+
173
+ def matsrc_init( class_MaterialSource, matsrc_extract_d_fct, data, fmt, cfg_params ):
174
+ from .exceptions import NCBadInput
175
+ assert fmt is None or isinstance(fmt,str)
176
+ assert data is not None
177
+ assert cfg_params is None or isinstance(cfg_params,str)
178
+ if not fmt:
179
+ fmt = matsrc_detect_fmt( class_MaterialSource, data )
180
+ if not fmt:
181
+ raise NCBadInput('Could not detect format of MaterialSource.'
182
+ ' If this is merely a detection problem, set'
183
+ ' the fmt parameter to an accepted value (one of:'
184
+ ' %s)'%matsrc_allfmts(as_str=True))
185
+ if fmt not in matsrc_allfmts():
186
+ raise NCBadInput( f'Unknown format "{fmt}" (must be one of:'
187
+ ' %s)'%matsrc_allfmts(as_str=True) )
188
+ d = matsrc_initfmt( matsrc_extract_d_fct(data) if fmt=='NCrystal.MaterialSource' else data, fmt, cfg_params )
189
+ assert len(d) in (2,3)
190
+ assert 'description' in d
191
+ assert int('preloaded' in d) + int('loadfct' in d) == 1
192
+ if 'preloaded' in d and (cfg_params or '').strip():
193
+ raise NCBadInput('MaterialSource objects that are wrapping preloaded'
194
+ ' physics objects can not be initialised with'
195
+ ' additional cfg parameters.')
196
+ return d
197
+
198
+ def anytextdata_init( data, *, is_path, name ):
199
+ if isinstance(name,bytes):
200
+ name = name.decode()
201
+ assert name is None or isinstance(name,str)
202
+ res_keepalive = None
203
+ if hasattr(data,'rawData') and hasattr(data,'dataSourceName'):
204
+ #TextData:
205
+ res_keepalive = data
206
+ res_name = name or data.dataSourceName
207
+ res_content = data.rawData
208
+ return res_name, res_content, res_keepalive
209
+ if hasattr( data, '__fspath__' ):
210
+ import pathlib
211
+ p = pathlib.Path(data)
212
+ res_name = name or p.name
213
+ res_content = p.read_text()
214
+ return res_name, res_content, res_keepalive
215
+ if isinstance(data,bytes):
216
+ data = data.decode()
217
+ if not isinstance(data,str):
218
+ from .exceptions import NCBadInput
219
+ raise NCBadInput('Invalid text data / text file data (got type %s)'%type(data))
220
+ is_path = is_path if ( is_path is not None ) else ( '\n' not in data )
221
+ if is_path:
222
+ from ._common import _lookup_existing_file
223
+ p = _lookup_existing_file( data )
224
+ if not p:
225
+ raise NCBadInput(f'Path not found: {data}')
226
+ res_name = name or p.name
227
+ res_content = p.read_text()
228
+ else:
229
+ res_content = data
230
+ res_name = name#Ok if None
231
+ return res_name or None, res_content, res_keepalive
232
+
233
+ def _anyvdos_detect_fmt( class_AnyVDOS, data ):
234
+ if isinstance(data,class_AnyVDOS):
235
+ return 'NCrystal.AnyVDOS'
236
+ from .core import Info
237
+ if isinstance( data, Info.DI_VDOS ):
238
+ return 'NCrystal.Info.DI_VDOS'
239
+ if isinstance( data, Info.DI_VDOSDebye ):
240
+ return 'NCrystal.Info.DI_VDOSDebye'
241
+ import numbers
242
+ if isinstance(data, numbers.Real):
243
+ return 'debyetemperature'
244
+ if hasattr(data,'__len__') and len(data)==2:
245
+ eg,dens = data
246
+ if hasattr(eg,'__len__') and len(eg) >= 2 and hasattr(dens,'__len__') and len(dens)>=2 and ( len(eg)==len(dens) or len(eg)==2 ):
247
+ return 'arrays'
248
+
249
+ def _anyvdos_preinit( data, fmt ):
250
+ allfmts = ('NCrystal.Info.DI_VDOS','NCrystal.Info.DI_VDOSDebye','debyetemperature','arrays','NCrystal.AnyVDOS')
251
+ from ._numpy import _ensure_numpy, _np
252
+ _ensure_numpy()
253
+
254
+ if fmt =='NCrystal.Info.DI_VDOS':
255
+ return dict( dos_orig = ( data.vdosOrigEgrid(), data.vdosOrigDensity() ),
256
+ dos = data.vdosData() )
257
+ if fmt =='NCrystal.Info.DI_VDOSDebye':
258
+ return dict( dos = data.vdosData(),
259
+ debyetemp = data.debyeTemperature() )
260
+ if fmt =='debyetemperature':
261
+ debyetemp = float(data)
262
+ from .vdos import createVDOSDebye
263
+ return dict( dos = createVDOSDebye( debyetemp ),
264
+ debyetemp = debyetemp )
265
+ if fmt =='arrays':
266
+ eg, dens = data
267
+ dens = _np.asarray( dens, dtype = float )
268
+ if len(eg)==2 and len(dens)>2:
269
+ eg = (float(eg[0]),float(eg[1]))
270
+ else:
271
+ eg = _np.asarray( eg, dtype = float )
272
+ return dict( dos = ( eg, dens ) )
273
+ assert not fmt == 'NCrystal.AnyVDOS'#should have been handled in calling code
274
+ if fmt not in allfmts:
275
+ from .exceptions import NCBadInput
276
+ s='"%s"'%('", "'.join(allfmts))
277
+ if fmt is None:
278
+ raise NCBadInput('Could not detect fmt of VDOS specification, consider specifying it explictly (must be one of %s)'%(s))
279
+ raise NCBadInput('Invalid VDOS fmt "%s". Possible options are %s'%(fmt,s))
280
+ assert False, "unhandled fmt case: %s"%fmt
281
+
282
+ def _anyvdos_initfmt( data, fmt ):
283
+ p = _anyvdos_preinit( data, fmt )
284
+ #find derived quantities:
285
+ d = {}
286
+ from ._numpy import _ensure_numpy, _np_linspace, _np, _np_trapezoid
287
+ _ensure_numpy()
288
+ def _needsexpand( egrid, dos ):
289
+ return len(egrid)==2 and len(dos)>2
290
+ def _expandegrid( egrid, dos ):
291
+ if _needsexpand(egrid,dos):
292
+ return _np_linspace( egrid[0], egrid[-1], len(dos) )
293
+ else:
294
+ return _np.asarray(egrid,dtype=float)
295
+ def integrate( expanded_egrid, dos ):
296
+ x,y = expanded_egrid, dos
297
+ if not x[0] > 0.0:
298
+ #simply ignore points <= 0.0
299
+ i = _np.argmax(x>0.0)
300
+ x,y = x[i:],y[i:]
301
+ parabola_contrib = ( x[0] * y[0] ) / 3.0#integral of parabola through (0,0) and (x[0],y[0]) over [0,x[0]]
302
+ return parabola_contrib + _np_trapezoid(x=x,y=y)
303
+ for k in ('dos','dos_orig'):
304
+ if k not in p:
305
+ continue
306
+ eg,dos = p[k]
307
+ egexpand = _expandegrid(eg,dos) if _needsexpand(eg,dos) else None
308
+ d[k+'_expandedegrid'] = egexpand
309
+ d[k+'_integral'] = integrate( ( eg if egexpand is None else egexpand), dos )
310
+
311
+ #combine and return:
312
+ import copy
313
+ res = {'derived':d}
314
+ for k,v in p.items():
315
+ res[k] = copy.deepcopy(v)
316
+ return res
317
+
318
+ def _anyvdos_init( class_AnyVDOS, anyvdos_extract_d, data, fmt, label ):
319
+ if label is None and hasattr(data,'_plotlabel'):
320
+ from .core import Info
321
+ if isinstance(data,Info.DynamicInfo):
322
+ label = data._plotlabel()
323
+ fmt = _anyvdos_detect_fmt(class_AnyVDOS,data) if fmt is None else fmt
324
+ if fmt == 'NCrystal.AnyVDOS':
325
+ d = anyvdos_extract_d( data )
326
+ if label is None or d.get('label')==label:
327
+ return d
328
+ else:
329
+ import copy
330
+ d = dict( (k,copy.deepcopy(v)) for k,v in d.items() if k != 'label' )
331
+ else:
332
+ d = _anyvdos_initfmt( data, fmt )
333
+ d['label'] = label or 'anonymous VDOS curve from "%s"'%fmt
334
+ if d.get('debyetemp'):
335
+ _='TDebye=%gK'%d['debyetemp']
336
+ if not d['label'].endswith(')'):
337
+ d['label'] += f' ({_})'
338
+ else:
339
+ d['label'] = d['label'][:-1]+f', {_})'
340
+ from types import MappingProxyType#read-only dict
341
+ d['derived'] = MappingProxyType(d['derived'])
342
+ return MappingProxyType( d )
343
+
344
+ def detect_scatcomps( standard_comp_types, matsrc ):
345
+ if matsrc.is_preloaded:
346
+ from .exceptions import NCBadInput
347
+ raise NCBadInput('detect_scattering_components can not be used'
348
+ ' with preloaded material sources')
349
+ res=[]
350
+ for ct in standard_comp_types:
351
+ _ = matsrc.load( extra_cfg_params = f'vdoslux=0;comp={ct}', doInfo = False, doAbsorption = False )
352
+ if not _.scatter.isNull():
353
+ res.append(ct)
354
+ return res