Merge halvor_xanes to master
This commit is contained in:
commit
b242602eba
27 changed files with 1235 additions and 771 deletions
35
.github/workflows/automated-testing.yml
vendored
Normal file
35
.github/workflows/automated-testing.yml
vendored
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
name: Automated testing
|
||||||
|
|
||||||
|
on: [push]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-linux:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
max-parallel: 5
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Set up Python 3.10
|
||||||
|
uses: actions/setup-python@v3
|
||||||
|
with:
|
||||||
|
python-version: 3.10.4
|
||||||
|
- name: Add conda to system path
|
||||||
|
run: |
|
||||||
|
# $CONDA is an environment variable pointing to the root of the miniconda directory
|
||||||
|
echo $CONDA/bin >> $GITHUB_PATH
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
conda env update --file environment.yml --name base
|
||||||
|
pip install .
|
||||||
|
- name: Lint with flake8
|
||||||
|
run: |
|
||||||
|
conda install flake8
|
||||||
|
# stop the build if there are Python syntax errors or undefined names
|
||||||
|
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
|
||||||
|
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
|
||||||
|
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
|
||||||
|
- name: Test with pytest
|
||||||
|
run: |
|
||||||
|
conda install pytest
|
||||||
|
pytest
|
||||||
|
|
@ -1,141 +0,0 @@
|
||||||
# This file may be used to create an environment using:
|
|
||||||
# $ conda create --name <env> --file <this file>
|
|
||||||
# platform: win-64
|
|
||||||
argon2-cffi=21.3.0=pyhd3eb1b0_0
|
|
||||||
argon2-cffi-bindings=21.2.0=py39h2bbff1b_0
|
|
||||||
attrs=21.4.0=pyhd3eb1b0_0
|
|
||||||
backcall=0.2.0=pyhd3eb1b0_0
|
|
||||||
beamtime=0.1=pypi_0
|
|
||||||
blas=1.0=mkl
|
|
||||||
bleach=4.1.0=pyhd3eb1b0_0
|
|
||||||
bottleneck=1.3.2=py39h7cc1a96_1
|
|
||||||
ca-certificates=2022.2.1=haa95532_0
|
|
||||||
cached-property=1.5.2=hd8ed1ab_1
|
|
||||||
cached_property=1.5.2=pyha770c72_1
|
|
||||||
certifi=2021.10.8=py39haa95532_2
|
|
||||||
cffi=1.15.0=py39h2bbff1b_1
|
|
||||||
colorama=0.4.4=pyhd3eb1b0_0
|
|
||||||
cycler=0.10.0=py_2
|
|
||||||
debugpy=1.4.1=py39hd77b12b_0
|
|
||||||
decorator=5.1.0=pyhd3eb1b0_0
|
|
||||||
defusedxml=0.7.1=pyhd3eb1b0_0
|
|
||||||
entrypoints=0.3=py39haa95532_0
|
|
||||||
fabio=0.12.0=py39h5d4886f_0
|
|
||||||
freetype=2.10.4=h546665d_1
|
|
||||||
glymur=0.9.4=pyhd8ed1ab_0
|
|
||||||
h5py=3.2.1=nompi_py39hf27771d_100
|
|
||||||
hdf5=1.10.6=nompi_h5268f04_1114
|
|
||||||
hdf5plugin=3.1.1=py39h71586dd_0
|
|
||||||
icc_rt=2019.0.0=h0cc432a_1
|
|
||||||
icu=68.1=h6c2663c_0
|
|
||||||
importlib-metadata=4.8.2=py39haa95532_0
|
|
||||||
importlib_metadata=4.8.2=hd3eb1b0_0
|
|
||||||
intel-openmp=2021.3.0=haa95532_3372
|
|
||||||
ipykernel=6.4.1=py39haa95532_1
|
|
||||||
ipython=7.27.0=py39hd4e2768_0
|
|
||||||
ipython_genutils=0.2.0=pyhd3eb1b0_1
|
|
||||||
ipywidgets=7.6.5=pyhd3eb1b0_1
|
|
||||||
jbig=2.1=h8d14728_2003
|
|
||||||
jedi=0.18.0=py39haa95532_1
|
|
||||||
jinja2=3.0.2=pyhd3eb1b0_0
|
|
||||||
jpeg=9d=h2bbff1b_0
|
|
||||||
jsonschema=3.2.0=pyhd3eb1b0_2
|
|
||||||
jupyter_client=7.0.1=pyhd3eb1b0_0
|
|
||||||
jupyter_core=4.8.1=py39haa95532_0
|
|
||||||
jupyterlab_pygments=0.1.2=py_0
|
|
||||||
jupyterlab_widgets=1.0.0=pyhd3eb1b0_1
|
|
||||||
kiwisolver=1.3.2=py39h2e07f2f_0
|
|
||||||
krb5=1.19.2=hbae68bd_2
|
|
||||||
lerc=3.0=h0e60522_0
|
|
||||||
libclang=11.1.0=default_h5c34c98_1
|
|
||||||
libcurl=7.79.1=h789b8ee_1
|
|
||||||
libdeflate=1.8=h2bbff1b_5
|
|
||||||
libiconv=1.16=he774522_0
|
|
||||||
libpng=1.6.37=h1d00b33_2
|
|
||||||
libssh2=1.10.0=h680486a_2
|
|
||||||
libtiff=4.3.0=hd413186_2
|
|
||||||
libwebp=1.2.0=h2bbff1b_0
|
|
||||||
libxml2=2.9.12=h0ad7f3c_0
|
|
||||||
libxslt=1.1.34=he774522_0
|
|
||||||
libzlib=1.2.11=h8ffe710_1013
|
|
||||||
lxml=4.6.3=py39h4fd7cdf_0
|
|
||||||
lz4-c=1.9.3=h8ffe710_1
|
|
||||||
mako=1.1.5=pyhd8ed1ab_0
|
|
||||||
markupsafe=2.0.1=py39h2bbff1b_0
|
|
||||||
matplotlib=3.4.3=py39hcbf5309_1
|
|
||||||
matplotlib-base=3.4.3=py39h581301d_1
|
|
||||||
matplotlib-inline=0.1.2=pyhd3eb1b0_2
|
|
||||||
mistune=0.8.4=py39h2bbff1b_1000
|
|
||||||
mkl=2021.3.0=haa95532_524
|
|
||||||
mkl-service=2.4.0=py39h2bbff1b_0
|
|
||||||
mkl_fft=1.3.1=py39h277e83a_0
|
|
||||||
mkl_random=1.2.2=py39hf11a4ad_0
|
|
||||||
nbclient=0.5.11=pyhd3eb1b0_0
|
|
||||||
nbconvert=6.1.0=py39haa95532_0
|
|
||||||
nbformat=5.1.3=pyhd3eb1b0_0
|
|
||||||
nest-asyncio=1.5.1=pyhd3eb1b0_0
|
|
||||||
notebook=6.4.8=py39haa95532_0
|
|
||||||
numexpr=2.7.3=py39hb80d3ca_1
|
|
||||||
numpy=1.21.2=py39hfca59bb_0
|
|
||||||
numpy-base=1.21.2=py39h0829f74_0
|
|
||||||
olefile=0.46=pyh9f0ad1d_1
|
|
||||||
openjpeg=2.4.0=hb211442_1
|
|
||||||
openssl=1.1.1m=h2bbff1b_0
|
|
||||||
packaging=21.3=pyhd3eb1b0_0
|
|
||||||
pandas=1.3.3=py39h6214cd6_0
|
|
||||||
pandocfilters=1.5.0=pyhd3eb1b0_0
|
|
||||||
parso=0.8.2=pyhd3eb1b0_0
|
|
||||||
pickleshare=0.7.5=pyhd3eb1b0_1003
|
|
||||||
pillow=8.4.0=py39hd45dc43_0
|
|
||||||
pip=21.2.4=py39haa95532_0
|
|
||||||
prometheus_client=0.13.1=pyhd3eb1b0_0
|
|
||||||
prompt-toolkit=3.0.20=pyhd3eb1b0_0
|
|
||||||
pycparser=2.21=pyhd3eb1b0_0
|
|
||||||
pyfai=0.20.0=hd8ed1ab_0
|
|
||||||
pyfai-base=0.20.0=py39h2e25243_0
|
|
||||||
pygments=2.10.0=pyhd3eb1b0_0
|
|
||||||
pyparsing=2.4.7=pyhd3eb1b0_0
|
|
||||||
pyqt=5.12.3=py39hcbf5309_7
|
|
||||||
pyqt-impl=5.12.3=py39h415ef7b_7
|
|
||||||
pyqt5-sip=4.19.18=py39h415ef7b_7
|
|
||||||
pyqtchart=5.12=py39h415ef7b_7
|
|
||||||
pyqtwebengine=5.12.1=py39h415ef7b_7
|
|
||||||
pyreadline=2.1=py39hcbf5309_1004
|
|
||||||
pyrsistent=0.18.0=py39h196d8e1_0
|
|
||||||
python=3.9.7=h6244533_1
|
|
||||||
python-dateutil=2.8.2=pyhd3eb1b0_0
|
|
||||||
python_abi=3.9=2_cp39
|
|
||||||
pytz=2021.3=pyhd3eb1b0_0
|
|
||||||
pywin32=228=py39hbaba5e8_1
|
|
||||||
pywinpty=2.0.2=py39h5da7b33_0
|
|
||||||
pyzmq=22.2.1=py39hd77b12b_1
|
|
||||||
qt=5.12.9=h5909a2a_4
|
|
||||||
qtconsole=5.1.1=pyhd3eb1b0_0
|
|
||||||
qtpy=1.11.2=pyhd8ed1ab_0
|
|
||||||
scipy=1.7.1=py39hbe87c03_2
|
|
||||||
send2trash=1.8.0=pyhd3eb1b0_1
|
|
||||||
setuptools=58.0.4=py39haa95532_0
|
|
||||||
silx=0.15.2=hd8ed1ab_0
|
|
||||||
silx-base=0.15.2=py39h2e25243_0
|
|
||||||
six=1.16.0=pyhd3eb1b0_0
|
|
||||||
sqlite=3.36.0=h2bbff1b_0
|
|
||||||
terminado=0.13.1=py39haa95532_0
|
|
||||||
testpath=0.5.0=pyhd3eb1b0_0
|
|
||||||
tk=8.6.11=h8ffe710_1
|
|
||||||
tornado=6.1=py39h2bbff1b_0
|
|
||||||
traitlets=5.1.0=pyhd3eb1b0_0
|
|
||||||
typing-extensions=3.10.0.2=hd3eb1b0_0
|
|
||||||
typing_extensions=3.10.0.2=pyh06a4308_0
|
|
||||||
tzdata=2021a=h5d7bf9c_0
|
|
||||||
vc=14.2=h21ff451_1
|
|
||||||
vs2015_runtime=14.27.29016=h5e58377_2
|
|
||||||
wcwidth=0.2.5=pyhd3eb1b0_0
|
|
||||||
webencodings=0.5.1=py39haa95532_1
|
|
||||||
wheel=0.37.0=pyhd3eb1b0_1
|
|
||||||
widgetsnbextension=3.5.2=py39haa95532_0
|
|
||||||
wincertstore=0.2=py39haa95532_2
|
|
||||||
winpty=0.4.3=4
|
|
||||||
xz=5.2.5=h62dcd97_1
|
|
||||||
zipp=3.7.0=pyhd3eb1b0_0
|
|
||||||
zlib=1.2.11=h8ffe710_1013
|
|
||||||
zstd=1.5.0=h6255e5f_0
|
|
||||||
|
|
@ -1,108 +0,0 @@
|
||||||
# This file may be used to create an environment using:
|
|
||||||
# $ conda create --name <env> --file <this file>
|
|
||||||
# platform: win-64
|
|
||||||
@EXPLICIT
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/blas-1.0-mkl.conda
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/ca-certificates-2021.10.8-h5b45459_0.tar.bz2
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/icc_rt-2019.0.0-h0cc432a_1.conda
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/intel-openmp-2021.3.0-haa95532_3372.conda
|
|
||||||
https://repo.anaconda.com/pkgs/main/noarch/tzdata-2021a-h5d7bf9c_0.conda
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/vs2015_runtime-14.27.29016-h5e58377_2.conda
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/mkl-2021.3.0-haa95532_524.conda
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/vc-14.2-h21ff451_1.conda
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/icu-68.1-h6c2663c_0.conda
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/jbig-2.1-h8d14728_2003.tar.bz2
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/jpeg-9d-h2bbff1b_0.conda
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/lerc-3.0-h0e60522_0.tar.bz2
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/libclang-11.1.0-default_h5c34c98_1.tar.bz2
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/libdeflate-1.8-h2bbff1b_5.conda
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/libiconv-1.16-he774522_0.tar.bz2
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/libwebp-1.2.0-h2bbff1b_0.conda
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/libzlib-1.2.11-h8ffe710_1013.tar.bz2
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/lz4-c-1.9.3-h8ffe710_1.tar.bz2
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/openssl-1.1.1l-h8ffe710_0.tar.bz2
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/sqlite-3.36.0-h2bbff1b_0.conda
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/tk-8.6.11-h8ffe710_1.tar.bz2
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/xz-5.2.5-h62dcd97_1.tar.bz2
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/krb5-1.19.2-hbae68bd_2.tar.bz2
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/python-3.9.7-h6244533_1.conda
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/zlib-1.2.11-h8ffe710_1013.tar.bz2
|
|
||||||
https://repo.anaconda.com/pkgs/main/noarch/backcall-0.2.0-pyhd3eb1b0_0.tar.bz2
|
|
||||||
https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/certifi-2021.10.8-py39haa95532_0.conda
|
|
||||||
https://repo.anaconda.com/pkgs/main/noarch/colorama-0.4.4-pyhd3eb1b0_0.conda
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/debugpy-1.4.1-py39hd77b12b_0.conda
|
|
||||||
https://repo.anaconda.com/pkgs/main/noarch/decorator-5.1.0-pyhd3eb1b0_0.conda
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/entrypoints-0.3-py39haa95532_0.conda
|
|
||||||
https://repo.anaconda.com/pkgs/main/noarch/ipython_genutils-0.2.0-pyhd3eb1b0_1.conda
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/libpng-1.6.37-h1d00b33_2.tar.bz2
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/libssh2-1.10.0-h680486a_2.tar.bz2
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/libxml2-2.9.12-h0ad7f3c_0.conda
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/markupsafe-2.0.1-py39h2bbff1b_0.conda
|
|
||||||
https://repo.anaconda.com/pkgs/main/noarch/nest-asyncio-1.5.1-pyhd3eb1b0_0.conda
|
|
||||||
https://conda.anaconda.org/conda-forge/noarch/olefile-0.46-pyh9f0ad1d_1.tar.bz2
|
|
||||||
https://repo.anaconda.com/pkgs/main/noarch/parso-0.8.2-pyhd3eb1b0_0.conda
|
|
||||||
https://repo.anaconda.com/pkgs/main/noarch/pickleshare-0.7.5-pyhd3eb1b0_1003.conda
|
|
||||||
https://repo.anaconda.com/pkgs/main/noarch/pyparsing-2.4.7-pyhd3eb1b0_0.tar.bz2
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/python_abi-3.9-2_cp39.tar.bz2
|
|
||||||
https://repo.anaconda.com/pkgs/main/noarch/pytz-2021.3-pyhd3eb1b0_0.conda
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/pywin32-228-py39hbaba5e8_1.conda
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/pyzmq-22.2.1-py39hd77b12b_1.conda
|
|
||||||
https://conda.anaconda.org/conda-forge/noarch/qtpy-1.11.2-pyhd8ed1ab_0.tar.bz2
|
|
||||||
https://repo.anaconda.com/pkgs/main/noarch/six-1.16.0-pyhd3eb1b0_0.conda
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/tornado-6.1-py39h2bbff1b_0.conda
|
|
||||||
https://repo.anaconda.com/pkgs/main/noarch/traitlets-5.1.0-pyhd3eb1b0_0.conda
|
|
||||||
https://repo.anaconda.com/pkgs/main/noarch/wcwidth-0.2.5-pyhd3eb1b0_0.conda
|
|
||||||
https://repo.anaconda.com/pkgs/main/noarch/wheel-0.37.0-pyhd3eb1b0_1.conda
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/wincertstore-0.2-py39haa95532_2.conda
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.0-h6255e5f_0.tar.bz2
|
|
||||||
https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2
|
|
||||||
https://conda.anaconda.org/conda-forge/noarch/cycler-0.10.0-py_2.tar.bz2
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/freetype-2.10.4-h546665d_1.tar.bz2
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/jedi-0.18.0-py39haa95532_1.conda
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/jupyter_core-4.8.1-py39haa95532_0.conda
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/kiwisolver-1.3.2-py39h2e07f2f_0.tar.bz2
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/libcurl-7.79.1-h789b8ee_1.tar.bz2
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/libtiff-4.3.0-hd413186_2.tar.bz2
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/libxslt-1.1.34-he774522_0.conda
|
|
||||||
https://conda.anaconda.org/conda-forge/noarch/mako-1.1.5-pyhd8ed1ab_0.tar.bz2
|
|
||||||
https://repo.anaconda.com/pkgs/main/noarch/matplotlib-inline-0.1.2-pyhd3eb1b0_2.conda
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/mkl-service-2.4.0-py39h2bbff1b_0.conda
|
|
||||||
https://repo.anaconda.com/pkgs/main/noarch/prompt-toolkit-3.0.20-pyhd3eb1b0_0.conda
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/pyqt5-sip-4.19.18-py39h415ef7b_7.tar.bz2
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/pyreadline-2.1-py39hcbf5309_1004.tar.bz2
|
|
||||||
https://repo.anaconda.com/pkgs/main/noarch/python-dateutil-2.8.2-pyhd3eb1b0_0.conda
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/qt-5.12.9-h5909a2a_4.tar.bz2
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/setuptools-58.0.4-py39haa95532_0.conda
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/hdf5-1.10.6-nompi_h5268f04_1114.tar.bz2
|
|
||||||
https://repo.anaconda.com/pkgs/main/noarch/jupyter_client-7.0.1-pyhd3eb1b0_0.conda
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/lxml-4.6.3-py39h4fd7cdf_0.tar.bz2
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/numpy-base-1.21.2-py39h0829f74_0.conda
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/openjpeg-2.4.0-hb211442_1.tar.bz2
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/pillow-8.4.0-py39hd45dc43_0.conda
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/pip-21.2.4-py39haa95532_0.conda
|
|
||||||
https://repo.anaconda.com/pkgs/main/noarch/pygments-2.10.0-pyhd3eb1b0_0.conda
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/pyqt-impl-5.12.3-py39h415ef7b_7.tar.bz2
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/ipython-7.27.0-py39hd4e2768_0.conda
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/pyqtchart-5.12-py39h415ef7b_7.tar.bz2
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/pyqtwebengine-5.12.1-py39h415ef7b_7.tar.bz2
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/ipykernel-6.4.1-py39haa95532_1.conda
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/pyqt-5.12.3-py39hcbf5309_7.tar.bz2
|
|
||||||
https://repo.anaconda.com/pkgs/main/noarch/qtconsole-5.1.1-pyhd3eb1b0_0.conda
|
|
||||||
https://conda.anaconda.org/conda-forge/noarch/glymur-0.9.4-pyhd8ed1ab_0.tar.bz2
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/fabio-0.12.0-py39h5d4886f_0.tar.bz2
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/h5py-3.2.1-nompi_py39hf27771d_100.tar.bz2
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/hdf5plugin-3.1.1-py39h71586dd_0.tar.bz2
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/matplotlib-3.4.3-py39hcbf5309_1.tar.bz2
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/matplotlib-base-3.4.3-py39h581301d_1.tar.bz2
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/silx-base-0.15.2-py39h2e25243_0.tar.bz2
|
|
||||||
https://conda.anaconda.org/conda-forge/noarch/silx-0.15.2-hd8ed1ab_0.tar.bz2
|
|
||||||
https://conda.anaconda.org/conda-forge/noarch/pyfai-0.20.0-hd8ed1ab_0.tar.bz2
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/bottleneck-1.3.2-py39h7cc1a96_1.conda
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/mkl_fft-1.3.1-py39h277e83a_0.conda
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/mkl_random-1.2.2-py39hf11a4ad_0.conda
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/numpy-1.21.2-py39hfca59bb_0.conda
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/numexpr-2.7.3-py39hb80d3ca_1.conda
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/scipy-1.7.1-py39hbe87c03_2.conda
|
|
||||||
https://repo.anaconda.com/pkgs/main/win-64/pandas-1.3.3-py39h6214cd6_0.conda
|
|
||||||
https://conda.anaconda.org/conda-forge/win-64/pyfai-base-0.20.0-py39h2e25243_0.tar.bz2
|
|
||||||
|
|
@ -1,378 +0,0 @@
|
||||||
import matplotlib.pyplot as plt
|
|
||||||
from matplotlib.ticker import (MultipleLocator, FormatStrFormatter,AutoMinorLocator)
|
|
||||||
|
|
||||||
import pandas as pd
|
|
||||||
import numpy as np
|
|
||||||
import math
|
|
||||||
|
|
||||||
import ipywidgets as widgets
|
|
||||||
|
|
||||||
import beamtime.xrd as xrd
|
|
||||||
import beamtime.auxillary as aux
|
|
||||||
import beamtime.plotting as btp
|
|
||||||
|
|
||||||
|
|
||||||
def plot_diffractogram(data, options={}):
|
|
||||||
''' Plots a diffractogram.
|
|
||||||
|
|
||||||
Input:
|
|
||||||
data (dict): Must include path = string to diffractogram data, and plot_kind = (recx, beamline, image)'''
|
|
||||||
|
|
||||||
# Update options
|
|
||||||
required_options = ['x_vals', 'y_vals', 'ylabel', 'xlabel', 'xunit', 'yunit', 'line', 'scatter', 'xlim', 'ylim',
|
|
||||||
'reflections_plot', 'reflections_indices', 'reflections_data', 'plot_kind', 'palettes', 'interactive', 'rc_params', 'format_params']
|
|
||||||
|
|
||||||
default_options = {
|
|
||||||
'x_vals': '2th',
|
|
||||||
'y_vals': 'I',
|
|
||||||
'ylabel': 'Intensity', 'xlabel': '2theta',
|
|
||||||
'xunit': 'deg', 'yunit': 'a.u.',
|
|
||||||
'xlim': None, 'ylim': None,
|
|
||||||
'line': True, # whether or not to plot diffractogram as a line plot
|
|
||||||
'scatter': False, # whether or not to plot individual data points
|
|
||||||
'reflections_plot': False, # whether to plot reflections as a plot
|
|
||||||
'reflections_indices': False, # whether to plot the reflection indices
|
|
||||||
'reflections_data': None, # Should be passed as a list of dictionaries on the form {path: rel_path, reflection_indices: number of indices, colour: [r,g,b], min_alpha: 0-1]
|
|
||||||
'plot_kind': None,
|
|
||||||
'palettes': [('qualitative', 'Dark2_8')],
|
|
||||||
'interactive': False,
|
|
||||||
'interactive_session_active': False,
|
|
||||||
'rc_params': {},
|
|
||||||
'format_params': {},
|
|
||||||
}
|
|
||||||
|
|
||||||
options = aux.update_options(options=options, required_options=required_options, default_options=default_options)
|
|
||||||
|
|
||||||
if not 'diffractogram' in data.keys():
|
|
||||||
diffractogram = xrd.io.read_data(data=data, options=options)
|
|
||||||
data['diffractogram'] = diffractogram
|
|
||||||
|
|
||||||
else:
|
|
||||||
diffractogram = data['diffractogram']
|
|
||||||
|
|
||||||
# Sets the xlim if this has not bee specified
|
|
||||||
if not options['xlim']:
|
|
||||||
options['xlim'] = [diffractogram[options['x_vals']].min(), diffractogram[options['x_vals']].max()]
|
|
||||||
|
|
||||||
|
|
||||||
# Start inteactive session with ipywidgets
|
|
||||||
if options['interactive']:
|
|
||||||
options['interactive'] = False
|
|
||||||
options['interactive_session_active'] = True
|
|
||||||
plot_diffractogram_interactive(data=data, options=options)
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
# Makes a list out of reflections_data if it only passed as a dict, as it will be looped through later
|
|
||||||
if options['reflections_data']:
|
|
||||||
if not isinstance(options['reflections_data'], list):
|
|
||||||
options['reflections_data'] = [options['reflections_data']]
|
|
||||||
|
|
||||||
# Determine number of subplots and height ratios between them
|
|
||||||
if len(options['reflections_data']) >= 1:
|
|
||||||
options = determine_grid_layout(options=options)
|
|
||||||
|
|
||||||
|
|
||||||
# Prepare plot, and read and process data
|
|
||||||
|
|
||||||
fig, ax = btp.prepare_plot(options=options)
|
|
||||||
|
|
||||||
|
|
||||||
# Assign the correct axes
|
|
||||||
if options['reflections_plot'] or options['reflections_indices']:
|
|
||||||
|
|
||||||
if options['reflections_indices']:
|
|
||||||
indices_ax = ax[0]
|
|
||||||
|
|
||||||
if options['reflections_plot']:
|
|
||||||
ref_axes = [axx for axx in ax[range(1,len(options['reflections_data'])+1)]]
|
|
||||||
|
|
||||||
else:
|
|
||||||
ref_axes = [axx for axx in ax[range(0,len(options['reflections_data']))]]
|
|
||||||
|
|
||||||
ax = ax[-1]
|
|
||||||
|
|
||||||
colours = btp.generate_colours(options['palettes'])
|
|
||||||
|
|
||||||
|
|
||||||
if options['line']:
|
|
||||||
diffractogram.plot(x=options['x_vals'], y=options['y_vals'], ax=ax, c=next(colours), zorder=1)
|
|
||||||
|
|
||||||
if options['scatter']:
|
|
||||||
ax.scatter(x=diffractogram[options['x_vals']], y = diffractogram[options['y_vals']], c=[(1,1,1,0)], edgecolors=[next(colours)], linewidths=plt.rcParams['lines.markeredgewidth'], zorder=2) #, edgecolors=np.array([next(colours)]))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fig, ax = btp.adjust_plot(fig=fig, ax=ax, options=options)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Make the reflection plots
|
|
||||||
if options['reflections_plot'] and options['reflections_data']:
|
|
||||||
options['xlim'] = ax.get_xlim()
|
|
||||||
options['to_wavelength'] = data['wavelength']
|
|
||||||
|
|
||||||
for reference, axis in zip(options['reflections_data'], ref_axes):
|
|
||||||
plot_reflection_table(data=reference, ax=axis, options=options)
|
|
||||||
|
|
||||||
# Print the reflection indices
|
|
||||||
if options['reflections_indices'] and options['reflections_data']:
|
|
||||||
options['xlim'] = ax.get_xlim()
|
|
||||||
options['to_wavelength'] = data['wavelength']
|
|
||||||
|
|
||||||
for reference in options['reflections_data']:
|
|
||||||
plot_reflection_indices(data=reference, ax=indices_ax, options=options)
|
|
||||||
|
|
||||||
|
|
||||||
if options['interactive_session_active']:
|
|
||||||
btp.update_widgets(options=options)
|
|
||||||
|
|
||||||
|
|
||||||
return diffractogram, fig, ax
|
|
||||||
|
|
||||||
|
|
||||||
def determine_grid_layout(options):
|
|
||||||
|
|
||||||
|
|
||||||
nrows = 1 if not options['reflections_indices'] else 2
|
|
||||||
|
|
||||||
if options['reflections_plot']:
|
|
||||||
for reference in options['reflections_data']:
|
|
||||||
nrows += 1
|
|
||||||
|
|
||||||
options['format_params']['nrows'] = nrows
|
|
||||||
options['format_params']['grid_ratio_height'] = [1 for i in range(nrows-1)]+[10]
|
|
||||||
|
|
||||||
return options
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def plot_diffractogram_interactive(data, options):
|
|
||||||
|
|
||||||
options['widgets'] = {
|
|
||||||
'xlim': {
|
|
||||||
'w': widgets.FloatRangeSlider(value=[data['diffractogram']['2th'].min(), data['diffractogram']['2th'].max()], min=data['diffractogram']['2th'].min(), max=data['diffractogram']['2th'].max(), step=0.5, layout=widgets.Layout(width='95%')),
|
|
||||||
'2th_default': {'min': data['diffractogram']['2th'].min(), 'max': data['diffractogram']['2th'].max(), 'value': [data['diffractogram']['2th'].min(), data['diffractogram']['2th'].max()], 'step': 0.5},
|
|
||||||
'2th_cuka_default': {'min': data['diffractogram']['2th_cuka'].min(), 'max': data['diffractogram']['2th_cuka'].max(), 'value': [data['diffractogram']['2th_cuka'].min(), data['diffractogram']['2th_cuka'].max()], 'step': 0.5},
|
|
||||||
'2th_moka_default': {'min': data['diffractogram']['2th_moka'].min(), 'max': data['diffractogram']['2th_moka'].max(), 'value': [data['diffractogram']['2th_moka'].min(), data['diffractogram']['2th_moka'].max()], 'step': 0.5},
|
|
||||||
'd_default': {'min': data['diffractogram']['d'].min(), 'max': data['diffractogram']['d'].max(), 'value': [data['diffractogram']['d'].min(), data['diffractogram']['d'].max()], 'step': 0.5},
|
|
||||||
'1/d_default': {'min': data['diffractogram']['1/d'].min(), 'max': data['diffractogram']['1/d'].max(), 'value': [data['diffractogram']['1/d'].min(), data['diffractogram']['1/d'].max()], 'step': 0.5},
|
|
||||||
'q_default': {'min': data['diffractogram']['q'].min(), 'max': data['diffractogram']['q'].max(), 'value': [data['diffractogram']['q'].min(), data['diffractogram']['q'].max()], 'step': 0.5},
|
|
||||||
'q2_default': {'min': data['diffractogram']['q2'].min(), 'max': data['diffractogram']['q2'].max(), 'value': [data['diffractogram']['q2'].min(), data['diffractogram']['q2'].max()], 'step': 0.5},
|
|
||||||
'q4_default': {'min': data['diffractogram']['q4'].min(), 'max': data['diffractogram']['q4'].max(), 'value': [data['diffractogram']['q4'].min(), data['diffractogram']['q4'].max()], 'step': 0.5},
|
|
||||||
'state': '2th'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if options['reflections_data']:
|
|
||||||
w = widgets.interactive(btp.ipywidgets_update, func=widgets.fixed(plot_diffractogram), data=widgets.fixed(data), options=widgets.fixed(options),
|
|
||||||
scatter=widgets.ToggleButton(value=False),
|
|
||||||
line=widgets.ToggleButton(value=True),
|
|
||||||
reflections_plot=widgets.ToggleButton(value=True),
|
|
||||||
reflections_indices=widgets.ToggleButton(value=False),
|
|
||||||
x_vals=widgets.Dropdown(options=['2th', 'd', '1/d', 'q', 'q2', 'q4', '2th_cuka', '2th_moka'], value='2th', description='X-values'),
|
|
||||||
xlim=options['widgets']['xlim']['w'])
|
|
||||||
|
|
||||||
else:
|
|
||||||
w = widgets.interactive(btp.ipywidgets_update, func=widgets.fixed(plot_diffractogram), data=widgets.fixed(data), options=widgets.fixed(options),
|
|
||||||
scatter=widgets.ToggleButton(value=False),
|
|
||||||
line=widgets.ToggleButton(value=True),
|
|
||||||
xlim=options['widgets']['xlim']['w'])
|
|
||||||
|
|
||||||
|
|
||||||
display(w)
|
|
||||||
|
|
||||||
|
|
||||||
def update_widgets(options):
|
|
||||||
|
|
||||||
for widget in options['widgets'].values():
|
|
||||||
|
|
||||||
if widget['state'] != options['x_vals']:
|
|
||||||
for arg in widget[f'{options["x_vals"]}_default']:
|
|
||||||
setattr(widget['w'], arg, widget[f'{options["x_vals"]}_default'][arg])
|
|
||||||
|
|
||||||
widget['state'] = options['x_vals']
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def plot_reflection_indices(data, ax, options={}):
|
|
||||||
''' Print reflection indices from output generated by VESTA.
|
|
||||||
|
|
||||||
Required contents of data:
|
|
||||||
path (str): relative path to reflection table file'''
|
|
||||||
|
|
||||||
required_options = ['reflection_indices', 'text_colour', 'hide_indices']
|
|
||||||
|
|
||||||
default_options = {
|
|
||||||
'reflection_indices': 3, # Number of reflection indices to plot, from highest intensity and working its way down
|
|
||||||
'text_colour': 'black',
|
|
||||||
'hide_indices': False
|
|
||||||
}
|
|
||||||
|
|
||||||
data = aux.update_options(options=data, required_options=required_options, default_options=default_options)
|
|
||||||
|
|
||||||
if not data['hide_indices']:
|
|
||||||
reflection_table = xrd.io.load_reflection_table(data=data, options=options)
|
|
||||||
|
|
||||||
if data['reflection_indices'] > 0:
|
|
||||||
|
|
||||||
# Get the data['reflection_indices'] number of highest reflections within the subrange options['xlim']
|
|
||||||
reflection_indices = reflection_table.loc[(reflection_table[options['x_vals']] > options['xlim'][0]) & (reflection_table[options['x_vals']] < options['xlim'][1])].nlargest(options['reflection_indices'], 'I')
|
|
||||||
|
|
||||||
# Plot the indices
|
|
||||||
for i in range(data['reflection_indices']):
|
|
||||||
if reflection_indices.shape[0] > i:
|
|
||||||
ax.text(s=f'({reflection_indices["h"].iloc[i]} {reflection_indices["k"].iloc[i]} {reflection_indices["l"].iloc[i]})', x=reflection_indices[options['x_vals']].iloc[i], y=0, fontsize=2.5, rotation=90, va='bottom', ha='center', c=data['text_colour'])
|
|
||||||
|
|
||||||
|
|
||||||
if options['xlim']:
|
|
||||||
ax.set_xlim(options['xlim'])
|
|
||||||
|
|
||||||
ax.axis('off')
|
|
||||||
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
def plot_reflection_table(data, ax=None, options={}):
|
|
||||||
''' Plots a reflection table from output generated by VESTA.
|
|
||||||
|
|
||||||
Required contents of data:
|
|
||||||
path (str): relative path to reflection table file'''
|
|
||||||
|
|
||||||
required_options = ['reflection_indices', 'reflections_colour', 'min_alpha', 'wavelength', 'format_params', 'rc_params', 'label']
|
|
||||||
|
|
||||||
default_options = {
|
|
||||||
'reflection_indices': 0, # Number of indices to print
|
|
||||||
'reflections_colour': [0,0,0],
|
|
||||||
'min_alpha': 0,
|
|
||||||
'wavelength': 1.54059, # CuKalpha, [Å]
|
|
||||||
'format_params': {},
|
|
||||||
'rc_params': {},
|
|
||||||
'label': None
|
|
||||||
}
|
|
||||||
|
|
||||||
if 'colour' in data.keys():
|
|
||||||
options['reflections_colour'] = data['colour']
|
|
||||||
if 'min_alpha' in data.keys():
|
|
||||||
options['min_alpha'] = data['min_alpha']
|
|
||||||
if 'reflection_indices' in data.keys():
|
|
||||||
options['reflection_indices'] = data['reflection_indices']
|
|
||||||
if 'label' in data.keys():
|
|
||||||
options['label'] = data['label']
|
|
||||||
if 'wavelength' in data.keys():
|
|
||||||
options['wavelength'] = data['wavelength']
|
|
||||||
|
|
||||||
options = aux.update_options(options=options, required_options=required_options, default_options=default_options)
|
|
||||||
|
|
||||||
|
|
||||||
if not ax:
|
|
||||||
_, ax = btp.prepare_plot(options)
|
|
||||||
|
|
||||||
reflection_table = xrd.io.load_reflection_table(data=data, options=options)
|
|
||||||
|
|
||||||
reflections, intensities = reflection_table[options['x_vals']], reflection_table['I']
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
colours = []
|
|
||||||
|
|
||||||
for ref, intensity in zip(reflections, intensities):
|
|
||||||
|
|
||||||
colour = list(options['reflections_colour'])
|
|
||||||
rel_intensity = (intensity / intensities.max())*(1-options['min_alpha']) + options['min_alpha']
|
|
||||||
colour.append(rel_intensity)
|
|
||||||
colours.append(colour)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ax.vlines(x=reflections, ymin=-1, ymax=1, colors=colours, lw=0.5)
|
|
||||||
ax.set_ylim([-0.5,0.5])
|
|
||||||
|
|
||||||
|
|
||||||
ax.tick_params(which='both', bottom=False, labelbottom=False, right=False, labelright=False, left=False, labelleft=False, top=False, labeltop=False)
|
|
||||||
|
|
||||||
if options['xlim']:
|
|
||||||
ax.set_xlim(options['xlim'])
|
|
||||||
|
|
||||||
|
|
||||||
if options['label']:
|
|
||||||
xlim_range = ax.get_xlim()[1] - ax.get_xlim()[0]
|
|
||||||
ylim_avg = (ax.get_ylim()[0]+ax.get_ylim()[1])/2
|
|
||||||
|
|
||||||
ax.text(s=data['label'], x=(ax.get_xlim()[0]-0.01*xlim_range), y=ylim_avg, ha = 'right', va = 'center')
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def prettify_labels(label):
|
|
||||||
|
|
||||||
labels_dict = {
|
|
||||||
'2th': '2$\\theta$',
|
|
||||||
'I': 'Intensity'
|
|
||||||
}
|
|
||||||
|
|
||||||
return labels_dict[label]
|
|
||||||
|
|
||||||
def plot_diffractograms(paths, kind, options=None):
|
|
||||||
|
|
||||||
|
|
||||||
fig, ax = prepare_diffractogram_plot(options=options)
|
|
||||||
|
|
||||||
diffractograms = []
|
|
||||||
|
|
||||||
for path in paths:
|
|
||||||
diffractogram = xrd.io.read_data(path=path, kind=kind, options=options)
|
|
||||||
diffractograms.append(diffractogram)
|
|
||||||
|
|
||||||
|
|
||||||
required_options = ['type', 'xvals', 'yvals', 'x_offset', 'y_offset', 'normalise', 'normalise_around', 'reverse_order']
|
|
||||||
default_options = {
|
|
||||||
'type': 'stacked',
|
|
||||||
'xvals': '2th',
|
|
||||||
'yvals': 'I',
|
|
||||||
'x_offset': 0,
|
|
||||||
'y_offset': 0.2,
|
|
||||||
'normalise': True,
|
|
||||||
'normalise_around': None,
|
|
||||||
'reverse_order': False
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# If reverse_order is enabled, reverse the order
|
|
||||||
if options['reverse_order']:
|
|
||||||
diffractograms = reverse_diffractograms(diffractograms)
|
|
||||||
|
|
||||||
|
|
||||||
# If normalise is enbaled, normalise all the diffractograms
|
|
||||||
if options['normalise']:
|
|
||||||
if not options['normalise_around']:
|
|
||||||
for diffractogram in diffractograms:
|
|
||||||
diffractogram["I"] = diffractogram["I"]/diffractogram["I"].max()
|
|
||||||
else:
|
|
||||||
diffractogram["I"] = diffractogram["I"]/diffractogram["I"].loc[(diffractogram['2th'] > options['normalise_around'][0]) & (diffractogram['2th'] < options['normalise_around'][1])].max()
|
|
||||||
|
|
||||||
|
|
||||||
if options['type'] == 'stacked':
|
|
||||||
for diffractogram in diffractograms:
|
|
||||||
diffractogram.plot(x=options['xvals'], y=options['yvals'], ax=ax)
|
|
||||||
|
|
||||||
|
|
||||||
fig, ax = prettify_diffractogram_plot(fig=fig, ax=ax, options=options)
|
|
||||||
|
|
||||||
|
|
||||||
return diffractogram, fig, ax
|
|
||||||
|
|
||||||
|
|
||||||
def reverse_diffractograms(diffractograms):
|
|
||||||
|
|
||||||
rev_diffractograms = []
|
|
||||||
|
|
||||||
for i in len(diffractograms):
|
|
||||||
rev_diffractograms.append(diffractograms.pop())
|
|
||||||
|
|
||||||
return rev_diffractograms
|
|
||||||
|
|
||||||
#def plot_heatmap():
|
|
||||||
16
environment.yml
Normal file
16
environment.yml
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
name: nafuma
|
||||||
|
channels:
|
||||||
|
- diffpy
|
||||||
|
- defaults
|
||||||
|
- conda-forge
|
||||||
|
dependencies:
|
||||||
|
- ipywidgets
|
||||||
|
- seaborn
|
||||||
|
- sympy
|
||||||
|
- matplotlib
|
||||||
|
- pytest
|
||||||
|
- numpy
|
||||||
|
- pandas
|
||||||
|
- palettable
|
||||||
|
- pyfai
|
||||||
|
prefix: C:\Users\rasmusvt\Anaconda3\envs\nafuma
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import json
|
import json
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
def update_options(options, required_options, default_options):
|
def update_options(options, required_options, default_options):
|
||||||
''' Takes a dictionary of options along with a list of required options and dictionary of default options, and sets all keyval-pairs of options that is not already defined to the default values'''
|
''' Takes a dictionary of options along with a list of required options and dictionary of default options, and sets all keyval-pairs of options that is not already defined to the default values'''
|
||||||
|
|
@ -37,6 +38,18 @@ def swap_values(dict, key1, key2):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def hello_world2(a=1, b=2):
|
def ceil(a, roundto=1):
|
||||||
|
|
||||||
print(f'Halla, MAFAKKAS! a = {a} og b = {b}')
|
fac = 1/roundto
|
||||||
|
|
||||||
|
a = np.ceil(a*fac) / fac
|
||||||
|
|
||||||
|
return a
|
||||||
|
|
||||||
|
def floor(a, roundto=1):
|
||||||
|
|
||||||
|
fac = 1/roundto
|
||||||
|
|
||||||
|
a = np.floor(a*fac) / fac
|
||||||
|
|
||||||
|
return a
|
||||||
|
|
@ -5,7 +5,7 @@ import pandas as pd
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import math
|
import math
|
||||||
|
|
||||||
import beamtime.electrochemistry as ec
|
import nafuma.electrochemistry as ec
|
||||||
|
|
||||||
|
|
||||||
def plot_gc(path, kind, options=None):
|
def plot_gc(path, kind, options=None):
|
||||||
|
|
@ -1,13 +1,11 @@
|
||||||
import beamtime.auxillary as aux
|
import nafuma.auxillary as aux
|
||||||
|
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
from matplotlib.ticker import (MultipleLocator, FormatStrFormatter,AutoMinorLocator)
|
from matplotlib.ticker import (MultipleLocator)
|
||||||
from mpl_toolkits.axes_grid.inset_locator import (inset_axes, InsetPosition, mark_inset)
|
|
||||||
import importlib
|
import importlib
|
||||||
import matplotlib.patches as mpatches
|
import matplotlib.patches as mpatches
|
||||||
from matplotlib.lines import Line2D
|
from matplotlib.lines import Line2D
|
||||||
import matplotlib.lines as mlines
|
import matplotlib.lines as mlines
|
||||||
from cycler import cycler
|
|
||||||
import itertools
|
import itertools
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -22,8 +20,15 @@ def prepare_plot(options={}):
|
||||||
|
|
||||||
format_params will determine the size, aspect ratio, resolution etc. of the figure. Should be modified to conform with any requirements from a journal.'''
|
format_params will determine the size, aspect ratio, resolution etc. of the figure. Should be modified to conform with any requirements from a journal.'''
|
||||||
|
|
||||||
rc_params = options['rc_params']
|
if 'rc_params' in options.keys():
|
||||||
format_params = options['format_params']
|
rc_params = options['rc_params']
|
||||||
|
else:
|
||||||
|
rc_params = {}
|
||||||
|
|
||||||
|
if 'format_params' in options.keys():
|
||||||
|
format_params = options['format_params']
|
||||||
|
else:
|
||||||
|
format_params = {}
|
||||||
|
|
||||||
required_format_params = ['single_column_width', 'double_column_width', 'column_type', 'width_ratio', 'aspect_ratio',
|
required_format_params = ['single_column_width', 'double_column_width', 'column_type', 'width_ratio', 'aspect_ratio',
|
||||||
'width', 'height', 'compress_width', 'compress_height', 'upscaling_factor', 'dpi',
|
'width', 'height', 'compress_width', 'compress_height', 'upscaling_factor', 'dpi',
|
||||||
|
|
@ -82,53 +87,14 @@ def prepare_plot(options={}):
|
||||||
|
|
||||||
return fig, axes
|
return fig, axes
|
||||||
|
|
||||||
def prepare_plots(options={}):
|
|
||||||
|
|
||||||
rc_params = options['rc_params']
|
|
||||||
format_params = options['format_params']
|
|
||||||
|
|
||||||
required_options = ['single_column_width', 'double_column_width', 'column_type', 'width_ratio', 'aspect_ratio', 'compress_width', 'compress_height', 'upscaling_factor', 'dpi']
|
|
||||||
|
|
||||||
default_options = {
|
|
||||||
'single_column_width': 8.3,
|
|
||||||
'double_column_width': 17.1,
|
|
||||||
'column_type': 'single',
|
|
||||||
'width_ratio': '1:1',
|
|
||||||
'aspect_ratio': '1:1',
|
|
||||||
'compress_width': 1,
|
|
||||||
'compress_height': 1,
|
|
||||||
'upscaling_factor': 1.0,
|
|
||||||
'dpi': 600,
|
|
||||||
}
|
|
||||||
|
|
||||||
format_params = aux.update_options(format_params, required_options, default_options)
|
|
||||||
|
|
||||||
|
|
||||||
# Reset run commands
|
|
||||||
plt.rcdefaults()
|
|
||||||
|
|
||||||
# Update run commands if any is passed (will pass an empty dictionary if not passed)
|
|
||||||
update_rc_params(rc_params)
|
|
||||||
|
|
||||||
width = determine_width(format_params)
|
|
||||||
height = determine_height(format_params, width)
|
|
||||||
width, height = scale_figure(options=format_params, width=width, height=height)
|
|
||||||
|
|
||||||
|
|
||||||
if options['plot_kind'] == 'relative':
|
|
||||||
fig, axes = plt.subplots(nrows=1, ncols=options['number_of_frames'], figsize=(width,height), facecolor='w', dpi=format_params['dpi'])
|
|
||||||
|
|
||||||
elif options['plot_kind'] == 'absolute':
|
|
||||||
fig, axes = plt.subplots(nrows=2, ncols=options['number_of_frames'], figsize=(width,height), gridspec_kw={'height_ratios': [1,5]}, facecolor='w', dpi=format_params['dpi'])
|
|
||||||
|
|
||||||
return fig, axes
|
|
||||||
|
|
||||||
|
|
||||||
def adjust_plot(fig, ax, options):
|
def adjust_plot(fig, ax, options):
|
||||||
''' A general function to adjust plot according to contents of the options-dictionary '''
|
''' A general function to adjust plot according to contents of the options-dictionary '''
|
||||||
|
|
||||||
required_options = [
|
required_options = [
|
||||||
'plot_kind',
|
'plot_kind',
|
||||||
|
'xlabel', 'ylabel',
|
||||||
|
'xunit', 'yunit',
|
||||||
'hide_x_labels', 'hide_y_labels',
|
'hide_x_labels', 'hide_y_labels',
|
||||||
'hide_x_ticklabels', 'hide_y_ticklabels',
|
'hide_x_ticklabels', 'hide_y_ticklabels',
|
||||||
'hide_x_ticks', 'hide_y_ticks',
|
'hide_x_ticks', 'hide_y_ticks',
|
||||||
|
|
@ -143,6 +109,8 @@ def adjust_plot(fig, ax, options):
|
||||||
|
|
||||||
default_options = {
|
default_options = {
|
||||||
'plot_kind': None, # defaults to None, but should be utilised when requiring special formatting for a particular plot
|
'plot_kind': None, # defaults to None, but should be utilised when requiring special formatting for a particular plot
|
||||||
|
'xlabel': None, 'ylabel': None,
|
||||||
|
'xunit': None, 'yunit': None,
|
||||||
'hide_x_labels': False, 'hide_y_labels': False, # Whether the main labels on the x- and/or y-axes should be hidden
|
'hide_x_labels': False, 'hide_y_labels': False, # Whether the main labels on the x- and/or y-axes should be hidden
|
||||||
'hide_x_ticklabels': False, 'hide_y_ticklabels': False, # Whether ticklabels on the x- and/or y-axes should be hidden
|
'hide_x_ticklabels': False, 'hide_y_ticklabels': False, # Whether ticklabels on the x- and/or y-axes should be hidden
|
||||||
'hide_x_ticks': False, 'hide_y_ticks': False, # Whether the ticks on the x- and/or y-axes should be hidden
|
'hide_x_ticks': False, 'hide_y_ticks': False, # Whether the ticks on the x- and/or y-axes should be hidden
|
||||||
|
|
@ -182,10 +150,10 @@ def adjust_plot(fig, ax, options):
|
||||||
ax.xaxis.set_minor_locator(MultipleLocator(options['x_tick_locators'][1]))
|
ax.xaxis.set_minor_locator(MultipleLocator(options['x_tick_locators'][1]))
|
||||||
|
|
||||||
|
|
||||||
# THIS NEEDS REWORK FOR IT TO FUNCTION PROPERLY!
|
# FIXME THIS NEEDS REWORK FOR IT TO FUNCTION PROPERLY!
|
||||||
if options['xticks']:
|
#if options['xticks']:
|
||||||
ax.set_xticks(np.arange(plot_data['start'], plot_data['end']+1))
|
# ax.set_xticks(np.arange(plot_data['start'], plot_data['end']+1))
|
||||||
ax.set_xticklabels(options['xticks'])
|
# ax.set_xticklabels(options['xticks'])
|
||||||
# else:
|
# else:
|
||||||
# ax.set_xticks(np.arange(plot_data['start'], plot_data['end']+1))
|
# ax.set_xticks(np.arange(plot_data['start'], plot_data['end']+1))
|
||||||
# ax.set_xticklabels([x/2 for x in np.arange(plot_data['start'], plot_data['end']+1)])
|
# ax.set_xticklabels([x/2 for x in np.arange(plot_data['start'], plot_data['end']+1)])
|
||||||
|
|
@ -307,17 +275,6 @@ def ipywidgets_update(func, data, options={}, **kwargs):
|
||||||
func(data=data, options=options)
|
func(data=data, options=options)
|
||||||
|
|
||||||
|
|
||||||
def update_widgets(options):
|
|
||||||
|
|
||||||
for widget in options['widgets'].values():
|
|
||||||
|
|
||||||
if widget['state'] != options['x_vals']:
|
|
||||||
for arg in widget[f'{options["x_vals"]}_default']:
|
|
||||||
setattr(widget['w'], arg, widget[f'{options["x_vals"]}_default'][arg])
|
|
||||||
|
|
||||||
widget['state'] = options['x_vals']
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def determine_width(format_params):
|
def determine_width(format_params):
|
||||||
''' '''
|
''' '''
|
||||||
|
|
@ -366,16 +323,20 @@ def update_rc_params(rc_params):
|
||||||
plt.rcParams.update({key: rc_params[key]})
|
plt.rcParams.update({key: rc_params[key]})
|
||||||
|
|
||||||
|
|
||||||
def generate_colours(palettes):
|
def generate_colours(palettes, kind=None):
|
||||||
|
|
||||||
# Creates a list of all the colours that is passed in the colour_cycles argument. Then makes cyclic iterables of these.
|
if kind == 'single':
|
||||||
colour_collection = []
|
colour_cycle = itertools.cycle(palettes)
|
||||||
for palette in palettes:
|
|
||||||
mod = importlib.import_module("palettable.colorbrewer.%s" % palette[0])
|
|
||||||
colour = getattr(mod, palette[1]).mpl_colors
|
|
||||||
colour_collection = colour_collection + colour
|
|
||||||
|
|
||||||
colour_cycle = itertools.cycle(colour_collection)
|
else:
|
||||||
|
# Creates a list of all the colours that is passed in the colour_cycles argument. Then makes cyclic iterables of these.
|
||||||
|
colour_collection = []
|
||||||
|
for palette in palettes:
|
||||||
|
mod = importlib.import_module("palettable.colorbrewer.%s" % palette[0])
|
||||||
|
colour = getattr(mod, palette[1]).mpl_colors
|
||||||
|
colour_collection = colour_collection + colour
|
||||||
|
|
||||||
|
colour_cycle = itertools.cycle(colour_collection)
|
||||||
|
|
||||||
|
|
||||||
return colour_cycle
|
return colour_cycle
|
||||||
9
nafuma/test/pytest.ini
Normal file
9
nafuma/test/pytest.ini
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
# pytest.ini
|
||||||
|
|
||||||
|
[pytest]
|
||||||
|
minversion = 6.0
|
||||||
|
testpaths =
|
||||||
|
.
|
||||||
|
|
||||||
|
filterwarnings =
|
||||||
|
ignore::DeprecationWarning
|
||||||
78
nafuma/test/test_auxillary.py
Normal file
78
nafuma/test/test_auxillary.py
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
import nafuma.auxillary as aux
|
||||||
|
import os
|
||||||
|
|
||||||
|
def test_swap_values():
|
||||||
|
|
||||||
|
|
||||||
|
dict = {'test1': 1, 'test2': 2}
|
||||||
|
key1 = 'test1'
|
||||||
|
key2 = 'test2'
|
||||||
|
|
||||||
|
oldval1 = dict[key1]
|
||||||
|
oldval2 = dict[key2]
|
||||||
|
|
||||||
|
new_dict = aux.swap_values(dict=dict, key1=key1, key2=key2)
|
||||||
|
|
||||||
|
assert (dict[key1] == oldval2) and (dict[key2] == oldval1)
|
||||||
|
|
||||||
|
|
||||||
|
def test_ceil() -> None:
|
||||||
|
|
||||||
|
assert aux.ceil(1.05, 0.5) == 1.5
|
||||||
|
assert aux.ceil(1.05, 1) == 2.0
|
||||||
|
assert aux.ceil(1.1, 0.2) == 1.2
|
||||||
|
|
||||||
|
|
||||||
|
def test_floor() -> None:
|
||||||
|
|
||||||
|
assert aux.floor(2.02, 1) == 2.0
|
||||||
|
assert aux.floor(2.02, 0.01) == 2.02
|
||||||
|
assert aux.floor(2.013, 0.01) == 2.01
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def test_options() -> None:
|
||||||
|
|
||||||
|
|
||||||
|
options = {}
|
||||||
|
required_options = ['test1', 'test2', 'test3', 'test4']
|
||||||
|
default_options = {
|
||||||
|
'test1': 1,
|
||||||
|
'test2': 2,
|
||||||
|
'test3': 3,
|
||||||
|
'test4': 4,
|
||||||
|
'test5': 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
options = aux.update_options(options=options, required_options=required_options, default_options=default_options)
|
||||||
|
|
||||||
|
assert options['test1'] == default_options['test1']
|
||||||
|
assert len(options.items()) == len(required_options)
|
||||||
|
assert 'test5' not in options.keys()
|
||||||
|
|
||||||
|
|
||||||
|
def test_save_options() -> None:
|
||||||
|
|
||||||
|
options = {'test1': 1, 'test2': 2}
|
||||||
|
path = 'tmp.dat'
|
||||||
|
|
||||||
|
aux.save_options(options, path)
|
||||||
|
|
||||||
|
assert os.path.isfile(path)
|
||||||
|
|
||||||
|
os.remove(path)
|
||||||
|
|
||||||
|
|
||||||
|
def test_load_options() -> None:
|
||||||
|
|
||||||
|
options = {'test1': 1, 'test2': 2}
|
||||||
|
path = 'tmp.dat'
|
||||||
|
|
||||||
|
aux.save_options(options, path)
|
||||||
|
|
||||||
|
loaded_options = aux.load_options(path)
|
||||||
|
|
||||||
|
assert (loaded_options['test1'] == 1) and (loaded_options['test2'] == 2)
|
||||||
|
|
||||||
|
os.remove(path)
|
||||||
181
nafuma/test/test_plotting.py
Normal file
181
nafuma/test/test_plotting.py
Normal file
|
|
@ -0,0 +1,181 @@
|
||||||
|
import nafuma.plotting as btp
|
||||||
|
from cycler import cycler
|
||||||
|
import itertools
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import matplotlib as mpl
|
||||||
|
|
||||||
|
|
||||||
|
def test_generate_colours() -> None:
|
||||||
|
|
||||||
|
assert type(btp.generate_colours('black', kind='single')) == itertools.cycle
|
||||||
|
|
||||||
|
palettes = [('qualitative', 'Dark2_8')]
|
||||||
|
colour_cycle = btp.generate_colours(palettes)
|
||||||
|
|
||||||
|
assert type(colour_cycle) == itertools.cycle
|
||||||
|
|
||||||
|
|
||||||
|
# Test that it actually loaded 8 colours when given a set of 8 colours to
|
||||||
|
|
||||||
|
same_colour = None
|
||||||
|
for i in range(10):
|
||||||
|
colour = next(colour_cycle)
|
||||||
|
if i == 0:
|
||||||
|
first_colour = colour
|
||||||
|
|
||||||
|
if colour == first_colour:
|
||||||
|
repeat_colour_index = i
|
||||||
|
|
||||||
|
|
||||||
|
assert repeat_colour_index == 8
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def test_update_rc_params() -> None:
|
||||||
|
|
||||||
|
rc_params = {
|
||||||
|
'lines.linewidth': 100
|
||||||
|
}
|
||||||
|
|
||||||
|
prev_params = plt.rcParams['lines.linewidth']
|
||||||
|
|
||||||
|
# Update run commands if any is passed (will pass an empty dictionary if not passed)
|
||||||
|
btp.update_rc_params(rc_params)
|
||||||
|
|
||||||
|
new_params = plt.rcParams['lines.linewidth']
|
||||||
|
|
||||||
|
assert new_params == 100
|
||||||
|
assert prev_params != new_params
|
||||||
|
|
||||||
|
|
||||||
|
# Reset run commands
|
||||||
|
plt.rcdefaults()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def test_scale_figure() -> None:
|
||||||
|
|
||||||
|
width, height = 1, 1
|
||||||
|
|
||||||
|
format_params = {
|
||||||
|
'upscaling_factor': 2,
|
||||||
|
'compress_width': 1,
|
||||||
|
'compress_height': 1
|
||||||
|
}
|
||||||
|
|
||||||
|
width1, height1 = btp.scale_figure(format_params=format_params, width=width, height=height)
|
||||||
|
|
||||||
|
assert width1 == 2 and height1 == 2
|
||||||
|
|
||||||
|
format_params = {
|
||||||
|
'upscaling_factor': 1,
|
||||||
|
'compress_width': 0.5,
|
||||||
|
'compress_height': 1
|
||||||
|
}
|
||||||
|
|
||||||
|
width2, height2 = btp.scale_figure(format_params=format_params, width=width, height=height)
|
||||||
|
|
||||||
|
assert width2 == 0.5 and height2 == 1
|
||||||
|
|
||||||
|
format_params = {
|
||||||
|
'upscaling_factor': 2,
|
||||||
|
'compress_width': 0.5,
|
||||||
|
'compress_height': 0.2
|
||||||
|
}
|
||||||
|
|
||||||
|
width2, height2 = btp.scale_figure(format_params=format_params, width=width, height=height)
|
||||||
|
|
||||||
|
assert width2 == 1 and height2 == 0.4
|
||||||
|
|
||||||
|
|
||||||
|
def test_determine_width() -> None:
|
||||||
|
|
||||||
|
conversion_cm_inch = 0.3937008 # cm to inch
|
||||||
|
|
||||||
|
format_params = {
|
||||||
|
'column_type': 'single',
|
||||||
|
'single_column_width': 5,
|
||||||
|
'double_column_width': 10,
|
||||||
|
'width_ratio': '1:1'
|
||||||
|
}
|
||||||
|
|
||||||
|
assert np.round(btp.determine_width(format_params),6) == np.round(5*conversion_cm_inch,6)
|
||||||
|
|
||||||
|
format_params['column_type'] = 'double'
|
||||||
|
|
||||||
|
assert np.round(btp.determine_width(format_params), 6) == np.round(10*conversion_cm_inch, 6)
|
||||||
|
|
||||||
|
|
||||||
|
format_params['column_type'] = 'single'
|
||||||
|
format_params['width_ratio'] = '1:2'
|
||||||
|
|
||||||
|
assert np.round(btp.determine_width(format_params), 6) == np.round(2.5*conversion_cm_inch, 6)
|
||||||
|
|
||||||
|
def test_determine_height() -> None:
|
||||||
|
|
||||||
|
|
||||||
|
width = 1
|
||||||
|
|
||||||
|
format_params = {
|
||||||
|
'aspect_ratio': '1:1'
|
||||||
|
}
|
||||||
|
|
||||||
|
assert btp.determine_height(format_params=format_params, width=width) == 1
|
||||||
|
|
||||||
|
format_params['aspect_ratio'] = '3:1'
|
||||||
|
|
||||||
|
assert (btp.determine_height(format_params=format_params, width=width) - 0.333333333333333) < 10e-7
|
||||||
|
|
||||||
|
assert True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def test_prepare_plot() -> None:
|
||||||
|
|
||||||
|
fig, ax = btp.prepare_plot()
|
||||||
|
|
||||||
|
assert type(fig) == plt.Figure
|
||||||
|
assert fig.get_dpi() == 600
|
||||||
|
assert ax.get_xlim() == (0.0, 1.0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def test_adjust_plot() -> None:
|
||||||
|
|
||||||
|
fig, ax = btp.prepare_plot()
|
||||||
|
|
||||||
|
options = {
|
||||||
|
'xlim': (0.0, 2.0),
|
||||||
|
'title': 'Test'
|
||||||
|
}
|
||||||
|
|
||||||
|
fig, ax = btp.adjust_plot(fig, ax, options)
|
||||||
|
|
||||||
|
|
||||||
|
assert ax.get_xlim() == (0.0, 2.0)
|
||||||
|
assert ax.get_title() == 'Test'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def test_ipywidgets_update() -> None:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def test_func(data, options):
|
||||||
|
test1 = options['test1']
|
||||||
|
test2 = options['test2']
|
||||||
|
|
||||||
|
assert type(data) == dict
|
||||||
|
assert test1 == 1
|
||||||
|
assert test2 == 2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
data = {}
|
||||||
|
options = {}
|
||||||
|
|
||||||
|
btp.ipywidgets_update(func=test_func, data=data, options=options, test1=1, test2=2)
|
||||||
|
|
||||||
0
nafuma/test/xrd/test_io.py
Normal file
0
nafuma/test/xrd/test_io.py
Normal file
0
nafuma/test/xrd/test_plot.py
Normal file
0
nafuma/test/xrd/test_plot.py
Normal file
|
|
@ -24,6 +24,7 @@ def finding_edge(df):
|
||||||
edge='Ni'
|
edge='Ni'
|
||||||
return(edge)
|
return(edge)
|
||||||
|
|
||||||
|
<<<<<<< HEAD:beamtime/xanes/calib.py
|
||||||
#def pre_edge_subtraction(df,filenames, options={}):
|
#def pre_edge_subtraction(df,filenames, options={}):
|
||||||
def test(innmat):
|
def test(innmat):
|
||||||
df_test= xas.io.put_in_dataframe(innmat)
|
df_test= xas.io.put_in_dataframe(innmat)
|
||||||
|
|
@ -40,6 +41,11 @@ def pre_edge_subtraction(path, options={}):
|
||||||
filenames = xas.io.get_filenames(path)
|
filenames = xas.io.get_filenames(path)
|
||||||
df= xas.io.put_in_dataframe(path)
|
df= xas.io.put_in_dataframe(path)
|
||||||
edge=finding_edge(df)
|
edge=finding_edge(df)
|
||||||
|
=======
|
||||||
|
def split_xanes_scan(filename, destination=None, replace=False):
|
||||||
|
#root is the path to the beamtime-folder
|
||||||
|
#destination should be the path to the processed data
|
||||||
|
>>>>>>> master:nafuma/xanes/calib.py
|
||||||
|
|
||||||
#Defining the end of the region used to define the background, thus start of the edge
|
#Defining the end of the region used to define the background, thus start of the edge
|
||||||
#implement widget
|
#implement widget
|
||||||
|
|
@ -9,7 +9,7 @@ import zipfile
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
|
|
||||||
|
|
||||||
import beamtime.auxillary as aux
|
import nafuma.auxillary as aux
|
||||||
|
|
||||||
|
|
||||||
def get_image_array(path):
|
def get_image_array(path):
|
||||||
|
|
@ -27,7 +27,7 @@ def get_image_headers(path):
|
||||||
return image.header
|
return image.header
|
||||||
|
|
||||||
|
|
||||||
def integrate_1d(data, options={}):
|
def integrate_1d(data, options={}, index=0):
|
||||||
''' Integrates an image file to a 1D diffractogram.
|
''' Integrates an image file to a 1D diffractogram.
|
||||||
|
|
||||||
Required content of data:
|
Required content of data:
|
||||||
|
|
@ -40,10 +40,12 @@ def integrate_1d(data, options={}):
|
||||||
df: DataFrame contianing 1D diffractogram if option 'return' is True
|
df: DataFrame contianing 1D diffractogram if option 'return' is True
|
||||||
'''
|
'''
|
||||||
|
|
||||||
required_options = ['unit', 'save', 'save_filename', 'save_extension', 'save_folder', 'overwrite']
|
required_options = ['unit', 'nbins', 'save', 'save_filename', 'save_extension', 'save_folder', 'overwrite', 'extract_folder']
|
||||||
|
|
||||||
default_options = {
|
default_options = {
|
||||||
'unit': '2th_deg',
|
'unit': '2th_deg',
|
||||||
|
'nbins': 3000,
|
||||||
|
'extract_folder': 'tmp',
|
||||||
'save': False,
|
'save': False,
|
||||||
'save_filename': None,
|
'save_filename': None,
|
||||||
'save_extension': '_integrated.xy',
|
'save_extension': '_integrated.xy',
|
||||||
|
|
@ -51,51 +53,57 @@ def integrate_1d(data, options={}):
|
||||||
'overwrite': False}
|
'overwrite': False}
|
||||||
|
|
||||||
options = aux.update_options(options=options, required_options=required_options, default_options=default_options)
|
options = aux.update_options(options=options, required_options=required_options, default_options=default_options)
|
||||||
|
|
||||||
|
if not isinstance(data['path'], list):
|
||||||
|
data['path'] = [data['path']]
|
||||||
|
|
||||||
|
|
||||||
# Get image array from filename if not passed
|
# Get image array from filename if not passed
|
||||||
if 'image' not in data.keys():
|
if 'image' not in data.keys():
|
||||||
data['image'] = get_image_array(data['path'])
|
data['image'] = get_image_array(data['path'][index])
|
||||||
|
|
||||||
# Instanciate the azimuthal integrator from pyFAI from the calibrant (.poni-file)
|
# Instanciate the azimuthal integrator from pyFAI from the calibrant (.poni-file)
|
||||||
ai = pyFAI.load(data['calibrant'])
|
ai = pyFAI.load(data['calibrant'])
|
||||||
|
|
||||||
# Determine filename
|
# Determine filename
|
||||||
filename = make_filename(data=data, options=options)
|
filename = make_filename(options=options, path=data['path'][index])
|
||||||
|
|
||||||
# Make save_folder if this does not exist already
|
# Make save_folder if this does not exist already
|
||||||
if not os.path.isdir(options['save_folder']):
|
if not os.path.isdir(options['extract_folder']):
|
||||||
os.makedirs(options['save_folder'])
|
os.makedirs(options['extract_folder'])
|
||||||
|
|
||||||
|
|
||||||
res = ai.integrate1d(data['image'], data['nbins'], unit=options['unit'], filename=filename)
|
res = ai.integrate1d(data['image'], options['nbins'], unit=options['unit'], filename=filename)
|
||||||
|
|
||||||
data['path'] = filename
|
data['path'][index] = filename
|
||||||
diffractogram = read_xy(data=data, options=options)
|
diffractogram, wavelength = read_xy(data=data, options=options, index=index)
|
||||||
|
|
||||||
if not options['save']:
|
if not options['save']:
|
||||||
os.remove(filename)
|
os.remove(filename)
|
||||||
shutil.rmtree('tmp')
|
shutil.rmtree(f'tmp')
|
||||||
|
|
||||||
|
|
||||||
|
# Reset this option
|
||||||
|
options['save_folder'] = None
|
||||||
|
|
||||||
return diffractogram
|
return diffractogram, wavelength
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def make_filename(data, options):
|
def make_filename(options, path=None):
|
||||||
|
|
||||||
# Define save location for integrated diffractogram data
|
# Define save location for integrated diffractogram data
|
||||||
if not options['save']:
|
if not options['save']:
|
||||||
options['save_folder'] = 'tmp'
|
filename = os.path.join(options['extract_folder'], 'tmp_diff.dat')
|
||||||
filename = os.path.join(options['save_folder'], 'tmp_diff.dat')
|
|
||||||
|
|
||||||
elif options['save']:
|
elif options['save']:
|
||||||
|
|
||||||
# Case 1: No filename is given.
|
# Case 1: No filename is given.
|
||||||
if not options['save_filename']:
|
if not options['save_filename']:
|
||||||
# If a path is given instead of an image array, the path is taken as the trunk of the savename
|
# If a path is given instead of an image array, the path is taken as the trunk of the savename
|
||||||
if data['path']:
|
if path:
|
||||||
# Make filename by joining the save_folder, the filename (with extension deleted) and adding the save_extension
|
# Make filename by joining the save_folder, the filename (with extension deleted) and adding the save_extension
|
||||||
filename = os.path.join(options['save_folder'], os.path.split(data['path'])[-1].split('.')[0] + options['save_extension'])
|
filename = os.path.join(options['save_folder'], os.path.split(path)[-1].split('.')[0] + options['save_extension'])
|
||||||
else:
|
else:
|
||||||
# Make filename just "integrated.dat" in the save_folder
|
# Make filename just "integrated.dat" in the save_folder
|
||||||
filename = os.path.join(options['save_folder'], 'integrated.xy')
|
filename = os.path.join(options['save_folder'], 'integrated.xy')
|
||||||
|
|
@ -141,7 +149,7 @@ def average_images(images):
|
||||||
image_arrays = []
|
image_arrays = []
|
||||||
|
|
||||||
for image in images:
|
for image in images:
|
||||||
image_array = xrd.io.get_image_array(image)
|
image_array = get_image_array(image)
|
||||||
image_arrays.append(image_array)
|
image_arrays.append(image_array)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -176,7 +184,10 @@ def view_integrator(calibrant):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def read_brml(data, options={}):
|
def read_brml(data, options={}, index=0):
|
||||||
|
|
||||||
|
|
||||||
|
# FIXME: Can't read RECX1-data, apparently must be formatted differently from RECX2. Check the RawData-files and compare between the two files.
|
||||||
|
|
||||||
|
|
||||||
required_options = ['extract_folder', 'save_folder']
|
required_options = ['extract_folder', 'save_folder']
|
||||||
|
|
@ -194,7 +205,7 @@ def read_brml(data, options={}):
|
||||||
|
|
||||||
|
|
||||||
# Extract the RawData0.xml file from the brml-file
|
# Extract the RawData0.xml file from the brml-file
|
||||||
with zipfile.ZipFile(data['path'], 'r') as brml:
|
with zipfile.ZipFile(data['path'][index], 'r') as brml:
|
||||||
for info in brml.infolist():
|
for info in brml.infolist():
|
||||||
if "RawData" in info.filename:
|
if "RawData" in info.filename:
|
||||||
brml.extract(info.filename, options['extract_folder'])
|
brml.extract(info.filename, options['extract_folder'])
|
||||||
|
|
@ -213,31 +224,66 @@ def read_brml(data, options={}):
|
||||||
|
|
||||||
for chain in root.findall('./DataRoutes/DataRoute'):
|
for chain in root.findall('./DataRoutes/DataRoute'):
|
||||||
|
|
||||||
for scantype in chain.findall('ScanInformation/ScanMode'):
|
|
||||||
if scantype.text == 'StillScan':
|
|
||||||
|
|
||||||
if chain.get('Description') == 'Originally measured data.':
|
# Get the scan type to be able to handle different data formats
|
||||||
for scandata in chain.findall('Datum'):
|
scantype = chain.findall('ScanInformation')[0].get('VisibleName')
|
||||||
|
|
||||||
|
# Check if the chain is the right one to extract the data from
|
||||||
|
if chain.get('Description') == 'Originally measured data.':
|
||||||
|
|
||||||
|
|
||||||
|
if scantype == 'TwoTheta':
|
||||||
|
for scandata in chain.findall('Datum'):
|
||||||
|
scandata = scandata.text.split(',')
|
||||||
|
twotheta, intensity = float(scandata[2]), float(scandata[3])
|
||||||
|
|
||||||
|
if twotheta > 0:
|
||||||
|
diffractogram.append({'2th': twotheta, 'I': intensity})
|
||||||
|
|
||||||
|
elif scantype == 'Coupled TwoTheta/Theta':
|
||||||
|
for scandata in chain.findall('Datum'):
|
||||||
|
scandata = scandata.text.split(',')
|
||||||
|
twotheta, intensity = float(scandata[2]), float(scandata[4])
|
||||||
|
|
||||||
|
if twotheta > 0:
|
||||||
|
diffractogram.append({'2th': twotheta, 'I': intensity})
|
||||||
|
|
||||||
|
elif scantype == 'Still (Eiger2R_500K (1D mode))':
|
||||||
|
|
||||||
|
start = float(chain.findall('ScanInformation/ScaleAxes/ScaleAxisInfo/Start')[0].text)
|
||||||
|
stop = float(chain.findall('ScanInformation/ScaleAxes/ScaleAxisInfo/Stop')[0].text)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for scandata in chain.findall('Datum'):
|
||||||
scandata = scandata.text.split(',')
|
scandata = scandata.text.split(',')
|
||||||
scandata = [float(i) for i in scandata]
|
raw = [float(i) for i in scandata]
|
||||||
twotheta, intensity = float(scandata[2]), float(scandata[3])
|
|
||||||
|
|
||||||
|
intensity = []
|
||||||
else:
|
for r in raw:
|
||||||
if chain.get('Description') == 'Originally measured data.':
|
if r > 601:
|
||||||
for scandata in chain.findall('Datum'):
|
intensity.append(r)
|
||||||
scandata = scandata.text.split(',')
|
|
||||||
twotheta, intensity = float(scandata[2]), float(scandata[3])
|
intensity = np.array(intensity)
|
||||||
|
|
||||||
if twotheta > 0:
|
|
||||||
diffractogram.append({'2th': twotheta, 'I': intensity})
|
|
||||||
|
|
||||||
|
twotheta = np.linspace(start, stop, len(intensity))
|
||||||
|
|
||||||
|
diffractogram = {'2th': twotheta, 'I': intensity}
|
||||||
|
|
||||||
|
|
||||||
if 'wavelength' not in data.keys():
|
|
||||||
for chain in root.findall('./FixedInformation/Instrument/PrimaryTracks/TrackInfoData/MountedOptics/InfoData/Tube/WaveLengthAlpha1'):
|
#if 'wavelength' not in data.keys():
|
||||||
data['wavelength'] = float(chain.attrib['Value'])
|
# Find wavelength
|
||||||
|
for chain in root.findall('./FixedInformation/Instrument/PrimaryTracks/TrackInfoData/MountedOptics/InfoData/Tube/WaveLengthAlpha1'):
|
||||||
|
wavelength = float(chain.attrib['Value'])
|
||||||
|
|
||||||
|
|
||||||
diffractogram = pd.DataFrame(diffractogram)
|
diffractogram = pd.DataFrame(diffractogram)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -249,15 +295,16 @@ def read_brml(data, options={}):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return diffractogram
|
return diffractogram, wavelength
|
||||||
|
|
||||||
|
|
||||||
def read_xy(data, options={}):
|
def read_xy(data, options={}, index=0):
|
||||||
|
|
||||||
if 'wavelength' not in data.keys():
|
#if 'wavelength' not in data.keys():
|
||||||
find_wavelength_from_xy(data=data)
|
# Get wavelength from scan
|
||||||
|
wavelength = find_wavelength_from_xy(path=data['path'][index])
|
||||||
|
|
||||||
with open(data['path'], 'r') as f:
|
with open(data['path'][index], 'r') as f:
|
||||||
position = 0
|
position = 0
|
||||||
|
|
||||||
current_line = f.readline()
|
current_line = f.readline()
|
||||||
|
|
@ -276,37 +323,89 @@ def read_xy(data, options={}):
|
||||||
diffractogram.columns = ['2th', 'I', 'sigma']
|
diffractogram.columns = ['2th', 'I', 'sigma']
|
||||||
|
|
||||||
|
|
||||||
return diffractogram
|
return diffractogram, wavelength
|
||||||
|
|
||||||
|
|
||||||
def read_data(data, options={}):
|
def read_data(data, options={}, index=0):
|
||||||
|
|
||||||
beamline_extensions = ['mar3450', 'edf', 'cbf']
|
beamline_extensions = ['mar3450', 'edf', 'cbf']
|
||||||
file_extension = data['path'].split('.')[-1]
|
file_extension = data['path'][index].split('.')[-1]
|
||||||
|
|
||||||
if file_extension in beamline_extensions:
|
if file_extension in beamline_extensions:
|
||||||
diffractogram = integrate_1d(data=data, options=options)
|
diffractogram, wavelength = integrate_1d(data=data, options=options, index=index)
|
||||||
|
|
||||||
elif file_extension == 'brml':
|
elif file_extension == 'brml':
|
||||||
diffractogram = read_brml(data=data, options=options)
|
diffractogram, wavelength = read_brml(data=data, options=options, index=index)
|
||||||
|
|
||||||
elif file_extension in['xy', 'xye']:
|
elif file_extension in['xy', 'xye']:
|
||||||
diffractogram = read_xy(data=data, options=options)
|
diffractogram, wavelength = read_xy(data=data, options=options, index=index)
|
||||||
|
|
||||||
|
|
||||||
diffractogram = translate_wavelengths(data=diffractogram, wavelength=data['wavelength'])
|
|
||||||
|
|
||||||
|
if options['offset'] or options['normalise']:
|
||||||
|
# Make copy of the original intensities before any changes are made through normalisation or offset, to easily revert back if need to update.
|
||||||
|
diffractogram['I_org'] = diffractogram['I']
|
||||||
|
diffractogram['2th_org'] = diffractogram['2th']
|
||||||
|
|
||||||
|
diffractogram = apply_offset(diffractogram, wavelength, index, options)
|
||||||
|
|
||||||
|
|
||||||
|
diffractogram = translate_wavelengths(data=diffractogram, wavelength=wavelength)
|
||||||
|
|
||||||
|
return diffractogram, wavelength
|
||||||
|
|
||||||
|
|
||||||
|
def apply_offset(diffractogram, wavelength, index, options):
|
||||||
|
|
||||||
|
if 'current_offset_y' not in options.keys():
|
||||||
|
options['current_offset_y'] = options['offset_y']
|
||||||
|
else:
|
||||||
|
if options['current_offset_y'] != options['offset_y']:
|
||||||
|
options['offset_change'] = True
|
||||||
|
|
||||||
|
options['current_offset_y'] = options['offset_y']
|
||||||
|
|
||||||
|
options['current_offset_x'] = options['offset_x']
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#Apply offset along y-axis
|
||||||
|
diffractogram['I'] = diffractogram['I_org'] # Reset intensities
|
||||||
|
|
||||||
|
if options['normalise']:
|
||||||
|
diffractogram['I'] = diffractogram['I'] / diffractogram['I'].max()
|
||||||
|
|
||||||
|
diffractogram['I'] = diffractogram['I'] + index*options['offset_y']
|
||||||
|
|
||||||
|
# Apply offset along x-axis
|
||||||
|
relative_shift = (wavelength / 1.54059)*options['offset_x'] # Adjusts the offset-factor to account for wavelength, so that offset_x given is given in 2th_cuka-units
|
||||||
|
diffractogram['2th'] = diffractogram['2th_org']
|
||||||
|
diffractogram['2th'] = diffractogram['2th'] + index*relative_shift
|
||||||
|
|
||||||
|
|
||||||
return diffractogram
|
return diffractogram
|
||||||
|
|
||||||
|
|
||||||
|
def revert_offset(diffractogram,which=None):
|
||||||
|
|
||||||
|
if which == 'both':
|
||||||
|
diffractogram['2th'] = diffractogram['2th_org']
|
||||||
|
diffractogram['I'] = diffractogram['I_org']
|
||||||
|
|
||||||
|
if which == 'y':
|
||||||
|
diffractogram['I'] = diffractogram['I_org']
|
||||||
|
|
||||||
|
if which == 'x':
|
||||||
|
diffractogram['2th'] = diffractogram['2th_org']
|
||||||
|
|
||||||
def load_reflection_table(data, options={}):
|
return diffractogram
|
||||||
|
|
||||||
required_options = ['wavelength', 'to_wavelength']
|
def load_reflection_table(data: dict, reflections_params: dict, options={}):
|
||||||
|
|
||||||
|
required_options = ['ref_wavelength', 'to_wavelength']
|
||||||
|
|
||||||
default_options = {
|
default_options = {
|
||||||
'wavelength': 1.54059,
|
'ref_wavelength': 1.54059,
|
||||||
'to_wavelength': None
|
'to_wavelength': None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -314,12 +413,12 @@ def load_reflection_table(data, options={}):
|
||||||
|
|
||||||
# VESTA outputs the file with a header that has a space between the parameter and units - so there is some extra code to rectify the issue
|
# VESTA outputs the file with a header that has a space between the parameter and units - so there is some extra code to rectify the issue
|
||||||
# that ensues from this formatting
|
# that ensues from this formatting
|
||||||
reflections = pd.read_csv(data['path'], delim_whitespace=True)
|
reflections = pd.read_csv(reflections_params['path'], delim_whitespace=True)
|
||||||
|
|
||||||
# Remove the extra column that appears from the headers issue
|
# Remove the extra column that appears from the headers issue
|
||||||
reflections.drop(reflections.columns[-1], axis=1, inplace=True)
|
reflections.drop(reflections.columns[-1], axis=1, inplace=True)
|
||||||
|
|
||||||
with open(data['path'], 'r') as f:
|
with open(reflections_params['path'], 'r') as f:
|
||||||
line = f.readline()
|
line = f.readline()
|
||||||
|
|
||||||
headers = line.split()
|
headers = line.split()
|
||||||
|
|
@ -333,15 +432,32 @@ def load_reflection_table(data, options={}):
|
||||||
# Set the new modified headers as the headers of
|
# Set the new modified headers as the headers of
|
||||||
reflections.columns = headers
|
reflections.columns = headers
|
||||||
|
|
||||||
reflections = translate_wavelengths(data=reflections, wavelength=options['wavelength'], to_wavelength=options['to_wavelength'])
|
reflections = translate_wavelengths(data=reflections, wavelength=options['ref_wavelength'], to_wavelength=options['to_wavelength'])
|
||||||
|
|
||||||
#print(reflections)
|
if 'heatmap' in data.keys():
|
||||||
|
|
||||||
|
start_2th, stop_2th = data['diffractogram'][0]['2th'].min(), data['diffractogram'][0]['2th'].max()
|
||||||
|
len_2th = stop_2th - start_2th
|
||||||
|
#print(start_2th, stop_2th, len_2th)
|
||||||
|
|
||||||
|
start_heatmap, stop_heatmap = 0, data['heatmap'].shape[1]
|
||||||
|
len_heatmap = stop_heatmap - start_heatmap
|
||||||
|
#print(start_heatmap, stop_heatmap, len_heatmap)
|
||||||
|
|
||||||
|
scale = len_heatmap/len_2th
|
||||||
|
|
||||||
|
#print(scale)
|
||||||
|
#print(stop_2th * scale)
|
||||||
|
|
||||||
|
reflections['heatmap'] = (reflections['2th']-start_2th) * scale
|
||||||
|
|
||||||
return reflections
|
return reflections
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def translate_wavelengths(data, wavelength, to_wavelength=None):
|
def translate_wavelengths(data: pd.DataFrame, wavelength: float, to_wavelength=None) -> pd.DataFrame:
|
||||||
|
# FIXME Somewhere here there is an invalid arcsin-argument. Not sure where.
|
||||||
|
|
||||||
pd.options.mode.chained_assignment = None
|
pd.options.mode.chained_assignment = None
|
||||||
|
|
||||||
# Translate to CuKalpha
|
# Translate to CuKalpha
|
||||||
|
|
@ -378,8 +494,7 @@ def translate_wavelengths(data, wavelength, to_wavelength=None):
|
||||||
|
|
||||||
|
|
||||||
if to_wavelength:
|
if to_wavelength:
|
||||||
|
if to_wavelength >= cuka:
|
||||||
if to_wavelength > cuka:
|
|
||||||
max_2th = 2*np.arcsin(cuka/to_wavelength) * 180/np.pi
|
max_2th = 2*np.arcsin(cuka/to_wavelength) * 180/np.pi
|
||||||
else:
|
else:
|
||||||
max_2th = data['2th_cuka'].max()
|
max_2th = data['2th_cuka'].max()
|
||||||
|
|
@ -395,19 +510,24 @@ def translate_wavelengths(data, wavelength, to_wavelength=None):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def find_wavelength_from_xy(data):
|
def find_wavelength_from_xy(path):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
wavelength_dict = {'Cu': 1.54059, 'Mo': 0.71073}
|
wavelength_dict = {'Cu': 1.54059, 'Mo': 0.71073}
|
||||||
|
|
||||||
with open(data['path'], 'r') as f:
|
with open(path, 'r') as f:
|
||||||
lines = f.readlines()
|
lines = f.readlines()
|
||||||
|
|
||||||
for line in lines:
|
for line in lines:
|
||||||
|
# For .xy-files output from EVA
|
||||||
if 'Anode' in line:
|
if 'Anode' in line:
|
||||||
anode = line.split()[8].strip('"')
|
anode = line.split()[8].strip('"')
|
||||||
data['wavelength'] = wavelength_dict[anode]
|
wavelength = wavelength_dict[anode]
|
||||||
|
|
||||||
|
# For .xy-files output from pyFAI integration
|
||||||
elif 'Wavelength' in line:
|
elif 'Wavelength' in line:
|
||||||
data['wavelength'] = float(line.split()[2])*10**10
|
wavelength = float(line.split()[2])*10**10
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return wavelength
|
||||||
672
nafuma/xrd/plot.py
Normal file
672
nafuma/xrd/plot.py
Normal file
|
|
@ -0,0 +1,672 @@
|
||||||
|
import seaborn as sns
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
from matplotlib.ticker import (MultipleLocator, FormatStrFormatter,AutoMinorLocator)
|
||||||
|
|
||||||
|
import pandas as pd
|
||||||
|
import numpy as np
|
||||||
|
import math
|
||||||
|
|
||||||
|
import ipywidgets as widgets
|
||||||
|
from IPython.display import display
|
||||||
|
|
||||||
|
import nafuma.xrd as xrd
|
||||||
|
import nafuma.auxillary as aux
|
||||||
|
import nafuma.plotting as btp
|
||||||
|
|
||||||
|
|
||||||
|
def plot_diffractogram(data, options={}):
|
||||||
|
''' Plots a diffractogram.
|
||||||
|
|
||||||
|
Input:
|
||||||
|
data (dict): Must include path = string to diffractogram data, and plot_kind = (recx, beamline, image)'''
|
||||||
|
|
||||||
|
# Update options
|
||||||
|
required_options = ['x_vals', 'y_vals', 'ylabel', 'xlabel', 'xunit', 'yunit', 'line', 'scatter', 'xlim', 'ylim', 'normalise', 'offset', 'offset_x', 'offset_y', 'offset_change',
|
||||||
|
'reflections_plot', 'reflections_indices', 'reflections_data', 'heatmap', 'cmap', 'plot_kind', 'palettes', 'interactive', 'rc_params', 'format_params', 'interactive_session_active']
|
||||||
|
|
||||||
|
default_options = {
|
||||||
|
'x_vals': '2th',
|
||||||
|
'y_vals': 'I',
|
||||||
|
'ylabel': 'Intensity', 'xlabel': '2theta',
|
||||||
|
'xunit': 'deg', 'yunit': 'a.u.',
|
||||||
|
'xlim': None, 'ylim': None,
|
||||||
|
'normalise': True,
|
||||||
|
'offset': True,
|
||||||
|
'offset_x': 0,
|
||||||
|
'offset_y': 1,
|
||||||
|
'offset_change': False,
|
||||||
|
'line': True, # whether or not to plot diffractogram as a line plot
|
||||||
|
'scatter': False, # whether or not to plot individual data points
|
||||||
|
'reflections_plot': False, # whether to plot reflections as a plot
|
||||||
|
'reflections_indices': False, # whether to plot the reflection indices
|
||||||
|
'reflections_data': None, # Should be passed as a list of dictionaries on the form {path: rel_path, reflection_indices: number of indices, colour: [r,g,b], min_alpha: 0-1]
|
||||||
|
'heatmap': False,
|
||||||
|
'cmap': 'viridis',
|
||||||
|
'plot_kind': None,
|
||||||
|
'palettes': [('qualitative', 'Dark2_8')],
|
||||||
|
'interactive': False,
|
||||||
|
'interactive_session_active': False,
|
||||||
|
'rc_params': {},
|
||||||
|
'format_params': {},
|
||||||
|
}
|
||||||
|
|
||||||
|
if 'offset_y' not in options.keys():
|
||||||
|
if len(data['path']) > 10:
|
||||||
|
default_options['offset_y'] = 0.05
|
||||||
|
|
||||||
|
options = aux.update_options(options=options, required_options=required_options, default_options=default_options)
|
||||||
|
#options['current_offset_y'] = options['offset_y']
|
||||||
|
|
||||||
|
# Convert data['path'] to list to allow iteration over this to accommodate both single and multiple diffractograms
|
||||||
|
if not isinstance(data['path'], list):
|
||||||
|
data['path'] = [data['path']]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Check if there is some data stored already, load in data if not. This speeds up replotting in interactive mode.
|
||||||
|
if not 'diffractogram' in data.keys():
|
||||||
|
# Initialise empty list for diffractograms and wavelengths
|
||||||
|
data['diffractogram'] = [None for _ in range(len(data['path']))]
|
||||||
|
data['wavelength'] = [None for _ in range(len(data['path']))]
|
||||||
|
|
||||||
|
for index in range(len(data['path'])):
|
||||||
|
diffractogram, wavelength = xrd.io.read_data(data=data, options=options, index=index)
|
||||||
|
|
||||||
|
data['diffractogram'][index] = diffractogram
|
||||||
|
data['wavelength'][index] = wavelength
|
||||||
|
|
||||||
|
# Sets the xlim if this has not bee specified
|
||||||
|
if not options['xlim']:
|
||||||
|
options['xlim'] = [data['diffractogram'][0][options['x_vals']].min(), data['diffractogram'][0][options['x_vals']].max()]
|
||||||
|
|
||||||
|
# Generate heatmap data
|
||||||
|
data['heatmap'], data['heatmap_xticks'], data['heatmap_xticklabels'] = generate_heatmap(data=data, options=options)
|
||||||
|
options['heatmap_loaded'] = True
|
||||||
|
|
||||||
|
if options['heatmap']:
|
||||||
|
options['xlim'] = options['heatmap_xlim']
|
||||||
|
|
||||||
|
else:
|
||||||
|
if not isinstance(data['diffractogram'], list):
|
||||||
|
data['diffractogram'] = [data['diffractogram']]
|
||||||
|
data['wavelength'] = [data['wavelength']]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if options['interactive_session_active']:
|
||||||
|
if options['offset']:
|
||||||
|
if (options['offset_x'] != options['current_offset_x']) or (options['offset_y'] != options['current_offset_y']):
|
||||||
|
for i, (diff, wl) in enumerate(zip(data['diffractogram'], data['wavelength'])):
|
||||||
|
xrd.io.apply_offset(diff, wl, i, options)
|
||||||
|
|
||||||
|
|
||||||
|
# Start inteactive session with ipywidgets. Disables options['interactive'] in order for the interactive loop to not start another interactive session
|
||||||
|
if options['interactive']:
|
||||||
|
options['interactive'] = False
|
||||||
|
options['interactive_session_active'] = True
|
||||||
|
plot_diffractogram_interactive(data=data, options=options)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
# Makes a list out of reflections_data if it only passed as a dict, as it will be looped through later
|
||||||
|
if options['reflections_data']:
|
||||||
|
if not isinstance(options['reflections_data'], list):
|
||||||
|
options['reflections_data'] = [options['reflections_data']]
|
||||||
|
|
||||||
|
# Determine number of subplots and height ratios between them
|
||||||
|
if len(options['reflections_data']) >= 1:
|
||||||
|
options = determine_grid_layout(options=options)
|
||||||
|
|
||||||
|
|
||||||
|
# Prepare plot, and read and process data
|
||||||
|
fig, ax = btp.prepare_plot(options=options)
|
||||||
|
|
||||||
|
|
||||||
|
# Assign the correct axes
|
||||||
|
if options['reflections_plot'] or options['reflections_indices']:
|
||||||
|
|
||||||
|
if options['reflections_indices']:
|
||||||
|
indices_ax = ax[0]
|
||||||
|
|
||||||
|
if options['reflections_plot']:
|
||||||
|
ref_axes = [axx for axx in ax[range(1,len(options['reflections_data'])+1)]]
|
||||||
|
|
||||||
|
else:
|
||||||
|
ref_axes = [axx for axx in ax[range(0,len(options['reflections_data']))]]
|
||||||
|
|
||||||
|
ax = ax[-1]
|
||||||
|
|
||||||
|
if len(data['path']) < 10:
|
||||||
|
colours = btp.generate_colours(options['palettes'])
|
||||||
|
else:
|
||||||
|
colours = btp.generate_colours(['black'], kind='single')
|
||||||
|
|
||||||
|
if options['heatmap']:
|
||||||
|
sns.heatmap(data['heatmap'], cmap=options['cmap'], cbar=False, ax=ax)
|
||||||
|
ax.set_xticks(data['heatmap_xticks'][options['x_vals']])
|
||||||
|
ax.set_xticklabels(data['heatmap_xticklabels'][options['x_vals']])
|
||||||
|
ax.tick_params(axis='x', which='minor', bottom=False, top=False)
|
||||||
|
|
||||||
|
else:
|
||||||
|
for diffractogram in data['diffractogram']:
|
||||||
|
if options['line']:
|
||||||
|
diffractogram.plot(x=options['x_vals'], y=options['y_vals'], ax=ax, c=next(colours), zorder=1)
|
||||||
|
|
||||||
|
if options['scatter']:
|
||||||
|
ax.scatter(x=diffractogram[options['x_vals']], y = diffractogram[options['y_vals']], c=[(1,1,1,0)], edgecolors=[next(colours)], linewidths=plt.rcParams['lines.markeredgewidth'], zorder=2) #, edgecolors=np.array([next(colours)]))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
fig, ax = btp.adjust_plot(fig=fig, ax=ax, options=options)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Make the reflection plots. By default, the wavelength of the first diffractogram will be used for these.
|
||||||
|
if options['reflections_plot'] and options['reflections_data']:
|
||||||
|
options['xlim'] = ax.get_xlim()
|
||||||
|
options['to_wavelength'] = data['wavelength'][0]
|
||||||
|
|
||||||
|
for reflections_params, axis in zip(options['reflections_data'], ref_axes):
|
||||||
|
plot_reflection_table(data=data, reflections_params=reflections_params, ax=axis, options=options)
|
||||||
|
|
||||||
|
# Print the reflection indices. By default, the wavelength of the first diffractogram will be used for this.
|
||||||
|
if options['reflections_indices'] and options['reflections_data']:
|
||||||
|
options['xlim'] = ax.get_xlim()
|
||||||
|
options['to_wavelength'] = data['wavelength'][0]
|
||||||
|
|
||||||
|
for reflections_params in options['reflections_data']:
|
||||||
|
plot_reflection_indices(data=data, reflections_params=reflections_params, ax=indices_ax, options=options)
|
||||||
|
|
||||||
|
|
||||||
|
if options['interactive_session_active']:
|
||||||
|
options['current_y_offset'] = options['widget'].kwargs['offset_y']
|
||||||
|
update_widgets(data=data, options=options)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return data['diffractogram'], fig, ax
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def generate_heatmap(data, options={}):
|
||||||
|
|
||||||
|
required_options = ['x_tick_locators']
|
||||||
|
|
||||||
|
default_options = {
|
||||||
|
'x_tick_locators': [0.5, 0.1]
|
||||||
|
}
|
||||||
|
|
||||||
|
options = aux.update_options(options=options, required_options=required_options, default_options=default_options)
|
||||||
|
|
||||||
|
twotheta = []
|
||||||
|
intensities = []
|
||||||
|
scans = []
|
||||||
|
|
||||||
|
for i, d in enumerate(data['diffractogram']):
|
||||||
|
twotheta = np.append(twotheta, d['2th'].to_numpy())
|
||||||
|
intensities = np.append(intensities, d['I'].to_numpy())
|
||||||
|
scans = np.append(scans, np.full(len(d['2th'].to_numpy()), int(i)))
|
||||||
|
|
||||||
|
|
||||||
|
heatmap = pd.DataFrame({'2th': twotheta, 'scan': scans, 'I': intensities})
|
||||||
|
xrd.io.translate_wavelengths(data=heatmap, wavelength=data['wavelength'][0])
|
||||||
|
min_dict = {'2th': heatmap['2th'].min(), '2th_cuka': heatmap['2th_cuka'].min(), '2th_moka': heatmap['2th_moka'].min(),
|
||||||
|
'q': heatmap['q'].min(), 'q2': heatmap['q2'].min(), 'q4': heatmap['q4'].min(), '1/d': heatmap['1/d'].min()}
|
||||||
|
|
||||||
|
max_dict = {'2th': heatmap['2th'].max(), '2th_cuka': heatmap['2th_cuka'].max(), '2th_moka': heatmap['2th_moka'].max(),
|
||||||
|
'q': heatmap['q'].max(), 'q2': heatmap['q2'].max(), 'q4': heatmap['q4'].max(), '1/d': heatmap['1/d'].max()}
|
||||||
|
|
||||||
|
|
||||||
|
ndatapoints = len(data['diffractogram'][0]['2th'])
|
||||||
|
|
||||||
|
xlims = [0, ndatapoints, 0, ndatapoints] # 0: xmin, 1: xmax, 2: xmin_start, 3: xmax_start
|
||||||
|
xticks = {}
|
||||||
|
xticklabels = {}
|
||||||
|
|
||||||
|
for xval in min_dict.keys():
|
||||||
|
|
||||||
|
# Add xticks labels
|
||||||
|
|
||||||
|
label_max = aux.floor(max_dict[xval], roundto=options['x_tick_locators'][0])
|
||||||
|
label_min = aux.ceil(min_dict[xval], roundto=options['x_tick_locators'][0])
|
||||||
|
label_steps = (label_max - label_min)/options['x_tick_locators'][0]
|
||||||
|
|
||||||
|
xticklabels[xval] = np.linspace(label_min, label_max, num=int(label_steps)+1)
|
||||||
|
|
||||||
|
# Add xticks
|
||||||
|
xval_span = max_dict[xval] - min_dict[xval]
|
||||||
|
steps = xval_span / ndatapoints
|
||||||
|
|
||||||
|
|
||||||
|
xticks_xval = []
|
||||||
|
|
||||||
|
for tick in xticklabels[xval]:
|
||||||
|
xticks_xval.append((tick-min_dict[xval])/steps)
|
||||||
|
|
||||||
|
xticks[xval] = xticks_xval
|
||||||
|
|
||||||
|
|
||||||
|
options['x_tick_locators'] = None
|
||||||
|
|
||||||
|
heatmap = heatmap.reset_index().pivot_table(index='scan', columns='2th', values='I')
|
||||||
|
|
||||||
|
options['heatmap_xlim'] = xlims
|
||||||
|
|
||||||
|
|
||||||
|
return heatmap, xticks, xticklabels
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# #results = np.transpose(np.vstack([twotheta, scans, intensities]))
|
||||||
|
|
||||||
|
|
||||||
|
def determine_grid_layout(options):
|
||||||
|
|
||||||
|
|
||||||
|
nrows = 1 if not options['reflections_indices'] else 2
|
||||||
|
|
||||||
|
if options['reflections_plot']:
|
||||||
|
for reference in options['reflections_data']:
|
||||||
|
nrows += 1
|
||||||
|
|
||||||
|
options['format_params']['nrows'] = nrows
|
||||||
|
options['format_params']['grid_ratio_height'] = [1 for i in range(nrows-1)]+[10]
|
||||||
|
|
||||||
|
return options
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def plot_diffractogram_interactive(data, options):
|
||||||
|
|
||||||
|
|
||||||
|
# Format here is xminmax[0]: xmin, xminmax[1]: xmax, xminmax[2]: xmin_start, xminmax[3]: xmax_start, where "_start" denotes starting value of the slider
|
||||||
|
xminmax = { '2th': [None, None, None, None], '2th_cuka': [None, None, None, None], '2th_moka': [None, None, None, None],
|
||||||
|
'd': [None, None, None, None], '1/d': [None, None, None, None],
|
||||||
|
'q': [None, None, None, None], 'q2': [None, None, None, None], 'q4': [None, None, None, None],
|
||||||
|
'heatmap': [None, None, None, None], 'start': [None, None, None, None]}
|
||||||
|
|
||||||
|
yminmax = { 'diff': [None, None, None, None], 'heatmap': [None, None, None, None], 'start': [None, None, None, None]}
|
||||||
|
|
||||||
|
update_xminmax(xminmax=xminmax, data=data, options=options)
|
||||||
|
update_yminmax(yminmax=yminmax, data=data, options=options)
|
||||||
|
|
||||||
|
options['xminmax'], options['yminmax'] = xminmax, yminmax
|
||||||
|
|
||||||
|
# Get start values for ylim slider based on choice (FIXME This can be impleneted into update_yminmax). Can also make a 'start' item that stores the start values, instead of having 4 items in 'diff' as it is now.
|
||||||
|
if options['heatmap']:
|
||||||
|
ymin = yminmax['heatmap'][0]
|
||||||
|
ymax = yminmax['heatmap'][1]
|
||||||
|
ymin_start = yminmax['heatmap'][0]
|
||||||
|
ymax_start = yminmax['heatmap'][1]
|
||||||
|
|
||||||
|
elif not options['heatmap']:
|
||||||
|
ymin = yminmax['diff'][0]
|
||||||
|
ymax = yminmax['diff'][1]
|
||||||
|
ymin_start = yminmax['diff'][2]
|
||||||
|
ymax_start = yminmax['diff'][3]
|
||||||
|
|
||||||
|
|
||||||
|
# FIXME The start values for xlim should probably also be decided by initial value of x_vals, and can likewise be implemented in update_xminmax()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
options['widgets'] = {
|
||||||
|
'xlim': {
|
||||||
|
'w': widgets.FloatRangeSlider(value=[xminmax['start'][2], xminmax['start'][3]], min=xminmax['start'][0], max=xminmax['start'][1], step=0.5, layout=widgets.Layout(width='95%')),
|
||||||
|
'state': options['x_vals'],
|
||||||
|
'2th_default': {'min': xminmax['2th'][0], 'max': xminmax['2th'][1], 'value': [xminmax['2th'][0], xminmax['2th'][1]], 'step': 0.5},
|
||||||
|
'2th_cuka_default': {'min': xminmax['2th_cuka'][0], 'max': xminmax['2th_cuka'][1], 'value': [xminmax['2th_cuka'][0], xminmax['2th_cuka'][1]], 'step': 0.5},
|
||||||
|
'2th_moka_default': {'min': xminmax['2th_moka'][0], 'max': xminmax['2th_moka'][1], 'value': [xminmax['2th_moka'][0], xminmax['2th_moka'][1]], 'step': 0.5},
|
||||||
|
'd_default': {'min': xminmax['d'][0], 'max': xminmax['d'][1], 'value': [xminmax['d'][0], xminmax['d'][1]], 'step': 0.5},
|
||||||
|
'1/d_default': {'min': xminmax['1/d'][0], 'max': xminmax['1/d'][1], 'value': [xminmax['1/d'][0], xminmax['1/d'][1]], 'step': 0.5},
|
||||||
|
'q_default': {'min': xminmax['q'][0], 'max': xminmax['q'][1], 'value': [xminmax['q'][0], xminmax['q'][1]], 'step': 0.5},
|
||||||
|
'q2_default': {'min': xminmax['q2'][0], 'max': xminmax['q2'][1], 'value': [xminmax['q2'][0], xminmax['q2'][1]], 'step': 0.5},
|
||||||
|
'q4_default': {'min': xminmax['q4'][0], 'max': xminmax['q4'][1], 'value': [xminmax['q4'][0], xminmax['q4'][1]], 'step': 0.5},
|
||||||
|
'heatmap_default': {'min': xminmax['heatmap'][0], 'max': xminmax['heatmap'][1], 'value': [xminmax['heatmap'][0], xminmax['heatmap'][1]], 'step': 10}
|
||||||
|
},
|
||||||
|
'ylim': {
|
||||||
|
'w': widgets.FloatRangeSlider(value=[yminmax['start'][2], yminmax['start'][3]], min=yminmax['start'][0], max=yminmax['start'][1], step=0.5, layout=widgets.Layout(width='95%')),
|
||||||
|
'state': 'heatmap' if options['heatmap'] else 'diff',
|
||||||
|
'diff_default': {'min': yminmax['diff'][0], 'max': yminmax['diff'][1], 'value': [yminmax['diff'][2], yminmax['diff'][3]], 'step': 0.1},
|
||||||
|
'heatmap_default': {'min': yminmax['heatmap'][0], 'max': yminmax['heatmap'][1], 'value': [yminmax['heatmap'][0], yminmax['heatmap'][1]], 'step': 0.1}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if options['reflections_data']:
|
||||||
|
w = widgets.interactive(btp.ipywidgets_update, func=widgets.fixed(plot_diffractogram), data=widgets.fixed(data), options=widgets.fixed(options),
|
||||||
|
scatter=widgets.ToggleButton(value=False),
|
||||||
|
line=widgets.ToggleButton(value=True),
|
||||||
|
reflections_plot=widgets.ToggleButton(value=True),
|
||||||
|
reflections_indices=widgets.ToggleButton(value=False),
|
||||||
|
heatmap=widgets.ToggleButton(value=options['heatmap']),
|
||||||
|
x_vals=widgets.Dropdown(options=['2th', 'd', '1/d', 'q', 'q2', 'q4', '2th_cuka', '2th_moka'], value='2th', description='X-values'),
|
||||||
|
xlim=options['widgets']['xlim']['w'],
|
||||||
|
ylim=options['widgets']['ylim']['w'],
|
||||||
|
offset_y=widgets.BoundedFloatText(value=options['offset_y'], min=-5, max=5, step=0.01, description='offset_y'),
|
||||||
|
offset_x=widgets.BoundedFloatText(value=options['offset_x'], min=-1, max=1, step=0.01, description='offset_x')
|
||||||
|
)
|
||||||
|
|
||||||
|
else:
|
||||||
|
w = widgets.interactive(btp.ipywidgets_update, func=widgets.fixed(plot_diffractogram), data=widgets.fixed(data), options=widgets.fixed(options),
|
||||||
|
scatter=widgets.ToggleButton(value=False),
|
||||||
|
line=widgets.ToggleButton(value=True),
|
||||||
|
xlim=options['widgets']['xlim']['w'])
|
||||||
|
|
||||||
|
|
||||||
|
options['widget'] = w
|
||||||
|
|
||||||
|
display(w)
|
||||||
|
|
||||||
|
|
||||||
|
def update_xminmax(xminmax, data, options={}):
|
||||||
|
''' Finds minimum and maximum values of each column and updates the minmax dictionary to contain the correct values.
|
||||||
|
|
||||||
|
Input:
|
||||||
|
minmax (dict): contains '''
|
||||||
|
|
||||||
|
xminmax['2th'] = [None, None, None, None]
|
||||||
|
for index, diffractogram in enumerate(data['diffractogram']):
|
||||||
|
|
||||||
|
if not xminmax['2th'][0] or diffractogram['2th'].min() < xminmax['2th'][0]:
|
||||||
|
xminmax['2th'][0] = diffractogram['2th'].min()
|
||||||
|
min_index = index
|
||||||
|
|
||||||
|
if not xminmax['2th'][1] or diffractogram['2th'].max() > xminmax['2th'][1]:
|
||||||
|
xminmax['2th'][1] = diffractogram['2th'].max()
|
||||||
|
max_index = index
|
||||||
|
|
||||||
|
|
||||||
|
xminmax['2th'][2], xminmax['2th'][3] = xminmax['2th'][0], xminmax['2th'][1]
|
||||||
|
|
||||||
|
xminmax['2th_cuka'][0], xminmax['2th_cuka'][1] = data['diffractogram'][min_index]['2th_cuka'].min(), data['diffractogram'][max_index]['2th_cuka'].max()
|
||||||
|
xminmax['2th_cuka'][2], xminmax['2th_cuka'][3] = xminmax['2th_cuka'][0], xminmax['2th_cuka'][1]
|
||||||
|
|
||||||
|
xminmax['2th_moka'][0], xminmax['2th_moka'][1] = data['diffractogram'][min_index]['2th_moka'].min(), data['diffractogram'][max_index]['2th_moka'].max()
|
||||||
|
xminmax['2th_moka'][2], xminmax['2th_moka'][3] = xminmax['2th_moka'][0], xminmax['2th_moka'][1]
|
||||||
|
|
||||||
|
xminmax['d'][0], xminmax['d'][1] = data['diffractogram'][max_index]['d'].min(), data['diffractogram'][min_index]['d'].max() # swapped, intended
|
||||||
|
xminmax['d'][2], xminmax['d'][3] = xminmax['d'][0], xminmax['d'][1]
|
||||||
|
|
||||||
|
xminmax['1/d'][0], xminmax['1/d'][1] = data['diffractogram'][min_index]['1/d'].min(), data['diffractogram'][max_index]['1/d'].max()
|
||||||
|
xminmax['1/d'][2], xminmax['1/d'][3] = xminmax['1/d'][0], xminmax['1/d'][1]
|
||||||
|
|
||||||
|
xminmax['q'][0], xminmax['q'][1] = data['diffractogram'][min_index]['q'].min(), data['diffractogram'][max_index]['q'].max()
|
||||||
|
xminmax['q'][2], xminmax['q'][3] = xminmax['q'][0], xminmax['q'][1]
|
||||||
|
|
||||||
|
xminmax['q2'][0], xminmax['q2'][1] = data['diffractogram'][min_index]['q2'].min(), data['diffractogram'][max_index]['q2'].max()
|
||||||
|
xminmax['q2'][2], xminmax['q2'][3] = xminmax['q2'][0], xminmax['q2'][1]
|
||||||
|
|
||||||
|
xminmax['q4'][0], xminmax['q4'][1] = data['diffractogram'][min_index]['q4'].min(), data['diffractogram'][max_index]['q4'].max()
|
||||||
|
xminmax['q4'][2], xminmax['q4'][3] = xminmax['q4'][0], xminmax['q4'][1]
|
||||||
|
|
||||||
|
|
||||||
|
xminmax['heatmap'] = options['heatmap_xlim'] # This value is set in the generate_heatmap()-function
|
||||||
|
|
||||||
|
|
||||||
|
xminmax['start'][0], xminmax['start'][1] = xminmax[options['x_vals']][0], xminmax[options['x_vals']][1]
|
||||||
|
xminmax['start'][2], xminmax['start'][3] = xminmax[options['x_vals']][2], xminmax[options['x_vals']][3]
|
||||||
|
|
||||||
|
|
||||||
|
def update_yminmax(yminmax: dict, data: dict, options={}) -> None:
|
||||||
|
|
||||||
|
yminmax['diff'] = [None, None, None, None]
|
||||||
|
# Go through diffractograms and find the minimum and maximum intensity values
|
||||||
|
for diffractogram in data['diffractogram']:
|
||||||
|
if not yminmax['diff'][0] or (yminmax['diff'][0] > (diffractogram['I'].min())):
|
||||||
|
yminmax['diff'][0] = diffractogram['I'].min()
|
||||||
|
|
||||||
|
if not yminmax['diff'][1] or (yminmax['diff'][1] < (diffractogram['I'].max())):
|
||||||
|
yminmax['diff'][1] = diffractogram['I'].max()
|
||||||
|
|
||||||
|
|
||||||
|
# Set start values of ymin and ymax to be slightly below lowest data points and slightly above highest data points to give some whitespace around the plot
|
||||||
|
yminmax['diff'][2] = yminmax['diff'][0] - 0.1*yminmax['diff'][1]
|
||||||
|
yminmax['diff'][3] = yminmax['diff'][1] + 0.2*yminmax['diff'][1]
|
||||||
|
|
||||||
|
# Allow for adjustment up to five times ymax above and below data
|
||||||
|
yminmax['diff'][0] = yminmax['diff'][0] - 5*yminmax['diff'][1]
|
||||||
|
yminmax['diff'][1] = yminmax['diff'][1]*5
|
||||||
|
|
||||||
|
|
||||||
|
# Set start values to the edges of the dataset
|
||||||
|
yminmax['heatmap'][0], yminmax['heatmap'][1] = 0, data['heatmap'].shape[0]
|
||||||
|
yminmax['heatmap'][2], yminmax['heatmap'][3] = yminmax['heatmap'][0], yminmax['heatmap'][1]
|
||||||
|
|
||||||
|
|
||||||
|
if options['heatmap']:
|
||||||
|
yminmax['start'][0], yminmax['start'][1] = yminmax['heatmap'][0], yminmax['heatmap'][1]
|
||||||
|
yminmax['start'][2], yminmax['start'][3] = yminmax['heatmap'][0], yminmax['heatmap'][1]
|
||||||
|
|
||||||
|
else:
|
||||||
|
# The third and fourth index are different here to not be zoomed completely out to begin with.
|
||||||
|
yminmax['start'][0], yminmax['start'][1] = yminmax['diff'][0], yminmax['diff'][1]
|
||||||
|
yminmax['start'][2], yminmax['start'][3] = yminmax['diff'][2], yminmax['diff'][3]
|
||||||
|
|
||||||
|
|
||||||
|
def update_defaults(widget: dict, minmax: dict) -> None:
|
||||||
|
''' Updates the default x- or y-limits of a given widget. Refer to plot_diffractogram_interactive() to see the form of the widget that is passed in. An update of the min/max-values is done just prior to calling this function.
|
||||||
|
Changes dictionaries in place.
|
||||||
|
|
||||||
|
Input:
|
||||||
|
widget (dict): A dictionary containing the widget itself (widget['w']) and all its default-values (e.g. widget['2th_default'])
|
||||||
|
minmax (dict): A dictionary containing min and max values, as well as min_start and max_start values. (e.g. minmax['2th'] is a list with four elements: [xmin, xmax, xmin_start, xmax_start])
|
||||||
|
|
||||||
|
Output:
|
||||||
|
None.'''
|
||||||
|
|
||||||
|
for name, attr in widget.items():
|
||||||
|
if name.endswith('default'):
|
||||||
|
attr['min'] = minmax[name.replace('_default', '')][0]
|
||||||
|
attr['max'] = minmax[name.replace('_default', '')][1]
|
||||||
|
attr['value'] = [minmax[name.replace('_default', '')][2], minmax[name.replace('_default', '')][3]]
|
||||||
|
|
||||||
|
|
||||||
|
def update_widgets(data, options):
|
||||||
|
|
||||||
|
|
||||||
|
for widget_name, widget in options['widgets'].items():
|
||||||
|
|
||||||
|
# Make changes to xlim-widget
|
||||||
|
if widget_name == 'xlim':
|
||||||
|
# First update the min and max values
|
||||||
|
update_xminmax(xminmax=options['xminmax'], data=data, options=options)
|
||||||
|
update_defaults(widget=widget, minmax=options['xminmax'])
|
||||||
|
|
||||||
|
|
||||||
|
if options['heatmap'] and (widget['state'] != 'heatmap'):
|
||||||
|
|
||||||
|
|
||||||
|
setattr(widget['w'], 'min', widget['heatmap_default']['min'])
|
||||||
|
setattr(widget['w'], 'max', widget['heatmap_default']['max'])
|
||||||
|
setattr(widget['w'], 'value', widget['heatmap_default']['value'])
|
||||||
|
setattr(widget['w'], 'step', widget['heatmap_default']['step'])
|
||||||
|
|
||||||
|
widget['state'] = 'heatmap'
|
||||||
|
|
||||||
|
elif not options['heatmap'] and (widget['state'] != options['x_vals']):
|
||||||
|
# Then loop through all attributes in the widget and change to current mode.
|
||||||
|
for arg in widget[f'{options["x_vals"]}_default']:
|
||||||
|
|
||||||
|
# If new min value is larger than previous max, or new max value is smaller than previous min, set the opposite first
|
||||||
|
if arg == 'min':
|
||||||
|
if widget[f'{options["x_vals"]}_default']['min'] > getattr(widget['w'], 'max'):
|
||||||
|
setattr(widget['w'], 'max', widget[f'{options["x_vals"]}_default']['max'])
|
||||||
|
|
||||||
|
elif arg == 'max':
|
||||||
|
if widget[f'{options["x_vals"]}_default']['max'] < getattr(widget['w'], 'min'):
|
||||||
|
setattr(widget['w'], 'min', widget[f'{options["x_vals"]}_default']['min'])
|
||||||
|
|
||||||
|
|
||||||
|
setattr(widget['w'], arg, widget[f'{options["x_vals"]}_default'][arg])
|
||||||
|
|
||||||
|
|
||||||
|
widget['state'] = options['x_vals']
|
||||||
|
|
||||||
|
# Make changes to ylim-widget
|
||||||
|
elif widget_name == 'ylim':
|
||||||
|
update_yminmax(yminmax=options['yminmax'], data=data, options=options)
|
||||||
|
update_defaults(widget=widget, minmax=options['yminmax'])
|
||||||
|
|
||||||
|
state = 'heatmap' if options['heatmap'] else 'diff'
|
||||||
|
|
||||||
|
if widget['state'] != state or options['offset_change']:
|
||||||
|
|
||||||
|
for arg in widget[f'{state}_default']:
|
||||||
|
# If new min value is larger than previous max, or new max value is smaller than previous min, set the opposite first
|
||||||
|
if arg == 'min':
|
||||||
|
if widget[f'{state}_default']['min'] > getattr(widget['w'], 'max'):
|
||||||
|
setattr(widget['w'], 'max', widget[f'{state}_default']['max'])
|
||||||
|
|
||||||
|
elif arg == 'max':
|
||||||
|
if widget[f'{state}_default']['max'] < getattr(widget['w'], 'min'):
|
||||||
|
setattr(widget['w'], 'min', widget[f'{state}_default']['min'])
|
||||||
|
|
||||||
|
|
||||||
|
setattr(widget['w'], arg, widget[f'{state}_default'][arg])
|
||||||
|
|
||||||
|
options['offset_change'] = False
|
||||||
|
widget['state'] = state
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def plot_reflection_indices(data, reflections_params, ax, options={}):
|
||||||
|
''' Print reflection indices from output generated by VESTA.
|
||||||
|
|
||||||
|
Required contents of data:
|
||||||
|
path (str): relative path to reflection table file'''
|
||||||
|
|
||||||
|
required_options = ['reflection_indices', 'text_colour', 'hide_indices']
|
||||||
|
|
||||||
|
default_options = {
|
||||||
|
'reflection_indices': 3, # Number of reflection indices to plot, from highest intensity and working its way down
|
||||||
|
'text_colour': 'black',
|
||||||
|
'hide_indices': False
|
||||||
|
}
|
||||||
|
|
||||||
|
reflections_params = aux.update_options(options=reflections_params, required_options=required_options, default_options=default_options)
|
||||||
|
|
||||||
|
if not reflections_params['hide_indices']:
|
||||||
|
reflection_table = xrd.io.load_reflection_table(data=data, reflections_params=reflections_params, options=options)
|
||||||
|
|
||||||
|
if reflections_params['reflection_indices'] > 0:
|
||||||
|
|
||||||
|
# Get the data['reflection_indices'] number of highest reflections within the subrange options['xlim']
|
||||||
|
x_vals = 'heatmap' if options['heatmap'] else options['x_vals']
|
||||||
|
reflection_indices = reflection_table.loc[(reflection_table[x_vals] > options['xlim'][0]) & (reflection_table[x_vals] < options['xlim'][1])].nlargest(options['reflection_indices'], 'I')
|
||||||
|
|
||||||
|
# Plot the indices
|
||||||
|
for i in range(reflections_params['reflection_indices']):
|
||||||
|
if reflection_indices.shape[0] > i:
|
||||||
|
ax.text(s=f'({reflection_indices["h"].iloc[i]} {reflection_indices["k"].iloc[i]} {reflection_indices["l"].iloc[i]})', x=reflection_indices[x_vals].iloc[i], y=0, fontsize=2.5, rotation=90, va='bottom', ha='center', c=reflections_params['text_colour'])
|
||||||
|
|
||||||
|
|
||||||
|
if options['xlim']:
|
||||||
|
ax.set_xlim(options['xlim'])
|
||||||
|
|
||||||
|
ax.axis('off')
|
||||||
|
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def plot_reflection_table(data, reflections_params, ax=None, options={}):
|
||||||
|
''' Plots a reflection table from output generated by VESTA.
|
||||||
|
|
||||||
|
Required contents of data:
|
||||||
|
path (str): relative path to reflection table file'''
|
||||||
|
|
||||||
|
required_options = ['reflection_indices', 'reflections_colour', 'min_alpha', 'wavelength', 'format_params', 'rc_params', 'label']
|
||||||
|
|
||||||
|
default_options = {
|
||||||
|
'reflection_indices': 0, # Number of indices to print
|
||||||
|
'reflections_colour': [0,0,0],
|
||||||
|
'min_alpha': 0,
|
||||||
|
'wavelength': 1.54059, # CuKalpha, [Å]
|
||||||
|
'format_params': {},
|
||||||
|
'rc_params': {},
|
||||||
|
'label': None
|
||||||
|
}
|
||||||
|
|
||||||
|
if 'colour' in data.keys():
|
||||||
|
options['reflections_colour'] = reflections_params['colour']
|
||||||
|
if 'min_alpha' in reflections_params.keys():
|
||||||
|
options['min_alpha'] = reflections_params['min_alpha']
|
||||||
|
if 'reflection_indices' in reflections_params.keys():
|
||||||
|
options['reflection_indices'] = reflections_params['reflection_indices']
|
||||||
|
if 'label' in reflections_params.keys():
|
||||||
|
options['label'] = reflections_params['label']
|
||||||
|
if 'wavelength' in reflections_params.keys():
|
||||||
|
options['wavelength'] = reflections_params['wavelength']
|
||||||
|
|
||||||
|
options = aux.update_options(options=options, required_options=required_options, default_options=default_options)
|
||||||
|
|
||||||
|
|
||||||
|
if not ax:
|
||||||
|
_, ax = btp.prepare_plot(options)
|
||||||
|
|
||||||
|
x_vals = 'heatmap' if options['heatmap'] else options['x_vals']
|
||||||
|
|
||||||
|
reflection_table = xrd.io.load_reflection_table(data=data, reflections_params=reflections_params, options=options)
|
||||||
|
reflections, intensities = reflection_table[x_vals], reflection_table['I']
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
colours = []
|
||||||
|
|
||||||
|
for ref, intensity in zip(reflections, intensities):
|
||||||
|
|
||||||
|
colour = list(options['reflections_colour'])
|
||||||
|
rel_intensity = (intensity / intensities.max())*(1-options['min_alpha']) + options['min_alpha']
|
||||||
|
colour.append(rel_intensity)
|
||||||
|
colours.append(colour)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ax.vlines(x=reflections, ymin=-1, ymax=1, colors=colours, lw=0.5)
|
||||||
|
ax.set_ylim([-0.5,0.5])
|
||||||
|
|
||||||
|
|
||||||
|
ax.tick_params(which='both', bottom=False, labelbottom=False, right=False, labelright=False, left=False, labelleft=False, top=False, labeltop=False)
|
||||||
|
|
||||||
|
if options['xlim']:
|
||||||
|
ax.set_xlim(options['xlim'])
|
||||||
|
|
||||||
|
|
||||||
|
if options['label']:
|
||||||
|
xlim_range = ax.get_xlim()[1] - ax.get_xlim()[0]
|
||||||
|
ylim_avg = (ax.get_ylim()[0]+ax.get_ylim()[1])/2
|
||||||
|
|
||||||
|
ax.text(s=reflections_params['label'], x=(ax.get_xlim()[0]-0.01*xlim_range), y=ylim_avg, ha = 'right', va = 'center')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def prettify_labels(label):
|
||||||
|
|
||||||
|
labels_dict = {
|
||||||
|
'2th': '2$\\theta$',
|
||||||
|
'I': 'Intensity'
|
||||||
|
}
|
||||||
|
|
||||||
|
return labels_dict[label]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def reverse_diffractograms(diffractograms):
|
||||||
|
|
||||||
|
rev_diffractograms = []
|
||||||
|
|
||||||
|
for i in len(diffractograms):
|
||||||
|
rev_diffractograms.append(diffractograms.pop())
|
||||||
|
|
||||||
|
return rev_diffractograms
|
||||||
|
|
||||||
|
#def plot_heatmap():
|
||||||
10
setup.py
10
setup.py
|
|
@ -1,11 +1,11 @@
|
||||||
from setuptools import setup, find_packages
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
setup(name='beamtime',
|
setup(name='nafuma',
|
||||||
version='0.1',
|
version='0.2',
|
||||||
description='Package for process and analysis of beamtime data from SNBL',
|
description='Analysis tools for inorganic materials chemistry at the NAFUMA-group at the University of Oslo',
|
||||||
url='http://github.uio.no/rasmusvt/beamtime',
|
url='https://github.com/rasmusthog/nafuma',
|
||||||
author='Rasmus Vester Thøgersen, Halvor Høen Hval',
|
author='Rasmus Vester Thøgersen, Halvor Høen Hval',
|
||||||
author_email='rasmusvt@smn.uio.no',
|
author_email='code@rasmusthog.me',
|
||||||
license='MIT',
|
license='MIT',
|
||||||
packages=find_packages(),
|
packages=find_packages(),
|
||||||
zip_safe=False)
|
zip_safe=False)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue