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
|
@@ -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)
|