├── VERSION ├── MANIFEST.in ├── test ├── test_data │ ├── lena.h5 │ ├── reader.h5 │ ├── read_stack.h5 │ ├── test_0001.tiff │ ├── test_chip00.xrm │ ├── test_chip01.xrm │ ├── reader_00000.tiff │ ├── reader_00001.tiff │ ├── reader_00002.tiff │ ├── reader_00003.tiff │ ├── test_f32_0001.tiff │ ├── test_spots_0001.tiff │ ├── txrm_test_chip_tomo.txrm │ ├── .fuse_hidden00000c3f00000002 │ └── .fuse_hidden00000c4c00000003 ├── __init__.py └── test_dxchange │ ├── __init__.py │ ├── test_exchange.py │ ├── test_writer.py │ └── test_reader.py ├── envs ├── requirements-doc.txt └── requirements.txt ├── bld.bat ├── doc ├── source │ ├── demo │ │ ├── doc.demo.als.rst │ │ ├── doc.demo.esrf.rst │ │ ├── doc.demo.aps_1id.rst │ │ ├── doc.demo.anka.rst │ │ ├── doc.demo.aps_8bm.rst │ │ ├── doc.demo.elettra.rst │ │ ├── doc.demo.tomcat.rst │ │ ├── doc.demo.aps_13bm.rst │ │ ├── doc.demo.aps_26id.rst │ │ ├── doc.demo.xradia.rst │ │ ├── doc.demo.aps_5bm.rst │ │ ├── doc.demo.petraIII_p05.rst │ │ ├── doc.demo.aps_32id.rst │ │ └── doc.demo.australian.rst │ ├── api.rst │ ├── api │ │ ├── dxchange.writer.rst │ │ ├── dxchange.reader.rst │ │ └── dxchange.exchange.rst │ ├── credits.rst │ ├── demo.rst │ ├── install.rst │ └── bibtex │ │ ├── cite.bib │ │ └── ref.bib ├── demo │ ├── rec_als.py │ ├── rec_aps_1id.py │ ├── rec_esrf.py │ ├── rec_als_hdf5.py │ ├── rec_tomcat.py │ ├── rec_aps_32id_full.py │ ├── rec_aps_5bm.py │ ├── rec_aps_32id_chunk.py │ ├── rec_elettra.py │ ├── rec_petraIII.py │ ├── rec_australian.py │ ├── rec_aps_13bm.py │ ├── rec_anka.py │ ├── rec_aps_8bm.py │ ├── rec_aps_26id.py │ ├── rec_xradia_xrm.py │ ├── rec_aps_32id_blocked_projs.py │ └── __init__.py ├── index.rst ├── Makefile ├── make.bat └── conf.py ├── .readthedocs.yml ├── meta.yaml ├── setup.py ├── README.rst ├── .gitignore ├── LICENSE.txt └── dxchange ├── __init__.py ├── dtype.py ├── writer.py └── exchange.py /VERSION: -------------------------------------------------------------------------------- 1 | 0.2.0 2 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.rst 2 | include LICENSE.txt 3 | include VERSION 4 | -------------------------------------------------------------------------------- /test/test_data/lena.h5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-exchange/dxchange/HEAD/test/test_data/lena.h5 -------------------------------------------------------------------------------- /test/test_data/reader.h5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-exchange/dxchange/HEAD/test/test_data/reader.h5 -------------------------------------------------------------------------------- /envs/requirements-doc.txt: -------------------------------------------------------------------------------- 1 | sphinx <7 2 | sphinx_rtd_theme 3 | sphinxcontrib-bibtex 4 | nbsphinx 5 | pandoc 6 | jupyter -------------------------------------------------------------------------------- /test/test_data/read_stack.h5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-exchange/dxchange/HEAD/test/test_data/read_stack.h5 -------------------------------------------------------------------------------- /test/test_data/test_0001.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-exchange/dxchange/HEAD/test/test_data/test_0001.tiff -------------------------------------------------------------------------------- /test/test_data/test_chip00.xrm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-exchange/dxchange/HEAD/test/test_data/test_chip00.xrm -------------------------------------------------------------------------------- /test/test_data/test_chip01.xrm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-exchange/dxchange/HEAD/test/test_data/test_chip01.xrm -------------------------------------------------------------------------------- /test/test_data/reader_00000.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-exchange/dxchange/HEAD/test/test_data/reader_00000.tiff -------------------------------------------------------------------------------- /test/test_data/reader_00001.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-exchange/dxchange/HEAD/test/test_data/reader_00001.tiff -------------------------------------------------------------------------------- /test/test_data/reader_00002.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-exchange/dxchange/HEAD/test/test_data/reader_00002.tiff -------------------------------------------------------------------------------- /test/test_data/reader_00003.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-exchange/dxchange/HEAD/test/test_data/reader_00003.tiff -------------------------------------------------------------------------------- /test/test_data/test_f32_0001.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-exchange/dxchange/HEAD/test/test_data/test_f32_0001.tiff -------------------------------------------------------------------------------- /test/test_data/test_spots_0001.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-exchange/dxchange/HEAD/test/test_data/test_spots_0001.tiff -------------------------------------------------------------------------------- /test/test_data/txrm_test_chip_tomo.txrm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-exchange/dxchange/HEAD/test/test_data/txrm_test_chip_tomo.txrm -------------------------------------------------------------------------------- /test/test_data/.fuse_hidden00000c3f00000002: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-exchange/dxchange/HEAD/test/test_data/.fuse_hidden00000c3f00000002 -------------------------------------------------------------------------------- /test/test_data/.fuse_hidden00000c4c00000003: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/data-exchange/dxchange/HEAD/test/test_data/.fuse_hidden00000c4c00000003 -------------------------------------------------------------------------------- /envs/requirements.txt: -------------------------------------------------------------------------------- 1 | numpy 2 | scipy 3 | h5py>3.7 4 | netcdf4 5 | spefile 6 | edffile 7 | tifffile 8 | dxfile 9 | fnmatch 10 | pandas 11 | -------------------------------------------------------------------------------- /bld.bat: -------------------------------------------------------------------------------- 1 | "%PYTHON%" setup.py install 2 | if errorlevel 1 exit 1 3 | 4 | :: Add more build steps here, if they are necessary. 5 | 6 | :: See 7 | :: http://docs.continuum.io/conda/build.html 8 | :: for a list of environment variables that are set during the build process. 9 | -------------------------------------------------------------------------------- /doc/source/demo/doc.demo.als.rst: -------------------------------------------------------------------------------- 1 | ALS 8.3.2 2 | ========= 3 | 4 | This section contains a script to read the als 8.3.2 tomography dataset and reconstruct it with tomoPy. 5 | 6 | Download file: :download:`rec_als.py <../../../doc/demo/rec_als.py>` and 7 | :download:`rec_als_hdf5.py <../../../doc/demo/rec_als_hdf5.py>` 8 | -------------------------------------------------------------------------------- /doc/source/api.rst: -------------------------------------------------------------------------------- 1 | API reference 2 | ============= 3 | 4 | .. rubric:: **dxchange Modules:** 5 | 6 | .. toctree:: 7 | 8 | api/dxchange.exchange 9 | api/dxchange.reader 10 | api/dxchange.writer 11 | 12 | .. automodule:: dxchange 13 | :members: 14 | :undoc-members: 15 | :show-inheritance: 16 | :noindex: -------------------------------------------------------------------------------- /doc/source/demo/doc.demo.esrf.rst: -------------------------------------------------------------------------------- 1 | ESRF ID-19 2 | ========== 3 | 4 | This section contains a script to read the ESRF ID-19 tomography dataset and reconstruct it with tomoPy. 5 | 6 | Download file: :download:`rec_esrf.py <../../../doc/demo/rec_esrf.py>` 7 | 8 | .. literalinclude:: ../../../doc/demo/rec_esrf.py :tab-width: 4 :linenos: :language: guess 9 | 10 | -------------------------------------------------------------------------------- /doc/source/demo/doc.demo.aps_1id.rst: -------------------------------------------------------------------------------- 1 | APS 1-ID 2 | ======== 3 | 4 | This section contains a script to read the APS 1-ID tomography dataset and reconstruct it with tomoPy. 5 | 6 | Download file: :download:`rec_aps_1id.py <../../../doc/demo/rec_aps_1id.py>` 7 | 8 | .. literalinclude:: ../../../doc/demo/rec_aps_1id.py :tab-width: 4 :linenos: :language: guess 9 | 10 | -------------------------------------------------------------------------------- /doc/source/demo/doc.demo.anka.rst: -------------------------------------------------------------------------------- 1 | Anka TopoTomo 2 | ============== 3 | 4 | This section contains a script to read the Anka TopoTomo tomography dataset and reconstruct it with tomoPy. 5 | 6 | Download file: :download:`rec_anka.py <../../../doc/demo/rec_anka.py>` 7 | 8 | .. literalinclude:: ../../../doc/demo/rec_anka.py :tab-width: 4 :linenos: :language: guess 9 | 10 | -------------------------------------------------------------------------------- /doc/source/demo/doc.demo.aps_8bm.rst: -------------------------------------------------------------------------------- 1 | APS 8-BM 2 | ======== 3 | 4 | This section contains a script to read the X-radia XRM tomography dataset and reconstruct it with tomoPy. 5 | 6 | Download file: :download:`rec_aps_8bm.py <../../../doc/demo/rec_aps_8bm.py>` 7 | 8 | .. literalinclude:: ../../../doc/demo/rec_aps_8bm.py :tab-width: 4 :linenos: :language: guess 9 | 10 | -------------------------------------------------------------------------------- /doc/source/demo/doc.demo.elettra.rst: -------------------------------------------------------------------------------- 1 | Elettra Syrmep 2 | ============== 3 | 4 | This section contains a script to read the Elettra syrmep tomography dataset and reconstruct it with tomoPy. 5 | 6 | Download file: :download:`rec_elettra.py <../../../doc/demo/rec_elettra.py>` 7 | 8 | .. literalinclude:: ../../../doc/demo/rec_elettra.py :tab-width: 4 :linenos: :language: guess 9 | -------------------------------------------------------------------------------- /doc/source/demo/doc.demo.tomcat.rst: -------------------------------------------------------------------------------- 1 | SLS Tomcat 2 | ========== 3 | 4 | This section contains a script to read the Swiss Light Source tomcat tomography dataset and reconstruct it with tomoPy. 5 | 6 | Download file: :download:`rec_tomcat.py <../../../doc/demo/rec_tomcat.py>` 7 | 8 | .. literalinclude:: ../../../doc/demo/rec_tomcat.py :tab-width: 4 :linenos: :language: guess 9 | -------------------------------------------------------------------------------- /doc/source/demo/doc.demo.aps_13bm.rst: -------------------------------------------------------------------------------- 1 | APS 13-BM 2 | ========= 3 | 4 | This section contains a script to read the APS 13-BM tomography dataset and reconstruct it with tomoPy. 5 | 6 | Download file: :download:`rec_aps_13bm.py <../../../doc/demo/rec_aps_13bm.py>` 7 | 8 | .. literalinclude:: ../../../doc/demo/rec_aps_13bm.py :tab-width: 4 :linenos: :language: guess 9 | 10 | -------------------------------------------------------------------------------- /doc/source/demo/doc.demo.aps_26id.rst: -------------------------------------------------------------------------------- 1 | APS 26-ID 2 | ========= 3 | 4 | This section contains a script to read the X-radia XRM tomography dataset and reconstruct it with tomoPy. 5 | 6 | Download file: :download:`rec_aps_26id.py <../../../doc/demo/rec_aps_26id.py>` 7 | 8 | .. literalinclude:: ../../../doc/demo/rec_aps_26id.py :tab-width: 4 :linenos: :language: guess 9 | 10 | -------------------------------------------------------------------------------- /doc/source/demo/doc.demo.xradia.rst: -------------------------------------------------------------------------------- 1 | X-radia XRM 2 | =========== 3 | 4 | This section contains a script to read the X-radia XRM tomography dataset and reconstruct it with tomoPy. 5 | 6 | Download file: :download:`rec_xradia_xrm.py <../../../doc/demo/rec_xradia_xrm.py>` 7 | 8 | .. literalinclude:: ../../../doc/demo/rec_xradia_xrm.py :tab-width: 4 :linenos: :language: guess 9 | 10 | -------------------------------------------------------------------------------- /.readthedocs.yml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | version: 2 5 | sphinx: 6 | configuration: doc/conf.py 7 | python: 8 | install: 9 | - requirements: envs/requirements-doc.txt 10 | submodules: 11 | recursive: false 12 | build: 13 | os: ubuntu-22.04 14 | tools: 15 | python: "3" -------------------------------------------------------------------------------- /doc/source/demo/doc.demo.aps_5bm.rst: -------------------------------------------------------------------------------- 1 | APS 5-BM 2 | ======== 3 | 4 | This section contains a script to read the APS 5-BM tomography dataset and reconstruct it with tomoPy. 5 | 6 | Download file: :download:`rec_aps_5bm.py 7 | <../../../doc/demo/rec_aps_5bm.py>` 8 | 9 | .. literalinclude:: ../../../doc/demo/rec_aps_5bm.py 10 | :tab-width: 4 11 | :linenos: 12 | :language: guess 13 | 14 | -------------------------------------------------------------------------------- /doc/source/demo/doc.demo.petraIII_p05.rst: -------------------------------------------------------------------------------- 1 | Petra III P05 2 | ============= 3 | 4 | This section contains a script to read the Petra III P05 tomography dataset and reconstruct it with tomoPy. 5 | 6 | Download file: :download:`rec_petraIII.py <../../../doc/demo/rec_petraIII.py>` 7 | 8 | .. literalinclude:: ../../../doc/demo/rec_petraIII.py :tab-width: 4 :linenos: :language: guess 9 | 10 | -------------------------------------------------------------------------------- /doc/source/api/dxchange.writer.rst: -------------------------------------------------------------------------------- 1 | :mod:`dxchange.writer` 2 | ====================== 3 | 4 | .. automodule:: dxchange.writer 5 | :members: 6 | :show-inheritance: 7 | :undoc-members: 8 | 9 | .. rubric:: **Functions:** 10 | 11 | .. autosummary:: 12 | 13 | write_dxf 14 | write_hdf5 15 | write_npy 16 | write_tiff 17 | write_tiff_stack 18 | write_netcdf4 19 | -------------------------------------------------------------------------------- /doc/source/demo/doc.demo.aps_32id.rst: -------------------------------------------------------------------------------- 1 | APS 2-BM & 32-ID 2 | ================ 3 | 4 | This section contains a script to read the APS 2-BM and 32-ID tomography dataset and reconstruct it with tomoPy. 5 | 6 | Download file: :download:`rec_aps_32id_full.py <../../../doc/demo/rec_aps_32id_full.py>` 7 | 8 | .. literalinclude:: ../../../doc/demo/rec_aps_32id_full.py :tab-width: 4 :linenos: :language: guess 9 | 10 | -------------------------------------------------------------------------------- /doc/source/demo/doc.demo.australian.rst: -------------------------------------------------------------------------------- 1 | Australian Synchrotron 2 | ====================== 3 | 4 | This section contains a script to read the Australian Synchrotron Facility tomography dataset and reconstruct it with tomoPy. 5 | 6 | Download file: :download:`rec_australian.py <../../../doc/demo/rec_australian.py>` 7 | 8 | .. literalinclude:: ../../../doc/demo/rec_australian.py :tab-width: 4 :linenos: :language: guess 9 | 10 | -------------------------------------------------------------------------------- /doc/source/api/dxchange.reader.rst: -------------------------------------------------------------------------------- 1 | :mod:`dxchange.reader` 2 | ====================== 3 | 4 | .. automodule:: dxchange.reader 5 | :members: 6 | :show-inheritance: 7 | :undoc-members: 8 | 9 | .. rubric:: **Functions:** 10 | 11 | .. autosummary:: 12 | 13 | read_hdf_meta 14 | read_edf 15 | read_hdf5 16 | read_netcdf4 17 | read_npy 18 | read_spe 19 | read_fits 20 | read_tiff 21 | read_tiff_stack 22 | read_hdf5_stack 23 | read_xrm 24 | read_xrm_stack 25 | read_txrm 26 | -------------------------------------------------------------------------------- /doc/source/credits.rst: -------------------------------------------------------------------------------- 1 | ======= 2 | Credits 3 | ======= 4 | 5 | Citations 6 | ========= 7 | 8 | We kindly request that you cite the following article 9 | :cite:`DeCarlo:14a` if you use DXchange. 10 | 11 | .. bibliography:: bibtex/cite.bib 12 | :style: plain 13 | :labelprefix: A 14 | 15 | Code from `algotom `_ :cite:`Vo:21` was used in the reader read_hdf_meta to generate an hdf file tree 16 | 17 | 18 | Reference 19 | --------- 20 | 21 | .. bibliography:: bibtex/ref.bib 22 | :style: plain 23 | :labelprefix: B 24 | :all: 25 | -------------------------------------------------------------------------------- /doc/source/api/dxchange.exchange.rst: -------------------------------------------------------------------------------- 1 | :mod:`dxchange.exchange` 2 | ======================== 3 | 4 | .. automodule:: dxchange.exchange 5 | :members: 6 | :show-inheritance: 7 | :undoc-members: 8 | 9 | .. rubric:: **Functions:** 10 | 11 | .. autosummary:: 12 | 13 | read_als_832 14 | read_als_832h5 15 | read_anka_topotomo 16 | read_aps_1id 17 | read_aps_2bm 18 | read_aps_5bm 19 | read_aps_7bm 20 | read_aps_13bm 21 | read_aps_13id 22 | read_aps_26id 23 | read_aps_32id 24 | read_aus_microct 25 | read_diamond_l12 26 | read_elettra_syrmep 27 | read_esrf_id19 28 | read_lnls_imx 29 | read_petraIII_p05 30 | read_sls_tomcat 31 | 32 | -------------------------------------------------------------------------------- /meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: dxchange 3 | version: '0.1.9' 4 | 5 | source: 6 | git_url: https://github.com/data-exchange/dxchange.git 7 | 8 | build: 9 | number: 0 10 | 11 | requirements: 12 | build: 13 | - python 14 | - setuptools 15 | 16 | run: 17 | - python 18 | - numpy 19 | - scipy 20 | - h5py 21 | - netcdf4 22 | - spefile 23 | - edffile 24 | - tifffile 25 | - dxfile 26 | - pandas 27 | 28 | test: 29 | # Python imports 30 | imports: 31 | - dxchange 32 | - dxchange.reader 33 | - dxchange.writer 34 | - dxchange.exchange 35 | 36 | about: 37 | home: http://dxchange.readthedocs.org 38 | license: BSD-3 39 | summary: 'Data I/O for tomography.' 40 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from setuptools import setup 5 | 6 | setup( 7 | name='dxchange', 8 | author='Doga Gursoy, Francesco De Carlo', 9 | packages=['dxchange'], 10 | version=open('VERSION').read().strip(), 11 | description = 'Data I/O for tomography.', 12 | license='BSD-3', 13 | platforms='Any', 14 | classifiers=[ 15 | 'Development Status :: 4 - Beta', 16 | 'Intended Audience :: Science/Research', 17 | 'License :: BSD-3', 18 | 'Natural Language :: English', 19 | 'Programming Language :: Python :: 3', 20 | 'Programming Language :: Python :: 3.5', 21 | 'Programming Language :: Python :: 3.6', 22 | 'Programming Language :: Python :: 3.7', 23 | ], 24 | ) 25 | -------------------------------------------------------------------------------- /doc/source/demo.rst: -------------------------------------------------------------------------------- 1 | ======== 2 | Examples 3 | ======== 4 | 5 | Below are examples for reading tomographic data sets from different 6 | facilities and process them with TomoPy :cite:`Gursoy:14b`. 7 | 8 | .. toctree:: 9 | 10 | demo/doc.demo.anka 11 | demo/doc.demo.australian 12 | demo/doc.demo.als 13 | demo/doc.demo.elettra 14 | demo/doc.demo.esrf 15 | demo/doc.demo.aps_1id 16 | demo/doc.demo.aps_5bm 17 | demo/doc.demo.aps_8bm 18 | demo/doc.demo.aps_13bm 19 | demo/doc.demo.aps_26id 20 | demo/doc.demo.aps_32id 21 | demo/doc.demo.petraIII_p05 22 | demo/doc.demo.tomcat 23 | demo/doc.demo.xradia 24 | 25 | .. automodule:: dxchange 26 | :members: 27 | :undoc-members: 28 | :show-inheritance: 29 | 30 | For a repository of experimental and simulated data sets please check 31 | `TomoBank `_ :cite:`DeCarlo:17`. 32 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ======== 2 | DXchange 3 | ======== 4 | 5 | `DXchange `_ provides an interface with 6 | `TomoPy `_ and raw tomographic 7 | data collected at different synchrotron facilities including the Data Exchange 8 | file format (`DXfile `_), 9 | currently in use at the Advanced Photon Source beamline 2-BM and 32-ID, 10 | at the Swiss Light Source Tomcat beamline and at the Elettra SYRMEP beamline. 11 | 12 | Documentation 13 | ------------- 14 | * http://dxchange.readthedocs.io 15 | 16 | Features 17 | -------- 18 | 19 | * Scientific Data Exchange file format. 20 | * Readers for tomographic data files collected at different facilities. 21 | * Writers for different file formats. 22 | 23 | Highlights 24 | ---------- 25 | * Based on Hierarchical Data Format 5 (HDF5). 26 | * Focuses on technique rather than instrument descriptions. 27 | * Provenance tracking for understanding analysis steps and results. 28 | * Ease of readability. 29 | 30 | Contribute 31 | ---------- 32 | 33 | * Documentation: https://github.com/data-exchange/dxchange/tree/master/doc 34 | * Issue Tracker: https://github.com/data-exchange/dxchange/issues 35 | * Source Code: https://github.com/data-exchange/dxchange 36 | -------------------------------------------------------------------------------- /doc/source/install.rst: -------------------------------------------------------------------------------- 1 | ======= 2 | Install 3 | ======= 4 | 5 | This section covers the basics of how to download and install 6 | `DXchange `_. 7 | 8 | .. contents:: Contents: 9 | :local: 10 | 11 | 12 | Installing from source 13 | ====================== 14 | 15 | Clone the `DXchange `_ 16 | from `GitHub `_ repository:: 17 | 18 | git clone https://github.com/data-exchange/dxchange.git dxchange 19 | 20 | then:: 21 | 22 | cd dxchange 23 | pip install . 24 | 25 | DXchange is dependent on other libraries, listed in the requirements.txt and 26 | meta.yaml files. 27 | 28 | Installing from Conda/Binstar 29 | ============================= 30 | 31 | First you must have `Conda `_ 32 | installed, then open a terminal or a command prompt window and run:: 33 | 34 | conda install -c conda-forge dxchange 35 | 36 | 37 | Updating the installation 38 | ========================= 39 | 40 | Data Management is an active project, so we suggest you update your installation 41 | frequently. To update the installation run in your terminal:: 42 | 43 | conda update -c conda-forge dxchange 44 | 45 | For some more information about using Conda, please refer to the 46 | `docs `__. 47 | 48 | -------------------------------------------------------------------------------- /doc/demo/rec_als.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | TomoPy example script to reconstruct the ALS tomography 6 | beamline 8.3.2 data as original tiff. 7 | """ 8 | from __future__ import print_function 9 | import tomopy 10 | import dxchange 11 | 12 | 13 | if __name__ == '__main__': 14 | # Set path to the micro-CT data to reconstruct. 15 | fname = 'data_dir/sample_name' 16 | 17 | # Select the sinogram range to reconstruct. 18 | start = 0 19 | end = 16 20 | 21 | # Read the ALS raw data. 22 | proj, flat, dark = dxchange.read_als_832(fname, sino=(start, end)) 23 | 24 | # Set data collection angles as equally spaced between 0-180 degrees. 25 | theta = tomopy.angles(proj.shape[0], 0, 180) 26 | 27 | # Flat-field correction of raw data. 28 | proj = tomopy.normalize(proj, flat, dark) 29 | 30 | # Find rotation center. 31 | rot_center = tomopy.find_center(proj, theta, init=1024, ind=0, tol=0.5) 32 | print("Center of rotation:", rot_center) 33 | 34 | proj = tomopy.minus_log(proj) 35 | 36 | # Reconstruct object using Gridrec algorithm. 37 | rec = tomopy.recon(proj, theta, center=rot_center, algorithm='gridrec') 38 | 39 | # Mask each reconstructed slice with a circle. 40 | rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) 41 | 42 | # Write data as stack of TIFs. 43 | dxchange.write_tiff_stack(rec, fname='recon_dir/als') 44 | -------------------------------------------------------------------------------- /doc/demo/rec_aps_1id.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | TomoPy example script to reconstruct the APS 1-ID tomography data as original tiff. 6 | """ 7 | 8 | from __future__ import print_function 9 | import tomopy 10 | import dxchange 11 | 12 | if __name__ == '__main__': 13 | 14 | # Set path to the micro-CT data to reconstruct. 15 | fname = 'data_dir/sample_name_prefix' 16 | 17 | # Select the sinogram range to reconstruct. 18 | start = 0 19 | end = 16 20 | 21 | # Read the APS 1-ID raw data. 22 | proj, flat, dark = dxchange.read_aps_1id(fname, sino=(start, end)) 23 | 24 | # Set data collection angles as equally spaced between 0-180 degrees. 25 | theta = tomopy.angles(proj.shape[0]) 26 | 27 | # Flat-field correction of raw data. 28 | proj = tomopy.normalize(proj, flat, dark) 29 | 30 | # Find rotation center. 31 | rot_center = tomopy.find_center(proj, theta, init=1024, ind=0, tol=0.5) 32 | print("Center of rotation: ", rot_center) 33 | 34 | proj = tomopy.minus_log(proj) 35 | 36 | # Reconstruct object using Gridrec algorithm. 37 | rec = tomopy.recon(proj, theta, center=rot_center, algorithm='gridrec') 38 | 39 | # Mask each reconstructed slice with a circle. 40 | rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) 41 | 42 | # Write data as stack of TIFs. 43 | dxchange.write_tiff_stack(rec, fname='recon_dir/recon') 44 | -------------------------------------------------------------------------------- /doc/demo/rec_esrf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | TomoPy example script to reconstruct the ESRF tomography data as original edf 6 | files. 7 | """ 8 | 9 | from __future__ import print_function 10 | import tomopy 11 | import dxchange 12 | 13 | if __name__ == '__main__': 14 | # Set path to the micro-CT data to reconstruct. 15 | fname = 'data_dir/' 16 | 17 | # Select the sinogram range to reconstruct. 18 | start = 0 19 | end = 16 20 | 21 | # Read the ESRF ID-19 raw data. 22 | proj, flat, dark = dxchange.read_esrf_id19(fname, sino=(start, end)) 23 | 24 | # Set data collection angles as equally spaced between 0-180 degrees. 25 | theta = tomopy.angles(proj.shape[0]) 26 | 27 | # Flat-field correction of raw data. 28 | proj = tomopy.normalize(proj, flat, dark) 29 | 30 | # Find rotation center. 31 | rot_center = tomopy.find_center(proj, theta, init=1024, 32 | ind=0, tol=0.5) 33 | print("Center of rotation: ", rot_center) 34 | 35 | proj = tomopy.minus_log(proj) 36 | 37 | # Reconstruct object using Gridrec algorithm. 38 | rec = tomopy.recon(proj, theta, center=rot_center, algorithm='gridrec') 39 | 40 | # Mask each reconstructed slice with a circle. 41 | rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) 42 | 43 | # Write data as stack of TIFs. 44 | dxchange.write_tiff_stack(rec, fname='recon_dir/recon') 45 | -------------------------------------------------------------------------------- /doc/demo/rec_als_hdf5.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | TomoPy example script to reconstruct the ALS tomography 6 | beamline 8.3.2 data as original hdf5. 7 | """ 8 | from __future__ import print_function 9 | import tomopy 10 | import dxchange 11 | 12 | 13 | if __name__ == '__main__': 14 | # Set path to the micro-CT data to reconstruct. 15 | fname = 'data_dir/sample.h5' 16 | 17 | # Select the sinogram range to reconstruct. 18 | start = 0 19 | end = 16 20 | 21 | # Read the ALS raw data. 22 | proj, flat, dark, grp_flat = dxchange.read_als_832h5(fname, sino=(start, end)) 23 | 24 | # Set data collection angles as equally spaced between 0-180 degrees. 25 | theta = tomopy.angles(proj.shape[0], 0, 180) 26 | 27 | # Flat-field correction of raw data. 28 | proj = tomopy.normalize_nf(proj, flat, dark, grp_flat) 29 | 30 | # Find rotation center. 31 | rot_center = tomopy.find_center(proj, theta, init=1024, ind=0, tol=0.5) 32 | print("Center of rotation:", rot_center) 33 | 34 | proj = tomopy.minus_log(proj) 35 | 36 | # Reconstruct object using Gridrec algorithm. 37 | rec = tomopy.recon(proj, theta, center=rot_center, algorithm='gridrec') 38 | 39 | # Mask each reconstructed slice with a circle. 40 | rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) 41 | 42 | # Write data as stack of TIFs. 43 | dxchange.write_tiff_stack(rec, fname='recon_dir/als_h5') 44 | -------------------------------------------------------------------------------- /doc/demo/rec_tomcat.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | TomoPy example script to reconstruct the Swiss Light Source TOMCAT tomography 6 | data as original tiff. 7 | """ 8 | 9 | from __future__ import print_function 10 | import tomopy 11 | import dxchange 12 | 13 | if __name__ == '__main__': 14 | # Set path to the micro-CT data to reconstruct. 15 | fname = 'data_dir/sample_name_prefix' 16 | 17 | # Select the sinogram range to reconstruct. 18 | start = 0 19 | end = 16 20 | 21 | # Read the APS 1-ID raw data. 22 | proj, flat, dark = dxchange.read_sls_tomcat(fname, sino=(start, end)) 23 | 24 | # Set data collection angles as equally spaced between 0-180 degrees. 25 | theta = tomopy.angles(proj.shape[0], 0, 180) 26 | 27 | # Flat-field correction of raw data. 28 | proj = tomopy.normalize(proj, flat, dark) 29 | 30 | # Find rotation center. 31 | rot_center = tomopy.find_center(proj, theta, init=1024, 32 | ind=0, tol=0.5) 33 | print("Center of rotation:", rot_center) 34 | 35 | proj = tomopy.minus_log(proj) 36 | 37 | # Reconstruct object using Gridrec algorithm. 38 | rec = tomopy.recon(proj, theta, center=rot_center, algorithm='gridrec') 39 | 40 | # Mask each reconstructed slice with a circle. 41 | rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) 42 | 43 | # Write data as stack of TIFs. 44 | dxchange.write_tiff_stack(rec, fname='recon_dir/recon') 45 | -------------------------------------------------------------------------------- /doc/demo/rec_aps_32id_full.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | TomoPy example script to reconstruct TXM data set. 6 | """ 7 | 8 | from __future__ import print_function 9 | import tomopy 10 | import dxchange 11 | 12 | if __name__ == '__main__': 13 | 14 | # Set path to the micro-CT data to reconstruct. 15 | fname = 'data_dir/sample.h5' 16 | 17 | # Select sinogram range to reconstruct. 18 | start = 0 19 | end = 16 20 | 21 | # Read APS 32-ID raw data. 22 | proj, flat, dark, theta = dxchange.read_aps_32id(fname, sino=(start, end)) 23 | 24 | # If data collection angles is not defined in the hdf file then set it as equally spaced between 0-180 degrees. 25 | if (theta is None): 26 | theta = tomopy.angles(proj.shape[0]) 27 | else: 28 | pass 29 | 30 | # Flat-field correction of raw data. 31 | proj = tomopy.normalize(proj, flat, dark) 32 | 33 | # Find rotation center. 34 | rot_center = tomopy.find_center(proj, theta, ind=0, init=1024, tol=0.5) 35 | print("Center of rotation: ", rot_center) 36 | 37 | proj = tomopy.minus_log(proj) 38 | 39 | # Reconstruct object using Gridrec algorithm. 40 | rec = tomopy.recon(proj, theta, center=rot_center, algorithm='gridrec') 41 | 42 | # Mask each reconstructed slice with a circle. 43 | rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) 44 | 45 | # Write data as stack of TIFs. 46 | dxchange.write_tiff_stack(rec, fname='recon_dir/recon') 47 | -------------------------------------------------------------------------------- /doc/index.rst: -------------------------------------------------------------------------------- 1 | ======== 2 | DXchange 3 | ======== 4 | 5 | `DXchange `_ provides an interface with 6 | `TomoPy `_ :cite:`Gursoy:14b` and raw tomographic 7 | data collected at different synchrotron facilities including the Data Exchange 8 | file format (`DXfile `_) :cite:`DeCarlo:14a`, 9 | currently in use at the Advanced Photon Source beamline 2-BM and 32-ID, 10 | at the Swiss Light Source Tomcat beamline and at the Elettra SYRMEP beamline :cite:`Elettra:01`. 11 | 12 | .. warning:: DXchange will drop support for Python 2 before 1 January 2020. For more information, visit https://python3statement.org/. 13 | 14 | Features 15 | -------- 16 | 17 | * Scientific Data Exchange file format. 18 | * Readers for tomographic data files collected at different facilities. 19 | * Writers for different file formats. 20 | 21 | Highlights 22 | ---------- 23 | * Based on Hierarchical Data Format 5 (HDF5). 24 | * Focuses on technique rather than instrument descriptions. 25 | * Provenance tracking for understanding analysis steps and results. 26 | * Ease of readability. 27 | 28 | Contribute 29 | ---------- 30 | 31 | * Documentation: https://github.com/data-exchange/dxchange/tree/master/doc 32 | * Issue Tracker: https://github.com/data-exchange/dxchange/issues 33 | * Source Code: https://github.com/data-exchange/dxchange 34 | 35 | .. toctree:: 36 | :hidden: 37 | :maxdepth: 1 38 | 39 | source/install 40 | source/api 41 | source/demo 42 | source/credits 43 | -------------------------------------------------------------------------------- /doc/demo/rec_aps_5bm.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | TomoPy example script to reconstruct the APS 5-BM data as original xmt. 6 | xmt are 16 bit unsigned integer tiff file that requires a byte swap before 7 | being processed. 8 | """ 9 | 10 | from __future__ import print_function 11 | import tomopy 12 | import dxchange 13 | 14 | if __name__ == '__main__': 15 | 16 | # Set path to the micro-CT data to reconstruct. 17 | fname = 'data_dir/' 18 | 19 | # Select the sinogram range to reconstruct. 20 | start = 290 21 | end = 294 22 | 23 | # Read the APS 5-BM raw data 24 | proj, flat, dark = dxchange.read_aps_5bm(fname, sino=(start, end)) 25 | 26 | # Set data collection angles as equally spaced between 0-180 degrees. 27 | theta = tomopy.angles(proj.shape[0]) 28 | 29 | # Flat-field correction of raw data. 30 | proj = tomopy.normalize(proj, flat, dark) 31 | 32 | # remove stripes 33 | proj = tomopy.remove_stripe_fw(proj,level=7,wname='sym16',sigma=1,pad=True) 34 | 35 | # Set rotation center. 36 | rot_center = proj.shape[2] / 2.0 37 | print("Center of rotation: ", rot_center) 38 | 39 | proj = tomopy.minus_log(proj) 40 | 41 | # Reconstruct object using Gridrec algorithm. 42 | rec = tomopy.recon(proj, theta, center=rot_center, algorithm='gridrec') 43 | 44 | # Mask each reconstructed slice with a circle. 45 | rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) 46 | 47 | # Write data as stack of TIFs. 48 | dxchange.write_tiff_stack(rec, fname='recon_dir/recon') 49 | -------------------------------------------------------------------------------- /doc/demo/rec_aps_32id_chunk.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | TomoPy example script to reconstruct TXM data iteratively 6 | in chuck of sinogrmas. This function is for reconstructing large 7 | data on limited memory computers. 8 | """ 9 | 10 | from __future__ import print_function 11 | import tomopy 12 | import dxchange 13 | 14 | if __name__ == '__main__': 15 | 16 | # Set path to the micro-CT data to reconstruct 17 | fname = 'data_dir/sample.h5' 18 | 19 | # Select sinogram range to reconstruct. 20 | start = 512 21 | end = 2048 22 | 23 | # Set number of data chunks for the reconstruction. 24 | chunks = 64 25 | num_sino = (end - start) // chunks 26 | 27 | for m in range(chunks): 28 | sino_start = start + num_sino * m 29 | sino_end = start + num_sino * (m + 1) 30 | 31 | # Read APS 32-ID raw data. 32 | proj, flat, dark, theta = dxchange.read_aps_32id(fname, sino=(sino_start, sino_end)) 33 | 34 | # If data collection angles is not defined in the hdf file then set it as equally spaced between 0-180 degrees. 35 | if (theta is None): 36 | theta = tomopy.angles(proj.shape[0]) 37 | else: 38 | pass 39 | 40 | # Flat-field correction of raw data. 41 | proj = tomopy.normalize(proj, flat, dark) 42 | 43 | proj = tomopy.minus_log(proj) 44 | 45 | # Reconstruct object using Gridrec algorithm. 46 | rec = tomopy.recon(proj, theta, center=rot_center, algorithm='gridrec') 47 | 48 | # Write data as stack of TIFs. 49 | dxchange.write_tiff_stack(rec, fname='recon_dir/recon', start=sino_start) 50 | -------------------------------------------------------------------------------- /doc/demo/rec_elettra.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | TomoPy example script to reconstruct the Elettra syrmep data as original tiff. 6 | """ 7 | 8 | from __future__ import print_function 9 | import tomopy 10 | import dxchange 11 | 12 | if __name__ == '__main__': 13 | 14 | # Set path to the CT data to reconstruct. 15 | fname = 'data_dir/' 16 | 17 | proj_start = 1 18 | proj_end = 1801 19 | flat_start = 1 20 | flat_end = 11 21 | dark_start = 1 22 | dark_end = 11 23 | 24 | ind_tomo = range(proj_start, proj_end) 25 | ind_flat = range(flat_start, flat_end) 26 | ind_dark = range(dark_start, dark_end) 27 | 28 | # Select the sinogram range to reconstruct. 29 | start = 0 30 | end = 16 31 | 32 | # Read the Elettra syrmep 33 | proj, flat, dark = dxchange.read_elettra_syrmep(fname, ind_tomo, ind_flat, ind_dark, sino=(start, end)) 34 | 35 | # Set data collection angles as equally spaced between 0-180 degrees. 36 | theta = tomopy.angles(proj.shape[0], 0, 180) 37 | 38 | # Flat-field correction of raw data. 39 | proj = tomopy.normalize(proj, flat, dark) 40 | 41 | # Find rotation center. 42 | rot_center = tomopy.find_center(proj, theta, init=1024, ind=0, tol=0.5) 43 | print("Center of rotation: ", rot_center) 44 | 45 | proj = tomopy.minus_log(proj) 46 | 47 | # Reconstruct object using Gridrec algorithm. 48 | rec = tomopy.recon(proj, theta, center=rot_center, algorithm='gridrec') 49 | 50 | # Mask each reconstructed slice with a circle. 51 | rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) 52 | 53 | # Write data as stack of TIFs. 54 | dxchange.write_tiff_stack(rec, fname='recon_dir/recon') 55 | -------------------------------------------------------------------------------- /doc/demo/rec_petraIII.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | TomoPy example script to reconstruct the PetraIII P05 tomography data as original tiff. 6 | """ 7 | 8 | from __future__ import print_function 9 | import tomopy 10 | import dxchange 11 | 12 | if __name__ == '__main__': 13 | 14 | # Set path to the micro-CT data to reconstruct. 15 | fname = '/data_dir/sample_name00_0000/' 16 | 17 | proj_start = 0 18 | proj_end = 1441 19 | flat_start = 0 20 | flat_end = 20 21 | dark_start = 0 22 | dark_end = 20 23 | 24 | ind_tomo = range(proj_start, proj_end) 25 | ind_flat = range(flat_start, flat_end) 26 | ind_dark = range(dark_start, dark_end) 27 | 28 | # Select the sinogram range to reconstruct. 29 | start = 0 30 | end = 16 31 | 32 | # Read the Petra III P05 33 | proj, flat, dark = dxchange.read_petraIII_p05(fname, ind_tomo, ind_flat, ind_dark, sino=(start, end)) 34 | 35 | # Set data collection angles as equally spaced between 0-180 degrees. 36 | theta = tomopy.angles(proj.shape[0]) 37 | 38 | # Flat-field correction of raw data. 39 | proj = tomopy.normalize(proj, flat, dark) 40 | 41 | # Find rotation center. 42 | rot_center = tomopy.find_center(proj, theta, init=1024, ind=0, tol=0.5) 43 | print("Center of rotation: ", rot_center) 44 | 45 | proj = tomopy.minus_log(proj) 46 | 47 | # Reconstruct object using Gridrec algorithm. 48 | rec = tomopy.recon(proj, theta, center=rot_center, algorithm='gridrec') 49 | 50 | # Mask each reconstructed slice with a circle. 51 | rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) 52 | 53 | # Write data as stack of TIFs. 54 | dxchange.write_tiff_stack(rec, fname='recon_dir/petra_') 55 | -------------------------------------------------------------------------------- /doc/demo/rec_australian.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | TomoPy example script to reconstruct the Australian Synchrotron Facility 6 | data as original tiff. 7 | """ 8 | 9 | from __future__ import print_function 10 | import tomopy 11 | import dxchange 12 | 13 | if __name__ == '__main__': 14 | 15 | # Set path to the micro-CT data to reconstruct. 16 | fname = 'data_dir/' 17 | 18 | proj_start = 0 19 | proj_end = 1801 20 | flat_start = 0 21 | flat_end = 10 22 | dark_start = 0 23 | dark_end = 10 24 | 25 | ind_tomo = range(proj_start, proj_end) 26 | ind_flat = range(flat_start, flat_end) 27 | ind_dark = range(dark_start, dark_end) 28 | 29 | # Select the sinogram range to reconstruct. 30 | start = 290 31 | end = 294 32 | 33 | # Read the Australian Synchrotron Facility data 34 | proj, flat, dark = dxchange.read_aus_microct(fname, ind_tomo, ind_flat, ind_dark, sino=(start, end)) 35 | 36 | # Set data collection angles as equally spaced between 0-180 degrees. 37 | theta = tomopy.angles(proj.shape[0]) 38 | 39 | # Flat-field correction of raw data. 40 | proj = tomopy.normalize(proj, flat, dark) 41 | 42 | # Find rotation center. 43 | rot_center = tomopy.find_center(proj, theta, init=1024, ind=0, tol=0.5) 44 | print("Center of rotation: ", rot_center) 45 | 46 | proj = tomopy.minus_log(proj) 47 | 48 | # Reconstruct object using Gridrec algorithm. 49 | rec = tomopy.recon(proj, theta, center=rot_center, algorithm='gridrec') 50 | 51 | # Mask each reconstructed slice with a circle. 52 | rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) 53 | 54 | # Write data as stack of TIFs. 55 | dxchange.write_tiff_stack(rec, fname='recon_dir/aus_') 56 | -------------------------------------------------------------------------------- /doc/demo/rec_aps_13bm.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | TomoPy example script to reconstruct the APS 13-BM tomography 6 | data as original netcdf files. To use, change fname to just 7 | the file name (e.g. 'sample[2].nc' would be 'sample'. 8 | Reconstructed dataset will be saved as float32 netcdf3. 9 | """ 10 | import glob 11 | import numpy as np 12 | import tomopy as tp 13 | import dxchange as dx 14 | 15 | from netCDF4 import Dataset 16 | 17 | if __name__ == '__main__': 18 | ## Set path (without file suffix) to the micro-CT data to reconstruct. 19 | fname = 'data_dir/sample' 20 | 21 | ## Import Data. 22 | proj, flat, dark, theta = dx.exchange.read_aps_13bm(fname, format = 'netcdf4') 23 | 24 | ## Flat-field correction of raw data. 25 | proj = tp.normalize(proj, flat = flat, dark = dark) 26 | 27 | ## Additional flat-field correction of raw data to negate need to mask. 28 | proj = tp.normalize_bg(proj, air = 10) 29 | 30 | ## Set rotation center. 31 | rot_center = tp.find_center_vo(proj) 32 | print('Center of rotation: ', rot_center) 33 | 34 | tp.minus_log(proj, out = proj) 35 | 36 | # Reconstruct object using Gridrec algorith. 37 | rec = tp.recon(proj, theta, center = rot_center, sinogram_order = False, algorithm = 'gridrec', filter_name = 'hann') 38 | rec = tp.remove_nan(rec) 39 | 40 | ## Writing data in netCDF3 .volume. 41 | ncfile = Dataset('filename.volume', 'w', format = 'NETCDF3_64BIT', clobber = True) 42 | NX = ncfile.createDimension('NX', rec.shape[2]) 43 | NY = ncfile.createDimension('NY', rec.shape[1]) 44 | NZ = ncfile.createDimension('NZ', rec.shape[0]) 45 | volume = ncfile.createVariable('VOLUME', 'f4', ('NZ','NY','NX')) 46 | volume[:] = rec 47 | ncfile.close() 48 | -------------------------------------------------------------------------------- /doc/demo/rec_anka.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | TomoPy example script to reconstruct the Anka topo-tomo tomography data as 6 | original tiff. 7 | """ 8 | 9 | from __future__ import print_function 10 | import tomopy 11 | import dxchange 12 | 13 | if __name__ == '__main__': 14 | # Set path to the micro-CT data to reconstruct. 15 | fname = 'data_dir/' 16 | 17 | proj_start = 0 18 | proj_end = 1800 19 | flat_start = 0 20 | flat_end = 100 21 | dark_start = 0 22 | dark_end = 100 23 | 24 | ind_tomo = range(proj_start, proj_end) 25 | ind_flat = range(flat_start, flat_end) 26 | ind_dark = range(dark_start, dark_end) 27 | 28 | # Select the sinogram range to reconstruct. 29 | start = 0 30 | end = 16 31 | 32 | # Read the Anka tiff raw data. 33 | proj, flat, dark = dxchange.read_anka_topotomo(fname, ind_tomo, ind_flat, 34 | ind_dark, sino=(start, end)) 35 | 36 | # Set data collection angles as equally spaced between 0-180 degrees. 37 | theta = tomopy.angles(proj.shape[0]) 38 | 39 | # Flat-field correction of raw data. 40 | proj = tomopy.normalize(proj, flat, dark) 41 | 42 | # Find rotation center. 43 | rot_center = tomopy.find_center(proj, theta, init=1024, 44 | ind=0, tol=0.5) 45 | print("Center of rotation: ", rot_center) 46 | 47 | proj = tomopy.minus_log(proj) 48 | 49 | # Reconstruct object using Gridrec algorithm. 50 | rec = tomopy.recon(proj, theta, center=rot_center, algorithm='gridrec') 51 | 52 | # Mask each reconstructed slice with a circle. 53 | rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) 54 | 55 | # Write data as stack of TIFs. 56 | dxchange.write_tiff_stack(rec, fname='recon_dir/recon') 57 | -------------------------------------------------------------------------------- /doc/demo/rec_aps_8bm.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | TomoPy example script to reconstruct the xrm tomography data from 6 | the original stack of xrm. To use rename the xrm data as 7 | radios/image_00000.xrm and flats/ref_00000.xrm 8 | """ 9 | 10 | from __future__ import print_function 11 | import tomopy 12 | import dxchange 13 | 14 | if __name__ == '__main__': 15 | # Set path to the micro-CT data to reconstruct. 16 | fname = 'data_dir/' 17 | 18 | proj_start = 0 19 | proj_end = 1800 20 | flat_start = 0 21 | flat_end = 100 22 | 23 | ind_tomo = range(proj_start, proj_end) 24 | ind_flat = range(flat_start, flat_end) 25 | 26 | # Select the sinogram range to reconstruct. 27 | start = 0 28 | end = 16 29 | 30 | # Read the APS 8-BM raw data. 31 | proj, flat, metadata = dxchange.read_aps_8bm(fname, ind_tomo, ind_flat, 32 | sino=(start, end)) 33 | 34 | # make the darks 35 | dark = np.zeros((1, proj.shape[1], proj.shape[2])) 36 | 37 | # Set data collection angles as equally spaced between 0-180 degrees. 38 | theta = tomopy.angles(proj.shape[0]) 39 | 40 | # Flat-field correction of raw data. 41 | proj = tomopy.normalize(proj, flat, dark) 42 | 43 | # Find rotation center. 44 | rot_center = tomopy.find_center(proj, theta, init=1024, 45 | ind=0, tol=0.5) 46 | print("Center of rotation: ", rot_center) 47 | 48 | proj = tomopy.minus_log(proj) 49 | 50 | # Reconstruct object using Gridrec algorithm. 51 | rec = tomopy.recon(proj, theta, center=rot_center, algorithm='gridrec') 52 | 53 | # Mask each reconstructed slice with a circle. 54 | rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) 55 | 56 | # Write data as stack of TIFs. 57 | dxchange.write_tiff_stack(rec, fname='recon_dir/recon') 58 | -------------------------------------------------------------------------------- /doc/demo/rec_aps_26id.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | TomoPy example script to reconstruct the xrm tomography data from 6 | the original stack of xrm. To use rename the xrm data as 7 | radios/image_00000.xrm and flats/ref_00000.xrm 8 | """ 9 | 10 | from __future__ import print_function 11 | import tomopy 12 | import dxchange 13 | 14 | if __name__ == '__main__': 15 | # Set path to the micro-CT data to reconstruct. 16 | fname = 'data_dir/' 17 | 18 | proj_start = 0 19 | proj_end = 1800 20 | flat_start = 0 21 | flat_end = 100 22 | 23 | ind_tomo = range(proj_start, proj_end) 24 | ind_flat = range(flat_start, flat_end) 25 | 26 | # Select the sinogram range to reconstruct. 27 | start = 0 28 | end = 16 29 | 30 | # Read the APS 26-ID raw data. 31 | proj, flat, metadata = dxchange.read_aps_26id(fname, ind_tomo, ind_flat, 32 | sino=(start, end)) 33 | 34 | # make the darks 35 | dark = np.zeros((1, proj.shape[1], proj.shape[2])) 36 | 37 | # Set data collection angles as equally spaced between 0-180 degrees. 38 | theta = tomopy.angles(proj.shape[0]) 39 | 40 | # Flat-field correction of raw data. 41 | proj = tomopy.normalize(proj, flat, dark) 42 | 43 | # Find rotation center. 44 | rot_center = tomopy.find_center(proj, theta, init=1024, 45 | ind=0, tol=0.5) 46 | print("Center of rotation: ", rot_center) 47 | 48 | proj = tomopy.minus_log(proj) 49 | 50 | # Reconstruct object using Gridrec algorithm. 51 | rec = tomopy.recon(proj, theta, center=rot_center, algorithm='gridrec') 52 | 53 | # Mask each reconstructed slice with a circle. 54 | rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) 55 | 56 | # Write data as stack of TIFs. 57 | dxchange.write_tiff_stack(rec, fname='recon_dir/recon') 58 | -------------------------------------------------------------------------------- /doc/demo/rec_xradia_xrm.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | TomoPy example script to reconstruct the xrm tomography data from 6 | the original stack of xrm. To use rename the xrm data as 7 | radios/image_00000.xrm and flats/ref_00000.xrm 8 | """ 9 | 10 | from __future__ import print_function 11 | import tomopy 12 | import dxchange 13 | 14 | if __name__ == '__main__': 15 | # Set path to the micro-CT data to reconstruct. 16 | fname = 'data_dir/' 17 | 18 | proj_start = 0 19 | proj_end = 1800 20 | flat_start = 0 21 | flat_end = 100 22 | 23 | ind_tomo = range(proj_start, proj_end) 24 | ind_flat = range(flat_start, flat_end) 25 | 26 | # Select the sinogram range to reconstruct. 27 | start = 0 28 | end = 16 29 | 30 | # APS 26-ID has an x-radia system collecting raw data as xrm. 31 | proj, flat, metadata = dxchange.read_aps_26id(fname, ind_tomo, ind_flat, 32 | sino=(start, end)) 33 | 34 | # make the darks 35 | dark = np.zeros((1, proj.shape[1], proj.shape[2])) 36 | 37 | # Set data collection angles as equally spaced between 0-180 degrees. 38 | theta = tomopy.angles(proj.shape[0]) 39 | 40 | # Flat-field correction of raw data. 41 | proj = tomopy.normalize(proj, flat, dark) 42 | 43 | # Find rotation center. 44 | rot_center = tomopy.find_center(proj, theta, init=1024, 45 | ind=0, tol=0.5) 46 | print("Center of rotation: ", rot_center) 47 | 48 | proj = tomopy.minus_log(proj) 49 | 50 | # Reconstruct object using Gridrec algorithm. 51 | rec = tomopy.recon(proj, theta, center=rot_center, algorithm='gridrec') 52 | 53 | # Mask each reconstructed slice with a circle. 54 | rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) 55 | 56 | # Write data as stack of TIFs. 57 | dxchange.write_tiff_stack(rec, fname='recon_dir/recon') 58 | -------------------------------------------------------------------------------- /doc/demo/rec_aps_32id_blocked_projs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | TomoPy example script to reconstruct a TXM data containing 6 | a series of useless projections becuase of the presence of an 7 | environment cell blocking some of the sample views. 8 | """ 9 | 10 | from __future__ import print_function 11 | import tomopy 12 | import dxchange 13 | import numpy as np 14 | 15 | if __name__ == '__main__': 16 | 17 | # Set path to the micro-CT data set to reconstruct. 18 | fname = 'data_dir/sample.h5' 19 | 20 | # Set the [start, end] index of the blocked projections. 21 | miss_projs = [128, 256] 22 | 23 | # Select sinogram range to reconstruct. 24 | start = 512 25 | end = 2048 26 | 27 | # Set number of data chunks for the reconstruction. 28 | chunks = 64 29 | num_sino = (end - start) // chunks 30 | 31 | for m in range(chunks): 32 | sino_start = start + num_sino * m 33 | sino_end = start + num_sino * (m + 1) 34 | 35 | # Read APS 32-ID raw data. 36 | proj, flat, dark, theta = dxchange.read_aps_32id(fname, sino=(sino_start, sino_end)) 37 | 38 | # If data collection angles is not defined in the hdf file then set it as equally spaced between 0-180 degrees. 39 | if (theta is None): 40 | theta = tomopy.angles(proj.shape[0]) 41 | else: 42 | pass 43 | 44 | # Remove the missing angles from data. 45 | proj = np.concatenate((proj[0:miss_projs[0], :, :], proj[miss_projs[1] + 1:-1, :, :]), axis=0) 46 | theta = np.concatenate((theta[0:miss_projs[0]], theta[miss_projs[1] + 1:-1])) 47 | 48 | # Flat-field correction of raw data. 49 | proj = tomopy.normalize(proj, flat, dark) 50 | 51 | proj = tomopy.minus_log(proj) 52 | 53 | # Reconstruct object using Gridrec algorithm. 54 | rec = tomopy.recon(proj, theta, center=rot_center, algorithm='gridrec') 55 | 56 | # Write data as stack of TIFs. 57 | dxchange.write_tiff_stack(rec, fname='recon_dir/recon', start=sino_start) 58 | 59 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files # 2 | ######################################### 3 | __pycache__/ 4 | *.py[cod] 5 | 6 | # Compiled source # 7 | ################### 8 | *.com 9 | *.class 10 | *.dll 11 | *.exe 12 | *.o 13 | *.so 14 | 15 | # Packages # 16 | ############ 17 | # it's better to unpack these files and commit the raw source 18 | # git has its own built in compression methods 19 | *.7z 20 | *.dmg 21 | *.gz 22 | *.iso 23 | *.jar 24 | *.rar 25 | *.tar 26 | *.zip 27 | 28 | # Logs and databases # 29 | ###################### 30 | *.log 31 | *.sql 32 | *.sqlite 33 | 34 | # OS generated files # 35 | ###################### 36 | .DS_Store 37 | .DS_Store? 38 | ._* 39 | .Spotlight-V100 40 | .Trashes 41 | ehthumbs.db 42 | Thumbs.db 43 | .spyderworkspace 44 | *.*~ 45 | *~ 46 | 47 | # Python pyproducts # 48 | ##################### 49 | *.pyc 50 | build 51 | dist 52 | docs/_build 53 | doc/_build 54 | *egg-info 55 | *.egg 56 | .settings 57 | 58 | # LaTex generated files # 59 | ######################### 60 | *.aux 61 | *.cls 62 | *.layout 63 | *.bst 64 | *.lof 65 | *.toc 66 | *.out 67 | *.bbl 68 | *.blg 69 | 70 | # Test files # 71 | ############## 72 | test.py 73 | main.py 74 | 75 | # Distribution / packaging # 76 | ############################ 77 | bin/ 78 | build/ 79 | develop-eggs/ 80 | dist/ 81 | eggs/ 82 | lib/ 83 | lib64/ 84 | parts/ 85 | sdist/ 86 | var/ 87 | .installed.cfg 88 | 89 | # Installer logs # 90 | ################## 91 | pip-log.txt 92 | 93 | # Unit test / coverage reports # 94 | ################################ 95 | .tox/ 96 | .coverage 97 | .cache 98 | nosetests.xml 99 | coverage.xml 100 | 101 | # Translations # 102 | ################ 103 | *.mo 104 | 105 | # Mr Developer # 106 | ################ 107 | .mr.developer.cfg 108 | .project 109 | .pydevproject 110 | *.sublime-project 111 | *.sublime-workspace 112 | docs/trunk/* 113 | .spyder* 114 | .idea 115 | 116 | # Francesco's # 117 | ################ 118 | tmp/ 119 | tmp2/ 120 | validate* 121 | workingOn/ 122 | #rec_* 123 | -------------------------------------------------------------------------------- /doc/source/bibtex/cite.bib: -------------------------------------------------------------------------------- 1 | @article{DeCarlo:14a, 2 | author = {De Carlo F and Gursoy D and Marone F and Rivers M and Parkinson YD and Khan F and Schwarz N and Vine DJ and Vogt S and Gleber SC and Narayanan S and Newville M and Lanzirotti T and Sun Y and Hong YP and Jacobsen C}, 3 | title = {Scientific Data Exchange: a schema for HDF5-based storage of raw and analyzed data}, 4 | journal = {Journal of Synchrotron Radiation}, 5 | year = {2014}, 6 | volume = {21}, 7 | number = {6}, 8 | pages = {1224--1230} 9 | } 10 | 11 | @article{Vo:21, 12 | author = {Nghia T. Vo and Robert C. Atwood and Michael Drakopoulos and Thomas Connolley}, 13 | journal = {Opt. Express}, 14 | keywords = {Digital image processing; Fluorescence tomography; Image processing; Image registration; Phase retrieval; Phase shift}, 15 | number = {12}, 16 | pages = {17849--17874}, 17 | publisher = {OSA}, 18 | title = {Data processing methods and data acquisition for samples larger than the field of view in parallel-beam tomography}, 19 | volume = {29}, 20 | month = {Jun}, 21 | year = {2021}, 22 | url = {http://www.opticsexpress.org/abstract.cfm?URI=oe-29-12-17849}, 23 | doi = {10.1364/OE.418448}, 24 | abstract = {Parallel-beam tomography systems at synchrotron facilities have limited field of view (FOV) determined by the available beam size and detector system coverage. Scanning the full size of samples bigger than the FOV requires various data acquisition schemes such as grid scan, 360-degree scan with offset center-of-rotation (COR), helical scan, or combinations of these schemes. Though straightforward to implement, these scanning techniques have not often been used due to the lack of software and methods to process such types of data in an easy and automated fashion. The ease of use and automation is critical at synchrotron facilities where using visual inspection in data processing steps such as image stitching, COR determination, or helical data conversion is impractical due to the large size of datasets. Here, we provide methods and their implementations in a Python package, named Algotom, for not only processing such data types but also with the highest quality possible. The efficiency and ease of use of these tools can help to extend applications of parallel-beam tomography systems.}, 25 | } -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, UChicago Argonne, LLC. All rights reserved. 2 | 3 | Copyright 2016. UChicago Argonne, LLC. This software was produced 4 | under U.S. Government contract DE-AC02-06CH11357 for Argonne National 5 | Laboratory (ANL), which is operated by UChicago Argonne, LLC for the 6 | U.S. Department of Energy. The U.S. Government has rights to use, 7 | reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR 8 | UChicago Argonne, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR 9 | ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is 10 | modified to produce derivative works, such modified software should 11 | be clearly marked, so as not to confuse it with the version available 12 | from ANL. 13 | 14 | Additionally, redistribution and use in source and binary forms, with 15 | or without modification, are permitted provided that the following 16 | conditions are met: 17 | 18 | * Redistributions of source code must retain the above copyright 19 | notice, this list of conditions and the following disclaimer. 20 | 21 | * Redistributions in binary form must reproduce the above copyright 22 | notice, this list of conditions and the following disclaimer in 23 | the documentation and/or other materials provided with the 24 | distribution. 25 | 26 | * Neither the name of UChicago Argonne, LLC, Argonne National 27 | Laboratory, ANL, the U.S. Government, nor the names of its 28 | contributors may be used to endorse or promote products derived 29 | from this software without specific prior written permission. 30 | 31 | THIS SOFTWARE IS PROVIDED BY UChicago Argonne, LLC AND CONTRIBUTORS 32 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 34 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UChicago 35 | Argonne, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 36 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 37 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 38 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 39 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 40 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 41 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42 | POSSIBILITY OF SUCH DAMAGE. 43 | -------------------------------------------------------------------------------- /doc/demo/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # ######################################################################### 5 | # Copyright (c) 2015, UChicago Argonne, LLC. All rights reserved. # 6 | # # 7 | # Copyright 2015. UChicago Argonne, LLC. This software was produced # 8 | # under U.S. Government contract DE-AC02-06CH11357 for Argonne National # 9 | # Laboratory (ANL), which is operated by UChicago Argonne, LLC for the # 10 | # U.S. Department of Energy. The U.S. Government has rights to use, # 11 | # reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR # 12 | # UChicago Argonne, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR # 13 | # ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is # 14 | # modified to produce derivative works, such modified software should # 15 | # be clearly marked, so as not to confuse it with the version available # 16 | # from ANL. # 17 | # # 18 | # Additionally, redistribution and use in source and binary forms, with # 19 | # or without modification, are permitted provided that the following # 20 | # conditions are met: # 21 | # # 22 | # * Redistributions of source code must retain the above copyright # 23 | # notice, this list of conditions and the following disclaimer. # 24 | # # 25 | # * Redistributions in binary form must reproduce the above copyright # 26 | # notice, this list of conditions and the following disclaimer in # 27 | # the documentation and/or other materials provided with the # 28 | # distribution. # 29 | # # 30 | # * Neither the name of UChicago Argonne, LLC, Argonne National # 31 | # Laboratory, ANL, the U.S. Government, nor the names of its # 32 | # contributors may be used to endorse or promote products derived # 33 | # from this software without specific prior written permission. # 34 | # # 35 | # THIS SOFTWARE IS PROVIDED BY UChicago Argonne, LLC AND CONTRIBUTORS # 36 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # 37 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # 38 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UChicago # 39 | # Argonne, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # 40 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # 41 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # 42 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # 43 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # 44 | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # 45 | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # 46 | # POSSIBILITY OF SUCH DAMAGE. # 47 | # ######################################################################### 48 | 49 | from __future__ import absolute_import, division, print_function 50 | -------------------------------------------------------------------------------- /test/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # ######################################################################### 5 | # Copyright (c) 2015, UChicago Argonne, LLC. All rights reserved. # 6 | # # 7 | # Copyright 2015. UChicago Argonne, LLC. This software was produced # 8 | # under U.S. Government contract DE-AC02-06CH11357 for Argonne National # 9 | # Laboratory (ANL), which is operated by UChicago Argonne, LLC for the # 10 | # U.S. Department of Energy. The U.S. Government has rights to use, # 11 | # reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR # 12 | # UChicago Argonne, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR # 13 | # ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is # 14 | # modified to produce derivative works, such modified software should # 15 | # be clearly marked, so as not to confuse it with the version available # 16 | # from ANL. # 17 | # # 18 | # Additionally, redistribution and use in source and binary forms, with # 19 | # or without modification, are permitted provided that the following # 20 | # conditions are met: # 21 | # # 22 | # * Redistributions of source code must retain the above copyright # 23 | # notice, this list of conditions and the following disclaimer. # 24 | # # 25 | # * Redistributions in binary form must reproduce the above copyright # 26 | # notice, this list of conditions and the following disclaimer in # 27 | # the documentation and/or other materials provided with the # 28 | # distribution. # 29 | # # 30 | # * Neither the name of UChicago Argonne, LLC, Argonne National # 31 | # Laboratory, ANL, the U.S. Government, nor the names of its # 32 | # contributors may be used to endorse or promote products derived # 33 | # from this software without specific prior written permission. # 34 | # # 35 | # THIS SOFTWARE IS PROVIDED BY UChicago Argonne, LLC AND CONTRIBUTORS # 36 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # 37 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # 38 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UChicago # 39 | # Argonne, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # 40 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # 41 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # 42 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # 43 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # 44 | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # 45 | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # 46 | # POSSIBILITY OF SUCH DAMAGE. # 47 | # ######################################################################### 48 | 49 | from __future__ import (absolute_import, division, print_function, 50 | unicode_literals) 51 | -------------------------------------------------------------------------------- /test/test_dxchange/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # ######################################################################### 5 | # Copyright (c) 2015, UChicago Argonne, LLC. All rights reserved. # 6 | # # 7 | # Copyright 2015. UChicago Argonne, LLC. This software was produced # 8 | # under U.S. Government contract DE-AC02-06CH11357 for Argonne National # 9 | # Laboratory (ANL), which is operated by UChicago Argonne, LLC for the # 10 | # U.S. Department of Energy. The U.S. Government has rights to use, # 11 | # reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR # 12 | # UChicago Argonne, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR # 13 | # ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is # 14 | # modified to produce derivative works, such modified software should # 15 | # be clearly marked, so as not to confuse it with the version available # 16 | # from ANL. # 17 | # # 18 | # Additionally, redistribution and use in source and binary forms, with # 19 | # or without modification, are permitted provided that the following # 20 | # conditions are met: # 21 | # # 22 | # * Redistributions of source code must retain the above copyright # 23 | # notice, this list of conditions and the following disclaimer. # 24 | # # 25 | # * Redistributions in binary form must reproduce the above copyright # 26 | # notice, this list of conditions and the following disclaimer in # 27 | # the documentation and/or other materials provided with the # 28 | # distribution. # 29 | # # 30 | # * Neither the name of UChicago Argonne, LLC, Argonne National # 31 | # Laboratory, ANL, the U.S. Government, nor the names of its # 32 | # contributors may be used to endorse or promote products derived # 33 | # from this software without specific prior written permission. # 34 | # # 35 | # THIS SOFTWARE IS PROVIDED BY UChicago Argonne, LLC AND CONTRIBUTORS # 36 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # 37 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # 38 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UChicago # 39 | # Argonne, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # 40 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # 41 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # 42 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # 43 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # 44 | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # 45 | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # 46 | # POSSIBILITY OF SUCH DAMAGE. # 47 | # ######################################################################### 48 | 49 | from __future__ import (absolute_import, division, print_function, 50 | unicode_literals) 51 | -------------------------------------------------------------------------------- /test/test_dxchange/test_exchange.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # ######################################################################### 5 | # Copyright (c) 2015, UChicago Argonne, LLC. All rights reserved. # 6 | # # 7 | # Copyright 2015. UChicago Argonne, LLC. This software was produced # 8 | # under U.S. Government contract DE-AC02-06CH11357 for Argonne National # 9 | # Laboratory (ANL), which is operated by UChicago Argonne, LLC for the # 10 | # U.S. Department of Energy. The U.S. Government has rights to use, # 11 | # reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR # 12 | # UChicago Argonne, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR # 13 | # ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is # 14 | # modified to produce derivative works, such modified software should # 15 | # be clearly marked, so as not to confuse it with the version available # 16 | # from ANL. # 17 | # # 18 | # Additionally, redistribution and use in source and binary forms, with # 19 | # or without modification, are permitted provided that the following # 20 | # conditions are met: # 21 | # # 22 | # * Redistributions of source code must retain the above copyright # 23 | # notice, this list of conditions and the following disclaimer. # 24 | # # 25 | # * Redistributions in binary form must reproduce the above copyright # 26 | # notice, this list of conditions and the following disclaimer in # 27 | # the documentation and/or other materials provided with the # 28 | # distribution. # 29 | # # 30 | # * Neither the name of UChicago Argonne, LLC, Argonne National # 31 | # Laboratory, ANL, the U.S. Government, nor the names of its # 32 | # contributors may be used to endorse or promote products derived # 33 | # from this software without specific prior written permission. # 34 | # # 35 | # THIS SOFTWARE IS PROVIDED BY UChicago Argonne, LLC AND CONTRIBUTORS # 36 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # 37 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # 38 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UChicago # 39 | # Argonne, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # 40 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # 41 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # 42 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # 43 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # 44 | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # 45 | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # 46 | # POSSIBILITY OF SUCH DAMAGE. # 47 | # ######################################################################### 48 | 49 | from __future__ import (absolute_import, division, print_function, 50 | unicode_literals) 51 | 52 | from numpy.testing.utils import assert_equal 53 | import dxchange 54 | 55 | #def test_read_aps_8bm(): 56 | # proj, flat = dxchange.read_aps_8bm('data_dir/', range(0, 200), range(0, 100), file_pattern="image_00000.xrm", sino=(0, 16)) 57 | -------------------------------------------------------------------------------- /dxchange/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # ######################################################################### 5 | # Copyright (c) 2015, UChicago Argonne, LLC. All rights reserved. # 6 | # # 7 | # Copyright 2015. UChicago Argonne, LLC. This software was produced # 8 | # under U.S. Government contract DE-AC02-06CH11357 for Argonne National # 9 | # Laboratory (ANL), which is operated by UChicago Argonne, LLC for the # 10 | # U.S. Department of Energy. The U.S. Government has rights to use, # 11 | # reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR # 12 | # UChicago Argonne, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR # 13 | # ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is # 14 | # modified to produce derivative works, such modified software should # 15 | # be clearly marked, so as not to confuse it with the version available # 16 | # from ANL. # 17 | # # 18 | # Additionally, redistribution and use in source and binary forms, with # 19 | # or without modification, are permitted provided that the following # 20 | # conditions are met: # 21 | # # 22 | # * Redistributions of source code must retain the above copyright # 23 | # notice, this list of conditions and the following disclaimer. # 24 | # # 25 | # * Redistributions in binary form must reproduce the above copyright # 26 | # notice, this list of conditions and the following disclaimer in # 27 | # the documentation and/or other materials provided with the # 28 | # distribution. # 29 | # # 30 | # * Neither the name of UChicago Argonne, LLC, Argonne National # 31 | # Laboratory, ANL, the U.S. Government, nor the names of its # 32 | # contributors may be used to endorse or promote products derived # 33 | # from this software without specific prior written permission. # 34 | # # 35 | # THIS SOFTWARE IS PROVIDED BY UChicago Argonne, LLC AND CONTRIBUTORS # 36 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # 37 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # 38 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UChicago # 39 | # Argonne, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # 40 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # 41 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # 42 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # 43 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # 44 | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # 45 | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # 46 | # POSSIBILITY OF SUCH DAMAGE. # 47 | # ######################################################################### 48 | 49 | from __future__ import (absolute_import, division, print_function, 50 | unicode_literals) 51 | 52 | import sys 53 | import warnings 54 | import logging 55 | 56 | from dxchange.exchange import * 57 | from dxchange.reader import * 58 | from dxchange.writer import * 59 | 60 | logging.getLogger(__name__).addHandler(logging.NullHandler()) 61 | 62 | try: 63 | from importlib.metadata import version 64 | except ImportError: 65 | # For Python < 3.8, fallback to backport 66 | from importlib_metadata import version 67 | 68 | try: 69 | __version__ = version("dxchange") 70 | except Exception: 71 | __version__ = "unknown" 72 | -------------------------------------------------------------------------------- /doc/source/bibtex/ref.bib: -------------------------------------------------------------------------------- 1 | @article{DeCarlo:14b, 2 | author = {De Carlo F and Gursoy D and Marone F and Rivers M and Parkinson YD and Khan F and Schwarz N and Vine DJ and Vogt S and Gleber SC and Narayanan S and Newville M and Lanzirotti T and Sun Y and Hong YP and Jacobsen C}, 3 | title = {Scientific Data Exchange: a schema for HDF5-based storage of raw and analyzed data}, 4 | journal = {Journal of Synchrotron Radiation}, 5 | year = {2014}, 6 | volume = {21}, 7 | number = {6}, 8 | pages = {1224--1230} 9 | } 10 | 11 | @article{DeCarlo:17, 12 | author={Francesco De Carlo and Doga Gursoy and Daniel Jackson Ching and Kees Joost Batenburg and Wolfgang Ludwig and Lucia Mancini and Federica Marone and Rajmund Mokso and Daniel M. Pelt and Jan Sijbers and Mark Rivers}, 13 | title={TomoBank: A tomographic data repository for computational X-ray science}, 14 | journal={Measurement Science and Technology}, 15 | url={https://doi.org/10.1088/1361-6501/aa9c19}, 16 | year={2017} 17 | } 18 | 19 | @article{Gursoy:14b, 20 | author = {G\"{u}rsoy D and De Carlo F and Xiao X and Jacobsen C}, 21 | title = {TomoPy: A framework for the analysis of synchrotron tomographic data},journal = {Journal of Synchrotron Radiation}, 22 | volume = {21}, 23 | number = {5}, 24 | pages = {1188--1193}, 25 | year = {2014} 26 | } 27 | 28 | @misc{CXI:01, 29 | title = {{The Coherent X-ray Imaging Data Bank}}, 30 | author = { Filipe R. N. C. Maia}, 31 | howpublished = {\url{http://cxidb.org/cxi.html}}, 32 | note = {Accessed: 2016-03-12} 33 | } 34 | 35 | @misc{CXI:02, 36 | title = {{The CXI File Format}}, 37 | author = {Filipe R. N. C. Maia}, 38 | howpublished = {\url{https://github.com/FilipeMaia/CXI/raw/master/cxi_file_format.pdf}}, 39 | note = {Accessed: 2016-03-12} 40 | } 41 | 42 | @misc{HDF:01, 43 | title = {{The HDF File Format}}, 44 | author = {The HDF Group}, 45 | howpublished = {\url{http://www.hdfgroup.org/HDF5}}, 46 | note = {Accessed: 2016-03-12} 47 | } 48 | 49 | @misc{HDF:02, 50 | title = {{The HDF Dump}}, 51 | author = {The HDF Group}, 52 | howpublished = {\url{http://www.hdfgroup.org/HDF5/doc/RM/Tools.html#Tools-Dump}}, 53 | note = {Accessed: 2016-03-12} 54 | } 55 | 56 | @misc{HDF:03, 57 | title = {{The HDF viewer}}, 58 | author = {The HDF Group}, 59 | howpublished = {\url{http://www.hdfgroup.org/hdf-java-html/hdfview}}, 60 | note = {Accessed: 2016-03-12} 61 | } 62 | 63 | @misc{AD:01, 64 | title = {{Area Detector}}, 65 | author = {Mark Rivers}, 66 | howpublished = {\url{http://cars9.uchicago.edu/software/epics/areaDetector.html}}, 67 | note = {Accessed: 2016-03-12} 68 | } 69 | 70 | @misc{AD:02, 71 | title = {{Area Detector HDF plugin}}, 72 | author = {Ulrik Pedersen and Arthur Glowacki and Alan Greer and Mark Rivers}, 73 | howpublished = {\url{http://cars.uchicago.edu/software/epics/NDFileHDF5.html}}, 74 | note = {Accessed: 2016-03-12} 75 | } 76 | 77 | @misc{EPICS:01, 78 | title = {{The EPICS control system}}, 79 | howpublished = {\url{http://www.aps.anl.gov/epics/}}, 80 | note = {Accessed: 2016-03-12} 81 | } 82 | 83 | @misc{UNIDATA:01, 84 | title = {{The UDUNITS at UNIDATA}}, 85 | howpublished = {\url{http://www.unidata.ucar.edu/software/udunits/}}, 86 | note = {Accessed: 2016-03-12} 87 | } 88 | 89 | @article{Elettra:01, 90 | author = {Francesco Brun and 91 | Serena Pacil{\`{e}} and 92 | Agostino Accardo and 93 | Georgios Kourousias and 94 | Diego Dreossi and 95 | Lucia Mancini and 96 | Giuliana Tromba and 97 | Roberto Pugliese}, 98 | title = {Enhanced and Flexible Software Tools for X-ray Computed Tomography 99 | at the Italian Synchrotron Radiation Facility Elettra}, 100 | journal = {Fundam. Inform.}, 101 | volume = {141}, 102 | number = {2-3}, 103 | pages = {233--243}, 104 | year = {2015}, 105 | url = {http://dx.doi.org/10.3233/FI-2015-1273}, 106 | doi = {10.3233/FI-2015-1273}, 107 | timestamp = {Thu, 05 Nov 2015 17:36:17 +0100}, 108 | biburl = {http://dblp.dagstuhl.de/rec/bib/journals/fuin/BrunPAKDMTP15}, 109 | bibsource = {dblp computer science bibliography, http://dblp.org} 110 | } 111 | -------------------------------------------------------------------------------- /test/test_dxchange/test_writer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # ######################################################################### 5 | # Copyright (c) 2015, UChicago Argonne, LLC. All rights reserved. # 6 | # # 7 | # Copyright 2015. UChicago Argonne, LLC. This software was produced # 8 | # under U.S. Government contract DE-AC02-06CH11357 for Argonne National # 9 | # Laboratory (ANL), which is operated by UChicago Argonne, LLC for the # 10 | # U.S. Department of Energy. The U.S. Government has rights to use, # 11 | # reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR # 12 | # UChicago Argonne, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR # 13 | # ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is # 14 | # modified to produce derivative works, such modified software should # 15 | # be clearly marked, so as not to confuse it with the version available # 16 | # from ANL. # 17 | # # 18 | # Additionally, redistribution and use in source and binary forms, with # 19 | # or without modification, are permitted provided that the following # 20 | # conditions are met: # 21 | # # 22 | # * Redistributions of source code must retain the above copyright # 23 | # notice, this list of conditions and the following disclaimer. # 24 | # # 25 | # * Redistributions in binary form must reproduce the above copyright # 26 | # notice, this list of conditions and the following disclaimer in # 27 | # the documentation and/or other materials provided with the # 28 | # distribution. # 29 | # # 30 | # * Neither the name of UChicago Argonne, LLC, Argonne National # 31 | # Laboratory, ANL, the U.S. Government, nor the names of its # 32 | # contributors may be used to endorse or promote products derived # 33 | # from this software without specific prior written permission. # 34 | # # 35 | # THIS SOFTWARE IS PROVIDED BY UChicago Argonne, LLC AND CONTRIBUTORS # 36 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # 37 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # 38 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UChicago # 39 | # Argonne, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # 40 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # 41 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # 42 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # 43 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # 44 | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # 45 | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # 46 | # POSSIBILITY OF SUCH DAMAGE. # 47 | # ######################################################################### 48 | from __future__ import (absolute_import, division, print_function, 49 | unicode_literals) 50 | 51 | import unittest 52 | from numpy.testing.utils import assert_equal 53 | import dxchange.writer as writer 54 | 55 | 56 | class remove_trailing_digits_test_case(unittest.TestCase): 57 | def test_remove_trailing_digits_removes_zeroes(self): 58 | text, number_of_digits = writer.remove_trailing_digits("someText0000") 59 | assert_equal(text, "someText") 60 | 61 | def test_remove_trailing_digits_removes_correct_number_of_zeroes(self): 62 | text, number_of_digits = writer.remove_trailing_digits("someText0000") 63 | assert_equal(number_of_digits, 4) 64 | 65 | def test_remove_trailing_digits_removes_digits(self): 66 | text, number_of_digits = writer.remove_trailing_digits( 67 | "someText1234567890") 68 | assert_equal(text, "someText") 69 | 70 | def test_remove_trailing_digits_does_not_remove_digits_in_the_middle(self): 71 | text, number_of_digits = writer.remove_trailing_digits( 72 | "8s7o6m5e4T3e2x1t00.0000") 73 | assert_equal(text, "8s7o6m5e4T3e2x1t00.") 74 | 75 | def test_remove_trailing_digits_handles_not_having_digits(self): 76 | text, number_of_digits = writer.remove_trailing_digits("someText") 77 | assert_equal(text, "someText") 78 | 79 | def test_remove_trailing_digits_handles_empty_string(self): 80 | text, number_of_digits = writer.remove_trailing_digits("") 81 | assert_equal(text, "") 82 | assert_equal(number_of_digits, 0) 83 | -------------------------------------------------------------------------------- /dxchange/dtype.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # ######################################################################### 5 | # Copyright (c) 2015, UChicago Argonne, LLC. All rights reserved. # 6 | # # 7 | # Copyright 2015. UChicago Argonne, LLC. This software was produced # 8 | # under U.S. Government contract DE-AC02-06CH11357 for Argonne National # 9 | # Laboratory (ANL), which is operated by UChicago Argonne, LLC for the # 10 | # U.S. Department of Energy. The U.S. Government has rights to use, # 11 | # reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR # 12 | # UChicago Argonne, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR # 13 | # ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is # 14 | # modified to produce derivative works, such modified software should # 15 | # be clearly marked, so as not to confuse it with the version available # 16 | # from ANL. # 17 | # # 18 | # Additionally, redistribution and use in source and binary forms, with # 19 | # or without modification, are permitted provided that the following # 20 | # conditions are met: # 21 | # # 22 | # * Redistributions of source code must retain the above copyright # 23 | # notice, this list of conditions and the following disclaimer. # 24 | # # 25 | # * Redistributions in binary form must reproduce the above copyright # 26 | # notice, this list of conditions and the following disclaimer in # 27 | # the documentation and/or other materials provided with the # 28 | # distribution. # 29 | # # 30 | # * Neither the name of UChicago Argonne, LLC, Argonne National # 31 | # Laboratory, ANL, the U.S. Government, nor the names of its # 32 | # contributors may be used to endorse or promote products derived # 33 | # from this software without specific prior written permission. # 34 | # # 35 | # THIS SOFTWARE IS PROVIDED BY UChicago Argonne, LLC AND CONTRIBUTORS # 36 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # 37 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # 38 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UChicago # 39 | # Argonne, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # 40 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # 41 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # 42 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # 43 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # 44 | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # 45 | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # 46 | # POSSIBILITY OF SUCH DAMAGE. # 47 | # ######################################################################### 48 | 49 | """ 50 | Module for internal utility functions. 51 | """ 52 | 53 | from __future__ import (absolute_import, division, print_function, 54 | unicode_literals) 55 | 56 | 57 | __author__ = "Doga Gursoy" 58 | __copyright__ = "Copyright (c) 2015-2016, UChicago Argonne, LLC." 59 | __version__ = "0.1.0" 60 | __docformat__ = 'restructuredtext en' 61 | __all__ = ['as_ndarray', 62 | 'as_dtype', 63 | 'as_float32', 64 | 'as_int32', 65 | 'as_uint8', 66 | 'as_uint16', 67 | 'as_c_float_p', 68 | 'as_c_int', 69 | 'as_c_int_p', 70 | 'as_c_float', 71 | 'as_c_char_p', 72 | 'as_c_void_p', 73 | 'as_sharedmem', 74 | 'is_sharedmem', 75 | 'is_contiguous', 76 | 'empty_shared_array'] 77 | 78 | 79 | import ctypes 80 | import numpy as np 81 | import multiprocessing as mp 82 | import logging 83 | 84 | logger = logging.getLogger(__name__) 85 | 86 | 87 | def as_ndarray(arr, dtype=None): 88 | if not isinstance(arr, np.ndarray): 89 | arr = np.array(arr, dtype=dtype) 90 | return arr 91 | 92 | 93 | def as_dtype(arr, dtype): 94 | if not arr.dtype == dtype: 95 | arr = np.array(arr, dtype=dtype) 96 | return arr 97 | 98 | 99 | def as_float32(arr): 100 | arr = as_ndarray(arr, np.float32) 101 | return as_dtype(arr, np.float32) 102 | 103 | 104 | def as_int32(arr): 105 | arr = as_ndarray(arr, np.int32) 106 | return as_dtype(arr, np.int32) 107 | 108 | 109 | def as_uint16(arr): 110 | arr = as_ndarray(arr, np.uint16) 111 | return as_dtype(arr, np.uint16) 112 | 113 | 114 | def as_uint8(arr): 115 | arr = as_ndarray(arr, np.uint8) 116 | return as_dtype(arr, np.uint8) 117 | 118 | 119 | def as_c_float_p(arr): 120 | c_float_p = ctypes.POINTER(ctypes.c_float) 121 | return arr.ctypes.data_as(c_float_p) 122 | 123 | 124 | def as_c_int(arr): 125 | return ctypes.c_int(arr) 126 | 127 | 128 | def as_c_int_p(arr): 129 | c_int_p = ctypes.POINTER(ctypes.c_int) 130 | return arr.ctypes.data_as(c_int_p) 131 | 132 | 133 | def as_c_float(arr): 134 | return ctypes.c_float(arr) 135 | 136 | 137 | def as_c_char_p(arr): 138 | c_char_p = ctypes.POINTER(ctypes.c_char) 139 | return arr.ctypes.data_as(c_char_p) 140 | 141 | 142 | def as_c_void_p(): 143 | return ctypes.POINTER(ctypes.c_void_p) 144 | 145 | 146 | def as_sharedmem(arr, copy=False): 147 | # first check to see if it already a shared array 148 | if not copy and is_sharedmem(arr): 149 | return arr 150 | # get ctype from numpy array 151 | ctype = np.ctypeslib._typecodes[arr.__array_interface__['typestr']] 152 | # create shared ctypes object with no lock 153 | shared_obj = mp.RawArray(ctype, arr.size) 154 | # create numpy array from shared object 155 | #shared_arr = np.ctypeslib.as_array(shared_obj) 156 | shared_arr = np.frombuffer(shared_obj, dtype=arr.dtype) 157 | shared_arr = np.reshape(shared_arr, arr.shape) 158 | # copy data to shared array 159 | shared_arr[:] = arr[:] 160 | return shared_arr 161 | 162 | 163 | def is_sharedmem(arr): 164 | # attempt to determine if data is in shared memory 165 | try: 166 | base = arr.base 167 | if base is None: 168 | return False 169 | elif type(base).__module__.startswith('multiprocessing.sharedctypes'): 170 | return True 171 | else: 172 | return is_sharedmem(base) 173 | except: 174 | return False 175 | 176 | 177 | def is_contiguous(arr): 178 | return arr.flags.c_contiguous 179 | 180 | 181 | def empty_shared_array(shape, dtype=np.float32): 182 | # create a shared ndarray with the provided shape and type 183 | # get ctype from np dtype 184 | temp_arr = np.empty((1), dtype) 185 | ctype = np.ctypeslib._typecodes[temp_arr.__array_interface__['typestr']] 186 | # create shared ctypes object with no lock 187 | size = 1 188 | for dim in shape: 189 | size *= dim 190 | shared_obj = mp.RawArray(ctype, size) 191 | # create numpy array from shared object 192 | arr = np.frombuffer(shared_obj, dtype) 193 | arr = arr.reshape(shape) 194 | return arr 195 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = _build 9 | 10 | # User-friendly check for sphinx-build 11 | ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) 12 | $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) 13 | endif 14 | 15 | # Internal variables. 16 | PAPEROPT_a4 = -D latex_paper_size=a4 17 | PAPEROPT_letter = -D latex_paper_size=letter 18 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 19 | # the i18n builder cannot share the environment and doctrees with the others 20 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 21 | 22 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext 23 | 24 | help: 25 | @echo "Please use \`make ' where is one of" 26 | @echo " html to make standalone HTML files" 27 | @echo " dirhtml to make HTML files named index.html in directories" 28 | @echo " singlehtml to make a single large HTML file" 29 | @echo " pickle to make pickle files" 30 | @echo " json to make JSON files" 31 | @echo " htmlhelp to make HTML files and a HTML help project" 32 | @echo " qthelp to make HTML files and a qthelp project" 33 | @echo " applehelp to make an Apple Help Book" 34 | @echo " devhelp to make HTML files and a Devhelp project" 35 | @echo " epub to make an epub" 36 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 37 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 38 | @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" 39 | @echo " text to make text files" 40 | @echo " man to make manual pages" 41 | @echo " texinfo to make Texinfo files" 42 | @echo " info to make Texinfo files and run them through makeinfo" 43 | @echo " gettext to make PO message catalogs" 44 | @echo " changes to make an overview of all changed/added/deprecated items" 45 | @echo " xml to make Docutils-native XML files" 46 | @echo " pseudoxml to make pseudoxml-XML files for display purposes" 47 | @echo " linkcheck to check all external links for integrity" 48 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 49 | @echo " coverage to run coverage check of the documentation (if enabled)" 50 | 51 | clean: 52 | rm -rf $(BUILDDIR)/* 53 | 54 | html: 55 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 56 | @echo 57 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 58 | 59 | dirhtml: 60 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 61 | @echo 62 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 63 | 64 | singlehtml: 65 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 66 | @echo 67 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 68 | 69 | pickle: 70 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 71 | @echo 72 | @echo "Build finished; now you can process the pickle files." 73 | 74 | json: 75 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 76 | @echo 77 | @echo "Build finished; now you can process the JSON files." 78 | 79 | htmlhelp: 80 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 81 | @echo 82 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 83 | ".hhp project file in $(BUILDDIR)/htmlhelp." 84 | 85 | qthelp: 86 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 87 | @echo 88 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 89 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 90 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/dquality.qhcp" 91 | @echo "To view the help file:" 92 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/dquality.qhc" 93 | 94 | applehelp: 95 | $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp 96 | @echo 97 | @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." 98 | @echo "N.B. You won't be able to view it unless you put it in" \ 99 | "~/Library/Documentation/Help or install it in your application" \ 100 | "bundle." 101 | 102 | devhelp: 103 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 104 | @echo 105 | @echo "Build finished." 106 | @echo "To view the help file:" 107 | @echo "# mkdir -p $$HOME/.local/share/devhelp/dquality" 108 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/dquality" 109 | @echo "# devhelp" 110 | 111 | epub: 112 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 113 | @echo 114 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 115 | 116 | latex: 117 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 118 | @echo 119 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 120 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 121 | "(use \`make latexpdf' here to do that automatically)." 122 | 123 | latexpdf: 124 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 125 | @echo "Running LaTeX files through pdflatex..." 126 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 127 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 128 | 129 | latexpdfja: 130 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 131 | @echo "Running LaTeX files through platex and dvipdfmx..." 132 | $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja 133 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 134 | 135 | text: 136 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 137 | @echo 138 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 139 | 140 | man: 141 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 142 | @echo 143 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 144 | 145 | texinfo: 146 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 147 | @echo 148 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 149 | @echo "Run \`make' in that directory to run these through makeinfo" \ 150 | "(use \`make info' here to do that automatically)." 151 | 152 | info: 153 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 154 | @echo "Running Texinfo files through makeinfo..." 155 | make -C $(BUILDDIR)/texinfo info 156 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 157 | 158 | gettext: 159 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 160 | @echo 161 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 162 | 163 | changes: 164 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 165 | @echo 166 | @echo "The overview file is in $(BUILDDIR)/changes." 167 | 168 | linkcheck: 169 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 170 | @echo 171 | @echo "Link check complete; look for any errors in the above output " \ 172 | "or in $(BUILDDIR)/linkcheck/output.txt." 173 | 174 | doctest: 175 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 176 | @echo "Testing of doctests in the sources finished, look at the " \ 177 | "results in $(BUILDDIR)/doctest/output.txt." 178 | 179 | coverage: 180 | $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage 181 | @echo "Testing of coverage in the sources finished, look at the " \ 182 | "results in $(BUILDDIR)/coverage/python.txt." 183 | 184 | xml: 185 | $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml 186 | @echo 187 | @echo "Build finished. The XML files are in $(BUILDDIR)/xml." 188 | 189 | pseudoxml: 190 | $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml 191 | @echo 192 | @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." 193 | -------------------------------------------------------------------------------- /doc/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | REM Command file for Sphinx documentation 4 | 5 | if "%SPHINXBUILD%" == "" ( 6 | set SPHINXBUILD=sphinx-build 7 | ) 8 | set BUILDDIR=_build 9 | set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . 10 | set I18NSPHINXOPTS=%SPHINXOPTS% . 11 | if NOT "%PAPER%" == "" ( 12 | set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% 13 | set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% 14 | ) 15 | 16 | if "%1" == "" goto help 17 | 18 | if "%1" == "help" ( 19 | :help 20 | echo.Please use `make ^` where ^ is one of 21 | echo. html to make standalone HTML files 22 | echo. dirhtml to make HTML files named index.html in directories 23 | echo. singlehtml to make a single large HTML file 24 | echo. pickle to make pickle files 25 | echo. json to make JSON files 26 | echo. htmlhelp to make HTML files and a HTML help project 27 | echo. qthelp to make HTML files and a qthelp project 28 | echo. devhelp to make HTML files and a Devhelp project 29 | echo. epub to make an epub 30 | echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter 31 | echo. text to make text files 32 | echo. man to make manual pages 33 | echo. texinfo to make Texinfo files 34 | echo. gettext to make PO message catalogs 35 | echo. changes to make an overview over all changed/added/deprecated items 36 | echo. xml to make Docutils-native XML files 37 | echo. pseudoxml to make pseudoxml-XML files for display purposes 38 | echo. linkcheck to check all external links for integrity 39 | echo. doctest to run all doctests embedded in the documentation if enabled 40 | echo. coverage to run coverage check of the documentation if enabled 41 | goto end 42 | ) 43 | 44 | if "%1" == "clean" ( 45 | for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i 46 | del /q /s %BUILDDIR%\* 47 | goto end 48 | ) 49 | 50 | 51 | REM Check if sphinx-build is available and fallback to Python version if any 52 | %SPHINXBUILD% 2> nul 53 | if errorlevel 9009 goto sphinx_python 54 | goto sphinx_ok 55 | 56 | :sphinx_python 57 | 58 | set SPHINXBUILD=python -m sphinx.__init__ 59 | %SPHINXBUILD% 2> nul 60 | if errorlevel 9009 ( 61 | echo. 62 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 63 | echo.installed, then set the SPHINXBUILD environment variable to point 64 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 65 | echo.may add the Sphinx directory to PATH. 66 | echo. 67 | echo.If you don't have Sphinx installed, grab it from 68 | echo.http://sphinx-doc.org/ 69 | exit /b 1 70 | ) 71 | 72 | :sphinx_ok 73 | 74 | 75 | if "%1" == "html" ( 76 | %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html 77 | if errorlevel 1 exit /b 1 78 | echo. 79 | echo.Build finished. The HTML pages are in %BUILDDIR%/html. 80 | goto end 81 | ) 82 | 83 | if "%1" == "dirhtml" ( 84 | %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml 85 | if errorlevel 1 exit /b 1 86 | echo. 87 | echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. 88 | goto end 89 | ) 90 | 91 | if "%1" == "singlehtml" ( 92 | %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml 93 | if errorlevel 1 exit /b 1 94 | echo. 95 | echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. 96 | goto end 97 | ) 98 | 99 | if "%1" == "pickle" ( 100 | %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle 101 | if errorlevel 1 exit /b 1 102 | echo. 103 | echo.Build finished; now you can process the pickle files. 104 | goto end 105 | ) 106 | 107 | if "%1" == "json" ( 108 | %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json 109 | if errorlevel 1 exit /b 1 110 | echo. 111 | echo.Build finished; now you can process the JSON files. 112 | goto end 113 | ) 114 | 115 | if "%1" == "htmlhelp" ( 116 | %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp 117 | if errorlevel 1 exit /b 1 118 | echo. 119 | echo.Build finished; now you can run HTML Help Workshop with the ^ 120 | .hhp project file in %BUILDDIR%/htmlhelp. 121 | goto end 122 | ) 123 | 124 | if "%1" == "qthelp" ( 125 | %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp 126 | if errorlevel 1 exit /b 1 127 | echo. 128 | echo.Build finished; now you can run "qcollectiongenerator" with the ^ 129 | .qhcp project file in %BUILDDIR%/qthelp, like this: 130 | echo.^> qcollectiongenerator %BUILDDIR%\qthelp\dmagic.qhcp 131 | echo.To view the help file: 132 | echo.^> assistant -collectionFile %BUILDDIR%\qthelp\dmagic.ghc 133 | goto end 134 | ) 135 | 136 | if "%1" == "devhelp" ( 137 | %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp 138 | if errorlevel 1 exit /b 1 139 | echo. 140 | echo.Build finished. 141 | goto end 142 | ) 143 | 144 | if "%1" == "epub" ( 145 | %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub 146 | if errorlevel 1 exit /b 1 147 | echo. 148 | echo.Build finished. The epub file is in %BUILDDIR%/epub. 149 | goto end 150 | ) 151 | 152 | if "%1" == "latex" ( 153 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 154 | if errorlevel 1 exit /b 1 155 | echo. 156 | echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. 157 | goto end 158 | ) 159 | 160 | if "%1" == "latexpdf" ( 161 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 162 | cd %BUILDDIR%/latex 163 | make all-pdf 164 | cd %~dp0 165 | echo. 166 | echo.Build finished; the PDF files are in %BUILDDIR%/latex. 167 | goto end 168 | ) 169 | 170 | if "%1" == "latexpdfja" ( 171 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 172 | cd %BUILDDIR%/latex 173 | make all-pdf-ja 174 | cd %~dp0 175 | echo. 176 | echo.Build finished; the PDF files are in %BUILDDIR%/latex. 177 | goto end 178 | ) 179 | 180 | if "%1" == "text" ( 181 | %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text 182 | if errorlevel 1 exit /b 1 183 | echo. 184 | echo.Build finished. The text files are in %BUILDDIR%/text. 185 | goto end 186 | ) 187 | 188 | if "%1" == "man" ( 189 | %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man 190 | if errorlevel 1 exit /b 1 191 | echo. 192 | echo.Build finished. The manual pages are in %BUILDDIR%/man. 193 | goto end 194 | ) 195 | 196 | if "%1" == "texinfo" ( 197 | %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo 198 | if errorlevel 1 exit /b 1 199 | echo. 200 | echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. 201 | goto end 202 | ) 203 | 204 | if "%1" == "gettext" ( 205 | %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale 206 | if errorlevel 1 exit /b 1 207 | echo. 208 | echo.Build finished. The message catalogs are in %BUILDDIR%/locale. 209 | goto end 210 | ) 211 | 212 | if "%1" == "changes" ( 213 | %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes 214 | if errorlevel 1 exit /b 1 215 | echo. 216 | echo.The overview file is in %BUILDDIR%/changes. 217 | goto end 218 | ) 219 | 220 | if "%1" == "linkcheck" ( 221 | %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck 222 | if errorlevel 1 exit /b 1 223 | echo. 224 | echo.Link check complete; look for any errors in the above output ^ 225 | or in %BUILDDIR%/linkcheck/output.txt. 226 | goto end 227 | ) 228 | 229 | if "%1" == "doctest" ( 230 | %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest 231 | if errorlevel 1 exit /b 1 232 | echo. 233 | echo.Testing of doctests in the sources finished, look at the ^ 234 | results in %BUILDDIR%/doctest/output.txt. 235 | goto end 236 | ) 237 | 238 | if "%1" == "coverage" ( 239 | %SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage 240 | if errorlevel 1 exit /b 1 241 | echo. 242 | echo.Testing of coverage in the sources finished, look at the ^ 243 | results in %BUILDDIR%/coverage/python.txt. 244 | goto end 245 | ) 246 | 247 | if "%1" == "xml" ( 248 | %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml 249 | if errorlevel 1 exit /b 1 250 | echo. 251 | echo.Build finished. The XML files are in %BUILDDIR%/xml. 252 | goto end 253 | ) 254 | 255 | if "%1" == "pseudoxml" ( 256 | %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml 257 | if errorlevel 1 exit /b 1 258 | echo. 259 | echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. 260 | goto end 261 | ) 262 | 263 | :end 264 | -------------------------------------------------------------------------------- /doc/conf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # DXchange documentation build configuration file, created by 5 | # sphinx-quickstart on Fri Mar 13 16:29:32 2015. 6 | # 7 | # This file is execfile()d with the current directory set to its 8 | # containing dir. 9 | # 10 | # Note that not all possible configuration values are present in this 11 | # autogenerated file. 12 | # 13 | # All configuration values have a default; values that are commented out 14 | # serve to show the default. 15 | 16 | import sys 17 | import os 18 | 19 | import sphinx_rtd_theme 20 | 21 | # If extensions (or modules to document with autodoc) are in another directory, 22 | # add these directories to sys.path here. If the directory is relative to the 23 | # documentation root, use os.path.abspath to make it absolute, like shown here. 24 | sys.path.insert(0, os.path.abspath('..')) 25 | 26 | # -- General configuration ------------------------------------------------ 27 | 28 | # If your documentation needs a minimal Sphinx version, state it here. 29 | #needs_sphinx = '1.0' 30 | 31 | # Add any Sphinx extension module names here, as strings. They can be 32 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 33 | # ones. 34 | extensions = [ 35 | 'sphinx.ext.autodoc', 36 | 'sphinx.ext.mathjax', 37 | 'sphinx.ext.todo', 38 | 'sphinx.ext.autosummary', 39 | 'sphinx.ext.napoleon', 40 | 'sphinxcontrib.bibtex', 41 | 'sphinx.ext.viewcode'] 42 | 43 | bibtex_bibfiles = [ 44 | 'source/bibtex/cite.bib', 45 | 'source/bibtex/ref.bib', 46 | ] 47 | 48 | # Napoleon settings 49 | napoleon_google_docstring = True 50 | napoleon_numpy_docstring = True 51 | napoleon_include_private_with_doc = False 52 | napoleon_include_special_with_doc = False 53 | napoleon_use_admonition_for_examples = False 54 | napoleon_use_admonition_for_notes = False 55 | napoleon_use_admonition_for_references = False 56 | napoleon_use_ivar = False 57 | napoleon_use_param = False 58 | napoleon_use_rtype = False 59 | 60 | todo_include_todos=True 61 | 62 | # Add any paths that contain templates here, relative to this directory. 63 | templates_path = ['_templates'] 64 | 65 | # The suffix of source filenames. 66 | source_suffix = '.rst' 67 | 68 | # The encoding of source files. 69 | #source_encoding = 'utf-8-sig' 70 | 71 | # The master toctree document. 72 | master_doc = 'index' 73 | 74 | # General information about the project. 75 | Argonne = u'Argonne National Laboratory' 76 | project = u'DXchange' 77 | copyright = u'2016, ' + Argonne 78 | 79 | # The version info for the project you're documenting, acts as replacement for 80 | # |version| and |release|, also used in various other places throughout the 81 | # built documents. 82 | # 83 | # The short X.Y version. 84 | version = open(os.path.join('..', 'VERSION')).read().strip() 85 | # The full version, including alpha/beta/rc tags. 86 | release = version 87 | 88 | # The language for content autogenerated by Sphinx. Refer to documentation 89 | # for a list of supported languages. 90 | #language = None 91 | 92 | # There are two options for replacing |today|: either, you set today to some 93 | # non-false value, then it is used: 94 | #today = '' 95 | # Else, today_fmt is used as the format for a strftime call. 96 | #today_fmt = '%B %d, %Y' 97 | 98 | # List of patterns, relative to source directory, that match files and 99 | # directories to ignore when looking for source files. 100 | exclude_patterns = ['_build'] 101 | 102 | # The reST default role (used for this markup: `text`) to use for all 103 | # documents. 104 | #default_role = None 105 | 106 | # If true, '()' will be appended to :func: etc. cross-reference text. 107 | #add_function_parentheses = True 108 | 109 | # If true, the current module name will be prepended to all description 110 | # unit titles (such as .. function::). 111 | #add_module_names = True 112 | 113 | # If true, sectionauthor and moduleauthor directives will be shown in the 114 | # output. They are ignored by default. 115 | show_authors = False 116 | 117 | # The name of the Pygments (syntax highlighting) style to use. 118 | pygments_style = 'sphinx' 119 | 120 | # A list of ignored prefixes for module index sorting. 121 | #modindex_common_prefix = [] 122 | 123 | # If true, keep warnings as "system message" paragraphs in the built documents. 124 | #keep_warnings = False 125 | 126 | 127 | # -- Options for HTML output ---------------------------------------------- 128 | 129 | # The theme to use for HTML and HTML Help pages. See the documentation for 130 | # a list of builtin themes. 131 | html_theme = 'sphinx_rtd_theme' 132 | html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] 133 | 134 | # on_rtd is whether we are on readthedocs.org 135 | on_rtd = os.environ.get('READTHEDOCS', None) == 'True' 136 | 137 | if not on_rtd: # only import and set the theme if we're building docs locally 138 | import sphinx_rtd_theme 139 | html_theme = 'sphinx_rtd_theme' 140 | html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] 141 | 142 | html_context = { 143 | "display_github": True, # Integrate GitHub 144 | "github_user": "data-exchange", # Username 145 | "github_repo": "dxchange", # Repo name 146 | "github_version": "master", # Version 147 | "conf_py_path": "/doc/", # Path in the checkout to the docs root 148 | } 149 | 150 | # Theme options are theme-specific and customize the look and feel of a theme 151 | # further. For a list of options available for each theme, see the 152 | # documentation. 153 | #html_theme_options = {} 154 | 155 | # Add any paths that contain custom themes here, relative to this directory. 156 | #html_theme_path = [] 157 | 158 | # The name for this set of Sphinx documents. If None, it defaults to 159 | # " v documentation". 160 | #html_title = None 161 | 162 | # A shorter title for the navigation bar. Default is the same as html_title. 163 | #html_short_title = None 164 | 165 | # The name of an image file (relative to this directory) to place at the top 166 | # of the sidebar. 167 | #html_logo = None 168 | 169 | # The name of an image file (within the static path) to use as favicon of the 170 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 171 | # pixels large. 172 | #html_favicon = None 173 | 174 | # Add any paths that contain custom static files (such as style sheets) here, 175 | # relative to this directory. They are copied after the builtin static files, 176 | # so a file named "default.css" will overwrite the builtin "default.css". 177 | # html_static_path = ['_static'] 178 | 179 | # Add any extra paths that contain custom files (such as robots.txt or 180 | # .htaccess) here, relative to this directory. These files are copied 181 | # directly to the root of the documentation. 182 | #html_extra_path = [] 183 | 184 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 185 | # using the given strftime format. 186 | #html_last_updated_fmt = '%b %d, %Y' 187 | 188 | # If true, SmartyPants will be used to convert quotes and dashes to 189 | # typographically correct entities. 190 | #html_use_smartypants = True 191 | 192 | # Custom sidebar templates, maps document names to template names. 193 | #html_sidebars = {} 194 | 195 | # Additional templates that should be rendered to pages, maps page names to 196 | # template names. 197 | #html_additional_pages = {} 198 | 199 | # If false, no module index is generated. 200 | #html_domain_indices = True 201 | 202 | # If false, no index is generated. 203 | #html_use_index = True 204 | 205 | # If true, the index is split into individual pages for each letter. 206 | #html_split_index = False 207 | 208 | # If true, links to the reST sources are added to the pages. 209 | #html_show_sourcelink = True 210 | 211 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 212 | #html_show_sphinx = True 213 | 214 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 215 | #html_show_copyright = True 216 | 217 | # If true, an OpenSearch description file will be output, and all pages will 218 | # contain a tag referring to it. The value of this option must be the 219 | # base URL from which the finished HTML is served. 220 | #html_use_opensearch = '' 221 | 222 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 223 | #html_file_suffix = None 224 | 225 | # Output file base name for HTML help builder. 226 | htmlhelp_basename = project+'doc' 227 | 228 | 229 | # -- Options for LaTeX output --------------------------------------------- 230 | 231 | latex_elements = { 232 | # The paper size ('letterpaper' or 'a4paper'). 233 | #'papersize': 'letterpaper', 234 | 235 | # The font size ('10pt', '11pt' or '12pt'). 236 | #'pointsize': '10pt', 237 | 238 | # Additional stuff for the LaTeX preamble. 239 | #'preamble': '', 240 | } 241 | 242 | # Grouping the document tree into LaTeX files. List of tuples 243 | # (source start file, target name, title, 244 | # author, documentclass [howto, manual, or own class]). 245 | latex_documents = [ 246 | ('index', 247 | project+'.tex', 248 | project+u' Documentation', 249 | Argonne,'manual'), 250 | ] 251 | 252 | # The name of an image file (relative to this directory) to place at the top of 253 | # the title page. 254 | #latex_logo = None 255 | 256 | # For "manual" documents, if this is true, then toplevel headings are parts, 257 | # not chapters. 258 | #latex_use_parts = False 259 | 260 | # If true, show page references after internal links. 261 | #latex_show_pagerefs = False 262 | 263 | # If true, show URL addresses after external links. 264 | #latex_show_urls = False 265 | 266 | # Documents to append as an appendix to all manuals. 267 | #latex_appendices = [] 268 | 269 | # If false, no module index is generated. 270 | #latex_domain_indices = True 271 | 272 | 273 | # -- Options for manual page output --------------------------------------- 274 | 275 | # One entry per manual page. List of tuples 276 | # (source start file, name, description, authors, manual section). 277 | man_pages = [ 278 | ('index',project, 279 | project+u' Documentation', 280 | [Argonne,], 281 | 1) 282 | ] 283 | 284 | # If true, show URL addresses after external links. 285 | #man_show_urls = False 286 | 287 | 288 | # -- Options for Texinfo output ------------------------------------------- 289 | 290 | # Grouping the document tree into Texinfo files. List of tuples 291 | # (source start file, target name, title, author, 292 | # dir menu entry, description, category) 293 | texinfo_documents = [ 294 | ('index', 295 | project, 296 | project+u' Documentation', 297 | Argonne, 298 | project, 299 | 'Scientific Data Exchange'), 300 | ] 301 | 302 | # Documents to append as an appendix to all manuals. 303 | #texinfo_appendices = [] 304 | 305 | # If false, no module index is generated. 306 | #texinfo_domain_indices = True 307 | 308 | # How to display URL addresses: 'footnote', 'no', or 'inline'. 309 | #texinfo_show_urls = 'footnote' 310 | 311 | # If true, do not generate a @detailmenu in the "Top" node's menu. 312 | #ztexinfo_no_detailmenu = False 313 | 314 | # picked from http://read-the-docs.readthedocs.org/en/latest/faq.html 315 | # class Mock(object): 316 | 317 | # __all__ = [] 318 | 319 | # def __init__(self, *args, **kwargs): 320 | # pass 321 | 322 | # def __call__(self, *args, **kwargs): 323 | # return Mock() 324 | 325 | # @classmethod 326 | # def __getattr__(cls, name): 327 | # return Mock() 328 | # def __mul__(self, other): 329 | # return Mock() 330 | # def __rmul__(self, other): 331 | # return Mock() 332 | # def __pow__(self, other): 333 | # return Mock() 334 | # def __div__(self, other): 335 | # return Mock() 336 | # def __add__(self, other): 337 | # return Mock() 338 | # def __radd__(self, other): 339 | # return Mock() 340 | 341 | # MOCK_MODULES = ['h5py', 342 | # 'numpy', 343 | # 'tifffile', 344 | # 'spefile', 345 | # 'netCDF4', 346 | # 'EdfFile', 347 | # 'astropy', 348 | # 'olefile', 349 | # 'pandas', 350 | # 'scipy', 351 | # 'scipy.misc', 352 | # # 'fnmatch', 353 | # # 'glob', 354 | # # 'collections', 355 | # # 'ssl', 356 | # # 'urllib3' 357 | # ] 358 | 359 | # for mod_name in MOCK_MODULES: 360 | # sys.modules[mod_name] = Mock() 361 | # -- Options for Texinfo output ------------------------------------------- 362 | # http://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#confval-autodoc_mock_imports 363 | 364 | autodoc_mock_imports = [ 365 | 'h5py', 366 | 'numpy', 367 | 'tifffile', 368 | 'spefile', 369 | 'netCDF4', 370 | 'EdfFile', 371 | 'astropy', 372 | 'olefile', 373 | 'pandas', 374 | 'scipy', 375 | 'scipy.misc',] 376 | -------------------------------------------------------------------------------- /test/test_dxchange/test_reader.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # ######################################################################### 5 | # Copyright (c) 2015, UChicago Argonne, LLC. All rights reserved. # 6 | # # 7 | # Copyright 2015. UChicago Argonne, LLC. This software was produced # 8 | # under U.S. Government contract DE-AC02-06CH11357 for Argonne National # 9 | # Laboratory (ANL), which is operated by UChicago Argonne, LLC for the # 10 | # U.S. Department of Energy. The U.S. Government has rights to use, # 11 | # reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR # 12 | # UChicago Argonne, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR # 13 | # ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is # 14 | # modified to produce derivative works, such modified software should # 15 | # be clearly marked, so as not to confuse it with the version available # 16 | # from ANL. # 17 | # # 18 | # Additionally, redistribution and use in source and binary forms, with # 19 | # or without modification, are permitted provided that the following # 20 | # conditions are met: # 21 | # # 22 | # * Redistributions of source code must retain the above copyright # 23 | # notice, this list of conditions and the following disclaimer. # 24 | # # 25 | # * Redistributions in binary form must reproduce the above copyright # 26 | # notice, this list of conditions and the following disclaimer in # 27 | # the documentation and/or other materials provided with the # 28 | # distribution. # 29 | # # 30 | # * Neither the name of UChicago Argonne, LLC, Argonne National # 31 | # Laboratory, ANL, the U.S. Government, nor the names of its # 32 | # contributors may be used to endorse or promote products derived # 33 | # from this software without specific prior written permission. # 34 | # # 35 | # THIS SOFTWARE IS PROVIDED BY UChicago Argonne, LLC AND CONTRIBUTORS # 36 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # 37 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # 38 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UChicago # 39 | # Argonne, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # 40 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # 41 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # 42 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # 43 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # 44 | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # 45 | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # 46 | # POSSIBILITY OF SUCH DAMAGE. # 47 | # ######################################################################### 48 | 49 | from __future__ import (absolute_import, division, print_function, 50 | unicode_literals) 51 | 52 | import unittest 53 | from dxchange import reader 54 | import numpy as np 55 | from numpy.testing.utils import assert_equal 56 | import os 57 | 58 | TEST_DIR = os.path.dirname(os.path.dirname(__file__)) 59 | 60 | 61 | class read_files_test_case(unittest.TestCase): 62 | def test_read_xrm_reads_an_xrm_file(self): 63 | print(TEST_DIR) 64 | image_data, metadata = reader.read_xrm( 65 | os.path.join(TEST_DIR, "test_data/test_chip00.xrm"), [1, 2]) 66 | np.testing.utils.assert_(image_data is not False) 67 | np.testing.utils.assert_(metadata is not False) 68 | 69 | def test_read_txrm_reads_a_txrm_file(self): 70 | image_data, metadata = reader.read_txrm( 71 | os.path.join( 72 | TEST_DIR, "test_data/txrm_test_chip_tomo.txrm")) 73 | np.testing.utils.assert_(image_data is not False) 74 | np.testing.utils.assert_(metadata is not False) 75 | 76 | def test_read_txrm_gets_metadata(self): 77 | image_data, metadata = reader.read_txrm( 78 | os.path.join( 79 | TEST_DIR, "test_data/txrm_test_chip_tomo.txrm")) 80 | np.testing.utils.assert_(metadata["thetas"] is not False) 81 | np.testing.utils.assert_(metadata["x_positions"] is not False) 82 | np.testing.utils.assert_(metadata["y_positions"] is not False) 83 | 84 | def test_read_txrm_uses_slice_data(self): 85 | image_data, metadata = reader.read_txrm( 86 | os.path.join( 87 | TEST_DIR, "test_data/txrm_test_chip_tomo.txrm"), (5, 128, 54)) 88 | self.assertEqual(image_data.shape, (5, 128, 54)) 89 | 90 | def test_read_txrm_works_on_a_list_of_slice_data(self): 91 | image_data, metadata = reader.read_txrm( 92 | os.path.join( 93 | TEST_DIR, "test_data/txrm_test_chip_tomo.txrm"), [1, 2]) 94 | self.assertEqual(image_data.shape, (1, 2, 256)) 95 | 96 | def test_read_xrm_stack_reads_multiple_xrms(self): 97 | image_data, metadata = reader.read_xrm_stack( 98 | os.path.join(TEST_DIR, "test_data/test_chip00.xrm"), [0, 1]) 99 | np.testing.utils.assert_(image_data is not False) 100 | np.testing.utils.assert_(metadata is not False) 101 | 102 | # def test_read_hdf5(): 103 | # file_data = reader.read_hdf5("test/test_data/reader.h5", [1,2]) 104 | # np.testing.utils.assert_(file_data is not False) 105 | 106 | def test_read_xrm_gets_theta(self): 107 | array_data, metadata = reader.read_xrm( 108 | os.path.join(TEST_DIR, "test_data/test_chip00.xrm")) 109 | self.assertEqual(metadata["thetas"], [-0.06000000238418579]) 110 | 111 | def test_read_xrm_gets_x_position(self): 112 | array_data, metadata = reader.read_xrm( 113 | os.path.join(TEST_DIR, "test_data/test_chip00.xrm")) 114 | self.assertEqual(metadata["x_positions"], [715.3599853515625]) 115 | 116 | def test_read_xrm_gets_y_position(self): 117 | array_data, metadata = reader.read_xrm( 118 | os.path.join(TEST_DIR, "test_data/test_chip00.xrm")) 119 | self.assertEqual(metadata["y_positions"], [-3761.9892578125]) 120 | 121 | # def test_read_xrm_handles_ref_image(): 122 | # array_data, theta = reader.read_xrm( 123 | # "test/test_data/test_flat.xrm", [1, 2]) 124 | # Need a good flat ref test image 125 | 126 | def test_read_xrm_returns_properly_sliced_np_array_x_slice(self): 127 | image_data, metadata = reader.read_xrm( 128 | os.path.join( 129 | TEST_DIR, 130 | "test_data/test_chip00.xrm", 131 | ), 132 | ((0, 256), ), 133 | ) 134 | self.assertEqual( 135 | image_data.shape, 136 | (256, 512, ), 137 | ) 138 | 139 | def test_read_xrm_returns_properly_sliced_np_array_y_x_slice(self): 140 | image_data, metadata = reader.read_xrm( 141 | os.path.join( 142 | TEST_DIR, 143 | "test_data/test_chip00.xrm", 144 | ), 145 | ((0, 256), (384, 512), ), 146 | ) 147 | self.assertEqual( 148 | image_data.shape, 149 | (256, 128, ), 150 | ) 151 | 152 | def test_read_xrm_stack_gets_theta_set(self): 153 | image_data, metadata = reader.read_xrm_stack( 154 | os.path.join(TEST_DIR, "test_data/test_chip00.xrm"), [0, 1]) 155 | self.assertEqual( 156 | metadata["thetas"], 157 | [ 158 | -0.06000000238418579, 159 | -0.06000000238418579, 160 | ] 161 | ) 162 | 163 | def test_read_xrm_stack_gets_x_position_set(self): 164 | image_data, metadata = reader.read_xrm_stack( 165 | os.path.join(TEST_DIR, "test_data/test_chip00.xrm"), [0, 1]) 166 | self.assertEqual( 167 | metadata["x_positions"], 168 | [ 169 | 715.3599853515625, 170 | 715.3599853515625, 171 | ] 172 | ) 173 | 174 | def test_read_xrm_stack_gets_y_position_set(self): 175 | image_data, metadata = reader.read_xrm_stack( 176 | os.path.join(TEST_DIR, "test_data/test_chip00.xrm"), [0, 1]) 177 | self.assertEqual( 178 | metadata["y_positions"], 179 | [ 180 | -3761.9892578125, 181 | -3761.9892578125, 182 | ] 183 | ) 184 | 185 | def test_read_txrm_gets_theta_set(self): 186 | array_data, metadata = reader.read_txrm( 187 | os.path.join( 188 | TEST_DIR, "test_data/txrm_test_chip_tomo.txrm")) 189 | self.assertEqual( 190 | metadata["thetas"], 191 | [ 192 | -45.018001556396484, 193 | -30.01412582397461, 194 | -15.01412582397461, 195 | -0.014125000685453415, 196 | 14.985876083374023, 197 | 29.985876083374023, 198 | 44.985877990722656 199 | ] 200 | ) 201 | 202 | def test_read_txrm_gets_x_position_set(self): 203 | array_data, metadata = reader.read_txrm( 204 | os.path.join( 205 | TEST_DIR, "test_data/txrm_test_chip_tomo.txrm")) 206 | self.assertEqual( 207 | metadata["x_positions"], 208 | [ 209 | 1019.4400024414062, 210 | 1019.4400024414062, 211 | 1019.4599609375, 212 | 1019.4400024414062, 213 | 1019.4599609375, 214 | 1019.4599609375, 215 | 1019.4599609375, 216 | ] 217 | ) 218 | 219 | def test_read_txrm_gets_y_position_set(self): 220 | array_data, metadata = reader.read_txrm( 221 | os.path.join( 222 | TEST_DIR, "test_data/txrm_test_chip_tomo.txrm")) 223 | self.assertEqual( 224 | metadata["y_positions"], 225 | [ 226 | -3965.869384765625, 227 | -3965.889404296875, 228 | -3965.889404296875, 229 | -3965.889404296875, 230 | -3965.869384765625, 231 | -3965.869384765625, 232 | -3965.869384765625, 233 | ] 234 | ) 235 | 236 | def test_read_txrm_returns_properly_sliced_np_array_x_slice(self): 237 | array_data, metadata = reader.read_txrm( 238 | os.path.join( 239 | TEST_DIR, 240 | "test_data/txrm_test_chip_tomo.txrm" 241 | ), 242 | ((0, 5), ), 243 | ) 244 | self.assertEqual( 245 | array_data.shape, 246 | (5, 256, 256, ) 247 | ) 248 | 249 | def test_read_txrm_returns_properly_sliced_np_array_y_x_slice(self): 250 | array_data, metadata = reader.read_txrm( 251 | os.path.join( 252 | TEST_DIR, 253 | "test_data/txrm_test_chip_tomo.txrm" 254 | ), 255 | ((0, 5), (0, 128), ), 256 | ) 257 | self.assertEqual( 258 | array_data.shape, 259 | (5, 128, 256, ) 260 | ) 261 | 262 | def test_read_txrm_returns_properly_sliced_np_array_z_y_x_slice(self): 263 | array_data, metadata = reader.read_txrm( 264 | os.path.join( 265 | TEST_DIR, 266 | "test_data/txrm_test_chip_tomo.txrm" 267 | ), 268 | ((0, 5), (0, 128), (59, 177), ), 269 | ) 270 | self.assertEqual( 271 | array_data.shape, 272 | (5, 128, 118, ) 273 | ) 274 | 275 | def test_slice_array_does_not_slice_when_not_given_a_slice_range(self): 276 | test_array = [1, 2, 3] 277 | test_array = reader._slice_array(test_array, None) 278 | self.assertEqual(test_array, [1, 2, 3]) 279 | 280 | def test_slice_array_slices_when_given_a_slice_range(self): 281 | test_array = reader._slice_array( 282 | np.array([[1, 2, 3], [1, 2, 3]]), [1, 2]) 283 | np.testing.utils.assert_equal(test_array, np.array([[1, 2]])) 284 | 285 | 286 | class shape_after_slice_test_case(unittest.TestCase): 287 | def test_it_should_return_shape_of_array_if_passed_none(self): 288 | shape = reader._shape_after_slice((2, 2), None) 289 | self.assertEqual((2, 2), shape) 290 | 291 | 292 | class list_file_stack_test_case(unittest.TestCase): 293 | def test_list_file_stack_one_digit(self): 294 | file_stack = reader._list_file_stack("path/image_0.xrm", [1, 2]) 295 | self.assertEqual( 296 | file_stack, ["path/image_1.xrm", "path/image_2.xrm"]) 297 | 298 | def test_list_file_stack_five_digits(self): 299 | file_stack = reader._list_file_stack( 300 | "path/image_00000.xrm", [1, 2]) 301 | self.assertEqual( 302 | file_stack, 303 | ["path/image_00001.xrm", "path/image_00002.xrm"]) 304 | 305 | def test_list_file_stack_ten_digits(self): 306 | file_stack = reader._list_file_stack( 307 | "path/image_0000000000.xrm", [1, 2]) 308 | self.assertEqual( 309 | file_stack, 310 | ["path/image_0000000001.xrm", "path/image_0000000002.xrm"]) 311 | 312 | def test_list_file_stack_underscore_split_digits(self): 313 | file_stack = reader._list_file_stack( 314 | "path/image_00000_00000.xrm", [1, 2]) 315 | self.assertEqual( 316 | file_stack, 317 | ["path/image_00000_00001.xrm", "path/image_00000_00002.xrm"]) 318 | 319 | def test_list_file_stack_long_path(self): 320 | file_stack = reader._list_file_stack( 321 | "someFile/otherFile/image_0.xrm", [1, 2]) 322 | self.assertEqual( 323 | file_stack, 324 | ["someFile/otherFile/image_1.xrm", "someFile/otherFile/image_2.xrm"]) 325 | 326 | class read_tiff_files_test_case(unittest.TestCase): 327 | def test_simple_read_tiff(self): 328 | array_data = reader.read_tiff(os.path.join(TEST_DIR, "test_data/test_0001.tiff")) 329 | 330 | self.assertEqual(array_data.shape, (9, 8)) 331 | np.testing.utils.assert_equal(array_data[0], [0, 1, 2, 3, 4, 5, 6, 7]) 332 | np.testing.utils.assert_equal(array_data[:,0], [0, 8, 16, 24, 32, 40, 48, 56, 64]) 333 | 334 | def test_read_tiff_slice(self): 335 | array_data = reader.read_tiff(os.path.join(TEST_DIR, "test_data/test_0001.tiff"), 336 | slc=((0, 5, 1),(6, 0, -1))) 337 | self.assertEqual(array_data.shape, (5, 6)) 338 | np.testing.utils.assert_equal(array_data[0], [6, 5, 4, 3, 2, 1]) 339 | np.testing.utils.assert_equal(array_data[:, 0], [6, 14, 22, 30, 38]) 340 | 341 | def test_read_tiff_rotate_90(self): 342 | # Note angle only works with float 32 data 343 | array_data = reader.read_tiff(os.path.join(TEST_DIR, "test_data/test_f32_0001.tiff"), 344 | angle=90) 345 | 346 | self.assertEqual(array_data.shape, (9, 8)) 347 | np.testing.utils.assert_equal(array_data[0], [0, 0, 0, 0, 0, 0, 0, 0]) 348 | np.testing.utils.assert_allclose(array_data[1], 349 | [9.390409, 18.998657, 26.565668, 34.689377, 42.62752, 50.751236, 58.318245, 67.92649], 350 | rtol=1e-6) 351 | np.testing.utils.assert_allclose(array_data[:, 0], 352 | [0., 9.390409, 8.189705, 7.242522, 6.231959, 5.221395, 4.274212, 3.073508, 0.], 353 | rtol=1e-6) 354 | 355 | def test_read_tiff_rotate_45(self): 356 | # Note angle only works with float 32 data 357 | array_data = reader.read_tiff(os.path.join(TEST_DIR, "test_data/test_f32_0001.tiff"), 358 | angle=45) 359 | 360 | self.assertEqual(array_data.shape, (9, 8)) 361 | np.testing.utils.assert_allclose(array_data[0], [0., 0., 5.406065, 12.034752, 19.378887, 0., 0., 0.], 362 | rtol=1e-6) 363 | np.testing.utils.assert_allclose(array_data[:, 0], 364 | [0., 0., 2.590548, 7.822704, 13.562099, 17.923655, 0., 0., 0.], 365 | rtol=1e-6) 366 | 367 | def test_read_tiff_mblur1(self): 368 | # Note mblur only works with float 32 data 369 | array_data = reader.read_tiff(os.path.join(TEST_DIR, "test_data/test_spots_0001.tiff"), 370 | mblur=1) 371 | 372 | self.assertEqual(array_data.shape, (10, 10)) 373 | np.testing.utils.assert_equal(array_data[0], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) 374 | np.testing.utils.assert_equal(array_data[2, 3], 25) 375 | np.testing.utils.assert_equal(array_data[5:7, 6:8], [[26, 26], [26, 26]]) 376 | 377 | def test_read_tiff_mblur3(self): 378 | array_data = reader.read_tiff(os.path.join(TEST_DIR, "test_data/test_spots_0001.tiff"), 379 | mblur=3) 380 | 381 | self.assertEqual(array_data.shape, (10, 10)) 382 | np.testing.utils.assert_equal(array_data[0], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) 383 | np.testing.utils.assert_equal(array_data[2, 3], 3) 384 | np.testing.utils.assert_equal(array_data[5:7, 6:8], [[7, 8], [7, 8]]) 385 | -------------------------------------------------------------------------------- /dxchange/writer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # ######################################################################### 5 | # Copyright (c) 2015, UChicago Argonne, LLC. All rights reserved. # 6 | # # 7 | # Copyright 2015. UChicago Argonne, LLC. This software was produced # 8 | # under U.S. Government contract DE-AC02-06CH11357 for Argonne National # 9 | # Laboratory (ANL), which is operated by UChicago Argonne, LLC for the # 10 | # U.S. Department of Energy. The U.S. Government has rights to use, # 11 | # reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR # 12 | # UChicago Argonne, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR # 13 | # ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is # 14 | # modified to produce derivative works, such modified software should # 15 | # be clearly marked, so as not to confuse it with the version available # 16 | # from ANL. # 17 | # # 18 | # Additionally, redistribution and use in source and binary forms, with # 19 | # or without modification, are permitted provided that the following # 20 | # conditions are met: # 21 | # # 22 | # * Redistributions of source code must retain the above copyright # 23 | # notice, this list of conditions and the following disclaimer. # 24 | # # 25 | # * Redistributions in binary form must reproduce the above copyright # 26 | # notice, this list of conditions and the following disclaimer in # 27 | # the documentation and/or other materials provided with the # 28 | # distribution. # 29 | # # 30 | # * Neither the name of UChicago Argonne, LLC, Argonne National # 31 | # Laboratory, ANL, the U.S. Government, nor the names of its # 32 | # contributors may be used to endorse or promote products derived # 33 | # from this software without specific prior written permission. # 34 | # # 35 | # THIS SOFTWARE IS PROVIDED BY UChicago Argonne, LLC AND CONTRIBUTORS # 36 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # 37 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # 38 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UChicago # 39 | # Argonne, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # 40 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # 41 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # 42 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # 43 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # 44 | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # 45 | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # 46 | # POSSIBILITY OF SUCH DAMAGE. # 47 | # ######################################################################### 48 | 49 | """ 50 | Module for data exporting data files. 51 | """ 52 | 53 | import dxchange.dtype as dt 54 | import numpy as np 55 | import os 56 | import h5py 57 | import logging 58 | import re 59 | from itertools import cycle 60 | 61 | __author__ = "Doga Gursoy, Francesco De Carlo" 62 | __copyright__ = "Copyright (c) 2015-2016, UChicago Argonne, LLC." 63 | __version__ = "0.1.0" 64 | __docformat__ = "restructuredtext en" 65 | __all__ = [ 66 | "write_dxf", 67 | "write_hdf5", 68 | "write_netcdf4", 69 | "write_npy", 70 | "write_tiff", 71 | "write_tiff_stack", 72 | "write_vtr", 73 | "write_aps_1id_report", 74 | ] 75 | 76 | logger = logging.getLogger(__name__) 77 | 78 | 79 | def _check_import(modname): 80 | try: 81 | return __import__(modname) 82 | except ImportError: 83 | logger.warn("Warning: " + modname + " module not found") 84 | return None 85 | 86 | 87 | dxfile = _check_import("dxfile") 88 | netCDF4 = _check_import("netCDF4") 89 | 90 | 91 | def get_body(fname): 92 | """ 93 | Get file name after extension removed. 94 | """ 95 | body = os.path.splitext(fname)[0] 96 | return body 97 | 98 | 99 | def get_extension(fname): 100 | """ 101 | Get file extension. 102 | """ 103 | return "." + fname.split(".")[-1] 104 | 105 | 106 | def remove_trailing_digits(text): 107 | digit_string = re.search(r"\d+$", text) 108 | if digit_string is not None: 109 | number_of_digits = len(digit_string.group()) 110 | text = "".join(text[:-number_of_digits]) 111 | return (text, number_of_digits) 112 | else: 113 | return (text, 0) 114 | 115 | 116 | def _init_dirs(fname): 117 | """ 118 | Initialize directories for saving output files. 119 | 120 | Parameters 121 | ---------- 122 | fname : str 123 | Output file name. 124 | """ 125 | dname = os.path.dirname(os.path.abspath(fname)) 126 | if not os.path.exists(dname): 127 | os.makedirs(dname) 128 | 129 | 130 | def _suggest_new_fname(fname, digit): 131 | """ 132 | Suggest new string with an attached (or increased) value indexing 133 | at the end of a given string. 134 | 135 | For example if "myfile.tiff" exist, it will return "myfile-1.tiff". 136 | 137 | Parameters 138 | ---------- 139 | fname : str 140 | Output file name. 141 | digit : int, optional 142 | Number of digits in indexing stacked files. 143 | 144 | Returns 145 | ------- 146 | str 147 | Indexed new string. 148 | """ 149 | if os.path.isfile(fname): 150 | body = get_body(fname) 151 | ext = get_extension(fname) 152 | indq = 1 153 | file_exist = False 154 | while not file_exist: 155 | fname = body + "-" + "{0:0={1}d}".format(indq, digit) + ext 156 | if not os.path.isfile(fname): 157 | file_exist = True 158 | else: 159 | indq += 1 160 | return fname 161 | 162 | 163 | def _init_write(arr, fname, ext, dtype, overwrite): 164 | if not (isinstance(fname, str)): 165 | fname = "tmp/data" + ext 166 | else: 167 | if not fname.endswith(ext): 168 | fname = fname + ext 169 | fname = os.path.abspath(fname) 170 | if not overwrite: 171 | fname = _suggest_new_fname(fname, digit=1) 172 | _init_dirs(fname) 173 | if dtype is not None: 174 | arr = dt.as_dtype(arr, dtype) 175 | return fname, arr 176 | 177 | 178 | def _write_hdf5_dataset(h5object, data, dname, appendaxis, maxshape): 179 | """ 180 | Create a dataset and write data to a specific hdf5 object 181 | (file or group). 182 | 183 | Parameters 184 | ---------- 185 | h5object: h5py object 186 | hdf5 object to write the dataset to. 187 | data : ndarray 188 | Array data to be saved. 189 | dname : str 190 | dataset name 191 | appendaxis : int 192 | Axis of dataset to which data will be appended. 193 | If given will create a resizable dataset. 194 | maxshape: tuple 195 | maxshape of resizable dataset. 196 | Only used if dataset has not been created. 197 | """ 198 | if appendaxis is not None: 199 | if dname not in h5object: 200 | h5object.create_dataset(dname, data=data, maxshape=maxshape) 201 | else: 202 | size = h5object[dname].shape 203 | newsize = list(size) 204 | newsize[appendaxis] += data.shape[appendaxis] 205 | h5object[dname].resize(newsize) 206 | 207 | slices = 3 * [ 208 | slice(None, None, None), 209 | ] 210 | slices[appendaxis] = slice(size[appendaxis], None, None) 211 | h5object[dname][tuple(slices)] = data 212 | else: 213 | h5object.create_dataset(dname, data=data) 214 | 215 | 216 | def write_hdf5( 217 | data, 218 | fname="tmp/data.h5", 219 | gname="exchange", 220 | dname="data", 221 | dtype=None, 222 | overwrite=False, 223 | appendaxis=None, 224 | maxsize=None, 225 | ): 226 | """ 227 | Write data to hdf5 file in a specific group. 228 | 229 | Parameters 230 | ---------- 231 | data : ndarray 232 | Array data to be saved. 233 | fname : str 234 | File name to which the data is saved. ``.h5`` extension 235 | will be appended if it does not already have one. 236 | gname : str, optional 237 | Path to the group inside hdf5 file where data will be written. 238 | dname : str, optional 239 | Name for dataset where data will be written. 240 | dtype : data-type, optional 241 | By default, the data-type is inferred from the input data. 242 | overwrite: bool, optional 243 | if True, overwrites the existing file if the file exists. 244 | appendaxis: int, optional 245 | Axis where data is to be appended to. 246 | Must be given when creating a resizable dataset. 247 | maxsizee: int, optional 248 | Maximum size that the dataset can be resized to along the 249 | given axis. 250 | """ 251 | mode = "w" if overwrite else "a" 252 | 253 | if appendaxis is not None: 254 | overwrite = True # True if appending to file so fname is not changed 255 | maxshape = list(data.shape) 256 | maxshape[appendaxis] = maxsize 257 | else: 258 | maxshape = maxsize 259 | fname, data = _init_write(data, fname, ".h5", dtype, overwrite) 260 | 261 | with h5py.File(fname, mode=mode) as f: 262 | if "implements" not in f: 263 | f.create_dataset("implements", data=gname) 264 | if gname not in f: 265 | f.create_group(gname) 266 | _write_hdf5_dataset(f[gname], data, dname, appendaxis, maxshape) 267 | 268 | 269 | def write_netcdf4( 270 | data, 271 | fname="tmp/data.nc", 272 | dname="VOLUME", 273 | dtype=None, 274 | overwrite=False, 275 | appendaxis=None, 276 | maxsize=None, 277 | ): 278 | """ 279 | Write data to netCDF file. 280 | 281 | Parameters 282 | ---------- 283 | data : ndarray 284 | Array data to be saved. 285 | fname : str 286 | File name to which the data is saved. 287 | """ 288 | mode = "w" if overwrite else "a" 289 | 290 | ncfile = netCDF4.Dataset(fname, mode="w", format="NETCDF3_64BIT") 291 | x_dim = ncfile.createDimension("NX", data.shape[0]) 292 | y_dim = ncfile.createDimension("NY", data.shape[1]) 293 | z_dim = ncfile.createDimension("NZ", data.shape[2]) 294 | d = ncfile.createVariable(dname, data.dtype, ("NX", "NY", "NZ")) 295 | d[:, :, :] = data 296 | ncfile.close() 297 | 298 | 299 | def write_dxf(data, fname="tmp/data.h5", axes="theta:y:x", dtype=None, overwrite=False): 300 | """ 301 | Write data to a data exchange hdf5 file. 302 | 303 | Parameters 304 | ---------- 305 | data : ndarray 306 | Array data to be saved. 307 | fname : str 308 | File name to which the data is saved. ``.h5`` extension 309 | will be appended if it does not already have one. 310 | axes : str 311 | Attribute labels for the data array axes. 312 | dtype : data-type, optional 313 | By default, the data-type is inferred from the input data. 314 | overwrite: bool, optional 315 | if True, overwrites the existing file if the file exists. 316 | """ 317 | fname, data = _init_write(data, fname, ".h5", dtype, overwrite) 318 | f = dxfile.dxtomo.File(fname, mode="w") 319 | f.add_entry( 320 | dxfile.dxtomo.Entry.data( 321 | data={ 322 | "value": data, 323 | "units": "counts", 324 | "description": "transmission", 325 | "axes": axes, 326 | } 327 | ) 328 | ) 329 | f.close() 330 | 331 | 332 | def write_npy(data, fname="tmp/data.npy", dtype=None, overwrite=False): 333 | """ 334 | Write data to a binary file in NumPy ``.npy`` format. 335 | 336 | Parameters 337 | ---------- 338 | data : ndarray 339 | Array data to be saved. 340 | fname : str 341 | File name to which the data is saved. ``.npy`` extension 342 | will be appended if it does not already have one. 343 | """ 344 | fname, data = _init_write(data, fname, ".npy", dtype, overwrite) 345 | np.save(fname, data) 346 | 347 | 348 | def write_tiff(data, fname="tmp/data.tiff", dtype=None, overwrite=False): 349 | """ 350 | Write image data to a tiff file. 351 | 352 | Parameters 353 | ---------- 354 | data : ndarray 355 | Array data to be saved. 356 | fname : str 357 | File name to which the data is saved. ``.tiff`` extension 358 | will be appended if it does not already have one. 359 | dtype : data-type, optional 360 | By default, the data-type is inferred from the input data. 361 | overwrite: bool, optional 362 | if True, overwrites the existing file if the file exists. 363 | """ 364 | fname, data = _init_write(data, fname, ".tiff", dtype, overwrite) 365 | import tifffile 366 | 367 | tifffile.imwrite(fname, data) 368 | 369 | 370 | def write_tiff_stack( 371 | data, fname="tmp/data.tiff", dtype=None, axis=0, digit=5, start=0, overwrite=False 372 | ): 373 | """ 374 | Write data to stack of tiff file. 375 | 376 | Parameters 377 | ---------- 378 | data : ndarray 379 | Array data to be saved. 380 | fname : str 381 | Base file name to which the data is saved. ``.tiff`` extension 382 | will be appended if it does not already have one. 383 | dtype : data-type, optional 384 | By default, the data-type is inferred from the input data. 385 | axis : int, optional 386 | Axis along which stacking is performed. 387 | start : int, optional 388 | First index of file in stack for saving. 389 | digit : int, optional 390 | Number of digits in indexing stacked files. 391 | overwrite: bool, optional 392 | if True, overwrites the existing file if the file exists. 393 | """ 394 | fname, data = _init_write(data, fname, ".tiff", dtype, True) 395 | body = get_body(fname) 396 | ext = get_extension(fname) 397 | _data = np.swapaxes(data, 0, axis) 398 | for m in range(start, start + data.shape[axis]): 399 | _fname = body + "_" + "{0:0={1}d}".format(m, digit) + ext 400 | if not overwrite: 401 | _fname = _suggest_new_fname(_fname, digit=1) 402 | write_tiff(_data[m - start], _fname, overwrite=overwrite) 403 | 404 | 405 | def write_vtr(data, fname="tmp/data.vtr", down_sampling=(5, 5, 5)): 406 | """ 407 | Write the reconstructed data (img stackes) to vtr file (retangular grid) 408 | 409 | Parameters 410 | ---------- 411 | data : np.3darray 412 | reconstructed 3D image stacks with axis=0 as the omega 413 | fname : str 414 | file name of the output vtr file 415 | down_sampling : tuple 416 | down sampling steps along three axes 417 | 418 | Returns 419 | ------- 420 | None 421 | """ 422 | # vtk is only used here, therefore doing an in module import 423 | import vtk 424 | from vtk.util import numpy_support 425 | 426 | # convert to unit8 can significantly reduce the output vtr file 427 | # size, or just do a severe down-sampling 428 | data = ( 429 | _normalize_imgstacks( 430 | data[ 431 | :: down_sampling[0], 432 | :: down_sampling[1], 433 | :: down_sampling[2], 434 | ] 435 | ) 436 | * 255 437 | ) 438 | 439 | # --init rectangular grid 440 | rGrid = vtk.vtkRectilinearGrid() 441 | coordArray = [ 442 | vtk.vtkDoubleArray(), 443 | vtk.vtkDoubleArray(), 444 | vtk.vtkDoubleArray(), 445 | ] 446 | coords = np.array([np.arange(data.shape[i]) for i in range(3)]) 447 | coords = [ 448 | 0.5 449 | * np.array( 450 | [3.0 * coords[i][0] - coords[i][0 + int(len(coords[i]) > 1)]] 451 | + [coords[i][j - 1] + coords[i][j] for j in range(1, len(coords[i]))] 452 | + [3.0 * coords[i][-1] - coords[i][-1 - int(len(coords[i]) > 1)]] 453 | ) 454 | for i in range(3) 455 | ] 456 | grid = np.array(list(map(len, coords)), "i") 457 | rGrid.SetDimensions(*grid) 458 | for i, points in enumerate(coords): 459 | for point in points: 460 | coordArray[i].InsertNextValue(point) 461 | 462 | rGrid.SetXCoordinates(coordArray[0]) 463 | rGrid.SetYCoordinates(coordArray[1]) 464 | rGrid.SetZCoordinates(coordArray[2]) 465 | 466 | # vtk requires x to be the fast axis 467 | # NOTE: 468 | # Proper coordinate transformation is required to connect the 469 | # tomography data with other down-stream analysis (such as FF-HEDM 470 | # and NF-HEDM). 471 | imgstacks = np.swapaxes(data, 0, 2) 472 | 473 | VTKarray = numpy_support.numpy_to_vtk( 474 | num_array=imgstacks.flatten().astype(np.uint8), 475 | deep=True, 476 | array_type=vtk.VTK_UNSIGNED_CHAR, 477 | ) 478 | VTKarray.SetName("img") 479 | rGrid.GetCellData().AddArray(VTKarray) 480 | 481 | rGrid.Modified() 482 | if vtk.VTK_MAJOR_VERSION <= 5: 483 | rGrid.Update() 484 | 485 | # output to file 486 | writer = vtk.vtkXMLRectilinearGridWriter() 487 | writer.SetFileName(fname) 488 | writer.SetDataModeToBinary() 489 | writer.SetCompressorTypeToZLib() 490 | if vtk.VTK_MAJOR_VERSION <= 5: 491 | writer.SetInput(rGrid) 492 | else: 493 | writer.SetInputData(rGrid) 494 | writer.Write() 495 | 496 | 497 | def write_aps_1id_report(df_scanmeta, reportfn): 498 | """ 499 | Generate report of beam conditions based on given DataFrame of the 500 | metadata 501 | 502 | Parameters 503 | ---------- 504 | df_scanmeta : pd.DataFrame 505 | DataFrame of the parsed metadata 506 | dxreader.read_aps_1id_metafile(log_file) 507 | reportfn : str 508 | Output report file name (include path) 509 | 510 | Returns 511 | ------- 512 | pd.DataFrame 513 | Updated Dataframe with added beam conditions 514 | """ 515 | import matplotlib.pyplot as plt 516 | 517 | # add calculation of four beam quality 518 | # -- Temporal Beam Stability 519 | df_scanmeta["TBS"] = df_scanmeta["IC-E3"] / df_scanmeta["IC-E3"].values[0] 520 | # -- Vertical Beam Stability 521 | df_scanmeta["VBS"] = df_scanmeta["IC-E1"] / df_scanmeta["IC-E2"] 522 | # -- Beam Loss at Slit 523 | df_scanmeta["BLS"] = (df_scanmeta["IC-E1"] + df_scanmeta["IC-E2"]) / df_scanmeta[ 524 | "IC-E3" 525 | ] 526 | # -- Beam Loss during Travel 527 | df_scanmeta["BLT"] = df_scanmeta["IC-E5"] / df_scanmeta["IC-E3"] 528 | # -- corresponding color code 529 | pltlbs = ["TBS", "VBS", "BLS", "BLT"] 530 | pltclrs = ["red", "blue", "magenta", "cyan"] 531 | 532 | # start plot 533 | fig = plt.figure(figsize=(8, 3)) 534 | ax = fig.add_subplot(111) 535 | lnclrs = cycle(["gray", "lime", "gray", "black"]) 536 | # -- plot one segment at a time 537 | for lb, clr in zip(pltlbs, pltclrs): 538 | addlabel = True 539 | for layerID in df_scanmeta["layerID"].unique(): 540 | tmpdf = df_scanmeta[df_scanmeta["layerID"] == layerID] 541 | for imgtype in tmpdf["type"].unique(): 542 | # plot the main curve 543 | currentSlice = tmpdf[tmpdf["type"] == imgtype] 544 | 545 | ax.plot( 546 | currentSlice["Date"], 547 | currentSlice[lb], 548 | linewidth=0.2, 549 | color=clr, 550 | label=lb if addlabel else "_nolegend_", 551 | alpha=0.5, 552 | ) 553 | addlabel = False 554 | # add the vertical guard 555 | tmpx = currentSlice["Date"].values 556 | tmpclr = next(lnclrs) 557 | for x in [tmpx[0], tmpx[-1]]: 558 | ax.plot( 559 | [x, x], 560 | [1e-4, 1e2], 561 | color=tmpclr, 562 | linewidth=0.05, 563 | linestyle="dashed", 564 | alpha=0.1, 565 | ) 566 | # -- set canvas property 567 | ax.set_yscale("log") 568 | plt.legend(loc=0) 569 | plt.ylim([0.9, 2.0]) # 10% as cut range 570 | plt.xticks(rotation=45) 571 | # -- save the figure (both pdf and png) 572 | plt.savefig( 573 | reportfn, 574 | transparent=True, 575 | bbox_inches="tight", 576 | pad_inches=0.1, 577 | ) 578 | # -- clear/close figure 579 | plt.close() 580 | 581 | return df_scanmeta 582 | 583 | 584 | def _normalize_imgstacks(img): 585 | """ 586 | Normalize image stacks on a per layer base 587 | 588 | Parameters 589 | ---------- 590 | img : np.3darray 591 | img stacks to be normalized 592 | 593 | Returns 594 | ------- 595 | np.3darray 596 | normalized image stacks 597 | """ 598 | return img / np.amax( 599 | img.reshape( 600 | img.shape[0], 601 | img.shape[1] * img.shape[2], 602 | ), 603 | axis=1, 604 | ).reshape(img.shape[0], 1, 1) 605 | -------------------------------------------------------------------------------- /dxchange/exchange.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # ######################################################################### 5 | # Copyright (c) 2015, UChicago Argonne, LLC. All rights reserved. # 6 | # # 7 | # Copyright 2015. UChicago Argonne, LLC. This software was produced # 8 | # under U.S. Government contract DE-AC02-06CH11357 for Argonne National # 9 | # Laboratory (ANL), which is operated by UChicago Argonne, LLC for the # 10 | # U.S. Department of Energy. The U.S. Government has rights to use, # 11 | # reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR # 12 | # UChicago Argonne, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR # 13 | # ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is # 14 | # modified to produce derivative works, such modified software should # 15 | # be clearly marked, so as not to confuse it with the version available # 16 | # from ANL. # 17 | # # 18 | # Additionally, redistribution and use in source and binary forms, with # 19 | # or without modification, are permitted provided that the following # 20 | # conditions are met: # 21 | # # 22 | # * Redistributions of source code must retain the above copyright # 23 | # notice, this list of conditions and the following disclaimer. # 24 | # # 25 | # * Redistributions in binary form must reproduce the above copyright # 26 | # notice, this list of conditions and the following disclaimer in # 27 | # the documentation and/or other materials provided with the # 28 | # distribution. # 29 | # # 30 | # * Neither the name of UChicago Argonne, LLC, Argonne National # 31 | # Laboratory, ANL, the U.S. Government, nor the names of its # 32 | # contributors may be used to endorse or promote products derived # 33 | # from this software without specific prior written permission. # 34 | # # 35 | # THIS SOFTWARE IS PROVIDED BY UChicago Argonne, LLC AND CONTRIBUTORS # 36 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # 37 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # 38 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UChicago # 39 | # Argonne, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # 40 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # 41 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # 42 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # 43 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # 44 | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # 45 | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # 46 | # POSSIBILITY OF SUCH DAMAGE. # 47 | # ######################################################################### 48 | 49 | """ 50 | Module for describing beamline/experiment specific data recipes. 51 | """ 52 | 53 | from __future__ import (absolute_import, 54 | division, 55 | print_function, 56 | unicode_literals, 57 | ) 58 | 59 | import os.path 60 | import re 61 | import fnmatch 62 | import logging 63 | import numpy as np 64 | import dxchange.reader as dxreader 65 | 66 | __authors__ = "Doga Gursoy, Luis Barroso-Luque, Francesco De Carlo" 67 | __copyright__ = "Copyright (c) 2015-2016, UChicago Argonne, LLC." 68 | __version__ = "0.1.0" 69 | __docformat__ = "restructuredtext en" 70 | __all__ = ['read_als_832', 71 | 'read_als_832h5', 72 | 'read_anka_topotomo', 73 | 'read_aps_tomoscan_hdf5', 74 | 'read_aps_1id', 75 | 'read_aps_2bm', 76 | 'read_aps_5bm', 77 | 'read_aps_7bm', 78 | 'read_aps_8bm', 79 | 'read_aps_13bm', 80 | 'read_aps_13id', 81 | 'read_aps_26id', 82 | 'read_aps_32id', 83 | 'read_aus_microct', 84 | 'read_diamond_l12', 85 | 'read_elettra_syrmep', 86 | 'read_esrf_id19', 87 | 'read_lnls_imx', 88 | 'read_nsls2_fxi18_h5', 89 | 'read_petraIII_p05', 90 | 'read_sls_tomcat', 91 | 'read_sesame_beats', 92 | 'read_nexus'] 93 | 94 | logger = logging.getLogger(__name__) 95 | 96 | 97 | def read_als_832(fname, ind_tomo=None, normalized=False, proj=None, sino=None): 98 | """ 99 | Read ALS 8.3.2 standard data format. 100 | 101 | Parameters 102 | ---------- 103 | fname : str 104 | Path to file name without indices and extension. 105 | 106 | ind_tomo : list of int, optional 107 | Indices of the projection files to read. 108 | 109 | normalized : boolean, optional 110 | If False, darks and flats will not be read. This should 111 | only be used for cases where tomo is already normalized. 112 | 8.3.2 has a plugin that normalization is preferred to be 113 | done with prior to tomopy reconstruction. 114 | 115 | proj : {sequence, int}, optional 116 | Specify projections to read. (start, end, step) 117 | 118 | sino : {sequence, int}, optional 119 | Specify sinograms to read. (start, end, step) 120 | 121 | Returns 122 | ------- 123 | ndarray 124 | 3D tomographic data. 125 | 126 | ndarray 127 | 3D flat field data. 128 | 129 | ndarray 130 | 3D dark field data. 131 | """ 132 | 133 | # File definitions. 134 | fname = os.path.abspath(fname) 135 | 136 | if not normalized: 137 | tomo_name = fname + '_0000_0000.tif' 138 | flat_name = fname + 'bak_0000.tif' 139 | dark_name = fname + 'drk_0000.tif' 140 | log_file = fname + '.sct' 141 | else: 142 | if "output" not in fname: 143 | raise Exception( 144 | 'Please provide the normalized output directory as input') 145 | tomo_name = fname + '_0.tif' 146 | fname = fname.split( 147 | 'output')[0] + fname.split('/')[len(fname.split('/')) - 1] 148 | log_file = fname + '.sct' 149 | 150 | # Read metadata from ALS log file. 151 | contents = open(log_file, 'r') 152 | for line in contents: 153 | if '-nangles' in line: 154 | nproj = int(re.findall(r'\d+', line)[0]) 155 | if '-num_bright_field' in line: 156 | nflat = int(re.findall(r'\d+', line)[0]) 157 | if '-i0cycle' in line: 158 | inter_bright = int(re.findall(r'\d+', line)[1]) 159 | if '-num_dark_fields' in line: 160 | ndark = int(re.findall(r'\d+', line)[0]) 161 | contents.close() 162 | if ind_tomo is None: 163 | ind_tomo = list(range(0, nproj)) 164 | if proj is not None: 165 | ind_tomo = ind_tomo[slice(*proj)] 166 | if not normalized: 167 | ind_flat = list(range(0, nflat)) 168 | if inter_bright > 0: 169 | ind_flat = list(range(0, nproj, inter_bright)) 170 | flat_name = fname + 'bak_0000_0000.tif' 171 | ind_dark = list(range(0, ndark)) 172 | 173 | # Read image data from tiff stack. 174 | tomo = dxreader.read_tiff_stack(tomo_name, ind=ind_tomo, digit=4, 175 | slc=(sino, None)) 176 | 177 | if not normalized: 178 | 179 | # Adheres to 8.3.2 flat/dark naming conventions: 180 | # ----Flats---- 181 | # root_namebak_xxxx_yyyy 182 | # For datasets that take flat at the start and end of its scan, 183 | # xxxx is in incrementals of one, and yyyy is either 0000 or the 184 | # last projection. For datasets that take flat while they scan 185 | # (when the beam fluctuates during scans), 186 | # xxxx is always 0000, and yyyy is in intervals given by log file. 187 | 188 | if inter_bright == 0: 189 | a = [0, nproj - 1] 190 | list_flat = dxreader._list_file_stack(flat_name, ind_flat, digit=4) 191 | for x in ind_flat: 192 | body = os.path.splitext(list_flat[x])[0] + "_" 193 | ext = os.path.splitext(list_flat[x])[1] 194 | for y, z in enumerate(a): 195 | y = body + '{0:0={1}d}'.format(z, 4) + ext 196 | if z == 0: 197 | list_flat[x] = y 198 | else: 199 | list_flat.append(y) 200 | list_flat = sorted(list_flat) 201 | for m, image in enumerate(list_flat): 202 | _arr = dxreader.read_tiff(image) 203 | if m == 0: 204 | dx = len(ind_flat * 2) 205 | dy, dz = _arr.shape 206 | flat = np.zeros((dx, dy, dz)) 207 | flat[m] = _arr 208 | flat = dxreader._slice_array(flat, (None, sino)) 209 | else: 210 | flat = dxreader.read_tiff_stack(flat_name, ind=ind_flat, digit=4, 211 | slc=(sino, None)) 212 | 213 | # Adheres to 8.3.2 flat/dark naming conventions: 214 | # ----Darks---- 215 | # root_namedrk_xxxx_yyyy 216 | # All datasets thus far that take darks at the start and end of 217 | # its scan, so xxxx is in incrementals of one, and yyyy is either 218 | # 0000 or the last projection. 219 | 220 | list_dark = dxreader._list_file_stack(dark_name, ind_dark, digit=4) 221 | for x in ind_dark: 222 | body = os.path.splitext(list_dark[x])[0] + '_' 223 | ext = os.path.splitext(list_dark[x])[1] 224 | body = body + '{0:0={1}d}'.format(nproj - 1, 4) + ext 225 | list_dark[x] = body 226 | list_dark = sorted(list_dark) 227 | for m, image in enumerate(list_dark): 228 | _arr = dxreader.read_tiff(image) 229 | if m == 0: 230 | dx = len(ind_dark) 231 | dy, dz = _arr.shape 232 | dark = np.zeros((dx, dy, dz)) 233 | dark[m] = _arr 234 | dark = dxreader._slice_array(dark, (None, sino)) 235 | else: 236 | flat = np.ones(1) 237 | dark = np.zeros(1) 238 | return tomo, flat, dark 239 | 240 | 241 | def read_als_832h5(fname, ind_tomo=None, ind_flat=None, ind_dark=None, 242 | proj=None, sino=None): 243 | """ 244 | Read ALS 8.3.2 hdf5 file with stacked datasets. 245 | 246 | Parameters 247 | ---------- 248 | 249 | fname : str 250 | Path to hdf5 file. 251 | 252 | ind_tomo : list of int, optional 253 | Indices of the projection files to read. 254 | 255 | ind_flat : list of int, optional 256 | Indices of the flat field files to read. 257 | 258 | ind_dark : list of int, optional 259 | Indices of the dark field files to read. 260 | 261 | proj : {sequence, int}, optional 262 | Specify projections to read. (start, end, step) 263 | 264 | sino : {sequence, int}, optional 265 | Specify sinograms to read. (start, end, step) 266 | 267 | Returns 268 | ------- 269 | ndarray 270 | 3D tomographic data. 271 | 272 | ndarray 273 | 3D flat field data. 274 | 275 | ndarray 276 | 3D dark field data. 277 | 278 | list of int 279 | Indices of flat field data within tomography projection list 280 | """ 281 | 282 | with dxreader.find_dataset_group(fname) as dgroup: 283 | dname = dgroup.name.split('/')[-1] 284 | 285 | tomo_name = dname + '_0000_0000.tif' 286 | flat_name = dname + 'bak_0000.tif' 287 | dark_name = dname + 'drk_0000.tif' 288 | 289 | # Read metadata from dataset group attributes 290 | keys = list(dgroup.attrs.keys()) 291 | if 'nangles' in keys: 292 | nproj = int(dgroup.attrs['nangles']) 293 | if 'i0cycle' in keys: 294 | inter_bright = int(dgroup.attrs['i0cycle']) 295 | if 'num_bright_field' in keys: 296 | nflat = int(dgroup.attrs['num_bright_field']) 297 | else: 298 | nflat = dxreader._count_proj(dgroup, flat_name, nproj, 299 | inter_bright=inter_bright) 300 | if 'num_dark_fields' in keys: 301 | ndark = int(dgroup.attrs['num_dark_fields']) 302 | else: 303 | ndark = dxreader._count_proj(dgroup, dark_name, nproj) 304 | 305 | # Create arrays of indices to read projections, flats and darks 306 | if ind_tomo is None: 307 | ind_tomo = list(range(0, nproj)) 308 | if proj is not None: 309 | ind_tomo = ind_tomo[slice(*proj)] 310 | ind_dark = list(range(0, ndark)) 311 | group_dark = [nproj - 1] 312 | ind_flat = list(range(0, nflat)) 313 | 314 | if inter_bright > 0: 315 | group_flat = list(range(0, nproj, inter_bright)) 316 | if group_flat[-1] != nproj - 1: 317 | group_flat.append(nproj - 1) 318 | elif inter_bright == 0: 319 | group_flat = [0, nproj - 1] 320 | else: 321 | group_flat = None 322 | 323 | tomo = dxreader.read_hdf5_stack( 324 | dgroup, tomo_name, ind_tomo, slc=(None, sino)) 325 | 326 | flat = dxreader.read_hdf5_stack( 327 | dgroup, flat_name, ind_flat, slc=(None, sino), out_ind=group_flat) 328 | 329 | dark = dxreader.read_hdf5_stack( 330 | dgroup, dark_name, ind_dark, slc=(None, sino), out_ind=group_dark) 331 | 332 | return tomo, flat, dark, dxreader._map_loc(ind_tomo, group_flat) 333 | 334 | 335 | def read_anka_topotomo( 336 | fname, ind_tomo, ind_flat, ind_dark, proj=None, sino=None): 337 | """ 338 | Read ANKA TOPO-TOMO standard data format. 339 | 340 | Parameters 341 | ---------- 342 | fname : str 343 | Path to data folder name without indices and extension. 344 | 345 | ind_tomo : list of int 346 | Indices of the projection files to read. 347 | 348 | ind_flat : list of int 349 | Indices of the flat field files to read. 350 | 351 | ind_dark : list of int, optional 352 | Indices of the dark field files to read. 353 | 354 | proj : {sequence, int}, optional 355 | Specify projections to read. (start, end, step) 356 | 357 | sino : {sequence, int}, optional 358 | Specify sinograms to read. (start, end, step) 359 | 360 | Returns 361 | ------- 362 | ndarray 363 | 3D tomographic data. 364 | 365 | ndarray 366 | 3D flat field data. 367 | 368 | ndarray 369 | 3D dark field data. 370 | """ 371 | fname = os.path.abspath(fname) 372 | tomo_name = os.path.join(fname, 'radios', 'image_00000.tif') 373 | flat_name = os.path.join(fname, 'flats', 'image_00000.tif') 374 | dark_name = os.path.join(fname, 'darks', 'image_00000.tif') 375 | if proj is not None: 376 | ind_tomo = ind_tomo[slice(*proj)] 377 | tomo = dxreader.read_tiff_stack( 378 | tomo_name, ind=ind_tomo, slc=(sino, None)) 379 | flat = dxreader.read_tiff_stack( 380 | flat_name, ind=ind_flat, slc=(sino, None)) 381 | dark = dxreader.read_tiff_stack( 382 | dark_name, ind=ind_dark, slc=(sino, None)) 383 | return tomo, flat, dark 384 | 385 | 386 | def read_aps_1id(fname, ind_tomo=None, proj=None, sino=None, layer=0): 387 | """ 388 | Read APS 1-ID standard data format. 389 | 390 | Parameters 391 | ---------- 392 | fname : str 393 | Path to file name without indices and extension. 394 | 395 | ind_tomo : list of int, optional 396 | Indices of the projection files to read. 397 | 398 | proj : {sequence, int}, optional 399 | Specify projections to read. (start, end, step) 400 | 401 | sino : {sequence, int}, optional 402 | Specify sinograms to read. (start, end, step) 403 | 404 | layer: int, optional 405 | Specify the layer to reconstruct 406 | 407 | Returns 408 | ------- 409 | ndarray 410 | 3D tomographic data. 411 | 412 | ndarray 413 | 3D flat field data. 414 | 415 | ndarray 416 | 3D dark field data. 417 | """ 418 | # File definitions. 419 | fname = os.path.abspath(fname) 420 | _fname = fname + '000001.tif' 421 | log_file = fname + 'TomoStillScan.dat' 422 | 423 | # parse the log/metadata file 424 | _metadf = dxreader.read_aps_1id_metafile(log_file) 425 | 426 | # meta data for layer to reconstruct 427 | try: 428 | _layerdf = _metadf[_metadf['layerID'] == layer] 429 | except: 430 | print("Valid layers for reconstruction are: {}".format(_metadf['layerID'].unique())) 431 | 432 | # -- queery image data meta for given layer 433 | # still/projection images 434 | prj_start = _layerdf.loc[_layerdf['type'] == 'still', 'nSeq'].values[0] 435 | nprj = _layerdf.loc[_layerdf['type'] == 'still', 'nSeq'].shape[0] 436 | # dark field images 437 | dark_start = _layerdf.loc[_layerdf['type'] == 'post_dark', 'nSeq'].values[0] 438 | ndark = _layerdf.loc[_layerdf['type'] == 'post_dark', 'nSeq'].shape[0] 439 | # white/flat field images (only use pre_white) 440 | # NOTE: The beam condition might change overtime, therefore flat field 441 | # images are taken both before and after the experiment. 442 | # The implementation here assumes the beam is stable throughout the 443 | # experiment 444 | flat_start = _layerdf.loc[_layerdf['type'] == 'pre_white', 'nSeq'].values[0] 445 | nflat = _layerdf.loc[_layerdf['type'] == 'pre_white', 'nSeq'].shape[0] 446 | 447 | if ind_tomo is None: 448 | ind_tomo = list(range(prj_start, prj_start + nprj)) 449 | if proj is not None: 450 | ind_tomo = ind_tomo[slice(*proj)] 451 | ind_flat = list(range(flat_start, flat_start + nflat)) 452 | ind_dark = list(range(dark_start, dark_start + ndark)) 453 | tomo = dxreader.read_tiff_stack( 454 | _fname, ind=ind_tomo, slc=(sino, None)) 455 | flat = dxreader.read_tiff_stack( 456 | _fname, ind=ind_flat, slc=(sino, None)) 457 | dark = dxreader.read_tiff_stack( 458 | _fname, ind=ind_dark, slc=(sino, None)) 459 | return tomo, flat, dark 460 | 461 | 462 | def read_aps_2bm(fname, proj=None, sino=None): 463 | """ 464 | Read APS 2-BM standard data format. 465 | 466 | Parameters 467 | ---------- 468 | fname : str 469 | Path to hdf5 file. 470 | 471 | proj : {sequence, int}, optional 472 | Specify projections to read. (start, end, step) 473 | 474 | sino : {sequence, int}, optional 475 | Specify sinograms to read. (start, end, step) 476 | 477 | Returns 478 | ------- 479 | ndarray 480 | 3D tomographic data. 481 | 482 | ndarray 483 | 3D flat field data. 484 | 485 | ndarray 486 | 3D dark field data. 487 | """ 488 | return read_aps_tomoscan_hdf5(fname, proj=proj, sino=sino) 489 | 490 | 491 | def read_aps_5bm(fname, sino=None): 492 | """ 493 | Read APS 5-BM standard data format. 494 | 495 | Parameters 496 | ---------- 497 | fname : str 498 | Path to data folder. 499 | 500 | sino : {sequence, int}, optional 501 | Specify sinograms to read. (start, end, step) 502 | 503 | Returns 504 | ------- 505 | ndarray 506 | 3D tomographic data. 507 | 508 | ndarray 509 | 3D flat field data. 510 | 511 | ndarray 512 | 3D dark field data. 513 | """ 514 | fname = os.path.abspath(fname) 515 | tomo_name = os.path.join(fname, 'sdat0000.xmt') 516 | flat_name = os.path.join(fname, 'snor0000.xmt') 517 | dark_name = os.path.join(fname, 'sdarkfile.xmt') 518 | 519 | 520 | ntomo = len(fnmatch.filter(os.listdir(fname), 'sdat*')) 521 | ind_tomo = range(0, ntomo) 522 | nflat = len(fnmatch.filter(os.listdir(fname), 'snor*')) 523 | ind_flat = range(0, nflat) 524 | 525 | tomo = dxreader.read_tiff_stack(tomo_name, ind=ind_tomo, slc=(sino, None)) 526 | flat = dxreader.read_tiff_stack(flat_name, ind=ind_flat, slc=(sino, None)) 527 | dark = dxreader.read_tiff(dark_name, slc=(sino, None)) 528 | 529 | # array bite swapping 530 | for index in ind_tomo: 531 | tomo[index] = tomo[index].byteswap() 532 | 533 | for index in ind_flat: 534 | flat[index] = flat[index].byteswap() 535 | 536 | dark = dark.byteswap() 537 | 538 | return tomo, flat, dark 539 | 540 | 541 | def read_aps_7bm(fname, proj=None, sino=None): 542 | """ 543 | Read APS 7-BM standard data format. 544 | 545 | Parameters 546 | ---------- 547 | fname : str 548 | Path to hdf5 file. 549 | 550 | proj : {sequence, int}, optional 551 | Specify projections to read. (start, end, step) 552 | 553 | sino : {sequence, int}, optional 554 | Specify sinograms to read. (start, end, step) 555 | 556 | Returns 557 | ------- 558 | ndarray 559 | 3D tomographic data. 560 | 561 | array 562 | Projection angles in radian. 563 | """ 564 | tomo_grp = '/'.join(['exchange', 'data']) 565 | theta_grp = '/'.join(['exchange', 'theta']) 566 | tomo = dxreader.read_hdf5(fname, tomo_grp, slc=(proj, sino)) 567 | theta = dxreader.read_hdf5(fname, theta_grp, slc=(proj, )) 568 | return tomo, theta 569 | 570 | 571 | def read_aps_8bm(image_directory, ind_tomo, ind_flat, 572 | image_file_pattern='image_00000.xrm', 573 | flat_file_pattern='ref_00000.xrm', proj=None, sino=None): 574 | """ 575 | Read APS 8-BM tomography data from a stack of xrm files. 576 | 577 | Parameters 578 | ---------- 579 | image_directory : str 580 | Path to data folder name without indices and extension. 581 | 582 | ind_tomo : list of int 583 | Indices of the projection files to read. 584 | 585 | ind_flat : list of int 586 | Indices of the flat field files to read. 587 | 588 | image_file_pattern: string 589 | Specify how the projection files are named. 590 | 591 | flat_file_pattern: string 592 | Specify how the flat reference files are named. 593 | 594 | proj : {sequence, int}, optional 595 | Specify projections to read. (start, end, step) 596 | 597 | sino : {sequence, int}, optional 598 | Specify sinograms to read. (start, end, step) 599 | 600 | Returns 601 | ------- 602 | ndarray 603 | 3D tomographic data. 604 | 605 | ndarray 606 | 3D flat field data. 607 | 608 | dictionary 609 | Image set metadata. 610 | """ 611 | image_directory = os.path.abspath(image_directory) 612 | tomo_name = os.path.join(image_directory, 'radios', image_file_pattern) 613 | flat_name = os.path.join(image_directory, 'flats', flat_file_pattern) 614 | if proj is not None: 615 | ind_tomo = ind_tomo[slice(*proj)] 616 | tomo, metadata = dxreader.read_xrm_stack( 617 | tomo_name, ind=ind_tomo, slc=(sino, None)) 618 | 619 | flat, _ = dxreader.read_xrm_stack( 620 | flat_name, ind=ind_flat, slc=(sino, None)) 621 | return tomo, flat, metadata 622 | 623 | 624 | def read_aps_13bm(fname, file_format, proj=None, sino=None): 625 | """ 626 | Read APS 13-BM standard data format. Searches directory for all necessary 627 | files, and then combines the separate flat fields. 628 | 629 | Parameters 630 | ---------- 631 | fname : str 632 | Path to hdf5 file. 633 | 634 | format : str 635 | Data format. 'spe' or 'netcdf4' 636 | 637 | proj : {sequence, int}, optional 638 | Specify projections to read. (start, end, step) 639 | 640 | sino : {sequence, int}, optional 641 | Specify sinograms to read. (start, end, step) 642 | 643 | Returns 644 | ------- 645 | ndarray 646 | 3D tomographic data. 647 | """ 648 | if file_format == 'netcdf4': 649 | base_name = fname[0:-4] 650 | tomo = dxreader.read_netcdf4(base_name + '2.nc', 'array_data', slc=(proj, sino)) 651 | 652 | flat1 = dxreader.read_netcdf4(base_name + '1.nc', 'array_data', slc=(None, sino)) 653 | flat2 = dxreader.read_netcdf4(base_name + '3.nc', 'array_data', slc=(None, sino)) 654 | flat = np.concatenate((flat1, flat2), axis = 0) 655 | del flat1, flat2 656 | setup = base_name + '.setup' 657 | setup = open(setup, 'r') 658 | setup_data = setup.readlines() 659 | result = {} 660 | for line in setup_data: 661 | words = line[:-1].split(':',1) 662 | result[words[0].lower()] = words[1] 663 | 664 | dark = float(result['dark_current']) 665 | dark = flat*0+dark 666 | theta = np.linspace(0.0, np.pi, tomo.shape[0]) 667 | return tomo, flat, dark, theta 668 | 669 | if file_format == 'hdf5': 670 | return read_aps_tomoscan_hdf5(fname, proj=proj, sino=sino) 671 | 672 | return None 673 | 674 | 675 | def read_aps_13id( 676 | fname, group='/xrfmap/roimap/sum_cor', proj=None, sino=None): 677 | """ 678 | Read APS 13-ID standard data format. 679 | 680 | Parameters 681 | ---------- 682 | fname : str 683 | Path to hdf5 file. 684 | 685 | group : str, optional 686 | Path to the group inside hdf5 file where data is located. 687 | 688 | proj : {sequence, int}, optional 689 | Specify projections to read. (start, end, step) 690 | 691 | sino : {sequence, int}, optional 692 | Specify sinograms to read. (start, end, step) 693 | 694 | Returns 695 | ------- 696 | ndarray 697 | 3D tomographic data. 698 | """ 699 | tomo = dxreader.read_hdf5(fname, group, slc=(None, proj, sino)) 700 | tomo = np.swapaxes(tomo, 0, 1) 701 | tomo = np.swapaxes(tomo, 1, 2).copy() 702 | return tomo 703 | 704 | 705 | def read_aps_26id(image_directory, ind_tomo, ind_flat, 706 | image_file_pattern='image_00000.xrm', 707 | flat_file_pattern='ref_00000.xrm', proj=None, sino=None): 708 | """ 709 | Read APS 26-ID tomography data from a stack of xrm files. 710 | 711 | Parameters 712 | ---------- 713 | fname : str 714 | Path to data folder name without indices and extension. 715 | 716 | ind_tomo : list of int 717 | Indices of the projection files to read. 718 | 719 | ind_flat : list of int 720 | Indices of the flat field files to read. 721 | 722 | proj : {sequence, int}, optional 723 | Specify projections to read. (start, end, step) 724 | 725 | sino : {sequence, int}, optional 726 | Specify sinograms to read. (start, end, step) 727 | 728 | Returns 729 | ------- 730 | ndarray 731 | 3D tomographic data. 732 | 733 | ndarray 734 | 3D flat field data. 735 | 736 | dictionary 737 | Image set metadata. 738 | """ 739 | return read_aps_8bm(image_directory, ind_tomo, ind_flat, 740 | image_file_pattern, flat_file_pattern, proj, sino) 741 | 742 | 743 | def read_aps_32id(fname, exchange_rank=0, proj=None, sino=None, dtype=None): 744 | """ 745 | Read APS 32-ID standard data format. 746 | 747 | Parameters 748 | ---------- 749 | fname : str 750 | Path to hdf5 file. 751 | 752 | exchange_rank : int, optional 753 | exchange_rank is added to "exchange" to point tomopy to the data 754 | to reconstruct. if rank is not set then the data are raw from the 755 | detector and are located under exchange = "exchange/...", to process 756 | data that are the result of some intemedite processing step then 757 | exchange_rank = 1, 2, ... will direct tomopy to process 758 | "exchange1/...", 759 | 760 | proj : {sequence, int}, optional 761 | Specify projections to read. (start, end, step) 762 | 763 | sino : {sequence, int}, optional 764 | Specify sinograms to read. (start, end, step) 765 | 766 | dtype : numpy datatype, optional 767 | Convert data to this datatype on read if specified. 768 | 769 | Returns 770 | ------- 771 | ndarray 772 | 3D tomographic data. 773 | 774 | ndarray 775 | 3D flat field data. 776 | 777 | ndarray 778 | 3D dark field data. 779 | 780 | ndarray 781 | 1D theta in radian. 782 | """ 783 | return read_aps_tomoscan_hdf5(fname, exchange_rank=exchange_rank, proj=proj, sino=sino) 784 | 785 | 786 | def read_aps_tomoscan_hdf5(fname, exchange_rank=0, proj=None, sino=None, dtype=None): 787 | """ 788 | Read APS tomoscan HDF5 format. 789 | 790 | Parameters 791 | ---------- 792 | fname : str 793 | Path to hdf5 file. 794 | 795 | exchange_rank : int, optional 796 | exchange_rank is added to "exchange" to point tomopy to the data 797 | to reconstruct. if rank is not set then the data are raw from the 798 | detector and are located under exchange = "exchange/...", to process 799 | data that are the result of some intermediate processing step then 800 | exchange_rank = 1, 2, ... will direct tomopy to process 801 | "exchange1/...", 802 | 803 | proj : {sequence, int}, optional 804 | Specify projections to read. (start, end, step) 805 | 806 | sino : {sequence, int}, optional 807 | Specify sinograms to read. (start, end, step) 808 | 809 | dtype : numpy datatype, optional 810 | Convert data to this datatype on read if specified. 811 | 812 | Returns 813 | ------- 814 | ndarray 815 | 3D tomographic data. 816 | 817 | ndarray 818 | 3D flat field data. 819 | 820 | ndarray 821 | 3D dark field data. 822 | 823 | ndarray 824 | 1D theta in radian. 825 | """ 826 | if exchange_rank > 0: 827 | exchange_base = 'exchange{:d}'.format(int(exchange_rank)) 828 | else: 829 | exchange_base = "exchange" 830 | 831 | tomo_grp = '/'.join([exchange_base, 'data']) 832 | flat_grp = '/'.join([exchange_base, 'data_white']) 833 | dark_grp = '/'.join([exchange_base, 'data_dark']) 834 | theta_grp = '/'.join([exchange_base, 'theta']) 835 | tomo = dxreader.read_hdf5(fname, tomo_grp, slc=(proj, sino), dtype=dtype) 836 | flat = dxreader.read_hdf5(fname, flat_grp, slc=(None, sino), dtype=dtype) 837 | dark = dxreader.read_hdf5(fname, dark_grp, slc=(None, sino), dtype=dtype) 838 | theta = dxreader.read_hdf5(fname, theta_grp, slc=None) 839 | 840 | if (flat is None) or ((flat.shape[0]==1) and (flat.max() == 0)): 841 | try: 842 | # See if flat_field_value is in the file 843 | flat_field_value = dxreader.read_hdf5(fname, 844 | '/process/acquisition/flat_fields/flat_field_value')[0] 845 | flat = tomo[0,:,:] * 0 + flat_field_value 846 | except: 847 | logger.warn('No flat field data or flat_field_value') 848 | 849 | if (dark is None) or ((dark.shape[0]==1) and (dark.max() == 0)): 850 | try: 851 | # See if dark_field_value is in the file 852 | dark_field_value = dxreader.read_hdf5(fname, 853 | '/process/acquisition/dark_fields/dark_field_value')[0] 854 | dark = tomo[0,:,:] * 0 + dark_field_value 855 | except: 856 | logger.warn('No dark field data or dark_field_value') 857 | 858 | if theta is None: 859 | try: 860 | # See if the rotation start, step, num_angles are in the file 861 | rotation_start = dxreader.read_hdf5(fname, 862 | '/process/acquisition/rotation/rotation_start')[0] 863 | rotation_step = dxreader.read_hdf5(fname, 864 | '/process/acquisition/rotation/rotation_step')[0] 865 | num_angles = dxreader.read_hdf5(fname, 866 | '/process/acquisition/rotation/num_angles')[0] 867 | if num_angles != tomo.shape[0]: 868 | logger.warn('num_angles(%d) is not the same as tomo.shape[0](%d)', num_angles, tomo.shape[0]) 869 | theta = rotation_start + rotation_step*range(num_angles) 870 | except: 871 | theta_size = tomo.shape[0] 872 | logger.warn('Generating "%s" [0-180] deg angles for missing "exchange/theta" dataset', str(theta_size)) 873 | theta = np.linspace(0. , 180, theta_size) 874 | theta = np.deg2rad(theta) 875 | return tomo, flat, dark, theta 876 | 877 | 878 | def read_nexus(fname, 879 | proj=None, 880 | sino=None, 881 | dtype=None, 882 | data_path="/entry1/tomo_entry/data/", 883 | angle_path="/entry1/tomo_entry/data/", 884 | image_key_path="/entry1/instrument/image_key/image_key"): 885 | """ 886 | Read NeXus tomo HDF5 format. 887 | 888 | Parameters 889 | ---------- 890 | fname : str 891 | Path to hdf5 file. 892 | 893 | proj : {sequence, int}, optional 894 | Specify projections to read. (start, end, step) 895 | 896 | sino : {sequence, int}, optional 897 | Specify sinograms to read. (start, end, step) 898 | 899 | dtype : numpy datatype, optional 900 | Convert data to this datatype on read if specified. 901 | 902 | data_path : string, optional 903 | hdf file path location of the data 904 | 905 | image_key_path : string, optional 906 | hdf file path location of the image type keys. 0 = projection, 1 = flat, 2 = dark 907 | 908 | Returns 909 | ------- 910 | ndarray 911 | 3D tomographic data. 912 | 913 | ndarray 914 | 3D flat field data. 915 | 916 | ndarray 917 | 3D dark field data. 918 | 919 | ndarray 920 | 1D theta in radian. 921 | """ 922 | 923 | dataset_grp = '/'.join([data_path, 'data']) 924 | theta_grp = '/'.join([data_path, 'rotation_angle']) 925 | 926 | dataset = read_hdf5(fname, dataset_grp, slc=(proj, sino), dtype=dtype) 927 | angles = read_hdf5(fname, theta_grp, slc=None) 928 | 929 | # Get the indices of where the data, flat and dark are the dataset 930 | with h5.File(fname, "r") as file: 931 | data_indices = [] 932 | darks_indices = [] 933 | flats_indices = [] 934 | 935 | for i, key in enumerate(file[image_key_path]): 936 | if int(key) == 0: 937 | data_indices.append(i) 938 | elif int(key) == 1: 939 | flats_indices.append(i) 940 | elif int(key) == 2: 941 | darks_indices.append(i) 942 | 943 | darks = [dataset[x] for x in darks_indices] 944 | flats = [dataset[x] for x in flats_indices] 945 | tomo = [dataset[x] for x in data_indices] 946 | theta = [angles[x] for x in data_indices] 947 | 948 | theta = np.deg2rad(theta) 949 | return tomo, flat, dark, theta 950 | 951 | 952 | def read_aus_microct(fname, ind_tomo, ind_flat, ind_dark, proj=None, sino=None): 953 | """ 954 | Read Australian Synchrotron micro-CT standard data format. 955 | 956 | Parameters 957 | ---------- 958 | fname : str 959 | Path to data folder. 960 | 961 | ind_tomo : list of int 962 | Indices of the projection files to read. 963 | 964 | ind_flat : list of int 965 | Indices of the flat field files to read. 966 | 967 | ind_dark : list of int 968 | Indices of the dark field files to read. 969 | 970 | proj : {sequence, int}, optional 971 | Specify projections to read. (start, end, step) 972 | 973 | sino : {sequence, int}, optional 974 | Specify sinograms to read. (start, end, step) 975 | 976 | Returns 977 | ------- 978 | ndarray 979 | 3D tomographic data. 980 | 981 | ndarray 982 | 3D flat field data. 983 | 984 | ndarray 985 | 3D dark field data. 986 | """ 987 | fname = os.path.abspath(fname) 988 | tomo_name = os.path.join(fname, 'SAMPLE_T_0000.tif') 989 | flat_name = os.path.join(fname, 'BG__BEFORE_00.tif') 990 | dark_name = os.path.join(fname, 'DF__BEFORE_00.tif') 991 | 992 | if proj is not None: 993 | ind_tomo = ind_tomo[slice(*proj)] 994 | tomo = dxreader.read_tiff_stack( 995 | tomo_name, ind=ind_tomo, slc=(sino, None)) 996 | flat = dxreader.read_tiff_stack( 997 | flat_name, ind=ind_flat, slc=(sino, None)) 998 | dark = dxreader.read_tiff_stack( 999 | dark_name, ind=ind_dark, slc=(sino, None)) 1000 | return tomo, flat, dark 1001 | 1002 | 1003 | def read_esrf_id19(fname, proj=None, sino=None): 1004 | """ 1005 | Read ESRF ID-19 standard data format. 1006 | 1007 | Parameters 1008 | ---------- 1009 | fname : str 1010 | Path to edf file. 1011 | 1012 | proj : {sequence, int}, optional 1013 | Specify projections to read. (start, end, step) 1014 | 1015 | sino : {sequence, int}, optional 1016 | Specify sinograms to read. (start, end, step) 1017 | 1018 | Returns 1019 | ------- 1020 | ndarray 1021 | 3D tomographic data. 1022 | 1023 | ndarray 1024 | 3D flat field data. 1025 | 1026 | ndarray 1027 | 3D dark field data. 1028 | """ 1029 | 1030 | fname = os.path.abspath(fname) 1031 | tomo_name = os.path.join(fname, 'tomo.edf') 1032 | flat_name = os.path.join(fname, 'flat.edf') 1033 | dark_name = os.path.join(fname, 'dark.edf') 1034 | tomo = dxreader.read_edf(tomo_name, slc=(proj, sino)) 1035 | flat = dxreader.read_edf(flat_name, slc=(None, sino)) 1036 | dark = dxreader.read_edf(dark_name, slc=(None, sino)) 1037 | return tomo, flat, dark 1038 | 1039 | 1040 | def read_diamond_l12(fname, ind_tomo, proj=None): 1041 | """ 1042 | Read Diamond Light Source L12 (JEEP) standard data format. 1043 | 1044 | Parameters 1045 | ---------- 1046 | fname : str 1047 | Path to data folder. 1048 | 1049 | ind_tomo : list of int 1050 | Indices of the projection files to read. 1051 | 1052 | proj : {sequence, int}, optional 1053 | Specify projections to read. (start, end, step) 1054 | 1055 | Returns 1056 | ------- 1057 | ndarray 1058 | 3D tomographic data. 1059 | 1060 | ndarray 1061 | 3D flat field data. 1062 | """ 1063 | fname = os.path.abspath(fname) 1064 | tomo_name = os.path.join(fname, 'im_001000.tif') 1065 | flat_name = os.path.join(fname, 'flat_000000.tif') 1066 | ind_flat = list(range(0, 1)) 1067 | if proj is not None: 1068 | ind_tomo = ind_tomo[slice(*proj)] 1069 | tomo = dxreader.read_tiff_stack(tomo_name, ind=ind_tomo) 1070 | flat = dxreader.read_tiff_stack(flat_name, ind=ind_flat) 1071 | return tomo, flat 1072 | 1073 | 1074 | def read_elettra_syrmep( 1075 | fname, ind_tomo, ind_flat, ind_dark, proj=None, sino=None): 1076 | """ 1077 | Read Elettra SYRMEP standard data format. 1078 | 1079 | Parameters 1080 | ---------- 1081 | fname : str 1082 | Path to data folder. 1083 | 1084 | ind_tomo : list of int 1085 | Indices of the projection files to read. 1086 | 1087 | ind_flat : list of int 1088 | Indices of the flat field files to read. 1089 | 1090 | ind_dark : list of int 1091 | Indices of the dark field files to read. 1092 | 1093 | proj : {sequence, int}, optional 1094 | Specify projections to read. (start, end, step) 1095 | 1096 | sino : {sequence, int}, optional 1097 | Specify sinograms to read. (start, end, step) 1098 | 1099 | Returns 1100 | ------- 1101 | ndarray 1102 | 3D tomographic data. 1103 | 1104 | ndarray 1105 | 3D flat field data. 1106 | 1107 | ndarray 1108 | 3D dark field data. 1109 | """ 1110 | fname = os.path.abspath(fname) 1111 | tomo_name = os.path.join(fname, 'tomo_0001.tif') 1112 | flat_name = os.path.join(fname, 'flat_1.tif') 1113 | dark_name = os.path.join(fname, 'dark_1.tif') 1114 | if proj is not None: 1115 | ind_tomo = ind_tomo[slice(*proj)] 1116 | tomo = dxreader.read_tiff_stack( 1117 | tomo_name, ind=ind_tomo, slc=(sino, None)) 1118 | flat = dxreader.read_tiff_stack( 1119 | flat_name, ind=ind_flat, slc=(sino, None)) 1120 | dark = dxreader.read_tiff_stack( 1121 | dark_name, ind=ind_dark, slc=(sino, None)) 1122 | return tomo, flat, dark 1123 | 1124 | 1125 | def read_lnls_imx(folder, proj=None, sino=None): 1126 | """ 1127 | Read LNLS IMX standard data format. 1128 | 1129 | Parameters 1130 | ---------- 1131 | folder : str 1132 | Path to sample folder (containing tomo.h5, flat.h5, dark.h5) 1133 | 1134 | proj : {sequence, int}, optional 1135 | Specify projections to read. (start, end, step) 1136 | 1137 | sino : {sequence, int}, optional 1138 | Specify sinograms to read. (start, end, step) 1139 | 1140 | Returns 1141 | ------- 1142 | ndarray 1143 | 3D tomographic data. 1144 | 1145 | ndarray 1146 | 3D flat field data. 1147 | 1148 | ndarray 1149 | 3D dark field data. 1150 | """ 1151 | folder = os.path.abspath(folder) 1152 | tomo_name = os.path.join(folder, 'tomo.h5') 1153 | flat_name = os.path.join(folder, 'tomo_flat_before.h5') 1154 | dark_name = os.path.join(folder, 'tomo_dark_before.h5') 1155 | tomo = dxreader.read_hdf5(tomo_name, 'images', slc=(proj, sino)) 1156 | flat = dxreader.read_hdf5(flat_name, 'flats', slc=(None, sino)) 1157 | dark = dxreader.read_hdf5(dark_name, 'darks', slc=(None, sino)) 1158 | return tomo, flat, dark 1159 | 1160 | 1161 | def read_nsls2_fxi18_h5(fname, proj=None, sino=None): 1162 | """ 1163 | Read LNLS IMX standard data format. 1164 | 1165 | Parameters 1166 | ---------- 1167 | fname : str 1168 | Path to h5 file. 1169 | 1170 | proj : {sequence, int}, optional 1171 | Specify projections to read. (start, end, step) 1172 | 1173 | sino : {sequence, int}, optional 1174 | Specify sinograms to read. (start, end, step) 1175 | 1176 | Returns 1177 | ------- 1178 | ndarray 1179 | 3D tomographic data. 1180 | 1181 | ndarray 1182 | 3D flat field data. 1183 | 1184 | ndarray 1185 | 3D dark field data. 1186 | 1187 | ndarray 1188 | 1D theta in radian. 1189 | 1190 | """ 1191 | tomo = dxreader.read_hdf5(fname, 'img_tomo', slc=(proj, sino)) 1192 | flats = dxreader.read_hdf5(fname, 'img_bkg', slc=(None, sino)) 1193 | darks = dxreader.read_hdf5(fname, 'img_dark', slc=(None, sino)) 1194 | theta = dxreader.read_hdf5(fname, 'angle', slc=(proj,)) 1195 | theta = np.deg2rad(theta) 1196 | return tomo, flats, darks, theta 1197 | 1198 | 1199 | def read_petraIII_p05( 1200 | fname, ind_tomo, ind_flat, ind_dark, proj=None, sino=None): 1201 | """ 1202 | Read Petra-III P05 standard data format. 1203 | 1204 | Parameters 1205 | ---------- 1206 | fname : str 1207 | Path to data folder. 1208 | 1209 | ind_tomo : list of int 1210 | Indices of the projection files to read. 1211 | 1212 | ind_flat : list of int 1213 | Indices of the flat field files to read. 1214 | 1215 | ind_dark : list of int 1216 | Indices of the dark field files to read. 1217 | 1218 | proj : {sequence, int}, optional 1219 | Specify projections to read. (start, end, step) 1220 | 1221 | sino : {sequence, int}, optional 1222 | Specify sinograms to read. (start, end, step) 1223 | 1224 | Returns 1225 | ------- 1226 | ndarray 1227 | 3D tomographic data. 1228 | 1229 | ndarray 1230 | 3D flat field data. 1231 | 1232 | ndarray 1233 | 3D dark field data. 1234 | """ 1235 | fname = os.path.abspath(fname) 1236 | tomo_name = os.path.join( 1237 | fname, 'scan_0002', 'ccd', 'pco01', 'ccd_0000.tif') 1238 | flat_name = os.path.join( 1239 | fname, 'scan_0001', 'ccd', 'pco01', 'ccd_0000.tif') 1240 | dark_name = os.path.join( 1241 | fname, 'scan_0000', 'ccd', 'pco01', 'ccd_0000.tif') 1242 | if proj is not None: 1243 | ind_tomo = ind_tomo[slice(*proj)] 1244 | tomo = dxreader.read_tiff_stack( 1245 | tomo_name, ind=ind_tomo, slc=(sino, None)) 1246 | flat = dxreader.read_tiff_stack( 1247 | flat_name, ind=ind_flat, slc=(sino, None)) 1248 | dark = dxreader.read_tiff_stack( 1249 | dark_name, ind=ind_dark, slc=(sino, None)) 1250 | return tomo, flat, dark 1251 | 1252 | 1253 | def read_sls_tomcat(fname, ind_tomo=None, proj=None, sino=None): 1254 | """ 1255 | Read SLS TOMCAT standard data format. 1256 | 1257 | Parameters 1258 | ---------- 1259 | fname : str 1260 | Path to file name without indices and extension. 1261 | 1262 | ind_tomo : list of int, optional 1263 | Indices of the projection files to read. 1264 | 1265 | proj : {sequence, int}, optional 1266 | Specify projections to read. (start, end, step) 1267 | 1268 | sino : {sequence, int}, optional 1269 | Specify sinograms to read. (start, end, step) 1270 | 1271 | Returns 1272 | ------- 1273 | ndarray 1274 | 3D tomographic data. 1275 | 1276 | ndarray 1277 | 3D flat field data. 1278 | 1279 | ndarray 1280 | 3D dark field data. 1281 | """ 1282 | # File definitions. 1283 | fname = os.path.abspath(fname) 1284 | _fname = fname + '0001.tif' 1285 | log_file = fname + '.log' 1286 | 1287 | # Read metadata from SLS log file. 1288 | contents = open(log_file, 'r') 1289 | for line in contents: 1290 | ls = line.split() 1291 | if len(ls) > 1: 1292 | if ls[0] == 'Number' and ls[2] == 'projections': 1293 | nproj = int(ls[4]) 1294 | elif ls[0] == 'Number' and ls[2] == 'flats': 1295 | nflat = int(ls[4]) 1296 | elif ls[0] == 'Number' and ls[2] == 'darks': 1297 | ndark = int(ls[4]) 1298 | contents.close() 1299 | 1300 | dark_start = 1 1301 | dark_end = ndark + 1 1302 | flat_start = dark_end 1303 | flat_end = flat_start + nflat 1304 | proj_start = flat_end 1305 | proj_end = proj_start + nproj 1306 | 1307 | if ind_tomo is None: 1308 | ind_tomo = list(range(proj_start, proj_end)) 1309 | if proj is not None: 1310 | ind_tomo = ind_tomo[slice(*proj)] 1311 | ind_flat = list(range(flat_start, flat_end)) 1312 | ind_dark = list(range(dark_start, dark_end)) 1313 | tomo = dxreader.read_tiff_stack( 1314 | _fname, ind=ind_tomo, slc=(sino, None)) 1315 | flat = dxreader.read_tiff_stack( 1316 | _fname, ind=ind_flat, slc=(sino, None)) 1317 | dark = dxreader.read_tiff_stack( 1318 | _fname, ind=ind_dark, slc=(sino, None)) 1319 | 1320 | return tomo, flat, dark 1321 | 1322 | 1323 | def read_sesame_beats(fname, exchange_rank=0, proj=None, sino=None, dtype=None): 1324 | """ 1325 | Read SESAME ID10-BEATS standard data format. 1326 | 1327 | Parameters 1328 | ---------- 1329 | fname : str 1330 | Path to hdf5 file. 1331 | 1332 | exchange_rank : int, optional 1333 | exchange_rank is added to "exchange" to point tomopy to the data 1334 | to reconstruct. if rank is not set then the data are raw from the 1335 | detector and are located under exchange = "exchange/...", to process 1336 | data that are the result of some intemedite processing step then 1337 | exchange_rank = 1, 2, ... will direct tomopy to process 1338 | "exchange1/...", 1339 | 1340 | proj : {sequence, int}, optional 1341 | Specify projections to read. (start, end, step) 1342 | 1343 | sino : {sequence, int}, optional 1344 | Specify sinograms to read. (start, end, step) 1345 | 1346 | dtype : numpy datatype, optional 1347 | Convert data to this datatype on read if specified. 1348 | 1349 | Returns 1350 | ------- 1351 | ndarray 1352 | 3D tomographic data. 1353 | 1354 | ndarray 1355 | 3D flat field data. 1356 | 1357 | ndarray 1358 | 3D dark field data. 1359 | 1360 | ndarray 1361 | 1D theta in radian. 1362 | """ 1363 | 1364 | # read projections, darks, flats and angles 1365 | projs, flats, darks, _ = read_aps_32id(fname, exchange_rank=0, proj=proj, sino=sino) 1366 | theta = np.radians(dxreader.read_hdf5(fname, 'exchange/theta', slc=(proj,))) 1367 | 1368 | return projs, flats, darks, theta 1369 | --------------------------------------------------------------------------------