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
@@ -0,0 +1,269 @@
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
+ from ._cliimpl import ( create_ArgumentParser,
23
+ cli_entry_point,
24
+ print )
25
+
26
+ def parseArgs( progname, arglist, return_parser=False ):
27
+ import textwrap
28
+ helpw = 60
29
+ descrw = helpw + 22
30
+ descr=( textwrap.fill(
31
+ """Script which can be used to generate NCMAT files from crystal
32
+ structures in local or remote CIF files. The script can optionally also compare
33
+ existing NCMAT files with online structures indicated in their comments.
34
+
35
+ It is essentially a command-line front-end for the functionality provided by the
36
+ NCrystal.cifutils Python module. Behind the scenes, CIF data is loaded and
37
+ processed with the gemmi and spglib modules, which must be available on the
38
+ system. They can be either installed via PyPi ("python3 -mpip install gemmi
39
+ spglib") or conda ("conda install -c conda-forge gemmi spglib").""",descrw)+'\n\n'
40
+ + textwrap.fill(
41
+ """IMPORTANT NOTE: It is important to realise that while most
42
+ CIF files contain crystal structure information, most of them lack appropriate
43
+ information about atomic dynamics (i.e. atomic displacements, Uiso, Biso, mean
44
+ squared displacements, Debye temperature, phonon DOS, ...). Even when available
45
+ as a Uiso (or Biso) value in the CIF data, the CIF data usually does not specify
46
+ which temperature the Uiso value is associated with, making it meaningless. The
47
+ --uisotemp parameter can be used to manually specify the temperature at which
48
+ any Uiso in the file is valid (it might of course require the user to perform a
49
+ bit of detective work to figure out the correct value). In other cases, this
50
+ script will simply assign each atom a Debye temperature value of 300K and use
51
+ that for dynamics (the --debyetemp flag can be used to modify this value if
52
+ desired). For more detailed options, one can either manually edit the generated
53
+ NCMAT data, or use the Python API (specifically the CIFAnalyser class from the
54
+ NCrystal.cifutils module) which offers more options and flexibility than the
55
+ present script. """,descrw)+f"""\n\nExample invocations:
56
+
57
+ $> {progname} myfile.cif
58
+ $> {progname} myfile.cif --output=myfile.ncmat
59
+ $> {progname} myfile.cif --output=stdout
60
+ $> {progname} myfile.cif --uisotemp=25
61
+ $> {progname} myfile.cif --debyetemp=500
62
+ $> {progname} mpid::127
63
+ $> {progname} codid::9008460 --debyetemp=412
64
+
65
+ """)
66
+
67
+ from argparse import RawTextHelpFormatter
68
+
69
+ parser = create_ArgumentParser( prog = progname,
70
+ description=descr.strip()+'\n',
71
+ usage=(f'{progname} CIFFILE [-o OUTPUT] [--debyetemp VAL] [--uisotemp VAL]\n'
72
+ +' '*(len(progname)+8)+'[<<other advanced options described below>>]'),
73
+ formatter_class=RawTextHelpFormatter )
74
+ def wrap(t):
75
+ return textwrap.fill(t,width=helpw)
76
+
77
+ #CIFFILE arg use nargs='?' if --valplots detected, to avoid spurious error:
78
+ parser.add_argument('CIFFILE', type=str,nargs=('?' if any( a.startswith('--val') for a in arglist ) else 1 ),
79
+ help=wrap('CIF file to use as source. This can either be a path '
80
+ 'to a physical file, or an online database ID, specified '
81
+ 'using a syntax like "codid::1000055" or "mpid::127". Do not specify with --valplot.'))
82
+ parser.add_argument('--output','-o',default=None,
83
+ help=wrap('Name of output NCMAT file (specify "stdout" to print to stdout). If not'
84
+ ' supplied, a name will be automatically generated. Alternatively, this'
85
+ ' can be used with --valplot to force output to a pdf file'))
86
+ value_fallback_debye_temp = 300.0
87
+ parser.add_argument("--debyetemp",default=value_fallback_debye_temp, type=float,metavar='VALUE',
88
+ help=wrap( 'Fall-back Debye temperature value (kelvin) to use for all'
89
+ f' atoms (default: {value_fallback_debye_temp}K)' ))
90
+ parser.add_argument("--uisotemp",default=None, type=float,metavar='VALUE',
91
+ help=wrap( 'Temperature value (kelvin) associated with any atomic displacement (Uiso/Biso) values'
92
+ ' in the input. Without this parameter, Uiso/Biso values in the input will be ignored.' ))
93
+ parser.add_argument('--quiet','-q',default=False,action='store_true',
94
+ help=wrap('Silence non-error output (automatic if --output=stdout).'))
95
+ parser.add_argument('--noval',default=False,action='store_true',
96
+ help=wrap('Do not validate generated NCMAT data by trying to load it.'))
97
+ parser.add_argument("--remap",metavar='COMP',default=[],type=str,action='append',
98
+ help=wrap('Redefine the composition of elements in the input CIF data, using'
99
+ ' a syntax like the one in @ATOMDB sections of NCMAT files.'
100
+ ' Examples: "H is D" and "B is 0.9 B10 0.1 B11". Colons can'
101
+ ' be used in place of spaces if desired ("H:is:D").'))
102
+ parser.add_argument("--atomdata",default=[],type=str,action='append',
103
+ help=wrap('Provide or override atom data of particular elements and isotopes, using'
104
+ ' a syntax like the one in @ATOMDB sections of NCMAT files. '
105
+ 'Example: "Si 28.09u 4.1491fm 0.004b 0.171b". Colons can'
106
+ ' be used in place of spaces if desired.'))
107
+ parser.add_argument('--dynamics','-d',default=None,metavar='FILE',
108
+ help=wrap('Data file from which to copy over dynamics information (matching up atoms'
109
+ ' based on Z-values). If this argument is not provided, or if a '
110
+ 'required element is not present in the indicated file, '
111
+ 'dynamics will be created with a fall-back Debye temperature (cf. --debyetemp).'))
112
+
113
+ parser.add_argument('--nomerge',default=False,action='store_true',
114
+ help=wrap('Do not use same label for different non-equivalent positions of the same atom species.'))
115
+ parser.add_argument('--showcif',default=False,action='store_true',
116
+ help=wrap('Simply show the input CIF data (mostly useful with mpid:: or codid:: sources).'))
117
+ parser.add_argument("--valplot",nargs='*',metavar="FILE",
118
+ help=wrap('List of existing NCMAT files which should be compared'
119
+ ' to crystal structures directly taken from online DBs (thus hopefully verifying'
120
+ ' that online DB references mentioned in comments in those files are'
121
+ ' actually compatible). This will launch interactive matplotlib plots, unless'
122
+ ' the --output option is used to request pdf output (either as -opdf or '
123
+ '-osomename.pdf, where the former will autogenerate a suitable name for the output PDF file'))
124
+
125
+ parser.add_argument("--spacegroup",default=None,type=str,
126
+ help=wrap('Override the space group, disregarding the spacegroup embedded in the file. '))
127
+ parser.add_argument('--via-ase',default=False,action='store_true',
128
+ help=wrap('Load input file via ASE (this can be useful to support non-CIF input files).'))
129
+
130
+
131
+ if return_parser:
132
+ return parser
133
+
134
+ args = parser.parse_args(arglist)
135
+ ll=[]
136
+ for c in args.remap:
137
+ p=c.replace(':',' ').split()
138
+ if not len(p)>=3 or p[1]!='is':
139
+ parser.error('invalid --remap syntax in "%s"'%c)
140
+ ll.append( (p[0],' '.join(p[2:]) ) )
141
+ args.remap = ll
142
+
143
+ ll=[]
144
+ for c in args.atomdata:
145
+ p = c.replace(':',' ').split()
146
+ if not len(p)==5 or not p[1].endswith('u') or not p[2].endswith('fm') or not p[3].endswith('b') or not p[4].endswith('b'):
147
+ parser.error('invalid --atomdata syntax in "%s"'%c)
148
+ ll.append( (p[0],' '.join(p[1:]) ) )
149
+ args.atomdata = ll
150
+
151
+ if (args.via_ase or args.showcif) and args.valplot:
152
+ parser.error('Conflicting options')
153
+ return args
154
+
155
+ def create_argparser_for_sphinx( progname ):
156
+ return parseArgs(progname,[],return_parser=True)
157
+
158
+
159
+ @cli_entry_point
160
+ def main( progname, arglist ):
161
+ args = parseArgs( progname, arglist )
162
+ do_quiet = ( args.quiet or args.output == 'stdout' or args.showcif )
163
+
164
+ if do_quiet:
165
+ from ._common import modify_ncrystal_print_fct_ctxmgr
166
+ with modify_ncrystal_print_fct_ctxmgr('block'):
167
+ _main_impl(args,do_quiet)
168
+ else:
169
+ _main_impl(args,do_quiet)
170
+
171
+ def _main_impl( args, do_quiet ):
172
+
173
+ from . import cifutils as nc_cifutils
174
+ from . import _ncmatimpl as nc_ncmatimpl
175
+ from . import _common as nc_common
176
+ import pathlib
177
+
178
+
179
+ #Trigger gemmi/spglib import error already here (and with nicer SystemExit):
180
+ if not args.showcif:
181
+ nc_cifutils._import_gemmi( sysexit = True )
182
+ nc_ncmatimpl._import_spglib( sysexit = True )
183
+
184
+ if args.via_ase:
185
+ nc_ncmatimpl._import_ase( sysexit = True )
186
+
187
+ with nc_common.WarningSpy( block = do_quiet):
188
+ if args.valplot:
189
+ _unit_test = nc_common.ncgetenv_bool('CIF2NCMAT_UNITTEST_NOPLOT')
190
+ pdf_target = None
191
+ if args.output and args.output.lower().endswith('pdf'):
192
+ if args.output.lower() in ('pdf','.pdf'):
193
+ #auto-detect name:
194
+ if len(args.valplot)==1:
195
+ pdf_target = pathlib.Path(args.valplot[0]).name + '.pdf'
196
+ elif args.output.endswith('.pdf'):
197
+ pdf_target = args.output
198
+ if not pdf_target:
199
+ pdf_target = 'ncrystal_onlinedb_validate.pdf'
200
+ assert len(pdf_target)>4 and pdf_target.endswith('.pdf')
201
+ if _unit_test:
202
+ print( 'UNITTEST: Would invoke nc_cifutils.produce_validation_plots with pdf_target=',pdf_target )
203
+ return
204
+ nc_cifutils.produce_validation_plots( args.valplot,
205
+ verbose_lbls = False,
206
+ pdf_target = pdf_target )
207
+ return
208
+ assert len(args.CIFFILE)==1
209
+ cifsrc = nc_cifutils.CIFSource( args.CIFFILE[0], allow_fail = True )
210
+ if args.via_ase:
211
+ if not cifsrc.filepath:
212
+ ase_input_data = cifsrc.load_data( quiet = do_quiet )
213
+ else:
214
+ ase_input_data = cifsrc.filepath
215
+
216
+ if cifsrc.is_remote:
217
+ #ase_input_data = cifsrc.load_data( quiet = do_quiet )
218
+ ase_format = 'cif'
219
+ else:
220
+ #ase_input_data = args.CIFFILE[0]
221
+ ase_format = None
222
+ ase_output_cifdata = nc_ncmatimpl._cifdata_via_ase( ase_input_data,
223
+ ase_format = ase_format,
224
+ quiet = do_quiet )
225
+ cifsrc = nc_cifutils.CIFSource( ase_output_cifdata )
226
+ if cifsrc.invalid:
227
+ raise SystemExit('Failed to load input')
228
+
229
+ if args.showcif:
230
+ import sys
231
+ sys.stdout.write( cifsrc.load_data() )
232
+ return
233
+
234
+ lc = nc_cifutils.CIFLoader( cifsrc,
235
+ merge_equiv = not args.nomerge,
236
+ quiet = do_quiet,
237
+ override_spacegroup = args.spacegroup )
238
+ composer = lc.create_ncmat_composer( top_comments=['<<disableautogennotice>>'],
239
+ uiso_temperature = args.uisotemp,
240
+ quiet = do_quiet,
241
+ remap = args.remap,
242
+ skip_dyninfo = bool(args.dynamics) )
243
+
244
+ if args.debyetemp and args.debyetemp > 0.0:
245
+ composer.allow_fallback_dyninfo( args.debyetemp )
246
+ if args.dynamics:
247
+ composer.transfer_dyninfo_objects( args.dynamics )
248
+
249
+ for elem, data in args.atomdata:
250
+ composer.update_atomdb( elem, data )
251
+
252
+ out, metadata = composer.create_ncmat( meta_data = True)
253
+ autofn = nc_cifutils._suggest_filename( metadata, lc )
254
+
255
+ fn = args.output or autofn
256
+
257
+ if not args.noval:
258
+ if not do_quiet:
259
+ print("Verifying that resulting ncmat data can be loaded")
260
+ from .core import directMultiCreate
261
+ directMultiCreate(out,'vdoslux=0;dcutoff=0.2')
262
+
263
+ if fn=='stdout':
264
+ import sys
265
+ sys.stdout.write(out)
266
+ else:
267
+ if not do_quiet:
268
+ print(f"Writing {fn}")
269
+ nc_common.write_text(fn,out)