#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Converts SPEC data files and scans into NeXus HDF5 files"""
# this is the main code for the *spec2nexus* application
__url__ = "https://prjemian.github.io/spec2nexus/spec2nexus.html"
import os
import sys
if __name__ == "__main__":
# put us on the path for developers
path = os.path.join("..", os.path.dirname(__file__))
sys.path.insert(0, os.path.abspath(path))
from . import spec
from . import writer
hdf5_extension = ".hdf5"
# -------------------------------------------------------------------------------------------
REPORTING_QUIET = "quiet"
REPORTING_STANDARD = "standard"
REPORTING_VERBOSE = "verbose"
SCAN_LIST_ALL = "all"
[docs]def get_user_parameters():
"""configure user's command line parameters from sys.argv"""
# global hdf5_extension
import argparse
from . import __version__
doc = __doc__.strip().splitlines()[0]
doc += "\n URL: " + __url__
doc += "\n v" + __version__
parser = argparse.ArgumentParser(prog="spec2nexus", description=doc)
parser.add_argument(
"infile", action="store", nargs="+", help="SPEC data file name(s)"
)
msg = "NeXus HDF5 output file extension"
msg += ", default = %s" % hdf5_extension
parser.add_argument(
"-e",
"--hdf5-extension",
action="store",
dest="hdf5_extension",
help=msg,
default=hdf5_extension,
)
parser.add_argument(
"-f",
"--force-overwrite",
action="store_true",
dest="force_write",
help="overwrite output file if it exists",
default=False,
)
parser.add_argument("-v", "--version", action="version", version=__version__)
msg = "specify which scans to save"
msg += ", such as: -s all or -s 1 or -s 1,2,3-5 (no spaces!)"
msg += ", default = %s" % SCAN_LIST_ALL
parser.add_argument(
"-s",
"--scan",
nargs=1,
# action='append',
dest="scan_list",
default=SCAN_LIST_ALL,
help=msg,
)
msg = "explicitly set the output file (default is same as input file, "
msg += "but with the .spec extension changed to .hdf5)"
parser.add_argument(
"-o",
"--output",
nargs=1,
action="store",
dest="output_filename",
help=msg)
# parser.add_argument('-t',
# '--tree-only',
# action='store_true',
# dest='tree_only',
# help='print NeXus/HDF5 node tree (does not save to a file)',
# default=False)
group = parser.add_mutually_exclusive_group()
group.set_defaults(reporting_level=REPORTING_STANDARD)
msg = "suppress all program output (except errors)"
msg += ", do not use with --verbose option"
group.add_argument(
"--quiet",
dest="reporting_level",
action="store_const",
const=REPORTING_QUIET,
help=msg,
)
msg = "print more program output"
msg += ", do not use with --quiet option"
group.add_argument(
"--verbose",
dest="reporting_level",
action="store_const",
const=REPORTING_VERBOSE,
help=msg,
)
return parser.parse_args()
[docs]def parse_scan_list_spec(scan_list_spec):
"""parses the argument of the -s option, returns a scan number list"""
# can this be simpler?
sl = scan_list_spec[0].split(",")
scan_list = []
for item in sl:
sublist = item.split("-")
if len(sublist) == 1:
scan_list.append(int(sublist[0]))
elif len(sublist) == 2:
scan_list += range(int(sublist[0]), int(sublist[1]) + 1)
else:
raise ValueError("improper scan list specifier: " + sublist)
sl = []
for item in sorted(scan_list):
if item not in sl:
sl.append(item)
return sl
[docs]def pick_scans(all_scans, opt_scan_list):
"""
edit opt_scan_list for the scans to be converted
To be converted, a scan number must be first specified in opt_scan_list
and then all_scans is checked to make sure that scan exists.
The final list is returned.
"""
if opt_scan_list == SCAN_LIST_ALL:
scan_list = all_scans
else:
scan_list = map(str, opt_scan_list)
# for item in scan_list:
# if str(item) not in all_scans:
# scan_list.remove(item)
scan_list = [item for item in scan_list if str(item) in all_scans]
return scan_list
[docs]def main():
"""entry point for command-line interface"""
user_parms = get_user_parameters()
spec_data_file_name_list = user_parms.infile
if user_parms.scan_list != SCAN_LIST_ALL:
user_parms.scan_list = parse_scan_list_spec(user_parms.scan_list)
if not user_parms.hdf5_extension.startswith(os.extsep):
user_parms.hdf5_extension = os.extsep + user_parms.hdf5_extension
for spec_data_file_name in spec_data_file_name_list:
if not os.path.exists(spec_data_file_name):
msg = "File not found: " + spec_data_file_name
print(msg)
continue
if user_parms.reporting_level in (REPORTING_STANDARD, REPORTING_VERBOSE,):
print("reading SPEC data file: " + spec_data_file_name)
spec_data = spec.SpecDataFile(spec_data_file_name)
all_scans = spec_data.getScanNumbers()
scan_list = list(pick_scans(all_scans, user_parms.scan_list))
if user_parms.reporting_level in (REPORTING_VERBOSE):
print(" discovered %d scans" % len(spec_data.scans.keys()))
print(" converting scan number(s): " + ", ".join(map(str, scan_list)))
basename = os.path.splitext(spec_data_file_name)[0]
if user_parms.output_filename is None:
nexus_output_file_name = basename + user_parms.hdf5_extension
else:
nexus_output_file_name = user_parms.output_filename[0]
if user_parms.force_write or not os.path.exists(nexus_output_file_name):
out = writer.Writer(spec_data)
out.save(nexus_output_file_name, scan_list)
if user_parms.reporting_level in (REPORTING_STANDARD, REPORTING_VERBOSE,):
print("wrote NeXus HDF5 file: " + nexus_output_file_name)
if __name__ == "__main__":
main()
# -----------------------------------------------------------------------------
# :author: Pete R. Jemian
# :email: prjemian@gmail.com
# :copyright: (c) 2014-2022, Pete R. Jemian
#
# Distributed under the terms of the Creative Commons Attribution 4.0 International Public License.
#
# The full license is in the file LICENSE.txt, distributed with this software.
# -----------------------------------------------------------------------------