mirror of
https://github.com/TREX-CoE/trexio.git
synced 2025-01-03 18:16:22 +01:00
commit
55c2c052b0
12
.github/workflows/actions.yml
vendored
12
.github/workflows/actions.yml
vendored
@ -31,6 +31,18 @@ jobs:
|
||||
- name: check TREXIO
|
||||
run: make check
|
||||
|
||||
- name: create virtual environment
|
||||
run: |
|
||||
python3 -m venv --clear pytrexio-venv
|
||||
source pytrexio-venv/bin/activate
|
||||
|
||||
- name: install Python API
|
||||
run: make python-install
|
||||
# alternatively we can also run pip install trexio to check PyPI installation
|
||||
|
||||
- name: check Python API
|
||||
run: make python-test
|
||||
|
||||
- name: clean
|
||||
run: make clean
|
||||
|
||||
|
6
.gitignore
vendored
6
.gitignore
vendored
@ -5,6 +5,11 @@
|
||||
*/*.la
|
||||
*/*.lo
|
||||
aclocal.m4
|
||||
m4/libtool.m4
|
||||
m4/ltoptions.m4
|
||||
m4/ltsugar.m4
|
||||
m4/ltversion.m4
|
||||
m4/lt~obsolete.m4
|
||||
autom4te.cache/
|
||||
compile
|
||||
config.guess
|
||||
@ -16,6 +21,7 @@ config.h.in
|
||||
config.h
|
||||
depcomp
|
||||
include/config.h.in
|
||||
include/config.h.in~
|
||||
include/stamp-h1
|
||||
install-sh
|
||||
libtool
|
||||
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,3 +1,6 @@
|
||||
[submodule "docs/org-html-themes"]
|
||||
path = docs/org-html-themes
|
||||
url = https://github.com:fniessen/org-html-themes.git
|
||||
[submodule "python/examples"]
|
||||
path = python/examples
|
||||
url = git@github.com:TREX-CoE/trexio-tutorials.git
|
||||
|
58
Makefile.am
58
Makefile.am
@ -87,6 +87,8 @@ TESTS_C = \
|
||||
tests/io_dset_float_text \
|
||||
tests/io_dset_int_hdf5 \
|
||||
tests/io_dset_int_text \
|
||||
tests/io_safe_dset_float_hdf5 \
|
||||
tests/io_safe_dset_float_text \
|
||||
tests/io_str_hdf5 \
|
||||
tests/io_str_text \
|
||||
tests/io_dset_str_hdf5 \
|
||||
@ -114,6 +116,8 @@ tests_io_dset_float_hdf5_LDFLAGS = -no-install
|
||||
tests_io_dset_float_text_LDFLAGS = -no-install
|
||||
tests_io_dset_int_hdf5_LDFLAGS = -no-install
|
||||
tests_io_dset_int_text_LDFLAGS = -no-install
|
||||
tests_io_safe_dset_float_hdf5_LDFLAGS = -no-install
|
||||
tests_io_safe_dset_float_text_LDFLAGS = -no-install
|
||||
tests_io_str_hdf5_LDFLAGS = -no-install
|
||||
tests_io_str_text_LDFLAGS = -no-install
|
||||
tests_io_dset_str_hdf5_LDFLAGS = -no-install
|
||||
@ -133,7 +137,7 @@ tests_test_f_SOURCES = $(test_trexio_f) tests/test_f.f90
|
||||
tests_test_f_LDFLAGS = -no-install
|
||||
|
||||
clean-local:
|
||||
-rm -rf -- *.dir/ *.h5
|
||||
-rm -rf -- *.dir/ *.h5 __pycache__/
|
||||
|
||||
# =============== DOCUMENTATION =============== #
|
||||
|
||||
@ -153,6 +157,11 @@ $(HTML_FILES): docs/index.html
|
||||
|
||||
# =============== DEVELOPER MODE =============== #
|
||||
|
||||
SWIG = @SWIG@
|
||||
HDF5_LDFLAGS = @HDF5_LDFLAGS@
|
||||
HDF5_CFLAGS = @HDF5_CFLAGS@
|
||||
HDF5_CPPFLAGS = @HDF5_CPPFLAGS@
|
||||
|
||||
if TREXIO_DEVEL
|
||||
|
||||
CLEANFILES += $(SOURCES) $(trexio_f) $(trexio_h)
|
||||
@ -179,7 +188,52 @@ cppcheck.out: $(trexio_h)
|
||||
--language=c --std=c99 -rp --platform=unix64 \
|
||||
-I../include *.c *.h 2>../$@
|
||||
|
||||
.PHONY: cppcheck
|
||||
setup_py = $(srcdir)/python/setup.py
|
||||
setup_cfg = $(srcdir)/python/setup.cfg
|
||||
pytrexio_py = $(srcdir)/python/pytrexio/pytrexio.py
|
||||
trexio_py = $(srcdir)/python/trexio.py
|
||||
TEST_PY = python/test/test_api.py
|
||||
pytrexio_c = $(srcdir)/src/pytrexio_wrap.c
|
||||
pytrexio_i = $(srcdir)/src/pytrexio.i
|
||||
numpy_i = $(srcdir)/src/numpy.i
|
||||
|
||||
|
||||
python-test: $(TEST_PY)
|
||||
python3 $(TEST_PY)
|
||||
$(RM) -r -- __pycache__
|
||||
|
||||
python-install: $(pytrexio_py) $(setup_py) $(setup_cfg)
|
||||
cd python && \
|
||||
./install_pytrexio.sh $(HDF5_CFLAGS) $(HDF5_CPPFLAGS) $(HDF5_LDFLAGS)
|
||||
|
||||
python-sdist: $(pytrexio_py) $(setup_py) $(setup_cfg)
|
||||
cd python && \
|
||||
python setup.py sdist
|
||||
|
||||
$(pytrexio_py): $(pytrexio_c)
|
||||
cd tools && ./prepare_python.sh
|
||||
|
||||
# Build Python module and C wrapper code for TREXIO using SWIG
|
||||
# [?] swig -python -threads pytrexio.i ----> Add thread support for all the interface
|
||||
$(pytrexio_c): $(ORG_FILES) $(trexio_h) $(pytrexio_i) $(numpy_i)
|
||||
cp $(trexio_h) src/
|
||||
cd src/ && \
|
||||
$(SWIG) -python -py3 -o pytrexio_wrap.c pytrexio.i
|
||||
$(RM) -- src/trexio.h
|
||||
|
||||
$(numpy_i):
|
||||
wget https://raw.githubusercontent.com/numpy/numpy/main/tools/swig/numpy.i -O $(numpy_i)
|
||||
|
||||
check-numpy:
|
||||
cd tools && ./check_numpy_i.sh
|
||||
|
||||
CLEANFILES += $(pytrexio_c) \
|
||||
$(pytrexio_py) \
|
||||
$(trexio_py) \
|
||||
python/src/*.c \
|
||||
python/src/*.h
|
||||
|
||||
.PHONY: cppcheck python-test python-install python-sdist check-numpy
|
||||
|
||||
endif
|
||||
|
||||
|
27
README.md
27
README.md
@ -4,12 +4,12 @@
|
||||
[![build](https://github.com/TREX-CoE/trexio/actions/workflows/actions.yml/badge.svg)](https://github.com/TREX-CoE/trexio/actions/workflows/actions.yml)
|
||||
![GitHub release (latest by date)](https://img.shields.io/github/v/release/TREX-CoE/trexio)
|
||||
|
||||
TREX library fo efficient I/O.
|
||||
TREX library for efficient I/O.
|
||||
|
||||
|
||||
## Minimal requirements (for users):
|
||||
|
||||
- Autotools (autoconf, automake, libtool)
|
||||
- Autotools (autoconf >= 2.69, automake >= 1.11, libtool >= 2.2)
|
||||
- C compiler (gcc/icc/clang)
|
||||
- Fortran compiler (gfortran/ifort)
|
||||
- HDF5 library (>= 1.8)
|
||||
@ -33,7 +33,7 @@ TREX library fo efficient I/O.
|
||||
|
||||
- python3 (>= 3.6)
|
||||
- Emacs (>= 26.0)
|
||||
|
||||
- SWIG (>= 4.0)
|
||||
|
||||
## Installation procedure from the GitHub repo clone (for developers):
|
||||
|
||||
@ -56,7 +56,8 @@ The primary TREXIO API is composed of the following functions:
|
||||
- `trexio_has_[group]_[variable]`
|
||||
- `trexio_close`
|
||||
|
||||
where `[group]` and `[variable]` substitutions correspond to the contents of the `trex.json` configuration file (for more details, see the corresponding [documentation](https://trex-coe.github.io/trexio/trex.html) page).
|
||||
where `[group]` and `[variable]` substitutions correspond to the contents of the `trex.json` configuration file
|
||||
(for more details, see the corresponding [documentation](https://trex-coe.github.io/trexio/trex.html) page).
|
||||
For example, consider the `coord` variable (array), which belongs to the `nucleus` group. The TREXIO user can write or read it using `trexio_write_nucleus_coord` or `trexio_read_nucleus_coord` functions, respectively.
|
||||
|
||||
Note: the `[variable]` names have to be unique only within the corresponding parent `[group]`.
|
||||
@ -64,9 +65,20 @@ There is no naming conflict when, for example, `num` variable exists both in the
|
||||
These quantities can be accessed using the corresponding `trexio_[has|read|write]_nucleus_num` and `trexio_[has|read|write]_mo_num`, respectively.
|
||||
|
||||
|
||||
## Python API
|
||||
|
||||
For more details regarding the installation and usage of the TREXIO Python API,
|
||||
see [this page](python/README.md).
|
||||
|
||||
|
||||
## Tutorial
|
||||
|
||||
**TODO**
|
||||
TREXIO tutorials in Jupyter notebook format can be found in the
|
||||
[corresponding GitHub repository](https://github.com/TREX-CoE/trexio-tutorials)
|
||||
or on [Binder](https://mybinder.org/v2/gh/TREX-CoE/trexio-tutorials/HEAD).
|
||||
|
||||
For example, the tutorial covering TREXIO basics using benzene molecule as an example can be viewed and executed online by clicking on this badge:
|
||||
[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/TREX-CoE/trexio-tutorials/HEAD?filepath=notebooks%2Ftutorial_benzene.ipynb)
|
||||
|
||||
|
||||
## Technical documentation
|
||||
@ -76,8 +88,9 @@ These quantities can be accessed using the corresponding `trexio_[has|read|write
|
||||
|
||||
### Miscellaneous
|
||||
|
||||
Note: The code should be compliant with the C99 [CERT C coding
|
||||
standard](https://resources.sei.cmu.edu/downloads/secure-coding/assets/sei-cert-c-coding-standard-2016-v01.pdf). This can be checked with the `cppcheck` tool.
|
||||
Note: The code should be compliant with the C99
|
||||
[CERT C coding standard](https://resources.sei.cmu.edu/downloads/secure-coding/assets/sei-cert-c-coding-standard-2016-v01.pdf).
|
||||
This can be checked with the `cppcheck` tool.
|
||||
|
||||
|
||||
|
||||
|
20
configure.ac
20
configure.ac
@ -50,6 +50,7 @@ AC_FC_LIBRARY_LDFLAGS
|
||||
# pkg-config
|
||||
PKG_PROG_PKG_CONFIG()
|
||||
PKG_CFLAGS=""
|
||||
PKG_LIBS=""
|
||||
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_LIBTOOL
|
||||
@ -94,18 +95,29 @@ CPPFLAGS="${HDF5_CPPFLAGS} ${CPPFLAGS}"
|
||||
LDFLAGS="${HDF5_LDFLAGS} ${LDFLAGS}"
|
||||
LIBS="${HDF5_LIBS} ${LIBS}"
|
||||
|
||||
# Check if HDF5 if available with pkg-config
|
||||
# Check if HDF5 is available with pkg-config.
|
||||
|
||||
PKG_CHECK_MODULES([HDF5], [hdf5 >= 1.8], [
|
||||
PKG_HDF5="hdf5"
|
||||
],[
|
||||
PKG_HDF5=""
|
||||
])
|
||||
PKG_CFLAGS="${PKG_CFLAGS}"
|
||||
PKG_CFLAGS="${HDF5_CFLAGS}"
|
||||
PKG_LIBS="${HDF5_LIBS}"
|
||||
|
||||
AC_SUBST([PKG_HDF5])
|
||||
AC_SUBST([PKG_CFLAGS])
|
||||
AC_SUBST([PKG_LIBS])
|
||||
|
||||
# The block below should only execute if the ax_lib_hdf5.m4 macro failed to find HDF5.
|
||||
# It is only needed to manually build Python API because setup.py depends on HDF5.
|
||||
|
||||
if test "$HDF5_LDFLAGS" = "" || "$HDF5_CFLAGS" = ""; then
|
||||
HDF5_LDFLAGS="${PKG_LIBS}"
|
||||
HDF5_CFLAGS="${PKG_CFLAGS}"
|
||||
AC_SUBST([HDF5_CFLAGS])
|
||||
AC_SUBST([HDF5_LDFLAGS])
|
||||
fi
|
||||
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_TYPE_INT32_T
|
||||
@ -126,6 +138,10 @@ if test "x${TREXIO_DEVEL}" != "x"; then
|
||||
AC_PROG_AWK
|
||||
AM_PATH_PYTHON([3.0])
|
||||
|
||||
AX_PKG_SWIG(4.0.0, [], AC_MSG_WARN([SWIG is required to build Python API.]) )
|
||||
# The macro below performs Python benchmarks, but overlapping with AM_PATH_PYTHON
|
||||
#AX_SWIG_PYTHON
|
||||
|
||||
AC_CHECK_PROGS([EMACS],[emacs26 emacs],[no])
|
||||
if test x${EMACS} == xno ; then
|
||||
AC_MSG_ERROR([
|
||||
|
2
docker/.gitignore
vendored
Normal file
2
docker/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
tmp*
|
||||
trexio-*
|
45
docker/README
Normal file
45
docker/README
Normal file
@ -0,0 +1,45 @@
|
||||
First, make sure to place the source code distribution (suffixed with .tar.gz) of the TREXIO Python API in this directory.
|
||||
|
||||
TODO: the scripts have to be adapted for an arbitrary version of TREXIO and Python !
|
||||
|
||||
Outside Docker image:
|
||||
|
||||
# Build containers with hdf5 inside:
|
||||
|
||||
# for manylinux2014_x86_64
|
||||
sudo docker build -t hdf5_1_12_on_2014_x86_64 . -f Dockerfile_2014_x86_64
|
||||
|
||||
# for manylinux_2_24_x86_64
|
||||
sudo docker build -t hdf5_1_12_on_2_24_x86_64 . -f Dockerfile_2_24_x86_64
|
||||
|
||||
# (create an image using HDF5 containers, see https://github.com/h5py/hdf5-manylinux)
|
||||
# -t hdf5_1_12_on_${PLATFORM} builds an image with a custom name (hdf5_1_12_1)
|
||||
|
||||
# Run one of the produced containers in the interactive mode
|
||||
|
||||
# for manylinux2014_x86_64
|
||||
sudo docker run --rm -it -e PLAT=manylinux2014_x86_64 -v `pwd`:/tmp hdf5_1_12_on_2014_x86_64 /bin/bash
|
||||
|
||||
# for manylinux_2_24_x86_64
|
||||
sudo docker run --rm -it -e PLAT=manylinux_2_24_x86_64 -v `pwd`:/tmp hdf5_1_12_on_2_24_x86_64 /bin/bash
|
||||
|
||||
#(PLAT specifies the base platform tag for manilinux)
|
||||
#-i (run docker container interactively)
|
||||
#-t f8e4232fa208 (run an image using ID if the image is not named)
|
||||
#/bin/bash (a binary to run inside a container environment)
|
||||
|
||||
In the Docker image:
|
||||
|
||||
cd tmp && ./build_manylinux_wheels_py_36_37_38.sh
|
||||
# (creates virtual environments, installs things with pip, produces conventional wheels and repairs them with auditwheel)
|
||||
|
||||
# auditwheel repair trexio-0.1.0/dist/trexio-0.1.0-cp37-cp37m-linux_x86_64.whl
|
||||
# (repairs wheel and produces manylinux one)
|
||||
|
||||
After Docker container execution:
|
||||
|
||||
# the produced manylinux wheels are in trexio-0.1.0/wheelhouse directory
|
||||
|
||||
# ALTERNATIVELY: one can copy the produced manylinux wheel from the container back to the host system
|
||||
sudo docker cp $CONTAINER_ID:/tmp/trexio-0.1.0/wheelhouse/MANYLINUX_NAME.whl directory-on-the-user-machine/
|
||||
|
188
docker/build_manylinux_wheels_py_36_37_38_39.sh
Executable file
188
docker/build_manylinux_wheels_py_36_37_38_39.sh
Executable file
@ -0,0 +1,188 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -x
|
||||
set -e
|
||||
|
||||
export H5_LDFLAGS=-L/usr/local/lib
|
||||
export H5_CFLAGS=-I/usr/local/include
|
||||
|
||||
# install emacs for Debian
|
||||
|
||||
#apt-get update
|
||||
#apt install software-properties-common -y
|
||||
#apt-get install wget -y
|
||||
|
||||
#wget -q http://emacs.ganneff.de/apt.key -O- | apt-key add
|
||||
|
||||
#add-apt-repository "deb http://emacs.ganneff.de/ stretch main"
|
||||
#apt-get update
|
||||
#apt-get install emacs-snapshot -y
|
||||
#update-alternatives --config emacsclient
|
||||
|
||||
# ===============================
|
||||
|
||||
# install TREXIO in the container from the GitHub repo clone
|
||||
|
||||
#apt-get install git -y
|
||||
|
||||
#git clone https://github.com/TREX-CoE/trexio.git
|
||||
#cd trexio
|
||||
#git checkout swig-python
|
||||
|
||||
#./autogen.sh
|
||||
#TREXIO_DEVEL=1 ./configure --enable-silent-rules
|
||||
#make
|
||||
#make check
|
||||
|
||||
# ===============================
|
||||
|
||||
# alternatively: build wheel directly from developer-provided .tar.gz of TREXIO (generated with `python setup.py sdist`)
|
||||
# note: trexio-VERSION.tar.gz has to be in the root directory of the host machine
|
||||
|
||||
# process input: first argument is the name of the .tar.gz with the source code of the Python API
|
||||
if [[ -z "$1" ]]; then
|
||||
echo "Please specify the name of the TREXIO source code distribution (with .tar.gz suffix)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TREXIO_SOURCE=${1}
|
||||
|
||||
# remove prefix that ends with "-"
|
||||
tmp=${TREXIO_SOURCE#*-}
|
||||
# remove suffix that ends with ".tar.gz"
|
||||
TR_VERSION=${tmp%.tar.gz*}
|
||||
|
||||
echo "TREXIO VERSION:" ${TR_VERSION}
|
||||
|
||||
# unzip and enter the folder with TREXIO Python API
|
||||
gzip -cd /tmp/trexio-${TR_VERSION}.tar.gz | tar xvf -
|
||||
cd trexio-${TR_VERSION}
|
||||
|
||||
# create and activate a virtual environment based on CPython version 3.6
|
||||
/opt/python/cp36-cp36m/bin/python3 -m venv --clear trexio-manylinux-py36
|
||||
source trexio-manylinux-py36/bin/activate
|
||||
python3 --version
|
||||
|
||||
# upgrade pip, otherwise it complains that manylinux wheel is "...not supported wheel on this platform"
|
||||
pip install --upgrade pip
|
||||
# install dependencies needed to build manylinux wheel
|
||||
pip install --upgrade setuptools wheel auditwheel numpy
|
||||
|
||||
# set an environment variable needed to locate numpy header files
|
||||
source tools/set_NUMPY_INCLUDEDIR.sh
|
||||
|
||||
# produce conventional (non-manylinux) wheel
|
||||
python3 setup.py bdist_wheel
|
||||
|
||||
# use auditwheel from PyPA to repair all wheels and make them manylinux-compatible
|
||||
auditwheel repair dist/trexio-${TR_VERSION}-cp36-cp36m-*.whl
|
||||
|
||||
# install the produced manylinux wheel in the virtual environment
|
||||
python3 -m pip install wheelhouse/trexio-${TR_VERSION}-cp36-cp36m-manylinux*.whl
|
||||
|
||||
# run test script
|
||||
cd test && python3 test_api.py && cd ..
|
||||
|
||||
# cleaning
|
||||
rm -rf -- dist/ build/ trexio.egg-info/
|
||||
|
||||
# deactivate the current environment
|
||||
deactivate
|
||||
|
||||
# create and activate a virtual environment based on CPython version 3.7
|
||||
/opt/python/cp37-cp37m/bin/python3 -m venv --clear trexio-manylinux-py37
|
||||
source trexio-manylinux-py37/bin/activate
|
||||
python3 --version
|
||||
|
||||
# upgrade pip, otherwise it complains that manylinux wheel is "...not supported wheel on this platform"
|
||||
pip install --upgrade pip
|
||||
# install dependencies needed to build manylinux wheel
|
||||
pip install --upgrade setuptools wheel auditwheel numpy
|
||||
|
||||
# set an environment variable needed to locate numpy header files
|
||||
source tools/set_NUMPY_INCLUDEDIR.sh
|
||||
|
||||
# produce conventional (non-manylinux) wheel
|
||||
python3 setup.py bdist_wheel
|
||||
|
||||
# use auditwheel from PyPA to repair all wheels and make them manylinux-compatible
|
||||
auditwheel repair dist/trexio-${TR_VERSION}-cp37-cp37m-*.whl
|
||||
|
||||
# install the produced manylinux wheel in the virtual environment
|
||||
python3 -m pip install wheelhouse/trexio-${TR_VERSION}-cp37-cp37m-manylinux*.whl
|
||||
|
||||
# run test script
|
||||
cd test && python3 test_api.py && cd ..
|
||||
|
||||
# cleaning
|
||||
rm -rf -- dist/ build/ trexio.egg-info/
|
||||
|
||||
# deactivate the current environment
|
||||
deactivate
|
||||
|
||||
# create and activate a virtual environment based on CPython version 3.8
|
||||
# NOTE: starting from CPython 3.8 there is no need to add m in the abi-tag, e.g. use cp38-cp38 instead of cp38-cp38m
|
||||
/opt/python/cp38-cp38/bin/python3 -m venv --clear trexio-manylinux-py38
|
||||
source trexio-manylinux-py38/bin/activate
|
||||
python3 --version
|
||||
|
||||
# upgrade pip, otherwise it complains that manylinux wheel is "...not supported wheel on this platform"
|
||||
pip install --upgrade pip
|
||||
# install dependencies needed to build manylinux wheel
|
||||
pip3 install --upgrade setuptools wheel auditwheel numpy
|
||||
|
||||
# set an environment variable needed to locate numpy header files
|
||||
source tools/set_NUMPY_INCLUDEDIR.sh
|
||||
|
||||
# produce conventional (non-manylinux) wheel
|
||||
python3 setup.py bdist_wheel
|
||||
|
||||
# use auditwheel from PyPA to repair all wheels and make them manylinux-compatible
|
||||
auditwheel repair dist/trexio-${TR_VERSION}-cp38-cp38-*.whl
|
||||
|
||||
# install the produced manylinux wheel in the virtual environment
|
||||
python3 -m pip install wheelhouse/trexio-${TR_VERSION}-cp38-cp38-manylinux*.whl
|
||||
|
||||
# run test script
|
||||
cd test && python3 test_api.py && cd ..
|
||||
|
||||
# cleaning
|
||||
rm -rf -- dist/ build/ trexio.egg-info/
|
||||
|
||||
# deactivate the current environment
|
||||
deactivate
|
||||
|
||||
# create and activate a virtual environment based on CPython version 3.8
|
||||
/opt/python/cp39-cp39/bin/python3 -m venv --clear trexio-manylinux-py39
|
||||
source trexio-manylinux-py39/bin/activate
|
||||
python3 --version
|
||||
|
||||
# upgrade pip, otherwise it complains that manylinux wheel is "...not supported wheel on this platform"
|
||||
pip install --upgrade pip
|
||||
# install dependencies needed to build manylinux wheel
|
||||
pip3 install --upgrade setuptools wheel auditwheel numpy
|
||||
|
||||
# produce conventional (non-manylinux) wheel
|
||||
python3 setup.py bdist_wheel
|
||||
|
||||
# use auditwheel from PyPA to repair all wheels and make them manylinux-compatible
|
||||
auditwheel repair dist/trexio-${TR_VERSION}-cp39-cp39-*.whl
|
||||
|
||||
# install the produced manylinux wheel in the virtual environment
|
||||
python3 -m pip install wheelhouse/trexio-${TR_VERSION}-cp39-cp39-manylinux*.whl
|
||||
|
||||
# run test script
|
||||
cd test && python3 test_api.py && cd ..
|
||||
|
||||
# cleaning
|
||||
rm -rf -- dist/ build/ trexio.egg-info/
|
||||
|
||||
# deactivate the current environment
|
||||
deactivate
|
||||
|
||||
# remove all virtual environments used to produce the wheels
|
||||
rm -rf -- trexio-manylinux-py39 \
|
||||
trexio-manylinux-py38 \
|
||||
trexio-manylinux-py37 \
|
||||
trexio-manylinux-py36
|
||||
|
139
m4/ax_pkg_swig.m4
Normal file
139
m4/ax_pkg_swig.m4
Normal file
@ -0,0 +1,139 @@
|
||||
# ===========================================================================
|
||||
# https://www.gnu.org/software/autoconf-archive/ax_pkg_swig.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_PKG_SWIG([major.minor.micro], [action-if-found], [action-if-not-found])
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# This macro searches for a SWIG installation on your system. If found,
|
||||
# then SWIG is AC_SUBST'd; if not found, then $SWIG is empty. If SWIG is
|
||||
# found, then SWIG_LIB is set to the SWIG library path, and AC_SUBST'd.
|
||||
#
|
||||
# You can use the optional first argument to check if the version of the
|
||||
# available SWIG is greater than or equal to the value of the argument. It
|
||||
# should have the format: N[.N[.N]] (N is a number between 0 and 999. Only
|
||||
# the first N is mandatory.) If the version argument is given (e.g.
|
||||
# 1.3.17), AX_PKG_SWIG checks that the swig package is this version number
|
||||
# or higher.
|
||||
#
|
||||
# As usual, action-if-found is executed if SWIG is found, otherwise
|
||||
# action-if-not-found is executed.
|
||||
#
|
||||
# In configure.in, use as:
|
||||
#
|
||||
# AX_PKG_SWIG(1.3.17, [], [ AC_MSG_ERROR([SWIG is required to build..]) ])
|
||||
# AX_SWIG_ENABLE_CXX
|
||||
# AX_SWIG_MULTI_MODULE_SUPPORT
|
||||
# AX_SWIG_PYTHON
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2008 Sebastian Huber <sebastian-huber@web.de>
|
||||
# Copyright (c) 2008 Alan W. Irwin
|
||||
# Copyright (c) 2008 Rafael Laboissiere <rafael@laboissiere.net>
|
||||
# Copyright (c) 2008 Andrew Collier
|
||||
# Copyright (c) 2011 Murray Cumming <murrayc@openismus.com>
|
||||
# Copyright (c) 2021 Vincent Danjean <Vincent.Danjean@ens-lyon.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the
|
||||
# Free Software Foundation; either version 2 of the License, or (at your
|
||||
# option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
# Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
||||
# gives unlimited permission to copy, distribute and modify the configure
|
||||
# scripts that are the output of Autoconf when processing the Macro. You
|
||||
# need not follow the terms of the GNU General Public License when using
|
||||
# or distributing such scripts, even though portions of the text of the
|
||||
# Macro appear in them. The GNU General Public License (GPL) does govern
|
||||
# all other use of the material that constitutes the Autoconf Macro.
|
||||
#
|
||||
# This special exception to the GPL applies to versions of the Autoconf
|
||||
# Macro released by the Autoconf Archive. When you make and distribute a
|
||||
# modified version of the Autoconf Macro, you may extend this special
|
||||
# exception to the GPL to apply to your modified version as well.
|
||||
|
||||
#serial 14
|
||||
|
||||
AC_DEFUN([AX_PKG_SWIG],[
|
||||
# Find path to the "swig" executable.
|
||||
AC_PATH_PROGS([SWIG],[swig swig3.0 swig2.0])
|
||||
if test -z "$SWIG" ; then
|
||||
m4_ifval([$3],[$3],[:])
|
||||
elif test -z "$1" ; then
|
||||
m4_ifval([$2],[$2],[:])
|
||||
else
|
||||
AC_MSG_CHECKING([SWIG version])
|
||||
[swig_version=`$SWIG -version 2>&1 | grep 'SWIG Version' | sed 's/.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/g'`]
|
||||
AC_MSG_RESULT([$swig_version])
|
||||
if test -n "$swig_version" ; then
|
||||
# Calculate the required version number components
|
||||
[required=$1]
|
||||
[required_major=`echo $required | sed 's/[^0-9].*//'`]
|
||||
if test -z "$required_major" ; then
|
||||
[required_major=0]
|
||||
fi
|
||||
[required=`echo $required. | sed 's/[0-9]*[^0-9]//'`]
|
||||
[required_minor=`echo $required | sed 's/[^0-9].*//'`]
|
||||
if test -z "$required_minor" ; then
|
||||
[required_minor=0]
|
||||
fi
|
||||
[required=`echo $required. | sed 's/[0-9]*[^0-9]//'`]
|
||||
[required_patch=`echo $required | sed 's/[^0-9].*//'`]
|
||||
if test -z "$required_patch" ; then
|
||||
[required_patch=0]
|
||||
fi
|
||||
# Calculate the available version number components
|
||||
[available=$swig_version]
|
||||
[available_major=`echo $available | sed 's/[^0-9].*//'`]
|
||||
if test -z "$available_major" ; then
|
||||
[available_major=0]
|
||||
fi
|
||||
[available=`echo $available | sed 's/[0-9]*[^0-9]//'`]
|
||||
[available_minor=`echo $available | sed 's/[^0-9].*//'`]
|
||||
if test -z "$available_minor" ; then
|
||||
[available_minor=0]
|
||||
fi
|
||||
[available=`echo $available | sed 's/[0-9]*[^0-9]//'`]
|
||||
[available_patch=`echo $available | sed 's/[^0-9].*//'`]
|
||||
if test -z "$available_patch" ; then
|
||||
[available_patch=0]
|
||||
fi
|
||||
# Convert the version tuple into a single number for easier comparison.
|
||||
# Using base 100 should be safe since SWIG internally uses BCD values
|
||||
# to encode its version number.
|
||||
required_swig_vernum=`expr $required_major \* 10000 \
|
||||
\+ $required_minor \* 100 \+ $required_patch`
|
||||
available_swig_vernum=`expr $available_major \* 10000 \
|
||||
\+ $available_minor \* 100 \+ $available_patch`
|
||||
|
||||
if test $available_swig_vernum -lt $required_swig_vernum; then
|
||||
AC_MSG_WARN([SWIG version >= $1 is required. You have $swig_version.])
|
||||
SWIG=''
|
||||
m4_ifval([$3],[$3],[])
|
||||
else
|
||||
AC_MSG_CHECKING([for SWIG library])
|
||||
SWIG_LIB=`$SWIG -swiglib`
|
||||
AC_MSG_RESULT([$SWIG_LIB])
|
||||
m4_ifval([$2],[$2],[])
|
||||
fi
|
||||
else
|
||||
AC_MSG_WARN([cannot determine SWIG version])
|
||||
SWIG=''
|
||||
m4_ifval([$3],[$3],[])
|
||||
fi
|
||||
fi
|
||||
AC_SUBST([SWIG_LIB])
|
||||
])
|
||||
|
8
python/.gitignore
vendored
Normal file
8
python/.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
AUTHORS
|
||||
LICENSE
|
||||
src/
|
||||
|
||||
build/
|
||||
dist/
|
||||
*.egg-info/
|
||||
__pycache__/
|
9
python/MANIFEST.in
Normal file
9
python/MANIFEST.in
Normal file
@ -0,0 +1,9 @@
|
||||
include src/*.c
|
||||
include src/trexio*.h
|
||||
include examples/notebooks/*
|
||||
include examples/README.md
|
||||
include requirements.txt tools/set_NUMPY_INCLUDEDIR.sh
|
||||
|
||||
exclude examples/LICENSE
|
||||
exclude examples/requirements.txt
|
||||
exclude examples/runtime.txt
|
97
python/README.md
Normal file
97
python/README.md
Normal file
@ -0,0 +1,97 @@
|
||||
|
||||
# TREXIO Python API
|
||||
|
||||
[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/TREX-CoE/trexio-tutorials/HEAD)
|
||||
|
||||
TREXIO provides a Python API, which enables interactive calls to the library.
|
||||
It facilitates the development of interfaces between different codes and
|
||||
can be used to convert data from one input/output file format into another.
|
||||
|
||||
|
||||
## Requirements
|
||||
|
||||
- python3 (>= 3.6)
|
||||
- numpy
|
||||
- C compiler (gcc/icc)
|
||||
|
||||
|
||||
## Installation from PyPI
|
||||
|
||||
In short, you can run the following command:
|
||||
|
||||
`pip install trexio`
|
||||
|
||||
However, it is good practice to first check for updates of the build-system packages. This can be achieved by running
|
||||
|
||||
`python3 -m pip install --upgrade pip setuptools wheel`
|
||||
|
||||
**Note: we highly recommend to use virtual environments to avoid compatibility issues and to improve reproducibility.**
|
||||
For more details, see the corresponding part of the [Python documentation](https://docs.python.org/3/library/venv.html#creating-virtual-environments).
|
||||
|
||||
|
||||
## Additional requirements (for installation from source)
|
||||
|
||||
- HDF5 library (>= 1.8)
|
||||
- pkgconfig (Python package)
|
||||
|
||||
|
||||
## Installation from source
|
||||
|
||||
1. Download the `trexio-<version>.tar.gz` file with the latest Python API
|
||||
2. `gzip -cd trexio-<version>.tar.gz | tar xvf -`
|
||||
3. `cd trexio-<version>`
|
||||
4. `pip3 install -r requirements.txt` (this installs all required python dependencies)
|
||||
5. Export custom environment variables needed for the installation following the procedure below and replacing `/path/to/hdf5/` with your paths.
|
||||
Steps (i) and (ii) can be skipped if HDF5 is properly configured for `pkg-config` (i.e. if executing `pkg-config --libs hdf5` returns a list of options).
|
||||
1. `export H5_CFLAGS=-I/path/to/hdf5/include`
|
||||
2. `export H5_LDFLAGS=-L/path/to/hdf5/lib`
|
||||
3. `source tools/set_NUMPY_INCLUDEDIR.sh`
|
||||
6. `pip3 install .` (this installs `trexio` in your environment)
|
||||
7. `cd test && python3 test_api.py` (this executes several tests that verify the installation)
|
||||
|
||||
You are ready to go!
|
||||
|
||||
**Note:**
|
||||
installation based on `pip` compiles its own C extension (shared library) called `pytrexio`.
|
||||
This extension is built from the TREXIO source files coupled to the wrapper code generated by [SWIG](http://www.swig.org/).
|
||||
The compiler options during this installation may differ from the ones used to compile the primary TREXIO API in C.
|
||||
Furthermore, custom compiler flags provided to `./configure` or `make` are not applied to the Python API.
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
An interactive Jupyter notebook called `tutorial_benzene.ipynb` is provided in the `examples` directory.
|
||||
The notebook can be lauched either locally (see [next section](#Running-the-notebook) for details) or using [pre-built environment on Binder](https://mybinder.org/v2/gh/TREX-CoE/trexio-tutorials/HEAD?filepath=notebooks%2Ftutorial_benzene.ipynb).
|
||||
|
||||
Jupyter can be installed using `pip install jupyter`. If you are not familiar with it, feel free to consult the [Jupyter documentation](https://jupyter-notebook.readthedocs.io/en/stable/notebook.html).
|
||||
|
||||
|
||||
### Running the notebook
|
||||
|
||||
The example notebook can be launched using the following command:
|
||||
|
||||
`jupyter notebook tutorial_benzene.ipynb`
|
||||
|
||||
|
||||
### Additional steps needed to run a custom virtual environment in Jupyter notebooks
|
||||
|
||||
In some cases, it may happen that the Jupyter kernels in the activated virtual environment (e.g. `myvenv`) still point to the system-wide python binaries and not to the environment ones.
|
||||
This will result in `ImportError` when importing `trexio` in the notebook cell. In order to avoid this, the `myvenv` has to be installed as an additional kernel.
|
||||
This requires `ipykernel` python package, which usually comes together with the Jupyter installation. If this is not the case, run `pip install ipykernel`.
|
||||
You can install `myvenv` as a kernel by executing the following command:
|
||||
|
||||
`python3 -m ipykernel install --user --name=myvenv`
|
||||
|
||||
Now you can launch a Jupyter notebook. Once it is open, make sure that your virtual environment is selected as the current kernel.
|
||||
If this is not the case, try this:
|
||||
|
||||
1. Press the `Kernel` button in the navigation panel
|
||||
2. In the output list of options select `Change kernel`
|
||||
3. Find the name of your virtual environment (e.g. `myvenv`) in the list and select it
|
||||
|
||||
That's it, you have activated the custom virtual environment called `myvenv` in your notebook.
|
||||
|
||||
To uninstall the kernel named `myvenv`, execute the following command:
|
||||
|
||||
`jupyter kernelspec uninstall myvenv`
|
||||
|
1
python/examples
Submodule
1
python/examples
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit b631619698a4b608a8778c75a9a359731bfa682a
|
77
python/install_pytrexio.sh
Executable file
77
python/install_pytrexio.sh
Executable file
@ -0,0 +1,77 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -x
|
||||
set -e
|
||||
|
||||
# the parser below is needed when ./configure outputs several HDF5-related flags, which are then provided as input arguments to this script
|
||||
for arg in "$@"
|
||||
do
|
||||
if [[ $arg == "-L"* ]] && [[ $arg == *"hdf5"* ]]; then
|
||||
H5_LDFLAGS_LOCAL=$arg
|
||||
elif [[ $arg == "-I"* ]] && [[ $arg == *"hdf5"* ]]; then
|
||||
H5_CFLAGS_LOCAL=$arg
|
||||
fi
|
||||
done
|
||||
|
||||
# check that both variables are set
|
||||
if [[ -z ${H5_LDFLAGS_LOCAL} ]] || [[ -z ${H5_CFLAGS_LOCAL} ]]; then
|
||||
if [[ -z ${H5_LDFLAGS} ]] || [[ -z ${H5_CFLAGS} ]]; then
|
||||
echo "Paths to the HDF5 installation are not provided. pkgconfig will try to detect them."
|
||||
else
|
||||
echo "Using exported H5_LDFLAGS and H5_CFLAGS environment variables."
|
||||
fi
|
||||
else
|
||||
export H5_LDFLAGS=${H5_LDFLAGS_LOCAL}
|
||||
export H5_CFLAGS=${H5_CFLAGS_LOCAL}
|
||||
fi
|
||||
|
||||
# Install/upgrade packages required for the installation
|
||||
python3 -m pip install --upgrade setuptools wheel twine
|
||||
python3 -m pip install -r requirements.txt
|
||||
|
||||
# export NUMPY_INCLUDEDIR environment variable needed for the proper setup
|
||||
source tools/set_NUMPY_INCLUDEDIR.sh
|
||||
|
||||
if [[ -z ${NUMPY_INCLUDEDIR} ]] ; then
|
||||
echo "NUMPY_INCLUDEDIR is not set. Check that numpy is installed (e.g. call pip freeze)."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create build directory and compile extension files (*.c)
|
||||
# --no-user-cfg disables custom .cfg files of the user machine, so that only setup.cfg is used
|
||||
python3 -s setup.py --no-user-cfg build
|
||||
|
||||
# Local inplace build of the .so module with SWIG-produced pytrexio_wrap.c (from the SWIG documentation)
|
||||
#python3 setup.py build_ext --inplace --swig-opts="-modern"
|
||||
|
||||
# Create distributions:
|
||||
# 1) sdist produces .tar.gz with all files necessary for manual compilation;
|
||||
# 2) bdist_whell produces .whl wheel distribution (see https://www.python.org/dev/peps/pep-0425/).
|
||||
python3 setup.py sdist bdist_wheel
|
||||
|
||||
# Install pytrexio in the current environment from the aforementioned wheel
|
||||
# --force-reinstall is needed here because build-system pre-installs pytrexio in the environment
|
||||
# but does not install things in the corresponding site-packages directory
|
||||
python3 -m pip install dist/trexio-*.whl --force-reinstall
|
||||
|
||||
# Run the command below in the root directory to install the package in 'editable' (-e) mode without dependencies (--no-deps)
|
||||
#python -m pip install -e . --no-deps
|
||||
|
||||
# Uninstall pytrexio: this only works from the pytrexio root directory
|
||||
#python3 -m pip uninstall trexio
|
||||
|
||||
# Test the current release by uploading to TestPyPI sandbox
|
||||
#python3 -m twine upload --repository testpypi dist/trexio-*.tar.gz
|
||||
|
||||
# Upload updated version of PyTREXIO to PyPI
|
||||
#python3 -m twine upload dist/trexio-*.tar.gz
|
||||
|
||||
# Cleaning
|
||||
rm -rf build dist trexio.egg-info
|
||||
|
||||
# Additional information related to the installation of the TREXIO Python API
|
||||
|
||||
#Removing MANIFEST.in leads to issues in the installation. In particular, the .c and .h source files do not get copied
|
||||
#from the src/ directory into the tar.gz which is produced by setup sdist command.
|
||||
#These source files are required to build the pytrexio.so extension module, which is needed for the Python API.
|
||||
|
7
python/pyproject.toml
Normal file
7
python/pyproject.toml
Normal file
@ -0,0 +1,7 @@
|
||||
[build-system]
|
||||
requires = [
|
||||
"setuptools>=42",
|
||||
"wheel",
|
||||
"pkgconfig"
|
||||
]
|
||||
build-backend = "setuptools.build_meta"
|
1
python/pytrexio/__init__.py
Normal file
1
python/pytrexio/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
#from ._version import __version__
|
1
python/pytrexio/_version.py
Normal file
1
python/pytrexio/_version.py
Normal file
@ -0,0 +1 @@
|
||||
__version__ = "0.1.0"
|
3
python/requirements.txt
Normal file
3
python/requirements.txt
Normal file
@ -0,0 +1,3 @@
|
||||
setuptools>=42
|
||||
pkgconfig
|
||||
numpy
|
11
python/setup.cfg
Normal file
11
python/setup.cfg
Normal file
@ -0,0 +1,11 @@
|
||||
[metadata]
|
||||
long_description = file: README.md
|
||||
licence_file = LICENSE
|
||||
project_urls =
|
||||
Bug Tracker = https://github.com/TREX-CoE/trexio/issues
|
||||
license = BSD 3-Clause License
|
||||
|
||||
[options]
|
||||
zip_safe = False
|
||||
python_requires = >=3.6
|
||||
|
119
python/setup.py
Normal file
119
python/setup.py
Normal file
@ -0,0 +1,119 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
setup.py file for TREXIO Python package
|
||||
"""
|
||||
|
||||
|
||||
import os
|
||||
from setuptools import setup, Extension
|
||||
|
||||
# this was recommended to solve the problem of the missing numpy header files
|
||||
# bit it causes `pip install .` to fail with numpy module not found error
|
||||
#try:
|
||||
# import numpy
|
||||
#except ImportError:
|
||||
# raise Exception("numpy Python package cannot be imported.")
|
||||
#numpy_includedir = numpy.get_include()
|
||||
|
||||
# this does not cause aforementioned issue but the includedir points to system-wide numpy and not to venv-wide
|
||||
#from distutils.sysconfig import get_python_inc
|
||||
#numpy_includedir = os.path.join(get_python_inc(plat_specific=1), 'numpy')
|
||||
|
||||
# dirty workaround: get numpy includedir from the environment variable that can be pre-set using set_NUMPY_INCLUDEDIR.sh
|
||||
numpy_includedir = os.environ.get("NUMPY_INCLUDEDIR", None)
|
||||
numpy_isUndefined = numpy_includedir is None or numpy_includedir==""
|
||||
|
||||
if numpy_isUndefined:
|
||||
raise Exception("NUMPY_INCLUDEDIR environment variable is not specified. Please do it manually or execute set_NUMPY_INCLUDEDIR.sh script.")
|
||||
|
||||
|
||||
rootpath = os.path.dirname(os.path.abspath(__file__))
|
||||
srcpath = os.path.join(rootpath, 'src')
|
||||
c_files = ['trexio.c', 'trexio_hdf5.c', 'trexio_text.c', 'pytrexio_wrap.c']
|
||||
|
||||
|
||||
with open("README.md", "r") as fh:
|
||||
long_description = fh.read()
|
||||
|
||||
VERSIONFILE = "pytrexio/_version.py"
|
||||
try:
|
||||
exec(open(VERSIONFILE).read())
|
||||
except:
|
||||
raise IOError("Could not open the version file %s." % (VERSIONFILE, ))
|
||||
|
||||
version_r = __version__
|
||||
if not version_r:
|
||||
raise RuntimeError("Unable to find a version string in %s." % (VERSIONFILE, ))
|
||||
|
||||
|
||||
# =========================== Start of the HDF5 block =========================== #
|
||||
# The block below is needed to derive additional flags related to the HDF5 library,
|
||||
# which is required to build pytrexio extension module during the setup.py execution
|
||||
|
||||
h5_ldflags_withl = os.environ.get("H5_LDFLAGS", None)
|
||||
h5_cflags_withI = os.environ.get("H5_CFLAGS", None)
|
||||
|
||||
h5_ldflags_isUndefined = h5_ldflags_withl is None or h5_ldflags_withl==""
|
||||
h5_cflags_isUndefined = h5_cflags_withI is None or h5_cflags_withI==""
|
||||
|
||||
if h5_ldflags_isUndefined or h5_cflags_isUndefined:
|
||||
|
||||
try:
|
||||
import pkgconfig as pk
|
||||
except ImportError:
|
||||
raise Exception("pkgconfig Python package cannot be imported.")
|
||||
|
||||
try:
|
||||
assert pk.exists('hdf5')
|
||||
except AssertionError:
|
||||
raise Exception("pkg-config could not locate HDF5")
|
||||
|
||||
h5_cflags_withI = pk.cflags('hdf5')
|
||||
h5_ldflags_withl = pk.libs('hdf5')
|
||||
|
||||
h5_cflags = h5_cflags_withI.replace("-I","").split(" ")[0]
|
||||
h5_ldflags = h5_ldflags_withl.split(" ")[0]
|
||||
|
||||
# ============================ End of the HDF5 block ============================ #
|
||||
|
||||
# Define pytrexio extension module based on TREXIO source codes + SWIG-generated wrapper
|
||||
pytrexio_module = Extension('pytrexio._pytrexio',
|
||||
sources = [os.path.join(srcpath, code) for code in c_files],
|
||||
include_dirs = [h5_cflags, srcpath, numpy_includedir],
|
||||
libraries = ['hdf5', 'hdf5_hl'],
|
||||
extra_compile_args = ['-Wno-discarded-qualifiers'],
|
||||
extra_link_args = [h5_ldflags]
|
||||
)
|
||||
|
||||
|
||||
setup(name = 'trexio',
|
||||
version = version_r,
|
||||
author = "TREX-CoE",
|
||||
author_email = "posenitskiy@irsamc.ups-tlse.fr",
|
||||
description = """Python API of the TREXIO library""",
|
||||
long_description = long_description,
|
||||
long_description_content_type = "text/markdown",
|
||||
ext_modules = [pytrexio_module],
|
||||
py_modules = ['trexio'],
|
||||
packages = ['pytrexio'],
|
||||
url = 'https://github.com/TREX-CoE/trexio',
|
||||
license = 'BSD',
|
||||
classifiers=[
|
||||
"Intended Audience :: Science/Research",
|
||||
"Intended Audience :: Developers",
|
||||
"Topic :: Scientific/Engineering",
|
||||
"Programming Language :: C",
|
||||
"Programming Language :: Python",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
"Programming Language :: Python :: Implementation :: CPython",
|
||||
"License :: OSI Approved :: BSD License",
|
||||
"Operating System :: POSIX",
|
||||
"Operating System :: Unix",
|
||||
"Operating System :: MacOS"
|
||||
],
|
||||
python_requires = ">=3.6",
|
||||
setup_requires = ['numpy', 'pkgconfig'],
|
||||
install_requires = ['numpy']
|
||||
)
|
||||
|
217
python/test/test_api.py
Normal file
217
python/test/test_api.py
Normal file
@ -0,0 +1,217 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import numpy as np
|
||||
|
||||
import trexio
|
||||
|
||||
#=========================================================#
|
||||
#======== SETUP THE BACK END AND OUTPUT FILE NAME ========#
|
||||
#=========================================================#
|
||||
|
||||
# 0: TREXIO_HDF5 ; 1: TREXIO_TEXT
|
||||
TEST_TREXIO_BACKEND = 0
|
||||
OUTPUT_FILENAME_TEXT = 'test_py_swig.dir'
|
||||
OUTPUT_FILENAME_HDF5 = 'test_py_swig.h5'
|
||||
|
||||
|
||||
# define TREXIO file name
|
||||
if TEST_TREXIO_BACKEND == trexio.TREXIO_HDF5:
|
||||
output_filename = OUTPUT_FILENAME_HDF5
|
||||
elif TEST_TREXIO_BACKEND == trexio.TREXIO_TEXT:
|
||||
output_filename = OUTPUT_FILENAME_TEXT
|
||||
else:
|
||||
raise ValueError ('Specify one of the supported back ends as TEST_TREXIO_BACKEND')
|
||||
|
||||
|
||||
# remove TREXIO file if exists in the current directory
|
||||
try:
|
||||
if TEST_TREXIO_BACKEND == trexio.TREXIO_HDF5:
|
||||
os.remove(output_filename)
|
||||
elif TEST_TREXIO_BACKEND == trexio.TREXIO_TEXT:
|
||||
shutil.rmtree(output_filename)
|
||||
except:
|
||||
print ('Nothing to remove.')
|
||||
|
||||
#=========================================================#
|
||||
#============ WRITE THE DATA IN THE TEST FILE ============#
|
||||
#=========================================================#
|
||||
|
||||
# create TREXIO file and open it for writing
|
||||
test_file = trexio.File(output_filename, mode='w', back_end=TEST_TREXIO_BACKEND)
|
||||
|
||||
# Print docstring of the trexio.open function
|
||||
#print(trexio.open.__doc__)
|
||||
|
||||
nucleus_num = 12
|
||||
|
||||
try:
|
||||
trexio.write_nucleus_num(test_file, -100)
|
||||
except trexio.Error:
|
||||
print("Writing negative nucleus_num: checked.")
|
||||
|
||||
# write nucleus_num in the file
|
||||
try:
|
||||
trexio.write_nucleus_num(test_file, nucleus_num)
|
||||
except:
|
||||
raise
|
||||
|
||||
try:
|
||||
trexio.write_nucleus_num(test_file, nucleus_num*2)
|
||||
except trexio.Error:
|
||||
print("Attempt to overwrite nucleus_num: checked.")
|
||||
|
||||
# initialize charge arrays as a list and convert it to numpy array
|
||||
charges = [6., 6., 6., 6., 6., 6., 1., 1., 1., 1., 1., 1.]
|
||||
#charges_np = np.array(charges, dtype=np.float32)
|
||||
charges_np = np.array(charges, dtype=np.int32)
|
||||
|
||||
# function call below works with both lists and numpy arrays, dimension needed for memory-safety is derived
|
||||
# from the size of the list/array by SWIG using typemaps from numpy.i
|
||||
trexio.write_nucleus_charge(test_file, charges_np)
|
||||
|
||||
# initialize arrays of nuclear indices as a list and convert it to numpy array
|
||||
indices = [i for i in range(nucleus_num)]
|
||||
# type cast is important here because by default numpy transforms a list of integers into int64 array
|
||||
indices_np = np.array(indices, dtype=np.int64)
|
||||
|
||||
# function call below works with both lists and numpy arrays, dimension needed for memory-safety is derived
|
||||
# from the size of the list/array by SWIG using typemacs from numpy.i
|
||||
trexio.write_basis_nucleus_index(test_file, indices_np)
|
||||
|
||||
# initialize a list of nuclear coordinates
|
||||
coords = [
|
||||
[ 0.00000000 , 1.39250319 , 0.00000000 ],
|
||||
[-1.20594314 , 0.69625160 , 0.00000000 ],
|
||||
[-1.20594314 , -0.69625160 , 0.00000000 ],
|
||||
[ 0.00000000 , -1.39250319 , 0.00000000 ],
|
||||
[ 1.20594314 , -0.69625160 , 0.00000000 ],
|
||||
[ 1.20594314 , 0.69625160 , 0.00000000 ],
|
||||
[-2.14171677 , 1.23652075 , 0.00000000 ],
|
||||
[-2.14171677 , -1.23652075 , 0.00000000 ],
|
||||
[ 0.00000000 , -2.47304151 , 0.00000000 ],
|
||||
[ 2.14171677 , -1.23652075 , 0.00000000 ],
|
||||
[ 2.14171677 , 1.23652075 , 0.00000000 ],
|
||||
[ 0.00000000 , 2.47304151 , 0.00000000 ],
|
||||
]
|
||||
|
||||
# write coordinates in the file
|
||||
trexio.write_nucleus_coord(test_file, coords)
|
||||
|
||||
point_group = 'B3U'
|
||||
|
||||
# write nucleus_point_group in the file
|
||||
trexio.write_nucleus_point_group(test_file, point_group)
|
||||
|
||||
labels = [
|
||||
'C',
|
||||
'C',
|
||||
'C',
|
||||
'C',
|
||||
'C',
|
||||
'C',
|
||||
'H',
|
||||
'H',
|
||||
'H',
|
||||
'H',
|
||||
'H',
|
||||
'H']
|
||||
|
||||
# write nucleus_label in the file
|
||||
trexio.write_nucleus_label(test_file,labels)
|
||||
|
||||
# close TREXIO file
|
||||
# this call is no longer needed as we introduced TREXIO_File class which has a desctructor that closes the file
|
||||
#trexio.close(test_file)
|
||||
# without calling destructor on test_file the TREXIO_FILE is not getting created and the data is not written when using TEXT back end.
|
||||
# This, the user still has to explicitly call destructor on test_file object instead of the trexio.close function.
|
||||
# This is only an issue when the data is getting written and read in the same session (e.g. in Jupyter notebook)
|
||||
del test_file
|
||||
|
||||
|
||||
#==========================================================#
|
||||
#============ READ THE DATA FROM THE TEST FILE ============#
|
||||
#==========================================================#
|
||||
|
||||
# open previously created TREXIO file, now in 'read' mode
|
||||
test_file2 = trexio.File(output_filename, 'r', TEST_TREXIO_BACKEND)
|
||||
|
||||
# check for existence of some of the previously written variables
|
||||
assert trexio.has_nucleus_num
|
||||
assert trexio.has_nucleus_charge
|
||||
assert trexio.has_nucleus_coord
|
||||
assert trexio.has_nucleus_label
|
||||
assert trexio.has_nucleus_point_group
|
||||
|
||||
# read nucleus_num from file
|
||||
rnum = trexio.read_nucleus_num(test_file2)
|
||||
assert rnum==nucleus_num
|
||||
|
||||
# safe call to read_nucleus_charge array of float values
|
||||
rcharges_np = trexio.read_nucleus_charge(test_file2, dim=nucleus_num)
|
||||
assert rcharges_np.dtype is np.dtype(np.float64)
|
||||
np.testing.assert_array_almost_equal(rcharges_np, charges_np, decimal=8)
|
||||
|
||||
# unsafe call to read_safe should fail with error message corresponding to TREXIO_UNSAFE_ARRAY_DIM
|
||||
try:
|
||||
rcharges_fail = trexio.read_nucleus_charge(test_file2, dim=nucleus_num*5)
|
||||
except trexio.Error:
|
||||
print("Unsafe call to safe API: checked")
|
||||
|
||||
# safe call to read array of int values (nuclear indices)
|
||||
rindices_np_16 = trexio.read_basis_nucleus_index(test_file2, dim=nucleus_num, dtype=np.int16)
|
||||
assert rindices_np_16.dtype is np.dtype(np.int16)
|
||||
for i in range(nucleus_num):
|
||||
assert rindices_np_16[i]==indices_np[i]
|
||||
|
||||
rindices_np_32 = trexio.read_basis_nucleus_index(test_file2, dim=nucleus_num, dtype=np.int32)
|
||||
assert rindices_np_32.dtype is np.dtype(np.int32)
|
||||
for i in range(nucleus_num):
|
||||
assert rindices_np_32[i]==indices_np[i]
|
||||
|
||||
rindices_np_64 = trexio.read_basis_nucleus_index(test_file2)
|
||||
assert rindices_np_64.dtype is np.dtype(np.int64)
|
||||
assert rindices_np_64.size==nucleus_num
|
||||
for i in range(nucleus_num):
|
||||
assert rindices_np_64[i]==indices_np[i]
|
||||
|
||||
# read nuclear coordinates without providing optional argument dim
|
||||
rcoords_np = trexio.read_nucleus_coord(test_file2)
|
||||
|
||||
assert rcoords_np.size==nucleus_num*3
|
||||
np.testing.assert_array_almost_equal(rcoords_np, np.array(coords).reshape(nucleus_num,3), decimal=8)
|
||||
|
||||
# set doReshape to False to get a flat 1D array (e.g. when reading matrices like nuclear coordinates)
|
||||
#rcoords_reshaped_2 = trexio.read_nucleus_coord(test_file2, doReshape=False)
|
||||
|
||||
# read array of nuclear labels
|
||||
rlabels_2d = trexio.read_nucleus_label(test_file2, dim=nucleus_num)
|
||||
print(rlabels_2d)
|
||||
for i in range(nucleus_num):
|
||||
assert rlabels_2d[i]==labels[i]
|
||||
|
||||
# read a string corresponding to nuclear point group
|
||||
rpoint_group = trexio.read_nucleus_point_group(test_file2)
|
||||
assert rpoint_group==point_group
|
||||
|
||||
# another way to read only if the variable exists
|
||||
if trexio.has_mo_num(test_file2):
|
||||
rmo_num = trexio.read_mo_num(test_file2)
|
||||
else:
|
||||
print("Not reading the non-existing variable mo_num.")
|
||||
|
||||
# close TREXIO file
|
||||
#trexio.close(test_file2)
|
||||
|
||||
# cleaning (remove the TREXIO file)
|
||||
try:
|
||||
if TEST_TREXIO_BACKEND == trexio.TREXIO_HDF5:
|
||||
os.remove(output_filename)
|
||||
elif TEST_TREXIO_BACKEND == trexio.TREXIO_TEXT:
|
||||
shutil.rmtree(output_filename)
|
||||
except:
|
||||
print (f'No output file {output_filename} has been produced')
|
||||
|
||||
#==========================================================#
|
||||
|
160
python/test/test_pytrexio.py
Normal file
160
python/test/test_pytrexio.py
Normal file
@ -0,0 +1,160 @@
|
||||
import os
|
||||
import shutil
|
||||
import numpy as np
|
||||
|
||||
from pytrexio.pytrexio import *
|
||||
|
||||
#=========================================================#
|
||||
#======== SETUP THE BACK END AND OUTPUT FILE NAME ========#
|
||||
#=========================================================#
|
||||
|
||||
# 0: TREXIO_HDF5 ; 1: TREXIO_TEXT
|
||||
TEST_TREXIO_BACKEND = 1
|
||||
OUTPUT_FILENAME_TEXT = 'test_py_swig.dir'
|
||||
OUTPUT_FILENAME_HDF5 = 'test_py_swig.h5'
|
||||
|
||||
|
||||
if TEST_TREXIO_BACKEND == 0:
|
||||
output_filename = OUTPUT_FILENAME_HDF5
|
||||
elif TEST_TREXIO_BACKEND == 1:
|
||||
output_filename = OUTPUT_FILENAME_TEXT
|
||||
else:
|
||||
raise ValueError ('Specify one of the supported back ends as TEST_TREXIO_BACKEND')
|
||||
|
||||
|
||||
try:
|
||||
if TEST_TREXIO_BACKEND == 0:
|
||||
os.remove(output_filename)
|
||||
elif TEST_TREXIO_BACKEND == 1:
|
||||
shutil.rmtree(output_filename)
|
||||
except:
|
||||
print ('Nothing to remove.')
|
||||
|
||||
#=========================================================#
|
||||
#============ WRITE THE DATA IN THE TEST FILE ============#
|
||||
#=========================================================#
|
||||
|
||||
test_file = trexio_open(output_filename, 'w', TEST_TREXIO_BACKEND)
|
||||
|
||||
nucleus_num = 12
|
||||
|
||||
rc = trexio_write_nucleus_num(test_file, nucleus_num)
|
||||
assert rc==0
|
||||
|
||||
# initialize charge arrays as a list and convert it to numpy array
|
||||
charges = [6., 6., 6., 6., 6., 6., 1., 1., 1., 1., 1., 1.]
|
||||
charges_np = np.array(charges, dtype=np.float64)
|
||||
|
||||
# function call below works with both lists and numpy arrays, dimension needed for memory-safety is derived
|
||||
# from the size of the list/array by SWIG using typemaps from numpy.i
|
||||
rc = trexio_write_safe_nucleus_charge(test_file, charges_np)
|
||||
assert rc==0
|
||||
|
||||
# less Python-ic way to read/write arrays using Array classes (probably more portable to other languages)
|
||||
#charges = doubleArray(nucleus_num)
|
||||
#for i in range(nucleus_num):
|
||||
# if i < nucleus_num/2:
|
||||
# charges[i] = 6.
|
||||
# else:
|
||||
# charges[i] = 1.
|
||||
#rc = trexio_write_nucleus_charge(test_file, charges)
|
||||
|
||||
# initialize arrays of nuclear indices as a list and convert it to numpy array
|
||||
indices = [i for i in range(nucleus_num)]
|
||||
# type cast is important here because by default numpy transforms a list of integers into int64 array
|
||||
indices_np = np.array(indices, dtype=np.int32)
|
||||
|
||||
# function call below works with both lists and numpy arrays, dimension needed for memory-safety is derived
|
||||
# from the size of the list/array by SWIG using typemacs from numpy.i
|
||||
rc = trexio_write_safe_basis_nucleus_index(test_file, indices_np)
|
||||
assert rc==0
|
||||
|
||||
point_group = 'B3U'
|
||||
|
||||
rc = trexio_write_nucleus_point_group(test_file, point_group, 10)
|
||||
assert rc==0
|
||||
|
||||
labels = [
|
||||
'C',
|
||||
'C',
|
||||
'C',
|
||||
'C',
|
||||
'C',
|
||||
'C',
|
||||
'H',
|
||||
'H',
|
||||
'H',
|
||||
'H',
|
||||
'H',
|
||||
'H']
|
||||
|
||||
rc = trexio_write_nucleus_label(test_file, labels, 10)
|
||||
assert rc==0
|
||||
|
||||
rc = trexio_close(test_file)
|
||||
assert rc==0
|
||||
|
||||
#==========================================================#
|
||||
#============ READ THE DATA FROM THE TEST FILE ============#
|
||||
#==========================================================#
|
||||
|
||||
test_file2 = trexio_open(output_filename, 'r', TEST_TREXIO_BACKEND)
|
||||
|
||||
result = trexio_read_nucleus_num(test_file2)
|
||||
assert result[0]==0
|
||||
assert result[1]==nucleus_num
|
||||
|
||||
# safe call to read_safe array of float values
|
||||
rc, rcharges_np = trexio_read_safe_nucleus_charge(test_file2, nucleus_num)
|
||||
assert rc==0
|
||||
assert rcharges_np.dtype is np.dtype(np.float64)
|
||||
np.testing.assert_array_almost_equal(rcharges_np, charges_np, decimal=8)
|
||||
|
||||
# unsafe call to read_safe should not only have return code = TREXIO_UNSAFE_ARRAY_DIM
|
||||
# TODO: it should not return numpy array filled with garbage
|
||||
rc, rcharges_fail = trexio_read_safe_nucleus_charge(test_file2, nucleus_num*5)
|
||||
assert rc==23
|
||||
|
||||
# less Python-ic way to read/write arrays using Array classes (probably more portable to other languages)
|
||||
#charges2 = doubleArray(nucleus_num)
|
||||
#for i in range(nucleus_num):
|
||||
# charges2[i] = -1.
|
||||
#rc = trexio_read_nucleus_charge(test_file2, charges2)
|
||||
#assert rc==0
|
||||
#for i in range(nucleus_num):
|
||||
# assert charges2[i]==charges[i]
|
||||
|
||||
# safe call to read_safe array of int values
|
||||
rc, rindices_np = trexio_read_safe_basis_nucleus_index(test_file2, nucleus_num)
|
||||
assert rc==0
|
||||
assert rindices_np.dtype is np.dtype(np.int32)
|
||||
for i in range(nucleus_num):
|
||||
assert rindices_np[i]==indices_np[i]
|
||||
|
||||
# currently only low-level routines (return one long string instead of an array of strings) work
|
||||
rc, labels_1d = trexio_read_nucleus_label_low(test_file2, 10)
|
||||
assert rc==0
|
||||
|
||||
labels_2d = [label for label in labels_1d.split(TREXIO_DELIM) if label]
|
||||
print('Read and parsed nuclear labels:\n', labels_2d)
|
||||
for i in range(nucleus_num):
|
||||
assert labels_2d[i]==labels[i]
|
||||
|
||||
rc, rpoint_group = trexio_read_nucleus_point_group(test_file2, 3)
|
||||
print(f'Read point group: {rpoint_group}')
|
||||
assert rc==0
|
||||
assert rpoint_group==point_group
|
||||
|
||||
rc = trexio_close(test_file2)
|
||||
assert rc==0
|
||||
|
||||
try:
|
||||
if TEST_TREXIO_BACKEND == 0:
|
||||
os.remove(output_filename)
|
||||
elif TEST_TREXIO_BACKEND == 1:
|
||||
shutil.rmtree(output_filename)
|
||||
except:
|
||||
print (f'No output file {output_filename} has been produced')
|
||||
|
||||
#==========================================================#
|
||||
|
4
python/tools/set_NUMPY_INCLUDEDIR.sh
Executable file
4
python/tools/set_NUMPY_INCLUDEDIR.sh
Executable file
@ -0,0 +1,4 @@
|
||||
|
||||
INCLUDEDIR=`python -c 'import numpy; print(numpy.get_include())'`
|
||||
export NUMPY_INCLUDEDIR=${INCLUDEDIR}
|
||||
|
14
src/.gitignore
vendored
14
src/.gitignore
vendored
@ -2,6 +2,7 @@ templates_front/*.c
|
||||
templates_front/*.h
|
||||
templates_front/*.f90
|
||||
templates_front/*.fh_90
|
||||
templates_front/*.py
|
||||
templates_front/*.dump
|
||||
templates_front/populated/
|
||||
|
||||
@ -15,20 +16,21 @@ templates_text/*.h
|
||||
templates_text/*.dump
|
||||
templates_text/populated/
|
||||
|
||||
libtrexio.so
|
||||
*.so
|
||||
*.o
|
||||
*.h
|
||||
*.dump
|
||||
*.cppcheck
|
||||
|
||||
trexio.c
|
||||
trexio_text.c
|
||||
trexio_hdf5.c
|
||||
trexio_f.f90
|
||||
trexio.mod
|
||||
|
||||
test_c
|
||||
test_f
|
||||
*.h5
|
||||
trexio_test/
|
||||
trexio_test_fort/
|
||||
pytrexio.py
|
||||
pytrexio_wrap.c
|
||||
|
||||
*.h5
|
||||
*.dir/
|
||||
__pycache__/
|
||||
|
3028
src/numpy.i
Normal file
3028
src/numpy.i
Normal file
File diff suppressed because it is too large
Load Diff
126
src/pytrexio.i
Normal file
126
src/pytrexio.i
Normal file
@ -0,0 +1,126 @@
|
||||
%module pytrexio
|
||||
/* Define SWIGWORDSIZE in order to properly align long integers on 64-bit system */
|
||||
#define SWIGWORDSIZE64
|
||||
%{
|
||||
#define SWIG_FILE_WITH_INIT
|
||||
/* Include the headers in the wrapper code */
|
||||
#include "trexio_s.h"
|
||||
#include "trexio.h"
|
||||
%}
|
||||
|
||||
/* Include stdint to recognize types from stdint.h */
|
||||
%include <stdint.i>
|
||||
|
||||
/* NOTE:
|
||||
carrays was useful before numpy.i was introduced.
|
||||
For Python interface it's better to use numpy arrays instead of carrays, because the latter are less python-ic.
|
||||
On the other hand, carrays might be more portable to other target languages.
|
||||
// Include carrays to work with C pointers to arrays
|
||||
%include "carrays.i"
|
||||
// Include classes that correspond to integer and float arrays
|
||||
%array_class(double, doubleArray);
|
||||
%array_class(float, floatArray);
|
||||
%array_class(int32_t, int32Array);
|
||||
%array_class(int64_t, int64Array);
|
||||
*/
|
||||
|
||||
/* Include typemaps to play with input/output re-casting
|
||||
Useful when working with C pointers
|
||||
*/
|
||||
%include typemaps.i
|
||||
/* Redefine the int32_t* and int64_t* num to be output
|
||||
Useful for TREXIO read_num functions where the
|
||||
num variable is modified by address
|
||||
*/
|
||||
%apply int *OUTPUT { int32_t* const num};
|
||||
%apply int *OUTPUT { int64_t* const num};
|
||||
|
||||
/* Does not work for arrays (SIGSEGV) */
|
||||
|
||||
/* This enables access to trexio_[...]_read_dset_str_low set of functions
|
||||
in order to return one long string with TREXIO_DELIM delimeter as 2-nd argument of output tuple
|
||||
*/
|
||||
%include <cstring.i>
|
||||
/* This enables read of long strings with TREXIO_DELIM delimeters that can be further converted into an array of string */
|
||||
%cstring_bounded_output(char* dset_out, 4096);
|
||||
/* This enables read of single string attributes with pre-defined max_str_len
|
||||
for Python we pre-define max_str_len = PYTREXIO_MAX_STR_LENGTH everywhere for simplicity
|
||||
*/
|
||||
%cstring_output_maxsize(char* const str_out, const int32_t max_str_len);
|
||||
|
||||
/* [WIP] TREXIO back ends and exit codes can be redefined in the SWIG target language
|
||||
using %ignore and further #define statements (instead of disabling the type cast in the trexio.h file)
|
||||
*/
|
||||
/*
|
||||
%ignore TREXIO_HDF5; // Ignore a macro in the header file
|
||||
%ignore TREXIO_TEST; // Ignore a macro in the header file
|
||||
#define TREXIO_HDF5 0
|
||||
#define TREXIO_TEXT 0
|
||||
*/
|
||||
|
||||
/* This is an attempt to make SWIG treat double * dset_out|_in, int64_t dim_out|_in pattern
|
||||
as a special case in order to return the NumPy array to Python from C pointer to array
|
||||
provided by trexio_read_safe_[dset_num] function.
|
||||
NOTE: numpy.i is currently not part of SWIG but included in the numpy distribution (under numpy/tools/swig/numpy.i)
|
||||
This means that the interface file have to be provided to SWIG during compilation either by
|
||||
copying it to the local working directory or by providing -l/path/to/numpy.i flag upon SWIG compilation
|
||||
*/
|
||||
%include "numpy.i"
|
||||
|
||||
%init %{
|
||||
import_array();
|
||||
%}
|
||||
|
||||
/* Typemaps below change the type of numpy array dimensions from int to int64_t */
|
||||
%numpy_typemaps(double, NPY_DOUBLE, int64_t)
|
||||
%numpy_typemaps(float, NPY_FLOAT, int64_t)
|
||||
%numpy_typemaps(int32_t, NPY_INT32, int64_t)
|
||||
%numpy_typemaps(int64_t, NPY_INT64, int64_t)
|
||||
/* Enable write|read_safe functions to convert numpy arrays from/to double arrays */
|
||||
%apply (double* ARGOUT_ARRAY1, int64_t DIM1) {(double * const dset_out, const int64_t dim_out)};
|
||||
%apply (double* IN_ARRAY1, int64_t DIM1) {(const double * dset_in, const int64_t dim_in)};
|
||||
/* Enable write|read_safe functions to convert numpy arrays from/to float arrays */
|
||||
%apply (float* ARGOUT_ARRAY1, int64_t DIM1) {(float * const dset_out, const int64_t dim_out)};
|
||||
%apply (float* IN_ARRAY1, int64_t DIM1) {(const float * dset_in, const int64_t dim_in)};
|
||||
/* Enable write|read_safe functions to convert numpy arrays from/to int32 arrays */
|
||||
%apply (int32_t* ARGOUT_ARRAY1, int64_t DIM1) {(int32_t * const dset_out, const int64_t dim_out)};
|
||||
%apply (int32_t* IN_ARRAY1, int64_t DIM1) {(const int32_t * dset_in, const int64_t dim_in)};
|
||||
/* Enable write|read_safe functions to convert numpy arrays from/to int64 arrays */
|
||||
%apply (int64_t* ARGOUT_ARRAY1, int64_t DIM1) {(int64_t * const dset_out, const int64_t dim_out)};
|
||||
%apply (int64_t* IN_ARRAY1, int64_t DIM1) {(const int64_t * dset_in, const int64_t dim_in)};
|
||||
|
||||
/* This tells SWIG to treat char ** dset_in pattern as a special case
|
||||
Enables access to trexio_[...]_write_dset_str set of functions directly, i.e.
|
||||
by converting input list of strings from Python into char ** of C
|
||||
*/
|
||||
%typemap(in) char ** dset_in {
|
||||
/* Check if is a list */
|
||||
if (PyList_Check($input)) {
|
||||
int size = PyList_Size($input);
|
||||
Py_ssize_t i = 0;
|
||||
$1 = (char **) malloc((size+1)*sizeof(char *));
|
||||
for (i = 0; i < size; i++) {
|
||||
PyObject *o = PyList_GetItem($input, i);
|
||||
if (PyUnicode_Check(o)) {
|
||||
$1[i] = PyUnicode_AsUTF8(PyList_GetItem($input,i));
|
||||
} else {
|
||||
PyErr_Format(PyExc_TypeError, "list must contain strings. %d/%d element was not string.", i, size);
|
||||
free($1);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
$1[i] = 0;
|
||||
} else {
|
||||
PyErr_SetString(PyExc_TypeError, "not a list");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
/* This cleans up the char ** array we malloc-ed before */
|
||||
%typemap(freearg) char ** dset_in {
|
||||
free((char *) $1);
|
||||
}
|
||||
|
||||
/* Parse the header files to generate wrappers */
|
||||
%include "trexio_s.h"
|
||||
%include "trexio.h"
|
||||
|
@ -10,6 +10,7 @@ echo "" >> trexio.h
|
||||
|
||||
cat prefix_s_front.h > trexio_s.h
|
||||
cat prefix_fortran.f90 > trexio_f.f90
|
||||
cat prefix_python.py > trexio.py
|
||||
|
||||
# c front end
|
||||
cat populated/pop_*.c >> trexio.c
|
||||
@ -21,6 +22,10 @@ cat populated/pop_*.f90 >> trexio_f.f90
|
||||
cat helper_fortran.f90 >> trexio_f.f90
|
||||
cat populated/pop_*.fh_90 >> trexio_f.f90
|
||||
|
||||
# python front end
|
||||
cat basic_python.py >> trexio.py
|
||||
cat populated/pop_*.py >> trexio.py
|
||||
|
||||
# suffixes
|
||||
cat suffix_s_front.h >> trexio_s.h
|
||||
cat suffix_front.h >> trexio.h
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -64,9 +64,8 @@
|
||||
#+begin_src c :tangle struct_hdf5.h
|
||||
typedef struct trexio_hdf5_s {
|
||||
trexio_t parent ;
|
||||
hid_t file_id;
|
||||
hid_t $group$_group;
|
||||
const char* file_name;
|
||||
hid_t file_id;
|
||||
hid_t $group$_group;
|
||||
} trexio_hdf5_t;
|
||||
#+end_src
|
||||
|
||||
@ -537,15 +536,22 @@ trexio_hdf5_write_$group_dset$ (trexio_t* const file, const char** $group_dset$,
|
||||
|
||||
/* we are going to write variable-length strings */
|
||||
hid_t memtype = H5Tcopy (H5T_C_S1);
|
||||
if (memtype <= 0) return TREXIO_INVALID_ID;
|
||||
|
||||
status = H5Tset_size (memtype, H5T_VARIABLE);
|
||||
if (status < 0) return TREXIO_FAILURE;
|
||||
|
||||
if ( H5LTfind_dataset(f->$group$_group, $GROUP_DSET$_NAME) != 1 ) {
|
||||
|
||||
/* code to create dataset */
|
||||
hid_t filetype = H5Tcopy (H5T_FORTRAN_S1);
|
||||
if (filetype <= 0) return TREXIO_INVALID_ID;
|
||||
|
||||
status = H5Tset_size (filetype, H5T_VARIABLE);
|
||||
if (status < 0) return TREXIO_FAILURE;
|
||||
|
||||
hid_t dspace = H5Screate_simple( (int) rank, (const hsize_t*) dims, NULL);
|
||||
if (dspace <= 0) return TREXIO_INVALID_ID;
|
||||
|
||||
dset_id = H5Dcreate (f->$group$_group, $GROUP_DSET$_NAME, filetype, dspace,
|
||||
H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
|
||||
|
@ -456,8 +456,6 @@ trexio_text_read_$group$ (trexio_text_t* const file)
|
||||
}
|
||||
// END REPEAT GROUP_DSET_NUM
|
||||
|
||||
size_t tmp_len;
|
||||
|
||||
// START REPEAT GROUP_DSET_STR
|
||||
/* Allocate arrays */
|
||||
$group$->$group_dset$ = CALLOC(size_$group_dset$, $group_dset_dtype$);
|
||||
@ -485,7 +483,7 @@ trexio_text_read_$group$ (trexio_text_t* const file)
|
||||
,*/
|
||||
char* tmp_$group_dset$;
|
||||
if(size_$group_dset$ != 0) tmp_$group_dset$ = CALLOC(size_$group_dset$*32, char);
|
||||
tmp_len = 0;
|
||||
|
||||
for (uint64_t i=0 ; i<size_$group_dset$ ; ++i) {
|
||||
$group$->$group_dset$[i] = tmp_$group_dset$;
|
||||
/* conventional fcanf with "%s" only return the string before the first space character
|
||||
@ -501,8 +499,8 @@ trexio_text_read_$group$ (trexio_text_t* const file)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tmp_len = strlen($group$->$group_dset$[i]);
|
||||
tmp_$group_dset$ += tmp_len + 1;
|
||||
size_t tmp_$group_dset$_len = strlen($group$->$group_dset$[i]);
|
||||
tmp_$group_dset$ += tmp_$group_dset$_len + 1;
|
||||
}
|
||||
// END REPEAT GROUP_DSET_STR
|
||||
|
||||
@ -852,9 +850,8 @@ trexio_text_write_$group_dset$ (trexio_t* const file, const char** dset, const u
|
||||
char* tmp_str = CALLOC(dims[0]*32 + 1, char);
|
||||
if (tmp_str == NULL) return TREXIO_ALLOCATION_FAILED;
|
||||
|
||||
size_t tmp_len = 0;
|
||||
for (uint64_t i=0 ; i<dims[0] ; ++i) {
|
||||
tmp_len = strlen(dset[i]);
|
||||
size_t tmp_len = strlen(dset[i]);
|
||||
$group$->$group_dset$[i] = tmp_str;
|
||||
strncpy(tmp_str, dset[i], tmp_len);
|
||||
tmp_str += tmp_len + 1;
|
||||
|
165
tests/io_safe_dset_float_hdf5.c
Normal file
165
tests/io_safe_dset_float_hdf5.c
Normal file
@ -0,0 +1,165 @@
|
||||
#include "trexio.h"
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define TEST_BACKEND TREXIO_HDF5
|
||||
#define TREXIO_FILE "test_safe_dset_f.h5"
|
||||
#define RM_COMMAND "rm -rf " TREXIO_FILE
|
||||
|
||||
static int test_write_dset (const char* file_name, const back_end_t backend) {
|
||||
|
||||
/* Try to write a dataset with floating point values into the TREXIO file using safe API */
|
||||
|
||||
trexio_t* file = NULL;
|
||||
trexio_exit_code rc;
|
||||
|
||||
// parameters to be written
|
||||
int num = 12;
|
||||
double coord[36] = {
|
||||
0.00000000 , 1.39250319 , 0.00000000 ,
|
||||
-1.20594314 , 0.69625160 , 0.00000000 ,
|
||||
-1.20594314 , -0.69625160 , 0.00000000 ,
|
||||
0.00000000 , -1.39250319 , 0.00000000 ,
|
||||
1.20594314 , -0.69625160 , 0.00000000 ,
|
||||
1.20594314 , 0.69625160 , 0.00000000 ,
|
||||
-2.14171677 , 1.23652075 , 0.00000000 ,
|
||||
-2.14171677 , -1.23652075 , 0.00000000 ,
|
||||
0.00000000 , -2.47304151 , 0.00000000 ,
|
||||
2.14171677 , -1.23652075 , 0.00000000 ,
|
||||
2.14171677 , 1.23652075 , 0.00000000 ,
|
||||
0.00000000 , 2.47304151 , 0.00000000 ,
|
||||
};
|
||||
|
||||
/*================= START OF TEST ==================*/
|
||||
|
||||
// open file in 'write' mode
|
||||
file = trexio_open(file_name, 'w', backend);
|
||||
assert (file != NULL);
|
||||
|
||||
// write numerical attribute in an empty file
|
||||
rc = trexio_write_nucleus_num(file, num);
|
||||
assert (rc == TREXIO_SUCCESS);
|
||||
|
||||
/* write numerical dataset with an unsafe dimension
|
||||
* this should return TREXIO_UNSAFE_ARRAY_DIM indicating
|
||||
* that access beyong allocated memory is likely to occur */
|
||||
uint64_t dim_unsafe = num * 12;
|
||||
rc = trexio_write_safe_nucleus_coord(file, coord, dim_unsafe);
|
||||
assert (rc == TREXIO_UNSAFE_ARRAY_DIM);
|
||||
|
||||
/* write numerical dataset with a safe dimension
|
||||
* this should return TREXIO_SUCCESS */
|
||||
uint64_t dim_safe = num * 3;
|
||||
rc = trexio_write_safe_nucleus_coord(file, coord, dim_safe);
|
||||
assert (rc == TREXIO_SUCCESS);
|
||||
|
||||
// close current session
|
||||
rc = trexio_close(file);
|
||||
assert (rc == TREXIO_SUCCESS);
|
||||
|
||||
/*================= END OF TEST ==================*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int test_has_dset (const char* file_name, const back_end_t backend) {
|
||||
|
||||
/* Try to check the existence of a dataset in the TREXIO file */
|
||||
|
||||
trexio_t* file = NULL;
|
||||
trexio_exit_code rc;
|
||||
|
||||
/*================= START OF TEST ==================*/
|
||||
|
||||
// open file in 'read' mode
|
||||
file = trexio_open(file_name, 'r', backend);
|
||||
assert (file != NULL);
|
||||
|
||||
// check that the previously written dataset exists
|
||||
rc = trexio_has_nucleus_coord(file);
|
||||
assert (rc == TREXIO_SUCCESS);
|
||||
|
||||
// close current session
|
||||
rc = trexio_close(file);
|
||||
assert (rc == TREXIO_SUCCESS);
|
||||
|
||||
/*================= END OF TEST ==================*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int test_read_dset (const char* file_name, const back_end_t backend) {
|
||||
|
||||
/* Try to read a dataset with floating point values from the TREXIO file using safe API */
|
||||
|
||||
trexio_t* file = NULL;
|
||||
trexio_exit_code rc;
|
||||
|
||||
// parameters to be read
|
||||
int num;
|
||||
double* coord;
|
||||
|
||||
/*================= START OF TEST ==================*/
|
||||
|
||||
// open file in 'read' mode
|
||||
file = trexio_open(file_name, 'r', backend);
|
||||
assert (file != NULL);
|
||||
|
||||
// read numerical attribute from the file
|
||||
rc = trexio_read_nucleus_num(file, &num);
|
||||
assert (rc == TREXIO_SUCCESS);
|
||||
assert (num == 12);
|
||||
|
||||
// read numerical (floating point) dataset from the file
|
||||
coord = (double*) calloc(3*num, sizeof(double));
|
||||
|
||||
/* write numerical dataset with an unsafe dimension
|
||||
* this should return TREXIO_UNSAFE_ARRAY_DIM indicating
|
||||
* that access beyong allocated memory is likely to occur */
|
||||
uint64_t dim_unsafe = num * 12;
|
||||
rc = trexio_read_safe_nucleus_coord(file, coord, dim_unsafe);
|
||||
assert (rc == TREXIO_UNSAFE_ARRAY_DIM);
|
||||
|
||||
/* write numerical dataset with a safe dimension
|
||||
* this should return TREXIO_SUCCESS */
|
||||
uint64_t dim_safe = num * 3;
|
||||
rc = trexio_read_safe_nucleus_coord(file, coord, dim_safe);
|
||||
assert (rc == TREXIO_SUCCESS);
|
||||
|
||||
double x = coord[30] - 2.14171677;
|
||||
assert( x*x < 1.e-14 );
|
||||
free(coord);
|
||||
|
||||
// close current session
|
||||
rc = trexio_close(file);
|
||||
assert (rc == TREXIO_SUCCESS);
|
||||
|
||||
/*================= END OF TEST ==================*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main(void) {
|
||||
|
||||
/*============== Test launcher ================*/
|
||||
|
||||
int rc;
|
||||
rc = system(RM_COMMAND);
|
||||
assert (rc == 0);
|
||||
|
||||
test_write_dset (TREXIO_FILE, TEST_BACKEND);
|
||||
test_has_dset (TREXIO_FILE, TEST_BACKEND);
|
||||
test_read_dset (TREXIO_FILE, TEST_BACKEND);
|
||||
|
||||
rc = system(RM_COMMAND);
|
||||
assert (rc == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
165
tests/io_safe_dset_float_text.c
Normal file
165
tests/io_safe_dset_float_text.c
Normal file
@ -0,0 +1,165 @@
|
||||
#include "trexio.h"
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define TEST_BACKEND TREXIO_TEXT
|
||||
#define TREXIO_FILE "test_safe_dset_f.dir"
|
||||
#define RM_COMMAND "rm -rf " TREXIO_FILE
|
||||
|
||||
static int test_write_dset (const char* file_name, const back_end_t backend) {
|
||||
|
||||
/* Try to write a dataset with floating point values into the TREXIO file using safe API */
|
||||
|
||||
trexio_t* file = NULL;
|
||||
trexio_exit_code rc;
|
||||
|
||||
// parameters to be written
|
||||
int num = 12;
|
||||
double coord[36] = {
|
||||
0.00000000 , 1.39250319 , 0.00000000 ,
|
||||
-1.20594314 , 0.69625160 , 0.00000000 ,
|
||||
-1.20594314 , -0.69625160 , 0.00000000 ,
|
||||
0.00000000 , -1.39250319 , 0.00000000 ,
|
||||
1.20594314 , -0.69625160 , 0.00000000 ,
|
||||
1.20594314 , 0.69625160 , 0.00000000 ,
|
||||
-2.14171677 , 1.23652075 , 0.00000000 ,
|
||||
-2.14171677 , -1.23652075 , 0.00000000 ,
|
||||
0.00000000 , -2.47304151 , 0.00000000 ,
|
||||
2.14171677 , -1.23652075 , 0.00000000 ,
|
||||
2.14171677 , 1.23652075 , 0.00000000 ,
|
||||
0.00000000 , 2.47304151 , 0.00000000 ,
|
||||
};
|
||||
|
||||
/*================= START OF TEST ==================*/
|
||||
|
||||
// open file in 'write' mode
|
||||
file = trexio_open(file_name, 'w', backend);
|
||||
assert (file != NULL);
|
||||
|
||||
// write numerical attribute in an empty file
|
||||
rc = trexio_write_nucleus_num(file, num);
|
||||
assert (rc == TREXIO_SUCCESS);
|
||||
|
||||
/* write numerical dataset with an unsafe dimension
|
||||
* this should return TREXIO_UNSAFE_ARRAY_DIM indicating
|
||||
* that access beyong allocated memory is likely to occur */
|
||||
uint64_t dim_unsafe = num * 12;
|
||||
rc = trexio_write_safe_nucleus_coord(file, coord, dim_unsafe);
|
||||
assert (rc == TREXIO_UNSAFE_ARRAY_DIM);
|
||||
|
||||
/* write numerical dataset with a safe dimension
|
||||
* this should return TREXIO_SUCCESS */
|
||||
uint64_t dim_safe = num * 3;
|
||||
rc = trexio_write_safe_nucleus_coord(file, coord, dim_safe);
|
||||
assert (rc == TREXIO_SUCCESS);
|
||||
|
||||
// close current session
|
||||
rc = trexio_close(file);
|
||||
assert (rc == TREXIO_SUCCESS);
|
||||
|
||||
/*================= END OF TEST ==================*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int test_has_dset (const char* file_name, const back_end_t backend) {
|
||||
|
||||
/* Try to check the existence of a dataset in the TREXIO file */
|
||||
|
||||
trexio_t* file = NULL;
|
||||
trexio_exit_code rc;
|
||||
|
||||
/*================= START OF TEST ==================*/
|
||||
|
||||
// open file in 'read' mode
|
||||
file = trexio_open(file_name, 'r', backend);
|
||||
assert (file != NULL);
|
||||
|
||||
// check that the previously written dataset exists
|
||||
rc = trexio_has_nucleus_coord(file);
|
||||
assert (rc == TREXIO_SUCCESS);
|
||||
|
||||
// close current session
|
||||
rc = trexio_close(file);
|
||||
assert (rc == TREXIO_SUCCESS);
|
||||
|
||||
/*================= END OF TEST ==================*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int test_read_dset (const char* file_name, const back_end_t backend) {
|
||||
|
||||
/* Try to read a dataset with floating point values from the TREXIO file using safe API */
|
||||
|
||||
trexio_t* file = NULL;
|
||||
trexio_exit_code rc;
|
||||
|
||||
// parameters to be read
|
||||
int num;
|
||||
double* coord;
|
||||
|
||||
/*================= START OF TEST ==================*/
|
||||
|
||||
// open file in 'read' mode
|
||||
file = trexio_open(file_name, 'r', backend);
|
||||
assert (file != NULL);
|
||||
|
||||
// read numerical attribute from the file
|
||||
rc = trexio_read_nucleus_num(file, &num);
|
||||
assert (rc == TREXIO_SUCCESS);
|
||||
assert (num == 12);
|
||||
|
||||
// read numerical (floating point) dataset from the file
|
||||
coord = (double*) calloc(3*num, sizeof(double));
|
||||
|
||||
/* write numerical dataset with an unsafe dimension
|
||||
* this should return TREXIO_UNSAFE_ARRAY_DIM indicating
|
||||
* that access beyong allocated memory is likely to occur */
|
||||
uint64_t dim_unsafe = num * 12;
|
||||
rc = trexio_read_safe_nucleus_coord(file, coord, dim_unsafe);
|
||||
assert (rc == TREXIO_UNSAFE_ARRAY_DIM);
|
||||
|
||||
/* write numerical dataset with a safe dimension
|
||||
* this should return TREXIO_SUCCESS */
|
||||
uint64_t dim_safe = num * 3;
|
||||
rc = trexio_read_safe_nucleus_coord(file, coord, dim_safe);
|
||||
assert (rc == TREXIO_SUCCESS);
|
||||
|
||||
double x = coord[30] - 2.14171677;
|
||||
assert( x*x < 1.e-14 );
|
||||
free(coord);
|
||||
|
||||
// close current session
|
||||
rc = trexio_close(file);
|
||||
assert (rc == TREXIO_SUCCESS);
|
||||
|
||||
/*================= END OF TEST ==================*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main(void) {
|
||||
|
||||
/*============== Test launcher ================*/
|
||||
|
||||
int rc;
|
||||
rc = system(RM_COMMAND);
|
||||
assert (rc == 0);
|
||||
|
||||
test_write_dset (TREXIO_FILE, TEST_BACKEND);
|
||||
test_has_dset (TREXIO_FILE, TEST_BACKEND);
|
||||
test_read_dset (TREXIO_FILE, TEST_BACKEND);
|
||||
|
||||
rc = system(RM_COMMAND);
|
||||
assert (rc == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
32
tools/check_numpy_i.sh
Executable file
32
tools/check_numpy_i.sh
Executable file
@ -0,0 +1,32 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Check that script is executed from tools directory
|
||||
if [[ $(basename $PWD) != "tools" ]] ; then
|
||||
echo "This script should run in the tools directory"
|
||||
exit -1
|
||||
fi
|
||||
|
||||
TREXIO_ROOT=$(dirname "${PWD}../")
|
||||
|
||||
# First define readonly global variables.
|
||||
readonly SRC=${TREXIO_ROOT}/src
|
||||
readonly TOOLS=${TREXIO_ROOT}/tools
|
||||
|
||||
# We want the script to crash on the 1st error:
|
||||
set -e
|
||||
|
||||
NUMPY_SRC=${SRC}/numpy.i
|
||||
NUMPY_LATEST=${TOOLS}/numpy.i
|
||||
|
||||
# Download the latest numpy.i file from NumPy GitHub
|
||||
wget https://raw.githubusercontent.com/numpy/numpy/main/tools/swig/numpy.i -O ${NUMPY_LATEST}
|
||||
|
||||
# Execute diff to check if the numpy.i file in the src/ directory is updated
|
||||
if ! diff -q ${NUMPY_LATEST} ${NUMPY_SRC} &>/dev/null; then
|
||||
>&2 echo "numpy.i SWIG interface file in the source tree is outdated; replacing ..."
|
||||
mv ${NUMPY_LATEST} ${NUMPY_SRC}
|
||||
else
|
||||
>&2 echo "numpy.i SWIG interface file in the source tree is up-to-date."
|
||||
rm ${NUMPY_LATEST}
|
||||
fi
|
||||
|
@ -100,7 +100,7 @@ def recursive_populate_file(fname: str, paths: dict, detailed_source: dict) -> N
|
||||
fname_new = join('populated',f'pop_{fname}')
|
||||
templ_path = get_template_path(fname, paths)
|
||||
|
||||
triggers = ['group_dset_dtype', 'group_dset_h5_dtype', 'default_prec', 'is_index',
|
||||
triggers = ['group_dset_dtype', 'group_dset_py_dtype', 'group_dset_h5_dtype', 'default_prec', 'is_index',
|
||||
'group_dset_f_dtype_default', 'group_dset_f_dtype_double', 'group_dset_f_dtype_single',
|
||||
'group_dset_dtype_default', 'group_dset_dtype_double', 'group_dset_dtype_single',
|
||||
'group_dset_rank', 'group_dset_dim_list', 'group_dset_f_dims',
|
||||
@ -111,25 +111,27 @@ def recursive_populate_file(fname: str, paths: dict, detailed_source: dict) -> N
|
||||
with open(join(templ_path,fname_new), 'a') as f_out :
|
||||
num_written = []
|
||||
for line in f_in :
|
||||
# special case to add error handling for read/write of dimensioning variables
|
||||
if '$group_dset_dim$' in line:
|
||||
rc_line = 'if (rc != TREXIO_SUCCESS) return rc;\n'
|
||||
indentlevel = len(line) - len(line.lstrip())
|
||||
for dim in detailed_source[item]['dims']:
|
||||
if not dim.isdigit() and not dim in num_written:
|
||||
num_written.append(dim)
|
||||
templine = line.replace('$group_dset_dim$', dim)
|
||||
if '_read' in templine and (not 'fortran' in fname):
|
||||
line_toadd = indentlevel*" " + rc_line
|
||||
templine += line_toadd
|
||||
# special case to add error handling for read/write of dimensioning variables
|
||||
if '$group_dset_dim$' in line:
|
||||
rc_line = 'if (rc != TREXIO_SUCCESS) return rc;\n'
|
||||
indentlevel = len(line) - len(line.lstrip())
|
||||
for dim in detailed_source[item]['dims']:
|
||||
if not dim.isdigit() and not dim in num_written:
|
||||
num_written.append(dim)
|
||||
templine = line.replace('$group_dset_dim$', dim)
|
||||
if '_read' in templine and (not 'fortran' in fname):
|
||||
line_toadd = indentlevel*" " + rc_line
|
||||
templine += line_toadd
|
||||
|
||||
f_out.write(templine)
|
||||
num_written = []
|
||||
continue
|
||||
# general case of recursive replacement of inline triggers
|
||||
else:
|
||||
populated_line = recursive_replace_line(line, triggers, detailed_source[item])
|
||||
f_out.write(populated_line)
|
||||
f_out.write(templine)
|
||||
num_written = []
|
||||
continue
|
||||
# general case of recursive replacement of inline triggers
|
||||
else:
|
||||
populated_line = recursive_replace_line(line, triggers, detailed_source[item])
|
||||
f_out.write(populated_line)
|
||||
|
||||
f_out.write("\n")
|
||||
|
||||
|
||||
def recursive_replace_line (input_line: str, triggers: list, source: dict) -> str:
|
||||
@ -215,6 +217,8 @@ def iterative_populate_file (filename: str, paths: dict, groups: dict, datasets:
|
||||
else:
|
||||
f_out.write(line)
|
||||
|
||||
f_out.write("\n")
|
||||
|
||||
|
||||
def iterative_replace_line (input_line: str, case: str, source: dict, add_line: str) -> str:
|
||||
"""
|
||||
@ -403,6 +407,8 @@ def special_populate_text_group(fname: str, paths: dict, group_dict: dict, detai
|
||||
else:
|
||||
loop_body += line
|
||||
|
||||
f_out.write("\n")
|
||||
|
||||
|
||||
def get_template_path (filename: str, path_dict: dict) -> str:
|
||||
"""
|
||||
@ -542,6 +548,7 @@ def split_dset_dict_detailed (datasets: dict) -> tuple:
|
||||
default_prec = '64'
|
||||
group_dset_std_dtype_out = '24.16e'
|
||||
group_dset_std_dtype_in = 'lf'
|
||||
group_dset_py_dtype = 'float'
|
||||
elif v[0] in ['int', 'index']:
|
||||
datatype = 'int64_t'
|
||||
group_dset_h5_dtype = 'native_int64'
|
||||
@ -554,6 +561,7 @@ def split_dset_dict_detailed (datasets: dict) -> tuple:
|
||||
default_prec = '32'
|
||||
group_dset_std_dtype_out = '" PRId64 "'
|
||||
group_dset_std_dtype_in = '" SCNd64 "'
|
||||
group_dset_py_dtype = 'int'
|
||||
elif v[0] == 'str':
|
||||
datatype = 'char*'
|
||||
group_dset_h5_dtype = ''
|
||||
@ -566,6 +574,7 @@ def split_dset_dict_detailed (datasets: dict) -> tuple:
|
||||
default_prec = ''
|
||||
group_dset_std_dtype_out = 's'
|
||||
group_dset_std_dtype_in = 's'
|
||||
group_dset_py_dtype = 'str'
|
||||
|
||||
# add the dset name for templates
|
||||
tmp_dict['group_dset'] = k
|
||||
@ -587,6 +596,7 @@ def split_dset_dict_detailed (datasets: dict) -> tuple:
|
||||
tmp_dict['default_prec'] = default_prec
|
||||
tmp_dict['group_dset_std_dtype_in'] = group_dset_std_dtype_in
|
||||
tmp_dict['group_dset_std_dtype_out'] = group_dset_std_dtype_out
|
||||
tmp_dict['group_dset_py_dtype'] = group_dset_py_dtype
|
||||
# add the rank
|
||||
tmp_dict['rank'] = len(v[1])
|
||||
tmp_dict['group_dset_rank'] = str(tmp_dict['rank'])
|
||||
|
34
tools/prepare_python.sh
Executable file
34
tools/prepare_python.sh
Executable file
@ -0,0 +1,34 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Check that script is executed from tools directory
|
||||
if [[ $(basename $PWD) != "tools" ]] ; then
|
||||
echo "This script should run in the tools directory"
|
||||
exit -1
|
||||
fi
|
||||
|
||||
TREXIO_ROOT=$(dirname "${PWD}../")
|
||||
|
||||
# First define readonly global variables.
|
||||
readonly SRC=${TREXIO_ROOT}/src
|
||||
readonly INCLUDIR=${TREXIO_ROOT}/include
|
||||
readonly TOOLS=${TREXIO_ROOT}/tools
|
||||
readonly PYDIR=${TREXIO_ROOT}/python
|
||||
readonly PYTREXIODIR=${PYDIR}/pytrexio
|
||||
|
||||
# We want the script to crash on the 1st error:
|
||||
set -e
|
||||
|
||||
# Create src and trexio directories in the python folder if not yet done
|
||||
mkdir -p ${PYDIR}/src
|
||||
mkdir -p ${PYTREXIODIR}
|
||||
|
||||
# Copy all the source code and header files in the corresponding python directory
|
||||
cp ${SRC}/pytrexio.py ${PYTREXIODIR}/pytrexio.py
|
||||
cp ${SRC}/trexio.py ${PYDIR}/trexio.py
|
||||
cp ${SRC}/*.c ${PYDIR}/src
|
||||
cp ${SRC}/*.h ${PYDIR}/src
|
||||
cp ${INCLUDIR}/trexio.h ${PYDIR}/src
|
||||
|
||||
# Copy additional info
|
||||
cp ${TREXIO_ROOT}/AUTHORS ${TREXIO_ROOT}/LICENSE ${PYDIR}
|
||||
|
Loading…
Reference in New Issue
Block a user