From 022167ad7d20fc883cc118157aba8b57b078c2e5 Mon Sep 17 00:00:00 2001 From: Ajith Pattammattel Date: Tue, 22 Jul 2025 10:08:42 -0400 Subject: [PATCH 01/18] v1.0.0 upgrade to python 3.12 and pyqt6, excluded xraylarch to avoid intallation issues --- AUTHORS.rst | 26 +- CONTRIBUTING.rst | 208 +- LICENSE | 58 +- MANIFEST.in | 36 +- README.rst | 24 +- docs/Makefile | 40 +- docs/make.bat | 72 +- docs/source/Loading_Data.rst | 92 +- docs/source/_static/.placeholder | 0 docs/source/conf.py | 402 +- docs/source/index.rst | 28 +- docs/source/installation.rst | 74 +- docs/source/release-history.rst | 12 +- docs/source/screenshots/FileOpen.jpg | Bin docs/source/screenshots/Midas_Preview.jpg | Bin docs/source/screenshots/Midas_view.jpg | Bin docs/source/screenshots/midas1.mp4 | Bin docs/source/screenshots/midas_structure.jpg | Bin pyproject.toml | 42 +- requirements-dev.txt | 34 +- requirements.txt | 24 +- setup.cfg | 12 +- versioneer.py | 3644 +++++----- xmidas/__init__.py | 5 +- xmidas/_version.py | 538 -- xmidas/css/darkStyle.css | 68 - xmidas/css/defaultStyle.css | 72 - xmidas/css/modern.css | 289 - xmidas/main.py | 6945 ++++++++----------- xmidas/tests/__init__.py | 0 xmidas/tests/conftest.py | 0 xmidas/tests/test_general.py | 15 - xmidas/uis/ClusterView.ui | 266 - xmidas/uis/ComponentScatterPlot.ui | 195 - xmidas/uis/ComponentView.ui | 296 - xmidas/uis/Log.ui | 68 - xmidas/uis/MaskedView.ui | 352 - xmidas/uis/RefChooser.ui | 247 - xmidas/uis/SVGs/Arrow Down.svg | 12 - xmidas/uis/SVGs/Arrow Left.svg | 12 - xmidas/uis/SVGs/Arrow Right.svg | 12 - xmidas/uis/SVGs/Arrow Up.svg | 12 - xmidas/uis/SVGs/Basket.svg | 14 - xmidas/uis/SVGs/Book.svg | 11 - xmidas/uis/SVGs/Calendar.svg | 14 - xmidas/uis/SVGs/Camera.svg | 14 - xmidas/uis/SVGs/Case.svg | 11 - xmidas/uis/SVGs/Change View.svg | 14 - xmidas/uis/SVGs/Check V2.svg | 13 - xmidas/uis/SVGs/Check.svg | 14 - xmidas/uis/SVGs/Chervon Right Circle.svg | 16 - xmidas/uis/SVGs/Chevron Down Circle.svg | 16 - xmidas/uis/SVGs/Chevron Down.svg | 8 - xmidas/uis/SVGs/Chevron Left Circle.svg | 16 - xmidas/uis/SVGs/Chevron Left.svg | 8 - xmidas/uis/SVGs/Chevron Right.svg | 8 - xmidas/uis/SVGs/Chevron Up Circle.svg | 16 - xmidas/uis/SVGs/Chevron Up.svg | 8 - xmidas/uis/SVGs/Clock.svg | 14 - xmidas/uis/SVGs/Close.svg | 9 - xmidas/uis/SVGs/Cog.svg | 40 - xmidas/uis/SVGs/Cross Circle.svg | 14 - xmidas/uis/SVGs/Download.svg | 13 - xmidas/uis/SVGs/Edit V2.svg | 13 - xmidas/uis/SVGs/Edit.svg | 19 - xmidas/uis/SVGs/File.svg | 16 - xmidas/uis/SVGs/Grid.svg | 16 - xmidas/uis/SVGs/Heart.svg | 18 - xmidas/uis/SVGs/Image.svg | 14 - xmidas/uis/SVGs/Link.svg | 14 - xmidas/uis/SVGs/Location Cursor.svg | 9 - xmidas/uis/SVGs/Location.svg | 11 - xmidas/uis/SVGs/Logout.svg | 16 - xmidas/uis/SVGs/Mail.svg | 9 - xmidas/uis/SVGs/Menu.svg | 17 - xmidas/uis/SVGs/Message.svg | 13 - xmidas/uis/SVGs/Microphone.svg | 13 - xmidas/uis/SVGs/More.svg | 11 - xmidas/uis/SVGs/Plus Circle.svg | 14 - xmidas/uis/SVGs/Plus.svg | 8 - xmidas/uis/SVGs/Power Button.svg | 32 - xmidas/uis/SVGs/Printer.svg | 11 - xmidas/uis/SVGs/Settings.svg | 14 - xmidas/uis/SVGs/Share.svg | 13 - xmidas/uis/SVGs/Shutter.svg | 13 - xmidas/uis/SVGs/Star.svg | 15 - xmidas/uis/SVGs/Trash.svg | 14 - xmidas/uis/SVGs/Trophy.svg | 12 - xmidas/uis/SVGs/User.svg | 14 - xmidas/uis/SVGs/Video.svg | 10 - xmidas/uis/Scatter3D.ui | 130 - xmidas/uis/Scatter3D_plotly.ui | 120 - xmidas/uis/ScatterView.ui | 249 - xmidas/uis/StackViewer.ui | 335 - xmidas/uis/XANESViewer.ui | 431 -- xmidas/uis/__init__.py | 0 xmidas/uis/align_test.ui | 71 - xmidas/uis/animation.gif | Bin 94900 -> 0 bytes xmidas/uis/animation2.gif | Bin 94900 -> 0 bytes xmidas/uis/animationWindow.ui | 68 - xmidas/uis/animation_atom.gif | Bin 383024 -> 0 bytes xmidas/uis/mainwindow_admin.ui | 2814 -------- xmidas/uis/maskedScatterPlotFit.ui | 187 - xmidas/uis/midas.py | 1048 --- xmidas/uis/midasMainwindow.ui | 2938 -------- xmidas/uis/multipleScatterFit.ui | 114 - xmidas/uis/mutlichannel.ui | 458 -- xmidas/uis/pancake.ico | Bin 4158 -> 0 bytes xmidas/uis/singleStackView.ui | 151 - xmidas/uis/splash.gif | Bin 40659 -> 0 bytes xmidas/uis/xanesFitStat.ui | 47 - xmidas/uis/xrf_xanes_gui_3ID.ui | 756 -- 112 files changed, 5141 insertions(+), 19678 deletions(-) mode change 100644 => 100755 AUTHORS.rst mode change 100644 => 100755 CONTRIBUTING.rst mode change 100644 => 100755 LICENSE mode change 100644 => 100755 MANIFEST.in mode change 100644 => 100755 README.rst mode change 100644 => 100755 docs/Makefile mode change 100644 => 100755 docs/make.bat mode change 100644 => 100755 docs/source/Loading_Data.rst mode change 100644 => 100755 docs/source/_static/.placeholder mode change 100644 => 100755 docs/source/conf.py mode change 100644 => 100755 docs/source/index.rst mode change 100644 => 100755 docs/source/installation.rst mode change 100644 => 100755 docs/source/release-history.rst mode change 100644 => 100755 docs/source/screenshots/FileOpen.jpg mode change 100644 => 100755 docs/source/screenshots/Midas_Preview.jpg mode change 100644 => 100755 docs/source/screenshots/Midas_view.jpg mode change 100644 => 100755 docs/source/screenshots/midas1.mp4 mode change 100644 => 100755 docs/source/screenshots/midas_structure.jpg mode change 100644 => 100755 pyproject.toml mode change 100644 => 100755 requirements-dev.txt mode change 100644 => 100755 requirements.txt mode change 100644 => 100755 setup.cfg mode change 100644 => 100755 versioneer.py mode change 100644 => 100755 xmidas/__init__.py delete mode 100644 xmidas/_version.py delete mode 100644 xmidas/css/darkStyle.css delete mode 100644 xmidas/css/defaultStyle.css delete mode 100644 xmidas/css/modern.css delete mode 100644 xmidas/tests/__init__.py delete mode 100644 xmidas/tests/conftest.py delete mode 100644 xmidas/tests/test_general.py delete mode 100644 xmidas/uis/ClusterView.ui delete mode 100644 xmidas/uis/ComponentScatterPlot.ui delete mode 100644 xmidas/uis/ComponentView.ui delete mode 100644 xmidas/uis/Log.ui delete mode 100644 xmidas/uis/MaskedView.ui delete mode 100644 xmidas/uis/RefChooser.ui delete mode 100644 xmidas/uis/SVGs/Arrow Down.svg delete mode 100644 xmidas/uis/SVGs/Arrow Left.svg delete mode 100644 xmidas/uis/SVGs/Arrow Right.svg delete mode 100644 xmidas/uis/SVGs/Arrow Up.svg delete mode 100644 xmidas/uis/SVGs/Basket.svg delete mode 100644 xmidas/uis/SVGs/Book.svg delete mode 100644 xmidas/uis/SVGs/Calendar.svg delete mode 100644 xmidas/uis/SVGs/Camera.svg delete mode 100644 xmidas/uis/SVGs/Case.svg delete mode 100644 xmidas/uis/SVGs/Change View.svg delete mode 100644 xmidas/uis/SVGs/Check V2.svg delete mode 100644 xmidas/uis/SVGs/Check.svg delete mode 100644 xmidas/uis/SVGs/Chervon Right Circle.svg delete mode 100644 xmidas/uis/SVGs/Chevron Down Circle.svg delete mode 100644 xmidas/uis/SVGs/Chevron Down.svg delete mode 100644 xmidas/uis/SVGs/Chevron Left Circle.svg delete mode 100644 xmidas/uis/SVGs/Chevron Left.svg delete mode 100644 xmidas/uis/SVGs/Chevron Right.svg delete mode 100644 xmidas/uis/SVGs/Chevron Up Circle.svg delete mode 100644 xmidas/uis/SVGs/Chevron Up.svg delete mode 100644 xmidas/uis/SVGs/Clock.svg delete mode 100644 xmidas/uis/SVGs/Close.svg delete mode 100644 xmidas/uis/SVGs/Cog.svg delete mode 100644 xmidas/uis/SVGs/Cross Circle.svg delete mode 100644 xmidas/uis/SVGs/Download.svg delete mode 100644 xmidas/uis/SVGs/Edit V2.svg delete mode 100644 xmidas/uis/SVGs/Edit.svg delete mode 100644 xmidas/uis/SVGs/File.svg delete mode 100644 xmidas/uis/SVGs/Grid.svg delete mode 100644 xmidas/uis/SVGs/Heart.svg delete mode 100644 xmidas/uis/SVGs/Image.svg delete mode 100644 xmidas/uis/SVGs/Link.svg delete mode 100644 xmidas/uis/SVGs/Location Cursor.svg delete mode 100644 xmidas/uis/SVGs/Location.svg delete mode 100644 xmidas/uis/SVGs/Logout.svg delete mode 100644 xmidas/uis/SVGs/Mail.svg delete mode 100644 xmidas/uis/SVGs/Menu.svg delete mode 100644 xmidas/uis/SVGs/Message.svg delete mode 100644 xmidas/uis/SVGs/Microphone.svg delete mode 100644 xmidas/uis/SVGs/More.svg delete mode 100644 xmidas/uis/SVGs/Plus Circle.svg delete mode 100644 xmidas/uis/SVGs/Plus.svg delete mode 100644 xmidas/uis/SVGs/Power Button.svg delete mode 100644 xmidas/uis/SVGs/Printer.svg delete mode 100644 xmidas/uis/SVGs/Settings.svg delete mode 100644 xmidas/uis/SVGs/Share.svg delete mode 100644 xmidas/uis/SVGs/Shutter.svg delete mode 100644 xmidas/uis/SVGs/Star.svg delete mode 100644 xmidas/uis/SVGs/Trash.svg delete mode 100644 xmidas/uis/SVGs/Trophy.svg delete mode 100644 xmidas/uis/SVGs/User.svg delete mode 100644 xmidas/uis/SVGs/Video.svg delete mode 100644 xmidas/uis/Scatter3D.ui delete mode 100644 xmidas/uis/Scatter3D_plotly.ui delete mode 100644 xmidas/uis/ScatterView.ui delete mode 100644 xmidas/uis/StackViewer.ui delete mode 100644 xmidas/uis/XANESViewer.ui delete mode 100644 xmidas/uis/__init__.py delete mode 100644 xmidas/uis/align_test.ui delete mode 100644 xmidas/uis/animation.gif delete mode 100644 xmidas/uis/animation2.gif delete mode 100644 xmidas/uis/animationWindow.ui delete mode 100644 xmidas/uis/animation_atom.gif delete mode 100644 xmidas/uis/mainwindow_admin.ui delete mode 100644 xmidas/uis/maskedScatterPlotFit.ui delete mode 100644 xmidas/uis/midas.py delete mode 100644 xmidas/uis/midasMainwindow.ui delete mode 100644 xmidas/uis/multipleScatterFit.ui delete mode 100644 xmidas/uis/mutlichannel.ui delete mode 100644 xmidas/uis/pancake.ico delete mode 100644 xmidas/uis/singleStackView.ui delete mode 100644 xmidas/uis/splash.gif delete mode 100644 xmidas/uis/xanesFitStat.ui delete mode 100644 xmidas/uis/xrf_xanes_gui_3ID.ui diff --git a/AUTHORS.rst b/AUTHORS.rst old mode 100644 new mode 100755 index ca072bb..e4ddda0 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -1,13 +1,13 @@ -======= -Credits -======= - -Maintainer ----------- - -* Brookhaven National Lab <> - -Contributors ------------- - -None yet. Why not be the first? See: CONTRIBUTING.rst +======= +Credits +======= + +Maintainer +---------- + +* Brookhaven National Lab <> + +Contributors +------------ + +None yet. Why not be the first? See: CONTRIBUTING.rst diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst old mode 100644 new mode 100755 index 0b71b77..fbaf5b5 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -1,104 +1,104 @@ -============ -Contributing -============ - -Contributions are welcome, and they are greatly appreciated! Every -little bit helps, and credit will always be given. - -You can contribute in many ways: - -Types of Contributions ----------------------- - -Report Bugs -~~~~~~~~~~~ - -Report bugs at https://github.com/dmgav/xmidas/issues. - -If you are reporting a bug, please include: - -* Any details about your local setup that might be helpful in troubleshooting. -* Detailed steps to reproduce the bug. - -Fix Bugs -~~~~~~~~ - -Look through the GitHub issues for bugs. Anything tagged with "bug" -is open to whoever wants to implement it. - -Implement Features -~~~~~~~~~~~~~~~~~~ - -Look through the GitHub issues for features. Anything tagged with "feature" -is open to whoever wants to implement it. - -Write Documentation -~~~~~~~~~~~~~~~~~~~ - -XMidas could always use more documentation, whether -as part of the official XMidas docs, in docstrings, -or even on the web in blog posts, articles, and such. - -Submit Feedback -~~~~~~~~~~~~~~~ - -The best way to send feedback is to file an issue at https://github.com/dmgav/xmidas/issues. - -If you are proposing a feature: - -* Explain in detail how it would work. -* Keep the scope as narrow as possible, to make it easier to implement. -* Remember that this is a volunteer-driven project, and that contributions - are welcome :) - -Get Started! ------------- - -Ready to contribute? Here's how to set up `xmidas` for local development. - -1. Fork the `xmidas` repo on GitHub. -2. Clone your fork locally:: - - $ git clone git@github.com:your_name_here/xmidas.git - -3. Install your local copy into a virtualenv. Assuming you have virtualenvwrapper installed, this is how you set up your fork for local development:: - - $ mkvirtualenv xmidas - $ cd xmidas/ - $ python setup.py develop - -4. Create a branch for local development:: - - $ git checkout -b name-of-your-bugfix-or-feature - - Now you can make your changes locally. - -5. When you're done making changes, check that your changes pass flake8 and the tests, including testing other Python versions with tox:: - - $ flake8 xmidas tests - $ python setup.py test - $ tox - - To get flake8 and tox, just pip install them into your virtualenv. - -6. Commit your changes and push your branch to GitHub:: - - $ git add . - $ git commit -m "Your detailed description of your changes." - $ git push origin name-of-your-bugfix-or-feature - -7. Submit a pull request through the GitHub website. - -Pull Request Guidelines ------------------------ - -Before you submit a pull request, check that it meets these guidelines: - -1. The pull request should include tests. -2. If the pull request adds functionality, the docs should be updated. Put - your new functionality into a function with a docstring, and add the - feature to the list in README.rst. -3. The pull request should work for Python 2.7, 3.3, 3.4, 3.5 and for PyPy. Check - https://travis-ci.org/dmgav/xmidas/pull_requests - and make sure that the tests pass for all supported Python versions. - +============ +Contributing +============ + +Contributions are welcome, and they are greatly appreciated! Every +little bit helps, and credit will always be given. + +You can contribute in many ways: + +Types of Contributions +---------------------- + +Report Bugs +~~~~~~~~~~~ + +Report bugs at https://github.com/dmgav/xmidas/issues. + +If you are reporting a bug, please include: + +* Any details about your local setup that might be helpful in troubleshooting. +* Detailed steps to reproduce the bug. + +Fix Bugs +~~~~~~~~ + +Look through the GitHub issues for bugs. Anything tagged with "bug" +is open to whoever wants to implement it. + +Implement Features +~~~~~~~~~~~~~~~~~~ + +Look through the GitHub issues for features. Anything tagged with "feature" +is open to whoever wants to implement it. + +Write Documentation +~~~~~~~~~~~~~~~~~~~ + +XMidas could always use more documentation, whether +as part of the official XMidas docs, in docstrings, +or even on the web in blog posts, articles, and such. + +Submit Feedback +~~~~~~~~~~~~~~~ + +The best way to send feedback is to file an issue at https://github.com/dmgav/xmidas/issues. + +If you are proposing a feature: + +* Explain in detail how it would work. +* Keep the scope as narrow as possible, to make it easier to implement. +* Remember that this is a volunteer-driven project, and that contributions + are welcome :) + +Get Started! +------------ + +Ready to contribute? Here's how to set up `xmidas` for local development. + +1. Fork the `xmidas` repo on GitHub. +2. Clone your fork locally:: + + $ git clone git@github.com:your_name_here/xmidas.git + +3. Install your local copy into a virtualenv. Assuming you have virtualenvwrapper installed, this is how you set up your fork for local development:: + + $ mkvirtualenv xmidas + $ cd xmidas/ + $ python setup.py develop + +4. Create a branch for local development:: + + $ git checkout -b name-of-your-bugfix-or-feature + + Now you can make your changes locally. + +5. When you're done making changes, check that your changes pass flake8 and the tests, including testing other Python versions with tox:: + + $ flake8 xmidas tests + $ python setup.py test + $ tox + + To get flake8 and tox, just pip install them into your virtualenv. + +6. Commit your changes and push your branch to GitHub:: + + $ git add . + $ git commit -m "Your detailed description of your changes." + $ git push origin name-of-your-bugfix-or-feature + +7. Submit a pull request through the GitHub website. + +Pull Request Guidelines +----------------------- + +Before you submit a pull request, check that it meets these guidelines: + +1. The pull request should include tests. +2. If the pull request adds functionality, the docs should be updated. Put + your new functionality into a function with a docstring, and add the + feature to the list in README.rst. +3. The pull request should work for Python 2.7, 3.3, 3.4, 3.5 and for PyPy. Check + https://travis-ci.org/dmgav/xmidas/pull_requests + and make sure that the tests pass for all supported Python versions. + diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 index 6853d64..c81fcd7 --- a/LICENSE +++ b/LICENSE @@ -1,29 +1,29 @@ -BSD 3-Clause License - -Copyright (c) 2021, Brookhaven National Lab -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +BSD 3-Clause License + +Copyright (c) 2021, Brookhaven National Lab +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/MANIFEST.in b/MANIFEST.in old mode 100644 new mode 100755 index d822171..0f75c6a --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,18 +1,18 @@ -include AUTHORS.rst -include CONTRIBUTING.rst -include LICENSE -include README.rst -include requirements.txt - -recursive-exclude * __pycache__ -recursive-exclude * *.py[co] - -recursive-include docs *.rst conf.py Makefile make.bat - -include versioneer.py -include xmidas/_version.py -recursive-include xmidas/uis * -recursive-include xmidas/css * - -# If including data files in the package, add them like: -# include path/to/data_file +include AUTHORS.rst +include CONTRIBUTING.rst +include LICENSE +include README.rst +include requirements.txt + +recursive-exclude * __pycache__ +recursive-exclude * *.py[co] + +recursive-include docs *.rst conf.py Makefile make.bat + +include versioneer.py +include xmidas/_version.py +recursive-include xmidas/uis * +recursive-include xmidas/css * + +# If including data files in the package, add them like: +# include path/to/data_file diff --git a/README.rst b/README.rst old mode 100644 new mode 100755 index 61a74e1..c4a226e --- a/README.rst +++ b/README.rst @@ -1,12 +1,12 @@ -====================================================== -XMidas (X-Ray Multimodal Image Data Analysis Software) -====================================================== - -.. image:: https://img.shields.io/pypi/v/xmidas.svg - :target: https://pypi.python.org/pypi/xmidas - -Software for analysis of imaging and spectrosocpy data collected at NSLS-II, -Brookhaven National Laboratory - -* Free software: 3-clause BSD license -* Documentation: https://nsls-ii.github.io/xmidas/. +====================================================== +XMidas (X-Ray Multimodal Image Data Analysis Software) +====================================================== + +.. image:: https://img.shields.io/pypi/v/xmidas.svg + :target: https://pypi.python.org/pypi/xmidas + +Software for analysis of imaging and spectrosocpy data collected at NSLS-II, +Brookhaven National Laboratory + +* Free software: 3-clause BSD license +* Documentation: https://nsls-ii.github.io/xmidas/. diff --git a/docs/Makefile b/docs/Makefile old mode 100644 new mode 100755 index b4a5893..e792a8c --- a/docs/Makefile +++ b/docs/Makefile @@ -1,20 +1,20 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = "-W" # This flag turns warnings into errors. -SPHINXBUILD = sphinx-build -SPHINXPROJ = PackagingScientificPython -SOURCEDIR = source -BUILDDIR = build - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = "-W" # This flag turns warnings into errors. +SPHINXBUILD = sphinx-build +SPHINXPROJ = PackagingScientificPython +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/make.bat b/docs/make.bat old mode 100644 new mode 100755 index 2be8306..ac53d5b --- a/docs/make.bat +++ b/docs/make.bat @@ -1,36 +1,36 @@ -@ECHO OFF - -pushd %~dp0 - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set SOURCEDIR=source -set BUILDDIR=build -set SPHINXPROJ=PackagingScientificPython - -if "%1" == "" goto help - -%SPHINXBUILD% >NUL 2>NUL -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.http://sphinx-doc.org/ - exit /b 1 -) - -%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% -goto end - -:help -%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% - -:end -popd +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build +set SPHINXPROJ=PackagingScientificPython + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% + +:end +popd diff --git a/docs/source/Loading_Data.rst b/docs/source/Loading_Data.rst old mode 100644 new mode 100755 index 6a261e2..363b7e7 --- a/docs/source/Loading_Data.rst +++ b/docs/source/Loading_Data.rst @@ -1,46 +1,46 @@ - -================ -Loading an Image -================ - -Supported Formats -***************** - -XRF Data --------- - -MIDAS can unpack fluorescence .h5 data from NSLS-II beamlines, HXN, XFM, SRX, and TES.XRF data will be normalized with the I0 (scalar) value on the file. - -2D-XANES Data -------------- - -2D and 3D tiff images (stacks). The list of energies has to be loaded as a separate tiff file (see load energy section below) - -To open the above data types use the "Open Image Data" option in the File menu and select the file. - -Load Energy ------------ - -You can load it using the following methods, - -1. file menu option 'Load Energy'. - -2. if you name the energy txt file matching the image file name, the program loads it automatically (like 'test.tiff' , 'test.txt'). - -3. In the folder you exported xanes data from the beamline there should be a file named 'maps_log_tiff.txt'. Copy this to the same folder as the image file, then Midas automatically load energy when you open the image. - - -Create an image stack ---------------------- - -You can also create a 3D image stack from a selection of single tiff files. To do so choose "Open Multiple Files" -options from the File menu. - -.. image:: screenshots/FileOpen.jpg - -Once loaded correctly you should see the image on the top panel and the spectrum on the bottom panel. In case of -incorrect formatting or unsupported formats, the bottom left corner of the program shows the error. - -.. image:: screenshots/Midas_view.jpg - -Also see the `Video Tutorial `_ + +================ +Loading an Image +================ + +Supported Formats +***************** + +XRF Data +-------- + +XMidas can unpack fluorescence .h5 data from NSLS-II beamlines- HXN, XFM, SRX, and TES.XRF data will be normalized with the I0 (scalar) value on the file. + +2D-XANES Data +------------- + +2D and 3D tiff images (stacks). The list of energies has to be loaded as a separate tiff file (see load energy section below) + +To open the above data types use the "Open Image Data" option in the File menu and select the file. + +Load Energy +----------- + +You can load it using the following methods, + +1. file menu option 'Load Energy'. + +2. if you name the energy txt file matching the image file name, the program loads it automatically (like 'test.tiff' , 'test.txt'). + +3. In the folder you exported xanes data from the beamline there should be a log file named 'maps_log_tiff.txt'. Copy this to the same folder as the image file, then XMidas automatically load energy when you open the image. + + +Create an image stack +--------------------- + +You can also create a 3D image stack from a selection of single tiff files. To do so choose "Open Multiple Files" +options from the File menu. + +.. image:: screenshots/FileOpen.jpg + +Once loaded correctly you should see the image on the top panel and the spectrum on the bottom panel. In case of +incorrect formatting or unsupported formats, the bottom left corner of the program shows the error. + +.. image:: screenshots/Midas_view.jpg + +Also see the `Video Tutorial `_ diff --git a/docs/source/_static/.placeholder b/docs/source/_static/.placeholder old mode 100644 new mode 100755 diff --git a/docs/source/conf.py b/docs/source/conf.py old mode 100644 new mode 100755 index abd9ff0..e36fb2d --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -1,201 +1,201 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# XMidas documentation build configuration file, created by -# sphinx-quickstart on Thu Jun 28 12:35:56 2018. -# -# This file is execfile()d with the current directory set to its -# containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# -# import os -# import sys -# sys.path.insert(0, os.path.abspath('.')) - - -# -- General configuration ------------------------------------------------ - -# If your documentation needs a minimal Sphinx version, state it here. -# -# needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.autosummary', - 'sphinx.ext.githubpages', - 'sphinx.ext.intersphinx', - 'sphinx.ext.mathjax', - 'sphinx.ext.viewcode', - 'IPython.sphinxext.ipython_directive', - 'IPython.sphinxext.ipython_console_highlighting', - 'matplotlib.sphinxext.plot_directive', - 'numpydoc', -] - -# Configuration options for plot_directive. See: -# https://github.com/matplotlib/matplotlib/blob/f3ed922d935751e08494e5fb5311d3050a3b637b/lib/matplotlib/sphinxext/plot_directive.py#L81 -plot_html_show_source_link = False -plot_html_show_formats = False - -# Generate the API documentation when building -autosummary_generate = True -numpydoc_show_class_members = False - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix(es) of source filenames. -# You can specify multiple suffix as a list of string: -# -# source_suffix = ['.rst', '.md'] -source_suffix = '.rst' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = 'XMidas' -copyright = '2021, Brookhaven National Lab' -author = 'Brookhaven National Lab' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -import xmidas -# The short X.Y version. -version = xmidas.__version__ -# The full version, including alpha/beta/rc tags. -release = xmidas.__version__ - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# -# This is also used if you do content translation via gettext catalogs. -# Usually you set "language" from the command line for these cases. -language = None - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This patterns also effect to html_static_path and html_extra_path -exclude_patterns = [] - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# If true, `todo` and `todoList` produce output, else they produce nothing. -todo_include_todos = False - - -# -- Options for HTML output ---------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# -html_theme = 'sphinx_rtd_theme' -import sphinx_rtd_theme -html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -# -# html_theme_options = {} - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# Custom sidebar templates, must be a dictionary that maps document names -# to template names. -# -# This is required for the alabaster theme -# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars -html_sidebars = { - '**': [ - 'relations.html', # needs 'show_related': True theme option to display - 'searchbox.html', - ] -} - - -# -- Options for HTMLHelp output ------------------------------------------ - -# Output file base name for HTML help builder. -htmlhelp_basename = 'xmidas' - - -# -- Options for LaTeX output --------------------------------------------- - -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - # - # 'papersize': 'letterpaper', - - # The font size ('10pt', '11pt' or '12pt'). - # - # 'pointsize': '10pt', - - # Additional stuff for the LaTeX preamble. - # - # 'preamble': '', - - # Latex figure (float) alignment - # - # 'figure_align': 'htbp', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). -latex_documents = [ - (master_doc, 'xmidas.tex', 'XMidas Documentation', - 'Contributors', 'manual'), -] - - -# -- Options for manual page output --------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, 'xmidas', 'XMidas Documentation', - [author], 1) -] - - -# -- Options for Texinfo output ------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - (master_doc, 'xmidas', 'XMidas Documentation', - author, 'xmidas', 'Multimodal Image Data Analysis Software', - 'Miscellaneous'), -] - - - - -# Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = { - 'python': ('https://docs.python.org/3/', None), - 'numpy': ('https://numpy.org/doc/stable/', None), - 'scipy': ('https://docs.scipy.org/doc/scipy/reference/', None), - 'pandas': ('https://pandas.pydata.org/pandas-docs/stable', None), - 'matplotlib': ('https://matplotlib.org/stable', None), -} +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# XMidas documentation build configuration file, created by +# sphinx-quickstart on Thu Jun 28 12:35:56 2018. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.autosummary', + 'sphinx.ext.githubpages', + 'sphinx.ext.intersphinx', + 'sphinx.ext.mathjax', + 'sphinx.ext.viewcode', + 'IPython.sphinxext.ipython_directive', + 'IPython.sphinxext.ipython_console_highlighting', + 'matplotlib.sphinxext.plot_directive', + 'numpydoc', +] + +# Configuration options for plot_directive. See: +# https://github.com/matplotlib/matplotlib/blob/f3ed922d935751e08494e5fb5311d3050a3b637b/lib/matplotlib/sphinxext/plot_directive.py#L81 +plot_html_show_source_link = False +plot_html_show_formats = False + +# Generate the API documentation when building +autosummary_generate = True +numpydoc_show_class_members = False + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = 'XMidas' +copyright = '2021, Brookhaven National Lab' +author = 'Brookhaven National Lab' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +import xmidas +# The short X.Y version. +version = xmidas.__version__ +# The full version, including alpha/beta/rc tags. +release = xmidas.__version__ + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This patterns also effect to html_static_path and html_extra_path +exclude_patterns = [] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = False + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'sphinx_rtd_theme' +import sphinx_rtd_theme +html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +# html_theme_options = {} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Custom sidebar templates, must be a dictionary that maps document names +# to template names. +# +# This is required for the alabaster theme +# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars +html_sidebars = { + '**': [ + 'relations.html', # needs 'show_related': True theme option to display + 'searchbox.html', + ] +} + + +# -- Options for HTMLHelp output ------------------------------------------ + +# Output file base name for HTML help builder. +htmlhelp_basename = 'xmidas' + + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'xmidas.tex', 'XMidas Documentation', + 'Contributors', 'manual'), +] + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'xmidas', 'XMidas Documentation', + [author], 1) +] + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'xmidas', 'XMidas Documentation', + author, 'xmidas', 'Multimodal Image Data Analysis Software', + 'Miscellaneous'), +] + + + + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = { + 'python': ('https://docs.python.org/3/', None), + 'numpy': ('https://numpy.org/doc/stable/', None), + 'scipy': ('https://docs.scipy.org/doc/scipy/reference/', None), + 'pandas': ('https://pandas.pydata.org/pandas-docs/stable', None), + 'matplotlib': ('https://matplotlib.org/stable', None), +} diff --git a/docs/source/index.rst b/docs/source/index.rst old mode 100644 new mode 100755 index 41b2dae..0a7d5c3 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -1,14 +1,14 @@ -.. Packaging Scientific Python documentation master file, created by - sphinx-quickstart on Thu Jun 28 12:35:56 2018. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -XMidas Documentation -==================== - -.. toctree:: - :maxdepth: 2 - - installation - Loading_Data - release-history +.. Packaging Scientific Python documentation master file, created by + sphinx-quickstart on Thu Jun 28 12:35:56 2018. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +XMidas Documentation +==================== + +.. toctree:: + :maxdepth: 2 + + installation + Loading_Data + release-history diff --git a/docs/source/installation.rst b/docs/source/installation.rst old mode 100644 new mode 100755 index 4f0f468..df7c283 --- a/docs/source/installation.rst +++ b/docs/source/installation.rst @@ -1,39 +1,35 @@ -============ -Installation -============ - -Create and activate Conda environment:: - - $ conda create -n xmidas_env python=3.9 -c conda-forge - $ conda activate xmidas_env - -Installation from *conda-forge*:: - - $ conda install xmidas -c conda-forge - -Installation from *PyPI* in a new environment:: - - $ conda install xraylarch -c conda-forge - $ pip install xmidas[all] - -Installation into an environment that already has ``PyQt`` and ``opencv`` installed, -for example an environment that has *XMidas* installed from *conda-forge*:: - - $ conda install xraylarch -c conda-forge - $ pip install xmidas - -Development installation from source is similar. In the new Conda environment use :: - - $ conda install xraylarch -c conda-forge - $ pip install -e .[all] - -and if the environment has ``PyQt`` and ``opencv`` installed use :: - - $ conda install xraylarch -c conda-forge - $ pip install -e . - -Start the program by typing :: - - $ xmidas - -in the command line. +============ +Installation +============ + +Create and activate Conda environment:: + + $ conda create -n xmidas_env python=3.9 -c conda-forge + $ conda activate xmidas_env + +Installation from *conda-forge*:: + + $ conda install xmidas -c conda-forge + +Installation from *PyPI* in a new environment:: + + $ pip install xmidas[all] + +Installation into an environment that already has ``PyQt`` and ``opencv`` installed, +for example an environment that has *XMidas* installed from *conda-forge*:: + + $ pip install xmidas + +Development installation from source is similar. In the new Conda environment use :: + + $ pip install -e .[all] + +and if the environment has ``PyQt`` and ``opencv`` installed use :: + + $ pip install -e . + +Start the program by typing :: + + $ xmidas + +in the command line. diff --git a/docs/source/release-history.rst b/docs/source/release-history.rst old mode 100644 new mode 100755 index 53707fb..06610d3 --- a/docs/source/release-history.rst +++ b/docs/source/release-history.rst @@ -1,6 +1,6 @@ -=============== -Release History -=============== - -Initial Release (YYYY-MM-DD) ----------------------------- +=============== +Release History +=============== + +Initial Release (YYYY-MM-DD) +---------------------------- diff --git a/docs/source/screenshots/FileOpen.jpg b/docs/source/screenshots/FileOpen.jpg old mode 100644 new mode 100755 diff --git a/docs/source/screenshots/Midas_Preview.jpg b/docs/source/screenshots/Midas_Preview.jpg old mode 100644 new mode 100755 diff --git a/docs/source/screenshots/Midas_view.jpg b/docs/source/screenshots/Midas_view.jpg old mode 100644 new mode 100755 diff --git a/docs/source/screenshots/midas1.mp4 b/docs/source/screenshots/midas1.mp4 old mode 100644 new mode 100755 diff --git a/docs/source/screenshots/midas_structure.jpg b/docs/source/screenshots/midas_structure.jpg old mode 100644 new mode 100755 diff --git a/pyproject.toml b/pyproject.toml old mode 100644 new mode 100755 index 56e0975..61323cb --- a/pyproject.toml +++ b/pyproject.toml @@ -1,21 +1,21 @@ -[tool.black] -line-length = 115 -include = '\.pyi?$' -exclude = ''' -( - \.eggs # exclude a few common directories in the - | \.git # root of the project - | \.hg - | \.mypy_cache - | \.tox - | \.venv - | \.pytest_cache - | _build - | buck-out - | build - | dist - | docs - | xmidas/uis - | versioneer.py -) -''' +[tool.black] +line-length = 115 +include = '\.pyi?$' +exclude = ''' +( + \.eggs # exclude a few common directories in the + | \.git # root of the project + | \.hg + | \.mypy_cache + | \.tox + | \.venv + | \.pytest_cache + | _build + | buck-out + | build + | dist + | docs + | xmidas/uis + | versioneer.py +) +''' diff --git a/requirements-dev.txt b/requirements-dev.txt old mode 100644 new mode 100755 index 55894e2..355f546 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,17 +1,17 @@ -# These are required for developing the package (running the tests, building -# the documentation) but not necessarily required for _using_ it. -codecov -coverage -flake8 -pytest -sphinx -twine -pre-commit -black -nbstripout -# These are dependencies of various sphinx extensions for documentation. -ipython -matplotlib -numpydoc -sphinx-copybutton -sphinx_rtd_theme +# These are required for developing the package (running the tests, building +# the documentation) but not necessarily required for _using_ it. +codecov +coverage +flake8 +pytest +sphinx +twine +pre-commit +black +nbstripout +# These are dependencies of various sphinx extensions for documentation. +ipython +matplotlib +numpydoc +sphinx-copybutton +sphinx_rtd_theme diff --git a/requirements.txt b/requirements.txt old mode 100644 new mode 100755 index fa5c198..62b72ff --- a/requirements.txt +++ b/requirements.txt @@ -1,13 +1,11 @@ -# List required packages in this file, one per line. -h5py -numpy -pandas -pyqtgraph>=0.12.2 -pystackreg -scikit-image -scikit-learn -scipy>=1.7 -tifffile -silx -xraylarch>=0.9.57 -packaging +# List required packages in this file, one per line. +h5py +numpy +pandas +pyqtgraph +pystackreg +scikit-image +scikit-learn +scipy +tifffile +packaging diff --git a/setup.cfg b/setup.cfg old mode 100644 new mode 100755 index e601645..b6c1992 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ -[versioneer] -VCS = git -style = pep440-post -versionfile_source = xmidas/_version.py -versionfile_build = xmidas/_version.py -tag_prefix = v +[versioneer] +VCS = git +style = pep440-post +versionfile_source = xmidas/_version.py +versionfile_build = xmidas/_version.py +tag_prefix = v diff --git a/versioneer.py b/versioneer.py old mode 100644 new mode 100755 index 64fea1c..7fcc43f --- a/versioneer.py +++ b/versioneer.py @@ -1,1822 +1,1822 @@ - -# Version: 0.18 - -"""The Versioneer - like a rocketeer, but for versions. - -The Versioneer -============== - -* like a rocketeer, but for versions! -* https://github.com/warner/python-versioneer -* Brian Warner -* License: Public Domain -* Compatible With: python2.6, 2.7, 3.2, 3.3, 3.4, 3.5, 3.6, and pypy -* [![Latest Version] -(https://pypip.in/version/versioneer/badge.svg?style=flat) -](https://pypi.python.org/pypi/versioneer/) -* [![Build Status] -(https://travis-ci.org/warner/python-versioneer.png?branch=master) -](https://travis-ci.org/warner/python-versioneer) - -This is a tool for managing a recorded version number in distutils-based -python projects. The goal is to remove the tedious and error-prone "update -the embedded version string" step from your release process. Making a new -release should be as easy as recording a new tag in your version-control -system, and maybe making new tarballs. - - -## Quick Install - -* `pip install versioneer` to somewhere to your $PATH -* add a `[versioneer]` section to your setup.cfg (see below) -* run `versioneer install` in your source tree, commit the results - -## Version Identifiers - -Source trees come from a variety of places: - -* a version-control system checkout (mostly used by developers) -* a nightly tarball, produced by build automation -* a snapshot tarball, produced by a web-based VCS browser, like github's - "tarball from tag" feature -* a release tarball, produced by "setup.py sdist", distributed through PyPI - -Within each source tree, the version identifier (either a string or a number, -this tool is format-agnostic) can come from a variety of places: - -* ask the VCS tool itself, e.g. "git describe" (for checkouts), which knows - about recent "tags" and an absolute revision-id -* the name of the directory into which the tarball was unpacked -* an expanded VCS keyword ($Id$, etc) -* a `_version.py` created by some earlier build step - -For released software, the version identifier is closely related to a VCS -tag. Some projects use tag names that include more than just the version -string (e.g. "myproject-1.2" instead of just "1.2"), in which case the tool -needs to strip the tag prefix to extract the version identifier. For -unreleased software (between tags), the version identifier should provide -enough information to help developers recreate the same tree, while also -giving them an idea of roughly how old the tree is (after version 1.2, before -version 1.3). Many VCS systems can report a description that captures this, -for example `git describe --tags --dirty --always` reports things like -"0.7-1-g574ab98-dirty" to indicate that the checkout is one revision past the -0.7 tag, has a unique revision id of "574ab98", and is "dirty" (it has -uncommitted changes. - -The version identifier is used for multiple purposes: - -* to allow the module to self-identify its version: `myproject.__version__` -* to choose a name and prefix for a 'setup.py sdist' tarball - -## Theory of Operation - -Versioneer works by adding a special `_version.py` file into your source -tree, where your `__init__.py` can import it. This `_version.py` knows how to -dynamically ask the VCS tool for version information at import time. - -`_version.py` also contains `$Revision$` markers, and the installation -process marks `_version.py` to have this marker rewritten with a tag name -during the `git archive` command. As a result, generated tarballs will -contain enough information to get the proper version. - -To allow `setup.py` to compute a version too, a `versioneer.py` is added to -the top level of your source tree, next to `setup.py` and the `setup.cfg` -that configures it. This overrides several distutils/setuptools commands to -compute the version when invoked, and changes `setup.py build` and `setup.py -sdist` to replace `_version.py` with a small static file that contains just -the generated version data. - -## Installation - -See [INSTALL.md](./INSTALL.md) for detailed installation instructions. - -## Version-String Flavors - -Code which uses Versioneer can learn about its version string at runtime by -importing `_version` from your main `__init__.py` file and running the -`get_versions()` function. From the "outside" (e.g. in `setup.py`), you can -import the top-level `versioneer.py` and run `get_versions()`. - -Both functions return a dictionary with different flavors of version -information: - -* `['version']`: A condensed version string, rendered using the selected - style. This is the most commonly used value for the project's version - string. The default "pep440" style yields strings like `0.11`, - `0.11+2.g1076c97`, or `0.11+2.g1076c97.dirty`. See the "Styles" section - below for alternative styles. - -* `['full-revisionid']`: detailed revision identifier. For Git, this is the - full SHA1 commit id, e.g. "1076c978a8d3cfc70f408fe5974aa6c092c949ac". - -* `['date']`: Date and time of the latest `HEAD` commit. For Git, it is the - commit date in ISO 8601 format. This will be None if the date is not - available. - -* `['dirty']`: a boolean, True if the tree has uncommitted changes. Note that - this is only accurate if run in a VCS checkout, otherwise it is likely to - be False or None - -* `['error']`: if the version string could not be computed, this will be set - to a string describing the problem, otherwise it will be None. It may be - useful to throw an exception in setup.py if this is set, to avoid e.g. - creating tarballs with a version string of "unknown". - -Some variants are more useful than others. Including `full-revisionid` in a -bug report should allow developers to reconstruct the exact code being tested -(or indicate the presence of local changes that should be shared with the -developers). `version` is suitable for display in an "about" box or a CLI -`--version` output: it can be easily compared against release notes and lists -of bugs fixed in various releases. - -The installer adds the following text to your `__init__.py` to place a basic -version in `YOURPROJECT.__version__`: - - from ._version import get_versions - __version__ = get_versions()['version'] - del get_versions - -## Styles - -The setup.cfg `style=` configuration controls how the VCS information is -rendered into a version string. - -The default style, "pep440", produces a PEP440-compliant string, equal to the -un-prefixed tag name for actual releases, and containing an additional "local -version" section with more detail for in-between builds. For Git, this is -TAG[+DISTANCE.gHEX[.dirty]] , using information from `git describe --tags ---dirty --always`. For example "0.11+2.g1076c97.dirty" indicates that the -tree is like the "1076c97" commit but has uncommitted changes (".dirty"), and -that this commit is two revisions ("+2") beyond the "0.11" tag. For released -software (exactly equal to a known tag), the identifier will only contain the -stripped tag, e.g. "0.11". - -Other styles are available. See [details.md](details.md) in the Versioneer -source tree for descriptions. - -## Debugging - -Versioneer tries to avoid fatal errors: if something goes wrong, it will tend -to return a version of "0+unknown". To investigate the problem, run `setup.py -version`, which will run the version-lookup code in a verbose mode, and will -display the full contents of `get_versions()` (including the `error` string, -which may help identify what went wrong). - -## Known Limitations - -Some situations are known to cause problems for Versioneer. This details the -most significant ones. More can be found on Github -[issues page](https://github.com/warner/python-versioneer/issues). - -### Subprojects - -Versioneer has limited support for source trees in which `setup.py` is not in -the root directory (e.g. `setup.py` and `.git/` are *not* siblings). The are -two common reasons why `setup.py` might not be in the root: - -* Source trees which contain multiple subprojects, such as - [Buildbot](https://github.com/buildbot/buildbot), which contains both - "master" and "slave" subprojects, each with their own `setup.py`, - `setup.cfg`, and `tox.ini`. Projects like these produce multiple PyPI - distributions (and upload multiple independently-installable tarballs). -* Source trees whose main purpose is to contain a C library, but which also - provide bindings to Python (and perhaps other langauges) in subdirectories. - -Versioneer will look for `.git` in parent directories, and most operations -should get the right version string. However `pip` and `setuptools` have bugs -and implementation details which frequently cause `pip install .` from a -subproject directory to fail to find a correct version string (so it usually -defaults to `0+unknown`). - -`pip install --editable .` should work correctly. `setup.py install` might -work too. - -Pip-8.1.1 is known to have this problem, but hopefully it will get fixed in -some later version. - -[Bug #38](https://github.com/warner/python-versioneer/issues/38) is tracking -this issue. The discussion in -[PR #61](https://github.com/warner/python-versioneer/pull/61) describes the -issue from the Versioneer side in more detail. -[pip PR#3176](https://github.com/pypa/pip/pull/3176) and -[pip PR#3615](https://github.com/pypa/pip/pull/3615) contain work to improve -pip to let Versioneer work correctly. - -Versioneer-0.16 and earlier only looked for a `.git` directory next to the -`setup.cfg`, so subprojects were completely unsupported with those releases. - -### Editable installs with setuptools <= 18.5 - -`setup.py develop` and `pip install --editable .` allow you to install a -project into a virtualenv once, then continue editing the source code (and -test) without re-installing after every change. - -"Entry-point scripts" (`setup(entry_points={"console_scripts": ..})`) are a -convenient way to specify executable scripts that should be installed along -with the python package. - -These both work as expected when using modern setuptools. When using -setuptools-18.5 or earlier, however, certain operations will cause -`pkg_resources.DistributionNotFound` errors when running the entrypoint -script, which must be resolved by re-installing the package. This happens -when the install happens with one version, then the egg_info data is -regenerated while a different version is checked out. Many setup.py commands -cause egg_info to be rebuilt (including `sdist`, `wheel`, and installing into -a different virtualenv), so this can be surprising. - -[Bug #83](https://github.com/warner/python-versioneer/issues/83) describes -this one, but upgrading to a newer version of setuptools should probably -resolve it. - -### Unicode version strings - -While Versioneer works (and is continually tested) with both Python 2 and -Python 3, it is not entirely consistent with bytes-vs-unicode distinctions. -Newer releases probably generate unicode version strings on py2. It's not -clear that this is wrong, but it may be surprising for applications when then -write these strings to a network connection or include them in bytes-oriented -APIs like cryptographic checksums. - -[Bug #71](https://github.com/warner/python-versioneer/issues/71) investigates -this question. - - -## Updating Versioneer - -To upgrade your project to a new release of Versioneer, do the following: - -* install the new Versioneer (`pip install -U versioneer` or equivalent) -* edit `setup.cfg`, if necessary, to include any new configuration settings - indicated by the release notes. See [UPGRADING](./UPGRADING.md) for details. -* re-run `versioneer install` in your source tree, to replace - `SRC/_version.py` -* commit any changed files - -## Future Directions - -This tool is designed to make it easily extended to other version-control -systems: all VCS-specific components are in separate directories like -src/git/ . The top-level `versioneer.py` script is assembled from these -components by running make-versioneer.py . In the future, make-versioneer.py -will take a VCS name as an argument, and will construct a version of -`versioneer.py` that is specific to the given VCS. It might also take the -configuration arguments that are currently provided manually during -installation by editing setup.py . Alternatively, it might go the other -direction and include code from all supported VCS systems, reducing the -number of intermediate scripts. - - -## License - -To make Versioneer easier to embed, all its code is dedicated to the public -domain. The `_version.py` that it creates is also in the public domain. -Specifically, both are released under the Creative Commons "Public Domain -Dedication" license (CC0-1.0), as described in -https://creativecommons.org/publicdomain/zero/1.0/ . - -""" - -from __future__ import print_function -try: - import configparser -except ImportError: - import ConfigParser as configparser -import errno -import json -import os -import re -import subprocess -import sys - - -class VersioneerConfig: - """Container for Versioneer configuration parameters.""" - - -def get_root(): - """Get the project root directory. - - We require that all commands are run from the project root, i.e. the - directory that contains setup.py, setup.cfg, and versioneer.py . - """ - root = os.path.realpath(os.path.abspath(os.getcwd())) - setup_py = os.path.join(root, "setup.py") - versioneer_py = os.path.join(root, "versioneer.py") - if not (os.path.exists(setup_py) or os.path.exists(versioneer_py)): - # allow 'python path/to/setup.py COMMAND' - root = os.path.dirname(os.path.realpath(os.path.abspath(sys.argv[0]))) - setup_py = os.path.join(root, "setup.py") - versioneer_py = os.path.join(root, "versioneer.py") - if not (os.path.exists(setup_py) or os.path.exists(versioneer_py)): - err = ("Versioneer was unable to run the project root directory. " - "Versioneer requires setup.py to be executed from " - "its immediate directory (like 'python setup.py COMMAND'), " - "or in a way that lets it use sys.argv[0] to find the root " - "(like 'python path/to/setup.py COMMAND').") - raise VersioneerBadRootError(err) - try: - # Certain runtime workflows (setup.py install/develop in a setuptools - # tree) execute all dependencies in a single python process, so - # "versioneer" may be imported multiple times, and python's shared - # module-import table will cache the first one. So we can't use - # os.path.dirname(__file__), as that will find whichever - # versioneer.py was first imported, even in later projects. - me = os.path.realpath(os.path.abspath(__file__)) - me_dir = os.path.normcase(os.path.splitext(me)[0]) - vsr_dir = os.path.normcase(os.path.splitext(versioneer_py)[0]) - if me_dir != vsr_dir: - print("Warning: build in %s is using versioneer.py from %s" - % (os.path.dirname(me), versioneer_py)) - except NameError: - pass - return root - - -def get_config_from_root(root): - """Read the project setup.cfg file to determine Versioneer config.""" - # This might raise EnvironmentError (if setup.cfg is missing), or - # configparser.NoSectionError (if it lacks a [versioneer] section), or - # configparser.NoOptionError (if it lacks "VCS="). See the docstring at - # the top of versioneer.py for instructions on writing your setup.cfg . - setup_cfg = os.path.join(root, "setup.cfg") - parser = configparser.SafeConfigParser() - with open(setup_cfg, "r") as f: - parser.readfp(f) - VCS = parser.get("versioneer", "VCS") # mandatory - - def get(parser, name): - if parser.has_option("versioneer", name): - return parser.get("versioneer", name) - return None - cfg = VersioneerConfig() - cfg.VCS = VCS - cfg.style = get(parser, "style") or "" - cfg.versionfile_source = get(parser, "versionfile_source") - cfg.versionfile_build = get(parser, "versionfile_build") - cfg.tag_prefix = get(parser, "tag_prefix") - if cfg.tag_prefix in ("''", '""'): - cfg.tag_prefix = "" - cfg.parentdir_prefix = get(parser, "parentdir_prefix") - cfg.verbose = get(parser, "verbose") - return cfg - - -class NotThisMethod(Exception): - """Exception raised if a method is not valid for the current scenario.""" - - -# these dictionaries contain VCS-specific tools -LONG_VERSION_PY = {} -HANDLERS = {} - - -def register_vcs_handler(vcs, method): # decorator - """Decorator to mark a method as the handler for a particular VCS.""" - def decorate(f): - """Store f in HANDLERS[vcs][method].""" - if vcs not in HANDLERS: - HANDLERS[vcs] = {} - HANDLERS[vcs][method] = f - return f - return decorate - - -def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, - env=None): - """Call the given command(s).""" - assert isinstance(commands, list) - p = None - for c in commands: - try: - dispcmd = str([c] + args) - # remember shell=False, so use git.cmd on windows, not just git - p = subprocess.Popen([c] + args, cwd=cwd, env=env, - stdout=subprocess.PIPE, - stderr=(subprocess.PIPE if hide_stderr - else None)) - break - except EnvironmentError: - e = sys.exc_info()[1] - if e.errno == errno.ENOENT: - continue - if verbose: - print("unable to run %s" % dispcmd) - print(e) - return None, None - else: - if verbose: - print("unable to find command, tried %s" % (commands,)) - return None, None - stdout = p.communicate()[0].strip() - if sys.version_info[0] >= 3: - stdout = stdout.decode() - if p.returncode != 0: - if verbose: - print("unable to run %s (error)" % dispcmd) - print("stdout was %s" % stdout) - return None, p.returncode - return stdout, p.returncode - - -LONG_VERSION_PY['git'] = ''' -# This file helps to compute a version number in source trees obtained from -# git-archive tarball (such as those provided by githubs download-from-tag -# feature). Distribution tarballs (built by setup.py sdist) and build -# directories (produced by setup.py build) will contain a much shorter file -# that just contains the computed version number. - -# This file is released into the public domain. Generated by -# versioneer-0.18 (https://github.com/warner/python-versioneer) - -"""Git implementation of _version.py.""" - -import errno -import os -import re -import subprocess -import sys - - -def get_keywords(): - """Get the keywords needed to look up the version information.""" - # these strings will be replaced by git during git-archive. - # setup.py/versioneer.py will grep for the variable names, so they must - # each be defined on a line of their own. _version.py will just call - # get_keywords(). - git_refnames = "%(DOLLAR)sFormat:%%d%(DOLLAR)s" - git_full = "%(DOLLAR)sFormat:%%H%(DOLLAR)s" - git_date = "%(DOLLAR)sFormat:%%ci%(DOLLAR)s" - keywords = {"refnames": git_refnames, "full": git_full, "date": git_date} - return keywords - - -class VersioneerConfig: - """Container for Versioneer configuration parameters.""" - - -def get_config(): - """Create, populate and return the VersioneerConfig() object.""" - # these strings are filled in when 'setup.py versioneer' creates - # _version.py - cfg = VersioneerConfig() - cfg.VCS = "git" - cfg.style = "%(STYLE)s" - cfg.tag_prefix = "%(TAG_PREFIX)s" - cfg.parentdir_prefix = "%(PARENTDIR_PREFIX)s" - cfg.versionfile_source = "%(VERSIONFILE_SOURCE)s" - cfg.verbose = False - return cfg - - -class NotThisMethod(Exception): - """Exception raised if a method is not valid for the current scenario.""" - - -LONG_VERSION_PY = {} -HANDLERS = {} - - -def register_vcs_handler(vcs, method): # decorator - """Decorator to mark a method as the handler for a particular VCS.""" - def decorate(f): - """Store f in HANDLERS[vcs][method].""" - if vcs not in HANDLERS: - HANDLERS[vcs] = {} - HANDLERS[vcs][method] = f - return f - return decorate - - -def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, - env=None): - """Call the given command(s).""" - assert isinstance(commands, list) - p = None - for c in commands: - try: - dispcmd = str([c] + args) - # remember shell=False, so use git.cmd on windows, not just git - p = subprocess.Popen([c] + args, cwd=cwd, env=env, - stdout=subprocess.PIPE, - stderr=(subprocess.PIPE if hide_stderr - else None)) - break - except EnvironmentError: - e = sys.exc_info()[1] - if e.errno == errno.ENOENT: - continue - if verbose: - print("unable to run %%s" %% dispcmd) - print(e) - return None, None - else: - if verbose: - print("unable to find command, tried %%s" %% (commands,)) - return None, None - stdout = p.communicate()[0].strip() - if sys.version_info[0] >= 3: - stdout = stdout.decode() - if p.returncode != 0: - if verbose: - print("unable to run %%s (error)" %% dispcmd) - print("stdout was %%s" %% stdout) - return None, p.returncode - return stdout, p.returncode - - -def versions_from_parentdir(parentdir_prefix, root, verbose): - """Try to determine the version from the parent directory name. - - Source tarballs conventionally unpack into a directory that includes both - the project name and a version string. We will also support searching up - two directory levels for an appropriately named parent directory - """ - rootdirs = [] - - for i in range(3): - dirname = os.path.basename(root) - if dirname.startswith(parentdir_prefix): - return {"version": dirname[len(parentdir_prefix):], - "full-revisionid": None, - "dirty": False, "error": None, "date": None} - else: - rootdirs.append(root) - root = os.path.dirname(root) # up a level - - if verbose: - print("Tried directories %%s but none started with prefix %%s" %% - (str(rootdirs), parentdir_prefix)) - raise NotThisMethod("rootdir doesn't start with parentdir_prefix") - - -@register_vcs_handler("git", "get_keywords") -def git_get_keywords(versionfile_abs): - """Extract version information from the given file.""" - # the code embedded in _version.py can just fetch the value of these - # keywords. When used from setup.py, we don't want to import _version.py, - # so we do it with a regexp instead. This function is not used from - # _version.py. - keywords = {} - try: - f = open(versionfile_abs, "r") - for line in f.readlines(): - if line.strip().startswith("git_refnames ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["refnames"] = mo.group(1) - if line.strip().startswith("git_full ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["full"] = mo.group(1) - if line.strip().startswith("git_date ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["date"] = mo.group(1) - f.close() - except EnvironmentError: - pass - return keywords - - -@register_vcs_handler("git", "keywords") -def git_versions_from_keywords(keywords, tag_prefix, verbose): - """Get version information from git keywords.""" - if not keywords: - raise NotThisMethod("no keywords at all, weird") - date = keywords.get("date") - if date is not None: - # git-2.2.0 added "%%cI", which expands to an ISO-8601 -compliant - # datestamp. However we prefer "%%ci" (which expands to an "ISO-8601 - # -like" string, which we must then edit to make compliant), because - # it's been around since git-1.5.3, and it's too difficult to - # discover which version we're using, or to work around using an - # older one. - date = date.strip().replace(" ", "T", 1).replace(" ", "", 1) - refnames = keywords["refnames"].strip() - if refnames.startswith("$Format"): - if verbose: - print("keywords are unexpanded, not using") - raise NotThisMethod("unexpanded keywords, not a git-archive tarball") - refs = set([r.strip() for r in refnames.strip("()").split(",")]) - # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of - # just "foo-1.0". If we see a "tag: " prefix, prefer those. - TAG = "tag: " - tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)]) - if not tags: - # Either we're using git < 1.8.3, or there really are no tags. We use - # a heuristic: assume all version tags have a digit. The old git %%d - # expansion behaves like git log --decorate=short and strips out the - # refs/heads/ and refs/tags/ prefixes that would let us distinguish - # between branches and tags. By ignoring refnames without digits, we - # filter out many common branch names like "release" and - # "stabilization", as well as "HEAD" and "master". - tags = set([r for r in refs if re.search(r'\d', r)]) - if verbose: - print("discarding '%%s', no digits" %% ",".join(refs - tags)) - if verbose: - print("likely tags: %%s" %% ",".join(sorted(tags))) - for ref in sorted(tags): - # sorting will prefer e.g. "2.0" over "2.0rc1" - if ref.startswith(tag_prefix): - r = ref[len(tag_prefix):] - if verbose: - print("picking %%s" %% r) - return {"version": r, - "full-revisionid": keywords["full"].strip(), - "dirty": False, "error": None, - "date": date} - # no suitable tags, so version is "0+unknown", but full hex is still there - if verbose: - print("no suitable tags, using unknown + full revision id") - return {"version": "0+unknown", - "full-revisionid": keywords["full"].strip(), - "dirty": False, "error": "no suitable tags", "date": None} - - -@register_vcs_handler("git", "pieces_from_vcs") -def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): - """Get version from 'git describe' in the root of the source tree. - - This only gets called if the git-archive 'subst' keywords were *not* - expanded, and _version.py hasn't already been rewritten with a short - version string, meaning we're inside a checked out source tree. - """ - GITS = ["git"] - if sys.platform == "win32": - GITS = ["git.cmd", "git.exe"] - - out, rc = run_command(GITS, ["rev-parse", "--git-dir"], cwd=root, - hide_stderr=True) - if rc != 0: - if verbose: - print("Directory %%s not under git control" %% root) - raise NotThisMethod("'git rev-parse --git-dir' returned error") - - # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty] - # if there isn't one, this yields HEX[-dirty] (no NUM) - describe_out, rc = run_command(GITS, ["describe", "--tags", "--dirty", - "--always", "--long", - "--match", "%%s*" %% tag_prefix], - cwd=root) - # --long was added in git-1.5.5 - if describe_out is None: - raise NotThisMethod("'git describe' failed") - describe_out = describe_out.strip() - full_out, rc = run_command(GITS, ["rev-parse", "HEAD"], cwd=root) - if full_out is None: - raise NotThisMethod("'git rev-parse' failed") - full_out = full_out.strip() - - pieces = {} - pieces["long"] = full_out - pieces["short"] = full_out[:7] # maybe improved later - pieces["error"] = None - - # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty] - # TAG might have hyphens. - git_describe = describe_out - - # look for -dirty suffix - dirty = git_describe.endswith("-dirty") - pieces["dirty"] = dirty - if dirty: - git_describe = git_describe[:git_describe.rindex("-dirty")] - - # now we have TAG-NUM-gHEX or HEX - - if "-" in git_describe: - # TAG-NUM-gHEX - mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe) - if not mo: - # unparseable. Maybe git-describe is misbehaving? - pieces["error"] = ("unable to parse git-describe output: '%%s'" - %% describe_out) - return pieces - - # tag - full_tag = mo.group(1) - if not full_tag.startswith(tag_prefix): - if verbose: - fmt = "tag '%%s' doesn't start with prefix '%%s'" - print(fmt %% (full_tag, tag_prefix)) - pieces["error"] = ("tag '%%s' doesn't start with prefix '%%s'" - %% (full_tag, tag_prefix)) - return pieces - pieces["closest-tag"] = full_tag[len(tag_prefix):] - - # distance: number of commits since tag - pieces["distance"] = int(mo.group(2)) - - # commit: short hex revision ID - pieces["short"] = mo.group(3) - - else: - # HEX: no tags - pieces["closest-tag"] = None - count_out, rc = run_command(GITS, ["rev-list", "HEAD", "--count"], - cwd=root) - pieces["distance"] = int(count_out) # total number of commits - - # commit date: see ISO-8601 comment in git_versions_from_keywords() - date = run_command(GITS, ["show", "-s", "--format=%%ci", "HEAD"], - cwd=root)[0].strip() - pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1) - - return pieces - - -def plus_or_dot(pieces): - """Return a + if we don't already have one, else return a .""" - if "+" in pieces.get("closest-tag", ""): - return "." - return "+" - - -def render_pep440(pieces): - """Build up version string, with post-release "local version identifier". - - Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you - get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty - - Exceptions: - 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty] - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"] or pieces["dirty"]: - rendered += plus_or_dot(pieces) - rendered += "%%d.g%%s" %% (pieces["distance"], pieces["short"]) - if pieces["dirty"]: - rendered += ".dirty" - else: - # exception #1 - rendered = "0+untagged.%%d.g%%s" %% (pieces["distance"], - pieces["short"]) - if pieces["dirty"]: - rendered += ".dirty" - return rendered - - -def render_pep440_pre(pieces): - """TAG[.post.devDISTANCE] -- No -dirty. - - Exceptions: - 1: no tags. 0.post.devDISTANCE - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"]: - rendered += ".post.dev%%d" %% pieces["distance"] - else: - # exception #1 - rendered = "0.post.dev%%d" %% pieces["distance"] - return rendered - - -def render_pep440_post(pieces): - """TAG[.postDISTANCE[.dev0]+gHEX] . - - The ".dev0" means dirty. Note that .dev0 sorts backwards - (a dirty tree will appear "older" than the corresponding clean one), - but you shouldn't be releasing software with -dirty anyways. - - Exceptions: - 1: no tags. 0.postDISTANCE[.dev0] - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"] or pieces["dirty"]: - rendered += ".post%%d" %% pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - rendered += plus_or_dot(pieces) - rendered += "g%%s" %% pieces["short"] - else: - # exception #1 - rendered = "0.post%%d" %% pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - rendered += "+g%%s" %% pieces["short"] - return rendered - - -def render_pep440_old(pieces): - """TAG[.postDISTANCE[.dev0]] . - - The ".dev0" means dirty. - - Eexceptions: - 1: no tags. 0.postDISTANCE[.dev0] - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"] or pieces["dirty"]: - rendered += ".post%%d" %% pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - else: - # exception #1 - rendered = "0.post%%d" %% pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - return rendered - - -def render_git_describe(pieces): - """TAG[-DISTANCE-gHEX][-dirty]. - - Like 'git describe --tags --dirty --always'. - - Exceptions: - 1: no tags. HEX[-dirty] (note: no 'g' prefix) - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"]: - rendered += "-%%d-g%%s" %% (pieces["distance"], pieces["short"]) - else: - # exception #1 - rendered = pieces["short"] - if pieces["dirty"]: - rendered += "-dirty" - return rendered - - -def render_git_describe_long(pieces): - """TAG-DISTANCE-gHEX[-dirty]. - - Like 'git describe --tags --dirty --always -long'. - The distance/hash is unconditional. - - Exceptions: - 1: no tags. HEX[-dirty] (note: no 'g' prefix) - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - rendered += "-%%d-g%%s" %% (pieces["distance"], pieces["short"]) - else: - # exception #1 - rendered = pieces["short"] - if pieces["dirty"]: - rendered += "-dirty" - return rendered - - -def render(pieces, style): - """Render the given version pieces into the requested style.""" - if pieces["error"]: - return {"version": "unknown", - "full-revisionid": pieces.get("long"), - "dirty": None, - "error": pieces["error"], - "date": None} - - if not style or style == "default": - style = "pep440" # the default - - if style == "pep440": - rendered = render_pep440(pieces) - elif style == "pep440-pre": - rendered = render_pep440_pre(pieces) - elif style == "pep440-post": - rendered = render_pep440_post(pieces) - elif style == "pep440-old": - rendered = render_pep440_old(pieces) - elif style == "git-describe": - rendered = render_git_describe(pieces) - elif style == "git-describe-long": - rendered = render_git_describe_long(pieces) - else: - raise ValueError("unknown style '%%s'" %% style) - - return {"version": rendered, "full-revisionid": pieces["long"], - "dirty": pieces["dirty"], "error": None, - "date": pieces.get("date")} - - -def get_versions(): - """Get version information or return default if unable to do so.""" - # I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have - # __file__, we can work backwards from there to the root. Some - # py2exe/bbfreeze/non-CPython implementations don't do __file__, in which - # case we can only use expanded keywords. - - cfg = get_config() - verbose = cfg.verbose - - try: - return git_versions_from_keywords(get_keywords(), cfg.tag_prefix, - verbose) - except NotThisMethod: - pass - - try: - root = os.path.realpath(__file__) - # versionfile_source is the relative path from the top of the source - # tree (where the .git directory might live) to this file. Invert - # this to find the root from __file__. - for i in cfg.versionfile_source.split('/'): - root = os.path.dirname(root) - except NameError: - return {"version": "0+unknown", "full-revisionid": None, - "dirty": None, - "error": "unable to find root of source tree", - "date": None} - - try: - pieces = git_pieces_from_vcs(cfg.tag_prefix, root, verbose) - return render(pieces, cfg.style) - except NotThisMethod: - pass - - try: - if cfg.parentdir_prefix: - return versions_from_parentdir(cfg.parentdir_prefix, root, verbose) - except NotThisMethod: - pass - - return {"version": "0+unknown", "full-revisionid": None, - "dirty": None, - "error": "unable to compute version", "date": None} -''' - - -@register_vcs_handler("git", "get_keywords") -def git_get_keywords(versionfile_abs): - """Extract version information from the given file.""" - # the code embedded in _version.py can just fetch the value of these - # keywords. When used from setup.py, we don't want to import _version.py, - # so we do it with a regexp instead. This function is not used from - # _version.py. - keywords = {} - try: - f = open(versionfile_abs, "r") - for line in f.readlines(): - if line.strip().startswith("git_refnames ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["refnames"] = mo.group(1) - if line.strip().startswith("git_full ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["full"] = mo.group(1) - if line.strip().startswith("git_date ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["date"] = mo.group(1) - f.close() - except EnvironmentError: - pass - return keywords - - -@register_vcs_handler("git", "keywords") -def git_versions_from_keywords(keywords, tag_prefix, verbose): - """Get version information from git keywords.""" - if not keywords: - raise NotThisMethod("no keywords at all, weird") - date = keywords.get("date") - if date is not None: - # git-2.2.0 added "%cI", which expands to an ISO-8601 -compliant - # datestamp. However we prefer "%ci" (which expands to an "ISO-8601 - # -like" string, which we must then edit to make compliant), because - # it's been around since git-1.5.3, and it's too difficult to - # discover which version we're using, or to work around using an - # older one. - date = date.strip().replace(" ", "T", 1).replace(" ", "", 1) - refnames = keywords["refnames"].strip() - if refnames.startswith("$Format"): - if verbose: - print("keywords are unexpanded, not using") - raise NotThisMethod("unexpanded keywords, not a git-archive tarball") - refs = set([r.strip() for r in refnames.strip("()").split(",")]) - # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of - # just "foo-1.0". If we see a "tag: " prefix, prefer those. - TAG = "tag: " - tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)]) - if not tags: - # Either we're using git < 1.8.3, or there really are no tags. We use - # a heuristic: assume all version tags have a digit. The old git %d - # expansion behaves like git log --decorate=short and strips out the - # refs/heads/ and refs/tags/ prefixes that would let us distinguish - # between branches and tags. By ignoring refnames without digits, we - # filter out many common branch names like "release" and - # "stabilization", as well as "HEAD" and "master". - tags = set([r for r in refs if re.search(r'\d', r)]) - if verbose: - print("discarding '%s', no digits" % ",".join(refs - tags)) - if verbose: - print("likely tags: %s" % ",".join(sorted(tags))) - for ref in sorted(tags): - # sorting will prefer e.g. "2.0" over "2.0rc1" - if ref.startswith(tag_prefix): - r = ref[len(tag_prefix):] - if verbose: - print("picking %s" % r) - return {"version": r, - "full-revisionid": keywords["full"].strip(), - "dirty": False, "error": None, - "date": date} - # no suitable tags, so version is "0+unknown", but full hex is still there - if verbose: - print("no suitable tags, using unknown + full revision id") - return {"version": "0+unknown", - "full-revisionid": keywords["full"].strip(), - "dirty": False, "error": "no suitable tags", "date": None} - - -@register_vcs_handler("git", "pieces_from_vcs") -def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): - """Get version from 'git describe' in the root of the source tree. - - This only gets called if the git-archive 'subst' keywords were *not* - expanded, and _version.py hasn't already been rewritten with a short - version string, meaning we're inside a checked out source tree. - """ - GITS = ["git"] - if sys.platform == "win32": - GITS = ["git.cmd", "git.exe"] - - out, rc = run_command(GITS, ["rev-parse", "--git-dir"], cwd=root, - hide_stderr=True) - if rc != 0: - if verbose: - print("Directory %s not under git control" % root) - raise NotThisMethod("'git rev-parse --git-dir' returned error") - - # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty] - # if there isn't one, this yields HEX[-dirty] (no NUM) - describe_out, rc = run_command(GITS, ["describe", "--tags", "--dirty", - "--always", "--long", - "--match", "%s*" % tag_prefix], - cwd=root) - # --long was added in git-1.5.5 - if describe_out is None: - raise NotThisMethod("'git describe' failed") - describe_out = describe_out.strip() - full_out, rc = run_command(GITS, ["rev-parse", "HEAD"], cwd=root) - if full_out is None: - raise NotThisMethod("'git rev-parse' failed") - full_out = full_out.strip() - - pieces = {} - pieces["long"] = full_out - pieces["short"] = full_out[:7] # maybe improved later - pieces["error"] = None - - # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty] - # TAG might have hyphens. - git_describe = describe_out - - # look for -dirty suffix - dirty = git_describe.endswith("-dirty") - pieces["dirty"] = dirty - if dirty: - git_describe = git_describe[:git_describe.rindex("-dirty")] - - # now we have TAG-NUM-gHEX or HEX - - if "-" in git_describe: - # TAG-NUM-gHEX - mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe) - if not mo: - # unparseable. Maybe git-describe is misbehaving? - pieces["error"] = ("unable to parse git-describe output: '%s'" - % describe_out) - return pieces - - # tag - full_tag = mo.group(1) - if not full_tag.startswith(tag_prefix): - if verbose: - fmt = "tag '%s' doesn't start with prefix '%s'" - print(fmt % (full_tag, tag_prefix)) - pieces["error"] = ("tag '%s' doesn't start with prefix '%s'" - % (full_tag, tag_prefix)) - return pieces - pieces["closest-tag"] = full_tag[len(tag_prefix):] - - # distance: number of commits since tag - pieces["distance"] = int(mo.group(2)) - - # commit: short hex revision ID - pieces["short"] = mo.group(3) - - else: - # HEX: no tags - pieces["closest-tag"] = None - count_out, rc = run_command(GITS, ["rev-list", "HEAD", "--count"], - cwd=root) - pieces["distance"] = int(count_out) # total number of commits - - # commit date: see ISO-8601 comment in git_versions_from_keywords() - date = run_command(GITS, ["show", "-s", "--format=%ci", "HEAD"], - cwd=root)[0].strip() - pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1) - - return pieces - - -def do_vcs_install(manifest_in, versionfile_source, ipy): - """Git-specific installation logic for Versioneer. - - For Git, this means creating/changing .gitattributes to mark _version.py - for export-subst keyword substitution. - """ - GITS = ["git"] - if sys.platform == "win32": - GITS = ["git.cmd", "git.exe"] - files = [manifest_in, versionfile_source] - if ipy: - files.append(ipy) - try: - me = __file__ - if me.endswith(".pyc") or me.endswith(".pyo"): - me = os.path.splitext(me)[0] + ".py" - versioneer_file = os.path.relpath(me) - except NameError: - versioneer_file = "versioneer.py" - files.append(versioneer_file) - present = False - try: - f = open(".gitattributes", "r") - for line in f.readlines(): - if line.strip().startswith(versionfile_source): - if "export-subst" in line.strip().split()[1:]: - present = True - f.close() - except EnvironmentError: - pass - if not present: - f = open(".gitattributes", "a+") - f.write("%s export-subst\n" % versionfile_source) - f.close() - files.append(".gitattributes") - run_command(GITS, ["add", "--"] + files) - - -def versions_from_parentdir(parentdir_prefix, root, verbose): - """Try to determine the version from the parent directory name. - - Source tarballs conventionally unpack into a directory that includes both - the project name and a version string. We will also support searching up - two directory levels for an appropriately named parent directory - """ - rootdirs = [] - - for i in range(3): - dirname = os.path.basename(root) - if dirname.startswith(parentdir_prefix): - return {"version": dirname[len(parentdir_prefix):], - "full-revisionid": None, - "dirty": False, "error": None, "date": None} - else: - rootdirs.append(root) - root = os.path.dirname(root) # up a level - - if verbose: - print("Tried directories %s but none started with prefix %s" % - (str(rootdirs), parentdir_prefix)) - raise NotThisMethod("rootdir doesn't start with parentdir_prefix") - - -SHORT_VERSION_PY = """ -# This file was generated by 'versioneer.py' (0.18) from -# revision-control system data, or from the parent directory name of an -# unpacked source archive. Distribution tarballs contain a pre-generated copy -# of this file. - -import json - -version_json = ''' -%s -''' # END VERSION_JSON - - -def get_versions(): - return json.loads(version_json) -""" - - -def versions_from_file(filename): - """Try to determine the version from _version.py if present.""" - try: - with open(filename) as f: - contents = f.read() - except EnvironmentError: - raise NotThisMethod("unable to read _version.py") - mo = re.search(r"version_json = '''\n(.*)''' # END VERSION_JSON", - contents, re.M | re.S) - if not mo: - mo = re.search(r"version_json = '''\r\n(.*)''' # END VERSION_JSON", - contents, re.M | re.S) - if not mo: - raise NotThisMethod("no version_json in _version.py") - return json.loads(mo.group(1)) - - -def write_to_version_file(filename, versions): - """Write the given version number to the given _version.py file.""" - os.unlink(filename) - contents = json.dumps(versions, sort_keys=True, - indent=1, separators=(",", ": ")) - with open(filename, "w") as f: - f.write(SHORT_VERSION_PY % contents) - - print("set %s to '%s'" % (filename, versions["version"])) - - -def plus_or_dot(pieces): - """Return a + if we don't already have one, else return a .""" - if "+" in pieces.get("closest-tag", ""): - return "." - return "+" - - -def render_pep440(pieces): - """Build up version string, with post-release "local version identifier". - - Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you - get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty - - Exceptions: - 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty] - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"] or pieces["dirty"]: - rendered += plus_or_dot(pieces) - rendered += "%d.g%s" % (pieces["distance"], pieces["short"]) - if pieces["dirty"]: - rendered += ".dirty" - else: - # exception #1 - rendered = "0+untagged.%d.g%s" % (pieces["distance"], - pieces["short"]) - if pieces["dirty"]: - rendered += ".dirty" - return rendered - - -def render_pep440_pre(pieces): - """TAG[.post.devDISTANCE] -- No -dirty. - - Exceptions: - 1: no tags. 0.post.devDISTANCE - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"]: - rendered += ".post.dev%d" % pieces["distance"] - else: - # exception #1 - rendered = "0.post.dev%d" % pieces["distance"] - return rendered - - -def render_pep440_post(pieces): - """TAG[.postDISTANCE[.dev0]+gHEX] . - - The ".dev0" means dirty. Note that .dev0 sorts backwards - (a dirty tree will appear "older" than the corresponding clean one), - but you shouldn't be releasing software with -dirty anyways. - - Exceptions: - 1: no tags. 0.postDISTANCE[.dev0] - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"] or pieces["dirty"]: - rendered += ".post%d" % pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - rendered += plus_or_dot(pieces) - rendered += "g%s" % pieces["short"] - else: - # exception #1 - rendered = "0.post%d" % pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - rendered += "+g%s" % pieces["short"] - return rendered - - -def render_pep440_old(pieces): - """TAG[.postDISTANCE[.dev0]] . - - The ".dev0" means dirty. - - Eexceptions: - 1: no tags. 0.postDISTANCE[.dev0] - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"] or pieces["dirty"]: - rendered += ".post%d" % pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - else: - # exception #1 - rendered = "0.post%d" % pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - return rendered - - -def render_git_describe(pieces): - """TAG[-DISTANCE-gHEX][-dirty]. - - Like 'git describe --tags --dirty --always'. - - Exceptions: - 1: no tags. HEX[-dirty] (note: no 'g' prefix) - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"]: - rendered += "-%d-g%s" % (pieces["distance"], pieces["short"]) - else: - # exception #1 - rendered = pieces["short"] - if pieces["dirty"]: - rendered += "-dirty" - return rendered - - -def render_git_describe_long(pieces): - """TAG-DISTANCE-gHEX[-dirty]. - - Like 'git describe --tags --dirty --always -long'. - The distance/hash is unconditional. - - Exceptions: - 1: no tags. HEX[-dirty] (note: no 'g' prefix) - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - rendered += "-%d-g%s" % (pieces["distance"], pieces["short"]) - else: - # exception #1 - rendered = pieces["short"] - if pieces["dirty"]: - rendered += "-dirty" - return rendered - - -def render(pieces, style): - """Render the given version pieces into the requested style.""" - if pieces["error"]: - return {"version": "unknown", - "full-revisionid": pieces.get("long"), - "dirty": None, - "error": pieces["error"], - "date": None} - - if not style or style == "default": - style = "pep440" # the default - - if style == "pep440": - rendered = render_pep440(pieces) - elif style == "pep440-pre": - rendered = render_pep440_pre(pieces) - elif style == "pep440-post": - rendered = render_pep440_post(pieces) - elif style == "pep440-old": - rendered = render_pep440_old(pieces) - elif style == "git-describe": - rendered = render_git_describe(pieces) - elif style == "git-describe-long": - rendered = render_git_describe_long(pieces) - else: - raise ValueError("unknown style '%s'" % style) - - return {"version": rendered, "full-revisionid": pieces["long"], - "dirty": pieces["dirty"], "error": None, - "date": pieces.get("date")} - - -class VersioneerBadRootError(Exception): - """The project root directory is unknown or missing key files.""" - - -def get_versions(verbose=False): - """Get the project version from whatever source is available. - - Returns dict with two keys: 'version' and 'full'. - """ - if "versioneer" in sys.modules: - # see the discussion in cmdclass.py:get_cmdclass() - del sys.modules["versioneer"] - - root = get_root() - cfg = get_config_from_root(root) - - assert cfg.VCS is not None, "please set [versioneer]VCS= in setup.cfg" - handlers = HANDLERS.get(cfg.VCS) - assert handlers, "unrecognized VCS '%s'" % cfg.VCS - verbose = verbose or cfg.verbose - assert cfg.versionfile_source is not None, \ - "please set versioneer.versionfile_source" - assert cfg.tag_prefix is not None, "please set versioneer.tag_prefix" - - versionfile_abs = os.path.join(root, cfg.versionfile_source) - - # extract version from first of: _version.py, VCS command (e.g. 'git - # describe'), parentdir. This is meant to work for developers using a - # source checkout, for users of a tarball created by 'setup.py sdist', - # and for users of a tarball/zipball created by 'git archive' or github's - # download-from-tag feature or the equivalent in other VCSes. - - get_keywords_f = handlers.get("get_keywords") - from_keywords_f = handlers.get("keywords") - if get_keywords_f and from_keywords_f: - try: - keywords = get_keywords_f(versionfile_abs) - ver = from_keywords_f(keywords, cfg.tag_prefix, verbose) - if verbose: - print("got version from expanded keyword %s" % ver) - return ver - except NotThisMethod: - pass - - try: - ver = versions_from_file(versionfile_abs) - if verbose: - print("got version from file %s %s" % (versionfile_abs, ver)) - return ver - except NotThisMethod: - pass - - from_vcs_f = handlers.get("pieces_from_vcs") - if from_vcs_f: - try: - pieces = from_vcs_f(cfg.tag_prefix, root, verbose) - ver = render(pieces, cfg.style) - if verbose: - print("got version from VCS %s" % ver) - return ver - except NotThisMethod: - pass - - try: - if cfg.parentdir_prefix: - ver = versions_from_parentdir(cfg.parentdir_prefix, root, verbose) - if verbose: - print("got version from parentdir %s" % ver) - return ver - except NotThisMethod: - pass - - if verbose: - print("unable to compute version") - - return {"version": "0+unknown", "full-revisionid": None, - "dirty": None, "error": "unable to compute version", - "date": None} - - -def get_version(): - """Get the short version string for this project.""" - return get_versions()["version"] - - -def get_cmdclass(): - """Get the custom setuptools/distutils subclasses used by Versioneer.""" - if "versioneer" in sys.modules: - del sys.modules["versioneer"] - # this fixes the "python setup.py develop" case (also 'install' and - # 'easy_install .'), in which subdependencies of the main project are - # built (using setup.py bdist_egg) in the same python process. Assume - # a main project A and a dependency B, which use different versions - # of Versioneer. A's setup.py imports A's Versioneer, leaving it in - # sys.modules by the time B's setup.py is executed, causing B to run - # with the wrong versioneer. Setuptools wraps the sub-dep builds in a - # sandbox that restores sys.modules to it's pre-build state, so the - # parent is protected against the child's "import versioneer". By - # removing ourselves from sys.modules here, before the child build - # happens, we protect the child from the parent's versioneer too. - # Also see https://github.com/warner/python-versioneer/issues/52 - - cmds = {} - - # we add "version" to both distutils and setuptools - from distutils.core import Command - - class cmd_version(Command): - description = "report generated version string" - user_options = [] - boolean_options = [] - - def initialize_options(self): - pass - - def finalize_options(self): - pass - - def run(self): - vers = get_versions(verbose=True) - print("Version: %s" % vers["version"]) - print(" full-revisionid: %s" % vers.get("full-revisionid")) - print(" dirty: %s" % vers.get("dirty")) - print(" date: %s" % vers.get("date")) - if vers["error"]: - print(" error: %s" % vers["error"]) - cmds["version"] = cmd_version - - # we override "build_py" in both distutils and setuptools - # - # most invocation pathways end up running build_py: - # distutils/build -> build_py - # distutils/install -> distutils/build ->.. - # setuptools/bdist_wheel -> distutils/install ->.. - # setuptools/bdist_egg -> distutils/install_lib -> build_py - # setuptools/install -> bdist_egg ->.. - # setuptools/develop -> ? - # pip install: - # copies source tree to a tempdir before running egg_info/etc - # if .git isn't copied too, 'git describe' will fail - # then does setup.py bdist_wheel, or sometimes setup.py install - # setup.py egg_info -> ? - - # we override different "build_py" commands for both environments - if "setuptools" in sys.modules: - from setuptools.command.build_py import build_py as _build_py - else: - from distutils.command.build_py import build_py as _build_py - - class cmd_build_py(_build_py): - def run(self): - root = get_root() - cfg = get_config_from_root(root) - versions = get_versions() - _build_py.run(self) - # now locate _version.py in the new build/ directory and replace - # it with an updated value - if cfg.versionfile_build: - target_versionfile = os.path.join(self.build_lib, - cfg.versionfile_build) - print("UPDATING %s" % target_versionfile) - write_to_version_file(target_versionfile, versions) - cmds["build_py"] = cmd_build_py - - if "cx_Freeze" in sys.modules: # cx_freeze enabled? - from cx_Freeze.dist import build_exe as _build_exe - # nczeczulin reports that py2exe won't like the pep440-style string - # as FILEVERSION, but it can be used for PRODUCTVERSION, e.g. - # setup(console=[{ - # "version": versioneer.get_version().split("+", 1)[0], # FILEVERSION - # "product_version": versioneer.get_version(), - # ... - - class cmd_build_exe(_build_exe): - def run(self): - root = get_root() - cfg = get_config_from_root(root) - versions = get_versions() - target_versionfile = cfg.versionfile_source - print("UPDATING %s" % target_versionfile) - write_to_version_file(target_versionfile, versions) - - _build_exe.run(self) - os.unlink(target_versionfile) - with open(cfg.versionfile_source, "w") as f: - LONG = LONG_VERSION_PY[cfg.VCS] - f.write(LONG % - {"DOLLAR": "$", - "STYLE": cfg.style, - "TAG_PREFIX": cfg.tag_prefix, - "PARENTDIR_PREFIX": cfg.parentdir_prefix, - "VERSIONFILE_SOURCE": cfg.versionfile_source, - }) - cmds["build_exe"] = cmd_build_exe - del cmds["build_py"] - - if 'py2exe' in sys.modules: # py2exe enabled? - try: - from py2exe.distutils_buildexe import py2exe as _py2exe # py3 - except ImportError: - from py2exe.build_exe import py2exe as _py2exe # py2 - - class cmd_py2exe(_py2exe): - def run(self): - root = get_root() - cfg = get_config_from_root(root) - versions = get_versions() - target_versionfile = cfg.versionfile_source - print("UPDATING %s" % target_versionfile) - write_to_version_file(target_versionfile, versions) - - _py2exe.run(self) - os.unlink(target_versionfile) - with open(cfg.versionfile_source, "w") as f: - LONG = LONG_VERSION_PY[cfg.VCS] - f.write(LONG % - {"DOLLAR": "$", - "STYLE": cfg.style, - "TAG_PREFIX": cfg.tag_prefix, - "PARENTDIR_PREFIX": cfg.parentdir_prefix, - "VERSIONFILE_SOURCE": cfg.versionfile_source, - }) - cmds["py2exe"] = cmd_py2exe - - # we override different "sdist" commands for both environments - if "setuptools" in sys.modules: - from setuptools.command.sdist import sdist as _sdist - else: - from distutils.command.sdist import sdist as _sdist - - class cmd_sdist(_sdist): - def run(self): - versions = get_versions() - self._versioneer_generated_versions = versions - # unless we update this, the command will keep using the old - # version - self.distribution.metadata.version = versions["version"] - return _sdist.run(self) - - def make_release_tree(self, base_dir, files): - root = get_root() - cfg = get_config_from_root(root) - _sdist.make_release_tree(self, base_dir, files) - # now locate _version.py in the new base_dir directory - # (remembering that it may be a hardlink) and replace it with an - # updated value - target_versionfile = os.path.join(base_dir, cfg.versionfile_source) - print("UPDATING %s" % target_versionfile) - write_to_version_file(target_versionfile, - self._versioneer_generated_versions) - cmds["sdist"] = cmd_sdist - - return cmds - - -CONFIG_ERROR = """ -setup.cfg is missing the necessary Versioneer configuration. You need -a section like: - - [versioneer] - VCS = git - style = pep440 - versionfile_source = src/myproject/_version.py - versionfile_build = myproject/_version.py - tag_prefix = - parentdir_prefix = myproject- - -You will also need to edit your setup.py to use the results: - - import versioneer - setup(version=versioneer.get_version(), - cmdclass=versioneer.get_cmdclass(), ...) - -Please read the docstring in ./versioneer.py for configuration instructions, -edit setup.cfg, and re-run the installer or 'python versioneer.py setup'. -""" - -SAMPLE_CONFIG = """ -# See the docstring in versioneer.py for instructions. Note that you must -# re-run 'versioneer.py setup' after changing this section, and commit the -# resulting files. - -[versioneer] -#VCS = git -#style = pep440 -#versionfile_source = -#versionfile_build = -#tag_prefix = -#parentdir_prefix = - -""" - -INIT_PY_SNIPPET = """ -from ._version import get_versions -__version__ = get_versions()['version'] -del get_versions -""" - - -def do_setup(): - """Main VCS-independent setup function for installing Versioneer.""" - root = get_root() - try: - cfg = get_config_from_root(root) - except (EnvironmentError, configparser.NoSectionError, - configparser.NoOptionError) as e: - if isinstance(e, (EnvironmentError, configparser.NoSectionError)): - print("Adding sample versioneer config to setup.cfg", - file=sys.stderr) - with open(os.path.join(root, "setup.cfg"), "a") as f: - f.write(SAMPLE_CONFIG) - print(CONFIG_ERROR, file=sys.stderr) - return 1 - - print(" creating %s" % cfg.versionfile_source) - with open(cfg.versionfile_source, "w") as f: - LONG = LONG_VERSION_PY[cfg.VCS] - f.write(LONG % {"DOLLAR": "$", - "STYLE": cfg.style, - "TAG_PREFIX": cfg.tag_prefix, - "PARENTDIR_PREFIX": cfg.parentdir_prefix, - "VERSIONFILE_SOURCE": cfg.versionfile_source, - }) - - ipy = os.path.join(os.path.dirname(cfg.versionfile_source), - "__init__.py") - if os.path.exists(ipy): - try: - with open(ipy, "r") as f: - old = f.read() - except EnvironmentError: - old = "" - if INIT_PY_SNIPPET not in old: - print(" appending to %s" % ipy) - with open(ipy, "a") as f: - f.write(INIT_PY_SNIPPET) - else: - print(" %s unmodified" % ipy) - else: - print(" %s doesn't exist, ok" % ipy) - ipy = None - - # Make sure both the top-level "versioneer.py" and versionfile_source - # (PKG/_version.py, used by runtime code) are in MANIFEST.in, so - # they'll be copied into source distributions. Pip won't be able to - # install the package without this. - manifest_in = os.path.join(root, "MANIFEST.in") - simple_includes = set() - try: - with open(manifest_in, "r") as f: - for line in f: - if line.startswith("include "): - for include in line.split()[1:]: - simple_includes.add(include) - except EnvironmentError: - pass - # That doesn't cover everything MANIFEST.in can do - # (http://docs.python.org/2/distutils/sourcedist.html#commands), so - # it might give some false negatives. Appending redundant 'include' - # lines is safe, though. - if "versioneer.py" not in simple_includes: - print(" appending 'versioneer.py' to MANIFEST.in") - with open(manifest_in, "a") as f: - f.write("include versioneer.py\n") - else: - print(" 'versioneer.py' already in MANIFEST.in") - if cfg.versionfile_source not in simple_includes: - print(" appending versionfile_source ('%s') to MANIFEST.in" % - cfg.versionfile_source) - with open(manifest_in, "a") as f: - f.write("include %s\n" % cfg.versionfile_source) - else: - print(" versionfile_source already in MANIFEST.in") - - # Make VCS-specific changes. For git, this means creating/changing - # .gitattributes to mark _version.py for export-subst keyword - # substitution. - do_vcs_install(manifest_in, cfg.versionfile_source, ipy) - return 0 - - -def scan_setup_py(): - """Validate the contents of setup.py against Versioneer's expectations.""" - found = set() - setters = False - errors = 0 - with open("setup.py", "r") as f: - for line in f.readlines(): - if "import versioneer" in line: - found.add("import") - if "versioneer.get_cmdclass()" in line: - found.add("cmdclass") - if "versioneer.get_version()" in line: - found.add("get_version") - if "versioneer.VCS" in line: - setters = True - if "versioneer.versionfile_source" in line: - setters = True - if len(found) != 3: - print("") - print("Your setup.py appears to be missing some important items") - print("(but I might be wrong). Please make sure it has something") - print("roughly like the following:") - print("") - print(" import versioneer") - print(" setup( version=versioneer.get_version(),") - print(" cmdclass=versioneer.get_cmdclass(), ...)") - print("") - errors += 1 - if setters: - print("You should remove lines like 'versioneer.VCS = ' and") - print("'versioneer.versionfile_source = ' . This configuration") - print("now lives in setup.cfg, and should be removed from setup.py") - print("") - errors += 1 - return errors - - -if __name__ == "__main__": - cmd = sys.argv[1] - if cmd == "setup": - errors = do_setup() - errors += scan_setup_py() - if errors: - sys.exit(1) + +# Version: 0.19 + +"""The Versioneer - like a rocketeer, but for versions. + +The Versioneer +============== + +* like a rocketeer, but for versions! +* https://github.com/warner/python-versioneer +* Brian Warner +* License: Public Domain +* Compatible With: python2.6, 2.7, 3.2, 3.3, 3.4, 3.5, 3.6, and pypy +* [![Latest Version] +(https://pypip.in/version/versioneer/badge.svg?style=flat) +](https://pypi.python.org/pypi/versioneer/) +* [![Build Status] +(https://travis-ci.org/warner/python-versioneer.png?branch=master) +](https://travis-ci.org/warner/python-versioneer) + +This is a tool for managing a recorded version number in distutils-based +python projects. The goal is to remove the tedious and error-prone "update +the embedded version string" step from your release process. Making a new +release should be as easy as recording a new tag in your version-control +system, and maybe making new tarballs. + + +## Quick Install + +* `pip install versioneer` to somewhere to your $PATH +* add a `[versioneer]` section to your setup.cfg (see below) +* run `versioneer install` in your source tree, commit the results + +## Version Identifiers + +Source trees come from a variety of places: + +* a version-control system checkout (mostly used by developers) +* a nightly tarball, produced by build automation +* a snapshot tarball, produced by a web-based VCS browser, like github's + "tarball from tag" feature +* a release tarball, produced by "setup.py sdist", distributed through PyPI + +Within each source tree, the version identifier (either a string or a number, +this tool is format-agnostic) can come from a variety of places: + +* ask the VCS tool itself, e.g. "git describe" (for checkouts), which knows + about recent "tags" and an absolute revision-id +* the name of the directory into which the tarball was unpacked +* an expanded VCS keyword ($Id$, etc) +* a `_version.py` created by some earlier build step + +For released software, the version identifier is closely related to a VCS +tag. Some projects use tag names that include more than just the version +string (e.g. "myproject-1.2" instead of just "1.2"), in which case the tool +needs to strip the tag prefix to extract the version identifier. For +unreleased software (between tags), the version identifier should provide +enough information to help developers recreate the same tree, while also +giving them an idea of roughly how old the tree is (after version 1.2, before +version 1.3). Many VCS systems can report a description that captures this, +for example `git describe --tags --dirty --always` reports things like +"0.7-1-g574ab98-dirty" to indicate that the checkout is one revision past the +0.7 tag, has a unique revision id of "574ab98", and is "dirty" (it has +uncommitted changes. + +The version identifier is used for multiple purposes: + +* to allow the module to self-identify its version: `myproject.__version__` +* to choose a name and prefix for a 'setup.py sdist' tarball + +## Theory of Operation + +Versioneer works by adding a special `_version.py` file into your source +tree, where your `__init__.py` can import it. This `_version.py` knows how to +dynamically ask the VCS tool for version information at import time. + +`_version.py` also contains `$Revision$` markers, and the installation +process marks `_version.py` to have this marker rewritten with a tag name +during the `git archive` command. As a result, generated tarballs will +contain enough information to get the proper version. + +To allow `setup.py` to compute a version too, a `versioneer.py` is added to +the top level of your source tree, next to `setup.py` and the `setup.cfg` +that configures it. This overrides several distutils/setuptools commands to +compute the version when invoked, and changes `setup.py build` and `setup.py +sdist` to replace `_version.py` with a small static file that contains just +the generated version data. + +## Installation + +See [INSTALL.md](./INSTALL.md) for detailed installation instructions. + +## Version-String Flavors + +Code which uses Versioneer can learn about its version string at runtime by +importing `_version` from your main `__init__.py` file and running the +`get_versions()` function. From the "outside" (e.g. in `setup.py`), you can +import the top-level `versioneer.py` and run `get_versions()`. + +Both functions return a dictionary with different flavors of version +information: + +* `['version']`: A condensed version string, rendered using the selected + style. This is the most commonly used value for the project's version + string. The default "pep440" style yields strings like `0.11`, + `0.11+2.g1076c97`, or `0.11+2.g1076c97.dirty`. See the "Styles" section + below for alternative styles. + +* `['full-revisionid']`: detailed revision identifier. For Git, this is the + full SHA1 commit id, e.g. "1076c978a8d3cfc70f408fe5974aa6c092c949ac". + +* `['date']`: Date and time of the latest `HEAD` commit. For Git, it is the + commit date in ISO 8601 format. This will be None if the date is not + available. + +* `['dirty']`: a boolean, True if the tree has uncommitted changes. Note that + this is only accurate if run in a VCS checkout, otherwise it is likely to + be False or None + +* `['error']`: if the version string could not be computed, this will be set + to a string describing the problem, otherwise it will be None. It may be + useful to throw an exception in setup.py if this is set, to avoid e.g. + creating tarballs with a version string of "unknown". + +Some variants are more useful than others. Including `full-revisionid` in a +bug report should allow developers to reconstruct the exact code being tested +(or indicate the presence of local changes that should be shared with the +developers). `version` is suitable for display in an "about" box or a CLI +`--version` output: it can be easily compared against release notes and lists +of bugs fixed in various releases. + +The installer adds the following text to your `__init__.py` to place a basic +version in `YOURPROJECT.__version__`: + + from ._version import get_versions + __version__ = get_versions()['version'] + del get_versions + +## Styles + +The setup.cfg `style=` configuration controls how the VCS information is +rendered into a version string. + +The default style, "pep440", produces a PEP440-compliant string, equal to the +un-prefixed tag name for actual releases, and containing an additional "local +version" section with more detail for in-between builds. For Git, this is +TAG[+DISTANCE.gHEX[.dirty]] , using information from `git describe --tags +--dirty --always`. For example "0.11+2.g1076c97.dirty" indicates that the +tree is like the "1076c97" commit but has uncommitted changes (".dirty"), and +that this commit is two revisions ("+2") beyond the "0.11" tag. For released +software (exactly equal to a known tag), the identifier will only contain the +stripped tag, e.g. "0.11". + +Other styles are available. See [details.md](details.md) in the Versioneer +source tree for descriptions. + +## Debugging + +Versioneer tries to avoid fatal errors: if something goes wrong, it will tend +to return a version of "0+unknown". To investigate the problem, run `setup.py +version`, which will run the version-lookup code in a verbose mode, and will +display the full contents of `get_versions()` (including the `error` string, +which may help identify what went wrong). + +## Known Limitations + +Some situations are known to cause problems for Versioneer. This details the +most significant ones. More can be found on Github +[issues page](https://github.com/warner/python-versioneer/issues). + +### Subprojects + +Versioneer has limited support for source trees in which `setup.py` is not in +the root directory (e.g. `setup.py` and `.git/` are *not* siblings). The are +two common reasons why `setup.py` might not be in the root: + +* Source trees which contain multiple subprojects, such as + [Buildbot](https://github.com/buildbot/buildbot), which contains both + "master" and "slave" subprojects, each with their own `setup.py`, + `setup.cfg`, and `tox.ini`. Projects like these produce multiple PyPI + distributions (and upload multiple independently-installable tarballs). +* Source trees whose main purpose is to contain a C library, but which also + provide bindings to Python (and perhaps other langauges) in subdirectories. + +Versioneer will look for `.git` in parent directories, and most operations +should get the right version string. However `pip` and `setuptools` have bugs +and implementation details which frequently cause `pip install .` from a +subproject directory to fail to find a correct version string (so it usually +defaults to `0+unknown`). + +`pip install --editable .` should work correctly. `setup.py install` might +work too. + +Pip-8.1.1 is known to have this problem, but hopefully it will get fixed in +some later version. + +[Bug #38](https://github.com/warner/python-versioneer/issues/38) is tracking +this issue. The discussion in +[PR #61](https://github.com/warner/python-versioneer/pull/61) describes the +issue from the Versioneer side in more detail. +[pip PR#3176](https://github.com/pypa/pip/pull/3176) and +[pip PR#3615](https://github.com/pypa/pip/pull/3615) contain work to improve +pip to let Versioneer work correctly. + +Versioneer-0.16 and earlier only looked for a `.git` directory next to the +`setup.cfg`, so subprojects were completely unsupported with those releases. + +### Editable installs with setuptools <= 18.5 + +`setup.py develop` and `pip install --editable .` allow you to install a +project into a virtualenv once, then continue editing the source code (and +test) without re-installing after every change. + +"Entry-point scripts" (`setup(entry_points={"console_scripts": ..})`) are a +convenient way to specify executable scripts that should be installed along +with the python package. + +These both work as expected when using modern setuptools. When using +setuptools-18.5 or earlier, however, certain operations will cause +`pkg_resources.DistributionNotFound` errors when running the entrypoint +script, which must be resolved by re-installing the package. This happens +when the install happens with one version, then the egg_info data is +regenerated while a different version is checked out. Many setup.py commands +cause egg_info to be rebuilt (including `sdist`, `wheel`, and installing into +a different virtualenv), so this can be surprising. + +[Bug #83](https://github.com/warner/python-versioneer/issues/83) describes +this one, but upgrading to a newer version of setuptools should probably +resolve it. + +### Unicode version strings + +While Versioneer works (and is continually tested) with both Python 2 and +Python 3, it is not entirely consistent with bytes-vs-unicode distinctions. +Newer releases probably generate unicode version strings on py2. It's not +clear that this is wrong, but it may be surprising for applications when then +write these strings to a network connection or include them in bytes-oriented +APIs like cryptographic checksums. + +[Bug #71](https://github.com/warner/python-versioneer/issues/71) investigates +this question. + + +## Updating Versioneer + +To upgrade your project to a new release of Versioneer, do the following: + +* install the new Versioneer (`pip install -U versioneer` or equivalent) +* edit `setup.cfg`, if necessary, to include any new configuration settings + indicated by the release notes. See [UPGRADING](./UPGRADING.md) for details. +* re-run `versioneer install` in your source tree, to replace + `SRC/_version.py` +* commit any changed files + +## Future Directions + +This tool is designed to make it easily extended to other version-control +systems: all VCS-specific components are in separate directories like +src/git/ . The top-level `versioneer.py` script is assembled from these +components by running make-versioneer.py . In the future, make-versioneer.py +will take a VCS name as an argument, and will construct a version of +`versioneer.py` that is specific to the given VCS. It might also take the +configuration arguments that are currently provided manually during +installation by editing setup.py . Alternatively, it might go the other +direction and include code from all supported VCS systems, reducing the +number of intermediate scripts. + + +## License + +To make Versioneer easier to embed, all its code is dedicated to the public +domain. The `_version.py` that it creates is also in the public domain. +Specifically, both are released under the Creative Commons "Public Domain +Dedication" license (CC0-1.0), as described in +https://creativecommons.org/publicdomain/zero/1.0/ . + +""" + +from __future__ import print_function +try: + import configparser +except ImportError: + import ConfigParser as configparser +import errno +import json +import os +import re +import subprocess +import sys + + +class VersioneerConfig: + """Container for Versioneer configuration parameters.""" + + +def get_root(): + """Get the project root directory. + + We require that all commands are run from the project root, i.e. the + directory that contains setup.py, setup.cfg, and versioneer.py . + """ + root = os.path.realpath(os.path.abspath(os.getcwd())) + setup_py = os.path.join(root, "setup.py") + versioneer_py = os.path.join(root, "versioneer.py") + if not (os.path.exists(setup_py) or os.path.exists(versioneer_py)): + # allow 'python path/to/setup.py COMMAND' + root = os.path.dirname(os.path.realpath(os.path.abspath(sys.argv[0]))) + setup_py = os.path.join(root, "setup.py") + versioneer_py = os.path.join(root, "versioneer.py") + if not (os.path.exists(setup_py) or os.path.exists(versioneer_py)): + err = ("Versioneer was unable to run the project root directory. " + "Versioneer requires setup.py to be executed from " + "its immediate directory (like 'python setup.py COMMAND'), " + "or in a way that lets it use sys.argv[0] to find the root " + "(like 'python path/to/setup.py COMMAND').") + raise VersioneerBadRootError(err) + try: + # Certain runtime workflows (setup.py install/develop in a setuptools + # tree) execute all dependencies in a single python process, so + # "versioneer" may be imported multiple times, and python's shared + # module-import table will cache the first one. So we can't use + # os.path.dirname(__file__), as that will find whichever + # versioneer.py was first imported, even in later projects. + me = os.path.realpath(os.path.abspath(__file__)) + me_dir = os.path.normcase(os.path.splitext(me)[0]) + vsr_dir = os.path.normcase(os.path.splitext(versioneer_py)[0]) + if me_dir != vsr_dir: + print("Warning: build in %s is using versioneer.py from %s" + % (os.path.dirname(me), versioneer_py)) + except NameError: + pass + return root + + +def get_config_from_root(root): + """Read the project setup.cfg file to determine Versioneer config.""" + # This might raise EnvironmentError (if setup.cfg is missing), or + # configparser.NoSectionError (if it lacks a [versioneer] section), or + # configparser.NoOptionError (if it lacks "VCS="). See the docstring at + # the top of versioneer.py for instructions on writing your setup.cfg . + setup_cfg = os.path.join(root, "setup.cfg") + parser = configparser.SafeConfigParser() + with open(setup_cfg, "r") as f: + parser.readfp(f) + VCS = parser.get("versioneer", "VCS") # mandatory + + def get(parser, name): + if parser.has_option("versioneer", name): + return parser.get("versioneer", name) + return None + cfg = VersioneerConfig() + cfg.VCS = VCS + cfg.style = get(parser, "style") or "" + cfg.versionfile_source = get(parser, "versionfile_source") + cfg.versionfile_build = get(parser, "versionfile_build") + cfg.tag_prefix = get(parser, "tag_prefix") + if cfg.tag_prefix in ("''", '""'): + cfg.tag_prefix = "" + cfg.parentdir_prefix = get(parser, "parentdir_prefix") + cfg.verbose = get(parser, "verbose") + return cfg + + +class NotThisMethod(Exception): + """Exception raised if a method is not valid for the current scenario.""" + + +# these dictionaries contain VCS-specific tools +LONG_VERSION_PY = {} +HANDLERS = {} + + +def register_vcs_handler(vcs, method): # decorator + """Decorator to mark a method as the handler for a particular VCS.""" + def decorate(f): + """Store f in HANDLERS[vcs][method].""" + if vcs not in HANDLERS: + HANDLERS[vcs] = {} + HANDLERS[vcs][method] = f + return f + return decorate + + +def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, + env=None): + """Call the given command(s).""" + assert isinstance(commands, list) + p = None + for c in commands: + try: + dispcmd = str([c] + args) + # remember shell=False, so use git.cmd on windows, not just git + p = subprocess.Popen([c] + args, cwd=cwd, env=env, + stdout=subprocess.PIPE, + stderr=(subprocess.PIPE if hide_stderr + else None)) + break + except EnvironmentError: + e = sys.exc_info()[1] + if e.errno == errno.ENOENT: + continue + if verbose: + print("unable to run %s" % dispcmd) + print(e) + return None, None + else: + if verbose: + print("unable to find command, tried %s" % (commands,)) + return None, None + stdout = p.communicate()[0].strip() + if sys.version_info[0] >= 3: + stdout = stdout.decode() + if p.returncode != 0: + if verbose: + print("unable to run %s (error)" % dispcmd) + print("stdout was %s" % stdout) + return None, p.returncode + return stdout, p.returncode + + +LONG_VERSION_PY['git'] = ''' +# This file helps to compute a version number in source trees obtained from +# git-archive tarball (such as those provided by githubs download-from-tag +# feature). Distribution tarballs (built by setup.py sdist) and build +# directories (produced by setup.py build) will contain a much shorter file +# that just contains the computed version number. + +# This file is released into the public domain. Generated by +# versioneer-0.18 (https://github.com/warner/python-versioneer) + +"""Git implementation of _version.py.""" + +import errno +import os +import re +import subprocess +import sys + + +def get_keywords(): + """Get the keywords needed to look up the version information.""" + # these strings will be replaced by git during git-archive. + # setup.py/versioneer.py will grep for the variable names, so they must + # each be defined on a line of their own. _version.py will just call + # get_keywords(). + git_refnames = "%(DOLLAR)sFormat:%%d%(DOLLAR)s" + git_full = "%(DOLLAR)sFormat:%%H%(DOLLAR)s" + git_date = "%(DOLLAR)sFormat:%%ci%(DOLLAR)s" + keywords = {"refnames": git_refnames, "full": git_full, "date": git_date} + return keywords + + +class VersioneerConfig: + """Container for Versioneer configuration parameters.""" + + +def get_config(): + """Create, populate and return the VersioneerConfig() object.""" + # these strings are filled in when 'setup.py versioneer' creates + # _version.py + cfg = VersioneerConfig() + cfg.VCS = "git" + cfg.style = "%(STYLE)s" + cfg.tag_prefix = "%(TAG_PREFIX)s" + cfg.parentdir_prefix = "%(PARENTDIR_PREFIX)s" + cfg.versionfile_source = "%(VERSIONFILE_SOURCE)s" + cfg.verbose = False + return cfg + + +class NotThisMethod(Exception): + """Exception raised if a method is not valid for the current scenario.""" + + +LONG_VERSION_PY = {} +HANDLERS = {} + + +def register_vcs_handler(vcs, method): # decorator + """Decorator to mark a method as the handler for a particular VCS.""" + def decorate(f): + """Store f in HANDLERS[vcs][method].""" + if vcs not in HANDLERS: + HANDLERS[vcs] = {} + HANDLERS[vcs][method] = f + return f + return decorate + + +def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, + env=None): + """Call the given command(s).""" + assert isinstance(commands, list) + p = None + for c in commands: + try: + dispcmd = str([c] + args) + # remember shell=False, so use git.cmd on windows, not just git + p = subprocess.Popen([c] + args, cwd=cwd, env=env, + stdout=subprocess.PIPE, + stderr=(subprocess.PIPE if hide_stderr + else None)) + break + except EnvironmentError: + e = sys.exc_info()[1] + if e.errno == errno.ENOENT: + continue + if verbose: + print("unable to run %%s" %% dispcmd) + print(e) + return None, None + else: + if verbose: + print("unable to find command, tried %%s" %% (commands,)) + return None, None + stdout = p.communicate()[0].strip() + if sys.version_info[0] >= 3: + stdout = stdout.decode() + if p.returncode != 0: + if verbose: + print("unable to run %%s (error)" %% dispcmd) + print("stdout was %%s" %% stdout) + return None, p.returncode + return stdout, p.returncode + + +def versions_from_parentdir(parentdir_prefix, root, verbose): + """Try to determine the version from the parent directory name. + + Source tarballs conventionally unpack into a directory that includes both + the project name and a version string. We will also support searching up + two directory levels for an appropriately named parent directory + """ + rootdirs = [] + + for i in range(3): + dirname = os.path.basename(root) + if dirname.startswith(parentdir_prefix): + return {"version": dirname[len(parentdir_prefix):], + "full-revisionid": None, + "dirty": False, "error": None, "date": None} + else: + rootdirs.append(root) + root = os.path.dirname(root) # up a level + + if verbose: + print("Tried directories %%s but none started with prefix %%s" %% + (str(rootdirs), parentdir_prefix)) + raise NotThisMethod("rootdir doesn't start with parentdir_prefix") + + +@register_vcs_handler("git", "get_keywords") +def git_get_keywords(versionfile_abs): + """Extract version information from the given file.""" + # the code embedded in _version.py can just fetch the value of these + # keywords. When used from setup.py, we don't want to import _version.py, + # so we do it with a regexp instead. This function is not used from + # _version.py. + keywords = {} + try: + f = open(versionfile_abs, "r") + for line in f.readlines(): + if line.strip().startswith("git_refnames ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + keywords["refnames"] = mo.group(1) + if line.strip().startswith("git_full ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + keywords["full"] = mo.group(1) + if line.strip().startswith("git_date ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + keywords["date"] = mo.group(1) + f.close() + except EnvironmentError: + pass + return keywords + + +@register_vcs_handler("git", "keywords") +def git_versions_from_keywords(keywords, tag_prefix, verbose): + """Get version information from git keywords.""" + if not keywords: + raise NotThisMethod("no keywords at all, weird") + date = keywords.get("date") + if date is not None: + # git-2.2.0 added "%%cI", which expands to an ISO-8601 -compliant + # datestamp. However we prefer "%%ci" (which expands to an "ISO-8601 + # -like" string, which we must then edit to make compliant), because + # it's been around since git-1.5.3, and it's too difficult to + # discover which version we're using, or to work around using an + # older one. + date = date.strip().replace(" ", "T", 1).replace(" ", "", 1) + refnames = keywords["refnames"].strip() + if refnames.startswith("$Format"): + if verbose: + print("keywords are unexpanded, not using") + raise NotThisMethod("unexpanded keywords, not a git-archive tarball") + refs = set([r.strip() for r in refnames.strip("()").split(",")]) + # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of + # just "foo-1.0". If we see a "tag: " prefix, prefer those. + TAG = "tag: " + tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)]) + if not tags: + # Either we're using git < 1.8.3, or there really are no tags. We use + # a heuristic: assume all version tags have a digit. The old git %%d + # expansion behaves like git log --decorate=short and strips out the + # refs/heads/ and refs/tags/ prefixes that would let us distinguish + # between branches and tags. By ignoring refnames without digits, we + # filter out many common branch names like "release" and + # "stabilization", as well as "HEAD" and "master". + tags = set([r for r in refs if re.search(r'\d', r)]) + if verbose: + print("discarding '%%s', no digits" %% ",".join(refs - tags)) + if verbose: + print("likely tags: %%s" %% ",".join(sorted(tags))) + for ref in sorted(tags): + # sorting will prefer e.g. "2.0" over "2.0rc1" + if ref.startswith(tag_prefix): + r = ref[len(tag_prefix):] + if verbose: + print("picking %%s" %% r) + return {"version": r, + "full-revisionid": keywords["full"].strip(), + "dirty": False, "error": None, + "date": date} + # no suitable tags, so version is "0+unknown", but full hex is still there + if verbose: + print("no suitable tags, using unknown + full revision id") + return {"version": "0+unknown", + "full-revisionid": keywords["full"].strip(), + "dirty": False, "error": "no suitable tags", "date": None} + + +@register_vcs_handler("git", "pieces_from_vcs") +def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): + """Get version from 'git describe' in the root of the source tree. + + This only gets called if the git-archive 'subst' keywords were *not* + expanded, and _version.py hasn't already been rewritten with a short + version string, meaning we're inside a checked out source tree. + """ + GITS = ["git"] + if sys.platform == "win32": + GITS = ["git.cmd", "git.exe"] + + out, rc = run_command(GITS, ["rev-parse", "--git-dir"], cwd=root, + hide_stderr=True) + if rc != 0: + if verbose: + print("Directory %%s not under git control" %% root) + raise NotThisMethod("'git rev-parse --git-dir' returned error") + + # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty] + # if there isn't one, this yields HEX[-dirty] (no NUM) + describe_out, rc = run_command(GITS, ["describe", "--tags", "--dirty", + "--always", "--long", + "--match", "%%s*" %% tag_prefix], + cwd=root) + # --long was added in git-1.5.5 + if describe_out is None: + raise NotThisMethod("'git describe' failed") + describe_out = describe_out.strip() + full_out, rc = run_command(GITS, ["rev-parse", "HEAD"], cwd=root) + if full_out is None: + raise NotThisMethod("'git rev-parse' failed") + full_out = full_out.strip() + + pieces = {} + pieces["long"] = full_out + pieces["short"] = full_out[:7] # maybe improved later + pieces["error"] = None + + # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty] + # TAG might have hyphens. + git_describe = describe_out + + # look for -dirty suffix + dirty = git_describe.endswith("-dirty") + pieces["dirty"] = dirty + if dirty: + git_describe = git_describe[:git_describe.rindex("-dirty")] + + # now we have TAG-NUM-gHEX or HEX + + if "-" in git_describe: + # TAG-NUM-gHEX + mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe) + if not mo: + # unparseable. Maybe git-describe is misbehaving? + pieces["error"] = ("unable to parse git-describe output: '%%s'" + %% describe_out) + return pieces + + # tag + full_tag = mo.group(1) + if not full_tag.startswith(tag_prefix): + if verbose: + fmt = "tag '%%s' doesn't start with prefix '%%s'" + print(fmt %% (full_tag, tag_prefix)) + pieces["error"] = ("tag '%%s' doesn't start with prefix '%%s'" + %% (full_tag, tag_prefix)) + return pieces + pieces["closest-tag"] = full_tag[len(tag_prefix):] + + # distance: number of commits since tag + pieces["distance"] = int(mo.group(2)) + + # commit: short hex revision ID + pieces["short"] = mo.group(3) + + else: + # HEX: no tags + pieces["closest-tag"] = None + count_out, rc = run_command(GITS, ["rev-list", "HEAD", "--count"], + cwd=root) + pieces["distance"] = int(count_out) # total number of commits + + # commit date: see ISO-8601 comment in git_versions_from_keywords() + date = run_command(GITS, ["show", "-s", "--format=%%ci", "HEAD"], + cwd=root)[0].strip() + pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1) + + return pieces + + +def plus_or_dot(pieces): + """Return a + if we don't already have one, else return a .""" + if "+" in pieces.get("closest-tag", ""): + return "." + return "+" + + +def render_pep440(pieces): + """Build up version string, with post-release "local version identifier". + + Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you + get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty + + Exceptions: + 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty] + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"] or pieces["dirty"]: + rendered += plus_or_dot(pieces) + rendered += "%%d.g%%s" %% (pieces["distance"], pieces["short"]) + if pieces["dirty"]: + rendered += ".dirty" + else: + # exception #1 + rendered = "0+untagged.%%d.g%%s" %% (pieces["distance"], + pieces["short"]) + if pieces["dirty"]: + rendered += ".dirty" + return rendered + + +def render_pep440_pre(pieces): + """TAG[.post.devDISTANCE] -- No -dirty. + + Exceptions: + 1: no tags. 0.post.devDISTANCE + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"]: + rendered += ".post.dev%%d" %% pieces["distance"] + else: + # exception #1 + rendered = "0.post.dev%%d" %% pieces["distance"] + return rendered + + +def render_pep440_post(pieces): + """TAG[.postDISTANCE[.dev0]+gHEX] . + + The ".dev0" means dirty. Note that .dev0 sorts backwards + (a dirty tree will appear "older" than the corresponding clean one), + but you shouldn't be releasing software with -dirty anyways. + + Exceptions: + 1: no tags. 0.postDISTANCE[.dev0] + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"] or pieces["dirty"]: + rendered += ".post%%d" %% pieces["distance"] + if pieces["dirty"]: + rendered += ".dev0" + rendered += plus_or_dot(pieces) + rendered += "g%%s" %% pieces["short"] + else: + # exception #1 + rendered = "0.post%%d" %% pieces["distance"] + if pieces["dirty"]: + rendered += ".dev0" + rendered += "+g%%s" %% pieces["short"] + return rendered + + +def render_pep440_old(pieces): + """TAG[.postDISTANCE[.dev0]] . + + The ".dev0" means dirty. + + Eexceptions: + 1: no tags. 0.postDISTANCE[.dev0] + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"] or pieces["dirty"]: + rendered += ".post%%d" %% pieces["distance"] + if pieces["dirty"]: + rendered += ".dev0" + else: + # exception #1 + rendered = "0.post%%d" %% pieces["distance"] + if pieces["dirty"]: + rendered += ".dev0" + return rendered + + +def render_git_describe(pieces): + """TAG[-DISTANCE-gHEX][-dirty]. + + Like 'git describe --tags --dirty --always'. + + Exceptions: + 1: no tags. HEX[-dirty] (note: no 'g' prefix) + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"]: + rendered += "-%%d-g%%s" %% (pieces["distance"], pieces["short"]) + else: + # exception #1 + rendered = pieces["short"] + if pieces["dirty"]: + rendered += "-dirty" + return rendered + + +def render_git_describe_long(pieces): + """TAG-DISTANCE-gHEX[-dirty]. + + Like 'git describe --tags --dirty --always -long'. + The distance/hash is unconditional. + + Exceptions: + 1: no tags. HEX[-dirty] (note: no 'g' prefix) + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + rendered += "-%%d-g%%s" %% (pieces["distance"], pieces["short"]) + else: + # exception #1 + rendered = pieces["short"] + if pieces["dirty"]: + rendered += "-dirty" + return rendered + + +def render(pieces, style): + """Render the given version pieces into the requested style.""" + if pieces["error"]: + return {"version": "unknown", + "full-revisionid": pieces.get("long"), + "dirty": None, + "error": pieces["error"], + "date": None} + + if not style or style == "default": + style = "pep440" # the default + + if style == "pep440": + rendered = render_pep440(pieces) + elif style == "pep440-pre": + rendered = render_pep440_pre(pieces) + elif style == "pep440-post": + rendered = render_pep440_post(pieces) + elif style == "pep440-old": + rendered = render_pep440_old(pieces) + elif style == "git-describe": + rendered = render_git_describe(pieces) + elif style == "git-describe-long": + rendered = render_git_describe_long(pieces) + else: + raise ValueError("unknown style '%%s'" %% style) + + return {"version": rendered, "full-revisionid": pieces["long"], + "dirty": pieces["dirty"], "error": None, + "date": pieces.get("date")} + + +def get_versions(): + """Get version information or return default if unable to do so.""" + # I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have + # __file__, we can work backwards from there to the root. Some + # py2exe/bbfreeze/non-CPython implementations don't do __file__, in which + # case we can only use expanded keywords. + + cfg = get_config() + verbose = cfg.verbose + + try: + return git_versions_from_keywords(get_keywords(), cfg.tag_prefix, + verbose) + except NotThisMethod: + pass + + try: + root = os.path.realpath(__file__) + # versionfile_source is the relative path from the top of the source + # tree (where the .git directory might live) to this file. Invert + # this to find the root from __file__. + for i in cfg.versionfile_source.split('/'): + root = os.path.dirname(root) + except NameError: + return {"version": "0+unknown", "full-revisionid": None, + "dirty": None, + "error": "unable to find root of source tree", + "date": None} + + try: + pieces = git_pieces_from_vcs(cfg.tag_prefix, root, verbose) + return render(pieces, cfg.style) + except NotThisMethod: + pass + + try: + if cfg.parentdir_prefix: + return versions_from_parentdir(cfg.parentdir_prefix, root, verbose) + except NotThisMethod: + pass + + return {"version": "0+unknown", "full-revisionid": None, + "dirty": None, + "error": "unable to compute version", "date": None} +''' + + +@register_vcs_handler("git", "get_keywords") +def git_get_keywords(versionfile_abs): + """Extract version information from the given file.""" + # the code embedded in _version.py can just fetch the value of these + # keywords. When used from setup.py, we don't want to import _version.py, + # so we do it with a regexp instead. This function is not used from + # _version.py. + keywords = {} + try: + f = open(versionfile_abs, "r") + for line in f.readlines(): + if line.strip().startswith("git_refnames ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + keywords["refnames"] = mo.group(1) + if line.strip().startswith("git_full ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + keywords["full"] = mo.group(1) + if line.strip().startswith("git_date ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + keywords["date"] = mo.group(1) + f.close() + except EnvironmentError: + pass + return keywords + + +@register_vcs_handler("git", "keywords") +def git_versions_from_keywords(keywords, tag_prefix, verbose): + """Get version information from git keywords.""" + if not keywords: + raise NotThisMethod("no keywords at all, weird") + date = keywords.get("date") + if date is not None: + # git-2.2.0 added "%cI", which expands to an ISO-8601 -compliant + # datestamp. However we prefer "%ci" (which expands to an "ISO-8601 + # -like" string, which we must then edit to make compliant), because + # it's been around since git-1.5.3, and it's too difficult to + # discover which version we're using, or to work around using an + # older one. + date = date.strip().replace(" ", "T", 1).replace(" ", "", 1) + refnames = keywords["refnames"].strip() + if refnames.startswith("$Format"): + if verbose: + print("keywords are unexpanded, not using") + raise NotThisMethod("unexpanded keywords, not a git-archive tarball") + refs = set([r.strip() for r in refnames.strip("()").split(",")]) + # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of + # just "foo-1.0". If we see a "tag: " prefix, prefer those. + TAG = "tag: " + tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)]) + if not tags: + # Either we're using git < 1.8.3, or there really are no tags. We use + # a heuristic: assume all version tags have a digit. The old git %d + # expansion behaves like git log --decorate=short and strips out the + # refs/heads/ and refs/tags/ prefixes that would let us distinguish + # between branches and tags. By ignoring refnames without digits, we + # filter out many common branch names like "release" and + # "stabilization", as well as "HEAD" and "master". + tags = set([r for r in refs if re.search(r'\d', r)]) + if verbose: + print("discarding '%s', no digits" % ",".join(refs - tags)) + if verbose: + print("likely tags: %s" % ",".join(sorted(tags))) + for ref in sorted(tags): + # sorting will prefer e.g. "2.0" over "2.0rc1" + if ref.startswith(tag_prefix): + r = ref[len(tag_prefix):] + if verbose: + print("picking %s" % r) + return {"version": r, + "full-revisionid": keywords["full"].strip(), + "dirty": False, "error": None, + "date": date} + # no suitable tags, so version is "0+unknown", but full hex is still there + if verbose: + print("no suitable tags, using unknown + full revision id") + return {"version": "0+unknown", + "full-revisionid": keywords["full"].strip(), + "dirty": False, "error": "no suitable tags", "date": None} + + +@register_vcs_handler("git", "pieces_from_vcs") +def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): + """Get version from 'git describe' in the root of the source tree. + + This only gets called if the git-archive 'subst' keywords were *not* + expanded, and _version.py hasn't already been rewritten with a short + version string, meaning we're inside a checked out source tree. + """ + GITS = ["git"] + if sys.platform == "win32": + GITS = ["git.cmd", "git.exe"] + + out, rc = run_command(GITS, ["rev-parse", "--git-dir"], cwd=root, + hide_stderr=True) + if rc != 0: + if verbose: + print("Directory %s not under git control" % root) + raise NotThisMethod("'git rev-parse --git-dir' returned error") + + # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty] + # if there isn't one, this yields HEX[-dirty] (no NUM) + describe_out, rc = run_command(GITS, ["describe", "--tags", "--dirty", + "--always", "--long", + "--match", "%s*" % tag_prefix], + cwd=root) + # --long was added in git-1.5.5 + if describe_out is None: + raise NotThisMethod("'git describe' failed") + describe_out = describe_out.strip() + full_out, rc = run_command(GITS, ["rev-parse", "HEAD"], cwd=root) + if full_out is None: + raise NotThisMethod("'git rev-parse' failed") + full_out = full_out.strip() + + pieces = {} + pieces["long"] = full_out + pieces["short"] = full_out[:7] # maybe improved later + pieces["error"] = None + + # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty] + # TAG might have hyphens. + git_describe = describe_out + + # look for -dirty suffix + dirty = git_describe.endswith("-dirty") + pieces["dirty"] = dirty + if dirty: + git_describe = git_describe[:git_describe.rindex("-dirty")] + + # now we have TAG-NUM-gHEX or HEX + + if "-" in git_describe: + # TAG-NUM-gHEX + mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe) + if not mo: + # unparseable. Maybe git-describe is misbehaving? + pieces["error"] = ("unable to parse git-describe output: '%s'" + % describe_out) + return pieces + + # tag + full_tag = mo.group(1) + if not full_tag.startswith(tag_prefix): + if verbose: + fmt = "tag '%s' doesn't start with prefix '%s'" + print(fmt % (full_tag, tag_prefix)) + pieces["error"] = ("tag '%s' doesn't start with prefix '%s'" + % (full_tag, tag_prefix)) + return pieces + pieces["closest-tag"] = full_tag[len(tag_prefix):] + + # distance: number of commits since tag + pieces["distance"] = int(mo.group(2)) + + # commit: short hex revision ID + pieces["short"] = mo.group(3) + + else: + # HEX: no tags + pieces["closest-tag"] = None + count_out, rc = run_command(GITS, ["rev-list", "HEAD", "--count"], + cwd=root) + pieces["distance"] = int(count_out) # total number of commits + + # commit date: see ISO-8601 comment in git_versions_from_keywords() + date = run_command(GITS, ["show", "-s", "--format=%ci", "HEAD"], + cwd=root)[0].strip() + pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1) + + return pieces + + +def do_vcs_install(manifest_in, versionfile_source, ipy): + """Git-specific installation logic for Versioneer. + + For Git, this means creating/changing .gitattributes to mark _version.py + for export-subst keyword substitution. + """ + GITS = ["git"] + if sys.platform == "win32": + GITS = ["git.cmd", "git.exe"] + files = [manifest_in, versionfile_source] + if ipy: + files.append(ipy) + try: + me = __file__ + if me.endswith(".pyc") or me.endswith(".pyo"): + me = os.path.splitext(me)[0] + ".py" + versioneer_file = os.path.relpath(me) + except NameError: + versioneer_file = "versioneer.py" + files.append(versioneer_file) + present = False + try: + f = open(".gitattributes", "r") + for line in f.readlines(): + if line.strip().startswith(versionfile_source): + if "export-subst" in line.strip().split()[1:]: + present = True + f.close() + except EnvironmentError: + pass + if not present: + f = open(".gitattributes", "a+") + f.write("%s export-subst\n" % versionfile_source) + f.close() + files.append(".gitattributes") + run_command(GITS, ["add", "--"] + files) + + +def versions_from_parentdir(parentdir_prefix, root, verbose): + """Try to determine the version from the parent directory name. + + Source tarballs conventionally unpack into a directory that includes both + the project name and a version string. We will also support searching up + two directory levels for an appropriately named parent directory + """ + rootdirs = [] + + for i in range(3): + dirname = os.path.basename(root) + if dirname.startswith(parentdir_prefix): + return {"version": dirname[len(parentdir_prefix):], + "full-revisionid": None, + "dirty": False, "error": None, "date": None} + else: + rootdirs.append(root) + root = os.path.dirname(root) # up a level + + if verbose: + print("Tried directories %s but none started with prefix %s" % + (str(rootdirs), parentdir_prefix)) + raise NotThisMethod("rootdir doesn't start with parentdir_prefix") + + +SHORT_VERSION_PY = """ +# This file was generated by 'versioneer.py' (0.18) from +# revision-control system data, or from the parent directory name of an +# unpacked source archive. Distribution tarballs contain a pre-generated copy +# of this file. + +import json + +version_json = ''' +%s +''' # END VERSION_JSON + + +def get_versions(): + return json.loads(version_json) +""" + + +def versions_from_file(filename): + """Try to determine the version from _version.py if present.""" + try: + with open(filename) as f: + contents = f.read() + except EnvironmentError: + raise NotThisMethod("unable to read _version.py") + mo = re.search(r"version_json = '''\n(.*)''' # END VERSION_JSON", + contents, re.M | re.S) + if not mo: + mo = re.search(r"version_json = '''\r\n(.*)''' # END VERSION_JSON", + contents, re.M | re.S) + if not mo: + raise NotThisMethod("no version_json in _version.py") + return json.loads(mo.group(1)) + + +def write_to_version_file(filename, versions): + """Write the given version number to the given _version.py file.""" + os.unlink(filename) + contents = json.dumps(versions, sort_keys=True, + indent=1, separators=(",", ": ")) + with open(filename, "w") as f: + f.write(SHORT_VERSION_PY % contents) + + print("set %s to '%s'" % (filename, versions["version"])) + + +def plus_or_dot(pieces): + """Return a + if we don't already have one, else return a .""" + if "+" in pieces.get("closest-tag", ""): + return "." + return "+" + + +def render_pep440(pieces): + """Build up version string, with post-release "local version identifier". + + Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you + get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty + + Exceptions: + 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty] + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"] or pieces["dirty"]: + rendered += plus_or_dot(pieces) + rendered += "%d.g%s" % (pieces["distance"], pieces["short"]) + if pieces["dirty"]: + rendered += ".dirty" + else: + # exception #1 + rendered = "0+untagged.%d.g%s" % (pieces["distance"], + pieces["short"]) + if pieces["dirty"]: + rendered += ".dirty" + return rendered + + +def render_pep440_pre(pieces): + """TAG[.post.devDISTANCE] -- No -dirty. + + Exceptions: + 1: no tags. 0.post.devDISTANCE + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"]: + rendered += ".post.dev%d" % pieces["distance"] + else: + # exception #1 + rendered = "0.post.dev%d" % pieces["distance"] + return rendered + + +def render_pep440_post(pieces): + """TAG[.postDISTANCE[.dev0]+gHEX] . + + The ".dev0" means dirty. Note that .dev0 sorts backwards + (a dirty tree will appear "older" than the corresponding clean one), + but you shouldn't be releasing software with -dirty anyways. + + Exceptions: + 1: no tags. 0.postDISTANCE[.dev0] + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"] or pieces["dirty"]: + rendered += ".post%d" % pieces["distance"] + if pieces["dirty"]: + rendered += ".dev0" + rendered += plus_or_dot(pieces) + rendered += "g%s" % pieces["short"] + else: + # exception #1 + rendered = "0.post%d" % pieces["distance"] + if pieces["dirty"]: + rendered += ".dev0" + rendered += "+g%s" % pieces["short"] + return rendered + + +def render_pep440_old(pieces): + """TAG[.postDISTANCE[.dev0]] . + + The ".dev0" means dirty. + + Eexceptions: + 1: no tags. 0.postDISTANCE[.dev0] + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"] or pieces["dirty"]: + rendered += ".post%d" % pieces["distance"] + if pieces["dirty"]: + rendered += ".dev0" + else: + # exception #1 + rendered = "0.post%d" % pieces["distance"] + if pieces["dirty"]: + rendered += ".dev0" + return rendered + + +def render_git_describe(pieces): + """TAG[-DISTANCE-gHEX][-dirty]. + + Like 'git describe --tags --dirty --always'. + + Exceptions: + 1: no tags. HEX[-dirty] (note: no 'g' prefix) + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"]: + rendered += "-%d-g%s" % (pieces["distance"], pieces["short"]) + else: + # exception #1 + rendered = pieces["short"] + if pieces["dirty"]: + rendered += "-dirty" + return rendered + + +def render_git_describe_long(pieces): + """TAG-DISTANCE-gHEX[-dirty]. + + Like 'git describe --tags --dirty --always -long'. + The distance/hash is unconditional. + + Exceptions: + 1: no tags. HEX[-dirty] (note: no 'g' prefix) + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + rendered += "-%d-g%s" % (pieces["distance"], pieces["short"]) + else: + # exception #1 + rendered = pieces["short"] + if pieces["dirty"]: + rendered += "-dirty" + return rendered + + +def render(pieces, style): + """Render the given version pieces into the requested style.""" + if pieces["error"]: + return {"version": "unknown", + "full-revisionid": pieces.get("long"), + "dirty": None, + "error": pieces["error"], + "date": None} + + if not style or style == "default": + style = "pep440" # the default + + if style == "pep440": + rendered = render_pep440(pieces) + elif style == "pep440-pre": + rendered = render_pep440_pre(pieces) + elif style == "pep440-post": + rendered = render_pep440_post(pieces) + elif style == "pep440-old": + rendered = render_pep440_old(pieces) + elif style == "git-describe": + rendered = render_git_describe(pieces) + elif style == "git-describe-long": + rendered = render_git_describe_long(pieces) + else: + raise ValueError("unknown style '%s'" % style) + + return {"version": rendered, "full-revisionid": pieces["long"], + "dirty": pieces["dirty"], "error": None, + "date": pieces.get("date")} + + +class VersioneerBadRootError(Exception): + """The project root directory is unknown or missing key files.""" + + +def get_versions(verbose=False): + """Get the project version from whatever source is available. + + Returns dict with two keys: 'version' and 'full'. + """ + if "versioneer" in sys.modules: + # see the discussion in cmdclass.py:get_cmdclass() + del sys.modules["versioneer"] + + root = get_root() + cfg = get_config_from_root(root) + + assert cfg.VCS is not None, "please set [versioneer]VCS= in setup.cfg" + handlers = HANDLERS.get(cfg.VCS) + assert handlers, "unrecognized VCS '%s'" % cfg.VCS + verbose = verbose or cfg.verbose + assert cfg.versionfile_source is not None, \ + "please set versioneer.versionfile_source" + assert cfg.tag_prefix is not None, "please set versioneer.tag_prefix" + + versionfile_abs = os.path.join(root, cfg.versionfile_source) + + # extract version from first of: _version.py, VCS command (e.g. 'git + # describe'), parentdir. This is meant to work for developers using a + # source checkout, for users of a tarball created by 'setup.py sdist', + # and for users of a tarball/zipball created by 'git archive' or github's + # download-from-tag feature or the equivalent in other VCSes. + + get_keywords_f = handlers.get("get_keywords") + from_keywords_f = handlers.get("keywords") + if get_keywords_f and from_keywords_f: + try: + keywords = get_keywords_f(versionfile_abs) + ver = from_keywords_f(keywords, cfg.tag_prefix, verbose) + if verbose: + print("got version from expanded keyword %s" % ver) + return ver + except NotThisMethod: + pass + + try: + ver = versions_from_file(versionfile_abs) + if verbose: + print("got version from file %s %s" % (versionfile_abs, ver)) + return ver + except NotThisMethod: + pass + + from_vcs_f = handlers.get("pieces_from_vcs") + if from_vcs_f: + try: + pieces = from_vcs_f(cfg.tag_prefix, root, verbose) + ver = render(pieces, cfg.style) + if verbose: + print("got version from VCS %s" % ver) + return ver + except NotThisMethod: + pass + + try: + if cfg.parentdir_prefix: + ver = versions_from_parentdir(cfg.parentdir_prefix, root, verbose) + if verbose: + print("got version from parentdir %s" % ver) + return ver + except NotThisMethod: + pass + + if verbose: + print("unable to compute version") + + return {"version": "0+unknown", "full-revisionid": None, + "dirty": None, "error": "unable to compute version", + "date": None} + + +def get_version(): + """Get the short version string for this project.""" + return get_versions()["version"] + + +def get_cmdclass(): + """Get the custom setuptools/distutils subclasses used by Versioneer.""" + if "versioneer" in sys.modules: + del sys.modules["versioneer"] + # this fixes the "python setup.py develop" case (also 'install' and + # 'easy_install .'), in which subdependencies of the main project are + # built (using setup.py bdist_egg) in the same python process. Assume + # a main project A and a dependency B, which use different versions + # of Versioneer. A's setup.py imports A's Versioneer, leaving it in + # sys.modules by the time B's setup.py is executed, causing B to run + # with the wrong versioneer. Setuptools wraps the sub-dep builds in a + # sandbox that restores sys.modules to it's pre-build state, so the + # parent is protected against the child's "import versioneer". By + # removing ourselves from sys.modules here, before the child build + # happens, we protect the child from the parent's versioneer too. + # Also see https://github.com/warner/python-versioneer/issues/52 + + cmds = {} + + # we add "version" to both distutils and setuptools + from distutils.core import Command + + class cmd_version(Command): + description = "report generated version string" + user_options = [] + boolean_options = [] + + def initialize_options(self): + pass + + def finalize_options(self): + pass + + def run(self): + vers = get_versions(verbose=True) + print("Version: %s" % vers["version"]) + print(" full-revisionid: %s" % vers.get("full-revisionid")) + print(" dirty: %s" % vers.get("dirty")) + print(" date: %s" % vers.get("date")) + if vers["error"]: + print(" error: %s" % vers["error"]) + cmds["version"] = cmd_version + + # we override "build_py" in both distutils and setuptools + # + # most invocation pathways end up running build_py: + # distutils/build -> build_py + # distutils/install -> distutils/build ->.. + # setuptools/bdist_wheel -> distutils/install ->.. + # setuptools/bdist_egg -> distutils/install_lib -> build_py + # setuptools/install -> bdist_egg ->.. + # setuptools/develop -> ? + # pip install: + # copies source tree to a tempdir before running egg_info/etc + # if .git isn't copied too, 'git describe' will fail + # then does setup.py bdist_wheel, or sometimes setup.py install + # setup.py egg_info -> ? + + # we override different "build_py" commands for both environments + if "setuptools" in sys.modules: + from setuptools.command.build_py import build_py as _build_py + else: + from distutils.command.build_py import build_py as _build_py + + class cmd_build_py(_build_py): + def run(self): + root = get_root() + cfg = get_config_from_root(root) + versions = get_versions() + _build_py.run(self) + # now locate _version.py in the new build/ directory and replace + # it with an updated value + if cfg.versionfile_build: + target_versionfile = os.path.join(self.build_lib, + cfg.versionfile_build) + print("UPDATING %s" % target_versionfile) + write_to_version_file(target_versionfile, versions) + cmds["build_py"] = cmd_build_py + + if "cx_Freeze" in sys.modules: # cx_freeze enabled? + from cx_Freeze.dist import build_exe as _build_exe + # nczeczulin reports that py2exe won't like the pep440-style string + # as FILEVERSION, but it can be used for PRODUCTVERSION, e.g. + # setup(console=[{ + # "version": versioneer.get_version().split("+", 1)[0], # FILEVERSION + # "product_version": versioneer.get_version(), + # ... + + class cmd_build_exe(_build_exe): + def run(self): + root = get_root() + cfg = get_config_from_root(root) + versions = get_versions() + target_versionfile = cfg.versionfile_source + print("UPDATING %s" % target_versionfile) + write_to_version_file(target_versionfile, versions) + + _build_exe.run(self) + os.unlink(target_versionfile) + with open(cfg.versionfile_source, "w") as f: + LONG = LONG_VERSION_PY[cfg.VCS] + f.write(LONG % + {"DOLLAR": "$", + "STYLE": cfg.style, + "TAG_PREFIX": cfg.tag_prefix, + "PARENTDIR_PREFIX": cfg.parentdir_prefix, + "VERSIONFILE_SOURCE": cfg.versionfile_source, + }) + cmds["build_exe"] = cmd_build_exe + del cmds["build_py"] + + if 'py2exe' in sys.modules: # py2exe enabled? + try: + from py2exe.distutils_buildexe import py2exe as _py2exe # py3 + except ImportError: + from py2exe.build_exe import py2exe as _py2exe # py2 + + class cmd_py2exe(_py2exe): + def run(self): + root = get_root() + cfg = get_config_from_root(root) + versions = get_versions() + target_versionfile = cfg.versionfile_source + print("UPDATING %s" % target_versionfile) + write_to_version_file(target_versionfile, versions) + + _py2exe.run(self) + os.unlink(target_versionfile) + with open(cfg.versionfile_source, "w") as f: + LONG = LONG_VERSION_PY[cfg.VCS] + f.write(LONG % + {"DOLLAR": "$", + "STYLE": cfg.style, + "TAG_PREFIX": cfg.tag_prefix, + "PARENTDIR_PREFIX": cfg.parentdir_prefix, + "VERSIONFILE_SOURCE": cfg.versionfile_source, + }) + cmds["py2exe"] = cmd_py2exe + + # we override different "sdist" commands for both environments + if "setuptools" in sys.modules: + from setuptools.command.sdist import sdist as _sdist + else: + from distutils.command.sdist import sdist as _sdist + + class cmd_sdist(_sdist): + def run(self): + versions = get_versions() + self._versioneer_generated_versions = versions + # unless we update this, the command will keep using the old + # version + self.distribution.metadata.version = versions["version"] + return _sdist.run(self) + + def make_release_tree(self, base_dir, files): + root = get_root() + cfg = get_config_from_root(root) + _sdist.make_release_tree(self, base_dir, files) + # now locate _version.py in the new base_dir directory + # (remembering that it may be a hardlink) and replace it with an + # updated value + target_versionfile = os.path.join(base_dir, cfg.versionfile_source) + print("UPDATING %s" % target_versionfile) + write_to_version_file(target_versionfile, + self._versioneer_generated_versions) + cmds["sdist"] = cmd_sdist + + return cmds + + +CONFIG_ERROR = """ +setup.cfg is missing the necessary Versioneer configuration. You need +a section like: + + [versioneer] + VCS = git + style = pep440 + versionfile_source = src/myproject/_version.py + versionfile_build = myproject/_version.py + tag_prefix = + parentdir_prefix = myproject- + +You will also need to edit your setup.py to use the results: + + import versioneer + setup(version=versioneer.get_version(), + cmdclass=versioneer.get_cmdclass(), ...) + +Please read the docstring in ./versioneer.py for configuration instructions, +edit setup.cfg, and re-run the installer or 'python versioneer.py setup'. +""" + +SAMPLE_CONFIG = """ +# See the docstring in versioneer.py for instructions. Note that you must +# re-run 'versioneer.py setup' after changing this section, and commit the +# resulting files. + +[versioneer] +#VCS = git +#style = pep440 +#versionfile_source = +#versionfile_build = +#tag_prefix = +#parentdir_prefix = + +""" + +INIT_PY_SNIPPET = """ +from ._version import get_versions +__version__ = get_versions()['version'] +del get_versions +""" + + +def do_setup(): + """Main VCS-independent setup function for installing Versioneer.""" + root = get_root() + try: + cfg = get_config_from_root(root) + except (EnvironmentError, configparser.NoSectionError, + configparser.NoOptionError) as e: + if isinstance(e, (EnvironmentError, configparser.NoSectionError)): + print("Adding sample versioneer config to setup.cfg", + file=sys.stderr) + with open(os.path.join(root, "setup.cfg"), "a") as f: + f.write(SAMPLE_CONFIG) + print(CONFIG_ERROR, file=sys.stderr) + return 1 + + print(" creating %s" % cfg.versionfile_source) + with open(cfg.versionfile_source, "w") as f: + LONG = LONG_VERSION_PY[cfg.VCS] + f.write(LONG % {"DOLLAR": "$", + "STYLE": cfg.style, + "TAG_PREFIX": cfg.tag_prefix, + "PARENTDIR_PREFIX": cfg.parentdir_prefix, + "VERSIONFILE_SOURCE": cfg.versionfile_source, + }) + + ipy = os.path.join(os.path.dirname(cfg.versionfile_source), + "__init__.py") + if os.path.exists(ipy): + try: + with open(ipy, "r") as f: + old = f.read() + except EnvironmentError: + old = "" + if INIT_PY_SNIPPET not in old: + print(" appending to %s" % ipy) + with open(ipy, "a") as f: + f.write(INIT_PY_SNIPPET) + else: + print(" %s unmodified" % ipy) + else: + print(" %s doesn't exist, ok" % ipy) + ipy = None + + # Make sure both the top-level "versioneer.py" and versionfile_source + # (PKG/_version.py, used by runtime code) are in MANIFEST.in, so + # they'll be copied into source distributions. Pip won't be able to + # install the package without this. + manifest_in = os.path.join(root, "MANIFEST.in") + simple_includes = set() + try: + with open(manifest_in, "r") as f: + for line in f: + if line.startswith("include "): + for include in line.split()[1:]: + simple_includes.add(include) + except EnvironmentError: + pass + # That doesn't cover everything MANIFEST.in can do + # (http://docs.python.org/2/distutils/sourcedist.html#commands), so + # it might give some false negatives. Appending redundant 'include' + # lines is safe, though. + if "versioneer.py" not in simple_includes: + print(" appending 'versioneer.py' to MANIFEST.in") + with open(manifest_in, "a") as f: + f.write("include versioneer.py\n") + else: + print(" 'versioneer.py' already in MANIFEST.in") + if cfg.versionfile_source not in simple_includes: + print(" appending versionfile_source ('%s') to MANIFEST.in" % + cfg.versionfile_source) + with open(manifest_in, "a") as f: + f.write("include %s\n" % cfg.versionfile_source) + else: + print(" versionfile_source already in MANIFEST.in") + + # Make VCS-specific changes. For git, this means creating/changing + # .gitattributes to mark _version.py for export-subst keyword + # substitution. + do_vcs_install(manifest_in, cfg.versionfile_source, ipy) + return 0 + + +def scan_setup_py(): + """Validate the contents of setup.py against Versioneer's expectations.""" + found = set() + setters = False + errors = 0 + with open("setup.py", "r") as f: + for line in f.readlines(): + if "import versioneer" in line: + found.add("import") + if "versioneer.get_cmdclass()" in line: + found.add("cmdclass") + if "versioneer.get_version()" in line: + found.add("get_version") + if "versioneer.VCS" in line: + setters = True + if "versioneer.versionfile_source" in line: + setters = True + if len(found) != 3: + print("") + print("Your setup.py appears to be missing some important items") + print("(but I might be wrong). Please make sure it has something") + print("roughly like the following:") + print("") + print(" import versioneer") + print(" setup( version=versioneer.get_version(),") + print(" cmdclass=versioneer.get_cmdclass(), ...)") + print("") + errors += 1 + if setters: + print("You should remove lines like 'versioneer.VCS = ' and") + print("'versioneer.versionfile_source = ' . This configuration") + print("now lives in setup.cfg, and should be removed from setup.py") + print("") + errors += 1 + return errors + + +if __name__ == "__main__": + cmd = sys.argv[1] + if cmd == "setup": + errors = do_setup() + errors += scan_setup_py() + if errors: + sys.exit(1) diff --git a/xmidas/__init__.py b/xmidas/__init__.py old mode 100644 new mode 100755 index 80edaf0..5c58ab0 --- a/xmidas/__init__.py +++ b/xmidas/__init__.py @@ -1,4 +1,3 @@ -from ._version import get_versions +# xmidas/__init__.py +__version__ = "1.0.0" -__version__ = get_versions()["version"] -del get_versions diff --git a/xmidas/_version.py b/xmidas/_version.py deleted file mode 100644 index 00d015b..0000000 --- a/xmidas/_version.py +++ /dev/null @@ -1,538 +0,0 @@ -# This file helps to compute a version number in source trees obtained from -# git-archive tarball (such as those provided by githubs download-from-tag -# feature). Distribution tarballs (built by setup.py sdist) and build -# directories (produced by setup.py build) will contain a much shorter file -# that just contains the computed version number. - -# This file is released into the public domain. Generated by -# versioneer-0.18 (https://github.com/warner/python-versioneer) - -"""Git implementation of _version.py.""" - -import errno -import os -import re -import subprocess -import sys - - -def get_keywords(): - """Get the keywords needed to look up the version information.""" - # these strings will be replaced by git during git-archive. - # setup.py/versioneer.py will grep for the variable names, so they must - # each be defined on a line of their own. _version.py will just call - # get_keywords(). - git_refnames = "$Format:%d$" - git_full = "$Format:%H$" - git_date = "$Format:%ci$" - keywords = {"refnames": git_refnames, "full": git_full, "date": git_date} - return keywords - - -class VersioneerConfig: - """Container for Versioneer configuration parameters.""" - - -def get_config(): - """Create, populate and return the VersioneerConfig() object.""" - # these strings are filled in when 'setup.py versioneer' creates - # _version.py - cfg = VersioneerConfig() - cfg.VCS = "git" - cfg.style = "pep440-post" - cfg.tag_prefix = "v" - cfg.parentdir_prefix = "None" - cfg.versionfile_source = "xmidas/_version.py" - cfg.verbose = False - return cfg - - -class NotThisMethod(Exception): - """Exception raised if a method is not valid for the current scenario.""" - - -LONG_VERSION_PY = {} -HANDLERS = {} - - -def register_vcs_handler(vcs, method): # decorator - """Decorator to mark a method as the handler for a particular VCS.""" - - def decorate(f): - """Store f in HANDLERS[vcs][method].""" - if vcs not in HANDLERS: - HANDLERS[vcs] = {} - HANDLERS[vcs][method] = f - return f - - return decorate - - -def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, env=None): - """Call the given command(s).""" - assert isinstance(commands, list) - p = None - for c in commands: - try: - dispcmd = str([c] + args) - # remember shell=False, so use git.cmd on windows, not just git - p = subprocess.Popen( - [c] + args, - cwd=cwd, - env=env, - stdout=subprocess.PIPE, - stderr=(subprocess.PIPE if hide_stderr else None), - ) - break - except EnvironmentError: - e = sys.exc_info()[1] - if e.errno == errno.ENOENT: - continue - if verbose: - print("unable to run %s" % dispcmd) - print(e) - return None, None - else: - if verbose: - print("unable to find command, tried %s" % (commands,)) - return None, None - stdout = p.communicate()[0].strip() - if sys.version_info[0] >= 3: - stdout = stdout.decode() - if p.returncode != 0: - if verbose: - print("unable to run %s (error)" % dispcmd) - print("stdout was %s" % stdout) - return None, p.returncode - return stdout, p.returncode - - -def versions_from_parentdir(parentdir_prefix, root, verbose): - """Try to determine the version from the parent directory name. - - Source tarballs conventionally unpack into a directory that includes both - the project name and a version string. We will also support searching up - two directory levels for an appropriately named parent directory - """ - rootdirs = [] - - for i in range(3): - dirname = os.path.basename(root) - if dirname.startswith(parentdir_prefix): - return { - "version": dirname[len(parentdir_prefix) :], - "full-revisionid": None, - "dirty": False, - "error": None, - "date": None, - } - else: - rootdirs.append(root) - root = os.path.dirname(root) # up a level - - if verbose: - print("Tried directories %s but none started with prefix %s" % (str(rootdirs), parentdir_prefix)) - raise NotThisMethod("rootdir doesn't start with parentdir_prefix") - - -@register_vcs_handler("git", "get_keywords") -def git_get_keywords(versionfile_abs): - """Extract version information from the given file.""" - # the code embedded in _version.py can just fetch the value of these - # keywords. When used from setup.py, we don't want to import _version.py, - # so we do it with a regexp instead. This function is not used from - # _version.py. - keywords = {} - try: - f = open(versionfile_abs, "r") - for line in f.readlines(): - if line.strip().startswith("git_refnames ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["refnames"] = mo.group(1) - if line.strip().startswith("git_full ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["full"] = mo.group(1) - if line.strip().startswith("git_date ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["date"] = mo.group(1) - f.close() - except EnvironmentError: - pass - return keywords - - -@register_vcs_handler("git", "keywords") -def git_versions_from_keywords(keywords, tag_prefix, verbose): - """Get version information from git keywords.""" - if not keywords: - raise NotThisMethod("no keywords at all, weird") - date = keywords.get("date") - if date is not None: - # git-2.2.0 added "%cI", which expands to an ISO-8601 -compliant - # datestamp. However we prefer "%ci" (which expands to an "ISO-8601 - # -like" string, which we must then edit to make compliant), because - # it's been around since git-1.5.3, and it's too difficult to - # discover which version we're using, or to work around using an - # older one. - date = date.strip().replace(" ", "T", 1).replace(" ", "", 1) - refnames = keywords["refnames"].strip() - if refnames.startswith("$Format"): - if verbose: - print("keywords are unexpanded, not using") - raise NotThisMethod("unexpanded keywords, not a git-archive tarball") - refs = set([r.strip() for r in refnames.strip("()").split(",")]) - # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of - # just "foo-1.0". If we see a "tag: " prefix, prefer those. - TAG = "tag: " - tags = set([r[len(TAG) :] for r in refs if r.startswith(TAG)]) - if not tags: - # Either we're using git < 1.8.3, or there really are no tags. We use - # a heuristic: assume all version tags have a digit. The old git %d - # expansion behaves like git log --decorate=short and strips out the - # refs/heads/ and refs/tags/ prefixes that would let us distinguish - # between branches and tags. By ignoring refnames without digits, we - # filter out many common branch names like "release" and - # "stabilization", as well as "HEAD" and "master". - tags = set([r for r in refs if re.search(r"\d", r)]) - if verbose: - print("discarding '%s', no digits" % ",".join(refs - tags)) - if verbose: - print("likely tags: %s" % ",".join(sorted(tags))) - for ref in sorted(tags): - # sorting will prefer e.g. "2.0" over "2.0rc1" - if ref.startswith(tag_prefix): - r = ref[len(tag_prefix) :] - if verbose: - print("picking %s" % r) - return { - "version": r, - "full-revisionid": keywords["full"].strip(), - "dirty": False, - "error": None, - "date": date, - } - # no suitable tags, so version is "0+unknown", but full hex is still there - if verbose: - print("no suitable tags, using unknown + full revision id") - return { - "version": "0+unknown", - "full-revisionid": keywords["full"].strip(), - "dirty": False, - "error": "no suitable tags", - "date": None, - } - - -@register_vcs_handler("git", "pieces_from_vcs") -def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): - """Get version from 'git describe' in the root of the source tree. - - This only gets called if the git-archive 'subst' keywords were *not* - expanded, and _version.py hasn't already been rewritten with a short - version string, meaning we're inside a checked out source tree. - """ - GITS = ["git"] - if sys.platform == "win32": - GITS = ["git.cmd", "git.exe"] - - out, rc = run_command(GITS, ["rev-parse", "--git-dir"], cwd=root, hide_stderr=True) - if rc != 0: - if verbose: - print("Directory %s not under git control" % root) - raise NotThisMethod("'git rev-parse --git-dir' returned error") - - # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty] - # if there isn't one, this yields HEX[-dirty] (no NUM) - describe_out, rc = run_command( - GITS, ["describe", "--tags", "--dirty", "--always", "--long", "--match", "%s*" % tag_prefix], cwd=root - ) - # --long was added in git-1.5.5 - if describe_out is None: - raise NotThisMethod("'git describe' failed") - describe_out = describe_out.strip() - full_out, rc = run_command(GITS, ["rev-parse", "HEAD"], cwd=root) - if full_out is None: - raise NotThisMethod("'git rev-parse' failed") - full_out = full_out.strip() - - pieces = {} - pieces["long"] = full_out - pieces["short"] = full_out[:7] # maybe improved later - pieces["error"] = None - - # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty] - # TAG might have hyphens. - git_describe = describe_out - - # look for -dirty suffix - dirty = git_describe.endswith("-dirty") - pieces["dirty"] = dirty - if dirty: - git_describe = git_describe[: git_describe.rindex("-dirty")] - - # now we have TAG-NUM-gHEX or HEX - - if "-" in git_describe: - # TAG-NUM-gHEX - mo = re.search(r"^(.+)-(\d+)-g([0-9a-f]+)$", git_describe) - if not mo: - # unparseable. Maybe git-describe is misbehaving? - pieces["error"] = "unable to parse git-describe output: '%s'" % describe_out - return pieces - - # tag - full_tag = mo.group(1) - if not full_tag.startswith(tag_prefix): - if verbose: - fmt = "tag '%s' doesn't start with prefix '%s'" - print(fmt % (full_tag, tag_prefix)) - pieces["error"] = "tag '%s' doesn't start with prefix '%s'" % (full_tag, tag_prefix) - return pieces - pieces["closest-tag"] = full_tag[len(tag_prefix) :] - - # distance: number of commits since tag - pieces["distance"] = int(mo.group(2)) - - # commit: short hex revision ID - pieces["short"] = mo.group(3) - - else: - # HEX: no tags - pieces["closest-tag"] = None - count_out, rc = run_command(GITS, ["rev-list", "HEAD", "--count"], cwd=root) - pieces["distance"] = int(count_out) # total number of commits - - # commit date: see ISO-8601 comment in git_versions_from_keywords() - date = run_command(GITS, ["show", "-s", "--format=%ci", "HEAD"], cwd=root)[0].strip() - pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1) - - return pieces - - -def plus_or_dot(pieces): - """Return a + if we don't already have one, else return a .""" - if "+" in pieces.get("closest-tag", ""): - return "." - return "+" - - -def render_pep440(pieces): - """Build up version string, with post-release "local version identifier". - - Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you - get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty - - Exceptions: - 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty] - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"] or pieces["dirty"]: - rendered += plus_or_dot(pieces) - rendered += "%d.g%s" % (pieces["distance"], pieces["short"]) - if pieces["dirty"]: - rendered += ".dirty" - else: - # exception #1 - rendered = "0+untagged.%d.g%s" % (pieces["distance"], pieces["short"]) - if pieces["dirty"]: - rendered += ".dirty" - return rendered - - -def render_pep440_pre(pieces): - """TAG[.post.devDISTANCE] -- No -dirty. - - Exceptions: - 1: no tags. 0.post.devDISTANCE - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"]: - rendered += ".post.dev%d" % pieces["distance"] - else: - # exception #1 - rendered = "0.post.dev%d" % pieces["distance"] - return rendered - - -def render_pep440_post(pieces): - """TAG[.postDISTANCE[.dev0]+gHEX] . - - The ".dev0" means dirty. Note that .dev0 sorts backwards - (a dirty tree will appear "older" than the corresponding clean one), - but you shouldn't be releasing software with -dirty anyways. - - Exceptions: - 1: no tags. 0.postDISTANCE[.dev0] - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"] or pieces["dirty"]: - rendered += ".post%d" % pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - rendered += plus_or_dot(pieces) - rendered += "g%s" % pieces["short"] - else: - # exception #1 - rendered = "0.post%d" % pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - rendered += "+g%s" % pieces["short"] - return rendered - - -def render_pep440_old(pieces): - """TAG[.postDISTANCE[.dev0]] . - - The ".dev0" means dirty. - - Eexceptions: - 1: no tags. 0.postDISTANCE[.dev0] - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"] or pieces["dirty"]: - rendered += ".post%d" % pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - else: - # exception #1 - rendered = "0.post%d" % pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - return rendered - - -def render_git_describe(pieces): - """TAG[-DISTANCE-gHEX][-dirty]. - - Like 'git describe --tags --dirty --always'. - - Exceptions: - 1: no tags. HEX[-dirty] (note: no 'g' prefix) - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"]: - rendered += "-%d-g%s" % (pieces["distance"], pieces["short"]) - else: - # exception #1 - rendered = pieces["short"] - if pieces["dirty"]: - rendered += "-dirty" - return rendered - - -def render_git_describe_long(pieces): - """TAG-DISTANCE-gHEX[-dirty]. - - Like 'git describe --tags --dirty --always -long'. - The distance/hash is unconditional. - - Exceptions: - 1: no tags. HEX[-dirty] (note: no 'g' prefix) - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - rendered += "-%d-g%s" % (pieces["distance"], pieces["short"]) - else: - # exception #1 - rendered = pieces["short"] - if pieces["dirty"]: - rendered += "-dirty" - return rendered - - -def render(pieces, style): - """Render the given version pieces into the requested style.""" - if pieces["error"]: - return { - "version": "unknown", - "full-revisionid": pieces.get("long"), - "dirty": None, - "error": pieces["error"], - "date": None, - } - - if not style or style == "default": - style = "pep440" # the default - - if style == "pep440": - rendered = render_pep440(pieces) - elif style == "pep440-pre": - rendered = render_pep440_pre(pieces) - elif style == "pep440-post": - rendered = render_pep440_post(pieces) - elif style == "pep440-old": - rendered = render_pep440_old(pieces) - elif style == "git-describe": - rendered = render_git_describe(pieces) - elif style == "git-describe-long": - rendered = render_git_describe_long(pieces) - else: - raise ValueError("unknown style '%s'" % style) - - return { - "version": rendered, - "full-revisionid": pieces["long"], - "dirty": pieces["dirty"], - "error": None, - "date": pieces.get("date"), - } - - -def get_versions(): - """Get version information or return default if unable to do so.""" - # I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have - # __file__, we can work backwards from there to the root. Some - # py2exe/bbfreeze/non-CPython implementations don't do __file__, in which - # case we can only use expanded keywords. - - cfg = get_config() - verbose = cfg.verbose - - try: - return git_versions_from_keywords(get_keywords(), cfg.tag_prefix, verbose) - except NotThisMethod: - pass - - try: - root = os.path.realpath(__file__) - # versionfile_source is the relative path from the top of the source - # tree (where the .git directory might live) to this file. Invert - # this to find the root from __file__. - for i in cfg.versionfile_source.split("/"): - root = os.path.dirname(root) - except NameError: - return { - "version": "0+unknown", - "full-revisionid": None, - "dirty": None, - "error": "unable to find root of source tree", - "date": None, - } - - try: - pieces = git_pieces_from_vcs(cfg.tag_prefix, root, verbose) - return render(pieces, cfg.style) - except NotThisMethod: - pass - - try: - if cfg.parentdir_prefix: - return versions_from_parentdir(cfg.parentdir_prefix, root, verbose) - except NotThisMethod: - pass - - return { - "version": "0+unknown", - "full-revisionid": None, - "dirty": None, - "error": "unable to compute version", - "date": None, - } diff --git a/xmidas/css/darkStyle.css b/xmidas/css/darkStyle.css deleted file mode 100644 index a5e9ddb..0000000 --- a/xmidas/css/darkStyle.css +++ /dev/null @@ -1,68 +0,0 @@ -QWidget { -background-color: rgb(60, 60, 60); -color: rgb(255, 255, 255); -font: 10pt "Segoe UI"; -} - -QPushButton { -background-color: rgb(175, 236, 255); -color: rgb(255, 5,0); -} - -QSlider::groove:horizontal { -border: 1px solid #bbb; -background: white; -height: 10px; -border-radius: 4px; -} - -QSlider::sub-page:horizontal { -background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #66e, stop: 1 #bbf); -background: qlineargradient(x1: 0, y1: 0.2, x2: 1, y2: 1, - stop: 0 #bbf, stop: 1 #55f); -border: 1px solid #777; -height: 10px; -border-radius: 4px; -} - -QSlider::add-page:horizontal { -background: #fff; -border: 1px solid #777; -height: 10px; -border-radius: 4px; -} - -QSlider::handle:horizontal { -background: qlineargradient(x1:0, y1:0, x2:1, y2:1, - stop:0 #eee, stop:1 #ccc); -border: 1px solid #777; -width: 13px; -margin-top: -2px; -margin-bottom: -2px; -border-radius: 4px; -} - -QSlider::handle:horizontal:hover { -background: qlineargradient(x1:0, y1:0, x2:1, y2:1, - stop:0 #fff, stop:1 #ddd); -border: 1px solid #444; -border-radius: 2px; -} - -QSlider::sub-page:horizontal:disabled { -background: #bbb; -border-color: #999; -} - -QSlider::add-page:horizontal:disabled { -background: #eee; -border-color: #999; -} - -QSlider::handle:horizontal:disabled { -background: #eee; -border: 1px solid #aaa; -border-radius: 4px; -} - diff --git a/xmidas/css/defaultStyle.css b/xmidas/css/defaultStyle.css deleted file mode 100644 index 981a787..0000000 --- a/xmidas/css/defaultStyle.css +++ /dev/null @@ -1,72 +0,0 @@ - -QWidget { -font: 10pt "Segoe UI"; -} - -QPushButton { -background-color: rgb(175, 236, 255); -color: rgb(255, 5,0); -font: 10pt "Segoe UI"; -} - -QLabel { -font: 10pt "Segoe UI"; -} - -QSlider::groove:horizontal { -border: 1px solid #bbb; -background: white; -height: 10px; -border-radius: 4px; -} - -QSlider::sub-page:horizontal { -background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #66e, stop: 1 #bbf); -background: qlineargradient(x1: 0, y1: 0.2, x2: 1, y2: 1, - stop: 0 #bbf, stop: 1 #55f); -border: 1px solid #777; -height: 10px; -border-radius: 4px; -} - -QSlider::add-page:horizontal { -background: #fff; -border: 1px solid #777; -height: 10px; -border-radius: 4px; -} - -QSlider::handle:horizontal { -background: qlineargradient(x1:0, y1:0, x2:1, y2:1, - stop:0 #eee, stop:1 #ccc); -border: 1px solid #777; -width: 13px; -margin-top: -2px; -margin-bottom: -2px; -border-radius: 4px; -} - -QSlider::handle:horizontal:hover { -background: qlineargradient(x1:0, y1:0, x2:1, y2:1, - stop:0 #fff, stop:1 #ddd); -border: 1px solid #444; -border-radius: 2px; -} - -QSlider::sub-page:horizontal:disabled { -background: #bbb; -border-color: #999; -} - -QSlider::add-page:horizontal:disabled { -background: #eee; -border-color: #999; -} - -QSlider::handle:horizontal:disabled { -background: #eee; -border: 1px solid #aaa; -border-radius: 4px; -} - diff --git a/xmidas/css/modern.css b/xmidas/css/modern.css deleted file mode 100644 index 1bc5d20..0000000 --- a/xmidas/css/modern.css +++ /dev/null @@ -1,289 +0,0 @@ -/* ///////////////////////////////////////////////////////////////////////////////////////////////// - -SET APP STYLESHEET - FULL STYLES HERE -DARK THEME - DRACULA COLOR BASED - -///////////////////////////////////////////////////////////////////////////////////////////////// */ - -QWidget{ - background-color: rgb(23,23,37); - color: rgb(255, 255, 200); - font: 10pt "Segoe UI"; -} - - - -/* ///////////////////////////////////////////////////////////////////////////////////////////////// -Tooltip */ -QToolTip { - color: #ffffff; - background-color: rgba(33, 37, 43, 180); - border: 1px solid rgb(44, 49, 58); - background-image: none; - background-position: left center; - background-repeat: no-repeat; - border: none; - border-left: 2px solid rgb(255, 121, 198); - text-align: left; - padding-left: 8px; - margin: 0px; -} - - -QPushButton { - background-color: rgb(210, 210, 98); - color: rgb(23,23,37); - border: none; - border-radius: 5px; - padding: 4px; -} -QPushButton:hover { - background-color: rgb(211, 100, 211); -} -QPushButton:pressed { - background-color: rgb(189, 147, 249); - color: rgb(255, 255, 255); -} - - -QTabWidget { - color: rgb(44, 0, 0); -} -QTabWidget::item{ - color: rgb(24, 0, 0); -} -QTabBar::tab { - color:rgb(24, 0, 0); -} - -QLineEdit { - background-color: rgb(33, 37, 43); - border-radius: 5px; - border: 2px solid rgb(33, 37, 43); - padding-left: 10px; - color: rgb(255,255,255); - selection-color: rgb(255, 255, 255); - selection-background-color: rgb(255, 121, 198); -} -QLineEdit:hover { - border: 2px solid rgb(64, 71, 88); -} -QLineEdit:focus { - border: 2px solid rgb(91, 101, 124); -} - -/* ///////////////////////////////////////////////////////////////////////////////////////////////// -PlainTextEdit */ -QPlainTextEdit { - background-color: rgb(27, 29, 35); - border-radius: 5px; - padding: 10px; - selection-color: rgb(255, 255, 255); - selection-background-color: rgb(255, 121, 198); -} -QPlainTextEdit QScrollBar:vertical { - width: 8px; - } -QPlainTextEdit QScrollBar:horizontal { - height: 8px; - } -QPlainTextEdit:hover { - border: 2px solid rgb(64, 71, 88); -} -QPlainTextEdit:focus { - border: 2px solid rgb(91, 101, 124); -} - -/* ///////////////////////////////////////////////////////////////////////////////////////////////// -ScrollBars */ -QScrollBar:horizontal { - border: none; - background: rgb(52, 59, 72); - height: 8px; - margin: 0px 21px 0 21px; - border-radius: 0px; -} -QScrollBar::handle:horizontal { - background: rgb(189, 147, 249); - min-width: 25px; - border-radius: 4px -} -QScrollBar::add-line:horizontal { - border: none; - background: rgb(55, 63, 77); - width: 20px; - border-top-right-radius: 4px; - border-bottom-right-radius: 4px; - subcontrol-position: right; - subcontrol-origin: margin; -} -QScrollBar::sub-line:horizontal { - border: none; - background: rgb(55, 63, 77); - width: 20px; - border-top-left-radius: 4px; - border-bottom-left-radius: 4px; - subcontrol-position: left; - subcontrol-origin: margin; -} -QScrollBar::up-arrow:horizontal, QScrollBar::down-arrow:horizontal -{ - background: none; -} -QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal -{ - background: none; -} - QScrollBar:vertical { - border: none; - background: rgb(52, 59, 72); - width: 8px; - margin: 21px 0 21px 0; - border-radius: 0px; - } - QScrollBar::handle:vertical { - background: rgb(189, 147, 249); - min-height: 25px; - border-radius: 4px - } - QScrollBar::add-line:vertical { - border: none; - background: rgb(55, 63, 77); - height: 20px; - border-bottom-left-radius: 4px; - border-bottom-right-radius: 4px; - subcontrol-position: bottom; - subcontrol-origin: margin; - } - QScrollBar::sub-line:vertical { - border: none; - background: rgb(55, 63, 77); - height: 20px; - border-top-left-radius: 4px; - border-top-right-radius: 4px; - subcontrol-position: top; - subcontrol-origin: margin; - } - QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical { - background: none; - } - - QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { - background: none; - } - - -QRadioButton::indicator { - border: 3px solid rgb(52, 59, 72); - width: 15px; - height: 15px; - border-radius: 10px; - background: rgb(44, 4, 0); -} -QRadioButton::indicator:hover { - border: 3px solid rgb(58, 66, 81); -} -QRadioButton::indicator:checked { - background: 3px solid rgb(0, 255, 0); - border: 3px solid rgb(255, 252, 255); -} - -QCheckBox::indicator { - border: 3px solid rgb(52, 59, 72); - width: 15px; - height: 15px; - border-radius: 10px; - background: rgb(44, 4, 0); -} -QCheckBox::indicator:hover { - border: 3px solid rgb(58, 66, 81); -} -QCheckBox::indicator:checked { - background: 3px solid rgb(0, 255, 0); - border: 3px solid rgb(255, 252, 255); -} - -/* ///////////////////////////////////////////////////////////////////////////////////////////////// -ComboBox */ -QComboBox{ - background-color: rgb(138, 138, 138); - color: rgb(79, 27, 79); - border-radius: 5px; - border: 2px solid rgb(33, 37, 43); - padding: 5px; - padding-left: 10px; -} -QComboBox:hover{ - border: 2px solid rgb(64, 71, 88); -} -QComboBox::drop-down { - subcontrol-origin: padding; - subcontrol-position: top right; - width: 25px; - border-left-width: 3px; - border-left-color: rgba(39, 44, 54, 150); - border-left-style: solid; - border-top-right-radius: 3px; - border-bottom-right-radius: 3px; - background-image: url(:/icons/images/icons/cil-arrow-bottom.png); - background-position: center; - background-repeat: no-reperat; - } -QComboBox QAbstractItemView { - color: rgb(255, 121, 198); - background-color: rgb(33, 37, 43); - padding: 10px; - selection-background-color: rgb(39, 44, 54); -} - -/* ///////////////////////////////////////////////////////////////////////////////////////////////// -Sliders */ -QSlider::groove:horizontal { - border-radius: 5px; - height: 10px; - margin: 0px; - background-color: rgb(52, 59, 72); -} -QSlider::groove:horizontal:hover { - background-color: rgb(55, 62, 76); -} -QSlider::handle:horizontal { - background-color: rgb(189, 147, 249); - border: none; - height: 10px; - width: 10px; - margin: 0px; - border-radius: 5px; -} -QSlider::handle:horizontal:hover { - background-color: rgb(195, 155, 255); -} -QSlider::handle:horizontal:pressed { - background-color: rgb(255, 121, 198); -} - -QSlider::groove:vertical { - border-radius: 5px; - width: 10px; - margin: 0px; - background-color: rgb(52, 59, 72); -} -QSlider::groove:vertical:hover { - background-color: rgb(55, 62, 76); -} -QSlider::handle:vertical { - background-color: rgb(189, 147, 249); - border: none; - height: 10px; - width: 10px; - margin: 0px; - border-radius: 5px; -} -QSlider::handle:vertical:hover { - background-color: rgb(195, 155, 255); -} -QSlider::handle:vertical:pressed { - background-color: rgb(255, 121, 198); -} - - diff --git a/xmidas/main.py b/xmidas/main.py index 9005597..7073849 100644 --- a/xmidas/main.py +++ b/xmidas/main.py @@ -1,4217 +1,2728 @@ -# -*- coding: utf-8 -*- - -# Author: Ajith Pattammattel -# First Version on:06-23-2020 - -import argparse -import logging -import sys -import webbrowser -import traceback -import os -import json -import h5py -import scipy.stats as stats -import numpy as np -import pandas as pd -import tifffile as tf -import pyqtgraph as pg -import pyqtgraph.exporters -import scipy.optimize as opt -import sklearn.decomposition as sd -import sklearn.cluster as sc - -from pyqtgraph import plot -from itertools import combinations -from scipy.stats import linregress -from scipy.signal import savgol_filter -from skimage.transform import resize -from skimage import filters -from sklearn import linear_model -from larch.xafs import preedge -from pystackreg import StackReg -from packaging import version - -from PyQt5 import QtWidgets, QtCore, QtGui, uic, QtTest -from PyQt5.QtGui import QMovie -from PyQt5.QtWidgets import QMessageBox, QFileDialog, QApplication -from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot, QRunnable, QThreadPool, PYQT_VERSION_STR - -from . import __version__ - -# from MultiChannel import * - -logger = logging.getLogger() -try: - import cv2 # noqa: F401 -except Exception: - logger.warning("openCV module not found") - pass -if hasattr(QtCore.Qt, "AA_EnableHighDpiScaling"): - QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True) - -if hasattr(QtCore.Qt, "AA_UseHighDpiPixmaps"): - QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True) - -ui_path = os.path.dirname(os.path.abspath(__file__)) - -# global settings for pyqtgraph plot and image colormaps -pg.setConfigOption("imageAxisOrder", "row-major") -cmap_names = ["CET-L13", "CET-L14", "CET-L15"] -cmap_combo = combinations(cmap_names, 2) -cmap_label1 = ["red", "green", "blue"] -cmap_label2 = ["yellow", "magenta", "cyan"] -cmap_dict = {} -for i, name in zip(cmap_names, cmap_label1): - cmap_dict[name] = pg.colormap.get(i).getLookupTable(alpha=True) - -for i, name in zip(cmap_combo, cmap_label2): - cmap_dict[name] = pg.colormap.get(i[0]).getLookupTable(alpha=True) + pg.colormap.get(i[1]).getLookupTable( - alpha=True - ) - cmap_dict[name][:, 3] = 255 - - grey = ( - pg.colormap.get("CET-L13").getLookupTable(alpha=True) - + pg.colormap.get("CET-L14").getLookupTable(alpha=True) - + pg.colormap.get("CET-L15").getLookupTable(alpha=True) - ) - - grey[:, 3] = 255 - cmap_dict["grey"] = grey - - -class jsonEncoder(json.JSONEncoder): - def default(self, obj): - if isinstance(obj, np.integer): - return int(obj) - elif isinstance(obj, np.floating): - return float(obj) - elif isinstance(obj, np.ndarray): - return obj.tolist() - else: - return super(jsonEncoder, self).default(obj) - - -class midasWindow(QtWidgets.QMainWindow): - def __init__(self, im_stack=None, energy=[], refs=[]): - super(midasWindow, self).__init__() - uic.loadUi(os.path.join(ui_path, "uis/midasMainwindow.ui"), self) - self.im_stack = im_stack - self.energy = energy - self.refs = refs - self.loaded_tranform_file = [] - self.image_roi2_flag = False - self.refStackAvailable = False - self.isAReload = False - self.plotWidth = 2 - self.stackStatusDict = {} - - self.plt_colors = [ - "g", - "r", - "c", - "m", - "y", - "w", - "b", - pg.mkPen(70, 5, 80), - pg.mkPen(255, 85, 130), - pg.mkPen(0, 85, 130), - pg.mkPen(255, 170, 60), - ] * 3 - # window style - self.actionDarkMode.triggered.connect(self.darkMode) - self.actionDefault.triggered.connect(self.defaultMode) - self.actionModern.triggered.connect(self.modernMode) - - # self.setToolTipsVisible(True) - for menuItem in self.findChildren(QtWidgets.QMenu): - menuItem.setToolTipsVisible(True) - - # plotview options - self.actionWhite.triggered.connect(lambda: self.spectrum_view.setBackground("w")) - self.actionRed.triggered.connect(lambda: self.spectrum_view.setBackground("r")) - self.actionYellow.triggered.connect(lambda: self.spectrum_view.setBackground("y")) - self.actionBlue.triggered.connect(lambda: self.spectrum_view.setBackground("b")) - self.actionBlack.triggered.connect(lambda: self.spectrum_view.setBackground((0, 0, 0))) - - self.actn1.triggered.connect(lambda: self.setPlotLineWidth(int(self.actn1.text()))) - self.actn2.triggered.connect(lambda: self.setPlotLineWidth(int(self.actn2.text()))) - self.actn3.triggered.connect(lambda: self.setPlotLineWidth(int(self.actn3.text()))) - self.actn4.triggered.connect(lambda: self.setPlotLineWidth(int(self.actn4.text()))) - self.actn5.triggered.connect(lambda: self.setPlotLineWidth(int(self.actn5.text()))) - self.actn6.triggered.connect(lambda: self.setPlotLineWidth(int(self.actn6.text()))) - self.actn8.triggered.connect(lambda: self.setPlotLineWidth(int(self.actn8.text()))) - self.actn10.triggered.connect(lambda: self.setPlotLineWidth(int(self.actn10.text()))) - - self.actionOpen_Image_Data.triggered.connect(self.browse_file) - self.actionOpen_Multiple_Files.triggered.connect(self.createVirtualStack) - self.actionSave_as.triggered.connect(lambda: self.save_stack()) - self.actionExit.triggered.connect(lambda: QApplication.closeAllWindows()) - self.actionOpen_in_GitHub.triggered.connect(self.open_github_link) - self.actionLoad_Energy.triggered.connect(self.select_elist) - self.menuFile.setToolTipsVisible(True) - - # Accessories - self.actionOpen_Mask_Gen.triggered.connect(self.openMaskMaker) - self.actionMultiColor.triggered.connect(self.openMultiColorWindow) - - # calculations - self.pb_transpose_stack.clicked.connect(lambda: self.threadMaker(self.transposeStack)) - self.pb_swapXY_stack.clicked.connect(lambda: self.threadMaker(self.swapStackXY)) - self.pb_reset_img.clicked.connect(self.reloadImageStack) - self.pb_crop.clicked.connect(self.crop_to_dim) - self.pb_crop.clicked.connect(self.view_stack) - self.sb_scaling_factor.valueChanged.connect(self.view_stack) - self.pb_ref_xanes.clicked.connect(self.select_ref_file) - self.pb_elist_xanes.clicked.connect(self.select_elist) - - # batchjobs - self.actionPlotAllCorrelations.triggered.connect(self.plotCorrelationsAllCombinations) - - [ - uis.valueChanged.connect(self.replot_image) - for uis in [self.hs_smooth_size, self.hs_nsigma, self.hs_bg_threshold] - ] - - [ - uis.stateChanged.connect(self.replot_image) - for uis in [self.cb_remove_bg, self.cb_remove_outliers, self.cb_smooth, self.cb_norm, self.cb_log] - ] - - [ - uis.stateChanged.connect(self.view_stack) - for uis in [self.cb_remove_edges, self.cb_upscale, self.cb_rebin] - ] - - # ToolBar - self.actionStack_Info.triggered.connect(self.displayStackInfo) - self.actionSave_Image.triggered.connect(self.save_disp_img) - self.actionExport_Stack.triggered.connect(lambda: self.save_stack()) - - # ROI background - self.actionSubtract_ROI_BG.triggered.connect(lambda: self.threadMaker(self.removeROIBGStack)) - - # alignment - self.pb_load_align_ref.clicked.connect(self.loadAlignRefImage) - self.pb_loadAlignTranform.clicked.connect(self.importAlignTransformation) - self.pb_saveAlignTranform.clicked.connect(self.exportAlignTransformation) - self.pb_alignStack.clicked.connect(lambda: self.threadMaker(self.stackRegistration)) - # self.pb_alignStack.clicked.connect(self.stackRegistration) - - # save_options - self.actionSave_Sum_Image.triggered.connect(lambda: self.save_stack(method="sum")) - self.actionSave_Mean_Image.triggered.connect(lambda: self.save_stack(method="mean")) - self.pb_save_disp_spec.clicked.connect(self.save_disp_spec) - self.actionSave_Energy_List.triggered.connect(self.saveEnergyList) - self.pb_show_roi.clicked.connect(self.getROIMask) - self.pb_addToCollector.clicked.connect(self.addSpectrumToCollector) - self.pb_collect_clear.clicked.connect(lambda: self.spectrum_view_collect.clear()) - self.pb_saveCollectorPlot.clicked.connect(self.saveCollectorPlot) - - # XANES Normalization - self.pb_apply_xanes_norm.clicked.connect(self.nomalizeLiveSpec) - self.pb_auto_Eo.clicked.connect(self.findEo) - self.pb_xanes_norm_vals.clicked.connect(self.initNormVals) - self.pb_apply_norm_to_stack.clicked.connect(lambda: self.threadMaker(self.normalizeStack)) - self.actionExport_Norm_Params.triggered.connect(self.exportNormParams) - self.actionImport_Norm_Params.triggered.connect(self.importNormParams) - - # Analysis - self.pb_pca_scree.clicked.connect(self.pca_scree_) - self.pb_calc_components.clicked.connect(self.calc_comp_) - self.pb_kmeans_elbow.clicked.connect(self.kmeans_elbow) - self.pb_calc_cluster.clicked.connect(self.clustering_) - self.pb_xanes_fit.clicked.connect(self.fast_xanes_fitting) - self.pb_plot_refs.clicked.connect(self.plt_xanes_refs) - - self.show() - - self.threadpool = QThreadPool() - print(f"Multithreading with maximum {self.threadpool.maxThreadCount()} threads") - - # View Options - def darkMode(self): - self.centralwidget.setStyleSheet(open(os.path.join(ui_path, "css/darkStyle.css")).read()) - - def defaultMode(self): - self.centralwidget.setStyleSheet(open(os.path.join(ui_path, "css/defaultStyle.css")).read()) - - def modernMode(self): - self.centralwidget.setStyleSheet(open(os.path.join(ui_path, "css/modern.css")).read()) - - def setPlotLineWidth(self, width_input): - self.plotWidth = width_input - try: - self.update_spectrum() - except Exception: - pass - - def openMultiColorWindow(self): - self.multicolorwindow = MultiChannelWindow() - self.multicolorwindow.show() - - def openMaskMaker(self): - self.mask_window = MaskSpecViewer(xanes_stack=self.displayedStack, energy=self.energy) - self.mask_window.show() - - def open_github_link(self): - webbrowser.open("https://github.com/pattammattel/NSLS-II-MIDAS/wiki") - - def threadMaker(self, funct): - # Pass the function to execute - worker = Worker(funct) # Any other args, kwargs are passed to the run function - self.loadSplashScreen() - worker.signals.start.connect(self.splash.startAnimation) - worker.signals.result.connect(self.print_output) - - list( - map( - worker.signals.finished.connect, - [ - self.thread_complete, - self.splash.stopAnimation, - self.update_stack_info, - self.update_spectrum, - self.update_image_roi, - ], - ) - ) - - # Execute - self.threadpool.start(worker) - - # File Loading - - def createVirtualStack(self): - """User can load multiple/series of tiff images with same shape. - The 'self.load_stack()' recognizes 'self.filename as list and create the stack. - """ - self.energy = [] - filter = "TIFF (*.tiff);;TIF (*.tif);;all_files (*)" - file_name = QFileDialog() - file_name.setFileMode(QFileDialog.ExistingFiles) - names = file_name.getOpenFileNames(self, "Open files", " ", filter) - if names[0]: - self.file_name = names[0] - self.load_stack() - - else: - self.statusbar_main.showMessage("No file has selected") - pass - - def load_stack(self): - """load the image data from the selected file. - If the the choice is for multiple files stack will be created in a loop. - If single h5 file is selected the unpacking will be done with 'get_xrf_data' function in StackCalcs. - From the h5 the program can recognize the beamline. The exported stack will be normalized to I0. - - If the single tiff file is choosen tf.imread() is used. - - The output 'self.im_stack' is the unmodified data file - """ - - self.log_warning = False # for the Qmessage box in cb_log - self.image_roi2_flag = False - self.cb_log.setChecked(False) - self.cb_remove_edges.setChecked(False) - self.cb_norm.setChecked(False) - self.cb_smooth.setChecked(False) - self.cb_remove_outliers.setChecked(False) - self.cb_remove_bg.setChecked(False) - self.cb_rebin.setChecked(False) - self.cb_upscale.setChecked(False) - self.sb_xrange1.setValue(0) - self.sb_yrange1.setValue(0) - self.sb_zrange1.setValue(0) - - self.menuMask.setEnabled(True) - self.actionLoad_Energy.setEnabled(True) - self.actionSave_Energy_List.setEnabled(True) - self.actionSave_as.setEnabled(True) - - self.sb_zrange2.setMaximum(99999) - self.sb_xrange2.setMaximum(99999) - self.sb_yrange2.setMaximum(99999) - - self.statusbar_main.showMessage("Loading.. please wait...") - - if isinstance(self.file_name, list): - all_images = [] - - for im_file in self.file_name: - img = tf.imread(im_file) - all_images.append(img) # row major image - self.im_stack = np.dstack(all_images).transpose((2, 0, 1)) - self.avgIo = 1 # I0 is only applicable to XRF h5 files - self.sb_zrange2.setValue(self.im_stack.shape[0]) - - else: - if self.file_name.endswith(".h5"): - self.im_stack, mono_e, bl_name, self.avgIo = get_xrf_data(self.file_name) - self.statusbar_main.showMessage(f"Data from {bl_name}") - self.sb_zrange2.setValue(mono_e / 10) - self.energy = [] - - elif self.file_name.endswith(".tiff") or self.file_name.endswith(".tif"): - self.im_stack_ = tf.imread(self.file_name) - if self.im_stack_.ndim == 2: - self.im_stack = self.im_stack_.reshape(1, self.im_stack_.shape[0], self.im_stack_.shape[1]) - - else: - self.im_stack = self.im_stack_ - self.sb_zrange2.setValue(self.im_stack.shape[0]) - self.autoEnergyLoader() - self.energyUnitCheck() - self.avgIo = 1 - - else: - logger.error("Unknown data format") - - """ Fill the stack dimensions to the GUI and set the image dimensions as max values. - This prevent user from choosing higher image dimensions during a resizing event""" - - logger.info(f" loaded stack with {np.shape(self.im_stack)} from the file") - - try: - logger.info(f" Transposed to shape: {np.shape(self.im_stack)}") - self.init_dimZ, self.init_dimY, self.init_dimX = self.im_stack.shape - # Remove any previously set max value during a reload - - self.sb_xrange2.setValue(self.init_dimX) - self.sb_yrange2.setValue(self.init_dimY) - - except UnboundLocalError: - logger.error("No file selected") - pass - - self.view_stack() - logger.info("Stack displayed correctly") - self.update_stack_info() - - logger.info(f"completed image shape {np.shape(self.im_stack)}") - - try: - self.statusbar_main.showMessage(f"Loaded: {self.file_name}") - - except AttributeError: - self.statusbar_main.showMessage("New Stack is made from selected tiffs") - pass - - def browse_file(self): - """To open a file widow and choose the data file. - The filename will be used to load data using 'rest and load stack' function""" - - filename = QFileDialog().getOpenFileName( - self, "Select image data", "", "image file(*.hdf *.h5 *tiff *tif )" - ) - self.file_name = str(filename[0]) - - # if user decides to cancel the file window gui returns to original state - if self.file_name: - self.disconnectImageActions() - self.isAReload = False - self.load_stack() - - else: - self.statusbar_main.showMessage("No file has selected") - pass - - def autoEnergyLoader(self): - dir_, filename_ = os.path.split(self.file_name) - self.efilePath_name = os.path.join(dir_, os.path.splitext(filename_)[0] + ".txt") - self.efilePath_log = os.path.join(dir_, "maps_log_tiff.txt") - - if os.path.isfile(self.efilePath_name): - self.efilePath = self.efilePath_name - self.efileLoader() - self.statusbar_main.showMessage(f"Energy File detected {self.efilePath}") - - elif os.path.isfile(self.efilePath_log): - self.efilePath = self.efilePath_log - self.efileLoader() - self.statusbar_main.showMessage(f"Energy File detected {self.efilePath}") - - else: - self.efilePath = False - self.efileLoader() - - def update_stack_info(self): - z, y, x = np.shape(self.displayedStack) - self.sb_zrange2.setMaximum(z + self.sb_zrange1.value()) - self.sb_xrange2.setValue(x) - self.sb_xrange2.setMaximum(x) - self.sb_yrange2.setValue(y) - self.sb_yrange2.setMaximum(y) - logger.info("Stack info has been updated") - - # Image Transformations - - def crop_to_dim(self): - self.x1, self.x2 = self.sb_xrange1.value(), self.sb_xrange2.value() - self.y1, self.y2 = self.sb_yrange1.value(), self.sb_yrange2.value() - self.z1, self.z2 = self.sb_zrange1.value(), self.sb_zrange2.value() - - try: - self.displayedStack = remove_nan_inf( - self.displayedStack[self.z1 : self.z2, self.y1 : self.y2, self.x1 : self.x2] - ) - except Exception: - self.displayedStack = remove_nan_inf( - self.im_stack[self.z1 : self.z2, self.y1 : self.y2, self.x1 : self.x2] - ) - - def transpose_stack(self): - self.displayedStack = self.displayedStack.T - self.update_spectrum() - self.update_spec_image_roi() - - # Alignement - - def loadAlignRefImage(self): - filename = QFileDialog().getOpenFileName(self, "Image Data", "", "*.tiff *.tif") - file_name = str(filename[0]) - self.alignRefImage = tf.imread(file_name) - assert self.alignRefImage.shape == self.displayedStack.shape, "Image dimensions do not match" - self.refStackAvailable = True - self.rb_alignRefVoid.setChecked(False) - self.change_color_on_load(self.pb_load_align_ref) - - def stackRegistration(self): - self.transformations = { - "TRANSLATION": StackReg.TRANSLATION, - "RIGID_BODY": StackReg.RIGID_BODY, - "SCALED_ROTATION": StackReg.SCALED_ROTATION, - "AFFINE": StackReg.AFFINE, - "BILINEAR": StackReg.BILINEAR, - } - - self.transformType = self.transformations[self.cb_alignTransform.currentText()] - self.alignReferenceImage = self.cb_alignRef.currentText() - self.alignRefStackVoid = self.rb_alignRefVoid.isChecked() - self.alignMaxIter = self.sb_maxIterVal.value() - - if self.cb_use_tmatFile.isChecked(): - if len(self.loaded_tranform_file) > 0: - self.displayedStack = align_with_tmat( - self.displayedStack, tmat_file=self.loaded_tranform_file, transformation=self.transformType - ) - logger.info("Aligned to the tranform File") - - else: - logger.error("No Tranformation File Loaded") - - elif self.cb_iterAlign.isChecked(): - if not self.refStackAvailable: - self.alignRefImage = self.displayedStack - else: - pass - - self.displayedStack = align_stack_iter( - self.displayedStack, - ref_stack_void=False, - ref_stack=self.alignRefImage, - transformation=self.transformType, - method=("previous", "first"), - max_iter=self.alignMaxIter, - ) - - else: - if not self.refStackAvailable: - self.alignRefImage = self.displayedStack - - else: - pass - - self.displayedStack, self.tranform_file = align_stack( - self.displayedStack, - ref_image_void=True, - ref_stack=self.alignRefImage, - transformation=self.transformType, - reference=self.alignReferenceImage, - ) - logger.info("New Tranformation file available") - self.im_stack = self.displayedStack - - def exportAlignTransformation(self): - file_name = QFileDialog().getSaveFileName( - self, "Save Transformation File", "TranformationMatrix.npy", "text file (*.npy)" - ) - if file_name[0]: - np.save(file_name[0], self.tranform_file) - else: - pass - - def importAlignTransformation(self): - file_name = QFileDialog().getOpenFileName(self, "Open Transformation File", " ", "text file (*.npy)") - if file_name[0]: - self.loaded_tranform_file = np.load(file_name[0]) - self.cb_use_tmatFile.setChecked(True) - logger.info("Tranformation File Loaded") - else: - pass - - def loadSplashScreen(self): - self.splash = LoadingScreen() - - px = self.geometry().x() - py = self.geometry().y() - ph = self.geometry().height() - pw = self.geometry().width() - dw = self.splash.width() - dh = self.splash.height() - new_x, new_y = px + (0.5 * pw) - dw, py + (0.5 * ph) - dh - self.splash.setGeometry(new_x, new_y, dw, dh) - - self.splash.show() - - def reloadImageStack(self): - self.isAReload = True - self.load_stack() - - def update_stack(self): - self.displayedStack = self.im_stack - self.crop_to_dim() - - if self.cb_rebin.isChecked(): - self.cb_upscale.setChecked(False) - self.sb_scaling_factor.setEnabled(True) - self.displayedStack = resize_stack(self.displayedStack, scaling_factor=self.sb_scaling_factor.value()) - self.update_stack_info() - - elif self.cb_upscale.isChecked(): - self.cb_rebin.setChecked(False) - self.sb_scaling_factor.setEnabled(True) - self.displayedStack = resize_stack( - self.displayedStack, upscaling=True, scaling_factor=self.sb_scaling_factor.value() - ) - self.update_stack_info() - - if self.cb_remove_outliers.isChecked(): - self.hs_nsigma.setEnabled(True) - nsigma = self.hs_nsigma.value() / 10 - self.displayedStack = remove_hot_pixels(self.displayedStack, NSigma=nsigma) - self.label_nsigma.setText(str(nsigma)) - logger.info(f"Removing Outliers with NSigma {nsigma}") - - elif self.cb_remove_outliers.isChecked() is False: - self.hs_nsigma.setEnabled(False) - - if self.cb_remove_edges.isChecked(): - self.displayedStack = remove_edges(self.displayedStack) - logger.info(f"Removed edges, new shape {self.displayedStack.shape}") - self.update_stack_info() - - if self.cb_remove_bg.isChecked(): - self.hs_bg_threshold.setEnabled(True) - logger.info("Removing background") - bg_threshold = self.hs_bg_threshold.value() - self.label_bg_threshold.setText(str(bg_threshold) + "%") - self.displayedStack = clean_stack(self.displayedStack, auto_bg=False, bg_percentage=bg_threshold) - - elif self.cb_remove_bg.isChecked() is False: - self.hs_bg_threshold.setEnabled(False) - - if self.cb_log.isChecked(): - self.displayedStack = remove_nan_inf(np.log10(self.displayedStack)) - logger.info("Log Stack is in use") - - if self.cb_smooth.isChecked(): - self.hs_smooth_size.setEnabled(True) - window = self.hs_smooth_size.value() - if window % 2 == 0: - window = +1 - self.smooth_winow_size.setText("Window size: " + str(window)) - self.displayedStack = smoothen(self.displayedStack, w_size=window) - logger.info("Spectrum Smoothening Applied") - - elif self.cb_smooth.isChecked() is False: - self.hs_smooth_size.setEnabled(False) - - if self.cb_norm.isChecked(): - logger.info("Normalizing spectra") - self.displayedStack = normalize(self.displayedStack, norm_point=-1) - - logger.info("Updated image is in use") - - # ImageView - - def view_stack(self): - if not self.im_stack.ndim == 3: - raise ValueError("stack should be an ndarray with ndim == 3") - else: - self.update_stack() - # self.StackUpdateThread() - - try: - self.image_view.removeItem(self.image_roi_math) - except Exception: - pass - - (self.dim1, self.dim2, self.dim3) = self.displayedStack.shape - self.image_view.setImage(self.displayedStack) - self.image_view.ui.menuBtn.hide() - self.image_view.ui.roiBtn.hide() - self.image_view.setPredefinedGradient("viridis") - self.image_view.setCurrentIndex(self.dim1 // 2) - if len(self.energy) == 0: - self.energy = np.arange(self.z1, self.z2) * 10 - logger.info("Arbitary X-axis used in the plot for XANES") - self.sz = np.max( - [int(self.dim2 * 0.1), int(self.dim3 * 0.1)] - ) # size of the roi set to be 10% of the image area - - self.stack_center = self.energy[len(self.energy) // 2] - self.stack_width = (self.energy.max() - self.energy.min()) // 10 - self.spec_roi = pg.LinearRegionItem( - values=(self.stack_center - self.stack_width, self.stack_center + self.stack_width) - ) - - # a second optional ROI for calculations follow - self.image_roi_math = pg.PolyLineROI( - [[0, 0], [0, self.sz], [self.sz, self.sz], [self.sz, 0]], - pos=(int(self.dim3 // 3), int(self.dim2 // 3)), - pen="r", - closed=True, - removable=True, - ) - - self.spec_roi_math = pg.LinearRegionItem( - values=(self.stack_center - self.stack_width - 10, self.stack_center + self.stack_width - 10), - pen="r", - brush=QtGui.QColor(0, 255, 200, 50), - ) - self.spec_lo_m_idx = self.spec_hi_m_idx = 0 - - self.setImageROI() - self.update_spectrum() - self.update_image_roi() - - if not self.isAReload: - # image connections - self.image_view.mousePressEvent = self.getPointSpectrum - self.spec_roi.sigRegionChanged.connect(self.update_image_roi) - self.spec_roi_math.sigRegionChangeFinished.connect(self.spec_roi_calc) - self.pb_apply_spec_calc.clicked.connect(self.spec_roi_calc) - self.rb_math_roi.clicked.connect(self.update_spectrum) - self.pb_add_roi_2.clicked.connect(self.math_img_roi_flag) - self.image_roi_math.sigRegionChangeFinished.connect(self.image_roi_calc) - self.pb_apply_img_calc.clicked.connect(self.image_roi_calc) - - [ - rbs.clicked.connect(self.setImageROI) - for rbs in [self.rb_poly_roi, self.rb_elli_roi, self.rb_rect_roi, self.rb_line_roi, self.rb_circle_roi] - ] - - def disconnectImageActions(self): - for btns in [self.pb_apply_spec_calc, self.rb_math_roi, self.pb_add_roi_2, self.pb_apply_img_calc]: - try: - btns.disconnect() - except Exception: - pass - - def select_elist(self): - self.energyFileChooser() - self.efileLoader() - self.energyUnitCheck() - self.view_stack() - - def efileLoader(self): - if self.efilePath: - if str(self.efilePath).endswith("log_tiff.txt"): - self.energy = energy_from_logfile(logfile=str(self.efilePath)) - logger.info("Log file from pyxrf processing") - - else: - self.energy = np.loadtxt(str(self.efilePath)) - self.change_color_on_load(self.pb_elist_xanes) - logger.info("Energy file loaded") - - else: - self.statusbar_main.showMessage("No Energy List Selected, Setting Arbitary Axis") - self.energy = np.arange(self.im_stack.shape[0]) - logger.info("Arbitary Energy Axis") - - # assert len(self.energy) == self.dim1, "Number of Energy Points is not equal to stack length" - - def energyUnitCheck(self): - if np.max(self.energy) < 100: - self.cb_kev_flag.setChecked(True) - self.energy *= 1000 - - else: - self.cb_kev_flag.setChecked(False) - - def select_ref_file(self): - self.pb_xanes_fit.setEnabled(True) - self.ref_names = [] - file_name = QFileDialog().getOpenFileName(self, "Open reference file", "", "text file (*.txt *.nor)") - if file_name[0]: - if file_name[0].endswith(".nor"): - self.refs, self.ref_names = create_df_from_nor_try2(athenafile=str(file_name[0])) - self.change_color_on_load(self.pb_ref_xanes) - - elif file_name[0].endswith(".txt"): - self.refs = pd.read_csv(str(file_name[0]), header=None, delim_whitespace=True) - self.change_color_on_load(self.pb_ref_xanes) - - else: - logger.error("No file selected") - pass - - self.plt_xanes_refs() - - def plt_xanes_refs(self): - try: - self.ref_plot.close() - except Exception: - pass - - self.ref_plot = plot(title="Reference Standards") - self.ref_plot.setLabel("bottom", "Energy") - self.ref_plot.setLabel("left", "Intensity") - self.ref_plot.addLegend() - - for n in range(np.shape(self.refs)[1]): - if not n == 0: - self.ref_plot.plot( - self.refs.values[:, 0], - self.refs.values[:, n], - pen=pg.mkPen(self.plt_colors[n - 1], width=self.plotWidth), - name=self.ref_names[n], - ) - - def getPointSpectrum(self, event): - if event.type() == QtCore.QEvent.MouseButtonDblClick: - if event.button() == QtCore.Qt.LeftButton: - self.xpixel = int(self.image_view.view.mapSceneToView(event.pos()).x()) - 1 - zlim, ylim, xlim = self.displayedStack.shape - - if self.xpixel > xlim: - self.xpixel = xlim - 1 - - self.ypixel = int(self.image_view.view.mapSceneToView(event.pos()).y()) - 1 - if self.ypixel > ylim: - self.ypixel = ylim - 1 - self.spectrum_view.addLegend() - self.point_spectrum = self.displayedStack[:, self.ypixel, self.xpixel] - self.spectrum_view.plot( - self.xdata, - self.point_spectrum, - clear=True, - pen=pg.mkPen(pg.mkColor(0, 0, 255, 255), width=self.plotWidth), - symbol="o", - symbolSize=6, - symbolBrush="r", - name=f"Point Spectrum; x= {self.xpixel}, y= {self.ypixel}", - ) - - self.spectrum_view.addItem(self.spec_roi) - - self.statusbar_main.showMessage(f"{self.xpixel} and {self.ypixel}") - - def setImageROI(self): - self.lineROI = pg.LineSegmentROI([[int(self.dim3 // 2), int(self.dim2 // 2)], [self.sz, self.sz]], pen="r") - - self.rectROI = pg.RectROI( - [int(self.dim3 // 2), int(self.dim2 // 2)], - [self.sz, self.sz], - pen="w", - maxBounds=QtCore.QRectF(0, 0, self.dim3, self.dim2), - ) - - self.rectROI.addTranslateHandle([0, 0], [2, 2]) - self.rectROI.addRotateHandle([0, 1], [2, 2]) - - self.ellipseROI = pg.EllipseROI( - [int(self.dim3 // 2), int(self.dim2 // 2)], - [self.sz, self.sz], - pen="w", - maxBounds=QtCore.QRectF(0, 0, self.dim3, self.dim2), - ) - - self.circleROI = pg.CircleROI( - [int(self.dim3 // 2), int(self.dim2 // 2)], - [self.sz, self.sz], - pen="w", - maxBounds=QtCore.QRectF(0, 0, self.dim3, self.dim2), - ) # pos and size - - self.polyLineROI = pg.PolyLineROI( - [[0, 0], [0, self.sz], [self.sz, self.sz], [self.sz, 0]], - pos=(int(self.dim3 // 2), int(self.dim2 // 2)), - maxBounds=QtCore.QRectF(0, 0, self.dim3, self.dim2), - closed=True, - removable=True, - ) - - self.rois = { - "rb_line_roi": self.lineROI, - "rb_rect_roi": self.rectROI, - "rb_circle_roi": self.circleROI, - "rb_elli_roi": self.ellipseROI, - "rb_poly_roi": self.polyLineROI, - } - - button_name = self.sender() - - if button_name.objectName() in self.rois.keys(): - self.roi_preference = button_name.objectName() - - else: - self.roi_preference = "rb_rect_roi" # default - - try: - self.image_view.removeItem(self.image_roi) - - except Exception: - pass - - # ROI settings for image, used polyline roi with non rectangular shape - - self.image_roi = self.rois[self.roi_preference] - self.image_view.addItem(self.image_roi) - self.image_roi.sigRegionChanged.connect(self.update_spectrum) - - def replot_image(self): - self.update_stack() - self.update_spectrum() - self.update_image_roi() - - def update_spec_roi_values(self): - self.stack_center = int(self.energy[len(self.energy) // 2]) - self.stack_width = int((self.energy.max() - self.energy.min()) * 0.05) - self.spec_roi.setBounds([self.xdata[0], self.xdata[-1]]) # if want to set bounds for the spec roi - self.spec_roi_math.setBounds([self.xdata[0], self.xdata[-1]]) - - def update_spectrum(self): - # set x-axis values; array taken from energy values, if clipped z box values will update the array - self.xdata = self.energy[self.sb_zrange1.value() : self.sb_zrange2.value()] - - # get the cropped stack from ROI region; pyqtgraph function is used - self.roi_img_stk = self.image_roi.getArrayRegion( - self.displayedStack, self.image_view.imageItem, axes=(1, 2) - ) - - posx, posy = self.image_roi.pos() - self.le_roi.setText(str(int(posx)) + ":" + str(int(posy))) - - # display the ROI features in the line edit boxes - if self.roi_img_stk.ndim == 3: - sizex, sizey = self.roi_img_stk.shape[1], self.roi_img_stk.shape[2] - self.le_roi_size.setText(str(sizex) + "," + str(sizey)) - self.mean_spectra = get_mean_spectra(self.roi_img_stk) - - elif self.roi_img_stk.ndim == 2: - sizex, sizey = self.roi_img_stk.shape[0], self.roi_img_stk.shape[1] - self.le_roi_size.setText(str(sizex) + "," + str(sizey)) - self.mean_spectra = self.roi_img_stk.mean(-1) - - self.spectrum_view.addLegend() - - try: - self.spectrum_view.plot( - self.xdata, - self.mean_spectra, - pen=pg.mkPen(pg.mkColor(5, 255, 5, 255), width=self.plotWidth), - clear=True, - symbol="o", - symbolSize=6, - symbolBrush="r", - name="ROI Spectrum", - ) - except Exception: - self.spectrum_view.plot( - self.mean_spectra, - clear=True, - pen=pg.mkPen(pg.mkColor(5, 255, 5, 255), width=self.plotWidth), - symbol="o", - symbolSize=6, - symbolBrush="r", - name="ROI Spectrum", - ) - - if self.energy[-1] > 1000: - self.e_unit = "eV" - else: - self.e_unit = "keV" - - self.spectrum_view.setLabel("bottom", "Energy", self.e_unit) - self.spectrum_view.setLabel("left", "Intensity", "A.U.") - self.spectrum_view.addItem(self.spec_roi) - self.update_spec_roi_values() - self.math_roi_flag() - - def update_image_roi(self): - self.spec_lo, self.spec_hi = self.spec_roi.getRegion() - self.spec_lo_idx = (np.abs(self.energy - self.spec_lo)).argmin() - self.spec_hi_idx = (np.abs(self.energy - self.spec_hi)).argmin() - self.le_spec_roi.setText(str(int(self.spec_lo)) + ":" + str(int(self.spec_hi))) - self.le_spec_roi_size.setText(str(int(self.spec_hi - self.spec_lo))) - self.update_spec_roi_values() - self.stackIndexToNames() - - try: - if int(self.spec_lo_idx) == int(self.spec_hi_idx): - self.disp_img = self.displayedStack[int(self.spec_hi_idx), :, :] - - else: - self.disp_img = self.displayedStack[int(self.spec_lo_idx) : int(self.spec_hi_idx), :, :].mean(0) - - self.image_view.setImage(self.disp_img) - self.statusbar_main.showMessage(f"Image Display is {self.corrImg1}") - except Exception: - logger.warning("Indices are out of range; Image cannot be created") - pass - - def set_spec_roi(self): - self.spec_lo_, self.spec_hi_ = int(self.sb_roi_spec_s.value()), int(self.sb_roi_spec_e.value()) - self.spec_lo_idx_ = (np.abs(self.energy - self.spec_lo_)).argmin() - self.spec_hi_idx_ = (np.abs(self.energy - self.spec_hi_)).argmin() - self.spec_roi.setRegion((self.xdata[self.spec_lo_idx_], self.xdata[self.spec_hi_idx_])) - self.update_image_roi() - - def math_roi_flag(self): - if self.rb_math_roi.isChecked(): - self.rb_math_roi.setStyleSheet("color : green") - self.spectrum_view.addItem(self.spec_roi_math) - else: - self.spectrum_view.removeItem(self.spec_roi_math) - - def spec_roi_calc(self): - self.spec_lo_m, self.spec_hi_m = self.spec_roi_math.getRegion() - self.spec_lo_m_idx = (np.abs(self.energy - self.spec_lo_m)).argmin() - self.spec_hi_m_idx = (np.abs(self.energy - self.spec_hi_m)).argmin() - - if int(self.spec_lo_idx) == int(self.spec_hi_idx): - self.img1 = self.displayedStack[int(self.spec_hi_idx), :, :] - - else: - self.img1 = self.displayedStack[int(self.spec_lo_idx) : int(self.spec_hi_idx), :, :].mean(0) - - if int(self.spec_lo_m_idx) == int(self.spec_hi_m_idx): - self.img2 = self.displayedStack[int(self.spec_hi_m_idx), :, :] - - else: - self.img2 = self.displayedStack[int(self.spec_lo_m_idx) : int(self.spec_hi_m_idx), :, :].mean(0) - - if self.cb_roi_operation.currentText() == "Correlation Plot": - self.correlation_plot() - - else: - calc = {"Divide": np.divide, "Subtract": np.subtract, "Add": np.add} - self.disp_img = remove_nan_inf(calc[self.cb_roi_operation.currentText()](self.img1, self.img2)) - self.image_view.setImage(self.disp_img) - - def math_img_roi_flag(self): - button_name = self.sender().text() - logger.info(f"{button_name}") - if button_name == "Add ROI_2": - self.image_view.addItem(self.image_roi_math) - self.pb_add_roi_2.setText("Remove ROI_2") - self.image_roi2_flag = 1 - elif button_name == "Remove ROI_2": - self.image_view.removeItem(self.image_roi_math) - self.pb_add_roi_2.setText("Add ROI_2") - self.image_roi2_flag = 0 - - else: - pass - logger.error("Unknown signal for second ROI") - - def image_roi_calc(self): - if self.image_roi2_flag == 1: - self.calc = {"Divide": np.divide, "Subtract": np.subtract, "Add": np.add} - self.update_spec_image_roi() - else: - logger.error("No ROI2 found") - return - - def update_spec_image_roi(self): - self.math_roi_reg = self.image_roi_math.getArrayRegion( - self.displayedStack, self.image_view.imageItem, axes=(1, 2) - ) - if self.math_roi_reg.ndim == 3: - self.math_roi_spectra = get_mean_spectra(self.math_roi_reg) - - elif self.roi_img_stk.ndim == 2: - self.math_roi_spectra = self.math_roi_reg.mean(-1) - - if self.cb_img_roi_action.currentText() in self.calc.keys(): - calc_spec = self.calc[self.cb_img_roi_action.currentText()](self.mean_spectra, self.math_roi_spectra) - self.spectrum_view.addLegend() - self.spectrum_view.plot( - self.xdata, - calc_spec, - clear=True, - pen=pg.mkPen("m", width=2), - name=self.cb_img_roi_action.currentText() + "ed", - ) - self.spectrum_view.plot(self.xdata, self.math_roi_spectra, pen=pg.mkPen("y", width=2), name="ROI2") - self.spectrum_view.plot(self.xdata, self.mean_spectra, pen=pg.mkPen("g", width=2), name="ROI1") - - elif self.cb_img_roi_action.currentText() == "Compare": - self.spectrum_view.plot( - self.xdata, self.math_roi_spectra, pen=pg.mkPen("y", width=2), clear=True, name="ROI2" - ) - self.spectrum_view.plot(self.xdata, self.mean_spectra, pen=pg.mkPen("g", width=2), name="ROI1") - - self.spectrum_view.addItem(self.spec_roi) - - def displayStackInfo(self): - try: - if isinstance(self.file_name, list): - info = f"Folder; {os.path.dirname(self.file_name[0])} \n" - for n, name in enumerate(self.file_name): - info += f"{n}: {os.path.basename(name)} \n" - - # info = f'Stack order; {[name for name in enumerate(self.file_name)]}' - else: - info = f"Stack; {self.file_name}" - - self.infoWindow = StackInfo(str(info)) - self.infoWindow.show() - - except AttributeError: - self.statusbar_main.showMessage("Warning: No Image Data Loaded") - - def stackIndexToNames(self): - # create list of tiff file names for virtutal stack for plot axes - self.elemFileName = [] - - if isinstance(self.file_name, list): - for name in self.file_name: - self.elemFileName.append(os.path.basename(name).split(".")[0]) - - logger.info(f" Virtual Stack - list of image names; {self.elemFileName}") - - # if the roi focus on one frame, Note that this slicing excludes the last index - if int(self.spec_lo_idx) == int(self.spec_hi_idx): - self.corrImg1 = str(self.elemFileName[int(self.spec_lo_idx)]) - else: - self.corrImg1 = self.elemFileName[int(self.spec_lo_idx) : int(self.spec_hi_idx)] - if len(self.corrImg1) > 1: - self.corrImg1 = f"Sum of {self.corrImg1} " - - if int(self.spec_lo_m_idx) == int(self.spec_hi_m_idx): - self.corrImg2 = str(self.elemFileName[int(self.spec_lo_m_idx)]) - - else: - self.corrImg2 = self.elemFileName[int(self.spec_lo_m_idx) : int(self.spec_hi_m_idx)] - - if len(self.corrImg2) > 1: - self.corrImg2 = f"Sum of {self.corrImg2}" - - logger.info( - f"Correlation stack {int(self.spec_lo_idx)}:{int(self.spec_hi_idx)} with " - f"{int(self.spec_lo_m_idx)}:{int(self.spec_hi_m_idx)}" - ) - - logger.info(f" Virtual Stack; corrlation plot of {self.corrImg1} vs {self.corrImg2}") - else: - self.corrImg1 = ( - f" Sum of {os.path.basename(self.file_name).split('.')[0]}_{int(self.spec_lo_idx)} " - f"to {int(self.spec_hi_idx)}" - ) - self.corrImg2 = ( - f" Sum of {os.path.basename(self.file_name).split('.')[0]}_{int(self.spec_lo_m_idx)} " - f"to {int(self.spec_hi_m_idx)}" - ) - # logger.info(f" corrlation plot of {self.corrImg1} vs {self.corrImg2}") - - def correlation_plot(self): - self.stackIndexToNames() - - self.statusbar_main.showMessage(f"Correlation of {self.corrImg1} with {self.corrImg2}") - - if self.rb_roiRegionOnly.isChecked(): - self.roi_mask = self.image_roi.getArrayRegion( - self.displayedStack, self.image_view.imageItem, axes=(1, 2) - ) - self.roi_img1 = np.mean(self.roi_mask[int(self.spec_lo_idx) : int(self.spec_hi_idx)], axis=0) - self.roi_img2 = np.mean(self.roi_mask[int(self.spec_lo_m_idx) : int(self.spec_hi_m_idx)], axis=0) - self.scatter_window = ScatterPlot( - self.roi_img1, self.roi_img2, (str(self.corrImg1), str(self.corrImg2)) - ) - - else: - self.scatter_window = ScatterPlot(self.img1, self.img2, (str(self.corrImg1), str(self.corrImg2))) - - # ph = self.geometry().height() - # pw = self.geometry().width() - # px = self.geometry().x() - # py = self.geometry().y() - # dw = self.scatter_window.width() - # dh = self.scatter_window.height() - # self.scatter_window.setGeometry(px+0.65*pw, py + ph - 2*dh-5, dw, dh) - self.scatter_window.show() - - def plotCorrelationsAllCombinations(self): - self.stackIndexToNames() - allElemCombNum = list(combinations(np.arange(len(self.elemFileName)), 2)) - - self.scW1 = self.scW2 = self.scW3 = self.scW4 = self.scW5 = None - self.scW6 = self.scW7 = self.scW8 = self.scW9 = self.scW10 = None - - self.scWindowList = [ - self.scW1, - self.scW2, - self.scW3, - self.scW4, - self.scW5, - self.scW6, - self.scW7, - self.scW8, - self.scW9, - self.scW10, - ] - self.scWindowDict = { - 1: self.scW1, - 2: self.scW2, - 3: self.scW3, - 4: self.scW4, - 5: self.scW5, - 6: self.scW6, - 7: self.scW7, - 8: self.scW8, - 9: self.scW9, - 10: self.scW10, - } - - if len(allElemCombNum) > len(self.scWindowDict): - reply = QMessageBox.warning( - self, - "Plot Window Limit", - f"The number of combination exceeds " - f"maxiumum number of " - f"plot windows. First {len(self.scWindowDict)} " - f"combinations will be plotted. \n Proceed?", - QMessageBox.Yes | QMessageBox.No, - QMessageBox.No, - ) - - if reply == QMessageBox.Yes: - for i, pair in enumerate(allElemCombNum): - im1 = self.displayedStack[pair[0]] - im2 = self.displayedStack[pair[1]] - im1Name = self.elemFileName[pair[0]] - im2Name = self.elemFileName[pair[1]] - - self.scWindowDict[i] = ScatterPlot(im1, im2, (str(im1Name), str(im2Name))) - self.scWindowDict[i].show() - - if reply == QMessageBox.No: - return - - def getROIMask(self): - self.roi_mask = self.image_roi.getArrayRegion(self.displayedStack, self.image_view.imageItem, axes=(1, 2)) - self.newWindow = singleStackViewer(self.roi_mask) - self.newWindow.show() - - def save_stack(self, method="raw"): - # self.update_stack() - file_name = QFileDialog().getSaveFileName( - self, "Save image data", "image_data.tiff", "image file(*tiff *tif )" - ) - if file_name[0]: - if method == "raw": - tf.imsave(str(file_name[0]), self.displayedStack) - logger.info(f"Updated Image Saved: {str(file_name[0])}") - self.statusbar_main.showMessage(f"Updated Image Saved: {str(file_name[0])}") - elif method == "sum": - tf.imsave(str(file_name[0]), np.sum(self.displayedStack, axis=0)) - - elif method == "mean": - tf.imsave(str(file_name[0]), np.mean(self.displayedStack, axis=0)) - - else: - self.statusbar_main.showMessage("Saving cancelled") - logger.info(f"Save failed: {str(file_name[0])}") - pass - - def save_disp_img(self): - file_name = QFileDialog().getSaveFileName(self, "Save image data", "image.tiff", "image file(*tiff *tif )") - if file_name[0]: - tf.imsave(str(file_name[0]), self.disp_img) - self.statusbar_main.showMessage(f"Image Saved to {str(file_name[0])}") - logger.info(f"Updated Image Saved: {str(file_name[0])}") - - else: - logger.error("No file to save") - self.statusbar_main.showMessage("Saving cancelled") - pass - - def getLivePlotData(self): - try: - data = np.squeeze([c.getData() for c in self.spectrum_view.plotItem.curves]) - # print(np.shape(data)) - if data.ndim == 2: - self.mu_ = data[1] - self.e_ = data[0] - elif data.ndim == 3: - e_mu = data[0, :, :] - self.mu_ = e_mu[1] - self.e_ = e_mu[0] - - else: - logger.error(f" Data shape of {data.ndim} is not supported") - pass - except AttributeError: - logger.error("No data loaded") - pass - - def addSpectrumToCollector(self): - self.getLivePlotData() - self.spectrum_view_collect.plot(self.e_, self.mu_, name="ROI Spectrum") - self.spectrum_view_collect.setLabel("bottom", "Energy", self.e_unit) - self.spectrum_view_collect.setLabel("left", "Intensity", "A.U.") - - def findEo(self): - try: - self.getLivePlotData() - e0_init = self.e_[np.argmax(np.gradient(self.mu_))] - self.dsb_norm_Eo.setValue(e0_init) - - except AttributeError: - logger.error("No data loaded") - pass - - def initNormVals(self): - self.getLivePlotData() - e0_init = self.e_[np.argmax(np.gradient(self.mu_))] - pre1, pre2, post1, post2 = xanesNormalization( - self.e_, self.mu_, e0=e0_init, step=None, nnorm=1, nvict=0, guess=True - ) - self.dsb_norm_pre1.setValue(pre1) - self.dsb_norm_pre2.setValue(pre2) - self.dsb_norm_post1.setValue(post1) - self.dsb_norm_post2.setValue(post2) - self.dsb_norm_Eo.setValue(e0_init) - - def getNormParams(self): - self.getLivePlotData() - eo_ = self.dsb_norm_Eo.value() - pre1_, pre2_ = self.dsb_norm_pre1.value(), self.dsb_norm_pre2.value() - norm1_, norm2_ = self.dsb_norm_post1.value(), self.dsb_norm_post2.value() - norm_order = self.sb_norm_order.value() - - return eo_, pre1_, pre2_, norm1_, norm2_, norm_order - - def exportNormParams(self): - self.xanesNormParam = {} - eo_, pre1_, pre2_, norm1_, norm2_, norm_order = self.getNormParams() - self.xanesNormParam["E0"] = eo_ - self.xanesNormParam["pre1"] = pre1_ - self.xanesNormParam["pre2"] = pre2_ - self.xanesNormParam["post1"] = norm1_ - self.xanesNormParam["post2"] = norm2_ - self.xanesNormParam["norm_order"] = norm_order - - file_name = QtWidgets.QFileDialog().getSaveFileName( - self, "Save XANES Norm Params", "xanes_norm_params.csv", "csv file(*csv)" - ) - - if file_name[0]: - pd.DataFrame(self.xanesNormParam, index=[0]).to_csv(file_name[0]) - - else: - pass - - def importNormParams(self): - file_name = QtWidgets.QFileDialog().getOpenFileName( - self, "Open a XANES Norm File", "", "csv file(*csv);;all_files (*)" - ) - - if file_name[0]: - xanesNormParam = pd.read_csv(file_name[0]) - self.dsb_norm_Eo.setValue(xanesNormParam["E0"]) - self.dsb_norm_pre1.setValue(xanesNormParam["pre1"]) - self.dsb_norm_pre2.setValue(xanesNormParam["pre2"]) - self.dsb_norm_post1.setValue(xanesNormParam["post1"]) - self.dsb_norm_post2.setValue(xanesNormParam["post2"]) - self.sb_norm_order.setValue(xanesNormParam["norm_order"]) - - def nomalizeLiveSpec(self): - eo_, pre1_, pre2_, norm1_, norm2_, norm_order = self.getNormParams() - self.spectrum_view.clear() - - pre_line, post_line, normXANES = xanesNormalization( - self.e_, - self.mu_, - e0=eo_, - step=None, - nnorm=norm_order, - nvict=0, - pre1=pre1_, - pre2=pre2_, - norm1=norm1_, - norm2=norm2_, - ) - - names = np.array(("Spectrum", "Pre", "Post")) - data_array = np.array((self.mu_, pre_line, post_line)) - colors = np.array(("c", "r", "m")) - - for data, clr, name in zip(data_array, colors, names): - self.spectrum_view.plot(self.e_, data, pen=pg.mkPen(clr, width=self.plotWidth), name=name) - - self.spectrum_view_norm.plot( - self.e_, normXANES, clear=True, pen=pg.mkPen(self.plt_colors[-1], width=self.plotWidth) - ) - self.spectrum_view_norm.setLabel("bottom", "Energy", self.e_unit) - self.spectrum_view_norm.setLabel("left", "Norm. Intensity", "A.U.") - - def normalizeStack(self): - self.getLivePlotData() - eo_, pre1_, pre2_, norm1_, norm2_, norm_order = self.getNormParams() - - self.im_stack = self.displayedStack = xanesNormStack( - self.e_, - self.displayedStack, - e0=eo_, - step=None, - nnorm=norm_order, - nvict=0, - pre1=pre1_, - pre2=pre2_, - norm1=norm1_, - norm2=norm2_, - ) - # self.im_stack = self.displayedStack - - def transposeStack(self): - self.im_stack = self.displayedStack = np.transpose(self.displayedStack, (2, 1, 0)) - - def swapStackXY(self): - self.im_stack = self.displayedStack = np.transpose(self.displayedStack, (0, 2, 1)) - - def removeROIBGStack(self): - self.displayedStack = subtractBackground(self.displayedStack, self.mean_spectra) - - def resetCollectorSpec(self): - pass - - def saveCollectorPlot(self): - exporter = pg.exporters.CSVExporter(self.spectrum_view_collect.plotItem) - exporter.parameters()["columnMode"] = "(x,y,y,y) for all plots" - file_name = QFileDialog().getSaveFileName(self, "save spectra", "", "spectra (*csv)") - if file_name[0]: - exporter.export(str(file_name[0]) + ".csv") - else: - self.statusbar_main.showMessage("Saving cancelled") - pass - - def save_disp_spec(self): - exporter = pg.exporters.CSVExporter(self.spectrum_view.plotItem) - exporter.parameters()["columnMode"] = "(x,y,y,y) for all plots" - file_name = QFileDialog().getSaveFileName(self, "save spectrum", "", "spectra (*csv)") - if file_name[0]: - exporter.export(str(file_name[0]) + ".csv") - else: - self.statusbar_main.showMessage("Saving cancelled") - pass - - def saveEnergyList(self): - file_name = QFileDialog().getSaveFileName(self, "save energy list", "energy_list.txt", "text file (*txt)") - if file_name[0]: - np.savetxt(file_name[0], self.xdata, fmt="%.4f") - else: - pass - - def pca_scree_(self): - logger.info("Process started..") - self.update_stack() - pca_scree(self.displayedStack) - logger.info("Process complete") - - def calc_comp_(self): - logger.info("Process started..") - - # self.update_stack() - n_components = self.sb_ncomp.value() - method_ = self.cb_comp_method.currentText() - - ims, comp_spec, decon_spec, decomp_map = decompose_stack( - self.displayedStack, decompose_method=method_, n_components_=n_components - ) - - self._new_window3 = ComponentViewer(ims, self.xdata, comp_spec, decon_spec, decomp_map) - self._new_window3.show() - - logger.info("Process complete") - - def kmeans_elbow(self): - logger.info("Process started..") - # self.update_stack() - - with pg.BusyCursor(): - try: - kmeans_variance(self.displayedStack) - logger.info("Process complete") - except OverflowError: - pass - logger.error("Overflow Error, values are too long") - - def kmeans_elbow_Thread(self): - # Pass the function to execute - worker = Worker(self.kmeans_elbow) # Any other args, kwargs are passed to the run function - worker.signals.result.connect(self.print_output) - worker.signals.finished.connect(self.thread_complete) - # Execute - self.threadpool.start(worker) - - def clustering_(self): - logger.info("Process started..") - # self.update_stack() - method_ = self.cb_clust_method.currentText() - - decon_images, X_cluster, decon_spectra = cluster_stack( - self.displayedStack, - method=method_, - n_clusters_=self.sb_ncluster.value(), - decomposed=False, - decompose_method=self.cb_comp_method.currentText(), - decompose_comp=self.sb_ncomp.value(), - ) - - self._new_window4 = ClusterViewer(decon_images, self.xdata, X_cluster, decon_spectra) - self._new_window4.show() - - logger.info("Process complete") - - def change_color_on_load(self, button_name): - button_name.setStyleSheet("background-color : rgb(0,150,0);" "color: rgb(255,255,255)") - - def energyFileChooser(self): - file_name = QFileDialog().getOpenFileName(self, "Open energy list", "", "text file (*.txt)") - self.efilePath = file_name[0] - - def fast_xanes_fitting(self): - self._new_window5 = XANESViewer(self.displayedStack, self.xdata, self.refs, self.ref_names) - self._new_window5.show() - - # Thread Signals - - def print_output(self, s): - print(s) - - def thread_complete(self): - print("THREAD COMPLETE!") - - def closeEvent(self, event): - reply = QMessageBox.question( - self, - "Window Close", - "Are you sure you want to close?", - QMessageBox.Yes | QMessageBox.No, - QMessageBox.No, - ) - - if reply == QMessageBox.Yes: - event.accept() - QApplication.closeAllWindows() - else: - event.ignore() - - -class WorkerSignals(QObject): - """ - Defines the signals available from a running worker thread. - Supported signals are: - - finished: No data - - error:`tuple` (exctype, value, traceback.format_exc() ) - - result: `object` data returned from processing, anything - - progress: `tuple` indicating progress metadata - """ - - start = pyqtSignal() - finished = pyqtSignal() - error = pyqtSignal(tuple) - result = pyqtSignal(object) - - -class Worker(QRunnable): - """ - Worker thread - Inherits from QRunnable to handler worker thread setup, signals and wrap-up. - """ - - def __init__(self, fn, *args, **kwargs): - super(Worker, self).__init__() - # Store constructor arguments (re-used for processing) - self.fn = fn - self.args = args - self.kwargs = kwargs - self.signals = WorkerSignals() - - @pyqtSlot() - def run(self): - """ - Initialise the runner function with passed args, kwargs. - """ - # Retrieve args/kwargs here; and fire processing using them - self.signals.start.emit() - try: - result = self.fn(*self.args, **self.kwargs) - except Exception: - traceback.print_exc() - exctype, value = sys.exc_info()[:2] - self.signals.error.emit((exctype, value, traceback.format_exc())) - else: - self.signals.result.emit(result) # Return the result of the processing - finally: - self.signals.finished.emit() # Done - - -class singleStackViewer(QtWidgets.QMainWindow): - def __init__(self, img_stack, gradient="viridis"): - super(singleStackViewer, self).__init__() - - # Load the UI Page - uic.loadUi(os.path.join(ui_path, "uis/singleStackView.ui"), self) - - self.image_view.ui.menuBtn.hide() - self.image_view.ui.roiBtn.hide() - - self.img_stack = img_stack - self.gradient = gradient - self.image_view.setPredefinedGradient(gradient) - - if self.img_stack.ndim == 3: - self.dim1, self.dim3, self.dim2 = img_stack.shape - elif self.img_stack.ndim == 2: - self.dim3, self.dim2 = img_stack.shape - self.dim1 = 1 - self.hs_img_stack.setMaximum(self.dim1 - 1) - self.hs_img_stack.setValue(np.round(self.dim1 / 2)) - self.displayStack() - - # connections - self.hs_img_stack.valueChanged.connect(self.displayStack) - self.actionSave.triggered.connect(self.saveImageStackAsTIFF) - - def displayStack(self): - im_index = self.hs_img_stack.value() - if self.img_stack.ndim == 2: - self.image_view.setImage(self.img_stack) - else: - self.image_view.setImage(self.img_stack[im_index]) - self.label_img_count.setText(f"{im_index + 1}/{self.dim1}") - - def saveImageStackAsTIFF(self): - file_name = QFileDialog().getSaveFileName(self, "", "", "*.tiff;;*.tif") - if file_name[0]: - if self.img_stack.ndim == 3: - tf.imsave(str(file_name[0]), np.float32(self.img_stack.transpose(0, 2, 1))) - elif self.img_stack.ndim == 2: - tf.imsave(str(file_name[0]), np.float32(self.img_stack.T)) - else: - pass - - -class ComponentViewer(QtWidgets.QMainWindow): - def __init__(self, comp_stack, energy, comp_spectra, decon_spectra, decomp_map): - super(ComponentViewer, self).__init__() - - # Load the UI Page - uic.loadUi(os.path.join(ui_path, "uis/ComponentView.ui"), self) - self.centralwidget.setStyleSheet(open(os.path.join(ui_path, "css/defaultStyle.css")).read()) - - self.comp_stack = comp_stack - self.energy = energy - self.comp_spectra = comp_spectra - self.decon_spectra = decon_spectra - self.decomp_map = decomp_map - - (self.dim1, self.dim3, self.dim2) = self.comp_stack.shape - self.hs_comp_number.setMaximum(self.dim1 - 1) - - self.image_view.setImage(self.comp_stack) - self.image_view.setPredefinedGradient("viridis") - self.image_view.ui.menuBtn.hide() - self.image_view.ui.roiBtn.hide() - - self.image_view2.setImage(self.decomp_map) - self.image_view2.setPredefinedGradient("bipolar") - self.image_view2.ui.menuBtn.hide() - self.image_view2.ui.roiBtn.hide() - - # connection - self.update_image() - self.pb_show_all.clicked.connect(self.show_all_spec) - self.hs_comp_number.valueChanged.connect(self.update_image) - self.actionSave.triggered.connect(self.save_comp_data) - self.pb_openScatterPlot.clicked.connect(self.openScatterPlot) - self.pb_showMultiColor.clicked.connect(self.generateMultiColorView) - - def update_image(self): - im_index = self.hs_comp_number.value() - self.spectrum_view.setLabel("bottom", "Energy") - self.spectrum_view.setLabel("left", "Intensity", "A.U.") - self.spectrum_view.plot(self.energy, self.decon_spectra[:, im_index], clear=True) - self.component_view.setLabel("bottom", "Energy") - self.component_view.setLabel("left", "Weight", "A.U.") - self.component_view.plot(self.energy, self.comp_spectra[:, im_index], clear=True) - self.label_comp_number.setText(f"{im_index + 1}/{self.dim1}") - # self.image_view.setCurrentIndex(im_index-1) - self.image_view.setImage(self.comp_stack[im_index]) - - def openScatterPlot(self): - self.scatter_window = ComponentScatterPlot(self.comp_stack, self.comp_spectra) - - # ph = self.geometry().height() - # pw = self.geometry().width() - # px = self.geometry().x() - # py = self.geometry().y() - # dw = self.scatter_window.width() - # dh = self.scatter_window.height() - # self.scatter_window.setGeometry(px+0.65*pw, py + ph - 2*dh-5, dw, dh) - self.scatter_window.show() - - def show_all_spec(self): - self.spectrum_view.clear() - self.plt_colors = ["g", "b", "r", "c", "m", "y", "w"] * 10 - offsets = np.arange(0, 2, 0.2) - self.spectrum_view.addLegend() - for ii in range(self.decon_spectra.shape[1]): - self.spectrum_view.plot( - self.energy, - (self.decon_spectra[:, ii] / self.decon_spectra[:, ii].max()) + offsets[ii], - pen=self.plt_colors[ii], - name="component" + str(ii + 1), - ) - - def save_comp_data(self): - file_name = QFileDialog().getSaveFileName(self, "", "", "data(*tiff *tif *txt *png )") - if file_name[0]: - tf.imsave( - str(file_name[0]) + "_components.tiff", np.float32(self.comp_stack.transpose(0, 2, 1)), imagej=True - ) - tf.imsave(str(file_name[0]) + "_component_masks.tiff", np.float32(self.decomp_map.T), imagej=True) - np.savetxt(str(file_name[0]) + "_deconv_spec.txt", self.decon_spectra) - np.savetxt(str(file_name[0]) + "_component_spec.txt", self.comp_spectra) - else: - pass - - def generateMultiColorView(self): - self.multichanneldict = {} - - for n, (colorName, image) in enumerate(zip(cmap_dict.keys(), self.comp_stack.transpose(0, 1, 2))): - low, high = np.min(image), np.max(image) - self.multichanneldict[f"Image {n + 1}"] = { - "ImageName": f"Image {n + 1}", - "ImageDir": ".", - "Image": image, - "Color": colorName, - "CmapLimits": (low, high), - "Opacity": 1.0, - } - self.muli_color_window = MultiChannelWindow(image_dict=self.multichanneldict) - self.muli_color_window.show() - - # add energy column - - -class ClusterViewer(QtWidgets.QMainWindow): - def __init__(self, decon_images, energy, X_cluster, decon_spectra): - super(ClusterViewer, self).__init__() - - # Load the UI Page - uic.loadUi(os.path.join(ui_path, "uis/ClusterView.ui"), self) - self.centralwidget.setStyleSheet(open(os.path.join(ui_path, "css/defaultStyle.css")).read()) - - self.decon_images = decon_images - self.energy = energy - self.X_cluster = X_cluster - self.decon_spectra = decon_spectra - (self.dim1, self.dim3, self.dim2) = self.decon_images.shape - self.hsb_cluster_number.setMaximum(self.dim1 - 1) - self.X_cluster = X_cluster - - self.image_view.setImage(self.decon_images, autoHistogramRange=True, autoLevels=True) - self.image_view.setPredefinedGradient("viridis") - self.image_view.ui.menuBtn.hide() - self.image_view.ui.roiBtn.hide() - - self.cluster_view.setImage(self.X_cluster, autoHistogramRange=True, autoLevels=True) - self.cluster_view.setPredefinedGradient("bipolar") - self.cluster_view.ui.histogram.hide() - self.cluster_view.ui.menuBtn.hide() - self.cluster_view.ui.roiBtn.hide() - - # connection - self.update_display() - self.hsb_cluster_number.valueChanged.connect(self.update_display) - self.actionSave.triggered.connect(self.save_clust_data) - self.pb_show_all_spec.clicked.connect(self.showAllSpec) - self.pb_showMultiColor.clicked.connect(self.generateMultiColorView) - - def update_display(self): - im_index = self.hsb_cluster_number.value() - self.component_view.setLabel("bottom", "Energy") - self.component_view.setLabel("left", "Intensity", "A.U.") - self.component_view.plot(self.energy, self.decon_spectra[:, im_index], clear=True) - # self.image_view.setCurrentIndex(im_index-1) - self.image_view.setImage(self.decon_images[im_index]) - self.label_comp_number.setText(f"{im_index + 1}/{self.dim1}") - - def save_clust_data(self): - file_name = QFileDialog().getSaveFileName(self, "", "", "data(*tiff *tif *txt *png )") - if file_name[0]: - tf.imsave( - str(file_name[0]) + "_cluster.tiff", np.float32(self.decon_images.transpose(0, 2, 1)), imagej=True - ) - tf.imsave(str(file_name[0]) + "_cluster_map.tiff", np.float32(self.X_cluster.T), imagej=True) - np.savetxt(str(file_name[0]) + "_deconv_spec.txt", self.decon_spectra) - - else: - logger.error("Saving Cancelled") - self.statusbar.showMessage("Saving Cancelled") - pass - - def showAllSpec(self): - self.component_view.clear() - self.plt_colors = ["g", "b", "r", "c", "m", "y", "w"] * 10 - offsets = np.arange(0, 2, 0.2) - self.component_view.addLegend() - for ii in range(self.decon_spectra.shape[1]): - self.component_view.plot( - self.energy, - (self.decon_spectra[:, ii] / self.decon_spectra[:, ii].max()) + offsets[ii], - pen=self.plt_colors[ii], - name="cluster" + str(ii + 1), - ) - - def generateMultiColorView(self): - self.multichanneldict = {} - - for n, (colorName, image) in enumerate(zip(cmap_dict.keys(), self.decon_images.transpose(0, 1, 2))): - low, high = np.min(image), np.max(image) - self.multichanneldict[f"Image {n + 1}"] = { - "ImageName": f"Image {n + 1}", - "ImageDir": ".", - "Image": image, - "Color": colorName, - "CmapLimits": (low, high), - "Opacity": 1.0, - } - self.muli_color_window = MultiChannelWindow(image_dict=self.multichanneldict) - self.muli_color_window.show() - - -class XANESViewer(QtWidgets.QMainWindow): - def __init__(self, im_stack=None, e_list=None, refs=None, ref_names=None): - super(XANESViewer, self).__init__() - - uic.loadUi(os.path.join(ui_path, "uis/XANESViewer.ui"), self) - self.centralwidget.setStyleSheet(open(os.path.join(ui_path, "css/defaultStyle.css")).read()) - - self.im_stack = im_stack - self.e_list = e_list - self.refs = refs - self.ref_names = ref_names - self.selected = self.ref_names - self.fitResultDict = {} - self.fit_method = self.cb_xanes_fit_model.currentText() - self.alphaForLM = self.dsb_alphaForLM.value() - - self.decon_ims, self.rfactor, self.coeffs_arr = xanes_fitting( - self.im_stack, self.e_list, self.refs, method=self.fit_method, alphaForLM=self.alphaForLM - ) - - (self.dim1, self.dim2, self.dim3) = self.im_stack.shape - self.cn = int(self.dim2 // 2) - self.sz = np.max([int(self.dim2 * 0.15), int(self.dim3 * 0.15)]) - self.image_roi = pg.RectROI( - [int(self.dim3 // 2), int(self.dim2 // 2)], - [self.sz, self.sz], - pen="w", - maxBounds=QtCore.QRectF(0, 0, self.dim3, self.dim2), - ) - - self.image_roi.addTranslateHandle([0, 0], [2, 2]) - self.image_roi.addRotateHandle([0, 1], [2, 2]) - - # self.image_roi = pg.PolyLineROI([[0, 0], [0, self.sz], [self.sz, self.sz], [self.sz, 0]], - # pos=(int(self.dim2 // 2), int(self.dim3 // 2)), - # maxBounds=QtCore.QRect(0, 0, self.dim3, self.dim2), closed=True) - # self.image_roi.addTranslateHandle([self.sz // 2, self.sz // 2], [2, 2]) - - self.stack_center = int(self.dim1 // 2) - self.stack_width = int(self.dim1 * 0.05) - # self.image_view.setCurrentIndex(self.stack_center) - - self.image_view.addItem(self.image_roi) - self.xdata = self.e_list + self.sb_e_shift.value() - - self.scrollBar_setup() - self.display_image_data() - self.display_references() - self.update_spectrum() - - # connections - self.sb_e_shift.valueChanged.connect(self.update_spectrum) - self.pb_re_fit.clicked.connect(self.re_fit_xanes) - self.pb_edit_refs.clicked.connect(self.choose_refs) - self.image_roi.sigRegionChanged.connect(self.update_spectrum) - self.hsb_xanes_stk.valueChanged.connect(self.display_image_data) - self.hsb_chem_map.valueChanged.connect(self.display_image_data) - self.pb_showMultiColor.clicked.connect(self.generateMultiColorView) - self.pb_showCompSpec.clicked.connect(self.showComponentXANES) - - # menu - self.actionSave_Chem_Map.triggered.connect(self.save_chem_map) - self.actionSave_R_factor_Image.triggered.connect(self.save_rfactor_img) - self.actionSave_Live_Fit_Data.triggered.connect(self.pg_export_spec_fit) - self.actionExport_Fit_Stats.triggered.connect(self.exportFitResults) - self.actionExport_Ref_Plot.triggered.connect(self.pg_export_references) - - def scrollBar_setup(self): - self.hsb_xanes_stk.setValue(self.stack_center) - self.hsb_xanes_stk.setMaximum(self.dim1 - 1) - self.hsb_chem_map.setValue(0) - self.hsb_chem_map.setMaximum(self.decon_ims.shape[-1] - 1) - - def display_image_data(self): - self.image_view.setImage(self.im_stack[self.hsb_xanes_stk.value()]) - self.image_view.ui.menuBtn.hide() - self.image_view.ui.roiBtn.hide() - self.image_view.setPredefinedGradient("viridis") - - self.image_view_maps.setImage(self.decon_ims.transpose(2, 0, 1)[self.hsb_chem_map.value()]) - self.image_view_maps.setPredefinedGradient("bipolar") - self.image_view_maps.ui.menuBtn.hide() - self.image_view_maps.ui.roiBtn.hide() - - def display_references(self): - self.inter_ref = interploate_E(self.refs, self.xdata) - self.plt_colors = ["c", "m", "y", "w"] * 10 - self.spectrum_view_refs.addLegend() - for ii in range(self.inter_ref.shape[0]): - if len(self.selected) != 0: - self.spectrum_view_refs.plot( - self.xdata, - self.inter_ref[ii], - pen=pg.mkPen(self.plt_colors[ii], width=2), - name=self.selected[1:][ii], - ) - else: - self.spectrum_view_refs.plot( - self.xdata, - self.inter_ref[ii], - pen=pg.mkPen(self.plt_colors[ii], width=2), - name="ref" + str(ii + 1), - ) - - def choose_refs(self): - "Interactively exclude some standards from the reference file" - self.ref_edit_window = RefChooser( - self.ref_names, - self.im_stack, - self.e_list, - self.refs, - self.sb_e_shift.value(), - self.cb_xanes_fit_model.currentText(), - ) - self.ref_edit_window.show() - # self.rf_plot = pg.plot(title="RFactor Tracker") - - # connections - self.ref_edit_window.choosenRefsSignal.connect(self.update_refs) - self.ref_edit_window.fitResultsSignal.connect(self.plotFitResults) - - def update_refs(self, list_): - self.selected = list_ # list_ is the signal from ref chooser - self.update_spectrum() - self.re_fit_xanes() - - def update_spectrum(self): - self.roi_img = self.image_roi.getArrayRegion(self.im_stack, self.image_view.imageItem, axes=(1, 2)) - sizex, sizey = self.roi_img.shape[1], self.roi_img.shape[2] - posx, posy = self.image_roi.pos() - self.roi_info.setText(f"ROI_Pos: {int(posx)},{int(posy)} ROI_Size: {sizex},{sizey}") - - self.xdata1 = self.e_list + self.sb_e_shift.value() - self.ydata1 = get_sum_spectra(self.roi_img) - self.fit_method = self.cb_xanes_fit_model.currentText() - - if len(self.selected) != 0: - self.inter_ref = interploate_E(self.refs[self.selected], self.xdata1) - stats, coeffs = xanes_fitting_1D( - self.ydata1, - self.xdata1, - self.refs[self.selected], - method=self.fit_method, - alphaForLM=self.alphaForLM, - ) - - else: - self.inter_ref = interploate_E(self.refs, self.xdata1) - stats, coeffs = xanes_fitting_1D( - self.ydata1, self.xdata1, self.refs, method=self.fit_method, alphaForLM=self.alphaForLM - ) - - self.fit_ = np.dot(coeffs, self.inter_ref) - pen = pg.mkPen("g", width=1.5) - pen2 = pg.mkPen("r", width=1.5) - # pen3 = pg.mkPen("y", width=1.5) - self.spectrum_view.addLegend() - self.spectrum_view.setLabel("bottom", "Energy") - self.spectrum_view.setLabel("left", "Intensity", "A.U.") - self.spectrum_view.plot(self.xdata1, self.ydata1, pen=pen, name="Data", clear=True) - self.spectrum_view.plot(self.xdata1, self.fit_, name="Fit", pen=pen2) - - for n, (coff, ref, plt_clr) in enumerate(zip(coeffs, self.inter_ref, self.plt_colors)): - if len(self.selected) != 0: - self.spectrum_view.plot(self.xdata1, np.dot(coff, ref), name=self.selected[1:][n], pen=plt_clr) - else: - self.spectrum_view.plot(self.xdata1, np.dot(coff, ref), name="ref" + str(n + 1), pen=plt_clr) - # set the rfactor value to the line edit slot - self.results = ( - f"Coefficients: {coeffs} \n" - f"R-Factor: {stats['R_Factor']}, R-Square: {stats['R_Square']},\n " - f"Chi-Square: {stats['Chi_Square']}, " - f"Reduced Chi-Square: {stats['Reduced Chi_Square']}" - ) - - self.fit_results.setText(self.results) - - def re_fit_xanes(self): - if len(self.selected) != 0: - self.decon_ims, self.rfactor, self.coeffs_arr = xanes_fitting( - self.im_stack, - self.e_list + self.sb_e_shift.value(), - self.refs[self.selected], - method=self.cb_xanes_fit_model.currentText(), - alphaForLM=self.alphaForLM, - ) - else: - # if non athena file with no header is loaded no ref file cannot be edited - self.decon_ims, self.rfactor, self.coeffs_arr = xanes_fitting( - self.im_stack, - self.e_list + self.sb_e_shift.value(), - self.refs, - method=self.cb_xanes_fit_model.currentText(), - alphaForLM=self.alphaForLM, - ) - - # rfactor is a list of all spectra so take the mean - self.rfactor_mean = np.mean(self.rfactor) - self.image_view_maps.setImage(self.decon_ims.transpose(2, 0, 1)) - self.scrollBar_setup() - - def plotFitResults(self, decon_ims, rfactor_mean, coeff_array): - # upadte the chem maps and scrollbar params - self.image_view_maps.setImage(decon_ims.transpose(2, 0, 1)) - # self.hsb_chem_map.setValue(0) - # self.hsb_chem_map.setMaximum(decon_ims.shape[-1]-1) - - # set the rfactor value to the line edit slot - self.le_r_sq.setText(f"{rfactor_mean :.4f}") - - def showComponentXANES(self): - compNum = self.hsb_chem_map.value() - currentComp = self.decon_ims.transpose(2, 0, 1)[compNum] - currentCompMask = currentComp > 0 - yData = applyMaskGetMeanSpectrum(self.im_stack, currentCompMask) - xanes_comp_plot = pg.plot( - self.e_list + self.sb_e_shift.value(), - yData, - title=f"Component_{compNum}", - pen=pg.mkPen("y", width=2, style=QtCore.Qt.DotLine), - symbol="o", - ) - xanes_comp_plot.setLabel("bottom", "Energy (keV)") - xanes_comp_plot.setLabel("left", "Intensity") - - def generateMultiColorView(self): - self.multichanneldict = {} - - for n, (colorName, image) in enumerate(zip(cmap_dict.keys(), self.decon_ims.transpose((2, 0, 1)))): - low, high = np.min(image), np.max(image) - self.multichanneldict[f"Image {n + 1}"] = { - "ImageName": f"Image {n + 1}", - "ImageDir": ".", - "Image": image, - "Color": colorName, - "CmapLimits": (low, high), - "Opacity": 1.0, - } - self.muli_color_window = MultiChannelWindow(image_dict=self.multichanneldict) - self.muli_color_window.show() - - def save_chem_map(self): - file_name = QFileDialog().getSaveFileName(self, "save image", "chemical_map.tiff", "image data (*tiff)") - if file_name[0]: - tf.imsave(str(file_name[0]), np.float32(self.decon_ims.transpose(2, 0, 1)), imagej=True) - else: - logger.error("No file to save") - pass - - def save_rfactor_img(self): - file_name = QFileDialog().getSaveFileName(self, "save image", "r-factor_map.tiff", "image data (*tiff)") - if file_name[0]: - tf.imsave(str(file_name[0]), np.float32(self.rfactor), imagej=True) - else: - logger.error("No file to save") - pass - - def save_spec_fit(self): - try: - to_save = np.column_stack([self.xdata1, self.ydata1, self.fit_]) - file_name = QFileDialog().getSaveFileName(self, "save spectrum", "", "spectrum and fit (*txt)") - if file_name[0]: - np.savetxt(str(file_name[0]) + ".txt", to_save) - else: - pass - except Exception: - logger.error("No file to save") - pass - - def pg_export_spec_fit(self): - exporter = pg.exporters.CSVExporter(self.spectrum_view.plotItem) - exporter.parameters()["columnMode"] = "(x,y,y,y) for all plots" - file_name = QFileDialog().getSaveFileName(self, "save spectrum", "", "spectrum and fit (*csv)") - if file_name[0]: - exporter.export(str(file_name[0]) + ".csv") - else: - pass - - def pg_export_references(self): - exporter = pg.exporters.CSVExporter(self.spectrum_view_refs.plotItem) - exporter.parameters()["columnMode"] = "(x,y,y,y) for all plots" - file_name = QFileDialog().getSaveFileName( - self, "save references", "xanes_references.csv", "column data (*csv)" - ) - if file_name[0]: - exporter.export(str(file_name[0])) - else: - pass - - def exportFitResults(self): - file_name = QFileDialog().getSaveFileName(self, "save txt", "xanes_1D_fit_results.txt", "txt data (*txt)") - if file_name[0]: - with open(file_name[0], "w") as file: - file.write(self.results) - else: - pass - - -class RefChooser(QtWidgets.QMainWindow): - choosenRefsSignal: pyqtSignal = QtCore.pyqtSignal(list) - fitResultsSignal: pyqtSignal = QtCore.pyqtSignal(np.ndarray, float, np.ndarray) - - def __init__(self, ref_names, im_stack, e_list, refs, e_shift, fit_model): - super(RefChooser, self).__init__() - uic.loadUi(os.path.join(ui_path, "uis/RefChooser.ui"), self) - self.centralwidget.setStyleSheet(open(os.path.join(ui_path, "css/defaultStyle.css")).read()) - self.ref_names = ref_names - self.refs = refs - self.im_stack = im_stack - self.e_list = e_list - self.e_shift = e_shift - self.fit_model = fit_model - - self.all_boxes = [] - self.rFactorList = [] - - self.displayCombinations() - - # selection become more apparent than default with red-ish color - self.tableWidget.setStyleSheet("background-color: white; selection-background-color: rgb(200,0,0);") - - # add a line to the plot to walk through the table. Note that the table is not sorted - self.selectionLine = pg.InfiniteLine( - pos=1, angle=90, pen=pg.mkPen("m", width=2.5), movable=True, bounds=None, label="Move Me!" - ) - self.stat_view.setLabel("bottom", "Fit ID") - self.stat_view.setLabel("left", "Reduced Chi^2") - - for n, i in enumerate(self.ref_names): - self.cb_i = QtWidgets.QCheckBox(self.ref_box_frame) - if n == 0: - self.cb_i.setChecked(True) - self.cb_i.setEnabled(False) - self.cb_i.setObjectName(i) - self.cb_i.setText(i) - self.gridLayout_2.addWidget(self.cb_i, n, 0, 1, 1) - self.cb_i.toggled.connect(self.enableApply) - self.all_boxes.append(self.cb_i) - - # connections - self.pb_apply.clicked.connect(self.clickedWhichAre) - self.pb_combo.clicked.connect(self.tryAllCombo) - self.actionExport_Results_csv.triggered.connect(self.exportFitResults) - self.selectionLine.sigPositionChanged.connect(self.updateFitWithLine) - self.tableWidget.itemSelectionChanged.connect(self.updateWithTableSelection) - # self.stat_view.scene().sigMouseClicked.connect(self.moveSelectionLine) - self.stat_view.mouseDoubleClickEvent = self.moveSelectionLine - self.sb_max_combo.valueChanged.connect(self.displayCombinations) - # self.pb_sort_with_r.clicked.connect(lambda: self.tableWidget.sortItems(3, QtCore.Qt.AscendingOrder)) - self.pb_sort_with_r.clicked.connect(self.sortTable) - self.cb_sorter.currentTextChanged.connect(self.sortTable) - - # def clickedWhich(self): - # button_name = self.sender() - - def populateChecked(self): - self.onlyCheckedBoxes = [] - for names in self.all_boxes: - if names.isChecked(): - self.onlyCheckedBoxes.append(names.objectName()) - - QtCore.pyqtSlot() - - def clickedWhichAre(self): - self.populateChecked() - self.choosenRefsSignal.emit(self.onlyCheckedBoxes) - - def generateRefList(self, ref_list, maxCombo, minCombo=1): - """ - Creates a list of reference combinations for xanes fitting - - Paramaters; - - ref_list (list): list of ref names from the header - maxCombo (int): maximum number of ref lists in combination - minCombo (int): min number of ref lists in combination - - returns; - - 1. int: length of total number of combinations - 2. list: all the combinations - - """ - - if not maxCombo > len(ref_list): - iter_list = [] - while minCombo < maxCombo + 1: - iter_list += list(combinations(ref_list, minCombo)) - minCombo += 1 - return len(iter_list), iter_list - - else: - raise ValueError(" Maximum numbinations cannot be larger than number of list items") - - def displayCombinations(self): - niter, self.iter_list = self.generateRefList(self.ref_names[1:], self.sb_max_combo.value()) - self.label_nComb.setText(str(niter) + " Combinations") - - @QtCore.pyqtSlot() - def tryAllCombo(self): - # empty list to to keep track and plot of reduced chi2 of all the fits - self.rfactor_list = [] - - # create dataframe for the table - self.df = pd.DataFrame( - columns=["Fit Number", "References", "Coefficients", "R-Factor", "R^2", "chi^2", "red-chi^2", "Score"] - ) - - # df columns is the header for the table widget - self.tableWidget.setHorizontalHeaderLabels(self.df.columns) - # self.iter_list = list(combinations(self.ref_names[1:],self.sb_max_combo.value())) - - niter, self.iter_list = self.generateRefList(self.ref_names[1:], self.sb_max_combo.value()) - tot_combo = len(self.iter_list) - for n, refs in enumerate(self.iter_list): - self.statusbar.showMessage(f"{n + 1}/{tot_combo}") - selectedRefs = list((str(self.ref_names[0]),) + refs) - self.fit_combo_progress.setValue((n + 1) * 100 / tot_combo) - self.stat, self.coeffs_arr = xanes_fitting_Binned( - self.im_stack, self.e_list + self.e_shift, self.refs[selectedRefs], method=self.fit_model - ) - - self.rfactor_list.append(self.stat["Reduced Chi_Square"]) - self.stat_view.plot( - x=np.arange(n + 1), - y=self.rfactor_list, - clear=True, - title="Reduced Chi^2", - pen=pg.mkPen("y", width=2, style=QtCore.Qt.DotLine), - symbol="o", - ) - - # arbitary number to rank the best fit - fit_score = (self.stat["R_Square"] + np.sum(self.coeffs_arr)) / ( - self.stat["R_Factor"] + self.stat["Reduced Chi_Square"] - ) - - resultsDict = { - "Fit Number": n, - "References": str(selectedRefs[1:]), - "Coefficients": str(np.around(self.coeffs_arr, 4)), - "Sum of Coefficients": str(np.around(np.sum(self.coeffs_arr), 4)), - "R-Factor": self.stat["R_Factor"], - "R^2": self.stat["R_Square"], - "chi^2": self.stat["Chi_Square"], - "red-chi^2": self.stat["Reduced Chi_Square"], - "Score": np.around(fit_score, 4), - } - - self.df = pd.concat([self.df, pd.DataFrame([resultsDict])], ignore_index=True) - - self.dataFrametoQTable(self.df) - QtTest.QTest.qWait(0.1) # hepls with real time plotting - - self.stat_view.addItem(self.selectionLine) - - def dataFrametoQTable(self, df_: pd.DataFrame): - nRows = len(df_.index) - nColumns = len(df_.columns) - self.tableWidget.setRowCount(nRows) - self.tableWidget.setColumnCount(nColumns) - self.tableWidget.setHorizontalHeaderLabels(df_.columns) - - for i in range(nRows): - for j in range(nColumns): - cell = QtWidgets.QTableWidgetItem(str(df_.values[i][j])) - self.tableWidget.setItem(i, j, cell) - - # set the property of the table view. Size policy to make the contents justified - self.tableWidget.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents) - self.tableWidget.resizeColumnsToContents() - - def exportFitResults(self): - file_name = QFileDialog().getSaveFileName(self, "save csv", "xanes_fit_results_log.csv", "txt data (*csv)") - if file_name[0]: - with open(str(file_name[0]), "w") as fp: - self.df.to_csv(fp) - else: - pass - - def selectTableAndCheckBox(self, x): - nSelection = int(round(x)) - self.tableWidget.selectRow(nSelection) - fit_num = int(self.tableWidget.item(nSelection, 0).text()) - refs_selected = self.iter_list[fit_num] - - # reset all the checkboxes to uncheck state, except the energy - for checkstate in self.findChildren(QtWidgets.QCheckBox): - if checkstate.isEnabled(): - checkstate.setChecked(False) - - for cb_names in refs_selected: - checkbox = self.findChild(QtWidgets.QCheckBox, name=cb_names) - checkbox.setChecked(True) - - def updateFitWithLine(self): - pos_x, pos_y = self.selectionLine.pos() - x = self.df.index[self.df[str("Fit Number")] == np.round(pos_x)][0] - self.selectTableAndCheckBox(x) - - def updateWithTableSelection(self): - x = self.tableWidget.currentRow() - self.selectTableAndCheckBox(x) - - def moveSelectionLine(self, event): - if event.button() == QtCore.Qt.LeftButton: - Pos = self.stat_view.plotItem.vb.mapSceneToView(event.pos()) - self.selectionLine.setPos(Pos.x()) - - def sortTable(self): - sorter_dict = { - "R-Factor": "R-Factor", - "R-Square": "R^2", - "Chi-Square": "chi^2", - "Reduced Chi-Square": "red-chi^2", - "Fit Number": "Fit Number", - } - sorter = sorter_dict[self.cb_sorter.currentText()] - self.df = self.df.sort_values(sorter, ignore_index=True) - self.dataFrametoQTable(self.df) - - def enableApply(self): - """ """ - self.populateChecked() - if len(self.onlyCheckedBoxes) > 1: - self.pb_apply.setEnabled(True) - else: - self.pb_apply.setEnabled(False) - - -class ScatterPlot(QtWidgets.QMainWindow): - def __init__(self, img1, img2, nameTuple): - super(ScatterPlot, self).__init__() - - uic.loadUi(os.path.join(ui_path, "uis/ScatterView.ui"), self) - self.centralwidget.setStyleSheet(open(os.path.join(ui_path, "css/defaultStyle.css")).read()) - self.clearPgPlot() - self.w1 = self.scatterViewer.addPlot() - self.img1 = img1 - self.img2 = img2 - self.nameTuple = nameTuple - x, y = np.shape(self.img1) - self.s1 = pg.ScatterPlotItem(size=2, pen=pg.mkPen(None), brush=pg.mkBrush(255, 255, 0, 255)) - # print(self.s1) - - # create three polyline ROIs for masking - Xsize = self.img1.max() / 6 - Ysize = self.img2.max() / 6 - - self.scatter_mask = pg.PolyLineROI( - [[0, 0], [0, Ysize], [Xsize / 2, Ysize * 1.5], [Xsize, Ysize], [Xsize, 0]], - pos=None, - pen=pg.mkPen("r", width=2), - hoverPen=pg.mkPen("w", width=2), - closed=True, - removable=True, - ) - - self.scatter_mask2 = pg.PolyLineROI( - [ - [Xsize * 1.2, 0], - [Xsize * 1.2, Ysize * 2], - [Xsize * 2, Ysize * 2], - [Xsize * 3, Ysize], - [Xsize * 2, 0], - ], - pos=None, - pen=pg.mkPen("g", width=2), - hoverPen=pg.mkPen("w", width=2), - closed=True, - removable=True, - ) - self.scatter_mask3 = pg.PolyLineROI( - [ - [Xsize * 2.5, 0], - [Xsize * 2.5, Ysize], - [Xsize * 4, Ysize], - [Xsize * 4, 0], - [Xsize * 3.7, Ysize * -0.5], - ], - pos=None, - pen=pg.mkPen("c", width=2), - hoverPen=pg.mkPen("w", width=2), - closed=True, - removable=True, - ) - - self.fitScatter = self.fitScatter2 = self.fitScatter3 = None - - self.rois = { - "ROI 1": (self.scatter_mask, self.rb_roi1.isChecked(), self.fitScatter), - "ROI 2": (self.scatter_mask2, self.rb_roi2.isChecked(), self.fitScatter2), - "ROI 3": (self.scatter_mask3, self.rb_roi3.isChecked(), self.fitScatter3), - } - - self.windowNames = {"ROI 1": self.fitScatter, "ROI 2": self.fitScatter2, "ROI 3": self.fitScatter3} - - self.s1.setData(self.img1.flatten(), self.img2.flatten()) - self.w1.setLabel("bottom", self.nameTuple[0], "counts") - self.label_img1.setText(self.nameTuple[0]) - self.w1.setLabel("left", self.nameTuple[1], "counts") - self.label_img2.setText(self.nameTuple[1]) - self.w1.addItem(self.s1) - - self.image_view.setImage(self.img1) - self.image_view.ui.menuBtn.hide() - self.image_view.ui.roiBtn.hide() - self.image_view.setPredefinedGradient("thermal") - - self.image_view2.setImage(self.img2) - self.image_view2.ui.menuBtn.hide() - self.image_view2.ui.roiBtn.hide() - self.image_view2.setPredefinedGradient("thermal") - - # connections - self.actionSave_Plot.triggered.connect(self.pg_export_correlation) - self.actionSave_Images.triggered.connect(self.tiff_export_images) - # self.pb_define_mask.clicked.connect(lambda:self.createMask(self.scatter_mask)) - self.pb_define_mask.clicked.connect(self.addMultipleROIs) - # self.pb_apply_mask.clicked.connect(lambda:self.getMaskRegion(self.scatter_mask)) - self.pb_apply_mask.clicked.connect(self.applyMultipleROIs) - self.pb_clear_mask.clicked.connect(self.clearMultipleROIs) - self.pb_compositeScatter.clicked.connect(self.createCompositeScatter) - [rbs.clicked.connect(self.updateROIDict) for rbs in [self.rb_roi1, self.rb_roi2, self.rb_roi3]] - - def pg_export_correlation(self): - exporter = pg.exporters.CSVExporter(self.w1) - exporter.parameters()["columnMode"] = "(x,y,y,y) for all plots" - file_name = QFileDialog().getSaveFileName(self, "save correlation", "", "spectrum and fit (*csv)") - if file_name[0]: - exporter.export(str(file_name[0]) + ".csv") - self.statusbar.showMessage(f"Data saved to {str(file_name[0])}") - else: - pass - - def tiff_export_images(self): - file_name = QFileDialog().getSaveFileName(self, "save images", "", "spectrum and fit (*tiff)") - if file_name[0]: - tf.imsave(str(file_name[0]) + ".tiff", np.dstack([self.img1, self.img2]).T) - self.statusbar.showMessage(f"Images saved to {str(file_name[0])}") - else: - pass - - def createMask(self, ROIName): - try: - self.w1.removeItem(ROIName) - except Exception: - pass - self.w1.addItem(ROIName) - - def clearMask(self, ROIName): - self.w1.removeItem(ROIName) - - def clearPgPlot(self): - try: - self.masked_img.close() - except Exception: - pass - - def getMaskRegion(self, ROIName, generateSeperateWindows=True): - """filter scatterplot points using polylineROI region""" - - # Ref : https://stackoverflow.com/questions/57719303/how-to-map-mouse-position-on-a-scatterplot - - # get the roi region:QPaintPathObject - roiShape = self.rois[ROIName][0].mapToItem(self.s1, self.rois[ROIName][0].shape()) - - # get data in the scatter plot - scatterData = np.array(self.s1.getData()) - - # generate a binary mask for points inside or outside the roishape - selected = [roiShape.contains(QtCore.QPointF(pt[0], pt[1])) for pt in scatterData.T] - - # reshape the mask to image dimensions - self.mask2D = np.reshape(selected, (self.img1.shape)) - - # get masked image1 - self.maskedImage = self.mask2D * self.img1 - - # get rid of the (0,0) values in the masked array - self.xData, self.yData = np.compress(selected, scatterData[0]), np.compress(selected, scatterData[1]) - - # linear regeression of the filtered X,Y data - result = linregress(self.xData, self.yData) - - # Pearson's correlation of the filtered X,Y data - pr, pp = stats.pearsonr(self.xData, self.yData) - - # apply the solved equation to xData to generate the fit line - self.yyData = result.intercept + result.slope * self.xData - - # Prepare strings for fit results and stats - self.fitLineEqn = ( - f" y = x*{result.slope :.3e} + {result.intercept :.3e}, " - "R^2 = {result.rvalue**2 :.3f}, r = {pr :.3f}\n" - ) - FitStats1 = f" Slope Error = {result.stderr :.3e}, Intercept Error = {result.intercept_stderr :.3e}\n" - FitStats2 = f" Pearson’s correlation coefficient = {pr :.3f}" - refs = "\n\n ***References****\n\n scipy.stats.linregress, scipy.stats.pearsonr " - fitStats = ( - f"\n ***{ROIName} Fit Results***\n\n" + " Equation: " + self.fitLineEqn + FitStats1 + FitStats2 + refs - ) - - # generate new window to plot the results - - if generateSeperateWindows: - self.windowNames[ROIName] = MaskedScatterPlotFit( - [self.xData, self.yData], - [self.xData, self.yyData], - self.mask2D, - self.maskedImage, - fitStats, - self.fitLineEqn, - self.nameTuple, - ) - self.windowNames[ROIName].show() - - """ - from scipy.linalg import lstsq - M = xData[:, np.newaxis]**[0, 1] #use >1 for polynomial fits - p, res, rnk, s = lstsq(M, yData) - yyData = p[0] + p[1]*xData - """ - - def updateROIDict(self): - self.rois = { - "ROI 1": (self.scatter_mask, self.rb_roi1.isChecked()), - "ROI 2": (self.scatter_mask2, self.rb_roi2.isChecked()), - "ROI 3": (self.scatter_mask3, self.rb_roi3.isChecked()), - } - - def applyMultipleROIs(self): - with pg.BusyCursor(): - self.updateROIDict() - for key in self.rois.keys(): - if self.rois[key][1]: - self.getMaskRegion(key) - else: - pass - - def addMultipleROIs(self): - self.updateROIDict() - for key in self.rois.keys(): - if self.rois[key][1]: - self.createMask(self.rois[key][0]) - else: - self.clearMask(self.rois[key][0]) - - def clearMultipleROIs(self): - self.updateROIDict() - for key in self.rois.keys(): - if not self.rois[key][1]: - self.clearMask(self.rois[key][0]) - else: - pass - - def createCompositeScatter(self): - points = [] - fitLine = [] - masks = [] - roiFitEqn = {} - - self.updateROIDict() - for n, key in enumerate(self.rois.keys()): - if self.rois[key][1]: - self.getMaskRegion(key, generateSeperateWindows=False) - points.append(np.column_stack([self.xData, self.yData])) - fitLine.append(np.column_stack([self.xData, self.yyData])) - masks.append(self.mask2D) - roiFitEqn[key] = self.fitLineEqn - else: - pass - - logger.info(f" fitline shape: {np.shape(fitLine)}") - logger.info(f" points shape: {np.shape(points)}") - logger.info(f" maks shape: {np.shape(masks)}") - self.compositeScatterWindow = CompositeScatterPlot( - np.array(points), np.array(fitLine), np.array(masks), roiFitEqn, self.nameTuple - ) - self.compositeScatterWindow.show() - - def _createCompositeScatter(self): - self.scatterColors = ["w", "c", "y", "k", "m"] - points = [] - fitLine = [] - - self.updateROIDict() - for n, key in enumerate(self.rois.keys()): - if self.rois[key][1]: - self.getMaskRegion(key, generateSeperateWindows=False) - - for x, y, yy in zip(self.xData, self.yData, self.yyData): - points.append( - { - "pos": (x, y), - "data": "id", - "size": 3, - "pen": pg.mkPen(None), - "brush": self.scatterColors[n], - } - ) - fitLine.extend(np.column_stack((self.xData, self.yyData))) - else: - pass - - logger.info(f" fitline shape: {np.shape(fitLine)}") - self.compositeScatterWindow = CompositeScatterPlot(points, np.array(fitLine)) - self.compositeScatterWindow.show() - - def getROIParams(self): - print(np.array(self.scatter_mask.getSceneHandlePositions())) - - -class MaskedScatterPlotFit(QtWidgets.QMainWindow): - def __init__(self, scatterData, fitData, mask, maskedImage, fitString, fitEquation, nameTuple): - super(MaskedScatterPlotFit, self).__init__() - - uic.loadUi(os.path.join(ui_path, "uis/maskedScatterPlotFit.ui"), self) - self.centralwidget.setStyleSheet(open(os.path.join(ui_path, "css/defaultStyle.css")).read()) - self.scatterData = scatterData - self.fitData = fitData - self.mask = mask - self.maskedImage = maskedImage - self.fitString = fitString - self.fitEquation = fitEquation - self.nameTuple = nameTuple - - # set the graphicslayoutwidget in the ui as canvas - self.canvas = self.scatterViewer.addPlot() - self.canvas.addLegend() - self.canvas.setLabel("bottom", self.nameTuple[0], "counts") - self.canvas.setLabel("left", self.nameTuple[1], "counts") - self.gb_maskedImage1.setTitle(f" Masked {self.nameTuple[0]}") - - # generate a scatter plot item - self.scattered = pg.ScatterPlotItem(size=3.5, pen=pg.mkPen(None), brush=pg.mkBrush(5, 214, 255, 200)) - - # set scatter plot data - self.scattered.setData(scatterData[0], scatterData[1], name="Data") - - # set z value negative to show scatter data behind the fit line - self.scattered.setZValue(-10) - - # add scatter plot to the canvas - self.canvas.addItem(self.scattered) - - # generate plotitem for fit line - self.fitLinePlot = pg.PlotDataItem(pen=pg.mkPen(pg.mkColor(220, 20, 60), width=3.3)) - - # set line plot data - self.fitLinePlot.setData(fitData[0], fitData[1], name="Linear Fit") - - # add line plot to the canvas - self.canvas.addItem(self.fitLinePlot) - - # display Mask - self.imageView_mask.setImage(self.mask) - self.imageView_mask.ui.menuBtn.hide() - self.imageView_mask.ui.roiBtn.hide() - self.imageView_mask.setPredefinedGradient("plasma") - - # display masked Image - self.imageView_maskedImage.setImage(self.maskedImage) - self.imageView_maskedImage.ui.menuBtn.hide() - self.imageView_maskedImage.ui.roiBtn.hide() - self.imageView_maskedImage.setPredefinedGradient("viridis") - - # display Fit stats - self.text_fit_results.setPlainText(fitString) - self.canvas.setTitle(self.fitEquation, color="r") - - # connections - self.pb_copy_results.clicked.connect(self.copyFitResults) - self.pb_save_results.clicked.connect(self.saveFitResults) - self.actionSave_Plot.triggered.connect(self.pg_export_correlation) - self.actionSaveMask.triggered.connect(self.saveMask) - self.actionSaveMaskedImage.triggered.connect(self.saveImage) - - def saveFitResults(self): - S__File = QFileDialog.getSaveFileName(self, "save txt", "correlationPlotFit.txt", "txt data (*txt)") - - Text = self.text_fit_results.toPlainText() - if S__File[0]: - with open(S__File[0], "w") as file: - file.write(Text) - - def copyFitResults(self): - self.text_fit_results.selectAll() - self.text_fit_results.copy() - self.statusbar.showMessage("text copied to clipboard") - - def pg_export_correlation(self): - exporter = pg.exporters.CSVExporter(self.canvas) - exporter.parameters()["columnMode"] = "(x,y,y,y) for all plots" - file_name = QFileDialog().getSaveFileName( - self, "save correlation", "scatterData.csv", "spectrum and fit (*csv)" - ) - if file_name[0]: - exporter.export(str(file_name[0])) - self.statusbar.showMessage(f"Data saved to {str(file_name[0])}") - else: - pass - - def saveImage(self): - file_name = QFileDialog().getSaveFileName(self, "Save image data", "image.tiff", "image file(*tiff *tif )") - if file_name[0]: - tf.imsave(str(file_name[0]), self.maskedImage) - self.statusbar.showMessage(f"Data saved to {str(file_name[0])}") - else: - self.statusbar.showMessage("Saving cancelled") - pass - - def saveMask(self): - file_name = QFileDialog().getSaveFileName(self, "Save image data", "mask.tiff", "image file(*tiff *tif )") - if file_name[0]: - tf.imsave(str(file_name[0]), self.mask) - self.statusbar.showMessage(f"Data saved to {str(file_name[0])}") - else: - self.statusbar.showMessage("Saving cancelled") - pass - - -class ComponentScatterPlot(QtWidgets.QMainWindow): - def __init__(self, decomp_stack, specs): - super(ComponentScatterPlot, self).__init__() - - uic.loadUi(os.path.join(ui_path, "uis/ComponentScatterPlot.ui"), self) - self.centralwidget.setStyleSheet(open(os.path.join(ui_path, "css/defaultStyle.css")).read()) - self.w1 = self.scatterViewer.addPlot() - self.decomp_stack = decomp_stack - self.specs = specs - (self.dim1, self.dim3, self.dim2) = self.decomp_stack.shape - # fill the combonbox depending in the number of components for scatter plot - for n, combs in enumerate(combinations(np.arange(self.dim1), 2)): - self.cb_scatter_comp.addItem(str(combs)) - self.cb_scatter_comp.setItemData(n, combs) - - self.s1 = pg.ScatterPlotItem(size=3, pen=pg.mkPen(None), brush=pg.mkBrush(255, 255, 0, 120)) - - self.setImageAndScatterPlot() - # connections - self.actionSave_Plot.triggered.connect(self.pg_export_correlation) - self.actionSave_Images.triggered.connect(self.tiff_export_images) - self.pb_updateComponents.clicked.connect(self.setImageAndScatterPlot) - self.pb_define_mask.clicked.connect(self.createMask) - self.pb_apply_mask.clicked.connect(self.getMaskRegion) - self.pb_reset_mask.clicked.connect(self.resetMask) - self.pb_addALine.clicked.connect(lambda: self.createMask(Line=True)) - - def setImageAndScatterPlot(self): - try: - self.s1.clear() - except Exception: - pass - - comp_tuple = self.cb_scatter_comp.currentData() - self.img1, self.img2 = self.decomp_stack[comp_tuple[0]], self.decomp_stack[comp_tuple[-1]] - self.image_view.setImage(self.decomp_stack[comp_tuple[0]]) - self.image_view.ui.menuBtn.hide() - self.image_view.ui.roiBtn.hide() - self.image_view.setPredefinedGradient("bipolar") - - self.image_view2.setImage(self.decomp_stack[comp_tuple[-1]]) - self.image_view2.ui.menuBtn.hide() - self.image_view2.ui.roiBtn.hide() - self.image_view2.setPredefinedGradient("bipolar") - - points = [] - for i, j in zip(self.img1.flatten(), self.img2.flatten()): - points.append( - { - "pos": (i, j), - "data": "id", - "size": 5, - "pen": pg.mkPen(None), - "brush": pg.mkBrush(255, 255, 0, 160), - } - ) - - self.s1.addPoints(points) - self.w1.addItem(self.s1) - # self.s1.setData(self.specs[:, comp_tuple[0]], self.specs[:, comp_tuple[-1]]) - self.w1.setLabel("bottom", f"PC{comp_tuple[0]+1}") - self.w1.setLabel("left", f"PC{comp_tuple[-1]+1}") - self.label_im1.setText(f"PC{comp_tuple[0]+1}") - self.label_im2.setText(f"PC{comp_tuple[-1]+1}") - - def createMask(self, Line=False): - self.size = self.img1.max() / 10 - self.pos = int(self.img1.mean()) - - if Line: - self.lineROI = pg.LineSegmentROI( - [0, 1], - pos=(self.pos, self.pos), - pen=pg.mkPen("r", width=4), - hoverPen=pg.mkPen("g", width=4), - removable=True, - ) - self.w1.addItem(self.lineROI) - - else: - self.scatter_mask = pg.PolyLineROI( - [[0, 0], [0, self.size], [self.size, self.size], [self.size, 0]], - pos=(self.pos, self.pos), - pen=pg.mkPen("r", width=4), - hoverPen=pg.mkPen("g", width=4), - closed=True, - removable=True, - ) - - self.w1.addItem(self.scatter_mask) - - def resetMask(self): - self.clearMask() - self.createMask() - - def clearMask(self): - try: - self.w1.removeItem(self.scatter_mask) - except AttributeError: - pass - - def clearPgPlot(self): - try: - self.masked_img.close() - except Exception: - pass - - def getMaskRegion(self): - # Ref : https://stackoverflow.com/questions/57719303/how-to-map-mouse-position-on-a-scatterplot - - roiShape = self.scatter_mask.mapToItem(self.s1, self.scatter_mask.shape()) - self._points = list() - logger.info("Building Scatter Plot Window; Please wait..") - for i in range(len(self.img1.flatten())): - self._points.append(QtCore.QPointF(self.img1.flatten()[i], self.img2.flatten()[i])) - - selected = [roiShape.contains(pt) for pt in self._points] - img_selected = np.reshape(selected, (self.img1.shape)) - - self.masked_img = singleStackViewer(img_selected * self.img1, gradient="bipolar") - self.masked_img.show() - - def pg_export_correlation(self): - exporter = pg.exporters.CSVExporter(self.w1) - exporter.parameters()["columnMode"] = "(x,y,y,y) for all plots" - file_name = QFileDialog().getSaveFileName(self, "save correlation", "", "spectrum and fit (*csv)") - if file_name[0]: - exporter.export(str(file_name[0]) + ".csv") - self.statusbar.showMessage(f"Data saved to {str(file_name[0])}") - else: - pass - - def tiff_export_images(self): - file_name = QFileDialog().getSaveFileName(self, "save images", "", "spectrum and fit (*tiff)") - if file_name[0]: - tf.imsave(str(file_name[0]) + ".tiff", np.dstack([self.img1, self.img2]).T) - self.statusbar.showMessage(f"Images saved to {str(file_name[0])}") - else: - pass - - -class LoadingScreen(QtWidgets.QSplashScreen): - def __init__(self): - super(LoadingScreen, self).__init__() - uic.loadUi(os.path.join(ui_path, "uis/animationWindow.ui"), self) - self.setWindowOpacity(0.65) - self.movie = QMovie("uis/animation.gif") - self.label.setMovie(self.movie) - - def mousePressEvent(self, event): - # disable default "click-to-dismiss" behaviour - pass - - def startAnimation(self): - self.movie.start() - self.show() - - def stopAnimation(self): - self.movie.stop() - self.hide() - - -class CompositeScatterPlot(QtWidgets.QMainWindow): - def __init__(self, scatterPoints, fitLine, maskImages, fitEquations, nameTuple): - super(CompositeScatterPlot, self).__init__() - - uic.loadUi(os.path.join(ui_path, "uis/multipleScatterFit.ui"), self) - self.centralwidget.setStyleSheet(open(os.path.join(ui_path, "css/defaultStyle.css")).read()) - - self.scatterPoints = scatterPoints - self.fitLine = fitLine - self.scatterColors = ["r", (0, 115, 0), (4, 186, 186), "c", "w", "k"] - self.fitColors = ["b", "r", "m", "k", "b"] - self.roiNames = list(fitEquations.keys()) - self.fitEqns = list(fitEquations.values()) - self.nameTuple = nameTuple - self.maskImages = maskImages - - # self.scatterViewer.setBackground('w') - # set the graphicslayoutwidget in the ui as canvas - self.canvas = self.scatterViewer.addPlot() - self.canvas.addLegend() - self.canvas.setLabel("bottom", self.nameTuple[0], "counts") - self.canvas.setLabel("left", self.nameTuple[1], "counts") - - # connections - self.actionExport.triggered.connect(self.exportData) - self.actionSave_as_PNG.triggered.connect(self.exportAsPNG) - self.actionGenerate_MultiColor_Mask.triggered.connect(self.generateMultiColorView) - self.actionWhite.triggered.connect(lambda: self.scatterViewer.setBackground("w")) - self.actionBlack.triggered.connect(lambda: self.scatterViewer.setBackground("k")) - - with pg.BusyCursor(): - for arr, fitline, clr, fitClr, rname, feqn in zip( - self.scatterPoints, self.fitLine, self.scatterColors, self.fitColors, self.roiNames, self.fitEqns - ): - sctrPoints = [] - for pt in arr: - sctrPoints.append( - {"pos": (pt[0], pt[1]), "data": "id", "size": 3, "pen": pg.mkPen(None), "brush": clr} - ) - - # generate a scatter plot item - self.scattered = pg.ScatterPlotItem(size=4.5, pen=clr, brush=pg.mkBrush(5, 214, 255, 200)) - # set scatter plot data - self.scattered.setPoints(sctrPoints, name=rname) - - # set z value negative to show scatter data behind the fit line - self.scattered.setZValue(-10) - - # add scatter plot to the canvas - self.canvas.addItem(self.scattered) - - # generate plotitem for fit line - self.fitLinePlot = pg.PlotDataItem(pen=pg.mkPen(fitClr, width=4.5)) - - # set line plot data - self.fitLinePlot.setData(fitline, name=feqn) - - # add line plot to the canvas - self.canvas.addItem(self.fitLinePlot) - - def generateMultiColorView(self): - self.multichanneldict = {} - - for n, (colorName, image, rname) in enumerate(zip(cmap_dict.keys(), self.maskImages, self.roiNames)): - low, high = np.min(image), np.max(image) - self.multichanneldict[rname] = { - "ImageName": rname, - "ImageDir": ".", - "Image": image, - "Color": colorName, - "CmapLimits": (low, high), - "Opacity": 1.0, - } - - # print( self.multichanneldict) - self.muli_color_window = MultiChannelWindow(image_dict=self.multichanneldict) - self.muli_color_window.show() - - def exportData(self): - exporter = pg.exporters.CSVExporter(self.canvas) - # exporter.parameters()['columnMode'] = '(x,y,y,y) for all plots' - file_name = QFileDialog().getSaveFileName(self, "Save CSV Data", "scatter.csv", "image file (*csv)") - if file_name[0]: - exporter.export(str(file_name[0])) - self.statusbar.showMessage(f"Data saved to {str(file_name[0])}") - else: - pass - - def exportAsPNG(self): - file_name = QtWidgets.QFileDialog().getSaveFileName( - self, "Save Image", "image.png", "PNG(*.png);; TIFF(*.tiff);; JPG(*.jpg)" - ) - exporter = pg.exporters.ImageExporter(self.canvas) - - if file_name[0]: - exporter.export(str(file_name[0])) - self.statusbar.showMessage(f"Image saved to {str(file_name[0])}") - else: - pass - - -class MaskSpecViewer(QtWidgets.QMainWindow): - def __init__(self, xanes_stack=None, xrf_map=None, energy=[]): - super(MaskSpecViewer, self).__init__() - uic.loadUi(os.path.join(ui_path, "uis/MaskedView.ui"), self) - - self.xanes_stack = xanes_stack - self.xrf_map = xrf_map - self.energy = energy - self.xrf_map = self.xanes_stack[-1] - self.view_data() - - # connections - self.sldr_xrf_low.valueChanged.connect(self.create_mask) - self.sldr_xrf_high.valueChanged.connect(self.create_mask) - self.pb_apply_mask.clicked.connect(self.apply_mask_to_xanes) - self.pb_export_mask.clicked.connect(self.export_mask) - self.pb_import_mask.clicked.connect(self.import_a_mask) - self.actionLoad_Energy_List.triggered.connect(self.load_energy) - self.actionLoad_XANES_Stack.triggered.connect(self.load_xanes_stack) - self.actionLoad_XRF_Map.triggered.connect(self.load_xrf_map) - - def view_data(self): - self.xanes_view.setImage(self.xanes_stack) - self.xanes_view.ui.menuBtn.hide() - self.xanes_view.ui.roiBtn.hide() - (self.dim1, self.dim3, self.dim2) = self.xanes_stack.shape - self.xanes_view.setPredefinedGradient("viridis") - self.xanes_view.setCurrentIndex(self.dim1 // 2) - self.statusbar.showMessage("One image from the XANES stack is used as mask") - self.xrf_view.setImage(self.xrf_map) - self.xrf_view.ui.menuBtn.hide() - self.xrf_view.ui.roiBtn.hide() - self.xrf_view.setPredefinedGradient("viridis") - - self.mask_view.ui.menuBtn.hide() - self.mask_view.ui.roiBtn.hide() - - def create_mask(self): - self.threshold_low = np.around(self.sldr_xrf_low.value() * 0.01, 3) - self.threshold_high = np.around(self.sldr_xrf_high.value() * 0.01, 3) - self.sldr_xrf_low.setMaximum(self.sldr_xrf_high.value() + 1) - self.sldr_xrf_high.setMinimum(self.sldr_xrf_low.value() + 1) - self.norm_xrf_map = remove_nan_inf(self.xrf_map) / remove_nan_inf(self.xrf_map.max()) - self.norm_xrf_map[self.norm_xrf_map < self.threshold_low] = 0 - self.norm_xrf_map[self.norm_xrf_map > self.threshold_high] = 0 - self.xrf_view.setImage(self.norm_xrf_map) - self.le_sldr_vals.setText(str(self.threshold_low) + " to " + str(self.threshold_high)) - self.statusbar.showMessage("New Threshold Applied") - self.xrf_mask = np.where(self.norm_xrf_map > 0, self.norm_xrf_map, 0) - self.xrf_mask[self.xrf_mask > 0] = 1 - self.mask_view.setImage(self.xrf_mask) - - def load_xanes_stack(self): - """loading a new xanes stack""" - filename = QFileDialog().getOpenFileName(self, "Select image data", "", "image file(*tiff *tif )") - self.file_name = str(filename[0]) - self.xanes_stack = tf.imread(self.file_name).transpose(0, 2, 1) - self.view_data() - - def load_energy(self): - """To load energy list that will be used for plotting the spectra. - number of stack should match length of energy list""" - - file_name = QFileDialog().getOpenFileName(self, "Open energy list", "", "text file (*.txt)") - - try: - self.energy = np.loadtxt(str(file_name[0])) - logger.info("Energy file loaded") - assert len(self.energy) == self.dim1 - self.view_data() - - except OSError: - logger.error("No File selected") - pass - - def load_xrf_map(self): - """To xrf map for masking. If 3D mean will be taken""" - - filename = QFileDialog().getOpenFileName(self, "Select image data", "", "image file(*tiff *tif )") - self.xrf_file_name = str(filename[0]) - self.xrf_map = tf.imread(self.xrf_file_name) - if self.xrf_map.ndim == 3: - self.xrf_map = self.xrf_map.mean(0).T - - else: - self.xrf_map = self.xrf_map.T - - assert ( - self.dim3, - self.dim2, - ) == self.xrf_map.shape, f"Unexpected image dimensions: {self.xrf_map.shape} vs {(self.dim2,self.dim3)}" - - self.view_data() - self.create_mask() - - def apply_mask_to_xanes(self): - """Generates a mask with 0 and 1 from the choosen threshold and multply with the xanes stack. - A spectrum will be generated from the new masked stack""" - - self.masked_xanes = self.xanes_stack * self.xrf_mask - self.xanes_view.setImage(self.masked_xanes) - self.xanes_view.setCurrentIndex(self.dim1 // 2) - self.statusbar.showMessage("Mask Applied to XANES") - self.mask_spec = get_mean_spectra(self.masked_xanes) - - if len(self.energy) != 0: - self.xdata = self.energy - else: - self.xdata = np.arange(0, self.dim1) - self.statusbar.showMessage("No Energy List Available; Integer values are used for plotting") - - self.spectrum_view.plot(self.xdata, self.mask_spec, clear=True) - - def import_a_mask(self): - filename = QFileDialog().getOpenFileName(self, "Select image data", "", "image file(*tiff *tif )") - xrf_file_name = str(filename[0]) - self.xrf_mask = tf.imread(xrf_file_name).T - self.statusbar.showMessage("A New Mask Imported") - self.mask_view.setImage(self.xrf_mask) - self.apply_mask_to_xanes() - - def export_mask(self): - try: - file_name = QFileDialog().getSaveFileName(self, "Save image data", "", "image file(*tiff *tif )") - tf.imsave(str(file_name[0]) + ".tiff", self.xrf_mask.T) - logger.info(f"Updated Image Saved: {str(file_name[0])}") - self.statusbar.showMessage("Mask Exported") - except Exception: - logger.error("No file to save") - pass - - -class StackInfo(QtWidgets.QMainWindow): - def __init__(self, text_to_write: str = " "): - super(StackInfo, self).__init__() - uic.loadUi(os.path.join(ui_path, "uis/log.ui"), self) - - self.text_to_write = text_to_write - self.pte_run_cmd.setPlainText(self.text_to_write) - - # connections - self.pb_save_cmd.clicked.connect(self.save_file) - self.pb_clear_cmd.clicked.connect(self.clear_text) - - def save_file(self): - S__File = QFileDialog.getSaveFileName(None, "SaveFile", "/", "txt Files (*.txt)") - - Text = self.pte_run_cmd.toPlainText() - if S__File[0]: - with open(S__File[0], "w") as file: - file.write(Text) - - def clear_text(self): - self.pte_run_cmd.clear() - - -class MultiChannelWindow(QtWidgets.QMainWindow): - def __init__(self, image_dict=None): - super(MultiChannelWindow, self).__init__() - if image_dict is None: - image_dict = {} - uic.loadUi(os.path.join(ui_path, "uis/mutlichannel.ui"), self) - - self.canvas = self.img_view.addPlot(title="") - self.canvas.getViewBox().invertY(True) - self.canvas.setAspectLocked(True) - self.cb_choose_color.addItems([i for i in cmap_dict.keys()]) - - self.image_dict = image_dict - self.buildFromDictionary() - - # connections - self.actionLoad.triggered.connect(self.createMuliColorAndList) - self.actionLoad_Stack.triggered.connect(self.createMuliColorAndList) - self.cb_choose_color.currentTextChanged.connect(self.updateImageDictionary) - self.pb_update_low_high.clicked.connect(self.updateImageDictionary) - self.listWidget.itemClicked.connect(self.editImageProperties) - self.listWidget.itemDoubleClicked.connect(self.showOneImageOnly) - self.pb_show_selected.clicked.connect(self.showOneImageOnly) - self.pb_show_all.clicked.connect(self.showAllItems) - self.actionLoad_State_File.triggered.connect(self.importState) - self.actionSave_State.triggered.connect(self.exportState) - self.actionSave_View.triggered.connect(self.saveImage) - - def buildFromDictionary(self): - if self.image_dict is not None: - self.createMultiColorView(self.image_dict) - self.displayImageNames(self.image_dict) - else: - pass - - def generateImageDictionary(self): - """Creates a dictionary contains image path, color scheme chosen, throshold limits etc. - when user edits the parameters dictionary will be updated and unwrapped for display later. - This dictionary is saved as json file while saving the state. Two image loading options are possible. - User can either select multiple 2D array images or one 3D array (stack)""" - - clickedAction = self.sender() - - if clickedAction.text() == "Load Images": - # multiple images are selected - self.loadMultipleImageFiles() - - elif clickedAction.text() == "Load Stack": - # an image stack is selected - self.loadAsStack() - - def loadMultipleImageFiles(self): - filter = "TIFF (*.tiff);;TIF (*.tif)" - QtWidgets.QFileDialog().setFileMode(QtWidgets.QFileDialog.ExistingFiles) - # choose mutliple tiff files - names = QtWidgets.QFileDialog().getOpenFileNames(self, "Open files", " ", filter) - if names[0]: - self.image_dict = {} - # select the file directory. Image files are expected to be in the same folder - self.imageDir = os.path.dirname(names[0][0]) - - # create the dictionary - for colorName, image in zip(cmap_dict.keys(), names[0]): - # squeeze to allow with pseudo 3D axis from some tomo recon (eg. 1, 100,100 array) - im_array = np.squeeze(tf.imread(image)) - # set values for thresholding as image min and max - low, high = np.min(im_array), np.max(im_array) - # name of the tiff file is chosen as key for the dictionary, - # inner keys are properties set for that image - im_name = os.path.basename(image) - # construct the dictionary - self.image_dict[f"{os.path.basename(image)}"] = { - "ImageName": im_name, - "ImageDir": self.imageDir, - "Image": im_array, - "Color": colorName, - "CmapLimits": (low, high), - "Opacity": 1.0, - } - else: - pass - - def loadAsStack(self): - """construct the dictionary with image +number as the key. - All other steps are similar to the loadMultipleImageFiles function""" - - filter = "TIFF (*.tiff);;TIF (*.tif)" - file_name = QtWidgets.QFileDialog().getOpenFileName( - self, "Open a Stack", "", "TIFF(*tiff *tif);;all_files (*)", filter - ) - if file_name[0]: - self.imageDir = os.path.dirname(file_name[0]) - self.image_dict = {} - im_stack = np.squeeze(tf.imread(file_name[0])) - # asset the file is a stack - assert im_stack.ndim == 3, "Not a stack" - # construct the dictionary - for n, (colorName, image) in enumerate(zip(cmap_dict.keys(), im_stack)): - low, high = np.min(image), np.max(image) - self.image_dict[f"Image {n+1}"] = { - "ImageName": f"Image {n+1}", - "ImageDir": self.imageDir, - "Image": image, - "Color": colorName, - "CmapLimits": (low, high), - "Opacity": 1.0, - } - - def loadAnImage(self, image, colormap, cmap_limits, opacity=1): - """load single image and colorbar to the widget. This function will be looped for - multiple images later - """ - # get pg image item - img = pg.ImageItem() - # add image to the graphicsview widget - self.canvas.addItem(img) - # set the color map - cmap = pg.ColorMap(pos=np.linspace(0, 1, len(colormap)), color=colormap) - # image = np.squeeze(tf.imread(image_path)) - # set image to the image item with cmap - img.setImage(np.array(image), lut=cmap.getLookupTable(), opacity=opacity) - - # set colorbar for thresholding - bar = pg.ColorBarItem(values=cmap_limits, cmap=cmap, limits=(0, None), orientation="vertical") - bar.setImageItem(img) - # set composition mode to plus for overlaying - img.setCompositionMode(QtGui.QPainter.CompositionMode_Plus) - - def createMultiColorView(self, image_dictionary): - """Function creates multi color image view by taking image - data and parameters from the dictionary""" - - # clear the plots and list in case of re-loading - self.canvas.clear() - self.listWidget.clear() - - # display individual images in for loop - for path_and_color in image_dictionary.values(): - self.loadAnImage( - path_and_color["Image"], - cmap_dict[path_and_color["Color"]], - path_and_color["CmapLimits"], - path_and_color["Opacity"], - ) - - def showOneImageOnly(self): - editItem = self.listWidget.currentItem() - editRow = self.listWidget.currentRow() - for i in range(self.listWidget.count()): - if self.listWidget.item(i) == editItem: - editItemName = self.listWidget.item(i).text().split(",")[0] - self.image_dict[editItemName]["Opacity"] = 1 - - elif self.listWidget.item(i) != editItem: - editItemName = self.listWidget.item(i).text().split(",")[0] - self.image_dict[editItemName]["Opacity"] = 0 - - self.createMultiColorView(self.image_dict) - self.displayImageNames(self.image_dict) - self.listWidget.setCurrentRow(editRow) - - def showAllItems(self): - # editItem = self.listWidget.currentItem() - editRow = self.listWidget.currentRow() - for i in range(self.listWidget.count()): - editItemName = self.listWidget.item(i).text().split(",")[0] - self.image_dict[editItemName]["Opacity"] = 1 - - self.createMultiColorView(self.image_dict) - self.displayImageNames(self.image_dict) - self.listWidget.setCurrentRow(editRow) - - def displayImageNames(self, image_dictionary): - """Populate the list widget table with image name and color used to plot, - using image dictionary input""" - - for im_name, vals in image_dictionary.items(): - self.listWidget.addItem(f"{im_name},{vals['Color']}") - self.listWidget.setCurrentRow(0) - - def createMuliColorAndList(self): - """Finally Load Images and poplulate the list widget from the dictionary""" - with pg.BusyCursor(): # gives the circle showing gui is doing something - self.generateImageDictionary() - if self.image_dict: - self.createMultiColorView(self.image_dict) - self.displayImageNames(self.image_dict) - - else: - pass - - def sliderSetUp(self, im_array): - """Setting the slider min and max from image values""" - - low = (np.min(im_array) / np.max(im_array)) * 100 - self.sldr_low.setMaximum(100) - self.sldr_low.setMinimum(low) - self.sldr_high.setMaximum(100) - self.sldr_high.setMinimum(low) - - def editImageProperties(self, item): - """function to control the assigned properties such as color, - threshold limits, opacity etc of a single image selected using the list widget item""" - - editItem = item.text() - # get the dictionary key from item text - editItemName = editItem.split(",")[0] - editItemColor = editItem.split(",")[1] - im_array = self.image_dict[editItemName]["Image"] - self.sliderSetUp(im_array) - setValLow = (self.image_dict[editItemName]["CmapLimits"][0] * 100) / np.max(im_array) - setValHigh = (self.image_dict[editItemName]["CmapLimits"][1] * 100) / np.max(im_array) - setOpacity = self.image_dict[editItemName]["Opacity"] * 100 - self.sldr_low.setValue(int(setValLow)) - self.sldr_high.setValue(int(setValHigh)) - self.sldr_opacity.setValue(int(setOpacity)) - self.low_high_vals.setText(f"low:{self.sldr_low.value()}," f"high:{self.sldr_high.value()}") - self.cb_choose_color.setCurrentText(editItemColor) - - def updateImageDictionary(self): - newColor = self.cb_choose_color.currentText() - editItem = self.listWidget.currentItem().text() - editRow = self.listWidget.currentRow() - editItemName = editItem.split(",")[0] - self.imageDir = self.image_dict[editItemName]["ImageDir"] - im_array = self.image_dict[editItemName]["Image"] - self.sliderSetUp(im_array) - cmap_limits = ( - self.sldr_low.value() * np.max(im_array) / 100, - self.sldr_high.value() * np.max(im_array) / 100, - ) - self.low_high_vals.setText(f"low:{cmap_limits[0]:.3f},high:{cmap_limits[1]:.3f}") - opacity = self.sldr_opacity.value() / 100 - self.opacity_val.setText(str(opacity)) - self.image_dict[editItemName] = { - "ImageName": editItemName, - "ImageDir": self.imageDir, - "Image": im_array, - "Color": newColor, - "CmapLimits": cmap_limits, - "Opacity": opacity, - } - - self.createMultiColorView(self.image_dict) - self.displayImageNames(self.image_dict) - self.listWidget.setCurrentRow(editRow) - - def exportState(self): - file_name = QtWidgets.QFileDialog().getSaveFileName( - self, "Save Current State", "multicolor_params.json", "json file(*json)" - ) - """ - for val in self.image_dict.values(): - val['CmapLimits'] = json.dumps(str(val['CmapLimits'])) - """ - - if file_name[0]: - with open(f"{file_name[0]}", "w") as fp: - json.dump(self.image_dict, fp, indent=4, cls=jsonEncoder) - - else: - pass - - def importState(self): - file_name = QtWidgets.QFileDialog().getOpenFileName( - self, "Open a State File", "", "json file(*json);;all_files (*)" - ) - if file_name[0]: - with open(file_name[0], "r") as fp: - self.image_dict = json.load(fp) - - self.createMultiColorView(self.image_dict) - self.displayImageNames(self.image_dict) - else: - pass - - def saveImage(self): - file_name = QtWidgets.QFileDialog().getSaveFileName( - self, "Save Image", "multicolor_image.png", "PNG(*.png);; TIFF(*.tiff);; JPG(*.jpg)" - ) - exporter = pg.exporters.ImageExporter(self.canvas.getViewBox()) - exporter.export(file_name[0]) - - -""" Helper Functions""" - - -def get_xrf_data(h="h5file"): - """ - get xrf stack from h5 data generated at NSLS-II beamlines - - Arguments: - h5/hdf5 file - - Returns: - norm_xrf_stack - xrf stack image normalized with Io - mono_e - excitation enegy used for xrf - beamline - identity of the beamline - Io_avg - an average Io value, used before taking log - - """ - - f = h5py.File(h, "r") - - if list(f.keys())[0] == "xrfmap": - logger.info("Data from HXN/TES/SRX") - beamline = f["xrfmap/scan_metadata"].attrs["scan_instrument_id"] - - try: - beamline_scalar = {"HXN": 2, "SRX": 0, "TES": 0} - - if beamline in beamline_scalar.keys(): - Io = np.array(f["xrfmap/scalers/val"])[:, :, beamline_scalar[beamline]] - raw_xrf_stack = np.array(f["xrfmap/detsum/counts"]) - norm_xrf_stack = raw_xrf_stack - Io_avg = int(remove_nan_inf(Io).mean()) - else: - logger.error("Unknown Beamline Scalar") - except Exception: - logger.warning("Unknown Scalar: Raw Detector count in use") - norm_xrf_stack = np.array(f["xrfmap/detsum/counts"]) - - elif list(f.keys())[0] == "xrmmap": - logger.info("Data from XFM") - beamline = "XFM" - raw_xrf_stack = np.array(f["xrmmap/mcasum/counts"]) - Io = np.array(f["xrmmap/scalars/I0"]) - norm_xrf_stack = raw_xrf_stack - Io_avg = int(remove_nan_inf(Io).mean()) - - else: - logger.error("Unknown Data Format") - - try: - mono_e = int(f["xrfmap/scan_metadata"].attrs["instrument_mono_incident_energy"] * 1000) - logger.info("Excitation energy was taken from the h5 data") - - except Exception: - mono_e = 12000 - logger.info(f"Unable to get Excitation energy from the h5 data; using default value {mono_e} KeV") - - return remove_nan_inf(norm_xrf_stack.transpose((2, 0, 1))), mono_e + 1500, beamline, Io_avg - - -def remove_nan_inf(im): - im = np.array(im, dtype=np.float32) - im[np.isnan(im)] = 0 - im[np.isinf(im)] = 0 - return im - - -def rebin_image(im, bin_factor): - arrx, arry = np.shape(im) - if arrx / bin_factor != int or arrx / bin_factor != int: - logger.error("Invalid Binning") - - else: - shape = (arrx / bin_factor, arry / bin_factor) - return im.reshape(shape).mean(-1).mean(1) - - -def remove_hot_pixels(image_array, NSigma=5): - image_array = remove_nan_inf(image_array) - a, b, c = np.shape(image_array) - img_stack2 = np.zeros((a, b, c)) - for i in range(a): - im = image_array[i, :, :] - im[abs(im) > np.std(im) * NSigma] = im.mean() - img_stack2[i, :, :] = im - return img_stack2 - - -def smoothen(image_array, w_size=5): - a, b, c = np.shape(image_array) - spec2D_Matrix = np.reshape(image_array, (a, (b * c))) - smooth2D_Matrix = savgol_filter(spec2D_Matrix, w_size, w_size - 2, axis=0) - return remove_nan_inf(np.reshape(smooth2D_Matrix, (a, b, c))) - - -def resize_stack(image_array, upscaling=False, scaling_factor=2): - en, im1, im2 = np.shape(image_array) - - if upscaling: - im1_ = im1 * scaling_factor - im2_ = im2 * scaling_factor - img_stack_resized = resize(image_array, (en, im1_, im2_)) - - else: - im1_ = int(im1 / scaling_factor) - im2_ = int(im2 / scaling_factor) - img_stack_resized = resize(image_array, (en, im1_, im2_)) - - return img_stack_resized - - -def normalize(image_array, norm_point=-1): - norm_stack = image_array / image_array[norm_point] - return remove_nan_inf(norm_stack) - - -def remove_edges(image_array): - # z, x, y = np.shape(image_array) - return image_array[:, 1:-1, 1:-1] - - -def background_value(image_array): - img = image_array.mean(0) - img_h = img.mean(0) - img_v = img.mean(1) - h = np.gradient(img_h) - v = np.gradient(img_v) - bg = np.min([img_h[h == h.max()], img_v[v == v.max()]]) - return bg - - -def background_subtraction(img_stack, bg_percentage=10): - img_stack = remove_nan_inf(img_stack) - a, b, c = np.shape(img_stack) - ref_image = np.reshape(img_stack.mean(0), (b * c)) - bg_ratio = int((b * c) * 0.01 * bg_percentage) - bg_ = np.max(sorted(ref_image)[0:bg_ratio]) - bged_img_stack = img_stack - bg_[:, np.newaxis, np.newaxis] - return bged_img_stack - - -def background_subtraction2(img_stack, bg_percentage=10): - img_stack = remove_nan_inf(img_stack) - a, b, c = np.shape(img_stack) - bg_ratio = int((b * c) * 0.01 * bg_percentage) - bged_img_stack = img_stack.copy() - - for n, img in enumerate(img_stack): - bg_ = np.max(sorted(img.flatten())[0:bg_ratio]) - print(bg_) - bged_img_stack[n] = img - bg_ - - return remove_nan_inf(bged_img_stack) - - -def background1(img_stack): - img = img_stack.sum(0) - img_h = img.mean(0) - img_v = img.mean(1) - h = np.gradient(img_h) - v = np.gradient(img_v) - bg = np.min([img_h[h == h.max()], img_v[v == v.max()]]) - return bg - - -def get_sum_spectra(image_array): - spec = np.sum(image_array, axis=(1, 2)) - return spec - - -def get_mean_spectra(image_array): - spec = np.mean(image_array, axis=(1, 2)) - return spec - - -def flatten_(image_array): - z, x, y = np.shape(image_array) - flat_array = np.reshape(image_array, (x * y, z)) - return flat_array - - -def image_to_pandas(image_array): - a, b, c = np.shape(image_array) - im_array = np.reshape(image_array, ((b * c), a)) - a, b = im_array.shape - df = pd.DataFrame( - data=im_array[:, :], columns=["e" + str(i) for i in range(b)], index=["s" + str(i) for i in range(a)] - ) - return df - - -def image_to_pandas2(image_array): - a, b, c = np.shape(image_array) - im_array = np.reshape(image_array, (a, (b * c))) - a, b = im_array.shape - df = pd.DataFrame( - data=im_array[:, :], index=["e" + str(i) for i in range(a)], columns=["s" + str(i) for i in range(b)] - ) - return df - - -def neg_log(image_array): - absorb = -1 * np.log(image_array) - return remove_nan_inf(absorb) - - -def clean_stack(img_stack, auto_bg=False, bg_percentage=5): - a, b, c = np.shape(img_stack) - - if auto_bg is True: - bg_ = background1(img_stack) - - else: - sum_spec = (img_stack.sum(1)).sum(1) - ref_stk_num = np.where(sum_spec == sum_spec.max())[-1] - - ref_image = np.reshape(img_stack[ref_stk_num], (b * c)) - bg_ratio = int((b * c) * 0.01 * bg_percentage) - bg_ = np.max(sorted(ref_image)[0:bg_ratio]) - - bg = np.where(img_stack[ref_stk_num] > bg_, img_stack[ref_stk_num], 0) - bg2 = np.where(bg < bg_, bg, 1) - - bged_img_stack = img_stack * bg2 - - return remove_nan_inf(bged_img_stack) - - -def subtractBackground(im_stack, bg_region): - if bg_region.ndim == 3: - bg_region_ = np.mean(bg_region, axis=(1, 2)) - - elif bg_region.ndim == 2: - bg_region_ = np.mean(bg_region, axis=1) - - else: - bg_region_ = bg_region - - return im_stack - bg_region_[:, np.newaxis, np.newaxis] - - -def classify(img_stack, correlation="Pearson"): - img_stack_ = img_stack - a, b, c = np.shape(img_stack_) - norm_img_stack = normalize(img_stack_) - f = np.reshape(norm_img_stack, (a, (b * c))) - - max_x, max_y = np.where(norm_img_stack.sum(0) == (norm_img_stack.sum(0)).max()) - ref = norm_img_stack[:, int(max_x), int(max_y)] - corr = np.zeros(len(f.T)) - for s in range(len(f.T)): - if correlation == "Kendall": - r, p = stats.kendalltau(ref, f.T[s]) - elif correlation == "Pearson": - r, p = stats.pearsonr(ref, f.T[s]) - - corr[s] = r - - cluster_image = np.reshape(corr, (b, c)) - return (cluster_image**3), img_stack_ - - -def correlation_kmeans(img_stack, n_clusters, correlation="Pearson"): - img, bg_image = classify(img_stack, correlation) - img[np.isnan(img)] = -99999 - X = img.reshape((-1, 1)) - k_means = sc.KMeans(n_clusters) - k_means.fit(X) - - X_cluster = k_means.labels_ - X_cluster = X_cluster.reshape(img.shape) + 1 - - return X_cluster - - -def cluster_stack( - im_array, method="KMeans", n_clusters_=4, decomposed=False, decompose_method="PCA", decompose_comp=2 -): - a, b, c = im_array.shape - - if method == "Correlation-Kmeans": - X_cluster = correlation_kmeans(im_array, n_clusters_, correlation="Pearson") - - else: - methods = { - "MiniBatchKMeans": sc.MiniBatchKMeans, - "KMeans": sc.KMeans, - "MeanShift": sc.MeanShift, - "Spectral Clustering": sc.SpectralClustering, - "Affinity Propagation": sc.AffinityPropagation, - } - - if decomposed: - im_array = denoise_with_decomposition(im_array, method_=decompose_method, n_components=decompose_comp) - - flat_array = np.reshape(im_array, (a, (b * c))) - init_cluster = methods[method](n_clusters=n_clusters_) - init_cluster.fit(np.transpose(flat_array)) - X_cluster = init_cluster.labels_.reshape(b, c) + 1 - - decon_spectra = np.zeros((a, n_clusters_)) - decon_images = np.zeros((n_clusters_, b, c)) - - for i in range(n_clusters_): - mask_i = np.where(X_cluster == (i + 1), X_cluster, 0) - spec_i = get_sum_spectra(im_array * mask_i) - decon_spectra[:, i] = spec_i - decon_images[i] = im_array.sum(0) * mask_i - - return decon_images, X_cluster, decon_spectra - - -def kmeans_variance(im_array): - a, b, c = im_array.shape - flat_array = np.reshape(im_array, (a, (b * c))) - var = np.arange(24) - clust_n = np.arange(24) + 2 - - for clust in var: - init_cluster = sc.KMeans(n_clusters=int(clust + 2)) - init_cluster.fit(np.transpose(flat_array)) - var_ = init_cluster.inertia_ - var[clust] = np.float64(var_) - - kmeans_var_plot = pg.plot( - clust_n, var, title="KMeans Variance", pen=pg.mkPen("y", width=2, style=QtCore.Qt.DotLine), symbol="o" - ) - kmeans_var_plot.setLabel("bottom", "Cluster Number") - kmeans_var_plot.setLabel("left", "Sum of squared distances") - - -def pca_scree(im_stack): - new_image = im_stack.transpose(2, 1, 0) - x, y, z = np.shape(new_image) - img_ = np.reshape(new_image, (x * y, z)) - pca = sd.PCA(z) - pca.fit(img_) - # var = pca.explained_variance_ratio_ - var = pca.singular_values_ - - pca_scree_plot = pg.plot( - var[:24], title="PCA Scree Plot", pen=pg.mkPen("y", width=2, style=QtCore.Qt.DotLine), symbol="o" - ) - pca_scree_plot.addLine(y=0) - pca_scree_plot.setLabel("bottom", "Component Number") - pca_scree_plot.setLabel("left", "Singular Values") - - -def decompose_stack(im_stack, decompose_method="PCA", n_components_=3): - new_image = im_stack.transpose(2, 1, 0) - x, y, z = np.shape(new_image) - img_ = np.reshape(new_image, (x * y, z)) - methods_dict = { - "PCA": sd.PCA, - "IncrementalPCA": sd.IncrementalPCA, - "NMF": sd.NMF, - "FastICA": sd.FastICA, - "DictionaryLearning": sd.MiniBatchDictionaryLearning, - "FactorAnalysis": sd.FactorAnalysis, - "TruncatedSVD": sd.TruncatedSVD, - } - - _mdl = methods_dict[decompose_method](n_components=n_components_) - - ims = (_mdl.fit_transform(img_).reshape(x, y, n_components_)).transpose(2, 1, 0) - spcs = _mdl.components_.transpose() - decon_spetra = np.zeros((z, n_components_)) - decom_map = np.zeros((ims.shape)) - - for i in range(n_components_): - f = ims.copy()[i] - f[f < 0] = 0 - spec_i = ((new_image.T * f).sum(1)).sum(1) - decon_spetra[:, i] = spec_i - - f[f > 0] = i + 1 - decom_map[i] = f - decom_map = decom_map.sum(0) - - return np.float32(ims), spcs, decon_spetra, decom_map - - -def denoise_with_decomposition(img_stack, method_="PCA", n_components=4): - new_image = img_stack.transpose(2, 1, 0) - x, y, z = np.shape(new_image) - img_ = np.reshape(new_image, (x * y, z)) - - methods_dict = { - "PCA": sd.PCA, - "IncrementalPCA": sd.IncrementalPCA, - "NMF": sd.NMF, - "FastICA": sd.FastICA, - "DictionaryLearning": sd.DictionaryLearning, - "FactorAnalysis": sd.FactorAnalysis, - "TruncatedSVD": sd.TruncatedSVD, - } - - decomposed = methods_dict[method_](n_components=n_components) - - ims = (decomposed.fit_transform(img_).reshape(x, y, n_components)).transpose(2, 1, 0) - ims[ims < 0] = 0 - ims[ims > 0] = 1 - mask = ims.sum(0) - mask[mask > 1] = 1 - # mask = uniform_filter(mask) - filtered = img_stack * mask - # plt.figure() - # plt.imshow(filtered.sum(0)) - # plt.title('background removed') - # plt.show() - return remove_nan_inf(filtered) - - -def interploate_E(refs, e): - n = np.shape(refs)[1] - refs = np.array(refs) - ref_e = refs[:, 0] - ref = refs[:, 1:n] - all_ref = [] - for i in range(n - 1): - ref_i = np.interp(e, ref_e, ref[:, i]) - all_ref.append(ref_i) - return np.array(all_ref) - - -def getStats(spec, fit, num_refs=2): - stats = {} - - r_factor = (np.sum(spec - fit) ** 2) / np.sum(spec**2) - stats["R_Factor"] = np.around(r_factor, 5) - - y_mean = np.sum(spec) / len(spec) - SS_tot = np.sum((spec - y_mean) ** 2) - SS_res = np.sum((spec - fit) ** 2) - r_square = 1 - (SS_res / SS_tot) - stats["R_Square"] = np.around(r_square, 4) - - chisq = np.sum((spec - fit) ** 2) - stats["Chi_Square"] = np.around(chisq, 5) - - red_chisq = chisq / (len(spec) - num_refs) - stats["Reduced Chi_Square"] = red_chisq - - return stats - - -def xanes_fitting_1D(spec, e_list, refs, method="NNLS", alphaForLM=0.01): - """Linear combination fit of image data with reference standards""" - - int_refs = interploate_E(refs, e_list) - - if method == "NNLS": - coeffs, r = opt.nnls(int_refs.T, spec) - - elif method == "LASSO": - lasso = linear_model.Lasso(positive=True, alpha=alphaForLM) # lowering alpha helps with 1D fits - fit_results = lasso.fit(int_refs.T, spec) - coeffs = fit_results.coef_ - - elif method == "RIDGE": - ridge = linear_model.Ridge(alpha=alphaForLM) - fit_results = ridge.fit(int_refs.T, spec) - coeffs = fit_results.coef_ - - fit = coeffs @ int_refs - stats = getStats(spec, fit, num_refs=np.min(np.shape(int_refs.T))) - - return stats, coeffs - - -def xanes_fitting(im_stack, e_list, refs, method="NNLS", alphaForLM=0.1, binStack=False): - """Linear combination fit of image data with reference standards""" - - if binStack: - im_stack = resize_stack(im_stack, scaling_factor=4) - - en, im1, im2 = np.shape(im_stack) - im_array = im_stack.reshape(en, im1 * im2) - coeffs_arr = [] - r_factor_arr = [] - # lasso = linear_model.Lasso(positive=True, alpha=alphaForLM) - for n, i in enumerate(range(im1 * im2)): - stats, coeffs = xanes_fitting_1D(im_array[:, i], e_list, refs, method=method, alphaForLM=alphaForLM) - coeffs_arr.append(coeffs) - r_factor_arr.append(stats["R_Factor"]) - - abundance_map = np.reshape(coeffs_arr, (im1, im2, -1)) - r_factor_im = np.reshape(r_factor_arr, (im1, im2)) - - return abundance_map, r_factor_im, np.mean(coeffs_arr, axis=0) - - -def xanes_fitting_Line(im_stack, e_list, refs, method="NNLS", alphaForLM=0.05): - """Linear combination fit of image data with reference standards""" - en, im1, im2 = np.shape(im_stack) - im_array = np.mean(im_stack, 2) - coeffs_arr = [] - meanStats = {"R_Factor": 0, "R_Square": 0, "Chi_Square": 0, "Reduced Chi_Square": 0} - - for i in range(im1): - stats, coeffs = xanes_fitting_1D(im_array[:, i], e_list, refs, method=method, alphaForLM=alphaForLM) - coeffs_arr.append(coeffs) - for key in stats.keys(): - meanStats[key] += stats[key] - - for key, vals in meanStats.items(): - meanStats[key] = np.around((vals / im1), 5) - - return meanStats, np.mean(coeffs_arr, axis=0) - - -def xanes_fitting_Binned(im_stack, e_list, refs, method="NNLS", alphaForLM=0.05): - """Linear combination fit of image data with reference standards""" - - im_stack = resize_stack(im_stack, scaling_factor=10) - # use a simple filter to find threshold value - val = filters.threshold_otsu(im_stack[-1]) - en, im1, im2 = np.shape(im_stack) - im_array = im_stack.reshape(en, im1 * im2) - coeffs_arr = [] - meanStats = {"R_Factor": 0, "R_Square": 0, "Chi_Square": 0, "Reduced Chi_Square": 0} - - specs_fitted = 0 - total_spec = im1 * im2 - for i in range(total_spec): - spec = im_array[:, i] - # do not fit low intensity/background regions - if spec[-1] > val: - specs_fitted += 1 - stats, coeffs = xanes_fitting_1D(spec / spec[-1], e_list, refs, method=method, alphaForLM=alphaForLM) - coeffs_arr.append(coeffs) - for key in stats.keys(): - meanStats[key] += stats[key] - else: - pass - - for key, vals in meanStats.items(): - meanStats[key] = np.around((vals / specs_fitted), 6) - # print(f"{specs_fitted}/{total_spec}") - return meanStats, np.mean(coeffs_arr, axis=0) - - -def create_df_from_nor(athenafile="fe_refs.nor"): - """create pandas dataframe from athena nor file, first column - is energy and headers are sample names""" - - refs = np.loadtxt(athenafile) - n_refs = refs.shape[-1] - skip_raw_n = n_refs + 6 - - df = pd.read_table( - athenafile, delim_whitespace=True, skiprows=skip_raw_n, header=None, usecols=np.arange(0, n_refs) - ) - df2 = pd.read_table( - athenafile, delim_whitespace=True, skiprows=skip_raw_n - 1, usecols=np.arange(0, n_refs + 1) - ) - new_col = df2.columns.drop("#") - df.columns = new_col - return df, list(new_col) - - -def create_df_from_nor_try2(athenafile="fe_refs.nor"): - """create pandas dataframe from athena nor file, first column - is energy and headers are sample names""" - - refs = np.loadtxt(athenafile) - n_refs = refs.shape[-1] - df_refs = pd.DataFrame(refs) - - df = pd.read_csv(athenafile, header=None) - new_col = list((str(df.iloc[n_refs + 5].values)).split(" ")[2::2]) - df_refs.columns = new_col - - return df_refs, list(new_col) - - -def energy_from_logfile(logfile="maps_log_tiff.txt"): - df = pd.read_csv(logfile, header=None, delim_whitespace=True, skiprows=9) - return df[9][df[7] == "energy"].values.astype(float) - - -def xanesNormalization( - e, mu, e0=7125, step=None, nnorm=2, nvict=0, pre1=None, pre2=-50, norm1=100, norm2=None, guess=False -): - if guess: - result = preedge(e, mu, e0, step=step, nnorm=nnorm, nvict=nvict) - - return result["pre1"], result["pre2"], result["norm1"], result["norm2"] - - else: - result = preedge(e, mu, e0, step, nnorm, nvict, pre1, pre2, norm1, norm2) - - return result["pre_edge"], result["post_edge"], result["norm"] - - -def xanesNormStack( - e_list, im_stack, e0=7125, step=None, nnorm=2, nvict=0, pre1=None, pre2=-50, norm1=100, norm2=None -): - en, im1, im2 = np.shape(im_stack) - im_array = im_stack.reshape(en, im1 * im2) - normedStackArray = np.zeros_like(im_array) - - for i in range(im1 * im2): - pre_line, post_line, normXANES = xanesNormalization( - e_list, - im_array[:, i], - e0=e0, - step=step, - nnorm=nnorm, - nvict=nvict, - pre1=pre1, - pre2=pre2, - norm1=norm1, - norm2=norm2, - guess=False, - ) - normedStackArray[:, i] = normXANES - - return remove_nan_inf(np.reshape(normedStackArray, (en, im1, im2))) - - -def align_stack( - stack_img, ref_image_void=True, ref_stack=None, transformation=StackReg.TRANSLATION, reference="previous" -): - """Image registration flow using pystack reg""" - - # all the options are in one function - - sr = StackReg(transformation) - - if ref_image_void: - tmats_ = sr.register_stack(stack_img, reference=reference) - - else: - tmats_ = sr.register_stack(ref_stack, reference=reference) - # out_ref = sr.transform_stack(ref_stack) - - out_stk = sr.transform_stack(stack_img, tmats=tmats_) - return np.float32(out_stk), tmats_ - - -def align_simple(stack_img, transformation=StackReg.TRANSLATION, reference="previous"): - sr = StackReg(transformation) - tmats_ = sr.register_stack(stack_img, reference="previous") - for i in range(10): - out_stk = sr.transform_stack(stack_img, tmats=tmats_) - import time - - time.sleep(2) - return np.float32(out_stk) - - -def align_with_tmat(stack_img, tmat_file, transformation=StackReg.TRANSLATION): - sr = StackReg(transformation) - out_stk = sr.transform_stack(stack_img, tmats=tmat_file) - return np.float32(out_stk) - - -def align_stack_iter( - stack, - ref_stack_void=True, - ref_stack=None, - transformation=StackReg.TRANSLATION, - method=("previous", "first"), - max_iter=2, -): - if ref_stack_void: - ref_stack = stack - - for i in range(max_iter): - sr = StackReg(transformation) - for ii in range(len(method)): - print(ii, method[ii]) - tmats = sr.register_stack(ref_stack, reference=method[ii]) - ref_stack = sr.transform_stack(ref_stack) - stack = sr.transform_stack(stack, tmats=tmats) - - return np.float32(stack) - - -def applyMaskGetMeanSpectrum(im_stack, mask): - """A 2d mask to multiply with the 3d xanes stack and returns mean spectrum""" - - masked_stack = im_stack * mask - return get_mean_spectra(masked_stack) - - -def modifyStack( - raw_stack, - normalizeStack=False, - normToPoint=-1, - applySmooth=False, - smoothWindowSize=3, - applyThreshold=False, - thresholdValue=0, - removeOutliers=False, - nSigmaOutlier=3, - applyTranspose=False, - transposeVals=(0, 1, 2), - applyCrop=False, - cropVals=(0, 1, 2), - removeEdges=False, - resizeStack=False, - upScaling=False, - binFactor=2, -): - """A giant function to modify the stack with many possible operations. - all the changes can be saved to a jason file as a config file. Enabling and - distabling the sliders is a problem""" - - """ - normStack = normalize(raw_stack, norm_point=normToPoint) - smoothStack = smoothen(raw_stack, w_size= smoothWindowSize) - thresholdStack = clean_stack(raw_stack, auto_bg=False, bg_percentage = thresholdValue) - outlierStack = remove_hot_pixels(raw_stack, NSigma=nSigmaOutlier) - transposeStack = np.transpose(raw_stack, transposeVals) - croppedStack = raw_stack[cropVals] - edgeStack = remove_edges(raw_stack) - binnedStack = resize_stack(raw_stack,upscaling=upScaling,scaling_factor=binFactor) - - """ - - if removeOutliers: - modStack = remove_hot_pixels(raw_stack, NSigma=nSigmaOutlier) - - else: - modStack = raw_stack - - if applyThreshold: - modStack = clean_stack(modStack, auto_bg=False, bg_percentage=thresholdValue) - - else: - pass - - if applySmooth: - modStack = smoothen(modStack, w_size=smoothWindowSize) - - else: - pass - - if applyTranspose: - modStack = np.transpose(modStack, transposeVals) - - else: - pass - - if applyCrop: - modStack = modStack[cropVals] - - else: - pass - - if normalizeStack: - modStack = normalize(raw_stack, norm_point=normToPoint) - else: - pass - - -def start_xmidas(): - def formatter(prog): - # Set maximum width such that printed help mostly fits in the RTD theme code block (documentation). - return argparse.RawDescriptionHelpFormatter(prog, max_help_position=20, width=90) - - parser = argparse.ArgumentParser( - description=f"XMidas: v{__version__}", - formatter_class=formatter, - ) - parser.parse_args() - - logger.setLevel(logging.INFO) - formatter = logging.Formatter(fmt="%(asctime)s : %(levelname)s : %(message)s") - stream_handler = logging.StreamHandler() - stream_handler.setFormatter(formatter) - stream_handler.setLevel(logging.INFO) - if logger.hasHandlers(): - logger.handlers.clear() - logger.addHandler(stream_handler) - - if version.parse(PYQT_VERSION_STR) >= version.parse("5.14"): - QApplication.setAttribute(QtCore.Qt.HighDpiScaleFactorRoundingPolicy.PassThrough) - - app = QtWidgets.QApplication(sys.argv) - # app.setAttribute(QtCore.Qt.AA_Use96Dpi) - window = midasWindow() - window.show() - sys.exit(app.exec_()) - - -if __name__ == "__main__": - start_xmidas() +# -*- coding: utf-8 -*- + +# Author: Ajith Pattammattel +# First Version on:06-23-2020 + +__version__ = "1.0.0" + +import argparse +import logging +import datetime +import sys +import webbrowser +import traceback +import os +import json +import scipy.stats as stats +import numpy as np +import pandas as pd +import tifffile as tf +import pyqtgraph as pg +import pyqtgraph.exporters +import faulthandler +faulthandler.enable() + + +from glob import glob +from pyqtgraph import plot +from itertools import combinations +from scipy.stats import linregress +from packaging import version + +from PyQt6 import QtWidgets, QtCore, QtGui, uic, QtTest +from PyQt6.QtGui import QMovie +from PyQt6.QtWidgets import QMessageBox, QFileDialog, QApplication +from PyQt6.QtCore import QObject, pyqtSignal, pyqtSlot, QRunnable, QThreadPool, PYQT_VERSION_STR + + +from utils.utils import * +from utils.color_maps import create_color_maps +from models.encoders import jsonEncoder + +from gui.windows.xanes_viewer import XANESViewer +from gui.windows.multichannel_viewer import MultiChannelWindow +from gui.windows.mask_maker import MaskSpecViewer +from gui.windows.singleStackViewer import * + +cmap_dict = create_color_maps() + +#from . import __version__ + +logger = logging.getLogger() +try: + import cv2 # noqa: F401 +except Exception: + logger.warning("openCV module not found") + pass +if hasattr(QtCore.Qt, "AA_EnableHighDpiScaling"): + QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True) + +if hasattr(QtCore.Qt, "AA_UseHighDpiPixmaps"): + QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True) + +ui_dir = os.path.normpath(os.path.join( + os.path.dirname(os.path.abspath(__file__)), + "gui/layout" +)) + +print(ui_dir) + +# global settings for pyqtgraph plot and image colormaps +pg.setConfigOption("imageAxisOrder", "row-major") + +class midasWindow(QtWidgets.QMainWindow): + def __init__(self, im_stack=None, energy=[], refs=[]): + super(midasWindow, self).__init__() + uic.loadUi(os.path.join(ui_dir, "midasMainwindow.ui"), self) + self.im_stack = im_stack + self.energy = energy + self.refs = refs + self.loaded_tranform_file = [] + self.image_roi2_flag = False + self.refStackAvailable = False + self.isAReload = False + self.plotWidth = 2 + self.stackStatusDict = {} + + self.user_wd = os.path.expanduser("~") + # self.user_config_path = os.path.join(ui_path,"user_config.json") + + # if not os.path.exists(self.user_config_path): + + # with open(f"{self.user_config_path}", "w") as fp: + # json.dump(self.user_config, fp, indent=4) + + self.plt_colors = [ + "g", + "r", + "c", + "m", + "y", + "w", + "b", + pg.mkPen(70, 5, 80), + pg.mkPen(255, 85, 130), + pg.mkPen(0, 85, 130), + pg.mkPen(255, 170, 60), + ] * 3 + # window style + self.actionDarkMode.triggered.connect(self.darkMode) + self.actionDefault.triggered.connect(self.defaultMode) + self.actionModern.triggered.connect(self.modernMode) + + # self.setToolTipsVisible(True) + for menuItem in self.findChildren(QtWidgets.QMenu): + menuItem.setToolTipsVisible(True) + + # plotview options + self.actionWhite.triggered.connect(lambda: self.spectrum_view.setBackground("w")) + self.actionRed.triggered.connect(lambda: self.spectrum_view.setBackground("r")) + self.actionYellow.triggered.connect(lambda: self.spectrum_view.setBackground("y")) + self.actionBlue.triggered.connect(lambda: self.spectrum_view.setBackground("b")) + self.actionBlack.triggered.connect(lambda: self.spectrum_view.setBackground((0, 0, 0))) + + self.actn1.triggered.connect(lambda: self.setPlotLineWidth(int(self.actn1.text()))) + self.actn2.triggered.connect(lambda: self.setPlotLineWidth(int(self.actn2.text()))) + self.actn3.triggered.connect(lambda: self.setPlotLineWidth(int(self.actn3.text()))) + self.actn4.triggered.connect(lambda: self.setPlotLineWidth(int(self.actn4.text()))) + self.actn5.triggered.connect(lambda: self.setPlotLineWidth(int(self.actn5.text()))) + self.actn6.triggered.connect(lambda: self.setPlotLineWidth(int(self.actn6.text()))) + self.actn8.triggered.connect(lambda: self.setPlotLineWidth(int(self.actn8.text()))) + self.actn10.triggered.connect(lambda: self.setPlotLineWidth(int(self.actn10.text()))) + + self.actionOpen_Image_Data.triggered.connect(self.browse_file) + self.actionOpen_Multiple_Files.triggered.connect(self.createVirtualStack) + self.actionSave_as.triggered.connect(lambda: self.save_stack()) + self.actionExit.triggered.connect(lambda: QApplication.closeAllWindows()) + self.actionOpen_in_GitHub.triggered.connect(self.open_github_link) + self.actionLoad_Energy.triggered.connect(self.select_elist) + self.menuFile.setToolTipsVisible(True) + + # Accessories + self.actionOpen_Mask_Gen.triggered.connect(self.openMaskMaker) + self.actionMultiColor.triggered.connect(self.openMultiColorWindow) + + # calculations + self.pb_transpose_stack.clicked.connect(lambda: self.threadMaker(self.transposeStack)) + self.pb_swapXY_stack.clicked.connect(lambda: self.threadMaker(self.swapStackXY)) + self.pb_reset_img.clicked.connect(self.reloadImageStack) + self.pb_crop.clicked.connect(self.crop_to_dim) + self.pb_apply_crop_to_all.clicked.connect(self.apply_crop_to_all) + self.pb_crop.clicked.connect(self.view_stack) + self.sb_scaling_factor.valueChanged.connect(self.view_stack) + self.pb_ref_xanes.clicked.connect(self.select_ref_file) + self.pb_elist_xanes.clicked.connect(self.select_elist) + + # batchjobs + self.actionPlotAllCorrelations.triggered.connect(self.plotCorrelationsAllCombinations) + + [ + uis.valueChanged.connect(self.replot_image) + for uis in [self.hs_smooth_size, self.hs_nsigma, self.hs_bg_threshold] + ] + + [ + uis.stateChanged.connect(self.replot_image) + for uis in [self.cb_remove_bg, self.cb_remove_outliers, self.cb_smooth, self.cb_norm, self.cb_log] + ] + + [ + uis.stateChanged.connect(self.view_stack) + for uis in [self.cb_remove_edges, self.cb_upscale, self.cb_rebin] + ] + + # ToolBar + self.actionStack_Info.triggered.connect(self.displayStackInfo) + self.actionSave_Image.triggered.connect(self.save_disp_img) + self.actionExport_Stack.triggered.connect(lambda: self.save_stack()) + + # ROI background + self.actionSubtract_ROI_BG.triggered.connect(lambda: self.threadMaker(self.removeROIBGStack)) + + # alignment + self.pb_load_align_ref.clicked.connect(self.loadAlignRefImage) + self.pb_loadAlignTranform.clicked.connect(self.importAlignTransformation) + self.pb_saveAlignTranform.clicked.connect(self.exportAlignTransformation) + self.pb_alignStack.clicked.connect(lambda: self.threadMaker(self.stackRegistration)) + # self.pb_alignStack.clicked.connect(self.stackRegistration) + + # save_options + self.actionSave_Sum_Image.triggered.connect(lambda: self.save_stack(method="sum")) + self.actionSave_Mean_Image.triggered.connect(lambda: self.save_stack(method="mean")) + self.actionExport_Image_to_CSV.triggered.connect(self.stackToCSV) + self.pb_save_disp_spec.clicked.connect(self.save_disp_spec) + self.actionSave_Energy_List.triggered.connect(self.saveEnergyList) + self.pb_show_roi.clicked.connect(self.getROIMask) + self.pb_addToCollector.clicked.connect(self.addSpectrumToCollector) + self.pb_collect_clear.clicked.connect(lambda: self.spectrum_view_collect.clear()) + self.pb_saveCollectorPlot.clicked.connect(self.saveCollectorPlot) + + # XANES Normalization + self.pb_apply_xanes_norm.clicked.connect(self.nomalizeLiveSpec) + self.pb_auto_Eo.clicked.connect(self.findEo) + self.pb_xanes_norm_vals.clicked.connect(self.initNormVals) + self.pb_apply_norm_to_stack.clicked.connect(lambda: self.threadMaker(self.normalizeStack)) + self.actionExport_Norm_Params.triggered.connect(self.exportNormParams) + self.actionImport_Norm_Params.triggered.connect(self.importNormParams) + + # Analysis + self.pb_pca_scree.clicked.connect(self.pca_scree_) + self.pb_calc_components.clicked.connect(self.calc_comp_) + self.pb_kmeans_elbow.clicked.connect(self.kmeans_elbow) + self.pb_calc_cluster.clicked.connect(self.clustering_) + self.pb_xanes_fit.clicked.connect(self.fast_xanes_fitting) + self.pb_plot_refs.clicked.connect(self.plt_xanes_refs) + + self.show() + + self.threadpool = QThreadPool() + print(f"Multithreading with maximum {self.threadpool.maxThreadCount()} threads") + + # View Options + def darkMode(self): + self.centralwidget.setStyleSheet(open(os.path.join(ui_dir, "css/darkStyle.css")).read()) + + def defaultMode(self): + self.centralwidget.setStyleSheet(open(os.path.join(ui_dir, "css/defaultStyle.css")).read()) + + def modernMode(self): + self.centralwidget.setStyleSheet(open(os.path.join(ui_dir, "css/modern.css")).read()) + + def setPlotLineWidth(self, width_input): + self.plotWidth = width_input + try: + self.update_spectrum() + except Exception: + pass + + def openMultiColorWindow(self): + self.multicolorwindow = MultiChannelWindow() + self.multicolorwindow.show() + + def openMaskMaker(self): + self.mask_window = MaskSpecViewer(xanes_stack=self.displayedStack, energy=self.energy) + self.mask_window.show() + + def open_github_link(self): + webbrowser.open("https://github.com/pattammattel/NSLS-II-MIDAS/wiki") + + def threadMaker(self, funct): + # Pass the function to execute + worker = Worker(funct) # Any other args, kwargs are passed to the run function + self.loadSplashScreen() + worker.signals.start.connect(self.splash.startAnimation) + worker.signals.result.connect(self.print_output) + + list( + map( + worker.signals.finished.connect, + [ + self.thread_complete, + self.splash.stopAnimation, + self.update_stack_info, + self.update_spectrum, + self.update_image_roi, + self.setImageROI + ], + ) + ) + + # Execute + self.threadpool.start(worker) + + + # File Loading + + def createVirtualStack(self): + """User can load multiple/series of tiff images with same shape. + The 'self.load_stack()' recognizes 'self.filename as list and create the stack. + """ + self.energy = [] + filter = "TIFF (*.tiff);;TIF (*.tif);;all_files (*)" + file_name = QFileDialog() + file_name.setFileMode(QFileDialog.FileMode.ExistingFiles) + names = file_name.getOpenFileNames(self, "Open files", self.user_wd, filter) + if names[0]: + + self.file_name = names[0] + self.user_wd = os.path.dirname(self.file_name[0]) + self.load_stack() + + else: + self.statusbar_main.showMessage("No file has selected") + pass + + def load_stack(self): + + """load the image data from the selected file. + If the the choice is for multiple files stack will be created in a loop. + If single h5 file is selected the unpacking will be done with 'get_xrf_data' function in StackCalcs. + From the h5 the program can recognize the beamline. The exported stack will be normalized to I0. + + If the single tiff file is choosen tf.imread() is used. + + The output 'self.im_stack' is the unmodified data file + """ + + self.log_warning = False # for the Qmessage box in cb_log + self.image_roi2_flag = False + self.cb_log.setChecked(False) + self.cb_remove_edges.setChecked(False) + self.cb_norm.setChecked(False) + self.cb_smooth.setChecked(False) + self.cb_remove_outliers.setChecked(False) + self.cb_remove_bg.setChecked(False) + self.cb_rebin.setChecked(False) + self.cb_upscale.setChecked(False) + self.sb_xrange1.setValue(0) + self.sb_yrange1.setValue(0) + self.sb_zrange1.setValue(0) + + self.menuMask.setEnabled(True) + self.actionLoad_Energy.setEnabled(True) + self.actionSave_Energy_List.setEnabled(True) + self.actionSave_as.setEnabled(True) + + self.sb_zrange2.setMaximum(99999) + self.sb_xrange2.setMaximum(99999) + self.sb_yrange2.setMaximum(99999) + + self.statusbar_main.showMessage("Loading.. please wait...") + + if isinstance(self.file_name, list): + + all_images = [] + + for im_file in self.file_name: + img = tf.imread(im_file) + all_images.append(img) # row major image + self.im_stack = np.dstack(all_images).transpose((2, 0, 1)) + self.avgIo = 1 # I0 is only applicable to XRF h5 files + self.sb_zrange2.setValue(self.im_stack.shape[0]) + + else: + + if self.file_name.endswith(".h5"): + self.im_stack, mono_e, bl_name, self.avgIo = get_xrf_data(self.file_name) + self.statusbar_main.showMessage(f"Data from {bl_name}") + self.sb_zrange2.setValue(mono_e / 10) + self.energy = [] + + elif self.file_name.endswith(".tiff") or self.file_name.endswith(".tif"): + self.im_stack_ = tf.imread(self.file_name) + if self.im_stack_.ndim == 2: + self.im_stack = self.im_stack_.reshape(1, self.im_stack_.shape[0], self.im_stack_.shape[1]) + + else: + self.im_stack = self.im_stack_ + self.sb_zrange2.setValue(self.im_stack.shape[0]) + self.autoEnergyLoader() + self.energyUnitCheck() + self.avgIo = 1 + + else: + logger.error("Unknown data format") + + """ Fill the stack dimensions to the GUI and set the image dimensions as max values. + This prevent user from choosing higher image dimensions during a resizing event""" + + logger.info(f" loaded stack with {np.shape(self.im_stack)} from the file") + + try: + logger.info(f" Transposed to shape: {np.shape(self.im_stack)}") + self.init_dimZ, self.init_dimY, self.init_dimX = self.im_stack.shape + # Remove any previously set max value during a reload + + self.sb_xrange2.setValue(self.init_dimX) + self.sb_yrange2.setValue(self.init_dimY) + + except UnboundLocalError: + logger.error("No file selected") + pass + + self.view_stack() + logger.info("Stack displayed correctly") + self.update_stack_info() + + logger.info(f"completed image shape {np.shape(self.im_stack)}") + + try: + self.statusbar_main.showMessage(f"Loaded: {self.file_name}") + + except AttributeError: + self.statusbar_main.showMessage("New Stack is made from selected tiffs") + pass + + def browse_file(self): + """To open a file widow and choose the data file. + The filename will be used to load data using 'rest and load stack' function""" + + filename = QFileDialog().getOpenFileName( + self, "Select image data", self.user_wd, "image file(*.hdf *.h5 *tiff *tif )" + ) + self.file_name = str(filename[0]) + self.user_wd = os.path.dirname(self.file_name) + + # if user decides to cancel the file window gui returns to original state + if self.file_name: + self.disconnectImageActions() + self.isAReload = False + self.load_stack() + + else: + self.statusbar_main.showMessage("No file has selected") + pass + + def autoEnergyLoader(self): + + dir_, filename_ = os.path.split(self.file_name) + self.efilePath_name = os.path.join(dir_, os.path.splitext(filename_)[0] + ".txt") + self.efilePath_log = os.path.join(dir_, "maps_log_tiff.txt") + + if os.path.isfile(self.efilePath_name): + self.efilePath = self.efilePath_name + self.efileLoader() + self.statusbar_main.showMessage(f"Energy File detected {self.efilePath}") + + elif os.path.isfile(self.efilePath_log): + self.efilePath = self.efilePath_log + self.efileLoader() + self.statusbar_main.showMessage(f"Energy File detected {self.efilePath}") + + else: + self.efilePath = False + self.efileLoader() + + def update_stack_info(self): + z, y, x = np.shape(self.displayedStack) + self.sb_zrange2.setMaximum(z + self.sb_zrange1.value()) + self.sb_xrange2.setValue(x) + self.sb_xrange2.setMaximum(x) + self.sb_yrange2.setValue(y) + self.sb_yrange2.setMaximum(y) + logger.info("Stack info has been updated") + + # Image Transformations + + def crop_to_dim(self): + self.x1, self.x2 = self.sb_xrange1.value(), self.sb_xrange2.value() + self.y1, self.y2 = self.sb_yrange1.value(), self.sb_yrange2.value() + self.z1, self.z2 = self.sb_zrange1.value(), self.sb_zrange2.value() + + try: + self.displayedStack = remove_nan_inf( + self.displayedStack[self.z1 : self.z2, self.y1 : self.y2, self.x1 : self.x2] + ) + except Exception: + self.displayedStack = remove_nan_inf( + self.im_stack[self.z1 : self.z2, self.y1 : self.y2, self.x1 : self.x2] + ) + + def apply_crop_to_all(self): + dir_ = os.path.dirname(self.file_name) + tiffs = glob(dir_+"/*.tiff") + + self.x1, self.x2 = self.sb_xrange1.value(), self.sb_xrange2.value() + self.y1, self.y2 = self.sb_yrange1.value(), self.sb_yrange2.value() + self.z1, self.z2 = self.sb_zrange1.value(), self.sb_zrange2.value() + + #print(tiffs) + save_str = ' ' + for fname in tiffs: + print(fname) + im_array = tf.imread(fname) + im_name = os.path.join(dir_,os.path.basename(fname).split('.')[0]+"_cropped.tiff") + save_path = os.path.relpath(im_name, os.path.expanduser('~')) + if np.ndim(im_array) == 3: + tf.imwrite(im_name, im_array[self.z1 : self.z2, self.y1 : self.y2, self.x1 : self.x2]) + save_str+=f"\n{save_path} cropped from {im_array.shape} to (z,y,x):{self.z1}:{self.z2},{self.y1}:{self.y2},{self.x1}:{self.x2}" + logger.info(f"{save_path} saved") + elif np.ndim(im_array) == 2: + tf.imwrite(im_name, im_array[self.y1 : self.y2, self.x1 : self.x2]) + logger.info(f"{save_path} saved") + save_str+=f"\n{save_path} cropped from {im_array.shape} to (z,y,x):{self.y1}:{self.y2},{self.x1}:{self.x2}" + else: + pass + + print(f"{save_str = }") + + # Get the current date and time + current_datetime = datetime.datetime.now() + formatted_date_time = current_datetime.strftime("%Y-%m-%d_%H-%M-%S") + + # save crop settings + file_name = os.path.join(dir_, f"crop_log_{formatted_date_time}.txt") + + with open(file_name, 'w') as file: + file.write(save_str) + + #print(f"log saved as '{file_name}'") + + def transpose_stack(self): + self.displayedStack = self.displayedStack.T + self.update_spectrum() + self.update_spec_image_roi() + + # Alignement + + def loadAlignRefImage(self): + filename = QFileDialog().getOpenFileName(self, "Image Data", self.user_wd, "*.tiff *.tif") + file_name = str(filename[0]) + self.user_wd = os.path.dirname(file_name) + self.alignRefImage = tf.imread(file_name) + assert self.alignRefImage.shape == self.displayedStack.shape, "Image dimensions do not match" + self.refStackAvailable = True + self.rb_alignRefVoid.setChecked(False) + self.change_color_on_load(self.pb_load_align_ref) + + def stackRegistration(self): + + self.transformations = { + "TRANSLATION": StackReg.TRANSLATION, + "RIGID_BODY": StackReg.RIGID_BODY, + "SCALED_ROTATION": StackReg.SCALED_ROTATION, + "AFFINE": StackReg.AFFINE, + "BILINEAR": StackReg.BILINEAR, + } + + self.transformType = self.transformations[self.cb_alignTransform.currentText()] + self.alignReferenceImage = self.cb_alignRef.currentText() + self.alignRefStackVoid = self.rb_alignRefVoid.isChecked() + self.alignMaxIter = self.sb_maxIterVal.value() + + if self.cb_use_tmatFile.isChecked(): + + if len(self.loaded_tranform_file) > 0: + + self.displayedStack = align_with_tmat( + self.displayedStack, tmat_file=self.loaded_tranform_file, transformation=self.transformType + ) + logger.info("Aligned to the tranform File") + + else: + logger.error("No Tranformation File Loaded") + + elif self.cb_iterAlign.isChecked(): + + if not self.refStackAvailable: + self.alignRefImage = self.displayedStack + else: + pass + + self.displayedStack = align_stack_iter( + self.displayedStack, + ref_stack_void=False, + ref_stack=self.alignRefImage, + transformation=self.transformType, + method=("previous", "first"), + max_iter=self.alignMaxIter, + ) + + else: + if not self.refStackAvailable: + self.alignRefImage = self.displayedStack + + else: + pass + + self.displayedStack, self.tranform_file = align_stack( + self.displayedStack, + ref_image_void=True, + ref_stack=self.alignRefImage, + transformation=self.transformType, + reference=self.alignReferenceImage, + ) + logger.info("New Tranformation file available") + self.im_stack = self.displayedStack + + def exportAlignTransformation(self): + + + + file_name = QFileDialog().getSaveFileName( + self, + "Save Transformation File", + os.path.join(self.user_wd,"TranformationMatrix.npy"), + "text file (*.npy)" + ) + if file_name[0]: + np.save(file_name[0], self.tranform_file) + self.user_wd = os.path.dirname(file_name[0]) + else: + pass + + def importAlignTransformation(self): + file_name = QFileDialog().getOpenFileName(self, "Open Transformation File", self.user_wd, "text file (*.npy)") + if file_name[0]: + self.loaded_tranform_file = np.load(file_name[0]) + self.cb_use_tmatFile.setChecked(True) + self.user_wd = os.path.dirname(file_name[0]) + logger.info("Transformation File Loaded") + else: + pass + + def loadSplashScreen(self): + self.splash = LoadingScreen() + + px = self.geometry().x() + py = self.geometry().y() + ph = self.geometry().height() + pw = self.geometry().width() + dw = self.splash.width() + dh = self.splash.height() + new_x, new_y = px + (0.5 * pw) - dw, py + (0.5 * ph) - dh + self.splash.setGeometry(int(new_x), int(new_y), int(dw), int(dh)) + + self.splash.show() + + def reloadImageStack(self): + self.isAReload = True + self.load_stack() + + def update_stack(self): + self.displayedStack = self.im_stack + self.crop_to_dim() + + if self.cb_rebin.isChecked(): + self.cb_upscale.setChecked(False) + self.sb_scaling_factor.setEnabled(True) + self.displayedStack = resize_stack(self.displayedStack, scaling_factor=self.sb_scaling_factor.value()) + self.update_stack_info() + + elif self.cb_upscale.isChecked(): + self.cb_rebin.setChecked(False) + self.sb_scaling_factor.setEnabled(True) + self.displayedStack = resize_stack( + self.displayedStack, upscaling=True, scaling_factor=self.sb_scaling_factor.value() + ) + self.update_stack_info() + + if self.cb_remove_outliers.isChecked(): + self.hs_nsigma.setEnabled(True) + nsigma = self.hs_nsigma.value() / 10 + self.displayedStack = remove_hot_pixels(self.displayedStack, NSigma=nsigma) + self.label_nsigma.setText(str(nsigma)) + logger.info(f"Removing Outliers with NSigma {nsigma}") + + elif self.cb_remove_outliers.isChecked() is False: + self.hs_nsigma.setEnabled(False) + + if self.cb_remove_edges.isChecked(): + self.displayedStack = remove_edges(self.displayedStack) + logger.info(f"Removed edges, new shape {self.displayedStack.shape}") + self.update_stack_info() + + if self.cb_remove_bg.isChecked(): + self.hs_bg_threshold.setEnabled(True) + logger.info("Removing background") + bg_threshold = self.hs_bg_threshold.value() + self.label_bg_threshold.setText(str(bg_threshold) + "%") + self.displayedStack = clean_stack(self.displayedStack, auto_bg=False, bg_percentage=bg_threshold) + + elif self.cb_remove_bg.isChecked() is False: + self.hs_bg_threshold.setEnabled(False) + + if self.cb_log.isChecked(): + + self.displayedStack = remove_nan_inf(np.log10(self.displayedStack)) + logger.info("Log Stack is in use") + + if self.cb_smooth.isChecked(): + self.hs_smooth_size.setEnabled(True) + window = self.hs_smooth_size.value() + if window % 2 == 0: + window = +1 + self.smooth_winow_size.setText("Window size: " + str(window)) + self.displayedStack = smoothen(self.displayedStack, w_size=window) + logger.info("Spectrum Smoothening Applied") + + elif self.cb_smooth.isChecked() is False: + self.hs_smooth_size.setEnabled(False) + + if self.cb_norm.isChecked(): + logger.info("Normalizing spectra") + self.displayedStack = normalize(self.displayedStack, norm_point=-1) + + logger.info("Updated image is in use") + + # ImageView + + def view_stack(self): + + if not self.im_stack.ndim == 3: + raise ValueError("stack should be an ndarray with ndim == 3") + else: + self.update_stack() + # self.StackUpdateThread() + + try: + self.image_view.removeItem(self.image_roi_math) + except Exception: + pass + + (self.dim1, self.dim2, self.dim3) = self.displayedStack.shape + self.image_view.setImage(self.displayedStack) + self.image_view.ui.menuBtn.hide() + self.image_view.ui.roiBtn.hide() + self.image_view.setPredefinedGradient("viridis") + self.image_view.setCurrentIndex(self.dim1 // 2) + if len(self.energy) == 0: + self.energy = np.arange(self.z1, self.z2) * 10 + logger.info("Arbitary X-axis used in the plot for XANES") + self.sz = np.max( + [int(self.dim2 * 0.1), int(self.dim3 * 0.1)] + ) # size of the roi set to be 10% of the image area + + self.stack_center = self.energy[len(self.energy) // 2] + self.stack_width = (self.energy.max() - self.energy.min()) // 10 + self.spec_roi = pg.LinearRegionItem( + values=(self.stack_center - self.stack_width, self.stack_center + self.stack_width) + ) + + # a second optional ROI for calculations follow + self.image_roi_math = pg.PolyLineROI( + [[0, 0], [0, self.sz], [self.sz, self.sz], [self.sz, 0]], + pos=(int(self.dim3 // 3), int(self.dim2 // 3)), + pen="r", + closed=True, + removable=True, + ) + + self.spec_roi_math = pg.LinearRegionItem( + values=(self.stack_center - self.stack_width - 10, self.stack_center + self.stack_width - 10), + pen="r", + brush=QtGui.QColor(0, 255, 200, 50), + ) + self.spec_lo_m_idx = self.spec_hi_m_idx = 0 + + self.setImageROI() + self.update_spectrum() + self.update_image_roi() + + if not self.isAReload: + # image connections + self.image_view.mousePressEvent = self.getPointSpectrum + self.pb_apply_spec_calc.clicked.connect(self.spec_roi_calc) + self.rb_math_roi.clicked.connect(self.update_spectrum) + self.pb_add_roi_2.clicked.connect(self.math_img_roi_flag) + self.image_roi_math.sigRegionChangeFinished.connect(self.image_roi_calc) + self.pb_apply_img_calc.clicked.connect(self.image_roi_calc) + + self.spec_roi.sigRegionChanged.connect(self.update_image_roi) + self.spec_roi_math.sigRegionChangeFinished.connect(self.spec_roi_calc) + + [ + rbs.clicked.connect(self.setImageROI) + for rbs in [self.rb_poly_roi, self.rb_elli_roi, self.rb_rect_roi, self.rb_line_roi, self.rb_circle_roi] + ] + + def disconnectImageActions(self): + for btns in [self.pb_apply_spec_calc, self.rb_math_roi, self.pb_add_roi_2, self.pb_apply_img_calc]: + try: + btns.disconnect() + except Exception: + pass + + def select_elist(self): + self.energyFileChooser() + self.efileLoader() + self.energyUnitCheck() + self.view_stack() + + def efileLoader(self): + + if self.efilePath: + + if str(self.efilePath).endswith("log_tiff.txt"): + self.energy = energy_from_logfile(logfile=str(self.efilePath)) + logger.info("Log file from pyxrf processing") + + else: + self.energy = np.loadtxt(str(self.efilePath)) + self.change_color_on_load(self.pb_elist_xanes) + logger.info("Energy file loaded") + + else: + self.statusbar_main.showMessage("No Energy List Selected, Setting Arbitary Axis") + self.energy = np.arange(self.im_stack.shape[0]) + logger.info("Arbitary Energy Axis") + + # assert len(self.energy) == self.dim1, "Number of Energy Points is not equal to stack length" + + def energyUnitCheck(self): + + if np.max(self.energy) < 100: + self.cb_kev_flag.setChecked(True) + self.energy *= 1000 + + else: + self.cb_kev_flag.setChecked(False) + + def select_ref_file(self): + self.pb_xanes_fit.setEnabled(True) + self.ref_names = [] + file_name = QFileDialog().getOpenFileName(self, "Open reference file", self.user_wd, "text file (*.csv *.nor)") + if file_name[0]: + if file_name[0].endswith(".nor"): + self.refs, self.ref_names = create_df_from_nor_try2(athenafile=file_name[0]) + self.change_color_on_load(self.pb_ref_xanes) + + elif file_name[0].endswith(".csv"): + self.refs = pd.read_csv(file_name[0]) + self.ref_names = list(self.refs.keys()) + + self.change_color_on_load(self.pb_ref_xanes) + + self.user_wd = os.path.dirname(file_name[0]) + + else: + logger.error("No file selected") + pass + + logger.info(f"{self.refs.shape = }") + + self.plt_xanes_refs() + + def plt_xanes_refs(self): + + try: + self.ref_plot.close() + except Exception: + pass + + self.ref_plot = plot(title="Reference Standards") + self.ref_plot.setLabel("bottom", "Energy") + self.ref_plot.setLabel("left", "Intensity") + self.ref_plot.addLegend() + + for n in range(np.shape(self.refs)[1]): + + if not n == 0: + self.ref_plot.plot( + self.refs.values[:, 0], + self.refs.values[:, n], + pen=pg.mkPen(self.plt_colors[n - 1], width=self.plotWidth), + name=self.ref_names[n], + ) + + def getPointSpectrum(self, event): + if event.type() == QtCore.QEvent.Type.MouseButtonDblClick: + if event.button() == QtCore.Qt.MouseButton.LeftButton: + self.xpixel = int(self.image_view.view.mapSceneToView(event.pos().toPointF()).x()) - 1 + zlim, ylim, xlim = self.displayedStack.shape + + if self.xpixel > xlim: + self.xpixel = xlim - 1 + + self.ypixel = int(self.image_view.view.mapSceneToView(event.pos().toPointF()).y()) - 1 + if self.ypixel > ylim: + self.ypixel = ylim - 1 + self.spectrum_view.addLegend() + self.point_spectrum = self.displayedStack[:, self.ypixel, self.xpixel] + self.spectrum_view.plot( + self.xdata, + self.point_spectrum, + clear=True, + pen=pg.mkPen(pg.mkColor(0, 0, 255, 255), width=self.plotWidth), + symbol="o", + symbolSize=6, + symbolBrush="r", + name=f"Point Spectrum; x= {self.xpixel}, y= {self.ypixel}", + ) + + self.spectrum_view.addItem(self.spec_roi) + + self.statusbar_main.showMessage(f"{self.xpixel} and {self.ypixel}") + + def setImageROI(self): + + self.lineROI = pg.LineSegmentROI([[int(self.dim3 // 2), int(self.dim2 // 2)], [self.sz, self.sz]], pen="r") + + self.rectROI = pg.RectROI( + [int(self.dim3 // 2), int(self.dim2 // 2)], + [self.sz, self.sz], + pen="w", + maxBounds=QtCore.QRectF(0, 0, self.dim3, self.dim2), + ) + + self.rectROI.addTranslateHandle([0, 0], [2, 2]) + self.rectROI.addRotateHandle([0, 1], [2, 2]) + + self.ellipseROI = pg.EllipseROI( + [int(self.dim3 // 2), int(self.dim2 // 2)], + [self.sz, self.sz], + pen="w", + maxBounds=QtCore.QRectF(0, 0, self.dim3, self.dim2), + ) + + self.circleROI = pg.CircleROI( + [int(self.dim3 // 2), int(self.dim2 // 2)], + [self.sz, self.sz], + pen="w", + maxBounds=QtCore.QRectF(0, 0, self.dim3, self.dim2), + ) # pos and size + + self.polyLineROI = pg.PolyLineROI( + [[0, 0], [0, self.sz], [self.sz, self.sz], [self.sz, 0]], + pos=(int(self.dim3 // 2), int(self.dim2 // 2)), + maxBounds=QtCore.QRectF(0, 0, self.dim3, self.dim2), + closed=True, + removable=True, + ) + + self.rois = { + "rb_line_roi": self.lineROI, + "rb_rect_roi": self.rectROI, + "rb_circle_roi": self.circleROI, + "rb_elli_roi": self.ellipseROI, + "rb_poly_roi": self.polyLineROI, + } + + button_name = self.sender() + + if button_name.objectName() in self.rois.keys(): + self.roi_preference = button_name.objectName() + + else: + self.roi_preference = "rb_rect_roi" # default + + try: + self.image_view.removeItem(self.image_roi) + + except Exception: + pass + + # ROI settings for image, used polyline roi with non rectangular shape + + self.image_roi = self.rois[self.roi_preference] + self.image_view.addItem(self.image_roi) + self.image_roi.sigRegionChanged.connect(self.update_spectrum) + + def replot_image(self): + self.update_stack() + self.update_spectrum() + self.update_image_roi() + + def update_spec_roi_values(self): + self.stack_center = int(self.energy[len(self.energy) // 2]) + self.stack_width = int((self.energy.max() - self.energy.min()) * 0.05) + self.spec_roi.setBounds([self.xdata[0], self.xdata[-1]]) # if want to set bounds for the spec roi + self.spec_roi_math.setBounds([self.xdata[0], self.xdata[-1]]) + + def update_spectrum(self): + + # set x-axis values; array taken from energy values, if clipped z box values will update the array + self.xdata = self.energy[self.sb_zrange1.value() : self.sb_zrange2.value()] + + # get the cropped stack from ROI region; pyqtgraph function is used + self.roi_img_stk = self.image_roi.getArrayRegion( + self.displayedStack, self.image_view.imageItem, axes=(1, 2) + ) + + posx, posy = self.image_roi.pos() + self.le_roi.setText(str(int(posx)) + ":" + str(int(posy))) + + # display the ROI features in the line edit boxes + if self.roi_img_stk.ndim == 3: + sizex, sizey = self.roi_img_stk.shape[1], self.roi_img_stk.shape[2] + self.le_roi_size.setText(str(sizex) + "," + str(sizey)) + self.mean_spectra = get_mean_spectra(self.roi_img_stk) + + elif self.roi_img_stk.ndim == 2: + sizex, sizey = self.roi_img_stk.shape[0], self.roi_img_stk.shape[1] + self.le_roi_size.setText(str(sizex) + "," + str(sizey)) + self.mean_spectra = self.roi_img_stk.mean(-1) + + self.spectrum_view.addLegend() + + try: + self.spectrum_view.plot( + self.xdata, + self.mean_spectra, + pen=pg.mkPen(pg.mkColor(5, 255, 5, 255), width=self.plotWidth), + clear=True, + symbol="o", + symbolSize=6, + symbolBrush="r", + name="ROI Spectrum", + ) + except Exception: + self.spectrum_view.plot( + self.mean_spectra, + clear=True, + pen=pg.mkPen(pg.mkColor(5, 255, 5, 255), width=self.plotWidth), + symbol="o", + symbolSize=6, + symbolBrush="r", + name="ROI Spectrum", + ) + + if self.energy[-1] > 1000: + self.e_unit = "eV" + else: + self.e_unit = "keV" + + self.spectrum_view.setLabel("bottom", "Energy", self.e_unit) + self.spectrum_view.setLabel("left", "Intensity", "A.U.") + self.spectrum_view.addItem(self.spec_roi) + self.update_spec_roi_values() + self.math_roi_flag() + + def update_image_roi(self): + self.spec_lo, self.spec_hi = self.spec_roi.getRegion() + self.spec_lo_idx = (np.abs(self.energy - self.spec_lo)).argmin() + self.spec_hi_idx = (np.abs(self.energy - self.spec_hi)).argmin() + self.le_spec_roi.setText(str(int(self.spec_lo)) + ":" + str(int(self.spec_hi))) + self.le_spec_roi_size.setText(str(int(self.spec_hi - self.spec_lo))) + self.update_spec_roi_values() + self.stackIndexToNames() + + try: + if int(self.spec_lo_idx) == int(self.spec_hi_idx): + self.disp_img = self.displayedStack[int(self.spec_hi_idx), :, :] + + else: + self.disp_img = self.displayedStack[int(self.spec_lo_idx) : int(self.spec_hi_idx), :, :].mean(0) + + self.image_view.setImage(self.disp_img) + self.statusbar_main.showMessage(f"Image Display is {self.corrImg1}") + except Exception: + logger.warning("Indices are out of range; Image cannot be created") + pass + + def set_spec_roi(self): + self.spec_lo_, self.spec_hi_ = int(self.sb_roi_spec_s.value()), int(self.sb_roi_spec_e.value()) + self.spec_lo_idx_ = (np.abs(self.energy - self.spec_lo_)).argmin() + self.spec_hi_idx_ = (np.abs(self.energy - self.spec_hi_)).argmin() + self.spec_roi.setRegion((self.xdata[self.spec_lo_idx_], self.xdata[self.spec_hi_idx_])) + self.update_image_roi() + + def math_roi_flag(self): + if self.rb_math_roi.isChecked(): + self.rb_math_roi.setStyleSheet("color : green") + self.spectrum_view.addItem(self.spec_roi_math) + else: + self.spectrum_view.removeItem(self.spec_roi_math) + + def spec_roi_calc(self): + + self.spec_lo_m, self.spec_hi_m = self.spec_roi_math.getRegion() + self.spec_lo_m_idx = (np.abs(self.energy - self.spec_lo_m)).argmin() + self.spec_hi_m_idx = (np.abs(self.energy - self.spec_hi_m)).argmin() + + if int(self.spec_lo_idx) == int(self.spec_hi_idx): + self.img1 = self.displayedStack[int(self.spec_hi_idx), :, :] + + else: + self.img1 = self.displayedStack[int(self.spec_lo_idx) : int(self.spec_hi_idx), :, :].mean(0) + + if int(self.spec_lo_m_idx) == int(self.spec_hi_m_idx): + self.img2 = self.displayedStack[int(self.spec_hi_m_idx), :, :] + + else: + self.img2 = self.displayedStack[int(self.spec_lo_m_idx) : int(self.spec_hi_m_idx), :, :].mean(0) + + if self.cb_roi_operation.currentText() == "Correlation Plot": + self.correlation_plot() + + else: + calc = {"Divide": np.divide, "Subtract": np.subtract, "Add": np.add} + self.disp_img = remove_nan_inf(calc[self.cb_roi_operation.currentText()](self.img1, self.img2)) + self.image_view.setImage(self.disp_img) + + def math_img_roi_flag(self): + + button_name = self.sender().text() + logger.info(f"{button_name}") + if button_name == "Add ROI_2": + self.image_view.addItem(self.image_roi_math) + self.pb_add_roi_2.setText("Remove ROI_2") + self.image_roi2_flag = 1 + elif button_name == "Remove ROI_2": + self.image_view.removeItem(self.image_roi_math) + self.pb_add_roi_2.setText("Add ROI_2") + self.image_roi2_flag = 0 + + else: + pass + logger.error("Unknown signal for second ROI") + + def image_roi_calc(self): + + if self.image_roi2_flag == 1: + self.calc = {"Divide": np.divide, "Subtract": np.subtract, "Add": np.add} + self.update_spec_image_roi() + else: + logger.error("No ROI2 found") + return + + def update_spec_image_roi(self): + + self.math_roi_reg = self.image_roi_math.getArrayRegion( + self.displayedStack, self.image_view.imageItem, axes=(1, 2) + ) + if self.math_roi_reg.ndim == 3: + + self.math_roi_spectra = get_mean_spectra(self.math_roi_reg) + + elif self.roi_img_stk.ndim == 2: + self.math_roi_spectra = self.math_roi_reg.mean(-1) + + if self.cb_img_roi_action.currentText() in self.calc.keys(): + + calc_spec = self.calc[self.cb_img_roi_action.currentText()](self.mean_spectra, self.math_roi_spectra) + self.spectrum_view.addLegend() + self.spectrum_view.plot( + self.xdata, + calc_spec, + clear=True, + pen=pg.mkPen("m", width=2), + name=self.cb_img_roi_action.currentText() + "ed", + ) + self.spectrum_view.plot(self.xdata, self.math_roi_spectra, pen=pg.mkPen("y", width=2), name="ROI2") + self.spectrum_view.plot(self.xdata, self.mean_spectra, pen=pg.mkPen("g", width=2), name="ROI1") + + elif self.cb_img_roi_action.currentText() == "Compare": + self.spectrum_view.plot( + self.xdata, self.math_roi_spectra, pen=pg.mkPen("y", width=2), clear=True, name="ROI2" + ) + self.spectrum_view.plot(self.xdata, self.mean_spectra, pen=pg.mkPen("g", width=2), name="ROI1") + + self.spectrum_view.addItem(self.spec_roi) + + def displayStackInfo(self): + + try: + + if isinstance(self.file_name, list): + info = f"Folder; {os.path.dirname(self.file_name[0])} \n" + for n, name in enumerate(self.file_name): + info += f"{n}: {os.path.basename(name)} \n" + + # info = f'Stack order; {[name for name in enumerate(self.file_name)]}' + else: + info = f"Stack; {self.file_name}" + + self.infoWindow = StackInfo(str(info)) + self.infoWindow.show() + + except AttributeError: + self.statusbar_main.showMessage("Warning: No Image Data Loaded") + + def stackIndexToNames(self): + # create list of tiff file names for virtutal stack for plot axes + self.elemFileName = [] + + if isinstance(self.file_name, list): + for name in self.file_name: + self.elemFileName.append(os.path.basename(name).split(".")[0]) + + logger.info(f" Virtual Stack - list of image names; {self.elemFileName}") + + # if the roi focus on one frame, Note that this slicing excludes the last index + if int(self.spec_lo_idx) == int(self.spec_hi_idx): + self.corrImg1 = str(self.elemFileName[int(self.spec_lo_idx)]) + else: + self.corrImg1 = self.elemFileName[int(self.spec_lo_idx) : int(self.spec_hi_idx)] + if len(self.corrImg1) > 1: + self.corrImg1 = f"Sum of {self.corrImg1} " + + if int(self.spec_lo_m_idx) == int(self.spec_hi_m_idx): + self.corrImg2 = str(self.elemFileName[int(self.spec_lo_m_idx)]) + + else: + self.corrImg2 = self.elemFileName[int(self.spec_lo_m_idx) : int(self.spec_hi_m_idx)] + + if len(self.corrImg2) > 1: + self.corrImg2 = f"Sum of {self.corrImg2}" + + logger.info( + f"Correlation stack {int(self.spec_lo_idx)}:{int(self.spec_hi_idx)} with " + f"{int(self.spec_lo_m_idx)}:{int(self.spec_hi_m_idx)}" + ) + + logger.info(f" Virtual Stack; corrlation plot of {self.corrImg1} vs {self.corrImg2}") + else: + self.corrImg1 = ( + f" Sum of {os.path.basename(self.file_name).split('.')[0]}_{int(self.spec_lo_idx)} " + f"to {int(self.spec_hi_idx)}" + ) + self.corrImg2 = ( + f" Sum of {os.path.basename(self.file_name).split('.')[0]}_{int(self.spec_lo_m_idx)} " + f"to {int(self.spec_hi_m_idx)}" + ) + # logger.info(f" corrlation plot of {self.corrImg1} vs {self.corrImg2}") + + def stackToCSV(self): + + self.stackIndexToNames() + self.imageDf = pd.DataFrame() + if len(self.elemFileName) == len(self.displayedStack): + for name, image in zip(self.elemFileName, self.displayedStack): + self.imageDf[f'{name}'] = image.flatten() + # print(self.imageDf.head()) + else: + self.imageDf = image_to_pandas2(self.displayedStack) + + file_name = QFileDialog().getSaveFileName(self, + "Save CSV Data", + os.path.join(self.user_wd,'image_2DArray.csv'), + 'file (*csv)') + if file_name[0]: + self.imageDf.to_csv(path_or_buf=file_name[0]) + self.user_wd = os.path.dirname(file_name[0]) + self.statusbar_main.showMessage(f"Data saved to {file_name[0]}") + else: + pass + + def correlation_plot(self): + self.stackIndexToNames() + + self.statusbar_main.showMessage(f"Correlation of {self.corrImg1} with {self.corrImg2}") + + if self.rb_roiRegionOnly.isChecked(): + self.roi_mask = self.image_roi.getArrayRegion( + self.displayedStack, self.image_view.imageItem, axes=(1, 2) + ) + self.roi_img1 = np.mean(self.roi_mask[int(self.spec_lo_idx) : int(self.spec_hi_idx)], axis=0) + self.roi_img2 = np.mean(self.roi_mask[int(self.spec_lo_m_idx) : int(self.spec_hi_m_idx)], axis=0) + self.scatter_window = ScatterPlot( + self.roi_img1, self.roi_img2, (str(self.corrImg1), str(self.corrImg2)) + ) + + else: + + self.scatter_window = ScatterPlot(self.img1, self.img2, (str(self.corrImg1), str(self.corrImg2))) + + self.scatter_window.show() + + def plotCorrelationsAllCombinations(self): + + print("Plotting all correlations") + self.stackIndexToNames() + allElemCombNum = list(combinations(np.arange(len(self.elemFileName)), 2)) + + self.scW1 = self.scW2 = self.scW3 = self.scW4 = self.scW5 = None + self.scW6 = self.scW7 = self.scW8 = self.scW9 = self.scW10 = None + + self.scWindowList = [ + self.scW1, + self.scW2, + self.scW3, + self.scW4, + self.scW5, + self.scW6, + self.scW7, + self.scW8, + self.scW9, + self.scW10, + ] + self.scWindowDict = { + 1: self.scW1, + 2: self.scW2, + 3: self.scW3, + 4: self.scW4, + 5: self.scW5, + 6: self.scW6, + 7: self.scW7, + 8: self.scW8, + 9: self.scW9, + 10: self.scW10, + } + + if len(allElemCombNum) > len(self.scWindowDict): + + reply = QMessageBox.warning( + self, + "Plot Window Limit", + f"The number of combination exceeds " + f"maxiumum number of " + f"plot windows. First {len(self.scWindowDict)} " + f"combinations will be plotted. \n Proceed?", + QMessageBox.Yes | QMessageBox.No, + QMessageBox.No, + ) + + if reply == QMessageBox.Yes: + + for i, pair in enumerate(allElemCombNum): + im1 = self.displayedStack[pair[0]] + im2 = self.displayedStack[pair[1]] + im1Name = self.elemFileName[pair[0]] + im2Name = self.elemFileName[pair[1]] + + self.scWindowDict[i] = ScatterPlot(im1, im2, (str(im1Name), str(im2Name))) + self.scWindowDict[i].show() + + if reply == QMessageBox.No: + return + + else: + + for i, pair in enumerate(allElemCombNum): + im1 = self.displayedStack[pair[0]] + im2 = self.displayedStack[pair[1]] + im1Name = self.elemFileName[pair[0]] + im2Name = self.elemFileName[pair[1]] + + self.scWindowDict[i] = ScatterPlot(im1, im2, (str(im1Name), str(im2Name))) + self.scWindowDict[i].show() + + def getROIMask(self): + self.roi_mask = self.image_roi.getArrayRegion(self.displayedStack, self.image_view.imageItem, axes=(1, 2)) + self.newWindow = singleStackViewer(self.roi_mask) + self.newWindow.show() + + def save_stack(self, method="raw"): + + # self.update_stack() + file_name = QFileDialog().getSaveFileName( + self, + "Save image data", + os.path.join(self.user_wd,"image_data.tiff"), + "image file(*tiff *tif )" + ) + if file_name[0]: + if method == "raw": + + tf.imwrite(file_name[0], self.displayedStack) + logger.info(f"Updated Image Saved: {file_name[0]}") + self.statusbar_main.showMessage(f"Updated Image Saved: {file_name[0]}") + elif method == "sum": + tf.imwrite(file_name[0], np.sum(self.displayedStack, axis=0)) + + elif method == "mean": + tf.imwrite(file_name[0], np.mean(self.displayedStack, axis=0)) + + self.user_wd = os.path.dirname(file_name[0]) + + else: + self.statusbar_main.showMessage("Saving cancelled") + logger.info(f"Save failed: {file_name[0]}") + pass + + def save_disp_img(self): + file_name = QFileDialog().getSaveFileName(self, + "Save image data", + os.path.join(self.user_wd,"image.tiff"), + "image file(*tiff *tif )") + if file_name[0]: + tf.imwrite(file_name[0], self.disp_img) + self.statusbar_main.showMessage(f"Image Saved to {file_name[0]}") + self.user_wd = os.path.dirname(file_name[0]) + logger.info(f"Updated Image Saved: {file_name[0]}") + + else: + logger.error("No file to save") + self.statusbar_main.showMessage("Saving cancelled") + pass + + def getLivePlotData(self): + try: + + data = np.squeeze([c.getData() for c in self.spectrum_view.plotItem.curves]) + # print(np.shape(data)) + if data.ndim == 2: + self.mu_ = data[1] + self.e_ = data[0] + elif data.ndim == 3: + e_mu = data[0, :, :] + self.mu_ = e_mu[1] + self.e_ = e_mu[0] + + else: + logger.error(f" Data shape of {data.ndim} is not supported") + pass + except AttributeError: + logger.error("No data loaded") + pass + + def addSpectrumToCollector(self): + self.getLivePlotData() + self.spectrum_view_collect.plot(self.e_, self.mu_, name="ROI Spectrum") + self.spectrum_view_collect.setLabel("bottom", "Energy", self.e_unit) + self.spectrum_view_collect.setLabel("left", "Intensity", "A.U.") + + def findEo(self): + try: + self.getLivePlotData() + e0_init = self.e_[np.argmax(np.gradient(self.mu_))] + self.dsb_norm_Eo.setValue(e0_init) + + except AttributeError: + logger.error("No data loaded") + pass + + def initNormVals(self): + self.getLivePlotData() + e0_init = self.e_[np.argmax(np.gradient(self.mu_))] + pre1, pre2, post1, post2 = xanesNormalization( + self.e_, + self.mu_, + e0=e0_init, + nnorm=1, + nvict=0, + ) + self.dsb_norm_pre1.setValue(pre1) + self.dsb_norm_pre2.setValue(pre2) + self.dsb_norm_post1.setValue(post1) + self.dsb_norm_post2.setValue(post2) + self.dsb_norm_Eo.setValue(e0_init) + + def getNormParams(self): + self.getLivePlotData() + eo_ = self.dsb_norm_Eo.value() + pre1_, pre2_ = self.dsb_norm_pre1.value(), self.dsb_norm_pre2.value() + norm1_, norm2_ = self.dsb_norm_post1.value(), self.dsb_norm_post2.value() + norm_order = self.sb_norm_order.value() + + return eo_, pre1_, pre2_, norm1_, norm2_, norm_order + + def exportNormParams(self): + self.xanesNormParam = {} + eo_, pre1_, pre2_, norm1_, norm2_, norm_order = self.getNormParams() + self.xanesNormParam["E0"] = eo_ + self.xanesNormParam["pre1"] = pre1_ + self.xanesNormParam["pre2"] = pre2_ + self.xanesNormParam["post1"] = norm1_ + self.xanesNormParam["post2"] = norm2_ + self.xanesNormParam["norm_order"] = norm_order + + file_name = QtWidgets.QFileDialog().getSaveFileName( + self, + "Save XANES Norm Params", + os.path.join(self.user_wd,"xanes_norm_params.csv"), + "csv file(*csv)" + ) + if file_name[0]: + pd.DataFrame(self.xanesNormParam, index=[0]).to_csv(file_name[0]) + self.user_wd = os.path.dirname(file_name[0]) + + else: + pass + + def importNormParams(self): + + file_name = QtWidgets.QFileDialog().getOpenFileName( + self, "Open a XANES Norm File", self.user_wd, "csv file(*csv);;all_files (*)" + ) + + if file_name[0]: + xanesNormParam = pd.read_csv(file_name[0]) + self.dsb_norm_Eo.setValue(xanesNormParam["E0"]) + self.dsb_norm_pre1.setValue(xanesNormParam["pre1"]) + self.dsb_norm_pre2.setValue(xanesNormParam["pre2"]) + self.dsb_norm_post1.setValue(xanesNormParam["post1"]) + self.dsb_norm_post2.setValue(xanesNormParam["post2"]) + self.sb_norm_order.setValue(xanesNormParam["norm_order"]) + self.user_wd = os.path.dirname(file_name[0]) + + def nomalizeLiveSpec(self): + eo_, pre1_, pre2_, norm1_, norm2_, norm_order = self.getNormParams() + self.spectrum_view.clear() + colors = np.array(("c", "r", "m")) + + if self.cb_mback.isChecked(): + pass + # f2, normXANES = xanesNormalization( + # self.e_, + # self.mu_, + # e0=eo_, + # nnorm=norm_order, + # nvict=0, + # pre1=pre1_, + # pre2=pre2_, + # norm1=norm1_, + # norm2=norm2_, + # useFlattened=self.cb_xanes_flat.isChecked(), + # ) + + # names = np.array(("matched mu(E)", "f2")) + # data_array = np.array((normXANES, f2)) + + else: + pre_line, post_line, normXANES = xanesNormalization( + self.e_, + self.mu_, + e0=eo_, + nnorm=norm_order, + nvict=0, + pre1=pre1_, + pre2=pre2_, + norm1=norm1_, + norm2=norm2_, + useFlattened=self.cb_xanes_flat.isChecked() + ) + + names = np.array(("Spectrum", "Pre", "Post")) + data_array = np.array((self.mu_, pre_line, post_line)) + + + for data, clr, name in zip(data_array, colors, names): + self.spectrum_view.plot(self.e_, data, pen=pg.mkPen(clr, width=self.plotWidth), name=name) + + self.spectrum_view_norm.plot( + self.e_, normXANES, clear=True, pen=pg.mkPen(self.plt_colors[-1], width=self.plotWidth)) + + self.spectrum_view_norm.setLabel("bottom", "Energy", self.e_unit) + self.spectrum_view_norm.setLabel("left", "Norm. Intensity", "A.U.") + + def normalizeStack(self): + self.getLivePlotData() + eo_, pre1_, pre2_, norm1_, norm2_, norm_order = self.getNormParams() + + self.im_stack = self.displayedStack = xanesNormStack( + self.e_, + self.displayedStack, + e0=eo_, + step=None, + nnorm=norm_order, + nvict=0, + pre1=pre1_, + pre2=pre2_, + norm1=norm1_, + norm2=norm2_, + useFlattened=self.cb_xanes_flat.isChecked(), + ignorePostEdgeNorm=self.cb_xanes_postedge.isChecked() + ) + # self.im_stack = self.displayedStack + + def transposeStack(self): + self.im_stack = self.displayedStack = np.transpose(self.displayedStack, (2, 1, 0)) + + def swapStackXY(self): + self.im_stack = self.displayedStack = np.transpose(self.displayedStack, (0, 2, 1)) + + def removeROIBGStack(self): + self.displayedStack = subtractBackground(self.displayedStack, self.mean_spectra) + + def resetCollectorSpec(self): + pass + + def saveCollectorPlot(self): + exporter = pg.exporters.CSVExporter(self.spectrum_view_collect.plotItem) + #exporter.parameters()["columnMode"] = "(x,y,y,y) for all plots" + file_name = QFileDialog().getSaveFileName(self, "save spectra", self.user_wd, "spectra (*csv)") + if file_name[0]: + exporter.export(file_name[0] + ".csv") + self.user_wd = os.path.dirname(file_name[0]) + else: + self.statusbar_main.showMessage("Saving cancelled") + pass + + def save_disp_spec(self): + + exporter = pg.exporters.CSVExporter(self.spectrum_view.plotItem) + #exporter.parameters()["columnMode"] = "(x,y,y,y) for all plots" + file_name = QFileDialog().getSaveFileName(self, + "save spectrum", + os.path.join(self.user_wd,"spectrum.csv"), + "spectra (*csv)") + if file_name[0]: + exporter.export(file_name[0] + ".csv") + self.user_wd = os.path.dirname(file_name[0]) + else: + self.statusbar_main.showMessage("Saving cancelled") + pass + + def saveEnergyList(self): + file_name = QFileDialog().getSaveFileName(self, + "save energy list", + os.path.join(self.user_wd,"energy_list.txt"), + "text file (*txt)") + if file_name[0]: + np.savetxt(file_name[0], self.xdata, fmt="%.4f") + self.user_wd = os.path.dirname(file_name[0]) + else: + pass + + def pca_scree_(self): + logger.info("Process started..") + self.update_stack() + var = pca_scree(self.displayedStack) + + pca_scree_plot = pg.plot( + var[:24], title="Scree Plot", pen=pg.mkPen("y", width=2, style=QtCore.Qt.DotLine), symbol="o" + ) + pca_scree_plot.addLine(y=0) + pca_scree_plot.setLabel("bottom", "Component Number") + pca_scree_plot.setLabel("left", "Singular Values") + + logger.info("Process complete") + + def calc_comp_(self): + + logger.info("Process started..") + + # self.update_stack() + n_components = self.sb_ncomp.value() + method_ = self.cb_comp_method.currentText() + + ims, comp_spec, decon_spec, decomp_map = decompose_stack( + self.displayedStack, decompose_method=method_, n_components_=n_components + ) + + self._new_window3 = ComponentViewer(ims, self.xdata, comp_spec, decon_spec, decomp_map) + self._new_window3.show() + + logger.info("Process complete") + + def kmeans_elbow(self): + logger.info("Process started..") + # self.update_stack() + + with pg.BusyCursor(): + try: + clust_n, var = kmeans_variance(self.displayedStack) + kmeans_var_plot = pg.plot( + clust_n, var, title="KMeans Variance", pen=pg.mkPen("y", width=2, style=QtCore.Qt.DotLine), + symbol="o" + ) + kmeans_var_plot.setLabel("bottom", "Cluster Number") + kmeans_var_plot.setLabel("left", "Sum of squared distances") + logger.info("Process complete") + except OverflowError: + pass + logger.error("Overflow Error, values are too long") + + def kmeans_elbow_Thread(self): + # Pass the function to execute + worker = Worker(self.kmeans_elbow) # Any other args, kwargs are passed to the run function + worker.signals.result.connect(self.print_output) + worker.signals.finished.connect(self.thread_complete) + # Execute + self.threadpool.start(worker) + + def clustering_(self): + + logger.info("Process started..") + # self.update_stack() + method_ = self.cb_clust_method.currentText() + + decon_images, X_cluster, decon_spectra = cluster_stack( + self.displayedStack, + method=method_, + n_clusters_=self.sb_ncluster.value(), + decomposed=False, + decompose_method=self.cb_comp_method.currentText(), + decompose_comp=self.sb_ncomp.value(), + ) + + self._new_window4 = ClusterViewer(decon_images, self.xdata, X_cluster, decon_spectra) + self._new_window4.show() + + logger.info("Process complete") + + def change_color_on_load(self, button_name): + button_name.setStyleSheet("background-color : rgb(0,150,0);" "color: rgb(255,255,255)") + + def energyFileChooser(self): + file_name = QFileDialog().getOpenFileName(self, + "Open energy list", + self.user_wd, + "text file (*.txt)") + self.efilePath = file_name[0] + + def fast_xanes_fitting(self): + + self._new_window5 = XANESViewer(self.displayedStack, self.xdata, self.refs, self.ref_names) + self._new_window5.show() + + # Thread Signals + + def print_output(self, s): + print(s) + + def thread_complete(self): + print("THREAD COMPLETE!") + + def closeEvent(self, event): + reply = QMessageBox.question( + self, + "Window Close", + "Are you sure you want to close?", + QMessageBox.Yes | QMessageBox.No, + QMessageBox.No, + ) + + if reply == QMessageBox.Yes: + event.accept() + QApplication.closeAllWindows() + else: + event.ignore() + + +class WorkerSignals(QObject): + """ + Defines the signals available from a running worker thread. + Supported signals are: + - finished: No data + - error:`tuple` (exctype, value, traceback.format_exc() ) + - result: `object` data returned from processing, anything + - progress: `tuple` indicating progress metadata + """ + + start = pyqtSignal() + finished = pyqtSignal() + error = pyqtSignal(tuple) + result = pyqtSignal(object) + + +class Worker(QRunnable): + """ + Worker thread + Inherits from QRunnable to handler worker thread setup, signals and wrap-up. + """ + + def __init__(self, fn, *args, **kwargs): + super(Worker, self).__init__() + # Store constructor arguments (re-used for processing) + self.fn = fn + self.args = args + self.kwargs = kwargs + self.signals = WorkerSignals() + + @pyqtSlot() + def run(self): + """ + Initialise the runner function with passed args, kwargs. + """ + # Retrieve args/kwargs here; and fire processing using them + self.signals.start.emit() + try: + result = self.fn(*self.args, **self.kwargs) + except Exception: + traceback.print_exc() + exctype, value = sys.exc_info()[:2] + self.signals.error.emit((exctype, value, traceback.format_exc())) + else: + self.signals.result.emit(result) # Return the result of the processing + finally: + self.signals.finished.emit() # Done + + + + +class ComponentViewer(QtWidgets.QMainWindow): + def __init__(self, comp_stack, energy, comp_spectra, decon_spectra, decomp_map): + super(ComponentViewer, self).__init__() + + # Load the UI Page + uic.loadUi(os.path.join(ui_dir, "ComponentView.ui"), self) + self.centralwidget.setStyleSheet(open(os.path.join(ui_dir, "css/defaultStyle.css")).read()) + self.user_wd = os.path.abspath("~") + + self.comp_stack = comp_stack + self.energy = energy + self.comp_spectra = comp_spectra + self.decon_spectra = decon_spectra + self.decomp_map = decomp_map + + (self.dim1, self.dim3, self.dim2) = self.comp_stack.shape + self.hs_comp_number.setMaximum(self.dim1 - 1) + + self.image_view.setImage(self.comp_stack) + self.image_view.setPredefinedGradient("viridis") + self.image_view.ui.menuBtn.hide() + self.image_view.ui.roiBtn.hide() + + self.image_view2.setImage(self.decomp_map) + self.image_view2.setPredefinedGradient("bipolar") + self.image_view2.ui.menuBtn.hide() + self.image_view2.ui.roiBtn.hide() + + # connection + self.update_image() + self.pb_show_all.clicked.connect(lambda:self.show_all_spec(norm_to_max = True, add_offset = True)) + self.hs_comp_number.valueChanged.connect(self.update_image) + self.actionSave.triggered.connect(self.save_comp_data) + self.pb_openScatterPlot.clicked.connect(self.openScatterPlot) + self.pb_showMultiColor.clicked.connect(lambda: self.generateMultiColorView(withSpectra=False)) + self.pb_showMultiImageXANESView.clicked.connect(lambda: self.generateMultiColorView(withSpectra=True)) + + def update_image(self): + im_index = self.hs_comp_number.value() + self.spectrum_view.setLabel("bottom", "Energy") + self.spectrum_view.setLabel("left", "Intensity", "A.U.") + self.spectrum_view.plot(self.energy, self.decon_spectra[:, im_index], clear=True) + self.component_view.setLabel("bottom", "Energy") + self.component_view.setLabel("left", "Weight", "A.U.") + self.component_view.plot(self.energy, self.comp_spectra[:, im_index], clear=True) + self.label_comp_number.setText(f"{im_index + 1}/{self.dim1}") + # self.image_view.setCurrentIndex(im_index-1) + self.image_view.setImage(self.comp_stack[im_index]) + + def openScatterPlot(self): + self.scatter_window = ComponentScatterPlot(self.comp_stack, self.comp_spectra) + + # ph = self.geometry().height() + # pw = self.geometry().width() + # px = self.geometry().x() + # py = self.geometry().y() + # dw = self.scatter_window.width() + # dh = self.scatter_window.height() + # self.scatter_window.setGeometry(px+0.65*pw, py + ph - 2*dh-5, dw, dh) + self.scatter_window.show() + + def show_all_spec(self, norm_to_max = True, add_offset = True): + self.spectrum_view.clear() + self.plt_colors = ["g", "b", "r", "c", "m", "y", "w"] * 10 + offsets = np.arange(0, 2, 0.2) + self.spectrum_view.addLegend() + for ii in range(self.decon_spectra.shape[1]): + to_plot = self.decon_spectra[:, ii] + if norm_to_max: + to_plot = self.decon_spectra[:, ii] / self.decon_spectra[:, ii].max() + if add_offset: + to_plot = to_plot+ + offsets[ii] + + self.spectrum_view.plot( + self.energy, + to_plot, + pen=self.plt_colors[ii], + name="component" + str(ii + 1), + ) + self.component_view.clear() + self.component_view.addLegend() + for ii in range(self.comp_spectra.shape[1]): + to_plot = self.comp_spectra[:, ii] + if norm_to_max: + to_plot = self.comp_spectra[:, ii] / self.comp_spectra[:, ii].max() + if add_offset: + to_plot = to_plot+ + offsets[ii] + self.component_view.plot( + self.energy, + to_plot, + pen=self.plt_colors[ii], + name="eigen_vector" + str(ii + 1), + ) + + def save_comp_data(self): + file_name = QFileDialog().getSaveFileName(self, "save all data", self.user_wd, "data(*tiff *tif *txt *png )") + if file_name[0]: + self.show_all_spec(norm_to_max = False, add_offset = False) + tf.imwrite(file_name[0] + "_components.tiff", np.float32(self.comp_stack)) + tf.imwrite(file_name[0] + "_component_masks.tiff", np.float32(self.decomp_map)) + exporter_spec = pg.exporters.CSVExporter(self.spectrum_view.plotItem) + exporter_spec.parameters()["columnMode"] = "(x,y) per plot" + exporter_spec.export(file_name[0] + "_deconv_spec.csv") + exporter_eigen = pg.exporters.CSVExporter(self.component_view.plotItem) + exporter_eigen.parameters()["columnMode"] = "(x,y) per plot" + exporter_eigen.export(file_name[0] + "_eigen_vectors.csv") + self.user_wd = os.path.dirname(file_name[0]) + else: + pass + + def generateMultiColorView(self, withSpectra=False): + self.multichanneldict = {} + + for n, (colorName, image) in enumerate(zip(cmap_dict.keys(), self.comp_stack.transpose(0, 1, 2))): + low, high = np.min(image), np.max(image) + self.multichanneldict[f'Image {n + 1}'] = {'ImageName': f'Image {n + 1}', + 'ImageDir': '.', + 'Image': image, + 'Color': colorName, + 'CmapLimits': (low, high), + 'Opacity': 1.0 + } + + if withSpectra: + compXanesSpetraAll = pd.DataFrame() + compXanesSpetraAll['Energy'] = self.energy + + for n, spec in enumerate(self.decon_spectra.T): + compXanesSpetraAll[f'Component_{n + 1}'] = spec + + self.muli_color_window = MultiXANESWindow(image_dict=self.multichanneldict, + spec_df=compXanesSpetraAll) + else: + self.muli_color_window = MultiChannelWindow(image_dict=self.multichanneldict) + + self.muli_color_window.show() + + # add energy column + + +class ClusterViewer(QtWidgets.QMainWindow): + def __init__(self, decon_images, energy, X_cluster, decon_spectra): + super(ClusterViewer, self).__init__() + + # Load the UI Page + uic.loadUi(os.path.join(ui_dir, "ClusterView.ui"), self) + self.user_wd = os.path.abspath("~") + self.centralwidget.setStyleSheet(open(os.path.join(ui_dir, "css/defaultStyle.css")).read()) + + self.decon_images = decon_images + self.energy = energy + self.X_cluster = X_cluster + self.decon_spectra = decon_spectra + (self.dim1, self.dim3, self.dim2) = self.decon_images.shape + self.hsb_cluster_number.setMaximum(self.dim1 - 1) + self.X_cluster = X_cluster + + self.image_view.setImage(self.decon_images, autoHistogramRange=True, autoLevels=True) + self.image_view.setPredefinedGradient("viridis") + self.image_view.ui.menuBtn.hide() + self.image_view.ui.roiBtn.hide() + + self.cluster_view.setImage(self.X_cluster, autoHistogramRange=True, autoLevels=True) + self.cluster_view.setPredefinedGradient("bipolar") + self.cluster_view.ui.histogram.hide() + self.cluster_view.ui.menuBtn.hide() + self.cluster_view.ui.roiBtn.hide() + + # connection + self.update_display() + self.hsb_cluster_number.valueChanged.connect(self.update_display) + self.actionSave.triggered.connect(self.save_clust_data) + self.pb_show_all_spec.clicked.connect(self.showAllSpec) + self.pb_showMultiColor.clicked.connect(self.generateMultiColorView) + + def update_display(self): + im_index = self.hsb_cluster_number.value() + self.component_view.setLabel("bottom", "Energy") + self.component_view.setLabel("left", "Intensity", "A.U.") + self.component_view.plot(self.energy, self.decon_spectra[:, im_index], clear=True) + # self.image_view.setCurrentIndex(im_index-1) + self.image_view.setImage(self.decon_images[im_index]) + self.label_comp_number.setText(f"{im_index + 1}/{self.dim1}") + + def save_clust_data(self): + file_name = QFileDialog().getSaveFileName(self, "", "", "data(*tiff *tif *txt *png )") + if file_name[0]: + + tf.imwrite( + file_name[0] + "_cluster.tiff", np.float32(self.decon_images.transpose(0, 2, 1)), imagej=True + ) + tf.imwrite(file_name[0] + "_cluster_map.tiff", np.float32(self.X_cluster.T), imagej=True) + np.savetxt(file_name[0] + "_deconv_spec.txt", self.decon_spectra) + + else: + logger.error("Saving Cancelled") + self.statusbar.showMessage("Saving Cancelled") + pass + + def showAllSpec(self): + self.component_view.clear() + self.plt_colors = ["g", "b", "r", "c", "m", "y", "w"] * 10 + offsets = np.arange(0, 2, 0.2) + self.component_view.addLegend() + for ii in range(self.decon_spectra.shape[1]): + self.component_view.plot( + self.energy, + (self.decon_spectra[:, ii] / self.decon_spectra[:, ii].max()) + offsets[ii], + pen=self.plt_colors[ii], + name="cluster" + str(ii + 1), + ) + + def generateMultiColorView(self): + self.multichanneldict = {} + + for n, (colorName, image) in enumerate(zip(cmap_dict.keys(), self.decon_images.transpose(0, 1, 2))): + low, high = np.min(image), np.max(image) + self.multichanneldict[f"Image {n + 1}"] = { + "ImageName": f"Image {n + 1}", + "ImageDir": ".", + "Image": image, + "Color": colorName, + "CmapLimits": (low, high), + "Opacity": 1.0, + } + self.muli_color_window = MultiChannelWindow(image_dict=self.multichanneldict) + self.muli_color_window.show() + + + +class ScatterPlot(QtWidgets.QMainWindow): + def __init__(self, img1, img2, nameTuple): + super(ScatterPlot, self).__init__() + + uic.loadUi(os.path.join(ui_dir, "ScatterView.ui"), self) + self.user_wd = os.path.abspath("~") + self.centralwidget.setStyleSheet(open(os.path.join(ui_dir, "css/defaultStyle.css")).read()) + self.clearPgPlot() + self.w1 = self.scatterViewer.addPlot() + self.img1 = img1 + self.img2 = img2 + self.nameTuple = nameTuple + x, y = np.shape(self.img1) + self.s1 = pg.ScatterPlotItem(size=2, pen=pg.mkPen(None), brush=pg.mkBrush(255, 255, 0, 255)) + # print(self.s1) + + # create three polyline ROIs for masking + Xsize = self.img1.max() / 6 + Ysize = self.img2.max() / 6 + + self.scatter_mask = pg.PolyLineROI( + [[0, 0], [0, Ysize], [Xsize / 2, Ysize * 1.5], [Xsize, Ysize], [Xsize, 0]], + pos=None, + pen=pg.mkPen("r", width=2), + hoverPen=pg.mkPen("w", width=2), + closed=True, + removable=True, + ) + + self.scatter_mask2 = pg.PolyLineROI( + [ + [Xsize * 1.2, 0], + [Xsize * 1.2, Ysize * 2], + [Xsize * 2, Ysize * 2], + [Xsize * 3, Ysize], + [Xsize * 2, 0], + ], + pos=None, + pen=pg.mkPen("g", width=2), + hoverPen=pg.mkPen("w", width=2), + closed=True, + removable=True, + ) + self.scatter_mask3 = pg.PolyLineROI( + [ + [Xsize * 2.5, 0], + [Xsize * 2.5, Ysize], + [Xsize * 4, Ysize], + [Xsize * 4, 0], + [Xsize * 3.7, Ysize * -0.5], + ], + pos=None, + pen=pg.mkPen("c", width=2), + hoverPen=pg.mkPen("w", width=2), + closed=True, + removable=True, + ) + + self.fitScatter = self.fitScatter2 = self.fitScatter3 = None + + self.rois = { + "ROI 1": (self.scatter_mask, self.rb_roi1.isChecked(), self.fitScatter), + "ROI 2": (self.scatter_mask2, self.rb_roi2.isChecked(), self.fitScatter2), + "ROI 3": (self.scatter_mask3, self.rb_roi3.isChecked(), self.fitScatter3), + } + + self.windowNames = {"ROI 1": self.fitScatter, "ROI 2": self.fitScatter2, "ROI 3": self.fitScatter3} + + self.s1.setData(self.img1.flatten(), self.img2.flatten()) + self.w1.setLabel("bottom", self.nameTuple[0], "counts") + self.label_img1.setText(self.nameTuple[0]) + self.w1.setLabel("left", self.nameTuple[1], "counts") + self.label_img2.setText(self.nameTuple[1]) + self.w1.addItem(self.s1) + + self.image_view.setImage(self.img1) + self.image_view.ui.menuBtn.hide() + self.image_view.ui.roiBtn.hide() + self.image_view.setPredefinedGradient("thermal") + + self.image_view2.setImage(self.img2) + self.image_view2.ui.menuBtn.hide() + self.image_view2.ui.roiBtn.hide() + self.image_view2.setPredefinedGradient("thermal") + + # connections + self.actionSave_Plot.triggered.connect(self.pg_export_correlation) + self.actionSave_Images.triggered.connect(self.tiff_export_images) + # self.pb_define_mask.clicked.connect(lambda:self.createMask(self.scatter_mask)) + self.pb_define_mask.clicked.connect(self.addMultipleROIs) + # self.pb_apply_mask.clicked.connect(lambda:self.getMaskRegion(self.scatter_mask)) + self.pb_apply_mask.clicked.connect(self.applyMultipleROIs) + self.pb_clear_mask.clicked.connect(self.clearMultipleROIs) + self.pb_compositeScatter.clicked.connect(self.createCompositeScatter) + [rbs.clicked.connect(self.updateROIDict) for rbs in [self.rb_roi1, self.rb_roi2, self.rb_roi3]] + + def pg_export_correlation(self): + + exporter = pg.exporters.CSVExporter(self.w1) + #exporter.parameters()["columnMode"] = "(x,y,y,y) for all plots" + file_name = QFileDialog().getSaveFileName(self, + "save correlation", + os.path.join(self.user_wd,"correlation.csv"), + "spectrum and fit (*csv)") + if file_name[0]: + exporter.export(file_name[0] + ".csv") + self.statusbar.showMessage(f"Data saved to {file_name[0]}") + self.user_wd = os.path.dirname(file_name[0]) + else: + pass + + def tiff_export_images(self): + file_name = QFileDialog().getSaveFileName(self, + "save images", + os.path.join(self.user_wd,"image.txt"), + "spectrum and fit (*tiff)") + if file_name[0]: + tf.imwrite(file_name[0] + ".tiff", np.dstack([self.img1, self.img2]).T) + self.statusbar.showMessage(f"Images saved to {file_name[0]}") + self.user_wd = os.path.dirname(file_name[0]) + else: + pass + + def createMask(self, ROIName): + + try: + self.w1.removeItem(ROIName) + except Exception: + pass + self.w1.addItem(ROIName) + + def clearMask(self, ROIName): + self.w1.removeItem(ROIName) + + def clearPgPlot(self): + try: + self.masked_img.close() + except Exception: + pass + + def getMaskRegion(self, ROIName, generateSeperateWindows=True): + + """filter scatterplot points using polylineROI region""" + + # Ref : https://stackoverflow.com/questions/57719303/how-to-map-mouse-position-on-a-scatterplot + + # get the roi region:QPaintPathObject + roiShape = self.rois[ROIName][0].mapToItem(self.s1, self.rois[ROIName][0].shape()) + + # get data in the scatter plot + scatterData = np.array(self.s1.getData()) + + # generate a binary mask for points inside or outside the roishape + selected = [roiShape.contains(QtCore.QPointF(pt[0], pt[1])) for pt in scatterData.T] + + # reshape the mask to image dimensions + self.mask2D = np.reshape(selected, (self.img1.shape)) + + # get masked image1 + self.maskedImage = self.mask2D * self.img1 + + # get rid of the (0,0) values in the masked array + self.xData, self.yData = np.compress(selected, scatterData[0]), np.compress(selected, scatterData[1]) + + # linear regeression of the filtered X,Y data + result = linregress(self.xData, self.yData) + + # Pearson's correlation of the filtered X,Y data + pr, pp = stats.pearsonr(self.xData, self.yData) + + # apply the solved equation to xData to generate the fit line + self.yyData = result.intercept + result.slope * self.xData + + # Prepare strings for fit results and stats + self.fitLineEqn = ( + f" y = x*{result.slope :.3e} + {result.intercept :.3e}," + f"\n R^2 = {result.rvalue**2 :.3f}, r = {pr :.3f}" + ) + FitStats1 = f" Slope Error = {result.stderr :.3e}, Intercept Error = {result.intercept_stderr :.3e}\n" + FitStats2 = f" Pearson's correlation coefficient = {pr :.3f}" + refs = "\n\n ***References****\n\n scipy.stats.linregress, scipy.stats.pearsonr " + fitStats = ( + f"\n ***{ROIName} Fit Results***\n\n" + " Equation: " + self.fitLineEqn + FitStats1 + FitStats2 + refs + ) + + # generate new window to plot the results + + if generateSeperateWindows: + self.windowNames[ROIName] = MaskedScatterPlotFit( + [self.xData, self.yData], + [self.xData, self.yyData], + self.mask2D, + self.maskedImage, + fitStats, + self.fitLineEqn, + self.nameTuple, + ) + self.windowNames[ROIName].show() + + """ + from scipy.linalg import lstsq + M = xData[:, np.newaxis]**[0, 1] #use >1 for polynomial fits + p, res, rnk, s = lstsq(M, yData) + yyData = p[0] + p[1]*xData + """ + + def updateROIDict(self): + self.rois = { + "ROI 1": (self.scatter_mask, self.rb_roi1.isChecked()), + "ROI 2": (self.scatter_mask2, self.rb_roi2.isChecked()), + "ROI 3": (self.scatter_mask3, self.rb_roi3.isChecked()), + } + + def applyMultipleROIs(self): + with pg.BusyCursor(): + self.updateROIDict() + for key in self.rois.keys(): + if self.rois[key][1]: + self.getMaskRegion(key) + else: + pass + + def addMultipleROIs(self): + self.updateROIDict() + for key in self.rois.keys(): + if self.rois[key][1]: + self.createMask(self.rois[key][0]) + else: + self.clearMask(self.rois[key][0]) + + def clearMultipleROIs(self): + self.updateROIDict() + for key in self.rois.keys(): + if not self.rois[key][1]: + self.clearMask(self.rois[key][0]) + else: + pass + + def createCompositeScatter(self): + + points = [] + fitLine = [] + masks = [] + roiFitEqn = {} + + self.updateROIDict() + for n, key in enumerate(self.rois.keys()): + if self.rois[key][1]: + self.getMaskRegion(key, generateSeperateWindows=False) + points.append(np.column_stack([self.xData, self.yData])) + fitLine.append(np.column_stack([self.xData, self.yyData])) + masks.append(self.mask2D) + roiFitEqn[key] = self.fitLineEqn + else: + pass + + self.compositeScatterWindow = CompositeScatterPlot( + points, + fitLine, + np.array(masks), + roiFitEqn, + self.nameTuple + ) + self.compositeScatterWindow.show() + + def _createCompositeScatter(self): + self.scatterColors = ["w", "c", "y", "k", "m"] + points = [] + fitLine = [] + + self.updateROIDict() + for n, key in enumerate(self.rois.keys()): + if self.rois[key][1]: + self.getMaskRegion(key, generateSeperateWindows=False) + + for x, y, yy in zip(self.xData, self.yData, self.yyData): + + points.append( + { + "pos": (x, y), + "data": "id", + "size": 3, + "pen": pg.mkPen(None), + "brush": self.scatterColors[n], + } + ) + fitLine.extend(np.column_stack((self.xData, self.yyData))) + else: + pass + + logger.info(f" fitline shape: {np.shape(fitLine)}") + self.compositeScatterWindow = CompositeScatterPlot(points, np.array(fitLine)) + self.compositeScatterWindow.show() + + def getROIParams(self): + print(np.array(self.scatter_mask.getSceneHandlePositions())) + +class MaskedScatterPlotFit(QtWidgets.QMainWindow): + def __init__(self, scatterData, fitData, mask, maskedImage, fitString, fitEquation, nameTuple): + super(MaskedScatterPlotFit, self).__init__() + + uic.loadUi(os.path.join(ui_dir, "maskedScatterPlotFit.ui"), self) + self.user_wd = os.path.abspath("~") + self.centralwidget.setStyleSheet(open(os.path.join(ui_dir, "css/defaultStyle.css")).read()) + self.scatterData = scatterData + self.fitData = fitData + self.mask = mask + self.maskedImage = maskedImage + self.fitString = fitString + self.fitEquation = fitEquation + self.nameTuple = nameTuple + + # set the graphicslayoutwidget in the ui as canvas + self.canvas = self.scatterViewer.addPlot() + self.canvas.addLegend() + self.canvas.setLabel("bottom", self.nameTuple[0], "counts") + self.canvas.setLabel("left", self.nameTuple[1], "counts") + self.gb_maskedImage1.setTitle(f" Masked {self.nameTuple[0]}") + + # generate a scatter plot item + self.scattered = pg.ScatterPlotItem(size=3.5, pen=pg.mkPen(None), brush=pg.mkBrush(5, 214, 255, 200)) + + # set scatter plot data + self.scattered.setData(scatterData[0], scatterData[1], name="Data") + + # set z value negative to show scatter data behind the fit line + self.scattered.setZValue(-10) + + # add scatter plot to the canvas + self.canvas.addItem(self.scattered) + + # generate plotitem for fit line + self.fitLinePlot = pg.PlotDataItem(pen=pg.mkPen(pg.mkColor(220, 20, 60), width=3.3)) + + # set line plot data + self.fitLinePlot.setData(fitData[0], fitData[1], name="Linear Fit") + + # add line plot to the canvas + self.canvas.addItem(self.fitLinePlot) + + # display Mask + self.imageView_mask.setImage(self.mask) + self.imageView_mask.ui.menuBtn.hide() + self.imageView_mask.ui.roiBtn.hide() + self.imageView_mask.setPredefinedGradient("plasma") + + # display masked Image + self.imageView_maskedImage.setImage(self.maskedImage) + self.imageView_maskedImage.ui.menuBtn.hide() + self.imageView_maskedImage.ui.roiBtn.hide() + self.imageView_maskedImage.setPredefinedGradient("viridis") + + # display Fit stats + self.text_fit_results.setPlainText(fitString) + self.canvas.setTitle(self.fitEquation, color="r") + + # connections + self.pb_copy_results.clicked.connect(self.copyFitResults) + self.pb_save_results.clicked.connect(self.saveFitResults) + self.actionSave_Plot.triggered.connect(self.pg_export_correlation) + self.actionSaveMask.triggered.connect(self.saveMask) + self.actionSaveMaskedImage.triggered.connect(self.saveImage) + + def saveFitResults(self): + S__File = QFileDialog.getSaveFileName(self, "save txt", "correlationPlotFit.txt", "txt data (*txt)") + + Text = self.text_fit_results.toPlainText() + if S__File[0]: + with open(S__File[0], "w") as file: + file.write(Text) + + def copyFitResults(self): + self.text_fit_results.selectAll() + self.text_fit_results.copy() + self.statusbar.showMessage("text copied to clipboard") + + def pg_export_correlation(self): + + exporter = pg.exporters.CSVExporter(self.canvas) + #exporter.parameters()["columnMode"] = "(x,y,y,y) for all plots" + file_name = QFileDialog().getSaveFileName( + self, "save correlation", "scatterData.csv", "spectrum and fit (*csv)" + ) + if file_name[0]: + exporter.export(file_name[0]) + self.statusbar.showMessage(f"Data saved to {file_name[0]}") + else: + pass + + def saveImage(self): + + file_name = QFileDialog().getSaveFileName(self, "Save image data", "image.tiff", "image file(*tiff *tif )") + if file_name[0]: + tf.imwrite(file_name[0], self.maskedImage) + self.statusbar.showMessage(f"Data saved to {file_name[0]}") + else: + self.statusbar.showMessage("Saving cancelled") + pass + + def saveMask(self): + + file_name = QFileDialog().getSaveFileName(self, "Save image data", "mask.tiff", "image file(*tiff *tif )") + if file_name[0]: + tf.imwrite(file_name[0], self.mask) + self.statusbar.showMessage(f"Data saved to {file_name[0]}") + else: + self.statusbar.showMessage("Saving cancelled") + pass + +class ComponentScatterPlot(QtWidgets.QMainWindow): + def __init__(self, decomp_stack, specs): + super(ComponentScatterPlot, self).__init__() + + uic.loadUi(os.path.join(ui_dir, "ComponentScatterPlot.ui"), self) + self.user_wd = os.path.abspath("~") + self.centralwidget.setStyleSheet(open(os.path.join(ui_dir, "css/defaultStyle.css")).read()) + self.w1 = self.scatterViewer.addPlot() + self.decomp_stack = decomp_stack + self.specs = specs + (self.dim1, self.dim3, self.dim2) = self.decomp_stack.shape + # fill the combonbox depending in the number of components for scatter plot + for n, combs in enumerate(combinations(np.arange(self.dim1), 2)): + self.cb_scatter_comp.addItem(str(combs)) + self.cb_scatter_comp.setItemData(n, combs) + + self.s1 = pg.ScatterPlotItem(size=3, pen=pg.mkPen(None), brush=pg.mkBrush(255, 255, 0, 120)) + + self.setImageAndScatterPlot() + # connections + self.actionSave_Plot.triggered.connect(self.pg_export_correlation) + self.actionSave_Images.triggered.connect(self.tiff_export_images) + self.pb_updateComponents.clicked.connect(self.setImageAndScatterPlot) + self.pb_define_mask.clicked.connect(self.createMask) + self.pb_apply_mask.clicked.connect(self.getMaskRegion) + self.pb_reset_mask.clicked.connect(self.resetMask) + self.pb_addALine.clicked.connect(lambda: self.createMask(Line=True)) + + def setImageAndScatterPlot(self): + + try: + self.s1.clear() + except Exception: + pass + + comp_tuple = self.cb_scatter_comp.currentData() + self.img1, self.img2 = self.decomp_stack[comp_tuple[0]], self.decomp_stack[comp_tuple[-1]] + self.image_view.setImage(self.decomp_stack[comp_tuple[0]]) + self.image_view.ui.menuBtn.hide() + self.image_view.ui.roiBtn.hide() + self.image_view.setPredefinedGradient("bipolar") + + self.image_view2.setImage(self.decomp_stack[comp_tuple[-1]]) + self.image_view2.ui.menuBtn.hide() + self.image_view2.ui.roiBtn.hide() + self.image_view2.setPredefinedGradient("bipolar") + + points = [] + for i, j in zip(self.img1.flatten(), self.img2.flatten()): + + points.append( + { + "pos": (i, j), + "data": "id", + "size": 5, + "pen": pg.mkPen(None), + "brush": pg.mkBrush(255, 255, 0, 160), + } + ) + + self.s1.addPoints(points) + self.w1.addItem(self.s1) + # self.s1.setData(self.specs[:, comp_tuple[0]], self.specs[:, comp_tuple[-1]]) + self.w1.setLabel("bottom", f"PC{comp_tuple[0]+1}") + self.w1.setLabel("left", f"PC{comp_tuple[-1]+1}") + self.label_im1.setText(f"PC{comp_tuple[0]+1}") + self.label_im2.setText(f"PC{comp_tuple[-1]+1}") + + def createMask(self, Line=False): + + self.size = self.img1.max() / 10 + self.pos = int(self.img1.mean()) + + if Line: + self.lineROI = pg.LineSegmentROI( + [0, 1], + pos=(self.pos, self.pos), + pen=pg.mkPen("r", width=4), + hoverPen=pg.mkPen("g", width=4), + removable=True, + ) + self.w1.addItem(self.lineROI) + + else: + + self.scatter_mask = pg.PolyLineROI( + [[0, 0], [0, self.size], [self.size, self.size], [self.size, 0]], + pos=(self.pos, self.pos), + pen=pg.mkPen("r", width=4), + hoverPen=pg.mkPen("g", width=4), + closed=True, + removable=True, + ) + + self.w1.addItem(self.scatter_mask) + + def resetMask(self): + self.clearMask() + self.createMask() + + def clearMask(self): + try: + self.w1.removeItem(self.scatter_mask) + except AttributeError: + pass + + def clearPgPlot(self): + try: + self.masked_img.close() + except Exception: + pass + + def getMaskRegion(self): + + # Ref : https://stackoverflow.com/questions/57719303/how-to-map-mouse-position-on-a-scatterplot + + roiShape = self.scatter_mask.mapToItem(self.s1, self.scatter_mask.shape()) + self._points = list() + logger.info("Building Scatter Plot Window; Please wait..") + for i in range(len(self.img1.flatten())): + self._points.append(QtCore.QPointF(self.img1.flatten()[i], self.img2.flatten()[i])) + + selected = [roiShape.contains(pt) for pt in self._points] + img_selected = np.reshape(selected, (self.img1.shape)) + + self.masked_img = singleStackViewer(img_selected * self.img1, gradient="bipolar") + self.masked_img.show() + + def pg_export_correlation(self): + + exporter = pg.exporters.CSVExporter(self.w1) + exporter.parameters()["columnMode"] = "(x,y,y,y) for all plots" + file_name = QFileDialog().getSaveFileName(self, "save correlation", "", "spectrum and fit (*csv)") + if file_name[0]: + exporter.export(file_name[0] + ".csv") + self.statusbar.showMessage(f"Data saved to {file_name[0]}") + else: + pass + + def tiff_export_images(self): + file_name = QFileDialog().getSaveFileName(self, "save images", "", "spectrum and fit (*tiff)") + if file_name[0]: + tf.imwrite(file_name[0] + ".tiff", np.dstack([self.img1, self.img2]).T) + self.statusbar.showMessage(f"Images saved to {file_name[0]}") + else: + pass + +class LoadingScreen(QtWidgets.QSplashScreen): + def __init__(self): + super(LoadingScreen, self).__init__() + uic.loadUi(os.path.join(ui_dir, "animationWindow.ui"), self) + self.setWindowOpacity(0.65) + self.movie = QMovie("uis/animation.gif") + self.label.setMovie(self.movie) + + def mousePressEvent(self, event): + # disable default "click-to-dismiss" behaviour + pass + + def startAnimation(self): + self.movie.start() + self.show() + + def stopAnimation(self): + self.movie.stop() + self.hide() + +class CompositeScatterPlot(QtWidgets.QMainWindow): + def __init__(self, scatterPoints, fitLine, maskImages, fitEquations, nameTuple): + super(CompositeScatterPlot, self).__init__() + + uic.loadUi(os.path.join(ui_dir, "multipleScatterFit.ui"), self) + self.user_wd = os.path.abspath("~") + self.centralwidget.setStyleSheet(open(os.path.join(ui_dir, "css/defaultStyle.css")).read()) + + self.scatterPoints = scatterPoints + # print(f"{np.shape(self.scatterPoints) = }") + self.fitLine = fitLine + #print(f"{np.shape(self.fitLine) = }") + self.scatterColors = ["r", (0, 115, 0), (4, 186, 186), "c", "w", "k"] + self.fitColors = ["b", "r", "m", "k", "b"] + self.roiNames = list(fitEquations.keys()) + self.fitEqns = list(fitEquations.values()) + # print(f"{np.shape(self.roiNames) = }") + # print(f"{np.shape(self.fitEqns) = }") + self.nameTuple = nameTuple + self.maskImages = maskImages + + # self.scatterViewer.setBackground('w') + # set the graphicslayoutwidget in the ui as canvas + self.canvas = self.scatterViewer.addPlot() + self.canvas.addLegend() + self.canvas.setLabel("bottom", self.nameTuple[0], "counts") + self.canvas.setLabel("left", self.nameTuple[1], "counts") + + # connections + self.actionExport.triggered.connect(self.exportData) + self.actionSave_as_PNG.triggered.connect(self.exportAsPNG) + self.actionGenerate_MultiColor_Mask.triggered.connect(self.generateMultiColorView) + self.actionWhite.triggered.connect(lambda: self.scatterViewer.setBackground("w")) + self.actionBlack.triggered.connect(lambda: self.scatterViewer.setBackground("k")) + + with pg.BusyCursor(): + + for arr, fitline, clr, fitClr, rname, feqn in zip( + self.scatterPoints, self.fitLine, self.scatterColors, self.fitColors, self.roiNames, self.fitEqns + ): + + sctrPoints = [] + for pt in arr: + sctrPoints.append( + {"pos": (pt[0], pt[1]), "data": "id", "size": 3, "pen": pg.mkPen(None), "brush": clr} + ) + + # generate a scatter plot item + self.scattered = pg.ScatterPlotItem(size=4.5, pen=clr, brush=pg.mkBrush(5, 214, 255, 200)) + # set scatter plot data + self.scattered.addPoints(sctrPoints, name=rname) + + # set z value negative to show scatter data behind the fit line + self.scattered.setZValue(-10) + + # add scatter plot to the canvas + self.canvas.addItem(self.scattered) + + # generate plotitem for fit line + self.fitLinePlot = pg.PlotDataItem(pen=pg.mkPen(fitClr, width=4.5)) + + # set line plot data + self.fitLinePlot.setData(fitline, name=feqn) + + # add line plot to the canvas + self.canvas.addItem(self.fitLinePlot) + + def generateMultiColorView(self): + self.multichanneldict = {} + + for n, (colorName, image, rname) in enumerate(zip(cmap_dict.keys(), self.maskImages, self.roiNames)): + low, high = np.min(image), np.max(image) + self.multichanneldict[rname] = { + "ImageName": rname, + "ImageDir": ".", + "Image": image, + "Color": colorName, + "CmapLimits": (low, high), + "Opacity": 1.0, + } + + # print( self.multichanneldict) + self.muli_color_window = MultiChannelWindow(image_dict=self.multichanneldict) + self.muli_color_window.show() + + def exportData(self): + + exporter = pg.exporters.CSVExporter(self.canvas) + # exporter.parameters()['columnMode'] = '(x,y,y,y) for all plots' + file_name = QFileDialog().getSaveFileName(self, + "Save CSV Data", + os.path.join(self.user_wd,"scatter.csv"), + "image file (*csv)") + if file_name[0]: + exporter.export(file_name[0]) + self.statusbar.showMessage(f"Data saved to {file_name[0]}") + self.user_wd = os.path.dirname(file_name[0]) + else: + pass + + def exportAsPNG(self): + file_name = QFileDialog().getSaveFileName(self, + "Save Image", + os.path.join(self.user_wd,"image.png"), + "PNG(*.png);; TIFF(*.tiff);; JPG(*.jpg)" + ) + exporter = pg.exporters.ImageExporter(self.canvas) + + if file_name[0]: + exporter.export(file_name[0]) + self.statusbar.showMessage(f"Image saved to {file_name[0]}") + self.user_wd = os.path.dirname(file_name[0]) + else: + pass + + +class StackInfo(QtWidgets.QMainWindow): + def __init__(self, text_to_write: str = " "): + super(StackInfo, self).__init__() + uic.loadUi(os.path.join(ui_dir, "log.ui"), self) + self.user_wd = os.path.abspath("~") + + self.text_to_write = text_to_write + self.pte_run_cmd.setPlainText(self.text_to_write) + + # connections + self.pb_save_cmd.clicked.connect(self.save_file) + self.pb_clear_cmd.clicked.connect(self.clear_text) + + def save_file(self): + S__File = QFileDialog.getSaveFileName(None, "SaveFile", "/", "txt Files (*.txt)") + + Text = self.pte_run_cmd.toPlainText() + if S__File[0]: + with open(S__File[0], "w") as file: + file.write(Text) + + def clear_text(self): + self.pte_run_cmd.clear() + + +def start_xmidas(): + def formatter(prog): + # Set maximum width such that printed help mostly fits in the RTD theme code block (documentation). + return argparse.RawDescriptionHelpFormatter(prog, max_help_position=20, width=90) + + parser = argparse.ArgumentParser( + description=f"XMidas: v{__version__}", + formatter_class=formatter, + ) + parser.parse_args() + + logger.setLevel(logging.INFO) + formatter = logging.Formatter(fmt="%(asctime)s : %(levelname)s : %(message)s") + stream_handler = logging.StreamHandler() + stream_handler.setFormatter(formatter) + stream_handler.setLevel(logging.INFO) + if logger.hasHandlers(): + logger.handlers.clear() + logger.addHandler(stream_handler) + if version.parse(PYQT_VERSION_STR) >= version.parse("5.14"): + QtWidgets.QApplication.setHighDpiScaleFactorRoundingPolicy( + QtCore.Qt.HighDpiScaleFactorRoundingPolicy.PassThrough + ) + + + app = QtWidgets.QApplication(sys.argv) + # app.setAttribute(QtCore.Qt.AA_Use96Dpi) + window = midasWindow() + window.show() + sys.exit(app.exec()) + + +if __name__ == "__main__": + start_xmidas() + +__version__ = "1.0.0" # or whatever version you want diff --git a/xmidas/tests/__init__.py b/xmidas/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/xmidas/tests/conftest.py b/xmidas/tests/conftest.py deleted file mode 100644 index e69de29..0000000 diff --git a/xmidas/tests/test_general.py b/xmidas/tests/test_general.py deleted file mode 100644 index 8bdb023..0000000 --- a/xmidas/tests/test_general.py +++ /dev/null @@ -1,15 +0,0 @@ -import subprocess - - -def test_package_installed(): - """ - Test if the package is installed (imports work) - """ - from xmidas.main import start_xmidas # noqa: F401 - - -def test_entry_point_installed(): - """ - Test that the entry point is installed and the application can be started. - """ - assert subprocess.call(["xmidas", "-h"]) == 0 diff --git a/xmidas/uis/ClusterView.ui b/xmidas/uis/ClusterView.ui deleted file mode 100644 index 6f5fa2e..0000000 --- a/xmidas/uis/ClusterView.ui +++ /dev/null @@ -1,266 +0,0 @@ - - - MainWindow - - - - 0 - 0 - 979 - 815 - - - - - 0 - 0 - - - - MainWindow - - - background-color: rgb(240, 240, 240); -font: 10pt "Segoe UI"; - - - - QPushButton { -background-color: rgb(175, 236, 255); -color: rgb(255, 5,0); -} - - - - - - - - - - - - - Composite Map - - - Qt::AlignCenter - - - - - - - Opan as RGBCMY Image - - - - - - - - - - - - - - - - - Nth Cluster - - - Qt::AlignCenter - - - - - - - - - - - - - 0 - 0 - - - - 0 - - - 20 - - - 1 - - - 1 - - - Qt::Horizontal - - - - - - - - 0 - 0 - - - - font: 12pt "Segoe UI"; - - - 1/3 - - - - - - - - - - - - - - - 100 - - - 100 - - - - - - - font: 75 12pt "MS Shell Dlg 2"; - - - Cluster Spectrum - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - - - - Show all - - - - - - - - - QAbstractScrollArea::AdjustToContents - - - - - - - - - - - - - 0 - 0 - 979 - 23 - - - - - Image - - - - - - - - Spectrum - - - - - - - Options - - - - - - - - - - - Save All Clusters - - - - - Save Current Cluster - - - - - Save Composite Map as Masks - - - - - Save All Cluster Spectra - - - - - Save Current Spectrum - - - - - Save Results as a Folder - - - - - - PlotWidget - QGraphicsView -
pyqtgraph
-
- - ImageView - QGraphicsView -
pyqtgraph
-
-
- - -
diff --git a/xmidas/uis/ComponentScatterPlot.ui b/xmidas/uis/ComponentScatterPlot.ui deleted file mode 100644 index 2e4519b..0000000 --- a/xmidas/uis/ComponentScatterPlot.ui +++ /dev/null @@ -1,195 +0,0 @@ - - - ScatterPlot - - - - 0 - 0 - 1034 - 859 - - - - Correlation Plot - - - font: 12pt "MS Shell Dlg 2"; - - - - - - - 10 - - - 10 - - - 10 - - - 10 - - - - - Image - - - Qt::AlignCenter - - - - - - - - - - - - 10 - - - 10 - - - 10 - - - 10 - - - - - Image - - - Qt::AlignCenter - - - - - - - - - - - - - - - Qt::LeftToRight - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - Apply - - - - - - - Scatter View of - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - - - Add A Line - - - - - - - Create A Mask - - - - - - - Reset Mask - - - - - - - Apply Mask - - - - - - - - - - - 0 - 0 - 1034 - 30 - - - - - File - - - - - - - - - - Save Plot - - - - - Save Images - - - - - - ImageView - QGraphicsView -
pyqtgraph
-
- - GraphicsLayoutWidget - QGraphicsView -
pyqtgraph
-
-
- - -
diff --git a/xmidas/uis/ComponentView.ui b/xmidas/uis/ComponentView.ui deleted file mode 100644 index df74ea3..0000000 --- a/xmidas/uis/ComponentView.ui +++ /dev/null @@ -1,296 +0,0 @@ - - - MainWindow - - - - 0 - 0 - 920 - 858 - - - - MainWindow - - - background-color: rgb(240, 240, 240); - - - - - - - - - - - - - - - - - - - - - Components - - - Qt::AlignCenter - - - - - - - - - - - - - - - 0 - 0 - - - - QSlider::groove:horizontal { -border: 1px solid #bbb; -background: white; -height: 10px; -border-radius: 4px; -} - -QSlider::sub-page:horizontal { -background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #66e, stop: 1 #bbf); -background: qlineargradient(x1: 0, y1: 0.2, x2: 1, y2: 1, - stop: 0 #bbf, stop: 1 #55f); -border: 1px solid #777; -height: 10px; -border-radius: 4px; -} - -QSlider::add-page:horizontal { -background: #fff; -border: 1px solid #777; -height: 10px; -border-radius: 4px; -} - -QSlider::handle:horizontal { -background: qlineargradient(x1:0, y1:0, x2:1, y2:1, - stop:0 #eee, stop:1 #ccc); -border: 1px solid #777; -width: 13px; -margin-top: -2px; -margin-bottom: -2px; -border-radius: 4px; -} - -QSlider::handle:horizontal:hover { -background: qlineargradient(x1:0, y1:0, x2:1, y2:1, - stop:0 #fff, stop:1 #ddd); -border: 1px solid #444; -border-radius: 2px; -} - -QSlider::sub-page:horizontal:disabled { -background: #bbb; -border-color: #999; -} - -QSlider::add-page:horizontal:disabled { -background: #eee; -border-color: #999; -} - -QSlider::handle:horizontal:disabled { -background: #eee; -border: 1px solid #aaa; -border-radius: 4px; -} - -QPushButton { -background-color: rgb(175, 236, 255); -color: rgb(255, 0, 127); -} - - - 20 - - - 1 - - - 1 - - - Qt::Horizontal - - - - - - - - 0 - 0 - - - - font: 12pt "Segoe UI"; - - - 1/3 - - - - - - - - - - - - - - - - Component Masks - - - Qt::AlignCenter - - - - - - - - - - - - - Show All Spectra - - - - - - - Opan as RGBCMY Image - - - - - - - - - - - - - - - - Masked Spectrum - - - Qt::AlignCenter - - - - - - - - - - - - - - - - Component Spectrum - - - Qt::AlignCenter - - - - - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - - Open ScatterPlot - - - - - - - - - - - - 0 - 0 - 920 - 26 - - - - - File - - - - - - - - - Save - - - - - - PlotWidget - QGraphicsView -
pyqtgraph
-
- - ImageView - QGraphicsView -
pyqtgraph
-
-
- - -
diff --git a/xmidas/uis/Log.ui b/xmidas/uis/Log.ui deleted file mode 100644 index 92ca4ec..0000000 --- a/xmidas/uis/Log.ui +++ /dev/null @@ -1,68 +0,0 @@ - - - MainWindow - - - - 0 - 0 - 624 - 759 - - - - Log - - - - - - - font: 10pt "Segoe UI"; - - - QAbstractScrollArea::AdjustToContentsOnFirstShow - - - QPlainTextEdit::NoWrap - - - start typing here.. - - - - - - - - - Save - - - - - - - Clear - - - - - - - - - - - 0 - 0 - 624 - 26 - - - - - - - - diff --git a/xmidas/uis/MaskedView.ui b/xmidas/uis/MaskedView.ui deleted file mode 100644 index a8c40db..0000000 --- a/xmidas/uis/MaskedView.ui +++ /dev/null @@ -1,352 +0,0 @@ - - - MainWindow - - - - 0 - 0 - 930 - 779 - - - - MaskedXANES - - - - - - - - - - - - color: rgb(255, 0, 0); -font: 12pt "MS Shell Dlg 2"; - - - XANES Stack - - - Qt::AlignCenter - - - - - - - - - - - - - - font: 12pt "MS Shell Dlg 2"; -color: rgb(255, 0, 0); - - - Mask - - - Qt::AlignCenter - - - - - - - - - - - - 0 - - - - - A Tiff Mask with same dimensions - - - background-color: rgb(170, 255, 255); -font: 10pt "MS Shell Dlg 2"; - - - Import Mask - - - - - - - Save Mask tiff - - - background-color: rgb(170, 255, 255); -font: 10pt "MS Shell Dlg 2"; - - - Export Mask - - - - - - - Apply the mask to XANES - - - background-color: rgb(170, 255, 255); -font: 10pt "MS Shell Dlg 2"; - - - Apply - - - - - - - - - - - font: 75 12pt "MS Shell Dlg 2"; -color: rgb(255, 0, 0); - - - Mean Spectrum - - - Qt::AlignCenter - - - - - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - font: 12pt "MS Shell Dlg 2"; -color: rgb(255, 0, 0); - - - XRF Map - - - Qt::AlignCenter - - - - - - - font: 10pt "MS Shell Dlg 2"; -color: rgb(255, 0, 0); - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - - - - - - - Qt::NoFocus - - - 100 - - - 5 - - - 5 - - - 0 - - - 0 - - - true - - - Qt::Vertical - - - QSlider::TicksAbove - - - 5 - - - - - - - - - - - Qt::NoFocus - - - 100 - - - 5 - - - 5 - - - 100 - - - 100 - - - true - - - Qt::Vertical - - - false - - - false - - - QSlider::TicksBelow - - - 5 - - - - - - - - - - - - - - - - - 0 - 0 - 930 - 26 - - - - - File - - - - - - - - - - - - - - Save XANES Stack - - - - - Save XRF Map - - - - - Save Spectrum - - - - - Load Energy List - - - - - Load XRF Map - - - - - Load XANES Stack - - - - - - ImageView - QGraphicsView -
pyqtgraph
-
- - PlotWidget - QGraphicsView -
pyqtgraph
-
-
- - -
diff --git a/xmidas/uis/RefChooser.ui b/xmidas/uis/RefChooser.ui deleted file mode 100644 index eea416f..0000000 --- a/xmidas/uis/RefChooser.ui +++ /dev/null @@ -1,247 +0,0 @@ - - - MainWindow - - - - 0 - 0 - 986 - 985 - - - - ArrowCursor - - - Select References - - - font: 10pt "MS Shell Dlg 2"; - - - - QCheckBox:checked { -color: rgb(255, 75, 52); - background-color: rgb(255, 248, 149); -} - -QPushButton { -background-color: rgb(175, 236, 255); -color: rgb(255, 5,0); -} - -QPushButton:disabled { -background-color: rgb(255, 227, 213); -color: rgb(255, 255, 255); -} - - - - - - - 25 - - - 25 - - - 25 - - - 25 - - - - - - 0 - 0 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - Drag the line or double click on a point to select the parameters - - - - - - - - 0 - 0 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - - - Max. No. of Refs - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - 1 - - - 10 - - - 2 - - - - - - - - - - - Try All Cobinations - - - - - - - false - - - Fit With Selected - - - - - - - - - - color: rgb(255, 75, 52); -font: 10pt "MS Shell Dlg 2"; - - - N Combinations - - - Qt::AlignCenter - - - - - - - selection-color: rgb(0, 170, 127); - - - 1 - - - - - - - - - Sort by - - - - - - - - Fit Number - - - - - Reduced Chi-Square - - - - - R-Factor - - - - - R-Square - - - - - Chi-Square - - - - - - - - - - - - - - - 0 - 0 - 986 - 22 - - - - - File - - - - - - - - - Export Results (.csv) - - - - - - PlotWidget - QGraphicsView -
pyqtgraph
-
-
- - -
diff --git a/xmidas/uis/SVGs/Arrow Down.svg b/xmidas/uis/SVGs/Arrow Down.svg deleted file mode 100644 index cce1eec..0000000 --- a/xmidas/uis/SVGs/Arrow Down.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - diff --git a/xmidas/uis/SVGs/Arrow Left.svg b/xmidas/uis/SVGs/Arrow Left.svg deleted file mode 100644 index 93a3cd4..0000000 --- a/xmidas/uis/SVGs/Arrow Left.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - diff --git a/xmidas/uis/SVGs/Arrow Right.svg b/xmidas/uis/SVGs/Arrow Right.svg deleted file mode 100644 index fb1f0e1..0000000 --- a/xmidas/uis/SVGs/Arrow Right.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - diff --git a/xmidas/uis/SVGs/Arrow Up.svg b/xmidas/uis/SVGs/Arrow Up.svg deleted file mode 100644 index 40dbd57..0000000 --- a/xmidas/uis/SVGs/Arrow Up.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - diff --git a/xmidas/uis/SVGs/Basket.svg b/xmidas/uis/SVGs/Basket.svg deleted file mode 100644 index e33eea3..0000000 --- a/xmidas/uis/SVGs/Basket.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - diff --git a/xmidas/uis/SVGs/Book.svg b/xmidas/uis/SVGs/Book.svg deleted file mode 100644 index 27d79f2..0000000 --- a/xmidas/uis/SVGs/Book.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - diff --git a/xmidas/uis/SVGs/Calendar.svg b/xmidas/uis/SVGs/Calendar.svg deleted file mode 100644 index 8e6ee76..0000000 --- a/xmidas/uis/SVGs/Calendar.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - diff --git a/xmidas/uis/SVGs/Camera.svg b/xmidas/uis/SVGs/Camera.svg deleted file mode 100644 index 80b9e35..0000000 --- a/xmidas/uis/SVGs/Camera.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - diff --git a/xmidas/uis/SVGs/Case.svg b/xmidas/uis/SVGs/Case.svg deleted file mode 100644 index 173d397..0000000 --- a/xmidas/uis/SVGs/Case.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - diff --git a/xmidas/uis/SVGs/Change View.svg b/xmidas/uis/SVGs/Change View.svg deleted file mode 100644 index 9332cfc..0000000 --- a/xmidas/uis/SVGs/Change View.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - diff --git a/xmidas/uis/SVGs/Check V2.svg b/xmidas/uis/SVGs/Check V2.svg deleted file mode 100644 index c8a5e40..0000000 --- a/xmidas/uis/SVGs/Check V2.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - diff --git a/xmidas/uis/SVGs/Check.svg b/xmidas/uis/SVGs/Check.svg deleted file mode 100644 index dadeaed..0000000 --- a/xmidas/uis/SVGs/Check.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - diff --git a/xmidas/uis/SVGs/Chervon Right Circle.svg b/xmidas/uis/SVGs/Chervon Right Circle.svg deleted file mode 100644 index 1492a0b..0000000 --- a/xmidas/uis/SVGs/Chervon Right Circle.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - diff --git a/xmidas/uis/SVGs/Chevron Down Circle.svg b/xmidas/uis/SVGs/Chevron Down Circle.svg deleted file mode 100644 index c7ce17b..0000000 --- a/xmidas/uis/SVGs/Chevron Down Circle.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - diff --git a/xmidas/uis/SVGs/Chevron Down.svg b/xmidas/uis/SVGs/Chevron Down.svg deleted file mode 100644 index 56a3576..0000000 --- a/xmidas/uis/SVGs/Chevron Down.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/xmidas/uis/SVGs/Chevron Left Circle.svg b/xmidas/uis/SVGs/Chevron Left Circle.svg deleted file mode 100644 index a0e84b0..0000000 --- a/xmidas/uis/SVGs/Chevron Left Circle.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - diff --git a/xmidas/uis/SVGs/Chevron Left.svg b/xmidas/uis/SVGs/Chevron Left.svg deleted file mode 100644 index f296cd7..0000000 --- a/xmidas/uis/SVGs/Chevron Left.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/xmidas/uis/SVGs/Chevron Right.svg b/xmidas/uis/SVGs/Chevron Right.svg deleted file mode 100644 index f468a3f..0000000 --- a/xmidas/uis/SVGs/Chevron Right.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/xmidas/uis/SVGs/Chevron Up Circle.svg b/xmidas/uis/SVGs/Chevron Up Circle.svg deleted file mode 100644 index 3ebfe80..0000000 --- a/xmidas/uis/SVGs/Chevron Up Circle.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - diff --git a/xmidas/uis/SVGs/Chevron Up.svg b/xmidas/uis/SVGs/Chevron Up.svg deleted file mode 100644 index fc00cf6..0000000 --- a/xmidas/uis/SVGs/Chevron Up.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/xmidas/uis/SVGs/Clock.svg b/xmidas/uis/SVGs/Clock.svg deleted file mode 100644 index 2bc6f3f..0000000 --- a/xmidas/uis/SVGs/Clock.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - diff --git a/xmidas/uis/SVGs/Close.svg b/xmidas/uis/SVGs/Close.svg deleted file mode 100644 index 5e22958..0000000 --- a/xmidas/uis/SVGs/Close.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - diff --git a/xmidas/uis/SVGs/Cog.svg b/xmidas/uis/SVGs/Cog.svg deleted file mode 100644 index 9a39f32..0000000 --- a/xmidas/uis/SVGs/Cog.svg +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - diff --git a/xmidas/uis/SVGs/Cross Circle.svg b/xmidas/uis/SVGs/Cross Circle.svg deleted file mode 100644 index b4d5ebb..0000000 --- a/xmidas/uis/SVGs/Cross Circle.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - diff --git a/xmidas/uis/SVGs/Download.svg b/xmidas/uis/SVGs/Download.svg deleted file mode 100644 index deeac83..0000000 --- a/xmidas/uis/SVGs/Download.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - diff --git a/xmidas/uis/SVGs/Edit V2.svg b/xmidas/uis/SVGs/Edit V2.svg deleted file mode 100644 index 49c8796..0000000 --- a/xmidas/uis/SVGs/Edit V2.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - diff --git a/xmidas/uis/SVGs/Edit.svg b/xmidas/uis/SVGs/Edit.svg deleted file mode 100644 index 7494aef..0000000 --- a/xmidas/uis/SVGs/Edit.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - diff --git a/xmidas/uis/SVGs/File.svg b/xmidas/uis/SVGs/File.svg deleted file mode 100644 index 9dadb9b..0000000 --- a/xmidas/uis/SVGs/File.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - diff --git a/xmidas/uis/SVGs/Grid.svg b/xmidas/uis/SVGs/Grid.svg deleted file mode 100644 index b9792e5..0000000 --- a/xmidas/uis/SVGs/Grid.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - diff --git a/xmidas/uis/SVGs/Heart.svg b/xmidas/uis/SVGs/Heart.svg deleted file mode 100644 index 5f71778..0000000 --- a/xmidas/uis/SVGs/Heart.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - diff --git a/xmidas/uis/SVGs/Image.svg b/xmidas/uis/SVGs/Image.svg deleted file mode 100644 index 8399140..0000000 --- a/xmidas/uis/SVGs/Image.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - diff --git a/xmidas/uis/SVGs/Link.svg b/xmidas/uis/SVGs/Link.svg deleted file mode 100644 index fba631d..0000000 --- a/xmidas/uis/SVGs/Link.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - diff --git a/xmidas/uis/SVGs/Location Cursor.svg b/xmidas/uis/SVGs/Location Cursor.svg deleted file mode 100644 index 65858b3..0000000 --- a/xmidas/uis/SVGs/Location Cursor.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - diff --git a/xmidas/uis/SVGs/Location.svg b/xmidas/uis/SVGs/Location.svg deleted file mode 100644 index 7626878..0000000 --- a/xmidas/uis/SVGs/Location.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - diff --git a/xmidas/uis/SVGs/Logout.svg b/xmidas/uis/SVGs/Logout.svg deleted file mode 100644 index 04d2dde..0000000 --- a/xmidas/uis/SVGs/Logout.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - diff --git a/xmidas/uis/SVGs/Mail.svg b/xmidas/uis/SVGs/Mail.svg deleted file mode 100644 index c64f596..0000000 --- a/xmidas/uis/SVGs/Mail.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - diff --git a/xmidas/uis/SVGs/Menu.svg b/xmidas/uis/SVGs/Menu.svg deleted file mode 100644 index af3578c..0000000 --- a/xmidas/uis/SVGs/Menu.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/xmidas/uis/SVGs/Message.svg b/xmidas/uis/SVGs/Message.svg deleted file mode 100644 index 0dc9f24..0000000 --- a/xmidas/uis/SVGs/Message.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - diff --git a/xmidas/uis/SVGs/Microphone.svg b/xmidas/uis/SVGs/Microphone.svg deleted file mode 100644 index d3bdff4..0000000 --- a/xmidas/uis/SVGs/Microphone.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - diff --git a/xmidas/uis/SVGs/More.svg b/xmidas/uis/SVGs/More.svg deleted file mode 100644 index ad2af87..0000000 --- a/xmidas/uis/SVGs/More.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - diff --git a/xmidas/uis/SVGs/Plus Circle.svg b/xmidas/uis/SVGs/Plus Circle.svg deleted file mode 100644 index be293d9..0000000 --- a/xmidas/uis/SVGs/Plus Circle.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - diff --git a/xmidas/uis/SVGs/Plus.svg b/xmidas/uis/SVGs/Plus.svg deleted file mode 100644 index 9a2a645..0000000 --- a/xmidas/uis/SVGs/Plus.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/xmidas/uis/SVGs/Power Button.svg b/xmidas/uis/SVGs/Power Button.svg deleted file mode 100644 index 2541ea6..0000000 --- a/xmidas/uis/SVGs/Power Button.svg +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - diff --git a/xmidas/uis/SVGs/Printer.svg b/xmidas/uis/SVGs/Printer.svg deleted file mode 100644 index 5ac0097..0000000 --- a/xmidas/uis/SVGs/Printer.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - diff --git a/xmidas/uis/SVGs/Settings.svg b/xmidas/uis/SVGs/Settings.svg deleted file mode 100644 index 28474d0..0000000 --- a/xmidas/uis/SVGs/Settings.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - diff --git a/xmidas/uis/SVGs/Share.svg b/xmidas/uis/SVGs/Share.svg deleted file mode 100644 index 3fe3197..0000000 --- a/xmidas/uis/SVGs/Share.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - diff --git a/xmidas/uis/SVGs/Shutter.svg b/xmidas/uis/SVGs/Shutter.svg deleted file mode 100644 index 92d99e7..0000000 --- a/xmidas/uis/SVGs/Shutter.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - diff --git a/xmidas/uis/SVGs/Star.svg b/xmidas/uis/SVGs/Star.svg deleted file mode 100644 index facd65d..0000000 --- a/xmidas/uis/SVGs/Star.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - diff --git a/xmidas/uis/SVGs/Trash.svg b/xmidas/uis/SVGs/Trash.svg deleted file mode 100644 index ec862c9..0000000 --- a/xmidas/uis/SVGs/Trash.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - diff --git a/xmidas/uis/SVGs/Trophy.svg b/xmidas/uis/SVGs/Trophy.svg deleted file mode 100644 index 050c08d..0000000 --- a/xmidas/uis/SVGs/Trophy.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - diff --git a/xmidas/uis/SVGs/User.svg b/xmidas/uis/SVGs/User.svg deleted file mode 100644 index 71bb60b..0000000 --- a/xmidas/uis/SVGs/User.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - diff --git a/xmidas/uis/SVGs/Video.svg b/xmidas/uis/SVGs/Video.svg deleted file mode 100644 index 6d8869f..0000000 --- a/xmidas/uis/SVGs/Video.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - diff --git a/xmidas/uis/Scatter3D.ui b/xmidas/uis/Scatter3D.ui deleted file mode 100644 index ca2ab8d..0000000 --- a/xmidas/uis/Scatter3D.ui +++ /dev/null @@ -1,130 +0,0 @@ - - - MainWindow - - - - 0 - 0 - 658 - 628 - - - - MainWindow - - - - - - - - - - - - - - 0 - 0 - - - - - - - - - - - - - 0 - 0 - 658 - 21 - - - - - View - - - - Plot Background - - - - - - - - - - - File - - - - - - - - - - - - Export - - - - - Save as PNG - - - - - Generate MultiColor Mask - - - - - Black - - - - - Charcol - - - - - White - - - - - Open Images - - - - - Open a Stack - - - - - Export Image - - - - - - GLViewWidget - QGraphicsView -
pyqtgraph.opengl
-
-
- - -
diff --git a/xmidas/uis/Scatter3D_plotly.ui b/xmidas/uis/Scatter3D_plotly.ui deleted file mode 100644 index 1318496..0000000 --- a/xmidas/uis/Scatter3D_plotly.ui +++ /dev/null @@ -1,120 +0,0 @@ - - - MainWindow - - - - 0 - 0 - 856 - 628 - - - - MainWindow - - - - - - - - - - - - - - 0 - 0 - - - - - - - - - - - - - 0 - 0 - 856 - 21 - - - - - View - - - - Plot Background - - - - - - - - - - - - - - toolBar - - - TopToolBarArea - - - false - - - - - - - - Export - - - - - Save as PNG - - - - - Generate MultiColor Mask - - - - - Black - - - - - Grey - - - - - White - - - - - - QWebEngineView - QGraphicsView -
QtWebEngineWidgets
-
-
- - -
diff --git a/xmidas/uis/ScatterView.ui b/xmidas/uis/ScatterView.ui deleted file mode 100644 index f5394d3..0000000 --- a/xmidas/uis/ScatterView.ui +++ /dev/null @@ -1,249 +0,0 @@ - - - CorrelationPlot - - - - 0 - 0 - 1034 - 859 - - - - Correlation Plot - - - font:10pt "Segoe UI"; - - - - QRadioButton::indicator { - border: 3px solid rgb(150, 150,150); - width: 15px; - height: 15px; - border-radius: 10px; - background: rgb(255, 255, 255); -} -QRadioButton::indicator:hover { - border: 3px solid rgb(58, 66, 81); -} -QRadioButton::indicator:checked { - background: 3px solid rgb(225, 75, 225); - border: 3px solid rgb(255, 252, 255); -} - - - - - - ROI Mask - - - - - - - - color: rgb(255, 0, 0); -background-color: rgb(20, 20, 20); -font: 87 10pt "Segoe UI Black"; - - - - ROI 1 - - - true - - - false - - - - - - - color: rgb(0, 255, 0); -background-color: rgb(20, 20, 20); -font: 87 10pt "Segoe UI Black"; - - - ROI 2 - - - false - - - - - - - color: rgb(0, 255, 255); -background-color: rgb(20, 20, 20); -font: 87 10pt "Segoe UI Black"; - - - ROI 3 - - - false - - - - - - - - - Create Composite Scatter Plot - - - - - - - Apply ROI Mask(s) - - - - - - - Clear Unchecked - - - - - - - Add Checked ROI(s) - - - - - - - - - - 10 - - - 10 - - - 10 - - - 10 - - - - - Image 1 (Blue Shade) - - - Qt::AlignCenter - - - - - - - - - - - - 10 - - - 10 - - - 10 - - - 10 - - - - - Image 2 (Green Shade) - - - Qt::AlignCenter - - - - - - - - - - - - - - - - - 0 - 0 - 1034 - 23 - - - - - File - - - - - - - Plot - - - - - - - - - - - - - Save Plot - - - - - Save Images - - - - - Swap Axes - - - - - - GraphicsLayoutWidget - QGraphicsView -
pyqtgraph
-
- - ImageView - QGraphicsView -
pyqtgraph
-
-
- - -
diff --git a/xmidas/uis/StackViewer.ui b/xmidas/uis/StackViewer.ui deleted file mode 100644 index 62f2665..0000000 --- a/xmidas/uis/StackViewer.ui +++ /dev/null @@ -1,335 +0,0 @@ - - - MainWindow - - - - 0 - 0 - 931 - 815 - - - - MainWindow - - - - - - 11 - 30 - 701 - 326 - - - - - 0 - 0 - - - - - - - 10 - 390 - 891 - 371 - - - - - - - 720 - 80 - 181 - 171 - - - - - 0 - 0 - - - - Image ROI - - - - 11 - - - 11 - - - - - - - - - - - Y End - - - - - - - true - - - - - - - - - - - X Start - - - - - - - true - - - - - - - - - - - Y Start - - - - - - - true - - - - - - - - - - - X End - - - - - - - true - - - - - - - - - - - - - font: 75 10pt "MS Shell Dlg 2"; - - - Size - - - - - - - true - - - - - - - - - - - - - 720 - 250 - 181 - 139 - - - - - 0 - 0 - - - - Spectrum ROI - - - - - - Sync - - - - - - - - - Start - - - - - - - 10000 - - - 2 - - - - - - - - - - - End - - - - - - - 1 - - - 10000 - - - 2 - - - 10 - - - - - - - - - - - font: 75 10pt "MS Shell Dlg 2"; - - - Size - - - - - - - true - - - - - - - - - - - 730 - 10 - 171 - 70 - - - - - - - false - - - background-color: rgb(170, 255, 255); -font: 75 12pt "MS Shell Dlg 2"; - - - Play - - - - - - - Log View - - - - - - - Reset - - - - - - - - - - 0 - 0 - 931 - 26 - - - - - - - - ImageView - QGraphicsView -
pyqtgraph
-
- - PlotWidget - QGraphicsView -
pyqtgraph
-
-
- - -
diff --git a/xmidas/uis/XANESViewer.ui b/xmidas/uis/XANESViewer.ui deleted file mode 100644 index 1209c09..0000000 --- a/xmidas/uis/XANESViewer.ui +++ /dev/null @@ -1,431 +0,0 @@ - - - mainWindow - - - - 0 - 0 - 1089 - 854 - - - - XANES View - - - font: 10pt "Verdana"; - - - - - - QPushButton { -background-color: rgb(175, 236, 255); -color: rgb(255, 5,0); -} - - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - - 0 - 0 - - - - Fit 2D - - - - - - - - - - - E_shift - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - -10.000000000000000 - - - 10.000000000000000 - - - 0.500000000000000 - - - - - - - Alpha: - - - - - - - 10.000000000000000 - - - 0.250000000000000 - - - 0.100000000000000 - - - - - - - - - - - Fitting Model - - - - - - - - NNLS - - - - - LASSO - - - - - RIDGE - - - - - - - - - - - - - - - - - - 0 - 0 - - - - font: 8pt "MS Shell Dlg 2"; -color: rgb(0, 85, 255); - - - Results Text - - - Qt::AlignCenter - - - - - - - - - - - - - - 0 - 0 - - - - ROI Position - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - Qt::Horizontal - - - - - - - - 0 - 0 - - - - - - - - - - - - - 0 - 0 - - - - - - - - - - - - - - Qt::Horizontal - - - - - - - - 0 - 0 - - - - Opan as RGBCMY Image - - - - - - - - 0 - 0 - - - - - - - XANES Maps - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - - - - - - 0 - 0 - - - - Show Component Spectrum - - - - - - - - - - - Live ROI Fit - - - Qt::AlignCenter - - - - - - - - - - - - - - - 0 - 0 - - - - Choose References - - - - - - - - - - References - - - Qt::AlignCenter - - - - - - - - - - - - - - - - 0 - 0 - 1089 - 22 - - - - - Image - - - - - - - Spectrum - - - - - - - Fit - - - - - - - - - - - Export Fit Stats - - - - - Export Ref. Plot - - - - - Save Chem Map - - - - - Save R-factor Image - - - - - false - - - Export References - - - - - Export Fit Stats - - - - - Save Live Fit Data - - - - - - PlotWidget - QGraphicsView -
pyqtgraph
-
- - ImageView - QGraphicsView -
pyqtgraph
-
-
- - -
diff --git a/xmidas/uis/__init__.py b/xmidas/uis/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/xmidas/uis/align_test.ui b/xmidas/uis/align_test.ui deleted file mode 100644 index da5604d..0000000 --- a/xmidas/uis/align_test.ui +++ /dev/null @@ -1,71 +0,0 @@ - - - MainWindow - - - - 0 - 0 - 280 - 271 - - - - MainWindow - - - - - - 100 - 50 - 93 - 28 - - - - Load - - - - - - 100 - 100 - 93 - 28 - - - - Align - - - - - - 100 - 160 - 93 - 28 - - - - Save - - - - - - - 0 - 0 - 280 - 26 - - - - - - - - diff --git a/xmidas/uis/animation.gif b/xmidas/uis/animation.gif deleted file mode 100644 index b5261ca9dd2596268ffff8554552153335797bc7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 94900 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 T9jF6jM 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 B4bA`n diff --git a/xmidas/uis/animation2.gif b/xmidas/uis/animation2.gif deleted file mode 100644 index b5261ca9dd2596268ffff8554552153335797bc7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 94900 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 T9jF6jM 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 B4bA`n diff --git a/xmidas/uis/animationWindow.ui b/xmidas/uis/animationWindow.ui deleted file mode 100644 index b90a5e0..0000000 --- a/xmidas/uis/animationWindow.ui +++ /dev/null @@ -1,68 +0,0 @@ - - - Wait - - - - 0 - 0 - 200 - 200 - - - - Wait... - - - Qt::LeftToRight - - - -background-color: rgba(0, 0, 90, 125); - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - Qt::NoContextMenu - - - - - - - - - false - - - Qt::AlignCenter - - - - - - - - diff --git a/xmidas/uis/animation_atom.gif b/xmidas/uis/animation_atom.gif deleted file mode 100644 index b0f8c7004ef65a145e2566070c92504f9650e216..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 383024 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�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

VI`Lp0%xm3hhZ?pBl$IoObF<(AaBR}2V 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 diff --git a/xmidas/uis/mainwindow_admin.ui b/xmidas/uis/mainwindow_admin.ui deleted file mode 100644 index a7d17b9..0000000 --- a/xmidas/uis/mainwindow_admin.ui +++ /dev/null @@ -1,2814 +0,0 @@ - - - Ajith - MainWindow - - - true - - - - 0 - 0 - 1364 - 1060 - - - - - 0 - 0 - - - - NSLS-II MIDAS - - - - ../pancake.ico../pancake.ico - - - font: 12pt "Segoe UI"; - - - - - true - - - - 0 - 0 - - - - font: 10pt "Segoe UI"; - - -QPushButton { -background-color: rgb(175, 236, 255); -color: rgb(255, 5,0); -} - -QSlider::groove:horizontal { -border: 1px solid #bbb; -background: white; -height: 10px; -border-radius: 4px; -} - -QSlider::sub-page:horizontal { -background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #66e, stop: 1 #bbf); -background: qlineargradient(x1: 0, y1: 0.2, x2: 1, y2: 1, - stop: 0 #bbf, stop: 1 #55f); -border: 1px solid #777; -height: 10px; -border-radius: 4px; -} - -QSlider::add-page:horizontal { -background: #fff; -border: 1px solid #777; -height: 10px; -border-radius: 4px; -} - -QSlider::handle:horizontal { -background: qlineargradient(x1:0, y1:0, x2:1, y2:1, - stop:0 #eee, stop:1 #ccc); -border: 1px solid #777; -width: 13px; -margin-top: -2px; -margin-bottom: -2px; -border-radius: 4px; -} - -QSlider::handle:horizontal:hover { -background: qlineargradient(x1:0, y1:0, x2:1, y2:1, - stop:0 #fff, stop:1 #ddd); -border: 1px solid #444; -border-radius: 2px; -} - -QSlider::sub-page:horizontal:disabled { -background: #bbb; -border-color: #999; -} - -QSlider::add-page:horizontal:disabled { -background: #eee; -border-color: #999; -} - -QSlider::handle:horizontal:disabled { -background: #eee; -border: 1px solid #aaa; -border-radius: 4px; -} - - - - - - - - - 0 - 0 - - - - QFrame::StyledPanel - - - QFrame::Sunken - - - - - - - 0 - 0 - - - - - - - 0 - - - - - 0 - 0 - 411 - 355 - - - - Adjust Image Dimensions - - - - - - - 0 - 0 - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - QLayout::SetMinimumSize - - - - - - 0 - 0 - - - - 0 - - - 500 - - - 0 - - - 10 - - - - - - - - 0 - 0 - - - - 1 - - - 5000 - - - 1200 - - - 10 - - - - - - - - 0 - 0 - - - - false - - - px - - - 1 - - - 10000 - - - 100 - - - - - - - - 0 - 0 - - - - false - - - px - - - 1 - - - 10000 - - - 100 - - - - - - - - 0 - 0 - - - - false - - - px - - - 0 - - - 10000 - - - 0 - - - - - - - - 0 - 0 - - - - Y Dimension - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - false - - - px - - - 0 - - - 10000 - - - 0 - - - - - - - - 0 - 0 - - - - X Dimension - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - Stack Range - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - to - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - to - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - to - - - Qt::AlignCenter - - - - - - - - - - 0 - 0 - - - - Adjust the dimensions of the image - - - - - - Update - - - - - - - - - - - 0 - 0 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - - 0 - 0 - - - - Removes one column/row from all four edges - - - Remove Edges - - - - - - - - - true - - - - 0 - 0 - - - - rebin - - - - - - - true - - - - 0 - 0 - - - - Upscale - - - - - - - - - Ratio - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - true - - - - 0 - 0 - - - - font: 10pt "MS Shell Dlg 2"; - - - 2 - - - 16 - - - 2 - - - 2 - - - - - - - - - - - - - - - - - - 0 - 0 - 334 - 423 - - - - Image Processing - - - - - - - - - - - - - - 0 - 0 - - - - Covert image dat to log values. - - - - - - Log - - - false - - - - - - - - 0 - 0 - - - - Intensity Normalization with the last Frame. - - - Normalize - - - - - - - - - - 0 - 0 - - - - Reverse the arrays. 012 will be 210 - - - Qt::LeftToRight - - - Transpose - - - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - Remove Outliers (NSigma) - - - - - - - false - - - - - - 200 - - - 3 - - - Qt::Horizontal - - - - - - - 1 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - - - Thresholding - - - - - - - - - - - false - - - 100 - - - 5 - - - 5 - - - 5 - - - Qt::Horizontal - - - - - - - 5 - - - - - - - - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - uses savgol_filter to smooth data - - - Smoothen - - - - - - - - - false - - - 3 - - - 12 - - - 2 - - - 2 - - - 3 - - - Qt::Horizontal - - - QSlider::TicksBelow - - - 2 - - - - - - - Window size - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - - - - - 0 - 0 - 420 - 344 - - - - Alignment - - - - - - - - - - - Transformations: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - TRANSLATION - - - - - RIGID_BODY - - - - - SCALED_ROTATION - - - - - AFFINE - - - - - BILINEAR - - - - - - - - - - - - Reference: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - previous - - - - - mean - - - - - first - - - - - - - - - - - - - 0 - 0 - - - - Iterative Mode - - - - - - - - - Max Iter. - - - - - - - - 0 - 0 - - - - 2 - - - 24 - - - - - - - - - - - - 0 - 0 - - - - Align - - - - - - - - - - 0 - 0 - - - - Load Reference Stack - - - - - - - No Ref. Available - - - true - - - - - - - - - - 0 - 0 - - - - Save Transformation File - - - - - - - Use - - - - - - - - 0 - 0 - - - - Load Transformation File - - - - - - - - - - - - - - - 0 - 0 - - - - - - - Reset Image - - - - - - - true - - - 2 - - - - - 0 - 0 - 411 - 318 - - - - Component Analysis - - - - - - - - - 0 - 0 - - - - - - - Calculate Components - - - - - - - - 0 - 0 - - - - - - - PCA Scree Plot - - - - - - - - - Method - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - - PCA - - - - - NMF - - - - - FastICA - - - - - IncrementalPCA - - - - - TruncatedSVD - - - - - FactorAnalysis - - - - - DictionaryLearning - - - - - - - - - - - - Number of Components - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - 1 - - - 4 - - - - - - - - - - - - - 0 - 0 - 411 - 318 - - - - Cluster Analysis - - - - - - - - - 0 - 0 - - - - - - - Calculate Clusters - - - - - - - - 0 - 0 - - - - - - - KMeans Variance Plot - - - - - - - Method - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - - KMeans - - - - - MiniBatchKMeans - - - - - MeanShift - - - - - Spectral Clustering - - - - - Correlation-Kmeans - - - - - Affinity Propagation - - - - - - - - Number of Clusters - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - 1 - - - 4 - - - - - - - - - - - 0 - 0 - 411 - 318 - - - - XANES Fitting - - - - - - - 11 - - - 11 - - - - - - - - 0 - 0 - - - - - - - Load Energy List - - - - - - - keV - - - - - - - - - - - - 0 - 0 - - - - - - - Load Ref. Spec. - - - - - - - - - - Plot - - - - - - - - - true - - - - 0 - 0 - - - - - - - Fit - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - - - - 0 - 0 - - - - font:12pt "Segoe UI"; - - - - - - - QLayout::SetMaximumSize - - - - - - 0 - 0 - - - - - - - Save Image (.tiff) - - - - - - - 0 - - - - Live - - - - - - - 0 - 0 - - - - Send to Collector - - - - - - - - 0 - 0 - - - - - - - Save - - - - - - - - 0 - 0 - - - - - - - - - Normalized - - - - - - Save - - - - - - - Clear - - - - - - - Norm. to Collector - - - - - - - - 0 - 0 - - - - - - - - - Collector - - - - - - - 0 - 0 - - - - - - - - Clear - - - - - - - Save - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - 0 - 0 - - - - - - - - - 0 - 0 - - - - Stack Info - - - - - - - - - - - 0 - 0 - - - - QFrame::StyledPanel - - - QFrame::Sunken - - - - QLayout::SetDefaultConstraint - - - 11 - - - 11 - - - - - - 0 - 0 - - - - ROI Shape - - - - - - - 0 - 0 - - - - Rectangle - - - true - - - - - - - - 0 - 0 - - - - Ellipse - - - - - - - - 0 - 0 - - - - Polygon - - - false - - - - - - - - 0 - 0 - - - - Circle - - - - - - - - 0 - 0 - - - - Line - - - - - - - - 0 - 0 - - - - Show ROI Stack - - - - - - - - - - font: 9pt "Segoe UI"; - - - ROI Positions - - - - - - Spectrum ROI - - - - - - color: rgb(255, 0,0); - - - roi_size - - - - - - - Range (eV): - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - Size (eV): - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - color: rgb(255, 0,0); - - - roix, roiy - - - - - - - - - - Image ROI - - - - - - Position: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - color: rgb(255, 0,0); - - - roix, roiy - - - - - - - - - - Size(pixels): - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - color: rgb(255, 0, 0); - - - roi_size - - - - - - - - - - - - - - 0 - 0 - - - - 2 - - - - - 0 - 0 - 361 - 193 - - - - Image Calculations - - - - - - - - - - - - - - - Add ROI_2 - - - - - - - Calculation: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - - Subtract - - - - - Divide - - - - - Add - - - - - Compare - - - - - - - - - - - - - 0 - 0 - 361 - 193 - - - - Spectrum Calculations - - - - - - - - - - - - - 0 - 0 - - - - Add ROI 2 - - - true - - - false - - - - - - - - - - 0 - 0 - - - - Calculation - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - - Divide - - - - - Subtract - - - - - Add - - - - - Correlation Plot - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - 0 - 0 - 433 - 308 - - - - XANES Normalization - - - - - - - 0 - 0 - - - - to - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - 1 - - - 5 - - - - - - - - 0 - 0 - - - - Eo - - - - - - - - 0 - 0 - - - - eV - - - 1000.000000000000000 - - - 20000.000000000000000 - - - 7125.000000000000000 - - - - - - - - 0 - 0 - - - - calculate the energy point with maximum derivative - - - Auto Eo - - - - - - - - 0 - 0 - - - - eV - - - 2 - - - -500.000000000000000 - - - 500.000000000000000 - - - 1.000000000000000 - - - -50.000000000000000 - - - - - - - - 0 - 0 - - - - Pre-edge - - - - - - - - 0 - 0 - - - - eV - - - -500.000000000000000 - - - 500.000000000000000 - - - -10.000000000000000 - - - - - - - - 0 - 0 - - - - Post-edge - - - - - - - - 0 - 0 - - - - to - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - Norm. Order - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - eV - - - 0.000000000000000 - - - 1000.000000000000000 - - - 25.000000000000000 - - - - - - - - 0 - 0 - - - - <html><head/><body><p> For mbak algorithm only, must be in <span style=" font-weight:600; font-style:italic;">element&lt;space&gt;edge</span> format</p></body></html> - - - Fe K - - - - - - - - 0 - 0 - - - - Element: - - - - - - - - 0 - 0 - - - - eV - - - 0.000000000000000 - - - 1500.000000000000000 - - - 75.000000000000000 - - - - - - - Initial Guess - - - - - - - - 0 - 0 - - - - Apply to Spectrum - - - - - - - Apply to Stack - - - - - - - - - - - - - - Available Stacks - - - - - - - - - - - - 0 - 0 - 1364 - 34 - - - - - Help - - - - - - - File - - - - - - - - - - - true - - - Tools - - - - - - - View - - - - Plot Background - - - - - - - - - - Window Background - - - - - - - - Change_Plot_Line_Width - - - - - - - - - - - - - - - - - Spectrum - - - - - - - - - Image - - - - - - - - - - - - - - - - Open PDF - - - - - Open in GitHub (most updated) - - - - - true - - - Open Image Data - - - Support all tiff and specific h5 files - - - Ctrl+O - - - - - Close - - - - - Exit - - - Ctrl+Q - - - - - false - - - Export Tiff Stack - - - Save the displayed/Modified stack as a tiff file - - - Ctrl+S - - - - - Open PyXRF - - - - - Open Image J - - - - - Open TomViz - - - - - Open Mantis - - - - - Open Athena - - - - - DataBroker - - - - - Open HXN DB - - - - - false - - - Load Energy - - - Load list of energies for XANES stack. Supports only .txt fromat - - - Ctrl+E - - - - - Create a Virtual Stack - - - Create a stack from multiple tiff images of same shape - - - Ctrl+M - - - - - true - - - Open Mask Generator - - - A new window will be opened to creat threshold based masks - - - - - Create elist from log file - - - - - false - - - Save Energy List - - - - - true - - - MultiColorView - - - A new window will be opened to align images in a stack - - - - - White - - - - - true - - - true - - - Black - - - - - Red - - - - - Yellow - - - - - Blue - - - - - false - - - false - - - Dark Mode - - - - - Black - - - - - false - - - false - - - Default - - - - - Vivid - - - - - Save Sum Image - - - - - Subtract ROI as Background - - - - - Export Norm. Params - - - - - 2 - - - - - 4 - - - - - 6 - - - - - 10 - - - - - 2 - - - - - 3 - - - - - 4 - - - - - 5 - - - - - 6 - - - - - 8 - - - - - 10 - - - - - 2 - - - - - Import Norm. Params - - - - - 1 - - - - - Save Sum Spectrum - - - - - Save Mean Spectrum - - - - - Save Current Image as Mask - - - - - - PlotWidget - QGraphicsView -

pyqtgraph
- - - ImageView - QGraphicsView -
pyqtgraph
-
- - - - diff --git a/xmidas/uis/maskedScatterPlotFit.ui b/xmidas/uis/maskedScatterPlotFit.ui deleted file mode 100644 index e8bd894..0000000 --- a/xmidas/uis/maskedScatterPlotFit.ui +++ /dev/null @@ -1,187 +0,0 @@ - - - CorrelationPlot - - - - 0 - 0 - 967 - 816 - - - - Correlation Plot - - - font: 12pt "MS Shell Dlg 2"; - - - - - 10 - - - 25 - - - 10 - - - 10 - - - - - Scatter Plot - - - - - - - 0 - 0 - - - - - - - - - - - Mask - - - - - - - 0 - 0 - - - - - - - - - - - - 0 - 0 - - - - Fit Results - - - - - - Copy - - - - - - - - 0 - 0 - - - - font: 11pt "Consolas"; - - - true - - - - - - - Export - - - - - - - - - - Masked Image1 - - - - - - - 0 - 0 - - - - - - - - - - - - - - 0 - 0 - 967 - 25 - - - - - Export - - - - - - - - - - Scatter Plot+Fit - - - - - Mask - - - - - Masked Image - - - - - - ImageView - QGraphicsView -
pyqtgraph
-
- - GraphicsLayoutWidget - QGraphicsView -
pyqtgraph
-
-
- - -
diff --git a/xmidas/uis/midas.py b/xmidas/uis/midas.py deleted file mode 100644 index 4b0ea40..0000000 --- a/xmidas/uis/midas.py +++ /dev/null @@ -1,1048 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'mainwindow_admin.ui' -# -# Created by: PyQt5 UI code generator 5.14.1 -# -# WARNING! All changes made in this file will be lost! - - -from PyQt5 import QtCore, QtGui, QtWidgets - - -class Ui_MainWindow(object): - def setupUi(self, MainWindow): - MainWindow.setObjectName("MainWindow") - MainWindow.setEnabled(True) - MainWindow.resize(1246, 936) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth()) - MainWindow.setSizePolicy(sizePolicy) - MainWindow.setStyleSheet("font: 10pt \"Segoe UI\";\n" -"\n" -"\n" -"QSlider::groove:horizontal {\n" -"border: 1px solid #bbb;\n" -"background: white;\n" -"height: 10px;\n" -"border-radius: 4px;\n" -"}\n" -"\n" -"QSlider::sub-page:horizontal {\n" -"background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,\n" -" stop: 0 #66e, stop: 1 #bbf);\n" -"background: qlineargradient(x1: 0, y1: 0.2, x2: 1, y2: 1,\n" -" stop: 0 #bbf, stop: 1 #55f);\n" -"border: 1px solid #777;\n" -"height: 10px;\n" -"border-radius: 4px;\n" -"}\n" -"\n" -"QSlider::add-page:horizontal {\n" -"background: #fff;\n" -"border: 1px solid #777;\n" -"height: 10px;\n" -"border-radius: 4px;\n" -"}\n" -"\n" -"QSlider::handle:horizontal {\n" -"background: qlineargradient(x1:0, y1:0, x2:1, y2:1,\n" -" stop:0 #eee, stop:1 #ccc);\n" -"border: 1px solid #777;\n" -"width: 13px;\n" -"margin-top: -2px;\n" -"margin-bottom: -2px;\n" -"border-radius: 4px;\n" -"}\n" -"\n" -"QSlider::handle:horizontal:hover {\n" -"background: qlineargradient(x1:0, y1:0, x2:1, y2:1,\n" -" stop:0 #fff, stop:1 #ddd);\n" -"border: 1px solid #444;\n" -"border-radius: 4px;\n" -"}\n" -"\n" -"QSlider::sub-page:horizontal:disabled {\n" -"background: #bbb;\n" -"border-color: #999;\n" -"}\n" -"\n" -"QSlider::add-page:horizontal:disabled {\n" -"background: #eee;\n" -"border-color: #999;\n" -"}\n" -"\n" -"QSlider::handle:horizontal:disabled {\n" -"background: #eee;\n" -"border: 1px solid #aaa;\n" -"border-radius: 4px;\n" -"}") - self.centralwidget = QtWidgets.QWidget(MainWindow) - self.centralwidget.setEnabled(False) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.MinimumExpanding) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.centralwidget.sizePolicy().hasHeightForWidth()) - self.centralwidget.setSizePolicy(sizePolicy) - self.centralwidget.setStyleSheet("QSlider::groove:horizontal {\n" -"border: 1px solid #bbb;\n" -"background: white;\n" -"height: 10px;\n" -"border-radius: 4px;\n" -"}\n" -"\n" -"QSlider::sub-page:horizontal {\n" -"background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,\n" -" stop: 0 #66e, stop: 1 #bbf);\n" -"background: qlineargradient(x1: 0, y1: 0.2, x2: 1, y2: 1,\n" -" stop: 0 #bbf, stop: 1 #55f);\n" -"border: 1px solid #777;\n" -"height: 10px;\n" -"border-radius: 4px;\n" -"}\n" -"\n" -"QSlider::add-page:horizontal {\n" -"background: #fff;\n" -"border: 1px solid #777;\n" -"height: 10px;\n" -"border-radius: 4px;\n" -"}\n" -"\n" -"QSlider::handle:horizontal {\n" -"background: qlineargradient(x1:0, y1:0, x2:1, y2:1,\n" -" stop:0 #eee, stop:1 #ccc);\n" -"border: 1px solid #777;\n" -"width: 13px;\n" -"margin-top: -2px;\n" -"margin-bottom: -2px;\n" -"border-radius: 4px;\n" -"}\n" -"\n" -"QSlider::handle:horizontal:hover {\n" -"background: qlineargradient(x1:0, y1:0, x2:1, y2:1,\n" -" stop:0 #fff, stop:1 #ddd);\n" -"border: 1px solid #444;\n" -"border-radius: 4px;\n" -"}\n" -"\n" -"QSlider::sub-page:horizontal:disabled {\n" -"background: #bbb;\n" -"border-color: #999;\n" -"}\n" -"\n" -"QSlider::add-page:horizontal:disabled {\n" -"background: #eee;\n" -"border-color: #999;\n" -"}\n" -"\n" -"QSlider::handle:horizontal:disabled {\n" -"background: #eee;\n" -"border: 1px solid #aaa;\n" -"border-radius: 4px;\n" -"}") - self.centralwidget.setObjectName("centralwidget") - self.gridLayout_16 = QtWidgets.QGridLayout(self.centralwidget) - self.gridLayout_16.setObjectName("gridLayout_16") - self.scrollArea = QtWidgets.QScrollArea(self.centralwidget) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Expanding) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.scrollArea.sizePolicy().hasHeightForWidth()) - self.scrollArea.setSizePolicy(sizePolicy) - self.scrollArea.setStyleSheet("font:12pt \"Segoe UI\";") - self.scrollArea.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustIgnored) - self.scrollArea.setWidgetResizable(True) - self.scrollArea.setAlignment(QtCore.Qt.AlignCenter) - self.scrollArea.setObjectName("scrollArea") - self.scrollAreaWidgetContents = QtWidgets.QWidget() - self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 321, 855)) - self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents") - self.gridLayout_9 = QtWidgets.QGridLayout(self.scrollAreaWidgetContents) - self.gridLayout_9.setObjectName("gridLayout_9") - self.gridLayout_13 = QtWidgets.QGridLayout() - self.gridLayout_13.setObjectName("gridLayout_13") - self.pb_reset_img = QtWidgets.QPushButton(self.scrollAreaWidgetContents) - self.pb_reset_img.setStyleSheet("background-color: rgb(175, 236, 255);\n" -"color: rgb(255, 0, 127);\n" -"") - self.pb_reset_img.setObjectName("pb_reset_img") - self.gridLayout_13.addWidget(self.pb_reset_img, 0, 0, 1, 1) - self.gridLayout_9.addLayout(self.gridLayout_13, 1, 0, 1, 1) - self.toolBox = QtWidgets.QToolBox(self.scrollAreaWidgetContents) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.toolBox.sizePolicy().hasHeightForWidth()) - self.toolBox.setSizePolicy(sizePolicy) - self.toolBox.setStyleSheet("font: 10pt \"Segoe UI\";") - self.toolBox.setObjectName("toolBox") - self.page = QtWidgets.QWidget() - self.page.setGeometry(QtCore.QRect(0, 0, 368, 331)) - self.page.setObjectName("page") - self.gridLayout_31 = QtWidgets.QGridLayout(self.page) - self.gridLayout_31.setObjectName("gridLayout_31") - self.frame_7 = QtWidgets.QFrame(self.page) - self.frame_7.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.frame_7.setFrameShadow(QtWidgets.QFrame.Raised) - self.frame_7.setObjectName("frame_7") - self.gridLayout_30 = QtWidgets.QGridLayout(self.frame_7) - self.gridLayout_30.setObjectName("gridLayout_30") - self.gridLayout_17 = QtWidgets.QGridLayout() - self.gridLayout_17.setSizeConstraint(QtWidgets.QLayout.SetMinimumSize) - self.gridLayout_17.setObjectName("gridLayout_17") - self.sb_zrange1 = QtWidgets.QSpinBox(self.frame_7) - self.sb_zrange1.setMinimum(0) - self.sb_zrange1.setMaximum(500) - self.sb_zrange1.setProperty("value", 0) - self.sb_zrange1.setDisplayIntegerBase(10) - self.sb_zrange1.setObjectName("sb_zrange1") - self.gridLayout_17.addWidget(self.sb_zrange1, 0, 1, 1, 1) - self.label_5 = QtWidgets.QLabel(self.frame_7) - self.label_5.setAlignment(QtCore.Qt.AlignCenter) - self.label_5.setObjectName("label_5") - self.gridLayout_17.addWidget(self.label_5, 1, 2, 1, 1) - self.label_9 = QtWidgets.QLabel(self.frame_7) - self.label_9.setAlignment(QtCore.Qt.AlignCenter) - self.label_9.setObjectName("label_9") - self.gridLayout_17.addWidget(self.label_9, 2, 2, 1, 1) - self.sb_yrange2 = QtWidgets.QSpinBox(self.frame_7) - self.sb_yrange2.setReadOnly(False) - self.sb_yrange2.setMinimum(1) - self.sb_yrange2.setMaximum(10000) - self.sb_yrange2.setProperty("value", 100) - self.sb_yrange2.setObjectName("sb_yrange2") - self.gridLayout_17.addWidget(self.sb_yrange2, 2, 3, 1, 1) - self.sb_zrange2 = QtWidgets.QSpinBox(self.frame_7) - self.sb_zrange2.setMinimum(1) - self.sb_zrange2.setMaximum(5000) - self.sb_zrange2.setProperty("value", 1200) - self.sb_zrange2.setDisplayIntegerBase(10) - self.sb_zrange2.setObjectName("sb_zrange2") - self.gridLayout_17.addWidget(self.sb_zrange2, 0, 3, 1, 1) - self.sb_xrange1 = QtWidgets.QSpinBox(self.frame_7) - self.sb_xrange1.setReadOnly(False) - self.sb_xrange1.setMinimum(0) - self.sb_xrange1.setMaximum(10000) - self.sb_xrange1.setProperty("value", 0) - self.sb_xrange1.setObjectName("sb_xrange1") - self.gridLayout_17.addWidget(self.sb_xrange1, 1, 1, 1, 1) - self.sb_xrange2 = QtWidgets.QSpinBox(self.frame_7) - self.sb_xrange2.setReadOnly(False) - self.sb_xrange2.setMinimum(1) - self.sb_xrange2.setMaximum(10000) - self.sb_xrange2.setProperty("value", 100) - self.sb_xrange2.setObjectName("sb_xrange2") - self.gridLayout_17.addWidget(self.sb_xrange2, 1, 3, 1, 1) - self.label_22 = QtWidgets.QLabel(self.frame_7) - self.label_22.setAlignment(QtCore.Qt.AlignCenter) - self.label_22.setObjectName("label_22") - self.gridLayout_17.addWidget(self.label_22, 0, 2, 1, 1) - self.label_19 = QtWidgets.QLabel(self.frame_7) - self.label_19.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) - self.label_19.setObjectName("label_19") - self.gridLayout_17.addWidget(self.label_19, 1, 0, 1, 1) - self.sb_yrange1 = QtWidgets.QSpinBox(self.frame_7) - self.sb_yrange1.setReadOnly(False) - self.sb_yrange1.setMinimum(0) - self.sb_yrange1.setMaximum(10000) - self.sb_yrange1.setProperty("value", 0) - self.sb_yrange1.setObjectName("sb_yrange1") - self.gridLayout_17.addWidget(self.sb_yrange1, 2, 1, 1, 1) - self.label_15 = QtWidgets.QLabel(self.frame_7) - self.label_15.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) - self.label_15.setObjectName("label_15") - self.gridLayout_17.addWidget(self.label_15, 2, 0, 1, 1) - self.label_20 = QtWidgets.QLabel(self.frame_7) - self.label_20.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) - self.label_20.setObjectName("label_20") - self.gridLayout_17.addWidget(self.label_20, 0, 0, 1, 1) - self.gridLayout_30.addLayout(self.gridLayout_17, 0, 0, 1, 1) - self.pb_crop = QtWidgets.QPushButton(self.frame_7) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.pb_crop.sizePolicy().hasHeightForWidth()) - self.pb_crop.setSizePolicy(sizePolicy) - self.pb_crop.setStyleSheet("background-color: rgb(175, 236, 255);\n" -"color: rgb(255, 0, 127);\n" -"") - self.pb_crop.setObjectName("pb_crop") - self.gridLayout_30.addWidget(self.pb_crop, 1, 0, 1, 1) - self.gridLayout_31.addWidget(self.frame_7, 1, 0, 1, 1) - self.frame_6 = QtWidgets.QFrame(self.page) - self.frame_6.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.frame_6.setFrameShadow(QtWidgets.QFrame.Raised) - self.frame_6.setObjectName("frame_6") - self.gridLayout_7 = QtWidgets.QGridLayout(self.frame_6) - self.gridLayout_7.setObjectName("gridLayout_7") - self.horizontalLayout_9 = QtWidgets.QHBoxLayout() - self.horizontalLayout_9.setObjectName("horizontalLayout_9") - self.cb_rebin = QtWidgets.QCheckBox(self.frame_6) - self.cb_rebin.setEnabled(False) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.cb_rebin.sizePolicy().hasHeightForWidth()) - self.cb_rebin.setSizePolicy(sizePolicy) - self.cb_rebin.setObjectName("cb_rebin") - self.horizontalLayout_9.addWidget(self.cb_rebin) - self.horizontalLayout_10 = QtWidgets.QHBoxLayout() - self.horizontalLayout_10.setObjectName("horizontalLayout_10") - self.cb_upscale = QtWidgets.QCheckBox(self.frame_6) - self.cb_upscale.setEnabled(False) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.cb_upscale.sizePolicy().hasHeightForWidth()) - self.cb_upscale.setSizePolicy(sizePolicy) - self.cb_upscale.setObjectName("cb_upscale") - self.horizontalLayout_10.addWidget(self.cb_upscale) - self.horizontalLayout_9.addLayout(self.horizontalLayout_10) - self.sb_scaling_factor = QtWidgets.QSpinBox(self.frame_6) - self.sb_scaling_factor.setEnabled(False) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.sb_scaling_factor.sizePolicy().hasHeightForWidth()) - self.sb_scaling_factor.setSizePolicy(sizePolicy) - self.sb_scaling_factor.setStyleSheet("font: 10pt \"MS Shell Dlg 2\";") - self.sb_scaling_factor.setMinimum(2) - self.sb_scaling_factor.setMaximum(16) - self.sb_scaling_factor.setSingleStep(2) - self.sb_scaling_factor.setProperty("value", 2) - self.sb_scaling_factor.setObjectName("sb_scaling_factor") - self.horizontalLayout_9.addWidget(self.sb_scaling_factor) - self.gridLayout_7.addLayout(self.horizontalLayout_9, 2, 0, 1, 1) - self.cb_remove_edges = QtWidgets.QCheckBox(self.frame_6) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.cb_remove_edges.sizePolicy().hasHeightForWidth()) - self.cb_remove_edges.setSizePolicy(sizePolicy) - self.cb_remove_edges.setObjectName("cb_remove_edges") - self.gridLayout_7.addWidget(self.cb_remove_edges, 0, 0, 1, 1) - self.gridLayout_31.addWidget(self.frame_6, 2, 0, 1, 1) - spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.gridLayout_31.addItem(spacerItem, 0, 0, 1, 1) - spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.gridLayout_31.addItem(spacerItem1, 3, 0, 1, 1) - self.toolBox.addItem(self.page, "") - self.page_2 = QtWidgets.QWidget() - self.page_2.setGeometry(QtCore.QRect(0, 0, 299, 462)) - self.page_2.setObjectName("page_2") - self.gridLayout_8 = QtWidgets.QGridLayout(self.page_2) - self.gridLayout_8.setObjectName("gridLayout_8") - self.groupBox = QtWidgets.QGroupBox(self.page_2) - self.groupBox.setTitle("") - self.groupBox.setObjectName("groupBox") - self.gridLayout_28 = QtWidgets.QGridLayout(self.groupBox) - self.gridLayout_28.setObjectName("gridLayout_28") - self.frame = QtWidgets.QFrame(self.groupBox) - self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.frame.setFrameShadow(QtWidgets.QFrame.Raised) - self.frame.setObjectName("frame") - self.gridLayout_27 = QtWidgets.QGridLayout(self.frame) - self.gridLayout_27.setObjectName("gridLayout_27") - self.groupBox_9 = QtWidgets.QGroupBox(self.frame) - self.groupBox_9.setObjectName("groupBox_9") - self.gridLayout_24 = QtWidgets.QGridLayout(self.groupBox_9) - self.gridLayout_24.setObjectName("gridLayout_24") - self.verticalLayout_3 = QtWidgets.QVBoxLayout() - self.verticalLayout_3.setObjectName("verticalLayout_3") - self.horizontalLayout_7 = QtWidgets.QHBoxLayout() - self.horizontalLayout_7.setObjectName("horizontalLayout_7") - self.cb_log = QtWidgets.QCheckBox(self.groupBox_9) - self.cb_log.setStyleSheet("") - self.cb_log.setChecked(False) - self.cb_log.setObjectName("cb_log") - self.horizontalLayout_7.addWidget(self.cb_log) - self.cb_norm = QtWidgets.QCheckBox(self.groupBox_9) - self.cb_norm.setObjectName("cb_norm") - self.horizontalLayout_7.addWidget(self.cb_norm) - self.verticalLayout_3.addLayout(self.horizontalLayout_7) - self.cb_transpose = QtWidgets.QCheckBox(self.groupBox_9) - self.cb_transpose.setLayoutDirection(QtCore.Qt.LeftToRight) - self.cb_transpose.setObjectName("cb_transpose") - self.verticalLayout_3.addWidget(self.cb_transpose) - self.gridLayout_24.addLayout(self.verticalLayout_3, 0, 0, 1, 1) - self.gridLayout_27.addWidget(self.groupBox_9, 0, 0, 1, 1) - self.gridLayout_28.addWidget(self.frame, 0, 0, 1, 1) - self.frame_4 = QtWidgets.QFrame(self.groupBox) - self.frame_4.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.frame_4.setFrameShadow(QtWidgets.QFrame.Raised) - self.frame_4.setObjectName("frame_4") - self.gridLayout_25 = QtWidgets.QGridLayout(self.frame_4) - self.gridLayout_25.setObjectName("gridLayout_25") - self.gridLayout_21 = QtWidgets.QGridLayout() - self.gridLayout_21.setObjectName("gridLayout_21") - self.cb_remove_outliers = QtWidgets.QCheckBox(self.frame_4) - self.cb_remove_outliers.setObjectName("cb_remove_outliers") - self.gridLayout_21.addWidget(self.cb_remove_outliers, 0, 0, 1, 1) - self.horizontalLayout = QtWidgets.QHBoxLayout() - self.horizontalLayout.setObjectName("horizontalLayout") - self.hs_nsigma = QtWidgets.QSlider(self.frame_4) - self.hs_nsigma.setEnabled(False) - self.hs_nsigma.setStyleSheet("border-color: rgb(0, 85, 255);") - self.hs_nsigma.setMaximum(200) - self.hs_nsigma.setProperty("value", 3) - self.hs_nsigma.setOrientation(QtCore.Qt.Horizontal) - self.hs_nsigma.setObjectName("hs_nsigma") - self.horizontalLayout.addWidget(self.hs_nsigma) - self.label_nsigma = QtWidgets.QLabel(self.frame_4) - self.label_nsigma.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) - self.label_nsigma.setObjectName("label_nsigma") - self.horizontalLayout.addWidget(self.label_nsigma) - self.gridLayout_21.addLayout(self.horizontalLayout, 1, 0, 1, 1) - self.gridLayout_25.addLayout(self.gridLayout_21, 0, 0, 1, 1) - self.gridLayout_28.addWidget(self.frame_4, 1, 0, 1, 1) - self.frame_3 = QtWidgets.QFrame(self.groupBox) - self.frame_3.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.frame_3.setFrameShadow(QtWidgets.QFrame.Raised) - self.frame_3.setObjectName("frame_3") - self.gridLayout_26 = QtWidgets.QGridLayout(self.frame_3) - self.gridLayout_26.setObjectName("gridLayout_26") - self.gridLayout_5 = QtWidgets.QGridLayout() - self.gridLayout_5.setObjectName("gridLayout_5") - self.horizontalLayout_3 = QtWidgets.QHBoxLayout() - self.horizontalLayout_3.setObjectName("horizontalLayout_3") - self.cb_remove_bg = QtWidgets.QCheckBox(self.frame_3) - self.cb_remove_bg.setObjectName("cb_remove_bg") - self.horizontalLayout_3.addWidget(self.cb_remove_bg) - self.gridLayout_5.addLayout(self.horizontalLayout_3, 0, 0, 1, 1) - self.horizontalLayout_2 = QtWidgets.QHBoxLayout() - self.horizontalLayout_2.setObjectName("horizontalLayout_2") - self.hs_bg_threshold = QtWidgets.QSlider(self.frame_3) - self.hs_bg_threshold.setEnabled(False) - self.hs_bg_threshold.setMaximum(100) - self.hs_bg_threshold.setSingleStep(5) - self.hs_bg_threshold.setPageStep(5) - self.hs_bg_threshold.setProperty("value", 5) - self.hs_bg_threshold.setOrientation(QtCore.Qt.Horizontal) - self.hs_bg_threshold.setObjectName("hs_bg_threshold") - self.horizontalLayout_2.addWidget(self.hs_bg_threshold) - self.label_bg_threshold = QtWidgets.QLabel(self.frame_3) - self.label_bg_threshold.setObjectName("label_bg_threshold") - self.horizontalLayout_2.addWidget(self.label_bg_threshold) - self.gridLayout_5.addLayout(self.horizontalLayout_2, 1, 0, 1, 1) - self.gridLayout_26.addLayout(self.gridLayout_5, 0, 0, 1, 1) - self.gridLayout_28.addWidget(self.frame_3, 2, 0, 1, 1) - self.frame_2 = QtWidgets.QFrame(self.groupBox) - self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised) - self.frame_2.setObjectName("frame_2") - self.gridLayout_3 = QtWidgets.QGridLayout(self.frame_2) - self.gridLayout_3.setObjectName("gridLayout_3") - self.cb_smooth = QtWidgets.QCheckBox(self.frame_2) - self.cb_smooth.setObjectName("cb_smooth") - self.gridLayout_3.addWidget(self.cb_smooth, 0, 0, 1, 1) - self.horizontalLayout_4 = QtWidgets.QHBoxLayout() - self.horizontalLayout_4.setObjectName("horizontalLayout_4") - self.hs_smooth_size = QtWidgets.QSlider(self.frame_2) - self.hs_smooth_size.setEnabled(False) - self.hs_smooth_size.setMinimum(3) - self.hs_smooth_size.setMaximum(12) - self.hs_smooth_size.setSingleStep(2) - self.hs_smooth_size.setPageStep(2) - self.hs_smooth_size.setProperty("value", 3) - self.hs_smooth_size.setOrientation(QtCore.Qt.Horizontal) - self.hs_smooth_size.setTickPosition(QtWidgets.QSlider.TicksBelow) - self.hs_smooth_size.setTickInterval(2) - self.hs_smooth_size.setObjectName("hs_smooth_size") - self.horizontalLayout_4.addWidget(self.hs_smooth_size) - self.smooth_winow_size = QtWidgets.QLabel(self.frame_2) - self.smooth_winow_size.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) - self.smooth_winow_size.setObjectName("smooth_winow_size") - self.horizontalLayout_4.addWidget(self.smooth_winow_size) - self.gridLayout_3.addLayout(self.horizontalLayout_4, 1, 0, 1, 1) - self.gridLayout_28.addWidget(self.frame_2, 3, 0, 1, 1) - self.gridLayout_8.addWidget(self.groupBox, 0, 0, 1, 1) - self.toolBox.addItem(self.page_2, "") - self.gridLayout_9.addWidget(self.toolBox, 0, 0, 1, 1) - spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) - self.gridLayout_9.addItem(spacerItem2, 2, 0, 1, 1) - self.toolBox_2 = QtWidgets.QToolBox(self.scrollAreaWidgetContents) - self.toolBox_2.setObjectName("toolBox_2") - self.page_5 = QtWidgets.QWidget() - self.page_5.setGeometry(QtCore.QRect(0, 0, 298, 189)) - self.page_5.setObjectName("page_5") - self.gridLayout_15 = QtWidgets.QGridLayout(self.page_5) - self.gridLayout_15.setObjectName("gridLayout_15") - self.gridLayout = QtWidgets.QGridLayout() - self.gridLayout.setObjectName("gridLayout") - self.pb_calc_components = QtWidgets.QPushButton(self.page_5) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.pb_calc_components.sizePolicy().hasHeightForWidth()) - self.pb_calc_components.setSizePolicy(sizePolicy) - self.pb_calc_components.setStyleSheet("background-color: rgb(175, 236, 255);\n" -"color: rgb(255, 0, 127);\n" -"") - self.pb_calc_components.setObjectName("pb_calc_components") - self.gridLayout.addWidget(self.pb_calc_components, 0, 0, 1, 1) - self.pb_pca_scree = QtWidgets.QPushButton(self.page_5) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.pb_pca_scree.sizePolicy().hasHeightForWidth()) - self.pb_pca_scree.setSizePolicy(sizePolicy) - self.pb_pca_scree.setStyleSheet("background-color: rgb(175, 236, 255);\n" -"color: rgb(255, 0, 127);\n" -"") - self.pb_pca_scree.setObjectName("pb_pca_scree") - self.gridLayout.addWidget(self.pb_pca_scree, 1, 0, 1, 1) - self.horizontalLayout_5 = QtWidgets.QHBoxLayout() - self.horizontalLayout_5.setObjectName("horizontalLayout_5") - self.label_11 = QtWidgets.QLabel(self.page_5) - self.label_11.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) - self.label_11.setObjectName("label_11") - self.horizontalLayout_5.addWidget(self.label_11) - self.cb_comp_method = QtWidgets.QComboBox(self.page_5) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.cb_comp_method.sizePolicy().hasHeightForWidth()) - self.cb_comp_method.setSizePolicy(sizePolicy) - self.cb_comp_method.setObjectName("cb_comp_method") - self.cb_comp_method.addItem("") - self.cb_comp_method.addItem("") - self.cb_comp_method.addItem("") - self.cb_comp_method.addItem("") - self.cb_comp_method.addItem("") - self.cb_comp_method.addItem("") - self.cb_comp_method.addItem("") - self.horizontalLayout_5.addWidget(self.cb_comp_method) - self.gridLayout.addLayout(self.horizontalLayout_5, 2, 0, 1, 1) - self.horizontalLayout_6 = QtWidgets.QHBoxLayout() - self.horizontalLayout_6.setObjectName("horizontalLayout_6") - self.label = QtWidgets.QLabel(self.page_5) - self.label.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) - self.label.setObjectName("label") - self.horizontalLayout_6.addWidget(self.label) - self.sb_ncomp = QtWidgets.QSpinBox(self.page_5) - self.sb_ncomp.setMinimum(1) - self.sb_ncomp.setProperty("value", 4) - self.sb_ncomp.setObjectName("sb_ncomp") - self.horizontalLayout_6.addWidget(self.sb_ncomp) - self.gridLayout.addLayout(self.horizontalLayout_6, 3, 0, 1, 1) - self.gridLayout_15.addLayout(self.gridLayout, 0, 0, 1, 1) - self.toolBox_2.addItem(self.page_5, "") - self.page_6 = QtWidgets.QWidget() - self.page_6.setGeometry(QtCore.QRect(0, 0, 308, 185)) - self.page_6.setObjectName("page_6") - self.gridLayout_18 = QtWidgets.QGridLayout(self.page_6) - self.gridLayout_18.setObjectName("gridLayout_18") - self.gridLayout_4 = QtWidgets.QGridLayout() - self.gridLayout_4.setObjectName("gridLayout_4") - self.pb_calc_cluster = QtWidgets.QPushButton(self.page_6) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.pb_calc_cluster.sizePolicy().hasHeightForWidth()) - self.pb_calc_cluster.setSizePolicy(sizePolicy) - self.pb_calc_cluster.setStyleSheet("background-color: rgb(175, 236, 255);\n" -"color: rgb(255, 0, 127);\n" -"") - self.pb_calc_cluster.setObjectName("pb_calc_cluster") - self.gridLayout_4.addWidget(self.pb_calc_cluster, 0, 0, 1, 3) - self.pb_kmeans_elbow = QtWidgets.QPushButton(self.page_6) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.pb_kmeans_elbow.sizePolicy().hasHeightForWidth()) - self.pb_kmeans_elbow.setSizePolicy(sizePolicy) - self.pb_kmeans_elbow.setStyleSheet("background-color: rgb(175, 236, 255);\n" -"color: rgb(255, 0, 127);\n" -"") - self.pb_kmeans_elbow.setObjectName("pb_kmeans_elbow") - self.gridLayout_4.addWidget(self.pb_kmeans_elbow, 1, 0, 1, 3) - self.label_10 = QtWidgets.QLabel(self.page_6) - self.label_10.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) - self.label_10.setObjectName("label_10") - self.gridLayout_4.addWidget(self.label_10, 2, 0, 1, 1) - self.cb_clust_method = QtWidgets.QComboBox(self.page_6) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.cb_clust_method.sizePolicy().hasHeightForWidth()) - self.cb_clust_method.setSizePolicy(sizePolicy) - self.cb_clust_method.setObjectName("cb_clust_method") - self.cb_clust_method.addItem("") - self.cb_clust_method.addItem("") - self.cb_clust_method.addItem("") - self.cb_clust_method.addItem("") - self.cb_clust_method.addItem("") - self.cb_clust_method.addItem("") - self.gridLayout_4.addWidget(self.cb_clust_method, 2, 1, 1, 2) - self.label_2 = QtWidgets.QLabel(self.page_6) - self.label_2.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) - self.label_2.setObjectName("label_2") - self.gridLayout_4.addWidget(self.label_2, 3, 0, 1, 2) - self.sb_ncluster = QtWidgets.QSpinBox(self.page_6) - self.sb_ncluster.setMinimum(1) - self.sb_ncluster.setProperty("value", 4) - self.sb_ncluster.setObjectName("sb_ncluster") - self.gridLayout_4.addWidget(self.sb_ncluster, 3, 2, 1, 1) - self.gridLayout_18.addLayout(self.gridLayout_4, 0, 0, 1, 1) - self.toolBox_2.addItem(self.page_6, "") - self.page_7 = QtWidgets.QWidget() - self.page_7.setGeometry(QtCore.QRect(0, 0, 299, 156)) - self.page_7.setObjectName("page_7") - self.gridLayout_20 = QtWidgets.QGridLayout(self.page_7) - self.gridLayout_20.setObjectName("gridLayout_20") - self.gridLayout_2 = QtWidgets.QGridLayout() - self.gridLayout_2.setObjectName("gridLayout_2") - self.pb_elist_xanes = QtWidgets.QPushButton(self.page_7) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.pb_elist_xanes.sizePolicy().hasHeightForWidth()) - self.pb_elist_xanes.setSizePolicy(sizePolicy) - self.pb_elist_xanes.setStyleSheet("background-color: rgb(175, 236, 255);\n" -"color: rgb(255, 0, 127);\n" -"") - self.pb_elist_xanes.setObjectName("pb_elist_xanes") - self.gridLayout_2.addWidget(self.pb_elist_xanes, 0, 0, 1, 2) - self.cb_kev_flag = QtWidgets.QCheckBox(self.page_7) - self.cb_kev_flag.setObjectName("cb_kev_flag") - self.gridLayout_2.addWidget(self.cb_kev_flag, 0, 2, 1, 1) - self.pb_ref_xanes = QtWidgets.QPushButton(self.page_7) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.pb_ref_xanes.sizePolicy().hasHeightForWidth()) - self.pb_ref_xanes.setSizePolicy(sizePolicy) - self.pb_ref_xanes.setStyleSheet("background-color: rgb(175, 236, 255);\n" -"color: rgb(255, 0, 127);\n" -"") - self.pb_ref_xanes.setObjectName("pb_ref_xanes") - self.gridLayout_2.addWidget(self.pb_ref_xanes, 1, 0, 1, 2) - self.pb_plot_refs = QtWidgets.QPushButton(self.page_7) - self.pb_plot_refs.setStyleSheet("background-color: rgb(175, 236, 255);\n" -"color: rgb(255, 0, 127);") - self.pb_plot_refs.setObjectName("pb_plot_refs") - self.gridLayout_2.addWidget(self.pb_plot_refs, 1, 2, 1, 1) - self.cb_xanes_fitting_method = QtWidgets.QComboBox(self.page_7) - self.cb_xanes_fitting_method.setObjectName("cb_xanes_fitting_method") - self.cb_xanes_fitting_method.addItem("") - self.gridLayout_2.addWidget(self.cb_xanes_fitting_method, 2, 0, 1, 1) - self.pb_xanes_fit = QtWidgets.QPushButton(self.page_7) - self.pb_xanes_fit.setEnabled(False) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.pb_xanes_fit.sizePolicy().hasHeightForWidth()) - self.pb_xanes_fit.setSizePolicy(sizePolicy) - self.pb_xanes_fit.setStyleSheet("background-color: rgb(175, 236, 255);\n" -"color: rgb(255, 0, 127);\n" -"") - self.pb_xanes_fit.setObjectName("pb_xanes_fit") - self.gridLayout_2.addWidget(self.pb_xanes_fit, 2, 1, 1, 2) - self.gridLayout_20.addLayout(self.gridLayout_2, 0, 0, 1, 1) - spacerItem3 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.gridLayout_20.addItem(spacerItem3, 1, 0, 1, 1) - self.toolBox_2.addItem(self.page_7, "") - self.gridLayout_9.addWidget(self.toolBox_2, 3, 0, 1, 1) - self.scrollArea.setWidget(self.scrollAreaWidgetContents) - self.gridLayout_16.addWidget(self.scrollArea, 0, 0, 1, 1) - self.groupBox_6 = QtWidgets.QGroupBox(self.centralwidget) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.groupBox_6.sizePolicy().hasHeightForWidth()) - self.groupBox_6.setSizePolicy(sizePolicy) - self.groupBox_6.setStyleSheet("font:12pt \"Segoe UI\";") - self.groupBox_6.setTitle("") - self.groupBox_6.setObjectName("groupBox_6") - self.gridLayout_29 = QtWidgets.QGridLayout(self.groupBox_6) - self.gridLayout_29.setObjectName("gridLayout_29") - self.frame_5 = QtWidgets.QFrame(self.groupBox_6) - self.frame_5.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.frame_5.setFrameShadow(QtWidgets.QFrame.Raised) - self.frame_5.setObjectName("frame_5") - self.gridLayout_23 = QtWidgets.QGridLayout(self.frame_5) - self.gridLayout_23.setObjectName("gridLayout_23") - self.groupBox_8 = QtWidgets.QGroupBox(self.frame_5) - self.groupBox_8.setStyleSheet("font: 9pt \"Segoe UI\";") - self.groupBox_8.setObjectName("groupBox_8") - self.gridLayout_19 = QtWidgets.QGridLayout(self.groupBox_8) - self.gridLayout_19.setObjectName("gridLayout_19") - self.groupBox_5 = QtWidgets.QGroupBox(self.groupBox_8) - self.groupBox_5.setObjectName("groupBox_5") - self.gridLayout_11 = QtWidgets.QGridLayout(self.groupBox_5) - self.gridLayout_11.setObjectName("gridLayout_11") - self.le_spec_roi_size = QtWidgets.QLabel(self.groupBox_5) - self.le_spec_roi_size.setStyleSheet("color: rgb(255, 0,0);") - self.le_spec_roi_size.setObjectName("le_spec_roi_size") - self.gridLayout_11.addWidget(self.le_spec_roi_size, 1, 1, 1, 1) - self.label_8 = QtWidgets.QLabel(self.groupBox_5) - self.label_8.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) - self.label_8.setObjectName("label_8") - self.gridLayout_11.addWidget(self.label_8, 0, 0, 1, 1) - self.label_29 = QtWidgets.QLabel(self.groupBox_5) - self.label_29.setStyleSheet("") - self.label_29.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) - self.label_29.setObjectName("label_29") - self.gridLayout_11.addWidget(self.label_29, 1, 0, 1, 1) - self.le_spec_roi = QtWidgets.QLabel(self.groupBox_5) - self.le_spec_roi.setStyleSheet("color: rgb(255, 0,0);") - self.le_spec_roi.setObjectName("le_spec_roi") - self.gridLayout_11.addWidget(self.le_spec_roi, 0, 1, 1, 1) - self.gridLayout_19.addWidget(self.groupBox_5, 0, 1, 1, 1) - self.groupBox_4 = QtWidgets.QGroupBox(self.groupBox_8) - self.groupBox_4.setObjectName("groupBox_4") - self.gridLayout_12 = QtWidgets.QGridLayout(self.groupBox_4) - self.gridLayout_12.setObjectName("gridLayout_12") - self.label_4 = QtWidgets.QLabel(self.groupBox_4) - self.label_4.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) - self.label_4.setObjectName("label_4") - self.gridLayout_12.addWidget(self.label_4, 0, 0, 1, 1) - self.le_roi = QtWidgets.QLabel(self.groupBox_4) - self.le_roi.setStyleSheet("color: rgb(255, 0,0);") - self.le_roi.setObjectName("le_roi") - self.gridLayout_12.addWidget(self.le_roi, 0, 1, 1, 1) - self.label_28 = QtWidgets.QLabel(self.groupBox_4) - self.label_28.setStyleSheet("") - self.label_28.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) - self.label_28.setObjectName("label_28") - self.gridLayout_12.addWidget(self.label_28, 1, 0, 1, 1) - self.le_roi_size = QtWidgets.QLabel(self.groupBox_4) - self.le_roi_size.setStyleSheet("color: rgb(255, 0, 0);") - self.le_roi_size.setObjectName("le_roi_size") - self.gridLayout_12.addWidget(self.le_roi_size, 1, 1, 1, 1) - self.gridLayout_19.addWidget(self.groupBox_4, 0, 0, 1, 1) - self.gridLayout_23.addWidget(self.groupBox_8, 0, 0, 1, 1) - self.groupBox_3 = QtWidgets.QGroupBox(self.frame_5) - self.groupBox_3.setObjectName("groupBox_3") - self.gridLayout_6 = QtWidgets.QGridLayout(self.groupBox_3) - self.gridLayout_6.setObjectName("gridLayout_6") - self.rb_math_roi_img = QtWidgets.QRadioButton(self.groupBox_3) - self.rb_math_roi_img.setLayoutDirection(QtCore.Qt.LeftToRight) - self.rb_math_roi_img.setObjectName("rb_math_roi_img") - self.gridLayout_6.addWidget(self.rb_math_roi_img, 0, 0, 1, 1) - self.pb_reset_roi_2 = QtWidgets.QPushButton(self.groupBox_3) - self.pb_reset_roi_2.setStyleSheet("background-color: rgb(175, 236, 255);") - self.pb_reset_roi_2.setObjectName("pb_reset_roi_2") - self.gridLayout_6.addWidget(self.pb_reset_roi_2, 0, 1, 1, 1) - self.label_14 = QtWidgets.QLabel(self.groupBox_3) - self.label_14.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) - self.label_14.setObjectName("label_14") - self.gridLayout_6.addWidget(self.label_14, 1, 0, 1, 1) - self.cb_img_roi_action = QtWidgets.QComboBox(self.groupBox_3) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.cb_img_roi_action.sizePolicy().hasHeightForWidth()) - self.cb_img_roi_action.setSizePolicy(sizePolicy) - self.cb_img_roi_action.setObjectName("cb_img_roi_action") - self.cb_img_roi_action.addItem("") - self.cb_img_roi_action.addItem("") - self.cb_img_roi_action.addItem("") - self.cb_img_roi_action.addItem("") - self.gridLayout_6.addWidget(self.cb_img_roi_action, 1, 1, 1, 1) - self.gridLayout_23.addWidget(self.groupBox_3, 3, 0, 1, 1) - self.groupBox_7 = QtWidgets.QGroupBox(self.frame_5) - self.groupBox_7.setObjectName("groupBox_7") - self.gridLayout_14 = QtWidgets.QGridLayout(self.groupBox_7) - self.gridLayout_14.setObjectName("gridLayout_14") - self.rb_math_roi = QtWidgets.QRadioButton(self.groupBox_7) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.rb_math_roi.sizePolicy().hasHeightForWidth()) - self.rb_math_roi.setSizePolicy(sizePolicy) - self.rb_math_roi.setCheckable(True) - self.rb_math_roi.setChecked(False) - self.rb_math_roi.setObjectName("rb_math_roi") - self.gridLayout_14.addWidget(self.rb_math_roi, 0, 0, 1, 2) - self.label_13 = QtWidgets.QLabel(self.groupBox_7) - self.label_13.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) - self.label_13.setObjectName("label_13") - self.gridLayout_14.addWidget(self.label_13, 1, 0, 1, 1) - self.cb_roi_operation = QtWidgets.QComboBox(self.groupBox_7) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.cb_roi_operation.sizePolicy().hasHeightForWidth()) - self.cb_roi_operation.setSizePolicy(sizePolicy) - self.cb_roi_operation.setObjectName("cb_roi_operation") - self.cb_roi_operation.addItem("") - self.cb_roi_operation.addItem("") - self.cb_roi_operation.addItem("") - self.cb_roi_operation.addItem("") - self.gridLayout_14.addWidget(self.cb_roi_operation, 1, 1, 1, 1) - self.gridLayout_23.addWidget(self.groupBox_7, 10, 0, 1, 1) - self.pb_save_disp_img = QtWidgets.QPushButton(self.frame_5) - self.pb_save_disp_img.setStyleSheet("background-color: rgb(175, 236, 255);\n" -"color: rgb(255, 0, 127);") - self.pb_save_disp_img.setObjectName("pb_save_disp_img") - self.gridLayout_23.addWidget(self.pb_save_disp_img, 13, 0, 1, 1) - spacerItem4 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.gridLayout_23.addItem(spacerItem4, 4, 0, 1, 1) - self.pb_save_disp_spec = QtWidgets.QPushButton(self.frame_5) - self.pb_save_disp_spec.setStyleSheet("background-color: rgb(175, 236, 255);\n" -"color: rgb(255, 0, 127);") - self.pb_save_disp_spec.setObjectName("pb_save_disp_spec") - self.gridLayout_23.addWidget(self.pb_save_disp_spec, 14, 0, 1, 1) - spacerItem5 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.gridLayout_23.addItem(spacerItem5, 12, 0, 1, 1) - self.groupBox_2 = QtWidgets.QGroupBox(self.frame_5) - self.groupBox_2.setObjectName("groupBox_2") - self.gridLayout_22 = QtWidgets.QGridLayout(self.groupBox_2) - self.gridLayout_22.setObjectName("gridLayout_22") - self.verticalLayout = QtWidgets.QVBoxLayout() - self.verticalLayout.setObjectName("verticalLayout") - self.rb_poly_roi = QtWidgets.QRadioButton(self.groupBox_2) - self.rb_poly_roi.setChecked(True) - self.rb_poly_roi.setObjectName("rb_poly_roi") - self.verticalLayout.addWidget(self.rb_poly_roi) - self.rb_rect_roi = QtWidgets.QRadioButton(self.groupBox_2) - self.rb_rect_roi.setObjectName("rb_rect_roi") - self.verticalLayout.addWidget(self.rb_rect_roi) - self.gridLayout_22.addLayout(self.verticalLayout, 0, 0, 1, 2) - self.verticalLayout_2 = QtWidgets.QVBoxLayout() - self.verticalLayout_2.setObjectName("verticalLayout_2") - self.rb_elli_roi = QtWidgets.QRadioButton(self.groupBox_2) - self.rb_elli_roi.setObjectName("rb_elli_roi") - self.verticalLayout_2.addWidget(self.rb_elli_roi) - self.rb_circle_roi = QtWidgets.QRadioButton(self.groupBox_2) - self.rb_circle_roi.setObjectName("rb_circle_roi") - self.verticalLayout_2.addWidget(self.rb_circle_roi) - self.gridLayout_22.addLayout(self.verticalLayout_2, 0, 2, 1, 1) - self.rb_line_roi = QtWidgets.QRadioButton(self.groupBox_2) - self.rb_line_roi.setObjectName("rb_line_roi") - self.gridLayout_22.addWidget(self.rb_line_roi, 1, 0, 1, 1) - self.gridLayout_23.addWidget(self.groupBox_2, 1, 0, 1, 1) - spacerItem6 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.gridLayout_23.addItem(spacerItem6, 2, 0, 1, 1) - self.gridLayout_29.addWidget(self.frame_5, 0, 2, 2, 1) - self.image_view = ImageView(self.groupBox_6) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.image_view.sizePolicy().hasHeightForWidth()) - self.image_view.setSizePolicy(sizePolicy) - self.image_view.setObjectName("image_view") - self.gridLayout_29.addWidget(self.image_view, 0, 1, 1, 1) - self.spectrum_view = PlotWidget(self.groupBox_6) - self.spectrum_view.setObjectName("spectrum_view") - self.gridLayout_29.addWidget(self.spectrum_view, 1, 1, 1, 1) - self.gridLayout_16.addWidget(self.groupBox_6, 0, 1, 1, 1) - MainWindow.setCentralWidget(self.centralwidget) - self.menubar = QtWidgets.QMenuBar(MainWindow) - self.menubar.setGeometry(QtCore.QRect(0, 0, 1246, 29)) - self.menubar.setObjectName("menubar") - self.menuManual = QtWidgets.QMenu(self.menubar) - self.menuManual.setObjectName("menuManual") - self.menuFile = QtWidgets.QMenu(self.menubar) - self.menuFile.setObjectName("menuFile") - self.menuMask = QtWidgets.QMenu(self.menubar) - self.menuMask.setObjectName("menuMask") - MainWindow.setMenuBar(self.menubar) - self.statusbar_main = QtWidgets.QStatusBar(MainWindow) - self.statusbar_main.setObjectName("statusbar_main") - MainWindow.setStatusBar(self.statusbar_main) - self.actionOpen_PDF = QtWidgets.QAction(MainWindow) - self.actionOpen_PDF.setObjectName("actionOpen_PDF") - self.actionOpen_in_GitHub = QtWidgets.QAction(MainWindow) - self.actionOpen_in_GitHub.setObjectName("actionOpen_in_GitHub") - self.actionOpen_Image_Data = QtWidgets.QAction(MainWindow) - self.actionOpen_Image_Data.setEnabled(True) - self.actionOpen_Image_Data.setObjectName("actionOpen_Image_Data") - self.actionClose = QtWidgets.QAction(MainWindow) - self.actionClose.setObjectName("actionClose") - self.actionExit = QtWidgets.QAction(MainWindow) - self.actionExit.setObjectName("actionExit") - self.actionSave_as = QtWidgets.QAction(MainWindow) - self.actionSave_as.setObjectName("actionSave_as") - self.actionOpen_PyXRF = QtWidgets.QAction(MainWindow) - self.actionOpen_PyXRF.setObjectName("actionOpen_PyXRF") - self.actionOpen_Image_J = QtWidgets.QAction(MainWindow) - self.actionOpen_Image_J.setObjectName("actionOpen_Image_J") - self.actionOpen_TomViz = QtWidgets.QAction(MainWindow) - self.actionOpen_TomViz.setObjectName("actionOpen_TomViz") - self.actionOpen_Mantis = QtWidgets.QAction(MainWindow) - self.actionOpen_Mantis.setObjectName("actionOpen_Mantis") - self.actionOpen_Athena = QtWidgets.QAction(MainWindow) - self.actionOpen_Athena.setObjectName("actionOpen_Athena") - self.actionDataBroker = QtWidgets.QAction(MainWindow) - self.actionDataBroker.setObjectName("actionDataBroker") - self.actionOpen_HXN_DB = QtWidgets.QAction(MainWindow) - self.actionOpen_HXN_DB.setObjectName("actionOpen_HXN_DB") - self.actionLoad_Energy = QtWidgets.QAction(MainWindow) - self.actionLoad_Energy.setObjectName("actionLoad_Energy") - self.actionOpen_Multiple_Files = QtWidgets.QAction(MainWindow) - self.actionOpen_Multiple_Files.setObjectName("actionOpen_Multiple_Files") - self.actionOpen_Mask_Gen = QtWidgets.QAction(MainWindow) - self.actionOpen_Mask_Gen.setObjectName("actionOpen_Mask_Gen") - self.actionCreate_elist_from_log = QtWidgets.QAction(MainWindow) - self.actionCreate_elist_from_log.setObjectName("actionCreate_elist_from_log") - self.actionSave_Energy_List = QtWidgets.QAction(MainWindow) - self.actionSave_Energy_List.setObjectName("actionSave_Energy_List") - self.actionAlign_Stack = QtWidgets.QAction(MainWindow) - self.actionAlign_Stack.setObjectName("actionAlign_Stack") - self.menuManual.addSeparator() - self.menuManual.addAction(self.actionOpen_in_GitHub) - self.menuFile.addAction(self.actionOpen_Image_Data) - self.menuFile.addAction(self.actionOpen_Multiple_Files) - self.menuFile.addAction(self.actionLoad_Energy) - self.menuFile.addAction(self.actionSave_Energy_List) - self.menuFile.addAction(self.actionSave_as) - self.menuFile.addAction(self.actionExit) - self.menuMask.addAction(self.actionOpen_Mask_Gen) - self.menuMask.addAction(self.actionAlign_Stack) - self.menubar.addAction(self.menuFile.menuAction()) - self.menubar.addAction(self.menuMask.menuAction()) - self.menubar.addAction(self.menuManual.menuAction()) - - self.retranslateUi(MainWindow) - self.toolBox.setCurrentIndex(1) - self.toolBox_2.setCurrentIndex(2) - QtCore.QMetaObject.connectSlotsByName(MainWindow) - - def retranslateUi(self, MainWindow): - _translate = QtCore.QCoreApplication.translate - MainWindow.setWindowTitle(_translate("MainWindow", "NSLS-II MIDAS")) - self.pb_reset_img.setText(_translate("MainWindow", "Reset Image")) - self.label_5.setText(_translate("MainWindow", "to")) - self.label_9.setText(_translate("MainWindow", "to")) - self.sb_yrange2.setSuffix(_translate("MainWindow", " px")) - self.sb_xrange1.setSuffix(_translate("MainWindow", " px")) - self.sb_xrange2.setSuffix(_translate("MainWindow", " px")) - self.label_22.setText(_translate("MainWindow", "to")) - self.label_19.setText(_translate("MainWindow", "X Dimension")) - self.sb_yrange1.setSuffix(_translate("MainWindow", " px")) - self.label_15.setText(_translate("MainWindow", "Y Dimension")) - self.label_20.setText(_translate("MainWindow", "Stack Range ")) - self.pb_crop.setToolTip(_translate("MainWindow", "Adjust the dimensions of the image")) - self.pb_crop.setText(_translate("MainWindow", "Update")) - self.cb_rebin.setText(_translate("MainWindow", "rebin")) - self.cb_upscale.setText(_translate("MainWindow", "Upscale")) - self.cb_remove_edges.setToolTip(_translate("MainWindow", "Removes one column/row from all four edges")) - self.cb_remove_edges.setText(_translate("MainWindow", "Remove Edges")) - self.toolBox.setItemText(self.toolBox.indexOf(self.page), _translate("MainWindow", "Adjust Image Dimensions")) - self.groupBox_9.setTitle(_translate("MainWindow", "Transform")) - self.cb_log.setToolTip(_translate("MainWindow", "Covert image dat to log values.")) - self.cb_log.setText(_translate("MainWindow", "Log ")) - self.cb_norm.setToolTip(_translate("MainWindow", "Intensity Normalization with the last Frame.")) - self.cb_norm.setText(_translate("MainWindow", "Normalize")) - self.cb_transpose.setToolTip(_translate("MainWindow", "Reverse the arrays. 012 will be 210")) - self.cb_transpose.setText(_translate("MainWindow", "Transpose")) - self.cb_remove_outliers.setText(_translate("MainWindow", "Remove Outliers (NSigma)")) - self.label_nsigma.setText(_translate("MainWindow", "1")) - self.cb_remove_bg.setText(_translate("MainWindow", "Thresholding")) - self.label_bg_threshold.setText(_translate("MainWindow", "5")) - self.cb_smooth.setToolTip(_translate("MainWindow", "uses savgol_filter to smooth data")) - self.cb_smooth.setText(_translate("MainWindow", "Smoothen")) - self.smooth_winow_size.setText(_translate("MainWindow", "Window size")) - self.toolBox.setItemText(self.toolBox.indexOf(self.page_2), _translate("MainWindow", "Image Processing")) - self.pb_calc_components.setText(_translate("MainWindow", "Calculate Components")) - self.pb_pca_scree.setText(_translate("MainWindow", "PCA Scree Plot")) - self.label_11.setText(_translate("MainWindow", "Method")) - self.cb_comp_method.setItemText(0, _translate("MainWindow", "PCA")) - self.cb_comp_method.setItemText(1, _translate("MainWindow", "NMF")) - self.cb_comp_method.setItemText(2, _translate("MainWindow", "FastICA")) - self.cb_comp_method.setItemText(3, _translate("MainWindow", "IncrementalPCA")) - self.cb_comp_method.setItemText(4, _translate("MainWindow", "TruncatedSVD")) - self.cb_comp_method.setItemText(5, _translate("MainWindow", "FactorAnalysis")) - self.cb_comp_method.setItemText(6, _translate("MainWindow", "DictionaryLearning")) - self.label.setText(_translate("MainWindow", "Number of Components")) - self.toolBox_2.setItemText(self.toolBox_2.indexOf(self.page_5), _translate("MainWindow", "Component Analysis")) - self.pb_calc_cluster.setText(_translate("MainWindow", "Calculate Clusters")) - self.pb_kmeans_elbow.setText(_translate("MainWindow", "KMeans Variance Plot")) - self.label_10.setText(_translate("MainWindow", "Method")) - self.cb_clust_method.setItemText(0, _translate("MainWindow", "KMeans")) - self.cb_clust_method.setItemText(1, _translate("MainWindow", "MiniBatchKMeans")) - self.cb_clust_method.setItemText(2, _translate("MainWindow", "MeanShift")) - self.cb_clust_method.setItemText(3, _translate("MainWindow", "Spectral Clustering")) - self.cb_clust_method.setItemText(4, _translate("MainWindow", "Correlation-Kmeans")) - self.cb_clust_method.setItemText(5, _translate("MainWindow", "Affinity Propagation")) - self.label_2.setText(_translate("MainWindow", "Number of Clusters")) - self.toolBox_2.setItemText(self.toolBox_2.indexOf(self.page_6), _translate("MainWindow", "Cluster Analysis")) - self.pb_elist_xanes.setText(_translate("MainWindow", "Load Energy List")) - self.cb_kev_flag.setText(_translate("MainWindow", "keV")) - self.pb_ref_xanes.setText(_translate("MainWindow", "Load Ref. Spec.")) - self.pb_plot_refs.setText(_translate("MainWindow", "Plot")) - self.cb_xanes_fitting_method.setItemText(0, _translate("MainWindow", "NNLS")) - self.pb_xanes_fit.setText(_translate("MainWindow", " Fit")) - self.toolBox_2.setItemText(self.toolBox_2.indexOf(self.page_7), _translate("MainWindow", "XANES Fitting")) - self.groupBox_8.setTitle(_translate("MainWindow", "ROI Positions")) - self.groupBox_5.setTitle(_translate("MainWindow", "Spectrum ROI")) - self.le_spec_roi_size.setText(_translate("MainWindow", "roi_size")) - self.label_8.setText(_translate("MainWindow", "Range (eV):")) - self.label_29.setText(_translate("MainWindow", "Size (eV):")) - self.le_spec_roi.setText(_translate("MainWindow", "roix, roiy")) - self.groupBox_4.setTitle(_translate("MainWindow", "Image ROI")) - self.label_4.setText(_translate("MainWindow", "Position:")) - self.le_roi.setText(_translate("MainWindow", "roix, roiy")) - self.label_28.setText(_translate("MainWindow", "Size(pixels):")) - self.le_roi_size.setText(_translate("MainWindow", "roi_size")) - self.groupBox_3.setTitle(_translate("MainWindow", "Image Calculations")) - self.rb_math_roi_img.setText(_translate("MainWindow", "Add Math ROI")) - self.pb_reset_roi_2.setText(_translate("MainWindow", "Reset")) - self.label_14.setText(_translate("MainWindow", "Action:")) - self.cb_img_roi_action.setItemText(0, _translate("MainWindow", "Subtract")) - self.cb_img_roi_action.setItemText(1, _translate("MainWindow", "Divide")) - self.cb_img_roi_action.setItemText(2, _translate("MainWindow", "Add")) - self.cb_img_roi_action.setItemText(3, _translate("MainWindow", "Compare")) - self.groupBox_7.setTitle(_translate("MainWindow", "Spectrum Calculations")) - self.rb_math_roi.setText(_translate("MainWindow", "Add Math ROI")) - self.label_13.setText(_translate("MainWindow", "Action:")) - self.cb_roi_operation.setItemText(0, _translate("MainWindow", "Divide")) - self.cb_roi_operation.setItemText(1, _translate("MainWindow", "Subtract")) - self.cb_roi_operation.setItemText(2, _translate("MainWindow", "Add")) - self.cb_roi_operation.setItemText(3, _translate("MainWindow", "Correlation Plot")) - self.pb_save_disp_img.setText(_translate("MainWindow", "Save Current Image (.tiff)")) - self.pb_save_disp_spec.setText(_translate("MainWindow", "Save Current Spectrum (.txt)")) - self.groupBox_2.setTitle(_translate("MainWindow", "ROI Shape")) - self.rb_poly_roi.setText(_translate("MainWindow", "Polygon (default)")) - self.rb_rect_roi.setText(_translate("MainWindow", "Rectangle")) - self.rb_elli_roi.setText(_translate("MainWindow", "Ellipse")) - self.rb_circle_roi.setText(_translate("MainWindow", "Circle")) - self.rb_line_roi.setText(_translate("MainWindow", "Line")) - self.menuManual.setTitle(_translate("MainWindow", "Help")) - self.menuFile.setTitle(_translate("MainWindow", "File")) - self.menuMask.setTitle(_translate("MainWindow", "Tools")) - self.actionOpen_PDF.setText(_translate("MainWindow", "Open PDF")) - self.actionOpen_in_GitHub.setText(_translate("MainWindow", "Open in GitHub (most updated)")) - self.actionOpen_Image_Data.setText(_translate("MainWindow", "Open Image Data")) - self.actionOpen_Image_Data.setToolTip(_translate("MainWindow", "Support all tiff and specific h5 files")) - self.actionOpen_Image_Data.setShortcut(_translate("MainWindow", "Ctrl+O")) - self.actionClose.setText(_translate("MainWindow", "Close")) - self.actionExit.setText(_translate("MainWindow", "Exit")) - self.actionExit.setShortcut(_translate("MainWindow", "Ctrl+Q")) - self.actionSave_as.setText(_translate("MainWindow", "Export Tiff Stack")) - self.actionSave_as.setToolTip(_translate("MainWindow", "Save the displayed/Modified stack as a tiff file")) - self.actionSave_as.setShortcut(_translate("MainWindow", "Ctrl+S")) - self.actionOpen_PyXRF.setText(_translate("MainWindow", "Open PyXRF")) - self.actionOpen_Image_J.setText(_translate("MainWindow", "Open Image J")) - self.actionOpen_TomViz.setText(_translate("MainWindow", "Open TomViz")) - self.actionOpen_Mantis.setText(_translate("MainWindow", "Open Mantis")) - self.actionOpen_Athena.setText(_translate("MainWindow", "Open Athena")) - self.actionDataBroker.setText(_translate("MainWindow", "DataBroker")) - self.actionOpen_HXN_DB.setText(_translate("MainWindow", "Open HXN DB")) - self.actionLoad_Energy.setText(_translate("MainWindow", "Load Energy")) - self.actionLoad_Energy.setToolTip(_translate("MainWindow", "Load list of energies for XANES stack. Supports only .txt fromat")) - self.actionLoad_Energy.setShortcut(_translate("MainWindow", "Ctrl+E")) - self.actionOpen_Multiple_Files.setText(_translate("MainWindow", "Open Multiple Files")) - self.actionOpen_Multiple_Files.setToolTip(_translate("MainWindow", "Create a stack from multiple tiff images of same shape")) - self.actionOpen_Multiple_Files.setShortcut(_translate("MainWindow", "Ctrl+M")) - self.actionOpen_Mask_Gen.setText(_translate("MainWindow", "Open Mask Generator")) - self.actionOpen_Mask_Gen.setToolTip(_translate("MainWindow", "A new window will be opened to creat threshold based masks")) - self.actionCreate_elist_from_log.setText(_translate("MainWindow", "Create elist from log file")) - self.actionSave_Energy_List.setText(_translate("MainWindow", "Save Energy List")) - self.actionAlign_Stack.setText(_translate("MainWindow", "Align Stack")) - self.actionAlign_Stack.setToolTip(_translate("MainWindow", "A new window will be opened to align images in a stack")) -from pyqtgraph import ImageView, PlotWidget - - -if __name__ == "__main__": - import sys - app = QtWidgets.QApplication(sys.argv) - MainWindow = QtWidgets.QMainWindow() - ui = Ui_MainWindow() - ui.setupUi(MainWindow) - MainWindow.show() - sys.exit(app.exec_()) diff --git a/xmidas/uis/midasMainwindow.ui b/xmidas/uis/midasMainwindow.ui deleted file mode 100644 index eb98ef8..0000000 --- a/xmidas/uis/midasMainwindow.ui +++ /dev/null @@ -1,2938 +0,0 @@ - - - Ajith - MainWindow - - - true - - - - 0 - 0 - 1232 - 931 - - - - - 0 - 0 - - - - NSLS-II MIDAS - - - - pancake.icopancake.ico - - - font: 10pt "Segoe UI"; - - - - - true - - - - 0 - 0 - - - - QWidget { -font: 10pt "Segoe UI"; -} - -QPushButton { -background-color: rgb(175, 236, 255); -color: rgb(255, 5,0); -font: 10pt "Segoe UI"; -} - -QLabel { -font: 10pt "Segoe UI"; -} - -QSlider::groove:horizontal { -border: 1px solid #bbb; -background: white; -height: 10px; -border-radius: 4px; -} - -QSlider::sub-page:horizontal { -background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #66e, stop: 1 #bbf); -background: qlineargradient(x1: 0, y1: 0.2, x2: 1, y2: 1, - stop: 0 #bbf, stop: 1 #55f); -border: 1px solid #777; -height: 10px; -border-radius: 4px; -} - -QSlider::add-page:horizontal { -background: #fff; -border: 1px solid #777; -height: 10px; -border-radius: 4px; -} - -QSlider::handle:horizontal { -background: qlineargradient(x1:0, y1:0, x2:1, y2:1, - stop:0 #eee, stop:1 #ccc); -border: 1px solid #777; -width: 13px; -margin-top: -2px; -margin-bottom: -2px; -border-radius: 4px; -} - -QSlider::handle:horizontal:hover { -background: qlineargradient(x1:0, y1:0, x2:1, y2:1, - stop:0 #fff, stop:1 #ddd); -border: 1px solid #444; -border-radius: 2px; -} - -QSlider::sub-page:horizontal:disabled { -background: #bbb; -border-color: #999; -} - -QSlider::add-page:horizontal:disabled { -background: #eee; -border-color: #999; -} - -QSlider::handle:horizontal:disabled { -background: #eee; -border: 1px solid #aaa; -border-radius: 4px; -} - - - - - - - - - - 0 - 0 - - - - QFrame::StyledPanel - - - QFrame::Sunken - - - - - - - 0 - 0 - - - - - - - 2 - - - - - 0 - 0 - 368 - 325 - - - - Adjust Image Dimensions - - - - - - - 0 - 0 - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - QLayout::SetMinimumSize - - - - - - 0 - 0 - - - - 0 - - - 500 - - - 0 - - - 10 - - - - - - - - 0 - 0 - - - - 1 - - - 5000 - - - 1200 - - - 10 - - - - - - - - 0 - 0 - - - - false - - - px - - - 1 - - - 10000 - - - 100 - - - - - - - - 0 - 0 - - - - false - - - px - - - 1 - - - 10000 - - - 100 - - - - - - - - 0 - 0 - - - - false - - - px - - - 0 - - - 10000 - - - 0 - - - - - - - - 0 - 0 - - - - Y Dimension - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - false - - - px - - - 0 - - - 10000 - - - 0 - - - - - - - - 0 - 0 - - - - X Dimension - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - Stack Range - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - to - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - to - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - to - - - Qt::AlignCenter - - - - - - - - - - 0 - 0 - - - - Adjust the dimensions of the image - - - - - - Update - - - - - - - - - - - 0 - 0 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - - 0 - 0 - - - - Removes one column/row from all four edges - - - Remove Edges - - - - - - - - - true - - - - 0 - 0 - - - - rebin - - - - - - - true - - - - 0 - 0 - - - - Upscale - - - - - - - - - Ratio - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - true - - - - 0 - 0 - - - - font: 10pt "MS Shell Dlg 2"; - - - 2 - - - 16 - - - 2 - - - 2 - - - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - 0 - 0 - 300 - 392 - - - - Image Processing - - - - - - - - - reverses the image axes (ZXY) to (YXZ) - - - Transpose - - - - - - - swaps 2nd and 3rd axes (ZXY) to (ZYX) - - - Swap XY Axes - - - - - - - - - - - - 0 - 0 - - - - Covert image dat to log values. - - - - - - Log - - - false - - - - - - - - 0 - 0 - - - - Intensity Normalization with the last Frame. - - - Normalize to Max - - - - - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - Remove Outliers (NSigma) - - - - - - - false - - - - - - 200 - - - 3 - - - Qt::Horizontal - - - - - - - 1 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - - - Thresholding - - - - - - - - - - - false - - - 100 - - - 5 - - - 5 - - - 5 - - - Qt::Horizontal - - - - - - - 5 - - - - - - - - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - uses savgol_filter to smooth data - - - Smoothen - - - - - - - - - false - - - 3 - - - 12 - - - 2 - - - 2 - - - 3 - - - Qt::Horizontal - - - QSlider::TicksBelow - - - 2 - - - - - - - Window size - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - - - - - 0 - 0 - 379 - 309 - - - - Alignment - - - - - - - - - - - Transformations: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - TRANSLATION - - - - - RIGID_BODY - - - - - SCALED_ROTATION - - - - - AFFINE - - - - - BILINEAR - - - - - - - - - - - - Reference: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - previous - - - - - mean - - - - - first - - - - - - - - - - - - - 0 - 0 - - - - Iterative Mode - - - - - - - - - Max Iter. - - - - - - - - 0 - 0 - - - - 2 - - - 24 - - - - - - - - - - - - 0 - 0 - - - - Align - - - - - - - - - - 0 - 0 - - - - Load Reference Stack - - - - - - - No Ref. Available - - - true - - - - - - - - - - 0 - 0 - - - - Save Transformation File - - - - - - - Use - - - - - - - - 0 - 0 - - - - Load Transformation File - - - - - - - - - - - - - - - 0 - 0 - - - - - - - Reset Image - - - - - - - true - - - 2 - - - - - 0 - 0 - 379 - 321 - - - - Component Analysis - - - - - - - - - 0 - 0 - - - - - - - Calculate Components - - - - - - - - 0 - 0 - - - - - - - PCA Scree Plot - - - - - - - - - Method - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - - PCA - - - - - NMF - - - - - FastICA - - - - - IncrementalPCA - - - - - TruncatedSVD - - - - - FactorAnalysis - - - - - DictionaryLearning - - - - - - - - - - - - Number of Components - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - 1 - - - 4 - - - - - - - - - - - - - 0 - 0 - 379 - 321 - - - - Cluster Analysis - - - - - - - - - 0 - 0 - - - - - - - Calculate Clusters - - - - - - - - 0 - 0 - - - - - - - KMeans Variance Plot - - - - - - - Method - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - - KMeans - - - - - MiniBatchKMeans - - - - - MeanShift - - - - - Spectral Clustering - - - - - Correlation-Kmeans - - - - - Affinity Propagation - - - - - - - - Number of Clusters - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - 1 - - - 4 - - - - - - - - - - - 0 - 0 - 379 - 205 - - - - XANES Fitting - - - - - - - 11 - - - 11 - - - - - - - - 0 - 0 - - - - - - - Load Energy List - - - - - - - keV - - - - - - - - - - - - 0 - 0 - - - - - - - Load Ref. Spec. - - - - - - - - - - Plot - - - - - - - - - true - - - - 0 - 0 - - - - - - - Fit - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - - - - 0 - 0 - - - - - - - - - - - QLayout::SetMaximumSize - - - - - 0 - - - - Live - - - - - - - 0 - 0 - - - - Send to Plot Collection - - - - - - - - 0 - 0 - - - - - - - Save - - - - - - - - 0 - 0 - - - - - - - - - Normalized - - - - - - Save - - - - - - - Clear - - - - - - - Norm. to Collector - - - - - - - - 0 - 0 - - - - - - - - - Collection - - - - - - - 0 - 0 - - - - - - - - Clear - - - - - - - Save - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - 0 - 0 - - - - - - - - - - - - 0 - 0 - - - - QFrame::StyledPanel - - - QFrame::Sunken - - - - QLayout::SetDefaultConstraint - - - 11 - - - 11 - - - - - - 0 - 0 - - - - ROI Shape - - - - - - - 0 - 0 - - - - Rectangle - - - true - - - - - - - - 0 - 0 - - - - Ellipse - - - - - - - - 0 - 0 - - - - Polygon - - - false - - - - - - - - 0 - 0 - - - - Circle - - - - - - - - 0 - 0 - - - - Line - - - - - - - - 0 - 0 - - - - Zoom to ROI - - - - - - - - - - font: 9pt "Segoe UI"; - - - ROI Positions - - - - - - Spectrum ROI - - - - - - Range (eV): - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - color: rgb(255, 0,0); - - - roi_size - - - - - - - color: rgb(255, 0,0); - - - roix, roiy - - - - - - - - - - Size (eV): - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - Image ROI - - - - - - color: rgb(255, 0,0); - - - roix, roiy - - - - - - - Position: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - Size(pixels): - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - color: rgb(255, 0, 0); - - - roi_size - - - - - - - - - - - - - - 0 - 0 - - - - 1 - - - - - 0 - 0 - 361 - 193 - - - - Image Calculations - - - - - - - - - - - - - - - Add ROI_2 - - - - - - - Calculation: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - - Subtract - - - - - Divide - - - - - Add - - - - - Compare - - - - - - - - Apply - - - - - - - - - - - - 0 - 0 - 361 - 231 - - - - Spectrum Calculations - - - - - - - - - - - - - 0 - 0 - - - - Add ROI 2 - - - true - - - false - - - false - - - - - - - - - - 0 - 0 - - - - Calculation - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - - Divide - - - - - Subtract - - - - - Add - - - - - Correlation Plot - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Apply - - - - - - - Use ROI for Correlations - - - - - - - - - - - - 0 - 0 - 386 - 273 - - - - XANES Normalization - - - - - - - 0 - 0 - - - - to - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - 1 - - - 5 - - - - - - - - 0 - 0 - - - - Eo - - - - - - - - 0 - 0 - - - - eV - - - 1000.000000000000000 - - - 20000.000000000000000 - - - 7125.000000000000000 - - - - - - - - 0 - 0 - - - - calculate the energy point with maximum derivative - - - Auto Eo - - - - - - - - 0 - 0 - - - - eV - - - 2 - - - -500.000000000000000 - - - 500.000000000000000 - - - 1.000000000000000 - - - -50.000000000000000 - - - - - - - - 0 - 0 - - - - Pre-edge - - - - - - - - 0 - 0 - - - - eV - - - -500.000000000000000 - - - 500.000000000000000 - - - -10.000000000000000 - - - - - - - - 0 - 0 - - - - Post-edge - - - - - - - - 0 - 0 - - - - to - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - Norm. Order - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - eV - - - 0.000000000000000 - - - 1000.000000000000000 - - - 25.000000000000000 - - - - - - - - 0 - 0 - - - - <html><head/><body><p> For mbak algorithm only, must be in <span style=" font-weight:600; font-style:italic;">element&lt;space&gt;edge</span> format</p></body></html> - - - Fe K - - - - - - - - 0 - 0 - - - - Element: - - - - - - - - 0 - 0 - - - - eV - - - 0.000000000000000 - - - 1500.000000000000000 - - - 75.000000000000000 - - - - - - - Initial Guess - - - - - - - - 0 - 0 - - - - Apply to Spectrum - - - - - - - Apply to Stack - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - 0 - 0 - 1232 - 29 - - - - - - - - Help - - - - - - - File - - - - - - - - - - - - true - - - Accessories - - - - - - - View - - - - Plot Background - - - - - - - - - - Window Background - - - - - - - - Change_Plot_Line_Width - - - - - - - - - - - - - - - - - Spectrum - - - - - - - - - Image - - - - - - - - - - - Batch - - - - - - - - - - - - - - - - - 0 - 0 - - - - toolBar - - - TopToolBarArea - - - false - - - - - - - - Open PDF - - - - - Open in GitHub (most updated) - - - - - true - - - Open Image Data - - - Support all tiff and specific h5 files - - - Ctrl+O - - - - - Close - - - - - Exit - - - Ctrl+Q - - - - - false - - - Export Tiff Stack - - - Save the displayed/Modified stack as a tiff file - - - Ctrl+S - - - - - Open PyXRF - - - - - Open Image J - - - - - Open TomViz - - - - - Open Mantis - - - - - Open Athena - - - - - DataBroker - - - - - Open HXN DB - - - - - false - - - Load Energy - - - Load list of energies for XANES stack. Supports only .txt fromat - - - Ctrl+E - - - - - Create a Virtual Stack - - - Create a stack from multiple tiff images of same shape - - - Ctrl+M - - - - - true - - - Open Mask Generator - - - A new window will be opened to creat threshold based masks - - - - - Create elist from log file - - - - - false - - - Export Energy List - - - - - true - - - MultiColorView - - - A new window will be opened to align images in a stack - - - - - White - - - - - true - - - true - - - Black - - - - - Red - - - - - Yellow - - - - - Blue - - - - - false - - - false - - - Dark Mode - - - - - Black - - - - - false - - - false - - - Default - - - - - Vivid - - - - - Export Sum Image (3D to 2D) - - - - - Subtract ROI as Background - - - - - Export Norm. Params - - - - - 2 - - - - - 4 - - - - - 6 - - - - - 10 - - - - - 2 - - - - - 3 - - - - - 4 - - - - - 5 - - - - - 6 - - - - - 8 - - - - - 10 - - - - - 2 - - - - - Import Norm. Params - - - - - 1 - - - - - Save Sum Spectrum - - - - - Save Mean Spectrum - - - - - Save Current Image as Mask - - - - - Stack to RGBCMY Image - - - - - Apply Current Crop to All images - - - all images in the folder will be cropped in reference to current - - - - - - - - - - - Save Current State - - - - - Normalize with another Stack - - - - - Stack Info - - - Diaplays details of the stack - - - - - Export Image - - - Saves displayed 2D image frame - - - - - - .. - - - Export Stack - - - Save current stack as is - - - false - - - - - Export Mean Image (3D to 2D) - - - - - Plot All Possible Image Correlations - - - - - - PlotWidget - QGraphicsView -
pyqtgraph
-
- - ImageView - QGraphicsView -
pyqtgraph
-
-
- - -
diff --git a/xmidas/uis/multipleScatterFit.ui b/xmidas/uis/multipleScatterFit.ui deleted file mode 100644 index 7112364..0000000 --- a/xmidas/uis/multipleScatterFit.ui +++ /dev/null @@ -1,114 +0,0 @@ - - - MainWindow - - - - 0 - 0 - 856 - 628 - - - - MainWindow - - - - - - - - - - - - - - 0 - 0 - - - - - - - - - - - - - 0 - 0 - 856 - 21 - - - - - View - - - - Plot Background - - - - - - - - - - - - - toolBar - - - TopToolBarArea - - - false - - - - - - - - Export - - - - - Save as PNG - - - - - Generate MultiColor Mask - - - - - Black - - - - - White - - - - - - GraphicsLayoutWidget - QGraphicsView -
pyqtgraph
-
-
- - -
diff --git a/xmidas/uis/mutlichannel.ui b/xmidas/uis/mutlichannel.ui deleted file mode 100644 index 133f006..0000000 --- a/xmidas/uis/mutlichannel.ui +++ /dev/null @@ -1,458 +0,0 @@ - - - MainWindow - - - - 0 - 0 - 674 - 765 - - - - MainWindow - - - font: 12pt "Segoe UI" - - - - QPushButton { -border: 1px solid #555; -border-radius: 5px; -background: qradialgradient(cx: 0.3, cy: -0.1, -fx: 0.7, fy: 0.1, -radius: 1, stop: 0 #fff, stop: 1 #888); -background-color: rgb(170, 255, 255); -} - -QPushButton:hover{ - background-color: rgb(255, 255, 0); - } - -QPushButton:pressed{ - background-color: rgb(0,255, 0); - } - -font: 12pt "Segoe UI"; - - - - 25 - - - 25 - - - 25 - - - 25 - - - - - - 0 - 0 - - - - - - - - Edit - - - - - - - 0 - 0 - - - - 0 - - - - - 0 - 0 - 316 - 85 - - - - Thresholding - - - - - - - - - 0 - 0 - - - - 0,100 - - - Qt::AlignCenter - - - - - - - - - - - - 0 - 0 - - - - Qt::NoFocus - - - click update after making changes - - - 100 - - - 5 - - - 5 - - - 100 - - - 100 - - - true - - - Qt::Horizontal - - - false - - - false - - - QSlider::NoTicks - - - 5 - - - - - - - - - - - - 0 - 0 - - - - Qt::NoFocus - - - click update after making changes - - - 100 - - - 5 - - - 5 - - - 0 - - - 0 - - - true - - - Qt::Horizontal - - - QSlider::NoTicks - - - 5 - - - - - - - - - - - - - - - 0 - 0 - 316 - 85 - - - - Opacity - - - - - - - - - 0 - 0 - - - - 1 - - - Qt::AlignCenter - - - - - - - click update after making changes - - - 100 - - - 10 - - - 100 - - - Qt::Horizontal - - - - - - - - - - - - - execute above changes to the selected item - - - Update - - - - - - - - - Show Selected - - - - - - - Show All - - - - - - - - - - 0 - 0 - - - - change properties of the selected item - - - font: 8pt "Segoe UI"; - - - QAbstractScrollArea::AdjustToContents - - - - - - - - - - 0 - 0 - - - - Change Selected To - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - true - - - - - - - - - - - - - - - - - - 0 - 0 - 674 - 34 - - - - - File - - - true - - - - - - - - - - - - - Load Images - - - Select and load multiple tiff images to create a multi color view - - - - - Load 2 - - - - - Load 3 - - - - - Load 4 - - - - - Load 5 - - - - - Load 6 - - - - - Export Image - - - Export the image view as a sinle image file - - - - - Save State File - - - Save the current state of the view. Images and properties are saved - - - - - Load State File - - - Load a state (json file) saved previously. - - - - - Load Stack - - - Load images as a stack of tiff - - - - - - GraphicsLayoutWidget - QGraphicsView -
pyqtgraph
-
-
- - -
diff --git a/xmidas/uis/pancake.ico b/xmidas/uis/pancake.ico deleted file mode 100644 index 9d118f4f2a79d9492741a3143a7b36c9de7db4da..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4158 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 P|H#Qd{b&6D;pYDU1f=H& diff --git a/xmidas/uis/singleStackView.ui b/xmidas/uis/singleStackView.ui deleted file mode 100644 index d832b04..0000000 --- a/xmidas/uis/singleStackView.ui +++ /dev/null @@ -1,151 +0,0 @@ - - - MainWindow - - - - 0 - 0 - 691 - 566 - - - - MainWindow - - - QSlider::groove:horizontal { -border: 1px solid #bbb; -background: white; -height: 10px; -border-radius: 4px; -} - -QSlider::sub-page:horizontal { -background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #66e, stop: 1 #bbf); -background: qlineargradient(x1: 0, y1: 0.2, x2: 1, y2: 1, - stop: 0 #bbf, stop: 1 #55f); -border: 1px solid #777; -height: 10px; -border-radius: 4px; -} - -QSlider::add-page:horizontal { -background: #fff; -border: 1px solid #777; -height: 10px; -border-radius: 4px; -} - -QSlider::handle:horizontal { -background: qlineargradient(x1:0, y1:0, x2:1, y2:1, - stop:0 #eee, stop:1 #ccc); -border: 1px solid #777; -width: 13px; -margin-top: -2px; -margin-bottom: -2px; -border-radius: 4px; -} - -QSlider::handle:horizontal:hover { -background: qlineargradient(x1:0, y1:0, x2:1, y2:1, - stop:0 #fff, stop:1 #ddd); -border: 1px solid #444; -border-radius: 2px; -} - -QSlider::sub-page:horizontal:disabled { -background: #bbb; -border-color: #999; -} - -QSlider::add-page:horizontal:disabled { -background: #eee; -border-color: #999; -} - -QSlider::handle:horizontal:disabled { -background: #eee; -border: 1px solid #aaa; -border-radius: 4px; -} - -QPushButton { -background-color: rgb(175, 236, 255); -color: rgb(255, 0, 127); -} - - - - - - - - - - 0 - 0 - - - - - - - - - - Qt::Horizontal - - - - - - - font: 12pt "MS Shell Dlg 2"; - - - 10 - - - - - - - - - - - - - 0 - 0 - 691 - 26 - - - - - File - - - - - - - - - Save - - - - - - ImageView - QGraphicsView -
pyqtgraph
-
-
- - -
diff --git a/xmidas/uis/splash.gif b/xmidas/uis/splash.gif deleted file mode 100644 index 800ffdb41fb58b5cb783a3581771bfc43b03d605..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40659 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 ZyJyLT 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 diff --git a/xmidas/uis/xanesFitStat.ui b/xmidas/uis/xanesFitStat.ui deleted file mode 100644 index 25685bf..0000000 --- a/xmidas/uis/xanesFitStat.ui +++ /dev/null @@ -1,47 +0,0 @@ - - - MainWindow - - - - 0 - 0 - 792 - 481 - - - - MainWindow - - - - - - - - - - - - - - - 0 - 0 - 792 - 26 - - - - - - - - PlotWidget - QGraphicsView -
pyqtgraph
-
-
- - -
diff --git a/xmidas/uis/xrf_xanes_gui_3ID.ui b/xmidas/uis/xrf_xanes_gui_3ID.ui deleted file mode 100644 index 8755841..0000000 --- a/xmidas/uis/xrf_xanes_gui_3ID.ui +++ /dev/null @@ -1,756 +0,0 @@ - - - Ajith - MainWindow - - - - 0 - 0 - 820 - 553 - - - - HXN_Wizard - - - font: 12pt "MS Shell Dlg 2"; - - - - - - - - - - 0 - 0 - - - - - - - - 20 - - - - - - - - 0 - 0 - - - - - - - C:\Matrix\Blue Pill\Morpheus.csv - - - - - - - - 0 - 0 - - - - - - - C:\Matrix\Blue Pill - - - - - - - 0 - - - 10 - - - - - - 0 - 0 - - - - Select Working Directory - - - - - - - - 0 - 0 - - - - Select Paramater File - - - - - - - - 0 - 0 - - - - Select XANES Reference File (xanes only) - - - - - - - - - - 0 - 0 - - - - - - - C:\Matrix\Blue Pill\TheChosenOne.json - - - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - background-color: rgb(255, 221, 98); - - - Open PyXRF GUI - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - font: 12pt "MS Shell Dlg 2"; - - - 1 - - - false - - - - XRF - - - - - - XRF Batch Processing - - - Qt::AlignCenter - - - - - - 150 - - - 150 - - - - - 92158 - - - 00000 - - - - - - - 92102 - - - 00000 - - - - - - - Last Scan ID: - - - - - - - Scalar Name: - - - - - - - First Scan ID: - - - - - - - sclr1_ch4 - - - Fe_K - - - - - - - background-color: rgb(85, 255, 127); - - - Start Batch Processing - - - - - - - - - - - - 150 - - - 150 - - - - - XRF Live Processing - - - Qt::AlignCenter - - - - - - - - background-color: rgb(0, 170, 255); -background-color: rgb(67, 246, 255); - - - Initiate Live - - - - - - - background-color: rgb(255, 130, 67); -font: 75 12pt "MS Shell Dlg 2"; - - - - Start - - - - - - - Live Processing is not ready - - - Qt::AlignCenter - - - - - - - - - - - - - - - XANES - - - - - - 50 - - - 50 - - - - - - - First Scan ID: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - 92102 - - - 00000 - - - - - - - XANES Element - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Fe_K - - - Fe_K - - - - - - - Alignemnt Element - - - - - - - P_K - - - Pt_L - - - - - - - - - 50 - - - 0 - - - - - Last Scan ID: - - - - - - - 92158 - - - 00000 - - - - - - - Scalar Name - - - - - - - sclr1_ch4 - - - Fe_K - - - - - - - Save All Elem tiff Stacks - - - true - - - - - - - - 0 - 0 - - - - Subtract Pre-edge - - - - - - - - - - - Qt::Horizontal - - - - 49 - 20 - - - - - - - - Qt::Vertical - - - - 20 - 48 - - - - - - - - 20 - - - 20 - - - - - - 0 - 0 - - - - Fitting method - - - - - - - - 0 - 0 - - - - - nnls - - - - - admm - - - - - - - - false - - - - 0 - 0 - - - - Lambda for ADMM: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - false - - - - 0 - 0 - - - - Qt::StrongFocus - - - 5 - - - Lambda for ADMM - - - - - - - - 0 - 0 - - - - Energy Shift (eV) - - - - - - - - 0 - 0 - - - - Qt::StrongFocus - - - 0 - - - Lambda for ADMM - - - - - - - Work Flow - - - - - - - - 0 - 0 - - - - - load_and_process - - - - - process - - - - - build_xanes_map - - - - - - - - font: 12pt "MS Shell Dlg 2"; -background-color: rgb(170, 255, 255); - - - Go - - - - - - - background-color: rgb(255, 77, 46); -color: rgb(0, 0, 0); -font: 75 10pt "MS Shell Dlg 2"; - - - Close All Plots - - - - - - - - - Qt::Horizontal - - - - 49 - 20 - - - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Vertical - - - - 20 - 52 - - - - - - - - - - 0 - 0 - 820 - 25 - - - - - HELP - - - - - - - - - From be447522ea447fed4949b916cefd18a6834262ae Mon Sep 17 00:00:00 2001 From: Ajith Pattammattel Date: Tue, 22 Jul 2025 14:16:17 -0400 Subject: [PATCH 02/18] pyqt6 added to requirements --- docs/source/Nano-XANES_Workflow.rst | 51 + requirements.txt | 3 +- xmidas/gui/layout/ClusterView.ui | 266 ++ xmidas/gui/layout/ComponentScatterPlot.ui | 195 ++ xmidas/gui/layout/ComponentView.ui | 303 ++ xmidas/gui/layout/MaskMaker.ui | 307 ++ xmidas/gui/layout/MaskSpecViewer.ui | 367 ++ xmidas/gui/layout/MaskedView.ui | 352 ++ xmidas/gui/layout/MultiImageSpectrumView.ui | 734 ++++ xmidas/gui/layout/RefChooser.ui | 252 ++ xmidas/gui/layout/Scatter3D.ui | 130 + xmidas/gui/layout/Scatter3D_plotly.ui | 120 + xmidas/gui/layout/ScatterView.ui | 249 ++ xmidas/gui/layout/StackViewer.ui | 335 ++ xmidas/gui/layout/XANESViewer.ui | 533 +++ xmidas/gui/layout/align_test.ui | 71 + xmidas/gui/layout/animationWindow.ui | 68 + xmidas/gui/layout/css/darkStyle.css | 68 + xmidas/gui/layout/css/defaultStyle.css | 72 + xmidas/gui/layout/css/modern.css | 289 ++ xmidas/gui/layout/decomposeViewer.ui | 694 ++++ xmidas/gui/layout/log.ui | 68 + xmidas/gui/layout/maskedScatterPlotFit.ui | 187 + xmidas/gui/layout/midasMainwindow.ui | 3034 +++++++++++++++++ xmidas/gui/layout/multipleScatterFit.ui | 114 + xmidas/gui/layout/mutlichannel.ui | 464 +++ xmidas/gui/layout/singleStackView.ui | 151 + xmidas/gui/layout/xanesFitStat.ui | 47 + xmidas/gui/layout/xrf_xanes_gui_3ID.ui | 756 ++++ xmidas/gui/resources/images/animation.gif | Bin 0 -> 94900 bytes .../gui/resources/images/animation_atom.gif | Bin 0 -> 383024 bytes xmidas/gui/resources/images/pancake.ico | Bin 0 -> 4158 bytes xmidas/gui/resources/images/splash.gif | Bin 0 -> 40659 bytes xmidas/gui/windows/decomposition_viewer.py | 391 +++ xmidas/gui/windows/mask_maker.py | 287 ++ xmidas/gui/windows/multichannel_viewer.py | 319 ++ xmidas/gui/windows/singleStackViewer.py | 95 + xmidas/gui/windows/xanes_viewer.py | 1320 +++++++ xmidas/models/encoders.py | 13 + xmidas/utils/color_maps.py | 28 + xmidas/utils/larch_norm.py | 119 + xmidas/utils/utils.py | 1153 +++++++ 42 files changed, 14004 insertions(+), 1 deletion(-) create mode 100755 docs/source/Nano-XANES_Workflow.rst create mode 100644 xmidas/gui/layout/ClusterView.ui create mode 100644 xmidas/gui/layout/ComponentScatterPlot.ui create mode 100644 xmidas/gui/layout/ComponentView.ui create mode 100644 xmidas/gui/layout/MaskMaker.ui create mode 100644 xmidas/gui/layout/MaskSpecViewer.ui create mode 100644 xmidas/gui/layout/MaskedView.ui create mode 100644 xmidas/gui/layout/MultiImageSpectrumView.ui create mode 100644 xmidas/gui/layout/RefChooser.ui create mode 100644 xmidas/gui/layout/Scatter3D.ui create mode 100644 xmidas/gui/layout/Scatter3D_plotly.ui create mode 100644 xmidas/gui/layout/ScatterView.ui create mode 100644 xmidas/gui/layout/StackViewer.ui create mode 100644 xmidas/gui/layout/XANESViewer.ui create mode 100644 xmidas/gui/layout/align_test.ui create mode 100644 xmidas/gui/layout/animationWindow.ui create mode 100644 xmidas/gui/layout/css/darkStyle.css create mode 100644 xmidas/gui/layout/css/defaultStyle.css create mode 100644 xmidas/gui/layout/css/modern.css create mode 100644 xmidas/gui/layout/decomposeViewer.ui create mode 100644 xmidas/gui/layout/log.ui create mode 100644 xmidas/gui/layout/maskedScatterPlotFit.ui create mode 100644 xmidas/gui/layout/midasMainwindow.ui create mode 100644 xmidas/gui/layout/multipleScatterFit.ui create mode 100644 xmidas/gui/layout/mutlichannel.ui create mode 100644 xmidas/gui/layout/singleStackView.ui create mode 100644 xmidas/gui/layout/xanesFitStat.ui create mode 100644 xmidas/gui/layout/xrf_xanes_gui_3ID.ui create mode 100755 xmidas/gui/resources/images/animation.gif create mode 100755 xmidas/gui/resources/images/animation_atom.gif create mode 100755 xmidas/gui/resources/images/pancake.ico create mode 100755 xmidas/gui/resources/images/splash.gif create mode 100644 xmidas/gui/windows/decomposition_viewer.py create mode 100644 xmidas/gui/windows/mask_maker.py create mode 100644 xmidas/gui/windows/multichannel_viewer.py create mode 100644 xmidas/gui/windows/singleStackViewer.py create mode 100644 xmidas/gui/windows/xanes_viewer.py create mode 100644 xmidas/models/encoders.py create mode 100644 xmidas/utils/color_maps.py create mode 100644 xmidas/utils/larch_norm.py create mode 100644 xmidas/utils/utils.py diff --git a/docs/source/Nano-XANES_Workflow.rst b/docs/source/Nano-XANES_Workflow.rst new file mode 100755 index 0000000..dfb730a --- /dev/null +++ b/docs/source/Nano-XANES_Workflow.rst @@ -0,0 +1,51 @@ + +================ +Nano-XANES Processing +================ + +In short +***************** +The aim is to generate multi-color chemical state maps from a XANES stack + +What data are required? +-------- + +1. A 3D XANES stack or set of 2D tiff images +2. List of energy points (.txt files) +3. Reference spectrum library as simple colum files or .nor file from Athena (preferred) +Note : Make sure the athena file headers (spectrun names) are not too long. Parsing seems to fail otherwise but this problem will be addressed late. + + +2D-XANES Data +------------- + +2D and 3D tiff images (stacks). The list of energies has to be loaded as a separate tiff file (see load energy section below) + +To open the above data types use the "Open Image Data" option in the File menu and select the file. + +Load Energy +----------- + +You can load it using the following methods, + +1. file menu option 'Load Energy'. + +2. if you name the energy txt file matching the image file name, the program loads it automatically (like 'test.tiff' , 'test.txt'). + +3. In the folder you exported xanes data from the beamline there should be a log file named 'maps_log_tiff.txt'. Copy this to the same folder as the image file, then XMidas automatically load energy when you open the image. + + +Create an image stack +--------------------- + +You can also create a 3D image stack from a selection of single tiff files. To do so choose "Open Multiple Files" +options from the File menu. + +.. image:: screenshots/FileOpen.jpg + +Once loaded correctly you should see the image on the top panel and the spectrum on the bottom panel. In case of +incorrect formatting or unsupported formats, the bottom left corner of the program shows the error. + +.. image:: screenshots/Midas_view.jpg + +Also see the `Video Tutorial `_ diff --git a/requirements.txt b/requirements.txt index 62b72ff..9a22f05 100755 --- a/requirements.txt +++ b/requirements.txt @@ -8,4 +8,5 @@ scikit-image scikit-learn scipy tifffile -packaging +packaging +pyqt6 diff --git a/xmidas/gui/layout/ClusterView.ui b/xmidas/gui/layout/ClusterView.ui new file mode 100644 index 0000000..0fea754 --- /dev/null +++ b/xmidas/gui/layout/ClusterView.ui @@ -0,0 +1,266 @@ + + + MainWindow + + + + 0 + 0 + 979 + 815 + + + + + 0 + 0 + + + + MainWindow + + + background-color: rgb(240, 240, 240); +font: 10pt "Segoe UI"; + + + + QPushButton { +background-color: rgb(175, 236, 255); +color: rgb(255, 5,0); +} + + + + + + + + + + + + + Composite Map + + + Qt::AlignCenter + + + + + + + Opan as RGBCMY Image + + + + + + + + + + + + + + + + + Nth Cluster + + + Qt::AlignCenter + + + + + + + + + + + + + 0 + 0 + + + + 0 + + + 20 + + + 1 + + + 1 + + + Qt::Horizontal + + + + + + + + 0 + 0 + + + + font: 12pt "Segoe UI"; + + + 1/3 + + + + + + + + + + + + + + + 100 + + + 100 + + + + + + + font: 75 12pt "MS Shell Dlg 2"; + + + Cluster Spectrum + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + + + Show all + + + + + + + + + QAbstractScrollArea::AdjustToContents + + + + + + + + + + + + + 0 + 0 + 979 + 23 + + + + + Image + + + + + + + + Spectrum + + + + + + + Options + + + + + + + + + + + Save All Clusters + + + + + Save Current Cluster + + + + + Save Composite Map as Masks + + + + + Save All Cluster Spectra + + + + + Save Current Spectrum + + + + + Save Results as a Folder + + + + + + PlotWidget + QGraphicsView +
pyqtgraph
+
+ + ImageView + QGraphicsView +
pyqtgraph
+
+
+ + +
diff --git a/xmidas/gui/layout/ComponentScatterPlot.ui b/xmidas/gui/layout/ComponentScatterPlot.ui new file mode 100644 index 0000000..ee95575 --- /dev/null +++ b/xmidas/gui/layout/ComponentScatterPlot.ui @@ -0,0 +1,195 @@ + + + ScatterPlot + + + + 0 + 0 + 1034 + 859 + + + + Correlation Plot + + + font: 12pt "MS Shell Dlg 2"; + + + + + + + 10 + + + 10 + + + 10 + + + 10 + + + + + Image + + + Qt::AlignCenter + + + + + + + + + + + + 10 + + + 10 + + + 10 + + + 10 + + + + + Image + + + Qt::AlignCenter + + + + + + + + + + + + + + + Qt::LeftToRight + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Apply + + + + + + + Scatter View of + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + + + + Add A Line + + + + + + + Create A Mask + + + + + + + Reset Mask + + + + + + + Apply Mask + + + + + + + + + + + 0 + 0 + 1034 + 30 + + + + + File + + + + + + + + + + Save Plot + + + + + Save Images + + + + + + ImageView + QGraphicsView +
pyqtgraph
+
+ + GraphicsLayoutWidget + QGraphicsView +
pyqtgraph
+
+
+ + +
diff --git a/xmidas/gui/layout/ComponentView.ui b/xmidas/gui/layout/ComponentView.ui new file mode 100644 index 0000000..c7aca47 --- /dev/null +++ b/xmidas/gui/layout/ComponentView.ui @@ -0,0 +1,303 @@ + + + MainWindow + + + + 0 + 0 + 920 + 858 + + + + MainWindow + + + background-color: rgb(240, 240, 240); + + + + + + + + + + + + + + + + + + + + + Components + + + Qt::AlignCenter + + + + + + + + + + + + + + + 0 + 0 + + + + QSlider::groove:horizontal { +border: 1px solid #bbb; +background: white; +height: 10px; +border-radius: 4px; +} + +QSlider::sub-page:horizontal { +background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #66e, stop: 1 #bbf); +background: qlineargradient(x1: 0, y1: 0.2, x2: 1, y2: 1, + stop: 0 #bbf, stop: 1 #55f); +border: 1px solid #777; +height: 10px; +border-radius: 4px; +} + +QSlider::add-page:horizontal { +background: #fff; +border: 1px solid #777; +height: 10px; +border-radius: 4px; +} + +QSlider::handle:horizontal { +background: qlineargradient(x1:0, y1:0, x2:1, y2:1, + stop:0 #eee, stop:1 #ccc); +border: 1px solid #777; +width: 13px; +margin-top: -2px; +margin-bottom: -2px; +border-radius: 4px; +} + +QSlider::handle:horizontal:hover { +background: qlineargradient(x1:0, y1:0, x2:1, y2:1, + stop:0 #fff, stop:1 #ddd); +border: 1px solid #444; +border-radius: 2px; +} + +QSlider::sub-page:horizontal:disabled { +background: #bbb; +border-color: #999; +} + +QSlider::add-page:horizontal:disabled { +background: #eee; +border-color: #999; +} + +QSlider::handle:horizontal:disabled { +background: #eee; +border: 1px solid #aaa; +border-radius: 4px; +} + +QPushButton { +background-color: rgb(175, 236, 255); +color: rgb(255, 0, 127); +} + + + 20 + + + 1 + + + 1 + + + Qt::Horizontal + + + + + + + + 0 + 0 + + + + font: 12pt "Segoe UI"; + + + 1/3 + + + + + + + + + + + + + + + + Component Masks + + + Qt::AlignCenter + + + + + + + + + + + + + Show All Spectra + + + + + + + Open as RGBCMY Image + + + + + + + + + + + + + + + + Masked Spectrum + + + Qt::AlignCenter + + + + + + + + + + + + + + + + Component Spectrum + + + Qt::AlignCenter + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + Open ScatterPlot + + + + + + + Open XANES Norm. View + + + + + + + + + + + + 0 + 0 + 920 + 26 + + + + + File + + + + + + + + + Save + + + + + + PlotWidget + QGraphicsView +
pyqtgraph
+
+ + ImageView + QGraphicsView +
pyqtgraph
+
+
+ + +
diff --git a/xmidas/gui/layout/MaskMaker.ui b/xmidas/gui/layout/MaskMaker.ui new file mode 100644 index 0000000..5209298 --- /dev/null +++ b/xmidas/gui/layout/MaskMaker.ui @@ -0,0 +1,307 @@ + + + MainWindow + + + + 0 + 0 + 979 + 513 + + + + Masked XANES + + + + + + + QPushButton { +background-color: rgb(175, 236, 255); +color: rgb(255, 5,0); +} + + + + 15 + + + 15 + + + 15 + + + 15 + + + 10 + + + + + + + + + + + + + Create A mask + + + Qt::AlignCenter + + + + + + + + + + + + + + + + + Binary Mask + + + Qt::AlignCenter + + + + + + + + + + + 3 + + + 1.000000000000000 + + + 0.010000000000000 + + + + + + + + 0 + 0 + + + + Qt::NoFocus + + + 100 + + + 5 + + + 5 + + + 0 + + + 0 + + + true + + + Qt::Horizontal + + + QSlider::TicksAbove + + + 5 + + + + + + + + 0 + 0 + + + + Qt::NoFocus + + + 100 + + + 5 + + + 5 + + + 100 + + + 100 + + + true + + + Qt::Horizontal + + + false + + + false + + + QSlider::TicksAbove + + + 5 + + + + + + + 3 + + + 0.001000000000000 + + + 1.000000000000000 + + + 0.010000000000000 + + + 1.000000000000000 + + + + + + + + + + + + + Send mask to XANESViewer + + + + + + + + + Use Binary Mask + + + + + + + + + + + 0 + 0 + 979 + 37 + + + + + File + + + + + + + + + Options + + + + + + + + + + + Save XANES Stack + + + + + Save XRF Map + + + + + Save Spectrum + + + + + Load Energy List + + + + + Load XRF Map + + + + + Load XANES Stack + + + + + Import Mask + + + + + Export Mask + + + + + + ImageView + QGraphicsView +
pyqtgraph
+
+
+ + +
diff --git a/xmidas/gui/layout/MaskSpecViewer.ui b/xmidas/gui/layout/MaskSpecViewer.ui new file mode 100644 index 0000000..db4d916 --- /dev/null +++ b/xmidas/gui/layout/MaskSpecViewer.ui @@ -0,0 +1,367 @@ + + + MainWindow + + + + 0 + 0 + 900 + 695 + + + + MaskedXANES + + + + + + + QPushButton { +background-color: rgb(175, 236, 255); +color: rgb(255, 5,0); +} + + + + 15 + + + 15 + + + 15 + + + 15 + + + 10 + + + + + + + 3 + + + 1.000000000000000 + + + 0.010000000000000 + + + + + + + + 0 + 0 + + + + Qt::NoFocus + + + 100 + + + 5 + + + 5 + + + 0 + + + 0 + + + true + + + Qt::Horizontal + + + QSlider::TicksAbove + + + 5 + + + + + + + + 0 + 0 + + + + Qt::NoFocus + + + 100 + + + 5 + + + 5 + + + 100 + + + 100 + + + true + + + Qt::Horizontal + + + false + + + false + + + QSlider::TicksAbove + + + 5 + + + + + + + 3 + + + 0.001000000000000 + + + 1.000000000000000 + + + 0.010000000000000 + + + 1.000000000000000 + + + + + + + + + + + + + Apply the mask to XANES + + + + + + Apply Mask + + + + + + + Send mask to XANESViewer + + + + + + + + + Use Binary Mask + + + + + + + + + + + + + + Create A mask + + + Qt::AlignCenter + + + + + + + + + + + + + + + + + Masked Mean Spectrum + + + Qt::AlignCenter + + + + + + + + + + + + + + + + + Binary Mask + + + Qt::AlignCenter + + + + + + + + + + + + + + + + + XANES Stack + + + Qt::AlignCenter + + + + + + + + + + + + + + 0 + 0 + 900 + 37 + + + + + File + + + + + + + + + + + Options + + + + + + + + + + + Save XANES Stack + + + + + Save XRF Map + + + + + Save Spectrum + + + + + Load Energy List + + + + + Load XRF Map + + + + + Load XANES Stack + + + + + Import Mask + + + + + Export Mask + + + + + + ImageView + QGraphicsView +
pyqtgraph
+
+ + PlotWidget + QGraphicsView +
pyqtgraph
+
+
+ + +
diff --git a/xmidas/gui/layout/MaskedView.ui b/xmidas/gui/layout/MaskedView.ui new file mode 100644 index 0000000..7a08678 --- /dev/null +++ b/xmidas/gui/layout/MaskedView.ui @@ -0,0 +1,352 @@ + + + MainWindow + + + + 0 + 0 + 930 + 779 + + + + MaskedXANES + + + + + + + + + + + + color: rgb(255, 0, 0); +font: 12pt "MS Shell Dlg 2"; + + + XANES Stack + + + Qt::AlignCenter + + + + + + + + + + + + + + font: 12pt "MS Shell Dlg 2"; +color: rgb(255, 0, 0); + + + Mask + + + Qt::AlignCenter + + + + + + + + + + + + 0 + + + + + A Tiff Mask with same dimensions + + + background-color: rgb(170, 255, 255); +font: 10pt "MS Shell Dlg 2"; + + + Import Mask + + + + + + + Save Mask tiff + + + background-color: rgb(170, 255, 255); +font: 10pt "MS Shell Dlg 2"; + + + Export Mask + + + + + + + Apply the mask to XANES + + + background-color: rgb(170, 255, 255); +font: 10pt "MS Shell Dlg 2"; + + + Apply + + + + + + + + + + + font: 75 12pt "MS Shell Dlg 2"; +color: rgb(255, 0, 0); + + + Mean Spectrum + + + Qt::AlignCenter + + + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + font: 12pt "MS Shell Dlg 2"; +color: rgb(255, 0, 0); + + + XRF Map + + + Qt::AlignCenter + + + + + + + font: 10pt "MS Shell Dlg 2"; +color: rgb(255, 0, 0); + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + + + + Qt::NoFocus + + + 100 + + + 5 + + + 5 + + + 0 + + + 0 + + + true + + + Qt::Vertical + + + QSlider::TicksAbove + + + 5 + + + + + + + + + + + Qt::NoFocus + + + 100 + + + 5 + + + 5 + + + 100 + + + 100 + + + true + + + Qt::Vertical + + + false + + + false + + + QSlider::TicksBelow + + + 5 + + + + + + + + + + + + + + + + + 0 + 0 + 930 + 26 + + + + + File + + + + + + + + + + + + + + Save XANES Stack + + + + + Save XRF Map + + + + + Save Spectrum + + + + + Load Energy List + + + + + Load XRF Map + + + + + Load XANES Stack + + + + + + ImageView + QGraphicsView +
pyqtgraph
+
+ + PlotWidget + QGraphicsView +
pyqtgraph
+
+
+ + +
diff --git a/xmidas/gui/layout/MultiImageSpectrumView.ui b/xmidas/gui/layout/MultiImageSpectrumView.ui new file mode 100644 index 0000000..a418c19 --- /dev/null +++ b/xmidas/gui/layout/MultiImageSpectrumView.ui @@ -0,0 +1,734 @@ + + + MainWindow + + + + 0 + 0 + 1182 + 821 + + + + Chemical Map Spectrum View + + + font: 12pt "Segoe UI" + + + + QPushButton { +border: 1px solid #555; +border-radius: 5px; +background: qradialgradient(cx: 0.3, cy: -0.1, +fx: 0.7, fy: 0.1, +radius: 1, stop: 0 #fff, stop: 1 #888); +background-color: rgb(170, 255, 255); +} + +QPushButton:hover{ + background-color: rgb(255, 255, 0); + } + +QPushButton:pressed{ + background-color: rgb(0,255, 0); + } + +font: 12pt "Segoe UI"; + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + 0 + 0 + + + + + + + + Edit + + + + + + + 0 + 0 + + + + 0 + + + + + 0 + 0 + 212 + 85 + + + + Thresholding + + + + + + + + + 0 + 0 + + + + 0,100 + + + Qt::AlignCenter + + + + + + + + + + + + 0 + 0 + + + + Qt::NoFocus + + + click update after making changes + + + 100 + + + 5 + + + 5 + + + 100 + + + 100 + + + true + + + Qt::Horizontal + + + false + + + false + + + QSlider::NoTicks + + + 5 + + + + + + + + + + + + 0 + 0 + + + + Qt::NoFocus + + + click update after making changes + + + 100 + + + 5 + + + 5 + + + 0 + + + 0 + + + true + + + Qt::Horizontal + + + QSlider::NoTicks + + + 5 + + + + + + + + + + + + + + + 0 + 0 + 212 + 85 + + + + Opacity + + + + + + + + + 0 + 0 + + + + 1 + + + Qt::AlignCenter + + + + + + + click update after making changes + + + 100 + + + 10 + + + 100 + + + Qt::Horizontal + + + + + + + + + + + + + execute above changes to the selected item + + + Update + + + + + + + + + Show Selected + + + + + + + Show All + + + + + + + + + + 0 + 0 + + + + change properties of the selected item + + + font: 8pt "Segoe UI"; + + + QAbstractScrollArea::AdjustToContents + + + + + + + + + + 0 + 0 + + + + Change Selected To + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + true + + + + + + + + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + XANES Normalization Parameters + + + + + + + 0 + 0 + + + + eV + + + -500.000000000000000 + + + 500.000000000000000 + + + -10.000000000000000 + + + + + + + + 0 + 0 + + + + eV + + + 0.000000000000000 + + + 1000.000000000000000 + + + 25.000000000000000 + + + + + + + + 0 + 0 + + + + 1 + + + 5 + + + + + + + + 0 + 0 + + + + Post-edge + + + + + + + + 0 + 0 + + + + to + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + Norm. Order + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + eV + + + 2 + + + -500.000000000000000 + + + 500.000000000000000 + + + 1.000000000000000 + + + -50.000000000000000 + + + + + + + + 0 + 0 + + + + eV + + + 0.000000000000000 + + + 1500.000000000000000 + + + 75.000000000000000 + + + + + + + + 0 + 0 + + + + Pre-edge + + + + + + + + 0 + 0 + + + + to + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + Eo + + + + + + + + 0 + 0 + + + + eV + + + 1000.000000000000000 + + + 20000.000000000000000 + + + 7125.000000000000000 + + + + + + + + 0 + 0 + + + + Plot Normalized Spectra + + + + + + + + + + + + + + + + + + 0 + 0 + 1182 + 27 + + + + + Image + + + true + + + + + + + + + + Spectrum + + + + + + + + + + Load Images + + + Select and load multiple tiff images to create a multi color view + + + + + Load 2 + + + + + Load 3 + + + + + Load 4 + + + + + Load 5 + + + + + Load 6 + + + + + Export Image + + + Export the image view as a sinle image file + + + + + Save State File + + + Save the current state of the view. Images and properties are saved + + + + + Load State File + + + Load a state (json file) saved previously. + + + + + Load Stack + + + Load images as a stack of tiff + + + + + Save Displayed Spectra(.CSV) + + + + + + PlotWidget + QGraphicsView +
pyqtgraph
+
+ + GraphicsLayoutWidget + QGraphicsView +
pyqtgraph
+
+
+ + +
diff --git a/xmidas/gui/layout/RefChooser.ui b/xmidas/gui/layout/RefChooser.ui new file mode 100644 index 0000000..26f9474 --- /dev/null +++ b/xmidas/gui/layout/RefChooser.ui @@ -0,0 +1,252 @@ + + + MainWindow + + + + 0 + 0 + 986 + 985 + + + + ArrowCursor + + + Select References + + + font: 10pt "MS Shell Dlg 2"; + + + + QCheckBox:checked { +color: rgb(255, 75, 52); + background-color: rgb(255, 248, 149); +} + +QPushButton { +background-color: rgb(175, 236, 255); +color: rgb(255, 5,0); +} + +QPushButton:disabled { +background-color: rgb(255, 227, 213); +color: rgb(255, 255, 255); +} + + + + + + + 25 + + + 25 + + + 25 + + + 25 + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + Drag the line or double click on a point to select the parameters + + + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + + Max. No. of Refs + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 1 + + + 10 + + + 2 + + + + + + + + + + + Try All Cobinations + + + + + + + false + + + Fit With Selected + + + + + + + + + + color: rgb(255, 75, 52); +font: 10pt "MS Shell Dlg 2"; + + + N Combinations + + + Qt::AlignCenter + + + + + + + selection-color: rgb(0, 170, 127); + + + 1 + + + + + + + + + Sort by + + + + + + + + Reduced Chi-Square + + + + + Score + + + + + Fit Number + + + + + R-Factor + + + + + R-Square + + + + + Chi-Square + + + + + + + + + + + + + + + 0 + 0 + 986 + 27 + + + + + File + + + + + + + + + Export Results (.csv) + + + + + + PlotWidget + QGraphicsView +
pyqtgraph
+
+
+ + +
diff --git a/xmidas/gui/layout/Scatter3D.ui b/xmidas/gui/layout/Scatter3D.ui new file mode 100644 index 0000000..cefddb8 --- /dev/null +++ b/xmidas/gui/layout/Scatter3D.ui @@ -0,0 +1,130 @@ + + + MainWindow + + + + 0 + 0 + 658 + 628 + + + + MainWindow + + + + + + + + + + + + + + 0 + 0 + + + + + + + + + + + + + 0 + 0 + 658 + 21 + + + + + View + + + + Plot Background + + + + + + + + + + + File + + + + + + + + + + + + Export + + + + + Save as PNG + + + + + Generate MultiColor Mask + + + + + Black + + + + + Charcol + + + + + White + + + + + Open Images + + + + + Open a Stack + + + + + Export Image + + + + + + GLViewWidget + QGraphicsView +
pyqtgraph.opengl
+
+
+ + +
diff --git a/xmidas/gui/layout/Scatter3D_plotly.ui b/xmidas/gui/layout/Scatter3D_plotly.ui new file mode 100644 index 0000000..df22d6d --- /dev/null +++ b/xmidas/gui/layout/Scatter3D_plotly.ui @@ -0,0 +1,120 @@ + + + MainWindow + + + + 0 + 0 + 856 + 628 + + + + MainWindow + + + + + + + + + + + + + + 0 + 0 + + + + + + + + + + + + + 0 + 0 + 856 + 21 + + + + + View + + + + Plot Background + + + + + + + + + + + + + + toolBar + + + TopToolBarArea + + + false + + + + + + + + Export + + + + + Save as PNG + + + + + Generate MultiColor Mask + + + + + Black + + + + + Grey + + + + + White + + + + + + QWebEngineView + QGraphicsView +
QtWebEngineWidgets
+
+
+ + +
diff --git a/xmidas/gui/layout/ScatterView.ui b/xmidas/gui/layout/ScatterView.ui new file mode 100644 index 0000000..4f0831e --- /dev/null +++ b/xmidas/gui/layout/ScatterView.ui @@ -0,0 +1,249 @@ + + + CorrelationPlot + + + + 0 + 0 + 1034 + 859 + + + + Correlation Plot + + + font:10pt "Segoe UI"; + + + + QRadioButton::indicator { + border: 3px solid rgb(150, 150,150); + width: 15px; + height: 15px; + border-radius: 10px; + background: rgb(255, 255, 255); +} +QRadioButton::indicator:hover { + border: 3px solid rgb(58, 66, 81); +} +QRadioButton::indicator:checked { + background: 3px solid rgb(225, 75, 225); + border: 3px solid rgb(255, 252, 255); +} + + + + + + ROI Mask + + + + + + + + color: rgb(255, 0, 0); +background-color: rgb(20, 20, 20); +font: 87 10pt "Segoe UI Black"; + + + + ROI 1 + + + true + + + false + + + + + + + color: rgb(0, 255, 0); +background-color: rgb(20, 20, 20); +font: 87 10pt "Segoe UI Black"; + + + ROI 2 + + + false + + + + + + + color: rgb(0, 255, 255); +background-color: rgb(20, 20, 20); +font: 87 10pt "Segoe UI Black"; + + + ROI 3 + + + false + + + + + + + + + Create Composite Scatter Plot + + + + + + + Apply ROI Mask(s) + + + + + + + Clear Unchecked + + + + + + + Add Checked ROI(s) + + + + + + + + + + 10 + + + 10 + + + 10 + + + 10 + + + + + Image 1 (Blue Shade) + + + Qt::AlignCenter + + + + + + + + + + + + 10 + + + 10 + + + 10 + + + 10 + + + + + Image 2 (Green Shade) + + + Qt::AlignCenter + + + + + + + + + + + + + + + + + 0 + 0 + 1034 + 23 + + + + + File + + + + + + + Plot + + + + + + + + + + + + + Save Plot + + + + + Save Images + + + + + Swap Axes + + + + + + GraphicsLayoutWidget + QGraphicsView +
pyqtgraph
+
+ + ImageView + QGraphicsView +
pyqtgraph
+
+
+ + +
diff --git a/xmidas/gui/layout/StackViewer.ui b/xmidas/gui/layout/StackViewer.ui new file mode 100644 index 0000000..1d58ea9 --- /dev/null +++ b/xmidas/gui/layout/StackViewer.ui @@ -0,0 +1,335 @@ + + + MainWindow + + + + 0 + 0 + 931 + 815 + + + + MainWindow + + + + + + 11 + 30 + 701 + 326 + + + + + 0 + 0 + + + + + + + 10 + 390 + 891 + 371 + + + + + + + 720 + 80 + 181 + 171 + + + + + 0 + 0 + + + + Image ROI + + + + 11 + + + 11 + + + + + + + + + + + Y End + + + + + + + true + + + + + + + + + + + X Start + + + + + + + true + + + + + + + + + + + Y Start + + + + + + + true + + + + + + + + + + + X End + + + + + + + true + + + + + + + + + + + + + font: 75 10pt "MS Shell Dlg 2"; + + + Size + + + + + + + true + + + + + + + + + + + + + 720 + 250 + 181 + 139 + + + + + 0 + 0 + + + + Spectrum ROI + + + + + + Sync + + + + + + + + + Start + + + + + + + 10000 + + + 2 + + + + + + + + + + + End + + + + + + + 1 + + + 10000 + + + 2 + + + 10 + + + + + + + + + + + font: 75 10pt "MS Shell Dlg 2"; + + + Size + + + + + + + true + + + + + + + + + + + 730 + 10 + 171 + 70 + + + + + + + false + + + background-color: rgb(170, 255, 255); +font: 75 12pt "MS Shell Dlg 2"; + + + Play + + + + + + + Log View + + + + + + + Reset + + + + + + + + + + 0 + 0 + 931 + 26 + + + + + + + + ImageView + QGraphicsView +
pyqtgraph
+
+ + PlotWidget + QGraphicsView +
pyqtgraph
+
+
+ + +
diff --git a/xmidas/gui/layout/XANESViewer.ui b/xmidas/gui/layout/XANESViewer.ui new file mode 100644 index 0000000..2194045 --- /dev/null +++ b/xmidas/gui/layout/XANESViewer.ui @@ -0,0 +1,533 @@ + + + mainWindow + + + + 0 + 0 + 1182 + 602 + + + + XANES Fit View + + + + + + + QPushButton { +background-color: rgb(175, 236, 255); +color: rgb(255, 5,0); +} + + + + + + + + + + + + + 0 + 0 + + + + + + + + XANES Stack + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + Qt::Horizontal + + + + + + + + + + + + 0 + 0 + + + + + + + Chemical Map + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + + + + + + + + + + + Qt::Horizontal + + + + + + + + + + + + + + + + 0 + 0 + + + + Live Fit + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + ROI Position + + + Qt::AlignCenter + + + + + + + + + + + + 0 + 0 + + + + + + + Reference Spectra + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + Choose References + + + + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Preferred + + + + 20 + 215 + + + + + + + + + + + + + 0 + 0 + + + + Update 2D Fit + + + + + + + + + + + E_shift + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + -50.000000000000000 + + + 50.000000000000000 + + + 0.500000000000000 + + + + + + + Regularizer: + + + + + + + useful for noisy data, higher if more noise, not applicable to NNLS + + + 10.000000000000000 + + + 0.250000000000000 + + + 0.100000000000000 + + + + + + + + + + + Fitting Model + + + + + + + + NNLS + + + + + ADMM + + + + + LASSO + + + + + RIDGE + + + + + + + + spectrum will be divided with its last point before fitting (similar to a post-edge normalization) + + + Normalize Fit + + + true + + + + + + + + + + + + + Normalize Chem. Map + + + + + + + + + + 0 + 0 + + + + font: 8pt "MS Shell Dlg 2"; +color: rgb(0, 85, 255); + + + Results Text + + + Qt::AlignCenter + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + 0 + 0 + + + + Open Mask Maker + + + + + + + + 0 + 0 + + + + Open Composite Chem Map Viewer + + + + + + + Open Cluster Mask Tool + + + + + + + Cluster Chem. map + + + + + + + + + + + + 0 + 0 + 1182 + 24 + + + + + File + + + + + + + + + Options + + + + + + + + + + Export Fit Stats + + + + + Export Ref. Plot + + + + + Export Chem Map + + + + + Export R-factor Image + + + + + false + + + Export References + + + + + Export Fit Stats + + + + + Export All Plotted Data + + + Ctrl+S + + + + + Export Sum Fit Data + + + + + + PlotWidget + QGraphicsView +
pyqtgraph
+
+ + ImageView + QGraphicsView +
pyqtgraph
+
+
+ + +
diff --git a/xmidas/gui/layout/align_test.ui b/xmidas/gui/layout/align_test.ui new file mode 100644 index 0000000..a5ab854 --- /dev/null +++ b/xmidas/gui/layout/align_test.ui @@ -0,0 +1,71 @@ + + + MainWindow + + + + 0 + 0 + 280 + 271 + + + + MainWindow + + + + + + 100 + 50 + 93 + 28 + + + + Load + + + + + + 100 + 100 + 93 + 28 + + + + Align + + + + + + 100 + 160 + 93 + 28 + + + + Save + + + + + + + 0 + 0 + 280 + 26 + + + + + + + + diff --git a/xmidas/gui/layout/animationWindow.ui b/xmidas/gui/layout/animationWindow.ui new file mode 100644 index 0000000..21e0c3a --- /dev/null +++ b/xmidas/gui/layout/animationWindow.ui @@ -0,0 +1,68 @@ + + + Wait + + + + 0 + 0 + 200 + 200 + + + + Wait... + + + Qt::LeftToRight + + + +background-color: rgba(0, 0, 90, 125); + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + Qt::NoContextMenu + + + + + + + + + false + + + Qt::AlignCenter + + + + + + + + diff --git a/xmidas/gui/layout/css/darkStyle.css b/xmidas/gui/layout/css/darkStyle.css new file mode 100644 index 0000000..ea2c89f --- /dev/null +++ b/xmidas/gui/layout/css/darkStyle.css @@ -0,0 +1,68 @@ +QWidget { +background-color: rgb(60, 60, 60); +color: rgb(255, 255, 255); +font: 10pt "Segoe UI"; +} + +QPushButton { +background-color: rgb(175, 236, 255); +color: rgb(255, 5,0); +} + +QSlider::groove:horizontal { +border: 1px solid #bbb; +background: white; +height: 10px; +border-radius: 4px; +} + +QSlider::sub-page:horizontal { +background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #66e, stop: 1 #bbf); +background: qlineargradient(x1: 0, y1: 0.2, x2: 1, y2: 1, + stop: 0 #bbf, stop: 1 #55f); +border: 1px solid #777; +height: 10px; +border-radius: 4px; +} + +QSlider::add-page:horizontal { +background: #fff; +border: 1px solid #777; +height: 10px; +border-radius: 4px; +} + +QSlider::handle:horizontal { +background: qlineargradient(x1:0, y1:0, x2:1, y2:1, + stop:0 #eee, stop:1 #ccc); +border: 1px solid #777; +width: 13px; +margin-top: -2px; +margin-bottom: -2px; +border-radius: 4px; +} + +QSlider::handle:horizontal:hover { +background: qlineargradient(x1:0, y1:0, x2:1, y2:1, + stop:0 #fff, stop:1 #ddd); +border: 1px solid #444; +border-radius: 2px; +} + +QSlider::sub-page:horizontal:disabled { +background: #bbb; +border-color: #999; +} + +QSlider::add-page:horizontal:disabled { +background: #eee; +border-color: #999; +} + +QSlider::handle:horizontal:disabled { +background: #eee; +border: 1px solid #aaa; +border-radius: 4px; +} + diff --git a/xmidas/gui/layout/css/defaultStyle.css b/xmidas/gui/layout/css/defaultStyle.css new file mode 100644 index 0000000..11c2467 --- /dev/null +++ b/xmidas/gui/layout/css/defaultStyle.css @@ -0,0 +1,72 @@ + +QWidget { +font: 10pt "Segoe UI"; +} + +QPushButton { +background-color: rgb(175, 236, 255); +color: rgb(255, 5,0); +font: 10pt "Segoe UI"; +} + +QLabel { +font: 10pt "Segoe UI"; +} + +QSlider::groove:horizontal { +border: 1px solid #bbb; +background: white; +height: 10px; +border-radius: 4px; +} + +QSlider::sub-page:horizontal { +background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #66e, stop: 1 #bbf); +background: qlineargradient(x1: 0, y1: 0.2, x2: 1, y2: 1, + stop: 0 #bbf, stop: 1 #55f); +border: 1px solid #777; +height: 10px; +border-radius: 4px; +} + +QSlider::add-page:horizontal { +background: #fff; +border: 1px solid #777; +height: 10px; +border-radius: 4px; +} + +QSlider::handle:horizontal { +background: qlineargradient(x1:0, y1:0, x2:1, y2:1, + stop:0 #eee, stop:1 #ccc); +border: 1px solid #777; +width: 13px; +margin-top: -2px; +margin-bottom: -2px; +border-radius: 4px; +} + +QSlider::handle:horizontal:hover { +background: qlineargradient(x1:0, y1:0, x2:1, y2:1, + stop:0 #fff, stop:1 #ddd); +border: 1px solid #444; +border-radius: 2px; +} + +QSlider::sub-page:horizontal:disabled { +background: #bbb; +border-color: #999; +} + +QSlider::add-page:horizontal:disabled { +background: #eee; +border-color: #999; +} + +QSlider::handle:horizontal:disabled { +background: #eee; +border: 1px solid #aaa; +border-radius: 4px; +} + diff --git a/xmidas/gui/layout/css/modern.css b/xmidas/gui/layout/css/modern.css new file mode 100644 index 0000000..a949b73 --- /dev/null +++ b/xmidas/gui/layout/css/modern.css @@ -0,0 +1,289 @@ +/* ///////////////////////////////////////////////////////////////////////////////////////////////// + +SET APP STYLESHEET - FULL STYLES HERE +DARK THEME - DRACULA COLOR BASED + +///////////////////////////////////////////////////////////////////////////////////////////////// */ + +QWidget{ + background-color: rgb(23,23,37); + color: rgb(255, 255, 200); + font: 10pt "Segoe UI"; +} + + + +/* ///////////////////////////////////////////////////////////////////////////////////////////////// +Tooltip */ +QToolTip { + color: #ffffff; + background-color: rgba(33, 37, 43, 180); + border: 1px solid rgb(44, 49, 58); + background-image: none; + background-position: left center; + background-repeat: no-repeat; + border: none; + border-left: 2px solid rgb(255, 121, 198); + text-align: left; + padding-left: 8px; + margin: 0px; +} + + +QPushButton { + background-color: rgb(210, 210, 98); + color: rgb(23,23,37); + border: none; + border-radius: 5px; + padding: 4px; +} +QPushButton:hover { + background-color: rgb(211, 100, 211); +} +QPushButton:pressed { + background-color: rgb(189, 147, 249); + color: rgb(255, 255, 255); +} + + +QTabWidget { + color: rgb(44, 0, 0); +} +QTabWidget::item{ + color: rgb(24, 0, 0); +} +QTabBar::tab { + color:rgb(24, 0, 0); +} + +QLineEdit { + background-color: rgb(33, 37, 43); + border-radius: 5px; + border: 2px solid rgb(33, 37, 43); + padding-left: 10px; + color: rgb(255,255,255); + selection-color: rgb(255, 255, 255); + selection-background-color: rgb(255, 121, 198); +} +QLineEdit:hover { + border: 2px solid rgb(64, 71, 88); +} +QLineEdit:focus { + border: 2px solid rgb(91, 101, 124); +} + +/* ///////////////////////////////////////////////////////////////////////////////////////////////// +PlainTextEdit */ +QPlainTextEdit { + background-color: rgb(27, 29, 35); + border-radius: 5px; + padding: 10px; + selection-color: rgb(255, 255, 255); + selection-background-color: rgb(255, 121, 198); +} +QPlainTextEdit QScrollBar:vertical { + width: 8px; + } +QPlainTextEdit QScrollBar:horizontal { + height: 8px; + } +QPlainTextEdit:hover { + border: 2px solid rgb(64, 71, 88); +} +QPlainTextEdit:focus { + border: 2px solid rgb(91, 101, 124); +} + +/* ///////////////////////////////////////////////////////////////////////////////////////////////// +ScrollBars */ +QScrollBar:horizontal { + border: none; + background: rgb(52, 59, 72); + height: 8px; + margin: 0px 21px 0 21px; + border-radius: 0px; +} +QScrollBar::handle:horizontal { + background: rgb(189, 147, 249); + min-width: 25px; + border-radius: 4px +} +QScrollBar::add-line:horizontal { + border: none; + background: rgb(55, 63, 77); + width: 20px; + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; + subcontrol-position: right; + subcontrol-origin: margin; +} +QScrollBar::sub-line:horizontal { + border: none; + background: rgb(55, 63, 77); + width: 20px; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; + subcontrol-position: left; + subcontrol-origin: margin; +} +QScrollBar::up-arrow:horizontal, QScrollBar::down-arrow:horizontal +{ + background: none; +} +QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal +{ + background: none; +} + QScrollBar:vertical { + border: none; + background: rgb(52, 59, 72); + width: 8px; + margin: 21px 0 21px 0; + border-radius: 0px; + } + QScrollBar::handle:vertical { + background: rgb(189, 147, 249); + min-height: 25px; + border-radius: 4px + } + QScrollBar::add-line:vertical { + border: none; + background: rgb(55, 63, 77); + height: 20px; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + subcontrol-position: bottom; + subcontrol-origin: margin; + } + QScrollBar::sub-line:vertical { + border: none; + background: rgb(55, 63, 77); + height: 20px; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + subcontrol-position: top; + subcontrol-origin: margin; + } + QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical { + background: none; + } + + QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { + background: none; + } + + +QRadioButton::indicator { + border: 3px solid rgb(52, 59, 72); + width: 15px; + height: 15px; + border-radius: 10px; + background: rgb(44, 4, 0); +} +QRadioButton::indicator:hover { + border: 3px solid rgb(58, 66, 81); +} +QRadioButton::indicator:checked { + background: 3px solid rgb(0, 255, 0); + border: 3px solid rgb(255, 252, 255); +} + +QCheckBox::indicator { + border: 3px solid rgb(52, 59, 72); + width: 15px; + height: 15px; + border-radius: 10px; + background: rgb(44, 4, 0); +} +QCheckBox::indicator:hover { + border: 3px solid rgb(58, 66, 81); +} +QCheckBox::indicator:checked { + background: 3px solid rgb(0, 255, 0); + border: 3px solid rgb(255, 252, 255); +} + +/* ///////////////////////////////////////////////////////////////////////////////////////////////// +ComboBox */ +QComboBox{ + background-color: rgb(138, 138, 138); + color: rgb(79, 27, 79); + border-radius: 5px; + border: 2px solid rgb(33, 37, 43); + padding: 5px; + padding-left: 10px; +} +QComboBox:hover{ + border: 2px solid rgb(64, 71, 88); +} +QComboBox::drop-down { + subcontrol-origin: padding; + subcontrol-position: top right; + width: 25px; + border-left-width: 3px; + border-left-color: rgba(39, 44, 54, 150); + border-left-style: solid; + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; + background-image: url(:/icons/images/icons/cil-arrow-bottom.png); + background-position: center; + background-repeat: no-reperat; + } +QComboBox QAbstractItemView { + color: rgb(255, 121, 198); + background-color: rgb(33, 37, 43); + padding: 10px; + selection-background-color: rgb(39, 44, 54); +} + +/* ///////////////////////////////////////////////////////////////////////////////////////////////// +Sliders */ +QSlider::groove:horizontal { + border-radius: 5px; + height: 10px; + margin: 0px; + background-color: rgb(52, 59, 72); +} +QSlider::groove:horizontal:hover { + background-color: rgb(55, 62, 76); +} +QSlider::handle:horizontal { + background-color: rgb(189, 147, 249); + border: none; + height: 10px; + width: 10px; + margin: 0px; + border-radius: 5px; +} +QSlider::handle:horizontal:hover { + background-color: rgb(195, 155, 255); +} +QSlider::handle:horizontal:pressed { + background-color: rgb(255, 121, 198); +} + +QSlider::groove:vertical { + border-radius: 5px; + width: 10px; + margin: 0px; + background-color: rgb(52, 59, 72); +} +QSlider::groove:vertical:hover { + background-color: rgb(55, 62, 76); +} +QSlider::handle:vertical { + background-color: rgb(189, 147, 249); + border: none; + height: 10px; + width: 10px; + margin: 0px; + border-radius: 5px; +} +QSlider::handle:vertical:hover { + background-color: rgb(195, 155, 255); +} +QSlider::handle:vertical:pressed { + background-color: rgb(255, 121, 198); +} + + diff --git a/xmidas/gui/layout/decomposeViewer.ui b/xmidas/gui/layout/decomposeViewer.ui new file mode 100644 index 0000000..2b1f173 --- /dev/null +++ b/xmidas/gui/layout/decomposeViewer.ui @@ -0,0 +1,694 @@ + + + MainWindow + + + + 0 + 0 + 971 + 666 + + + + MainWindow + + + + + + + + + + + + + true + + + + 0 + 0 + + + + + + + View Stack + + + + + + + + 0 + 0 + + + + + + + Show Scree Plot + + + + + + + + + + 0 + 0 + + + + + + + Calculate Components + + + + + + + + + Method + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + PCA + + + + + NMF + + + + + FastICA + + + + + IncrementalPCA + + + + + TruncatedSVD + + + + + FactorAnalysis + + + + + DictionaryLearning + + + + + + + + + + + + Number of Components + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 1 + + + 4 + + + + + + + + + + + + + + + + 0 + 0 + + + + + + + Cluster Stack + + + + + + + Use components + + + + + + + + + + + Method + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + + + + KMeans + + + + + MiniBatchKMeans + + + + + MeanShift + + + + + Spectral Clustering + + + + + Correlation-Kmeans + + + + + Affinity Propagation + + + + + + + + + + + + Number of Clusters + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 1 + + + 4 + + + + + + + + + + + + + + + + + + + + + 0 + 0 + + + + + + + + + + + Eigen Values + + + Qt::AlignCenter + + + + + + + + + + + + + + Eigen Spectrum + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + + + + + + + + + + + Eigen Value Mask + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + + + + + + + + + + + Masked Spectrum + + + Qt::AlignCenter + + + + + + + + + + + + + + + + + 0 + 0 + + + + font: 12pt "Segoe UI"; + + + 1/3 + + + + + + + + 0 + 0 + + + + + + + 20 + + + 1 + + + 1 + + + Qt::Horizontal + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + 0 + 0 + + + + + + + Open ScatterPlot + + + + + + + + 0 + 0 + + + + + + + Show All Spectra + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Send Comp. as Mask + + + + + + + Use Binary Mask + + + true + + + + + + + + + + + + + 0 + 0 + + + + Qt::NoFocus + + + 100 + + + 5 + + + 5 + + + 100 + + + 100 + + + true + + + Qt::Horizontal + + + false + + + false + + + QSlider::TicksAbove + + + 5 + + + + + + + 3 + + + 0.001000000000000 + + + 1.000000000000000 + + + 0.010000000000000 + + + 1.000000000000000 + + + + + + + 3 + + + 1.000000000000000 + + + 0.010000000000000 + + + + + + + + 0 + 0 + + + + Qt::NoFocus + + + 100 + + + 5 + + + 5 + + + 0 + + + 0 + + + true + + + Qt::Horizontal + + + QSlider::TicksAbove + + + 5 + + + + + + + Apply + + + + + + + + + + + Send mask and save results + + + + + + + + + + Browse + + + + + + + + + + + 0 + 0 + 971 + 37 + + + + + File + + + + + + + + + Save + + + + + + PlotWidget + QGraphicsView +
pyqtgraph
+
+ + ImageView + QGraphicsView +
pyqtgraph
+
+
+ + +
diff --git a/xmidas/gui/layout/log.ui b/xmidas/gui/layout/log.ui new file mode 100644 index 0000000..6ff023b --- /dev/null +++ b/xmidas/gui/layout/log.ui @@ -0,0 +1,68 @@ + + + MainWindow + + + + 0 + 0 + 624 + 759 + + + + Log + + + + + + + font: 10pt "Segoe UI"; + + + QAbstractScrollArea::AdjustToContentsOnFirstShow + + + QPlainTextEdit::NoWrap + + + start typing here.. + + + + + + + + + Save + + + + + + + Clear + + + + + + + + + + + 0 + 0 + 624 + 26 + + + + + + + + diff --git a/xmidas/gui/layout/maskedScatterPlotFit.ui b/xmidas/gui/layout/maskedScatterPlotFit.ui new file mode 100644 index 0000000..8ad2145 --- /dev/null +++ b/xmidas/gui/layout/maskedScatterPlotFit.ui @@ -0,0 +1,187 @@ + + + CorrelationPlot + + + + 0 + 0 + 967 + 816 + + + + Correlation Plot + + + font: 12pt "MS Shell Dlg 2"; + + + + + 10 + + + 25 + + + 10 + + + 10 + + + + + Scatter Plot + + + + + + + 0 + 0 + + + + + + + + + + + Mask + + + + + + + 0 + 0 + + + + + + + + + + + + 0 + 0 + + + + Fit Results + + + + + + Copy + + + + + + + + 0 + 0 + + + + font: 11pt "Consolas"; + + + true + + + + + + + Export + + + + + + + + + + Masked Image1 + + + + + + + 0 + 0 + + + + + + + + + + + + + + 0 + 0 + 967 + 25 + + + + + Export + + + + + + + + + + Scatter Plot+Fit + + + + + Mask + + + + + Masked Image + + + + + + ImageView + QGraphicsView +
pyqtgraph
+
+ + GraphicsLayoutWidget + QGraphicsView +
pyqtgraph
+
+
+ + +
diff --git a/xmidas/gui/layout/midasMainwindow.ui b/xmidas/gui/layout/midasMainwindow.ui new file mode 100644 index 0000000..dcd166c --- /dev/null +++ b/xmidas/gui/layout/midasMainwindow.ui @@ -0,0 +1,3034 @@ + + + Ajith + MainWindow + + + true + + + + 0 + 0 + 1287 + 842 + + + + + 0 + 0 + + + + NSLS-II MIDAS + + + + pancake.icopancake.ico + + + font: 10pt "Segoe UI"; + + + + + true + + + + 0 + 0 + + + + QWidget { +font: 10pt "Segoe UI"; +} + +QPushButton { +background-color: rgb(175, 236, 255); +color: rgb(255, 5,0); +font: 10pt "Segoe UI"; +} + +QLabel { +font: 10pt "Segoe UI"; +} + +QSlider::groove:horizontal { +border: 1px solid #bbb; +background: white; +height: 10px; +border-radius: 4px; +} + +QSlider::sub-page:horizontal { +background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #66e, stop: 1 #bbf); +background: qlineargradient(x1: 0, y1: 0.2, x2: 1, y2: 1, + stop: 0 #bbf, stop: 1 #55f); +border: 1px solid #777; +height: 10px; +border-radius: 4px; +} + +QSlider::add-page:horizontal { +background: #fff; +border: 1px solid #777; +height: 10px; +border-radius: 4px; +} + +QSlider::handle:horizontal { +background: qlineargradient(x1:0, y1:0, x2:1, y2:1, + stop:0 #eee, stop:1 #ccc); +border: 1px solid #777; +width: 13px; +margin-top: -2px; +margin-bottom: -2px; +border-radius: 4px; +} + +QSlider::handle:horizontal:hover { +background: qlineargradient(x1:0, y1:0, x2:1, y2:1, + stop:0 #fff, stop:1 #ddd); +border: 1px solid #444; +border-radius: 2px; +} + +QSlider::sub-page:horizontal:disabled { +background: #bbb; +border-color: #999; +} + +QSlider::add-page:horizontal:disabled { +background: #eee; +border-color: #999; +} + +QSlider::handle:horizontal:disabled { +background: #eee; +border: 1px solid #aaa; +border-radius: 4px; +} + + + + + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + + + + 0 + 0 + + + + + + + 0 + + + + + 0 + 0 + 302 + 288 + + + + Adjust Image Dimensions + + + + + + + 0 + 0 + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + QLayout::SetMinimumSize + + + + + + 0 + 0 + + + + 0 + + + 500 + + + 0 + + + 10 + + + + + + + + 0 + 0 + + + + 1 + + + 5000 + + + 1200 + + + 10 + + + + + + + + 0 + 0 + + + + false + + + px + + + 1 + + + 10000 + + + 100 + + + + + + + + 0 + 0 + + + + false + + + px + + + 1 + + + 10000 + + + 100 + + + + + + + + 0 + 0 + + + + false + + + px + + + 0 + + + 10000 + + + 0 + + + + + + + + 0 + 0 + + + + Y Dimension + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + false + + + px + + + 0 + + + 10000 + + + 0 + + + + + + + + 0 + 0 + + + + X Dimension + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + Stack Range + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + to + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + to + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + to + + + Qt::AlignCenter + + + + + + + + + + 0 + 0 + + + + Adjust the dimensions of the image + + + + + + Update + + + + + + + Apply crop to all tiffs in directory + + + + + + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + 0 + 0 + + + + Removes one column/row from all four edges + + + Remove Edges + + + + + + + + + true + + + + 0 + 0 + + + + rebin + + + + + + + true + + + + 0 + 0 + + + + Upscale + + + + + + + + + Ratio + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + true + + + + 0 + 0 + + + + font: 10pt "MS Shell Dlg 2"; + + + 2 + + + 16 + + + 2 + + + 2 + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + 0 + 0 + 233 + 365 + + + + Image Processing + + + + + + + + + reverses the image axes (ZXY) to (YXZ) + + + Transpose + + + + + + + swaps 2nd and 3rd axes (ZXY) to (ZYX) + + + Swap XY Axes + + + + + + + + + + + + 0 + 0 + + + + Covert image dat to log values. + + + + + + Log + + + false + + + + + + + + 0 + 0 + + + + Intensity Normalization with the last Frame. + + + Normalize to Max + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + Remove Outliers (NSigma) + + + + + + + false + + + + + + 200 + + + 3 + + + Qt::Horizontal + + + + + + + 1 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + + Thresholding + + + + + + + + + + + false + + + 100 + + + 5 + + + 5 + + + 5 + + + Qt::Horizontal + + + + + + + 5 + + + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + uses savgol_filter to smooth data + + + Smoothen + + + + + + + + + false + + + 3 + + + 12 + + + 2 + + + 2 + + + 3 + + + Qt::Horizontal + + + QSlider::TicksBelow + + + 2 + + + + + + + Window size + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + + + + + + 0 + 0 + 286 + 247 + + + + Alignment + + + + + + + + + + + Transformations: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + TRANSLATION + + + + + RIGID_BODY + + + + + SCALED_ROTATION + + + + + AFFINE + + + + + BILINEAR + + + + + + + + + + + + Reference: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + previous + + + + + mean + + + + + first + + + + + + + + + + + + + 0 + 0 + + + + Iterative Mode + + + + + + + + + Max Iter. + + + + + + + + 0 + 0 + + + + 2 + + + 24 + + + + + + + + + + + + 0 + 0 + + + + Align + + + + + + + + + + 0 + 0 + + + + Load Reference Stack + + + + + + + No Ref. Available + + + true + + + + + + + + + + 0 + 0 + + + + Save Transformation File + + + + + + + Use + + + + + + + + 0 + 0 + + + + Load Transformation File + + + + + + + + + + + + + + + 0 + 0 + + + + + + + Reset Image + + + + + + + true + + + 1 + + + + + 0 + 0 + 302 + 205 + + + + Component Analysis + + + + + + + + + 0 + 0 + + + + + + + Calculate Components + + + + + + + + 0 + 0 + + + + + + + PCA Scree Plot + + + + + + + + + Method + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + PCA + + + + + NMF + + + + + FastICA + + + + + IncrementalPCA + + + + + TruncatedSVD + + + + + FactorAnalysis + + + + + DictionaryLearning + + + + + + + + + + + + Number of Components + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 1 + + + 4 + + + + + + + + + + + + + 0 + 0 + 302 + 205 + + + + Cluster Analysis + + + + + + + + + 0 + 0 + + + + + + + Calculate Clusters + + + + + + + + 0 + 0 + + + + + + + KMeans Variance Plot + + + + + + + Method + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + KMeans + + + + + MiniBatchKMeans + + + + + MeanShift + + + + + Spectral Clustering + + + + + Correlation-Kmeans + + + + + Affinity Propagation + + + + + + + + Number of Clusters + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 1 + + + 4 + + + + + + + + + + + 0 + 0 + 302 + 205 + + + + XANES Fitting + + + + + + + 11 + + + 11 + + + + + + + + 0 + 0 + + + + + + + Load Energy List + + + + + + + keV + + + + + + + + + + + + 0 + 0 + + + + + + + Load Ref. Spec. + + + + + + + + + + Plot + + + + + + + + + true + + + + 0 + 0 + + + + + + + Fit + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + + 0 + 0 + + + + + + + + + + + QLayout::SetMaximumSize + + + + + 0 + + + + Live + + + + + + + 0 + 0 + + + + Send to Plot Collection + + + + + + + + 0 + 0 + + + + + + + Save + + + + + + + + 0 + 0 + + + + + + + + + Normalized + + + + + + + 0 + 0 + + + + + + + + Norm. to Collector + + + + + + + Save + + + + + + + Clear + + + + + + + + Collection + + + + + + + 0 + 0 + + + + + + + + Clear + + + + + + + Save + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 0 + 0 + + + + + + + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + + + + + font: 9pt "Segoe UI"; + + + ROI Positions + + + + + + Spectrum ROI + + + + + + Range (eV): + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + color: rgb(255, 0,0); + + + roi_size + + + + + + + color: rgb(255, 0,0); + + + roix, roiy + + + + + + + + + + Size (eV): + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + Image ROI + + + + + + Position: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + color: rgb(255, 0,0); + + + roix, roiy + + + + + + + + + + Size(pixels): + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + color: rgb(255, 0, 0); + + + roi_size + + + + + + + + + + + + + + 0 + 0 + + + + ROI Shape + + + + + + + 0 + 0 + + + + Ellipse + + + + + + + + 0 + 0 + + + + Rectangle + + + true + + + + + + + + 0 + 0 + + + + Polygon + + + false + + + + + + + + 0 + 0 + + + + Circle + + + + + + + + 0 + 0 + + + + Zoom to ROI + + + + + + + + 0 + 0 + + + + Line + + + + + + + + + + + 0 + 0 + + + + Qt::LeftToRight + + + 2 + + + + + 0 + 0 + 305 + 384 + + + + Image Calculations + + + + + + + + + + + + + + + Add ROI_2 + + + + + + + Calculation: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + Subtract + + + + + Divide + + + + + Add + + + + + Compare + + + + + + + + Apply + + + + + + + + + + + + 0 + 0 + 323 + 384 + + + + Spectrum Calculations + + + + + + + + + + + + + 0 + 0 + + + + Add ROI 2 + + + true + + + false + + + false + + + + + + + + + + 0 + 0 + + + + Calculation + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + Divide + + + + + Subtract + + + + + Add + + + + + Correlation Plot + + + + + + + + + + Use ROI for Correlations + + + + + + + Apply + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + 0 + 0 + 365 + 384 + + + + XANES Normalization + + + + + + + + + + + + + + + 0 + 0 + + + + calculate the energy point with maximum derivative + + + Find Eo + + + + + + + + 0 + 0 + + + + Initial Guess + + + + + + + + + + + + 0 + 0 + + + + Element_Edge: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + Pre-edge + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + Post-edge + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + 0 + 0 + + + + <html><head/><body><p> For mbak algorithm only, must be in <span style=" font-weight:600; font-style:italic;">element&lt;space&gt;edge</span> format</p></body></html> + + + Fe_K + + + + + + + + 0 + 0 + + + + eV + + + 2 + + + -500.000000000000000 + + + 500.000000000000000 + + + 1.000000000000000 + + + -50.000000000000000 + + + + + + + + 0 + 0 + + + + eV + + + 0.000000000000000 + + + 1000.000000000000000 + + + 25.000000000000000 + + + + + + + + + + + + 0 + 0 + + + + Eo: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + to + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + to + + + Qt::AlignCenter + + + + + + + + + + + + 0 + 0 + + + + eV + + + 1000.000000000000000 + + + 20000.000000000000000 + + + 7125.000000000000000 + + + + + + + + 0 + 0 + + + + eV + + + -500.000000000000000 + + + 500.000000000000000 + + + -10.000000000000000 + + + + + + + + 0 + 0 + + + + eV + + + 0.000000000000000 + + + 1500.000000000000000 + + + 75.000000000000000 + + + + + + + + + + + + + + + + 0 + 0 + + + + Norm. Order + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + 1 + + + 5 + + + + + + + + + + 0 + 0 + + + + Use Flattened + + + + + + + + 0 + 0 + + + + Apply to Spectrum + + + + + + + + 0 + 0 + + + + Apply to Stack + + + + + + + + 0 + 0 + + + + Ignore Post Edge (Stack Only) + + + + + + + MBAK Algorithm + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 0 + 1287 + 24 + + + + + + + + Help + + + + + + + File + + + + + + + + + + + + true + + + Accessories + + + + + + + View + + + + Plot Background + + + + + + + + + + Window Background + + + + + + + + Change_Plot_Line_Width + + + + + + + + + + + + + + + + + Spectrum + + + + + + + + + Image + + + + + + + + + + + + Batch + + + + + + + + + + + + + + + + + 0 + 0 + + + + toolBar + + + TopToolBarArea + + + false + + + + + + + + Open PDF + + + + + Open in GitHub (most updated) + + + + + true + + + Open Image Data + + + Support all tiff and specific h5 files + + + Ctrl+O + + + + + Close + + + + + Exit + + + Ctrl+Q + + + + + false + + + Export Tiff Stack + + + Save the displayed/Modified stack as a tiff file + + + Ctrl+S + + + + + Open PyXRF + + + + + Open Image J + + + + + Open TomViz + + + + + Open Mantis + + + + + Open Athena + + + + + DataBroker + + + + + Open HXN DB + + + + + false + + + Load Energy + + + Load list of energies for XANES stack. Supports only .txt fromat + + + Ctrl+E + + + + + Create a Virtual Stack + + + Create a stack from multiple tiff images of same shape + + + Ctrl+M + + + + + true + + + Open Mask Generator + + + A new window will be opened to creat threshold based masks + + + + + Create elist from log file + + + + + false + + + Export Energy List + + + + + true + + + MultiColorView + + + A new window will be opened to align images in a stack + + + + + White + + + + + true + + + true + + + Black + + + + + Red + + + + + Yellow + + + + + Blue + + + + + false + + + false + + + Dark Mode + + + + + Black + + + + + false + + + false + + + Default + + + + + Vivid + + + + + Export Sum Image (XYZ to sum(XY)) + + + + + Subtract ROI as Background + + + + + Export Norm. Params + + + + + 2 + + + + + 4 + + + + + 6 + + + + + 10 + + + + + 2 + + + + + 3 + + + + + 4 + + + + + 5 + + + + + 6 + + + + + 8 + + + + + 10 + + + + + 2 + + + + + Import Norm. Params + + + + + 1 + + + + + Save Sum Spectrum + + + + + Save Mean Spectrum + + + + + Save Current Image as Mask + + + + + Stack to RGBCMY Image + + + + + Apply Current Crop to All images + + + all images in the folder will be cropped in reference to current + + + + + + + + + + + Save Current State + + + + + Normalize with another Stack + + + + + Stack Info + + + Diaplays details of the stack + + + + + Export Image + + + Saves displayed 2D image frame + + + + + + .. + + + Export Stack + + + Save current stack as is + + + false + + + + + Export Mean Image (XYZ to mean(XY)) + + + + + Plot All Possible Image Correlations + + + + + Export Image as CSV (XYZ to Z,X*Y) + + + + + + PlotWidget + QGraphicsView +
pyqtgraph
+
+ + ImageView + QGraphicsView +
pyqtgraph
+
+
+ + +
diff --git a/xmidas/gui/layout/multipleScatterFit.ui b/xmidas/gui/layout/multipleScatterFit.ui new file mode 100644 index 0000000..64b9363 --- /dev/null +++ b/xmidas/gui/layout/multipleScatterFit.ui @@ -0,0 +1,114 @@ + + + MainWindow + + + + 0 + 0 + 856 + 628 + + + + MainWindow + + + + + + + + + + + + + + 0 + 0 + + + + + + + + + + + + + 0 + 0 + 856 + 21 + + + + + View + + + + Plot Background + + + + + + + + + + + + + toolBar + + + TopToolBarArea + + + false + + + + + + + + Export + + + + + Save as PNG + + + + + Generate MultiColor Mask + + + + + Black + + + + + White + + + + + + GraphicsLayoutWidget + QGraphicsView +
pyqtgraph
+
+
+ + +
diff --git a/xmidas/gui/layout/mutlichannel.ui b/xmidas/gui/layout/mutlichannel.ui new file mode 100644 index 0000000..7315290 --- /dev/null +++ b/xmidas/gui/layout/mutlichannel.ui @@ -0,0 +1,464 @@ + + + MainWindow + + + + 0 + 0 + 612 + 765 + + + + MainWindow + + + font: 12pt "Segoe UI" + + + + QPushButton { +border: 1px solid #555; +border-radius: 5px; +background: qradialgradient(cx: 0.3, cy: -0.1, +fx: 0.7, fy: 0.1, +radius: 1, stop: 0 #fff, stop: 1 #888); +background-color: rgb(170, 255, 255); +} + +QPushButton:hover{ + background-color: rgb(255, 255, 0); + } + +QPushButton:pressed{ + background-color: rgb(0,255, 0); + } + +font: 12pt "Segoe UI"; + + + + 25 + + + 25 + + + 25 + + + 25 + + + + + + 0 + 0 + + + + + + + + Edit + + + + + + + 0 + 0 + + + + 0 + + + + + 0 + 0 + 254 + 85 + + + + Thresholding + + + + + + + + + 0 + 0 + + + + 0,100 + + + Qt::AlignCenter + + + + + + + + + + + + 0 + 0 + + + + Qt::NoFocus + + + click update after making changes + + + 100 + + + 5 + + + 5 + + + 100 + + + 100 + + + true + + + Qt::Horizontal + + + false + + + false + + + QSlider::NoTicks + + + 5 + + + + + + + + + + + + 0 + 0 + + + + Qt::NoFocus + + + click update after making changes + + + 100 + + + 5 + + + 5 + + + 0 + + + 0 + + + true + + + Qt::Horizontal + + + QSlider::NoTicks + + + 5 + + + + + + + + + + + + + + + 0 + 0 + 98 + 81 + + + + Opacity + + + + + + + + + 0 + 0 + + + + 1 + + + Qt::AlignCenter + + + + + + + click update after making changes + + + 100 + + + 10 + + + 100 + + + Qt::Horizontal + + + + + + + + + + + + + execute above changes to the selected item + + + Update + + + + + + + + + Show Selected + + + + + + + Show All + + + + + + + + + + 0 + 0 + + + + change properties of the selected item + + + font: 8pt "Segoe UI"; + + + QAbstractScrollArea::AdjustToContents + + + + + + + + + + 0 + 0 + + + + Change Selected To + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + true + + + + + + + + + + + + + + + + + + 0 + 0 + 612 + 34 + + + + + File + + + true + + + + + + + + + + + + + + Load Images + + + Select and load multiple tiff images to create a multi color view + + + + + Load 2 + + + + + Load 3 + + + + + Load 4 + + + + + Load 5 + + + + + Load 6 + + + + + Export Image + + + Export the image view as a sinle image file + + + + + Save State File + + + Save the current state of the view. Images and properties are saved + + + + + Load State File + + + Load a state (json file) saved previously. + + + + + Load Stack + + + Load images as a stack of tiff + + + + + Save Stack (.tiff) + + + + + + GraphicsLayoutWidget + QGraphicsView +
pyqtgraph
+
+
+ + +
diff --git a/xmidas/gui/layout/singleStackView.ui b/xmidas/gui/layout/singleStackView.ui new file mode 100644 index 0000000..22ee549 --- /dev/null +++ b/xmidas/gui/layout/singleStackView.ui @@ -0,0 +1,151 @@ + + + MainWindow + + + + 0 + 0 + 691 + 566 + + + + MainWindow + + + QSlider::groove:horizontal { +border: 1px solid #bbb; +background: white; +height: 10px; +border-radius: 4px; +} + +QSlider::sub-page:horizontal { +background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #66e, stop: 1 #bbf); +background: qlineargradient(x1: 0, y1: 0.2, x2: 1, y2: 1, + stop: 0 #bbf, stop: 1 #55f); +border: 1px solid #777; +height: 10px; +border-radius: 4px; +} + +QSlider::add-page:horizontal { +background: #fff; +border: 1px solid #777; +height: 10px; +border-radius: 4px; +} + +QSlider::handle:horizontal { +background: qlineargradient(x1:0, y1:0, x2:1, y2:1, + stop:0 #eee, stop:1 #ccc); +border: 1px solid #777; +width: 13px; +margin-top: -2px; +margin-bottom: -2px; +border-radius: 4px; +} + +QSlider::handle:horizontal:hover { +background: qlineargradient(x1:0, y1:0, x2:1, y2:1, + stop:0 #fff, stop:1 #ddd); +border: 1px solid #444; +border-radius: 2px; +} + +QSlider::sub-page:horizontal:disabled { +background: #bbb; +border-color: #999; +} + +QSlider::add-page:horizontal:disabled { +background: #eee; +border-color: #999; +} + +QSlider::handle:horizontal:disabled { +background: #eee; +border: 1px solid #aaa; +border-radius: 4px; +} + +QPushButton { +background-color: rgb(175, 236, 255); +color: rgb(255, 0, 127); +} + + + + + + + + + + 0 + 0 + + + + + + + + + + Qt::Horizontal + + + + + + + font: 12pt "MS Shell Dlg 2"; + + + 10 + + + + + + + + + + + + + 0 + 0 + 691 + 26 + + + + + File + + + + + + + + + Save + + + + + + ImageView + QGraphicsView +
pyqtgraph
+
+
+ + +
diff --git a/xmidas/gui/layout/xanesFitStat.ui b/xmidas/gui/layout/xanesFitStat.ui new file mode 100644 index 0000000..258e475 --- /dev/null +++ b/xmidas/gui/layout/xanesFitStat.ui @@ -0,0 +1,47 @@ + + + MainWindow + + + + 0 + 0 + 792 + 481 + + + + MainWindow + + + + + + + + + + + + + + + 0 + 0 + 792 + 26 + + + + + + + + PlotWidget + QGraphicsView +
pyqtgraph
+
+
+ + +
diff --git a/xmidas/gui/layout/xrf_xanes_gui_3ID.ui b/xmidas/gui/layout/xrf_xanes_gui_3ID.ui new file mode 100644 index 0000000..18a9043 --- /dev/null +++ b/xmidas/gui/layout/xrf_xanes_gui_3ID.ui @@ -0,0 +1,756 @@ + + + Ajith + MainWindow + + + + 0 + 0 + 820 + 553 + + + + HXN_Wizard + + + font: 12pt "MS Shell Dlg 2"; + + + + + + + + + + 0 + 0 + + + + + + + + 20 + + + + + + + + 0 + 0 + + + + + + + C:\Matrix\Blue Pill\Morpheus.csv + + + + + + + + 0 + 0 + + + + + + + C:\Matrix\Blue Pill + + + + + + + 0 + + + 10 + + + + + + 0 + 0 + + + + Select Working Directory + + + + + + + + 0 + 0 + + + + Select Paramater File + + + + + + + + 0 + 0 + + + + Select XANES Reference File (xanes only) + + + + + + + + + + 0 + 0 + + + + + + + C:\Matrix\Blue Pill\TheChosenOne.json + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + background-color: rgb(255, 221, 98); + + + Open PyXRF GUI + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + font: 12pt "MS Shell Dlg 2"; + + + 1 + + + false + + + + XRF + + + + + + XRF Batch Processing + + + Qt::AlignCenter + + + + + + 150 + + + 150 + + + + + 92158 + + + 00000 + + + + + + + 92102 + + + 00000 + + + + + + + Last Scan ID: + + + + + + + Scalar Name: + + + + + + + First Scan ID: + + + + + + + sclr1_ch4 + + + Fe_K + + + + + + + background-color: rgb(85, 255, 127); + + + Start Batch Processing + + + + + + + + + + + + 150 + + + 150 + + + + + XRF Live Processing + + + Qt::AlignCenter + + + + + + + + background-color: rgb(0, 170, 255); +background-color: rgb(67, 246, 255); + + + Initiate Live + + + + + + + background-color: rgb(255, 130, 67); +font: 75 12pt "MS Shell Dlg 2"; + + + + Start + + + + + + + Live Processing is not ready + + + Qt::AlignCenter + + + + + + + + + + + + + + + XANES + + + + + + 50 + + + 50 + + + + + + + First Scan ID: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 92102 + + + 00000 + + + + + + + XANES Element + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Fe_K + + + Fe_K + + + + + + + Alignemnt Element + + + + + + + P_K + + + Pt_L + + + + + + + + + 50 + + + 0 + + + + + Last Scan ID: + + + + + + + 92158 + + + 00000 + + + + + + + Scalar Name + + + + + + + sclr1_ch4 + + + Fe_K + + + + + + + Save All Elem tiff Stacks + + + true + + + + + + + + 0 + 0 + + + + Subtract Pre-edge + + + + + + + + + + + Qt::Horizontal + + + + 49 + 20 + + + + + + + + Qt::Vertical + + + + 20 + 48 + + + + + + + + 20 + + + 20 + + + + + + 0 + 0 + + + + Fitting method + + + + + + + + 0 + 0 + + + + + nnls + + + + + admm + + + + + + + + false + + + + 0 + 0 + + + + Lambda for ADMM: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + false + + + + 0 + 0 + + + + Qt::StrongFocus + + + 5 + + + Lambda for ADMM + + + + + + + + 0 + 0 + + + + Energy Shift (eV) + + + + + + + + 0 + 0 + + + + Qt::StrongFocus + + + 0 + + + Lambda for ADMM + + + + + + + Work Flow + + + + + + + + 0 + 0 + + + + + load_and_process + + + + + process + + + + + build_xanes_map + + + + + + + + font: 12pt "MS Shell Dlg 2"; +background-color: rgb(170, 255, 255); + + + Go + + + + + + + background-color: rgb(255, 77, 46); +color: rgb(0, 0, 0); +font: 75 10pt "MS Shell Dlg 2"; + + + Close All Plots + + + + + + + + + Qt::Horizontal + + + + 49 + 20 + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Vertical + + + + 20 + 52 + + + + + + + + + + 0 + 0 + 820 + 25 + + + + + HELP + + + + + + + + + diff --git a/xmidas/gui/resources/images/animation.gif b/xmidas/gui/resources/images/animation.gif new file mode 100755 index 0000000000000000000000000000000000000000..b5261ca9dd2596268ffff8554552153335797bc7 GIT binary patch literal 94900 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 T9jF6jM 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 B4bA`n literal 0 HcmV?d00001 diff --git a/xmidas/gui/resources/images/animation_atom.gif b/xmidas/gui/resources/images/animation_atom.gif new file mode 100755 index 0000000000000000000000000000000000000000..b0f8c7004ef65a145e2566070c92504f9650e216 GIT binary patch literal 383024 zcmV({K+?ZQNk%w1Ve|p?0o6YM8X_eT78nf@6Jw2-aigjxIY+zY?J-JP#_#evLPaPt zH-P}Hc(;*3k*_MSwdiP ziM_-FVQZq!*hpr1JyBXJ zKTcJ5i%Mj2G)-Spb$d{2dOB8U3JwrUYI0S4giUdHMr3zwfP_(QfC2*p0RjR60RaF2 z0RR90A^!_bMO0HmK~P09E-(WD0000X`2+<606zdM00000^a1n%00#d+pKwSl8jr}N za>;BupU|juO08P2*sONT?Rvl9uy{-^o6qR9dd+UT-|)D6POsbV_`H74@B9CNfr5jC zg@%WSiHeJijgF6yk&=^?m6n&7nVOrNot~edp`xRtrKYE-sj922t*)=Iv9hzYwYImo zxw^Z&y}rM|!NSAD#m2|T$;!*j&Cbuz(bCh@)z;V8+1lIO-QM5e;o{@u<>u$;>FVod zJ?`)D@$l^Q!}9m|`1Sj?`Tqa%_z7eMu%N+t0~3Zi$dIAJhng7jm`Jgr#fk?ZYMfN? zqQ{RO4Q?E%2q4IlC^7yc$#T%YlstCGoJo@=%#|&3?(uiBrqBPMK2Q47Nz@Kck3f?u zo%wNS(Wh_neOyYFYDj%hv!;=1v8vaq7xQTyONJ{&uNTs)UCZ`@*Rc1<%KdWh;?lNw z^Qv76H{jgASMb?Qs<&|Aq+$S9G`_OxpQ8`DivcMeMIv_ z&Yn}_1!^%a>DNN!J+7%*ZHC(!YNw?f`W@`orhj_IO}sd9&%7tP{(V{YX4;XBOP`)Q za&jJinJ;$!d}eg&;H4YBo?ZJ~?lGb3rB0*0`}gjrkFVL=o%z4$eHNY$zrTMP;^`F> zMdjU>RXi05mzQz>HRzvlli5U|Wd=f(pL%T-*Ps9#cIf}10RI&ip-lDlP~m~_B#0qf z8p8MCi!k;F;cE0v=-Y`!UFh9{#PtW`k1xu29E}oUCmN19A=sTvJmTgekOBk{0F)fU zCnAv~+Grn=Nv61DlefM1qm*QpS!Rsy4cXR!MpDS7MoONxVp=V>2cwyI;u&O`xP4Y+ zn_IrQQJm@Rn4y#Iy_n~sdU|MOpKI0#sEL9OB$$dc;Z>)d9WqLS12@=k0}CW9`XQf? zvPIrS}QMvDl-S9Ofy44Z22) zs|_MFS|zHtMJg$=lp1@^tFRin*0PCqYNiOcN-O{E1l5}9D6pvtyDe7UmIJPW!H&PsBbA}Db3#0sQL=D_e`yq3lV%G?djnJVk>$Pkk$ zf(SM2{I3H~TO72ue{O8FHsF2?vaBNSd$ZFmgdnxLF+A<_lq&<+vRm^Oy)`ySe{FNq zQsz8^zh~=8ZPhA+cy-2-YCZQgbu+2-()^MMzz2Kx9c|ib2Tm~IS<8L+G-i3Nc*7Yy z9Ptb@m>{{XR9Ai`&@9KhTii!(ZcW$thP?l@*mws}0OT`laC)vitGzbsZVTr}zkD=_?{H|?&a zyp{8un#8~Y*Lg>GrtzA{BNjdFVNX_qEo}P|!2yy90{}R!oaQ{|7}rTU6&f^X)j_Bt zHMh`QaI>3`T%7+3Fi{vV;9UP01tEJA;w6}h)kAM5(F1tZSxBX&@D$M04;b~MF3hP;d1_T& zoHSfXi{yJ0;8hs3Ab0)@YfQ^(Qx?9{nro$MTX*qR!r+r!4Djj!B!Jh8>NR^zoq-OI zh*q3Rb*fI3;b3V|*eS+Qjsi%mSIc+Q$3Cq9q|>2UD;rhJ$&-zng+*r_D%3DZK(PgA z9G*1}9spBnlU>iDYYcXYpObf++(5C~pDgIJQOUl?1A_ByfL~ zR<$zmwcMTWD(Y+BNRptu0N`(b{fksAS`r3+g(`eaiQoh)_!L-0XOc`sK#x>67jZ=|h&nhjn z?iA!Q0hq|@Gjetf%;AxGc*&z^GHpX9f$|2xm=Du!m9dNg3~L!%2Hvic!HnaE zDkVB5ZUICkJmKgb0Lw6FFWZP`S*gmG&ZrQxa#_S<1}Gq(X(lbBS^(&N26x6w>~e8Q zis(;-Sj1n;5QP6Xg<>@?s**&8LB$4*=@)9cM4eW`1S9cjxGs7vBH*!}88l@es~FG? zymYI%oaC6@xFH28iK1_v7811J+3fkTuNkGx3kO=*N6vI|=IK*pdwb4)s5N*;jF$pD z`_a*swyDiT=@%!{(yY$5tL0qP!G8PRUpC6JwW^k9w?G8p*-(lXrGQkc+Q{;bbFu5) zR(v}=-*FH(RSH7`e^&=Q0$;b30AO&+#yjB!+q8}8`S6k(TiKNPOaXadrz7Al{ebPUC;Jwq4&0Qk%ot=R8mL%o=i)sGmG4 z`(CuUTLAxnNb#9s${V+*cy zH`5%>A%8j>*k1B&*c0wI`S#qi?!1=Ym(=HNEXVt9QDN8ovh~>t;iJwq^dSE8Je7JI zOfs9gt0mVhD8PQw9qGm@lcF#v0KzX%+{~9{^Mt3H=X(McxGR3`bT@sopDh8yU|jEc zN;>TOYW4zS9%gjGz4Wi{jINdbE5EFIL)1X}tO|eY0{D(})GcXPj@|F^roBi7kA>;G z1N0yf2{aCmee9zI*_wYl_SdrY&agi6cydJsmom*aT!E!fR)Bl(w}7EXeQxwd^%sG~ zRT=;CcYFG`e`)b-s^@>>hkRxt0cBEDj0vW)<_U2fiNf(_%{aK z=Y3vLaYL6H`~h~m#b!mubk0|T?3Wo)w}Li!9Vr125BMrD*o4~>cQXhEH3(`-fqGpx z932>Gc~WgJHedu+XlQq6NKk|f=!C4HeNGV!HS`q%5`#_gdtESvR0tG87k)aJg#c(K zNtbHwByWKyhC{$}3uuNBNP*ne4<0jarpht+LIDty|Q@f{fx>16lVTc)#1(7%y*k^795MJU3X#+-ZID zc!G(hkm`tcuGWxzagvYd1QIEUUcquLu#%sZk!He$FJ>*hq+RqThZ9MR3@I4~d5pE7 zlKfV5;lYSX!Gib(1v4p&RpD&4xR73_lVxIlSQcZIwPCLYj$VQi#aNW9_>%vjhg^h$ zli|^pT*i)na*z2xgghFX+NnvghaA&u8J4cr%yGUg4283YQj!py|Uj&(McwuX<# zS76iuna&84Fv4&aMoB)nYJd5Q1v!BtNr! za-8WPI0cr+c}kM`jwo1{^5_%vsAs~Lm1*WI8~Idz2$!FyoXhE$kJ%ZuX`g#ljqm8GOQq3u(acP^<2NG4G04 zx}jXEog)VdV0vFZIwlCWsBm_sNBNNM$EHhRZW&O2a#}^fsQ~|)iUFoVXr9`HW{IU} zCaT67AcERqIf|-dsa%kUiHw3Kulkmb`lxcLfV>A3<`#juie~F30h;;&Ym=vD%Avk_ zrJ*XSiV9VX+MM(jo$ug%VB&#QHhWr1tuUH>kQ$KLS`#H!qLzB1<+)qo+M-k1sC#Oq zl0mG+>LBY1B!HS}A320N>YC02QTkY~Kq#B|YLfRieJSx1x}yNxs;UF4k(%n4H+7xM zxtTO-tPiWGA=0SD#$?TUp%_bABESMRFaSO~0XKlBeb}xY>#;Jpru{k-08juVAb}?9 zqz0;~LQAgY+Oo{)mM}}ERR*zodOWrVVmBLV`AAw05JLa!!i~QwTr69v4*9X0N0vSz z0R>=>B}-x`s)w4&sV*9%>qxA|8hIJ3vC?{WhITMu8?Rr|KPM|)1T;0#<*L_Nv_>nd zRu{50K?1o2gHPL;dBOmi%8>`lw|7{hf6HfqtFhhKwH)@f6^ppxVz*G6H$ZeURFk&D z2CI#Dw3Ta`Gf@Dlr@45yxMi|l0XD7)8oBuDvTa$qrhB@m>yxA;u@Z!mn6RU;J4t17 z1E(_rqO`Fy!nU!xugE5jzH6B#x>d%cal50byOg?SDzV+Vyvz%@(E7Y8)`?VFB&V7Q z+;Oq#TRsY4wr9gG-P@5`Iv=@9x%`TF<%^_wiN62BOC|uOsi9=NtVXm!`m*!eyc)+S zVHIRwn7_(esD|n_iaSSU5(B?O0smIO7yPOSoWKfnhm%6WJ~zcCwjV8vS!kODpHvo??d2CKv(Y%u$K3H>X!x{5a>&^JEovn7N? z$NRnD8@}Qjk0+r!006fSJjS~v0@K4$y5vCUIkRhAx^3LSWdZ;Suyu6>dk4S(EkFWX zq`m4g05MQ`2E4@aWVo$c!u~5d!}~7-U<3aqfCGdyP?Du;Luas9EV^!}yAFqVA|QK^ zjFmU^#uz|Tq|-p(WTvoE=QUwrWYKzE;+_qdizHleE8DP20+|F+d1K%vJ7-hTc`XEMkpV&-g zWg@rxL}YgQ&7?EW9iRhLoGSz1m#(U9*fh&e3|EI`%VaVFx-tRrEYI`2PAl4G$;1Hn z{8yrzuV~rNR0k87o1C=O%#$op7X88KskR&3dJp|S&el?FR?*+g(quHdxZ<mTNEKSc!r&#}`JhzeSoLjueZ|4!A%+onc(51xyO+8HsJ=8?a zyhp7lO_S8H$CFs3Lro3V>eRSVT?15m&U$>+9I?(}N-jE!F1y0gD*yo?Fad*XLgq$Z z-8|N+rdU13SO}Z2i0QU8oDvPpyKk+lKb>pqL`Y_YRMGmQf11~(wzT`y*M9xifNjyd zBiK+~$ghmpH>cQ=kkyOm*!}f1EIA6Lss(407_NY>`mLj$tX+vXY}3I_AN^XFm&qOL!0CPx-tOp^VHHZ0EQjJ#Zxe{ zEDFYLHzM=cB5=_Q1OX>A0h)x#*d^Z>US8)W0{h(Iq}|0K{>b8ej~TSuB9KndzHXVgWGX<1I-{zC|qk0nVi6v2DcmtE4UU=D1B{a$Z{h z#7Qc==VatN(h@MiJ#YU8?xhit;EO}(7e!VMPU~os=8Ya)KpFsUI_Z;60(MxfH{InS zSrG!TU!1PhTW#Xa-@{>gO0twe&|qb1A#>BhWyGLyR^!#ffA4#PKbEBo6I}lnv!aZKJ8dK?%>=$@f{#j zux-B>9{}Wje&tS42QarmrdPGJ+|t6!D5Ne95bp&(@5`#ru3O9a?oYsuLR{1WEN}n{ za84BN=!h)e1FuC*i12K;w9YZogsJ4@omY7D0Ua>$8}RfSAOTW8^|d6_86Wa2b)Yc) z<{xjtZ>;W{Bmw{G;_kxE(So+9Rh`)M?(&EW^PI9j z>s->l?oX}V0S7?$6JG2@e%5(G1DLDqb8FK>3YAfZxq#p4qu)$<1OpCm_)ve(iof{& z4(|5*V37}O9~Gd)g5W)m&t9K9>A_ASrHNgk#TWzzm+&<^hH7QgcV&-#TS z0Ixsk3LpTMe(Cq703>kx*6!(JLrZyd0KO0P3=sVKKm3gk1OefYSOl~%N#&BMguxC4 zQIT4$im?A#tq9Qd0vr@E1=2CkCS!4pC~ymC@ytAPvEMH{y`I6Zd(cf@+f;H ze}N?-hlz`gdkQ3ugZp~*U@=+UinK@>Hn6dAwqZ!TCBVbQOHa$Kh(rnwn%J9QM$hBp z%d1OY#vINz)F@(#R5f9W<;xEwM+XrmRJc&kFiE|j(UCR{9RN_FW|Y!+stQ0>uI9uV zxFW`z|tK+Qna z0^`l8*%pKo_^zg%xL~JXN6YTIk9;YE0;X#cKRj~M$+Mo2vJwX@SBM~j6%`sI<^l;KWv|FeV-f&UK;Cnb(@rVukIHbo8MRbX=~dNU1-5jRlyv`M+-_Fc zV2~m=T?yVbtF1_o6@y@hm{3s=%`+C+Whurp#fSC~Nxw9UkRYnQ7Pj!(M6+F#(Qa1? zK!Hd}$RILuVG7{f9@16!l8v!*x5{|urPl-#TDaF=DsxMNYwUJ3Cee09uW{U@vBNYJ{y^oPVfg=BVybEVQ*BrcX z!%a>6XB}7=!FtB=bv&F;@|irWz8DM`H#0RiEcSxcBmv;@zyGu;(PWOupfD2L*xB%*i2M7s}pk{vq9JFF5CI3v&C<@qs z^mL#D2tdFA)-&MR^{)q~oo6VazGC%_APC45`Aah#sr~mJkc3AI;a2# zOizR(B;g57n8Kn&E*sc*q4#9S005{7YB=`43LKe)c zpxgLm_bAs5*N`t)5Vh(J3kHA#G;>Ba%p?$bgvCXAl&l}MpSN_XKT1C3q%Ejn?mk2; z-XSoiZ2={uL=Ycl6o5!5tEW9#xxqOCbp$LJVNr_;fdniTsV7|H&rH=+96Z%~2MAym zsCuTWZWf2R3cvwC3t9j;^s8VEt0y^HR*!--i5FbrB=?ep*|;^c(TuBUP1nh~R`U-T zsD%_@5*fbA?XRyDTu%p^Dy2dIv4~~tVn>jG6o^my?DH9t#lb0trj_xer)DEg@iC$^NnfdW7OsrHCy*hL^;hdZ-&(5LyjscEsrP zud#T0C-=Vhh-iIXH@%6Sa5mus`StF8skq5>{&!L^Nslge(6{>-*n&6Kp9UG6Tm_u) z0Yshfl^>7*7RUgxZcN;Dv-=mpbT>RKK4yv0oZyG5BeVs$s(RN;&0@^BtdE4`O>T^1 zlB$dyJ;s%p3)tTv_O7lm`CS7a=r<;BGp*;lr+=gj#{`66!WFQzrKdaL#E!7KCIGWj z|I(c?gV>N5Ep3`nZDRAW8MJPOXiE>6z!?9hj?Q(iF{AAOlKE1|r0no#ePReb! z!9CVp9axh+T&l@VW+E$F`8)?(Z?O`-^tCT7;Y~xJ)1U4@GDJOUm7=%BsW!K+%?B$6 zFdzyKEpe=cnA%!j)6TfgwVKt+ycXEE3BN8iON9+@lok6}vo571d@HUy&q4wA7AYAy z*F3@gbjl}WtP8N6aZQK7jolv5w~N*Va{l{|=QcTsHF30cGr-m54)3tVYVdj6`qm+R z_^$O*USI21#6cGFH0QS4jVd`933s3~N@DXdj`T&K@~OQne({WBd*dDVbOcIxlyHBT zn1DX@$-xd10IZzl!AA33VLa=ZtG55%4o7#shp<(CFM+nj?D=hf4)m1>T^Mz(+tK$R z0tv)ddHBvTPkY*6<(lxh3BdTJK`?b~bDYyA$hy|IK5}8%mcM6r>B+~w@&bgtba7^{ zyw^_enzz=qIL@H^!p{|R&i=Xu|CFs;jw}F* zOFtaV_>NDX7Owyg5b_dG0kbXo8t{6m5A(!rrM@oUF7OFmK?7H=WzNk5KM;asOaw=8 z_15nK-Y(ywL+wFnd}h0wNahAF)=t$ z>@rfVIsr6x=BExI0uE~(Ww9MC?YZPp5LZ$HgC%#6k|u%iCvX7=$?~Oa@)&ZG&M*U~ zp79GYF$}4337-GSAuABh{!uBLjZ>OZKa58N$gv|maw_#H0dPPhuQC?*&?F`AJY;McL^70AT4K58JDpwXUxvpFb7|2E?-0TW{(W*?)JuVFZmMB{^~EW zDljRDFbgxEM&N^H=_)CW9ZmAuSU@rZ5dy=F7qf4QAQBN}GZ-6VJ#r5i?{DacK{V&h z8I_Lx5E2DrZxff`06g&%(GW8uQk}NN6`JxV^@*Xr#Au#p1RNlG6mujQvoUG04=-&v z0TG4fkr0tnEL}_n{mP}DGZ$!*(5MsjtWzhIES2E!1UaTVo2dz|1~2b1?`o1S&l5d= zk_gsw4n6uODOw|=U}k@T*^E*G{I7$_^2RN+LOV23Ihg2K55Cy^l%R=AO#-a z0UW>`UDO3;U_W!wKN*T-0u(ko2^w^?AEmQL12PMNwAS8oNb?LrrRGT6;Vv!oGRZS3 zv(q#&C`w;%H?Y8+=ucQ|rKzeb{tRU+hNJ z#awVf1m=`Z>l7#N^g3I|#+Hsx^Lq&>4snbGI1)GMuoe_R9DpKHlhutVRl+WHv7Ge*p!M1&k6McpR6h(` zbw?DpwNX3)I&Cyu;bUCMRRpoKP}9}@h(G~ubqR{{qQ;X~gE743OGs`LUrXUXf(Ab2 zrDqbSpD48kB9ma9^#l+$`iM$l8)pz_)H3;N$RZYH_K^g(sS=8|B``K)HI@qt6&lA8 z1^Fjrl>ks%6BJ+bWIJ|0Dira|u~@Z3K(h2-0hZDt;AR=iSrgy^c9sDbmL3~6IpzN( zK#R6_Hggp2RwDC85}kJK2ux2OG@|ybzG|Zr{|v}{PS6grV^u-$gcUR#l>}gbY-M(4 zhbjbQKtCG~XBkUc;r3_M)M4X_X!lk#)Wb4P*Cr$JZ*#IB&$T%R7w(9_aBJghv)0sb z&t#>xYj-6y?kQ|l;~HZ2a(i>AsHbz4_j5UwXDM$5_|q#_1H?uZLsz#)Xdrbn;Cj}N^0rWS89dGg|4+0_pfCG4Zsy90Ck0oMrV)ZtGU#4jrcpx9RFMHR08({TFvmB_EPBl>N!WRfXBrc*jO|J7lM8DG^Mc$B!J&$<$~X8eL2hhR(4JL z7=){&Uy-$h`)PzsKy48@ksD7PxtQBb;C~7@G$@RJzipy+mbZL z_mj(44qwB*{^f|(Bmf8|mFIGmwZL{rK{eo$RH}HExs7uhj|J2=k#)I+AxnB=7*QSu z=-BXFWhNH_fO|6;CYbqk2`qLSR|iA66V{=c?RfsOxrrqzaxNMVkmN_m3 zRM=qCIfZrE>O9SzgBF{E`R7;{|9lTR@mZNCW1oGPH2v97Dd+37J>7$S4D)nb8;~(&2(Q znq_CAVETxW^O`++b2_I=Gcr_0BbEpGe$Q5Og}S1HT7@H^g}eVP0v;KP;Q3)om8qNh zQt;|}r8+*Sx{b{hE~D0Q_ZXZ`szHW{%)q*_<2P)#)zUJh%{3{FGqf7g`6BKrTA$wPQw)wKy$VI}d+Sq*jjb}H9;(-Kc zXT$$zLqPn=>A^cxBb;>FxUKB6ReZDid&{|e%U8T@n|rZfJixCDC1^aUt^2fKY%-YP zQ6!*@$+*yhT*!y~C9c}SFVVbj`vBC2$!B1(p&Z1$qgcaXG>E&h1D2w3HfOuM(H(uc z*H%BrJj0@U1Z<(s4rb__pY42}Xxp%*xg0TM!@UOswrI6>;X~$x+DL~(u;J^;65cyaC+(-Qm3ffSt23wR6XO zt_P$A&OD3{e5srLB_0KgqJ7k-o!YDY)QcReReh@^u3tjo+s(jT$9>Stz1+QFH^td( z?VE(M9H`qp-a$Uzf4yKEuh@Axx^Y0?G2O<~T+QVyK7Q+_242qf#^4v!&`=$S)Ag{o zz*iuCa`J(p3BBTpUNuldP%^%_bv*>|d(p#`%R@fuqrTDE_POxzNQ~S318~no$5P#v92E9wSM14)kE;{>to_kXlm?Dy6nyVPSO6_WjBJ6T%kokePAf= z9iWanU|)%zRaAdV!kJ!5*toI0-~bm;xYLvbt-r2_4?v|zcc^xIjwFN;01v_KOp)80syphbT~L{Br0y;G&(4d zL`qIlN-A7pW?r`7M0iG+go^4wl$M4>B&e=Fw4S`4G|0|s)M^ZHs95aosw@zc*w)U@ z!k)A~tR^^^hI+2xd?-jr2m%21;n~e)z+JGdA)Nsf6l9$BFsUb@w@a15$IH*t*V|{g zr-8S5$8l%asgnm!pFMyA2_i8A(IQ5T9^yDqNfX72nH+!;rBMedQ>9F>P^Jo*F=7pD zq423>w|zUrLAjuyfCP8x)-iD^mB_uS zRLp(iqiXv3;}(#{z=HpN4vMe_Kmv@05OJ)CyJCaIx)u*)+{n?R#}pz*x`JiW z7KN6ES1t%P%p|OusvLyCsq+A}0t$Zq$tGaioTB@XIuTG#z|^Nuo0OKSbv5hOuERLh zXB4cPe*goPEr?d_+7^o5%3bjZhTRdyk0Up}f#Y7j&LKod_7~X$!Nh8z;BeRgcLRq9 z*kb(3@v_JeoJD{JgPH^qOo0Z-!JaG-}sC_rLI>LEO!{MX-9uMt?Ffvs_cgjYMz zcELYm<<`e;YEh#=2M`7KNk$uta7l6>CdWcY&yg6Cbjnay5-l2_pbJag!Ps3(6of}i zV<$o;S$a6EM~xs$Ww!r^d_#2xhf$zqP)+~>GTG!52SOR8l=38a#DcWh1|dPZ9mE@Z z5@67XTpDf!5{PFe5CMtLMdsH?(*^d*bu7BbON@8QxDt(v$#SD~Gnl7CPCNGKlORk5 zB@_)r8Tr`}Lx`Xse@;?5;FOnQnyD658gV6958{>wmk0^+WqX{&^@(1lqynNcBQO(! zth3TuYX~x&m_V+&k|gJx+O34Au->f%6Q463)5>Fk4yqn|*8Jg~2=OV(=o?2Kp;Q4& zR@!Ylnt~f{rkwKNX+NOeu_Yf9mdc(b7`E%2aO{oCmLmVCPK81X2qZ%;TI99%9T9+j7kJxo6yky$GL+<+3kSLask<(zYq>iK zUZXfis|mX%kb(<0}CQiKv03+dsm=y&N_tT z^NA^17qA8@*(odniz8q(F9~a4Rrv&Ivr_`nwIR;P?E_A2jC8Y?l%Ju zLh%3Z4Ohiu1z_S7ixmxkV9aw~^YFwA6-X~x$*7)Wu%|uE$wvYT_+EW>kR%0M;8EqP zRQgJ2LNS!Bedlr=Szxy^w~;^-#!0{nX0^Nifgp!E+@b&W<^tjk@J-aIPT@|X0buRo zP7GwA19zdAVoa|*=5dAveH67sSxsXA0G}Jy&^>mH&`Bp8BN?}_J_V`pZ0~zr{MyzY zOVkcIcnbmlaLB_u=CA?+4B{$GL^yyMu}&6H;u0GOy{&5$QlpmD z7N!3|0Td+zm-q%4!ziFKf-;moIHQ%)7#2B%N)HlxA^qU!A>^n+2X)jN9%~5#7qEb4 z1I*QNm(va z)`o?mS|!`&_r|xy@i?on8Q*Mq#}|-?kH`Dh0S#9IU~)&8&O4+9I1oW)DYJqrn87o# z*g0|tK$9f+#x+HlO>J^BqUiIcSKNn6_>oh7?K)=+(>cRFx?pea)FCd1D9-}Yb58e6 z9E|j7NEq?LpL|MYBhSOkffiIq)#^;>w&f^?KGZ1^9qRcg3Qh-!(}m^SDD6Bt0#^U% zpq(SlAp|6-OTqQhml{}U5*O&w=fQLrGCd};09sQj;xv-m+vyx2fl!PAHK^YrDqY2f zj@7ZjqPJmVM%~!dSE@4sGni!srn*CTUe#w-4cdx^#?oMZ6|8ycr@|I_)|)z0tr%o$ zHQhi1NHFv$*pw?e>S|hXdGnjBTj3g8s7jSBm1P{YA1qfu$B;_ZupkIQ;7-cRKh8;c zkIiRf`ALA8(sY^WSpg&swbn`k1hhsXhc!hTSJIy0wAvllUD3E&)?Spau+^w+{|eYS z-WInaohsjIkXVtNV4g$-WGxnePXm0li54)HB9%o!o9?K&5rd|psO!0lC29XZoy4v? zw(H;nrM9AaO=TO+XYYi&7xLc zge44KExmTUZsaHlMz8^x<*rtCQw1aaW^0`3;Hrr>;GA-B-=Yz-7fJssEA^Q5uo=e? zx;GB(H8r*$P(yUo(l$d1zyDTd30>co$;h-S2uMOKD5>+G1;}NX#Hr@d`zA zOyK}nPDcmk##iq|lB*J{bb0UQ&PuxMWl7WfdOUjOC1|Ya4mOkrk$QH(+f4AAQ^DY+ zl=Ga!E8c8-i9HHn#F!>daZ_=z&9n5SeSu9a@kV16<#400)P-Qup0OUT6fLg&zc5 zT7%dsGn1ldG0SPo^hz-3&TPT}A2=^y|3I6SF~ z2M9^Q8=gkT$YDg$A;Lu;3n?HTG9V!o0v{fN5hkIju-YKh7VU`k~nWRL$<8s=dh=1E3E0c=2qOkAIFSO^eLRu$1$ z0whgPhe*7DPOiWhN+T#%qcy_iRA@^9gb-ayq!``h*yLq{^qkN2rC*8wm;`2RN@WWm zW^U@HVV2|ptmHkqBpr2}OqOL$mL+CpCW>rkCw3-JvQ~Rc!J~%kN^XsXL_n-F!gjPfZ09WFrY!Cs8sSx>^?XmW}}mO}C{!vyhdSw##!k?ENdfp~(Lte~(NUnu7d_>tit1-BDT9j&O0$fB zjIyN*hUVDCAW))#X(T~@6o3fe6_57l4gM&QPKkrM;wyINKujMWkN^fGsgjZ>3}|SF z`emY0A9`9Pdoaa&awQ@LCml&4N_pv}o@h)e!wQ(fm_9?9I%hyEo0`I56hOs+S{I$F zDmV5Ap62Np%xO}BSD*T+UlxF%4r-FtW(#nrqWY?As^^DhUS%|9e75AI(&w&V>av~y znEpismdRe7Iaf`egs9ZsTc~-Px(?x7KM?w5qE@*eSBlgC?M#erF5hYP)^_ z2An5){_4EWYkF4YJF-WW0^^nH&a5rsvQ~%Vi3GHEDiuxZj8$L66mT!yKO`yMJ%}5DaBUoYnbY}?kU{CW|5jBn1Jk{#%URntjSuf z)ha5Z>fw>KM*%oMq)KXVR_aOd=g$<64AhiO<-{aFjkPKYwkqt;szEju01XT+(E?y; z94*prE5>FlpVDfb^@0Ba;A+&a2gz#2)he#y0xMcjr8&{h-GOcR$qKp!5sSW;GTaN! zI>WS5>wpy>+}7yNf?l@*z}@2QIz-#vW<}rb+|q_q0y=F$+-lTTsK_Gj;x6UxqFSw@ zti(vEyRg7-ejB(&#-Vwfv!0a3rETZ#?3p5@nTh644y93$Knuhu>ZY!^svYa54jL%! z-_9zL&Tbzt00tCpyJCO>hU<>$l~s=hA{lvMiygmD*b7^dZ=u%$KA2;m3{;ZJe3S9Lzbqk z4hZl7L+{)6FrB_3xP}h)?ne>Ju{t1e65E68x*gBGCiy}!pmH$!s_(W~vB|!#7Bg}d z$FJa$z@gS17`F!upx(ZcF$7pH8YjSQ=}RfJvFEmJ8Aj8nswrG8!QDC}_L>78=P~y_ z0U!6VANQaIs}VV7Z~zc)Ascd%8fqe|>moPuFgx;6LUA>m;}^5+3|ulxhOH_1>q+fQ zw1zUV4bX=)nF8^g!2eBN;R%=rHKE zrCUyKMDK$LVDAc^GC1pTELZdxTr@@xsUWNK275FIlYp-;!Ch=EH?b3EwO~&T3=p;$N_Aq7#bP)1Z#(wJM)sdB zDsS+FnL=u$lIU&0q@`8|@DTLHfi^-{D=9CuDf=*MuQK+YE^AXSHof+ynDgsmByIQZ z=&?m^gLG3~v8ehsaKm>X!=?h*wm!>`dqlFSc&&2BS{(@x&GwKF)v$CQ^udmHB_(8O z%QaqibBvbsHp4PShj-46w`{wn7C-SIr}tAQAz}{%@4h!<|8+@YcpZ>HY;tuV=*Rz6 zUT?9EXmHMwdr=1qd>BnjCUUSf0Ut!-x;J*4_FPLqP@ATRJFs3m!Gw=eY+HCn%dU5( zngZZ9blp`@Tw${=;2CBZ+}(n^Yw+L>!6CS7a0nV0U~mcU?jAgN26vaB3GVKJBpm*; zch%l?s?OcISXb-ftJPn3zfS~Zt7)tE!5>hfJe#HEW7IEmtt1dCl8e9gQH%?*xemZW z3<_EhRJ|E@vkI{@7xmou*Lv@8Vxrfa#Q9tErtZ(RBv7VZo>yX2&CA7> zJGb~;XAP3>;Z~K)h3bFUp9nzr$!3DLY3KT8U0@r0ug{KXjc4TxnfA4O%jX1^Q2z#C z0KPrmE`Z%MBz<{gFK;UN%8QQwBu^{s^6;4Y?oq%|=q(d`XkTvJI=j`0ti)y@a>Ca6 z2nXx8`evl?i`R+gp+irRhL!4eHntqkpp5y?*K z1ZQ_XB77>SzUjCSMhdDI(rr(D_W4x)6y}JVxc7XR_-0oPp$2x=G_MIinT)~~&B0nW z9QW;G{WJ9-O|iy3tz3hC{d?9Vz}Ge)yqXu}*){xLXoT_U>qGtfxlTtykqSF?KtY@M zS5op8IGQJTVmN^PY_fVm6iDQ{oz*dQ^Ji5=!P=4&`RvcV&5xgi-Rx^mgge5NOn+$4Tbnl`<6fE{?$Qnt;(OAQ#guKNcqeA`)`DF_hyrrWv3X( zQKVS;c0Ji~WBML(&Ew~ZnE5wADkyL>hC(0wSJ+BOAKo2G6}YKJ*_o2gx`DO&Q`b34 z>}>0?!tmd(?@l40=Y7_IgB_t6&XGJy-$7l$)1mX)AKu6B?)=E!bq)Jp&kx;CU46R; zt$Sc}c(*SZ>gSm+BS(&0M079f!IyRab!)Ki+XgPMe%J91tZov+K85vDPy3wGrz)Dx z|AxtxYB?a9paF7q_{h1UoxL z9QY2riNAt&`CQz9&!%l+<4nkE7v+rNTG!*cuCc2*cYOa3g7t0nTtn1KPN3|_ku0sc zzkl9?(S}IlYxu5>e!Xd-Od?Mh3lI&t&SW%8mQ@CZ)cz?B z^$v}=+cxL7fx$%GF_yE?P!LSY7S}0cByjk02qZF<{HMGCQHO21=F9^AmWVp9)hxC`GSi* zmce6f;P6`$CZ5UHy}XdAe`Uce`Xy)F&pxiZP$q6QI5;IwGe9+4ER03x)-srm0p)5J zy@IsPgE$ZY&5doP(bljMv3JP{85vubE(2{YeZ!3Y?tIU2$c48j*ckJ^W==zuBevFb zxV@GUXFs?VwU)d9nu|qw2?waJnArABNZ685{92DkF9TxZxS6&rjh=PvzZ_HJdP-Wu z8ZoW*X!O|}N^8IQg~DM(&|+4)Z2`9kihyfHwe~$>(S9LFfwZEqOobtW2!UQ#Ujt_V z3+($pgX$XSwR0B^q)T9aCIj~!NLBo}q)0M&9*!&#LVbVZJoEwpQ>E0u&=j!;gGsDr zB!BwN_rj0`>R?;#_XylHfhMkK5l6AfW6N+%O8YZdo_7peppde4W$-nucMcW}uLJ^lE z{{`D6>3292ZsQ1@A<~SXNzApD`g@^z1dWD;xdo1HBXdM@{g#>J&YWD!?hlT84^*Vi zgE~J1gHK;4n?hvuxy6{-1>{~QTt88N&0v2&EN!j2kmT?ak4D__C7nwOhR}RxJBsk; z_r3no07k*Q`(){y1nXKKZb<8D*yV=y-k`Y&WQeXwg%`*AtEs^^gvWNfWZDemP%JgU zV^_lcUPGxrR?z(9f}TkfATc0DsC)BvMYIknl$C%0R@%6Avx4l3h5 z#G>Bk1i)|-UE9APimSLqj50pc@SXVTmewkSRftd(#dey%GfX#J8q?jfpDY#WCu;CT zE2hdOBJw(YfNdVm`+!hPOu&=LonUdmX<)xz|MlzCEi*Ls#hxwy-(H`*oy6x_ZBi4WxntWk^YtIe0#OD)bxieH7nDFRygck8q-l_NZ zEy-BxA?e(aKf}W4u>)?>j{T>6t=wz9NZyJggrHfucbxbIflRa(IMhSTOdC!T1w|vb zf+J*y1a=UHnGYyf-cm><^&ko;5Ji7ks%Vf)H4r@?Y!}&6x>?Vey|x7^yqA`PT*YMK z7BA6-3*)l6c~QD<Qs*0XtsLIes#L}vfU0k-0KxeZ4^Z$x|^qo$FbmzEPqiYdkeEzv2; zEdVz`eO)`px^@$)a76Etyv)b;>6Lg-oz~#_ z+GJ8*m+C$Gj@1kx4o;GmofOgtuuG)?z6b))2eO81^XRf*uK6@tw;Gh;Der5$4g}bj zCtFIJL0Hzz_@zF&?^iikXvjWDx}v_PO)%30pyY{N$Q7ebwP*2vWswD&mlh&hMfCR=Xw+U>I{vBqtvk5ylH_eag0AVXNY_{Q zrh1ZmrGiOI&PoE8R^-&oZ49LTr?}iTZkILGVTe~4>gt+O19Bf-_=27a#8f}DAzNL! zCWnFx;-u}3l{D_cBfyqny}-aulb$5%#F*IHg+s=jzgWJ}Ox1dD;UUefSc10%iQ_Sw; zum;^(GAJSZ8zP9DOukTR@(;sAEk-rF{hh5Spu`LTBykOPE`WCMctRxCEPLYTN0+L! zyo+x%A*7zDEdi|fYaD$aPfJX_I- z`uJ3^VBJ@0;j#Xf`{m*1(%P^f;W|=v`0SU!TX1u_ln5!|7?ABi2+5o#69QKV)}g0u z{iu{^jMng{8!8ZiuDnapoKC?&?z;NNMzE7b>F>_RTxJ^+(Sr{|{&^q(7p?9hrh1zl z#jT^i*`YKo=}0u;^&7euE}(+m^DIt8X9D=d6yiW(>jM*l^WG>vZIy-Or{31*h)dhEitguUE zG1A`H@w0yb9-SaS=OwOKB!IBlkHaTLDPO9C^F@I#x*Oq9)CQe(CI*j*69P6A zVHK1$&CR~o*u&S0x*y@DVFG;@>b}=5vcjx~a`S1&qwWcPaLbv4^X)~>fjLp9-Vm>+ z&DItGNaQ1%{B!MP8~qsbTGeG_9)I5IUCwcz`#tvA?|INiiaFy8VPuAe3+LywWUj>q zi6w?O1bnNqBH!m>&7&eG)%8?j%mjoyhZ};A@C%E^yHe&+K;N$sCN47xKh&OpA;v4f zUIPe3YpNUmHefic=TCHCjjtV<8|K1&SFz-Um-2+T|`jymw~vSUC&Pg!oyHt<9x+&C#15! z=d{1evA67*l}0fMdgYj_qy={W`G~(L}3gM1G@r1G;cS1G_yH`Vnu>MFK zp;o!u2M@eleJ8mT0fM`R6pPHMf`ys7z+IqS#}0@m9LcKdAXNOwLpX7b&nmkNeL-Sq zxrbr|e=Rz63QrQ1N|H>l_olONQdl^6_Uu#zFp05k0}Fsl?H*AS!1V2-UxO&>{}Joa(LwhAf)^YHaw zkwK;D7;opBQ+=fETqQOAP`@=v)2jn;NBX_iq;zsV__Kq=8c8r#T1mZJ z_@%iYSSd^1{7&5STW4sJ@$MjoUAL*x5bZ~J2+xoYloOH>A?6Rq`YWG9%GeL*)=+LhX7Eng?lzrNf*c7Pp6JR8}2laGB=%d28|48=Xz{fu_ zSM>@Cov*8-Om=*o1kL!mqVlDG=#pXwTiPYPo8KA5$^d>tKaR5jRir<|WW1?{WUcyg z*A<~w624vO1-D>CGayn1@Fy;?XaK6hD-zyJ6Y){0JXWD1b{NpsR#^gd;+0x{A(8LF z1tJ1Q?d-aVjp~1deos0L)-3+s&Z_*!9~UrNi#gKzkqize>-?sjM(WrnTcZ5f2kKnU zr$bdjvEy@W3dVVaDwC=xv#Hn%tCXpzxcZEx#*Y1LR&dQx>GtcedK{TR$8*4Lo`MZ7 z`%}Ha{gTbol7zy0xY|n%VhLB66d7y9oEiTTsydSdC9PKN=!)(4mm5M;f*`*mqf+XN zmD|Y~+EqcXZt5O%zySEDXoy11U^E1Lq2tX{2?J9V^J>dY{jwv_l;kgd(e2lwld1~u zUHeK}@rTl$TEt?ef0MH^c;<5TPUF=m;N(CNtv1b6XgW>AW%dDY!sgrH!I@5IP* z^J^oPM~!x7fRpvyg=(65BO&NA1@)G?&&P?IQ*dWraX`Q%KDpoxIzDc~^s0)4R4|Ze zkbRD}pC@M)g>GtezOQt*kNhtrYE2sJPqL61kZMv8n~7n_ab^_SKkkcS&s5fEKj-d| z{TLIylstE3HO116h6114C7bKiZsVXAoS_*KH=G?WApY75fPx`&XuXxOQ2S*%Hn6%> zjF!;i>|lU)y9Ge3R)E5e>D)~j6(4|utS#A{lQ0myMN>De-O8Sf+UlsS%{#834aFuX zn`ISqah!?9ZRDU2ztks#)KB_6YQNZ5s9SfMx~gfA1170NbY4Es?|jtJTMXGl=b`0! zkD~w-qX3W*b22yp8IqUWfKXsC1VT(_I+%LG7K^AgtU(r+xH7|Rtm`b?uxMT(e#VZs zp}^Ox-JTUnhtFDUMyT9aO;VtPV->6~sfQY-rD~a)Tl^=l<`64d$ejk5uRg8`Jedbf>av`ji^$3gk@#)RzqC*GZ{l9laF#HNCKcs!A=9 z$^3!t&femT8)DX+Qfi1>yA6FQIfu%UJ zbbYBG&J#RB0T|<-08Fko@*7S~_O1>t7jDY$WKYi37HS|sr3{Rd{0FDC7asMq*+9JV zpBKLGrDXo4EEgNQv*=&Eq;>qO$Tg_Aq*%GVw>s*iRgbYYPO-M<^utkm^mk9jIbczGmx}hpzx+Db6(rzmXE{uw9$VZ2uz*U^i-jYWe zeHGJ7R5sBaG! zY80pVft?*^N%ei?I?;&f-#ewfu&o!w&2~w`H4Jz0uf6FG(*BY~ZjzZ59AZTLWgc4LQ!{%+8OQUDp3o)*W4@jcVzrS&YimQ)-2{=JwGG3|>| zdsIkhiw16H5mnwkZ?vS&5xQm3zZfj>b)U2YGeIb^U?WO>F#e@tMZCiao?%tp@uZHW z)&54XWM|#Jd6t~L7&$^>JAUI&`=*yP&=7qJjLjy)<|I};>l;Vq!@wB9pPheqCoBcs z@S)?57;3eBzWzM>fjWCbx)4eR+ZiUuk@(P{aYt?Ry1sw56A+x3uoDQM0PFo&CFU91 z2RDIL_S! z&o|VZ_ud?HV@8I`p7KFJb_LF_D`}F|WOwqytyy$&R0k_CY}*WVhBz zx_GUhE|DTGm(E`^NhY2jFH>GBt8YqXaK%nzkGQJ6A#Ly?Y4KXy+kJ-l(3ig&*dzjg{dy4pYaAw9w1 zf=(Fmnx5rs1hMr94e52SE2kP-F5B4scWn+=EN*iOxId*LxgHm|zJOS|I&NO4d4S(v zN__LcdK=5~?OJU3`cMu`3i3oW-2r&7fJ;YT!ZpftSvU$d7g*JyGsWd zO5G;&I}gUcpCtd?*?NQR;BLx9w~=We+_u=}z}0nUvuPOwxA=!v=VY#*$1I)R0n^@} z%fCk--1BaURG2TytUggT@9Ry!k2UZ_QEMEUvV-*_MPHSZtc_c^u}<`{7ndyn}< zXE}3Eh2`$5U&LGvZ?olLkLa%(mwrH`>Tx*Hh~k}t9!K<7m$slQkqh5^BL9M~vP~~5 zMQ@+J%Z)zuLvSJ?Q!l4RM2ueE^{Wi%4v`0+YUKUufBMO}xEMdEIHCmXPk!nPa-n7( ztt5FY@dleu+uw1VF{C{|{b@}UILw;%@3y^jIyim+JWzP5LA_x;loBf|ja8`g?FxVQ#LdGLzU_K`Y}eF&uD+ zB+Z7-_Dv{FCXB%F#M6H~+n!>dMC{}*#v6_v*)xYgzFZDIHB9?z3P=HK$l1OK5*wQY zxvOien^{7SbW~218@_C62XpeKP=G?Xq0}dQR)a2m>s6sBv~u$RKo~|a(~>(DD2)1+L!;SKWNh+K4P~LCqoT^lo{^Os5o$&Z zskfz)Y_NREC&@gFt21c5ED-C65%Os3$f330PkK8lEns87RQ2%SplpGdKqByGamHfk zEyX*5P7){9F+rj2f9RrZeNzJw$lea%ylf+OfY~!z#*~A_5LZ`tFV$7!iYqClr(;*q z`GzB-7f!r*ck{N_;*N2tUN)I8yW0J0$}$&s|B@-uj2fPIdBg0Q)7EFcpK_=MkW7Ef zvf(^qtPn`P-IAH+9LYnaCxPzM88t%Ck3>MhM=$){4S~%&fL;h%*3A-(N0`_=mX~HY zG$7-!5shKS>yY}*A23z0*Wcc<2n)tl?KN-68{%{;P7b$~*EYQ(^?Uu0ke#s16haBI z8Cjy25O1q>9)^?0Vu}bJiKblT7ZXhYh-Y8vODmnj9 zHC5L7GupO%)U8h$AZjAPk`RGe8G#&R6ro>SEB?fg(>nTlt)^Kj#Ia>*PQNfeb)ml) z5JoDzkw8cOOj>OgcIQwsJtef&tYVDj(xqW@!c2RY(F+AX20Jpmt8EX@ZD-)guIo^f zs@BRo*JN?&$D~!bs9Uor27u7<&2%dJaXaO`Z6evYna`zzD_jCcI*qj za0>wRCnRV}vsmbc{ky=fjq$iDjZH{RYwojhle=0ow69Zs zEg8e7#pEytjL{G*fLwH>rc#QIyIbKt;dw&L#WpKL#q zl%{B|R$cNPSME%Td{=Xoe|)|1^ZA1m6^HiNIl62+{rS(e@_0h4CG6LyK_qgjm%g(C zG#+I1!*hN5Dzay@#Yh5G=Row2RJmP@4bLc3HhkE<|1b-n*BFXm^3wvO>ib~elezN= z*@tJE^0!D;u3?JRzaILyB!$SgL(rLIwnZbQ$yumiP{4-~a=mV}0Th2Wwjvy6Db8ga zrEo91-hWAMEEapN(G*q^$g;@rd@)R~bN?SW-;w1S?*;-l@$e8&3ZNijhEU<+BC^RSupa3G^$?;V(PK9;%YZFR3*r`Geb*qm-C?o~g%DQE%XbLUKTz;0;9^SdNf%Ke zVRVsQ60Z+jfK4jQ-$R5hLw)Q(0hCn`3rzsurbyf7Fl{re92O!KteV zq*DVTozXF~sp&8rm^s7RkSI`Lli#CjkBpuxRD);EC|-t&?ib_4$Hs(=uY5Lai66>l zu2c|!f^>kXs40)_dc@h-Vn*K&@}@=D8LKtrmur(HlUF@9wxbfDnsl(AjGiuR=&D%|gT_-7+l+tTD36)8{jr z4QYI)iVPxEIwg|?rr4?mCXYmkXuv_E8uP%(ie0Hpi;;5Y?>Tydg>XM?>-Qp&S~=01 zAkn{oVxH1o4gtKXnr{vc71K;X;( zAc~7XQR=Cx=nkRgixE0_Qv{_xuo_1_h7bC>)|F}Owl;4sSJng50AOM`P}C1FAC2#5 zn#j6)cs%%n<*ms8`iXufYEkZ+W)NuR%-L5NN{Wu3)fdO0_#stCyDTYhoc*HA;COv( zNf$hmBZ(wj06MWC>ReT|b?qcW9>6^H-1hqQylMLrV2IZ3r{lnb@tXSG_RzgJc^1%+ z4e(Uj?B2+=F>3eFj6l$bleg-4Fp3!V)OmwJ1+GXm1#2%zH=h89U0)S$$g(dXcOPEP z>f^*z%vPfL6K2@cFqm9J5xoIm=DZ7A5&!^EUB3j?$5!#Th~=i+-H>+cT!dG^(3^C; zW`<7^p|#nDWB{|?ey?jO9e<;x*4D9)X|t)__M5JlA>ek5;3zkM%?2g_q8wia&iOM> zg*n^c#KG6fb|jxM=8J_ia|Tg~-4@j{L-?F0i8hh5tfec}PbSb@zPQtUJEvRbXXok6 zjBzAd{M3zvQ4@$k{C=qFcVT{=SLqXz15UCq0I|LfO=Ue8!>4tMLHrO&eC&(LjrTmN zQB!UHUkRDc+YHvD2IQVUE69LOkRTL_Lau%q`tL<(WvuRJK{DEz=QpNd*Rq*KwGX!R_Elmj;AEyN$?G~})UUt?b=-@&^l18nrH+g6&@ z+NXzm&r61UXVb&l^BB2++(8Lj=qvxIPXdarRrA2b15kz7OH?TEJ6rSX@KI^TC)fX{Tjy*-<|BGd_>IR(7*DG!q_ z-K=@ategx~mK}~aD6zYevF3&bYCG3J+5Mf{mH*G!Q1g_z098;rl}9O zvr_80yAksnfBR`{<{~hyJ{YLJJYBr} zeUs2|u@L_K4`Q=^H9xahM9_?$o4J=)BV78bJ{1gA_bH z>|MdlKpBaP`3NOz3nZ|0W4a1PCl0Yl_o4IgYglxC^GKw9<%%8Q%P|s+D;Uf-5{gl3 zF4z`~*AgnG5Sqs2D4`G{Z|!C;55pKa`S>mprf3(UJQAe(sPIomPlG9}QqN0x3AV)L z2(AeGd7z|C9Lnm0*0U90sSv(y6|TgGtL^UokvQ1-H9j8bM$#7USrHiI5g~Dfde9r8 za2R2XjH4#O9!ea>>7ke!92r#+X&FhYg&P?{9OX%jmckT~;1d;^fvJ^*nadQ7)*n?Q z7+um9QAQkfUKCx+ggUqt-O%QXMjg{)7xOJLroAGjb0ntwFy=dQY%f!6ze4PwUF>jV z>}W;o_(<&JVeB+=+$>Yvyh7ZfUEGhzxRr{ywUM}u!?<6_@moysI|}i8cJT+1@xJ)r z|M4%_0Th5VU>ES!zkvV0{zcZUZ0*AT@-J8$jGKM`%fBG6$@_2r!u0R|_AgAuG~#3b z<6rnBID4hO`WIoDvgx`1@h=qer3)2ARcgv!{fpo#nL6!Ox#q@K|H8Pf=heS(>ac+i zjE?n;jKBI9?`sFV#m~QW#p7ouaUtQna-i>D#PF~*s z`Mch7RANNzV?HJxggjn|8*;jt7=l8pv^$r8G7v?~%OiQfH6a^E_1o*uRiXlfo zZ?W1&7SjVsamR!0chA-%k))did16_R=3vKV`0+r4Ew6s1;sgg7Hq0C zrKTY+Y17z=Kwz)~DKCZMT_^P8TA*|Bz=M(L6B%O&`R*GN0c-+{nGzOCN3-?AvEXPr zXea~7VEAX8f^!n+Jp{0+N{-|7okm-veGB&K>OfUc809amL^KmV-9*?F#gtQ~jfmH4i0ia9+i6G2`T`UF;`#t>pzg$xOa_0)Y2{IG) zOQ{<=^s;GEqBi|lc&{1#F|rc?@=S166fBB3){Qb(IXvtD$4;D@As_ZMJXoMiu7BvS zLyB`)l)y53m?tAjdQ_TWlQoaaHL(IK%?h`(#7Pl$aHvogP-4NOfeKSpbs77}RMuzd zkr41MRh`tO*FAu1yCAG=Rd7tl(+0%zL79d@8pph%DLK}&<^^3xCxsc4>a*5$j?7W1 zjqqyK*6kh~)Aqx%>X-A5#+>o<&P(^A=+3KqFo$2(ri60?l}$H{YCnsZW%V$MEMQ%UU`wPQ~hz=L<` z<9aN|kCb(7n6yUlS@;i~orVis&dgi^HWEheMlBgG`mi;ZgHu>;b1IwGPqRmih)!9M zN#y323R*-jvj%IyUP8&llO5C17#W=~0&bzb=?b@V+05*rcH(U1ykW++0w+BH;yQc} zi<^A&_)wG2@dfoz6`w0OLab53pS-nyt340%(gcRlgcasd*K4ccM;?lCMFo>y-XF+1 z`dep9&9kNhy;4Xh|6AoO`h9Sf36cNgMAa(&+wXja#6RSRL>gJfJyN~vkMAcqM|x&G z5Hdn|5eI;3U|cgv4C0%zeUx6P3cw7v?11u;IT)dT>lf}d<9Beq3o@QvFlhL-Q-zPt zRNb_Rb*KgDvS;-nCr2nsg7?u4090vJKsZ!5-#%1gqwuCALLwvzY4F|n|0%DNd>X;# zj4VgP?I7!PCmy6H#}VOP#w*=?h|uQaM&YE6HWf#P=tPwo`9}86@ghIen?~a0R7yM`Bp_L97 z=&#{wO|tDX+TmsnsEiF^!w~2+M3u}?fzp#j+K1aWiRqK>R-BKzIltyfRx`VIR9}fo6*xT~AS+P8665w*4m&hU41Dldb-pP1`NsVsjr) zlwS##r;zqHOR6}|F*wL38JXg8Miz}ZA{`^8NX3AhTi{$!r$6jXTsd{fGT2hbB<>*KMxJiF-SUF2G;fG< zOb)LYYl4smWSbzrIg~0D`ihM@_LJR*0A&W%B}kT5facN(?ynyai1U%0h3WAd`cx>C z;4KVMUJx6vhl`D;D;jF=Lvm>s{^^|xazCp1Kx9F!kCT--E~AAu`=^H3R6Y#+=|@b4 zo`!huiJdoi{b~aD4Mgs2yEG!KBXVkuN$C^23?jcr)#Dpe%2oDQ41bU5Pc^1}o7m&< z|2=Mo*_1J?vd@$Kd%{kwDeK3?zCh>iN!R$MoCB2u;kDmWK2uG34-*IC&%dXkn9T)9 zs)tf!PcxBf%|%3$hjJoMvkCFdC5);^N`_B!8B@(=8lJ1FokBx-fz2~7t?(_;`L_#k z@uX!!a#q@mqziQ%cUg%6u-%T1X(W=E8kflv`hGuJ3&7fq_WFs)ca`NhXRikSN&fHP zRzOS{o2>O;N8V+F`P`p3bwLRqsO<>z{>cour4G(JarzTAGE`@$ZrJ{-qYmZGu*=-Y z)u*e-uDi@#k%qgv@XiZ=`y}!}Si*iOuI&$RoOsLKxA6-gxW47~_&`Qn*Koj1=x6cB z4^X%?ea|YvD?%!PAv_i4s1+YmUPq1tcs&#(&7`4n^6!RmaPJwUQxJTi#UAo2 zvw)UXCvMr+pl=fi3(}7Tyt<+f*~o`_6-&NBbuABpVg=pDQ%ll2*!ts$6F)ginzTB- z9(8rRA<0=ex1l*tN8f0{^_-H0E4<4G5deSPLA+D$Wl?fY%DaWZn~N0I9^3`?Nm}h+ z=xv-*)=zkVU$l~iwR-vlrDI@}whd(VuQo(MuD72J@h&uwgSy0DZfRg5e`WQbt{*xf zH@v;iv7Yk(N?a9Y@ZznEG!kIQCEp^6 zz+X>=R}f@;DTgHe@s1Jf)GU>Y3|gy#cu&4mv+EgwAZeChcSF%*zgHv_clRpcK7{XGMfH|gva zQDv9x0U7V#BO|smh?$mJl7Iu=7X+9vBG#Gt8WJNaUm0EZ3dQl0vyXtGRz{4v;0FtI zo5qN&reK1%5UXXd`!b>ljsXb>9|@N*)`zEeUZrZ7VQ||Zc{%vFMR2JU5F80k(F-^6 z6l%F8;+KCby2pZgDUB!LUi*kBS%Ik15VI0u`l5!X4{!yQ3j&z21Bdx7$ZeeML4akL zhjX9KX&D%if&baconjDCVFyvW7~f~eAxYrvEVAH|Ak3V~&5lUO2s>VyFTMl^@wiRi zE|DOhC9t{;>>-Q2O3NC{i`=g7w^(YG$)xAr5BZtkjyxEDo{o6F^u@3&_7n-Grv55c zm?KBU%%}Qy@0m&5#A_;`HqS_lU?;U#v?ThWG~;t?RH%(U++5`Pn=Qk(k#&oG&^021 zpe+%PP%5*XIWt&1H9AN@eQRGOay!Eb!j4unboTkOg|C!l%rLq(uF_GoSRxBBB_AvJ?LpjUN7t_`<;(nWuV>`;MQk^oi zjRJ6d2d|x6D)nf1^e1i_-^wK2Wc<(yeTV~%E}}~~#_*zafs(aiFBdG@P9@9Mk=G)| z!20f{O5Lm)yqC-#W&66FCNsEHZ3C%^St@R#t69hSUu7c4Ynhn-|1A?gyfTTYWB z+A+4CDE~K;SpMVwznDaGALxHEiAH)+|CdR0k5Lu-50jXxE|&NoCehSTIo&u%rM&Q! zNz5-+Nb{NEuZ@vk7r&oEubOU^L=aHfXw)h2LJv;O*M{p0^94Ho zFw^mH87D@)yA*oOIYF1PTIE7TLEe|bh23;{8I5XA$bZEBqK$8<$)FTVYIwXJwVNUI z;)$=AS82an#*wFxY#`z{#Xw$!-@>h<2|pt-J!-tbv8ovl^is4$+> zQ8a|T)W_$p)qkvtvWu(XzY(Bb&hZ2(->jq*taTgl)UzA-6mAZ0jy=U?fw>dWGk6_! zi`p8ueDC|D-iV#QIh>YfL+d>)^>A1~1t#a6p;{@8RTeg4?ig^Mes2!_niR0+Xt2>8 zF{3|~)1JI5&4w1oYS?xsJ+OnyZsGgQom3l+b){CqYP9)d{w>WvX>*f--E?Ifb(wz- zhwmoxKh^Yn=U!Xg6UcMC52OBxwJRH8X!nmlW5igp`_nIPIb<_x{9ER?d9b0D;g^C? zs%?YYUgDax#SdT7np`Kl@_ck`OcmoX%Ga+)W=d-moMVx|W zp{!5?;7&STX6vCpOcrdmm->!0kv{bud1Qgh2WuG^m13GA#7xL!iRO#gKWHg3(gLLLhrGbS%%cO6x7%f#Fe&npQfxg0^?raHI(8^nr?K7gHTsPCM}CH;IiZ8p zq1;xAlgSD~v4T1m04)&}rzB?mYQ?0iJ_N@uVlPv_qN)%=g#c1fmk0(`stMV<@9)uD z){F=Q6M6f68nsOAh+l<$WiL@GO_=y+W7xRPL9JN}6Gn4L#f5YA;*~{9yuebcFtgcf z@hDc#@|)tp`{`lPL=Hg8kASeR6?HL=J!By>;_7cdd}5Irio{$m^+|C+(;Zn~dfx2@kFkMK-l>R& z;`by0JSNCuo?Xkkps^lh!Y+Hv!%h}dw=;xV1#m3+7aynI*>>UUd1{ju%<|v-)n9S+ z9CZbl61|43uK~)%8^n zpZfD*+&8bk&&3{;0Q8^LFCf4t7SoREBY$rjn z9x;yShO8o#sDeIDE4R=SgV~mfx58X3DzWseA*f#k!+1kpIOE=0(SkPg%Z}k!QI>+1 zC%b9#^|`Mraa}*=;Goby_BHVa>oi586?~Y~NrppG2tMR1;6wJU*x9C~_*HL3mBdTr zQ6UN1d;s7*Zei+7%r3e(e1HLhg<8(GXX*X{EYXOY1_w(3t%RD3+mFHp7fSPem=M*J zdQ;_yvv|LJP?%=owK{(e#w|QT+^($g`C^q%9|s?I)D25F_O;0FfVPN;p{4Hs(Guc@ zfh{?MSt!H`W0J71;(GXv zYp(&dSHWNr&PzHg*M=V*bOAJrrO#|tNXIshib0JntBuW;nH3Fx5HPU+D{7 z63SvYa8NS<@dPXIziGE~#5F%7os%9Zs9C&Z;B9Y%FKNQQjjLig9Z4|s`bBoDFURxj zAN~A1Km=7Bg+Y;GquR5+VIc|3$zGm>MWr=;PrZY{UU)XSt%1Fhe-+*G3x1u-3f4D{ zz{2p@qR>5Py6q2LEyV-MxBxqYX9O6oJ2PMKT-wlBhR9eJZhpA}q(5-}!Ks!5!)Y$%f+!`SV^yaBXn&%G_=creQ&l)r)v9_$9lV`4ZcL>Mio$G zp6K}jwMvLiXnev#xbut4R!nGl#V%V2&!k4s40EDFOOMZh(Qk<6@7&7 zf)&6sS)<$3v*rm&KdrAC=bo+#)h}Pg&LN)u@7D3_#Ygu!q{uMW=GI4nH9|3#^NScR zr7jj(q4UT=%iXvYRo2b`iM) zv83@u72-VZw-a>!*tQq!O5267fumUhELW#8jB7GyD@Uj;2YA#T{@84?^Wxwuq+q(k zO_;QonvOYckVGQ3qW}3)2_62!z{}Ye;1U>J_VCOzlPQdARdvr;_viTeXYA;= zf0w$}$)jua>`v*j(Ptq1KMX$AhPKQ zE8i3J_{|>l-Ih|`J)c6JHz59fk?Y{m^uICwS8Bm(HuQjcD#W*!2ns3hedcIP8hxeH z1DPU>3M{B!J1m%X&=c>^FKz;O=JG-JXl0E^50N|MubxvzYJq8N!W03)ziD3Iv`c$mt;yorW;d7Q3R@@$|lUXSSA|(2$A?Vh$T5$xE(>73xKx?c=Vy) zK}fnFioIb75U@>(ABpDkO>iz^MafK10VqAv3EuIlQuzk*N9oH@naC6*OBEzP%7Dvh zQYeqYU;gT|1#-u3G7%~J#)`v4IJMY8{HX>oe)?3Ycj|HiYt@L;BL=e=7tI z5dw!RDn_--50(4HWv1L5M4HXX(Axq9~0;{VZ*Oj1*MT z{C5r*mcjRd`5Slk@`vn{1HtuC`coRgE?;m@pU|G70=5^}Z!uo)AoUmp@iHno4mbBj znmMfA_w7S_q*IjDvrzo?R{jUvf@a>B2g`Q_p?WA)1uy%lTJTuY6(;V@EHBIa#;C&P zqck!HsW+%!I**d%E(Oed-t9$&KvKCGp8{ITi)4zyT|z)E(j+;QgvrIv3BK8++l5uk zU;uWA%%uRsqmrb7I`1gd$umbu0s-F@eDs<_HB<8UvE)lsbi8lS>S(?jinc5OAbtBf zg8}t6C@?!Vh>|ZGBaxIdE0d>^R;VvqTqs*aDWyLmZbeDo&CsHX2Cr)?Kk+3O+b80L zm%N`TSoaiHf@V6t%_VpucvLL@@;iEFeNZ9RIocq6i-oj38kFB%4}%4Dw&kGvJzZ~8fWHJr;rMbK&p~W zKsZ+dH!O>S>OX9!)YjcskVXbs;fvNFE^h-aNi zTHuciFt;I?mnxN_zM9^rcJ8pAQL!=B zyVtuGjl*Gu0jX*_eaq=twk)ZtB&rMrUs-E0o$72b&Qd5tX1yCiyvIhKt(dYn49pgO ztCDiLRAdv3Rab;wM@5XErmZ6p zHnmYgZ|T5fZM3JmwKt4J>Y+y1FLkLHc8-(&8wuieTI zG@MDIf)0Jw*)zG(6Vw(7dT#h_-kSDc&Ibd9YpJ%n+7tJn`SBCByUxuo!7$-#Wstqd zFXYWs>yu6e*1oB6STziF0s&~_bw9CQ0Bc=8(WEO`ln>u96rVHnVkZb+xBqCRPYN|q znJONa5LR*5#-g|LlEB>?DmX*j%V^esBMZ8(GlXX{h}ye{Q&8O@_MFA6{>u&IM-#UJun3s@Q%mU$jvtAbb6C}O1@ z;>0U6K`jIF8$A=i{ID6(!E?KWMy6>Vt^VEJbC{!`?3V1PfqmR)F7h>Da`X#cMFdVA zdxSxlJnYTCvAjuupKey#B=*(!p#o*tTZC~n5x4v&rw`Z*)Z5DOO9VO#2RDOwot8-) zw^IFKjmc9-8zQN$aT_9LHy55c7!0zy&WFiZ?5WW%Ca-IgRYW-ER%030alPFsRPM1I zn<+(ruLv~4;bhCsB-VG-X@^hrDhuUIpagx1f6RMEJ${BZAMJ4n=Fi2<@dowGz!vO^sb51BrKNgTn-IPdeU4B>l|S;^b*xPMKwmI_k5wFC;gNz z({Gz;OG3UaUXjqy4CZl_e(`hZ|Z7l(5JxgKT({`Pc+{Gt)-8F9hM1HwS0mf9a=R47cB`a@) z?S`LmpR?6!$Cfb_!$j#DsT$d)*V{%zz=k*Bdhbtb>WR&UZU;+|!O1No@_c2>k&anG zlk?5Si_W2qsSN}z^0ue-#i=D~q?vzo4T0L-0L{r4MuyP1UsNt#{#~G+i$#dbwCY{0 zbC+%X>}^>;oz-r?+O2j#(hfG!POS3o$4?xB6uMo%gUycY4RgcRfjbo-fFWT&U7|(5^IZc&}zt)KMG~@{klRN#2 zCx)(|Qbm?XJFEOX5`N}HYAe?@@j)^PGONsZ80eMgQM3}U?9(S{B8DD8M0&AYD3IJn z!T8$gQ<{HxD8qWuCOMRO1wF#NwGtj&`F=`^b0QNbu^*F_tbYd6F}yhKExp+`?!@RN z>5YTf-tjK8?<3hucq#FIIdsuSq!7J*26dhD>z~)Ilt_(4Z|nG9>0{(^k}(h?qPgY@ z?xaa4u=bC#;kD%TNmS+^N@TZz^GJ2lj2Q*^G2&8(iKLTpP{C$tBEnGA<~5|e)Ytx0 z-8w9CQGLF&W@Au|OeZ@U*qp?We->Aurj7QVf$BnT&yqN;ASz#X1Xdi=}T;gXt>q74J zX2FJYOj3Tx-G_RP^42sCggG~l@DKs9<*Xq=RBR^%t8`l>^|H~j*2bqM!F{5yjO3GXShej(aKDXC18YdM)0^Q{D5lPmBwLmqXa-6%%hEh zg|$fn#E8cLyYPuf$SA02=t|o#DX@|reMWsIW6pw(_OmvZ_m6_aC$1AL9{>6P-+?d) zu>jQ2jwsyV-Vh#!&rD)$e7+7oORh`qk6c#du%MCg>G|at#psSb$!Kk1JzqorNDFHq zR46SV+SMaFAo23g&D}$?XL?R8E90Ixw0ap?Q5)S$itJ`QfA)P|CYE0?7Cf>Om5%z* zf>11psAfN^GAuRi)T@M-vFd0jl_4}TowQUYIJ2yOu1Re=OI!y4t)4GJPMl=m9fOF_ zo@A-ULXj^k`q6%9fSDq!OAOaCvM{N^Dff25Wnwg4%O5O$ctGQqPlve)AJ1JYBS=k@ zeYDhxW3`z0=2Wf@?)Q&|!?59r>t$y^q+qT6IqvE}u$C#@J7yWyqL!u&wupzN4-P1y z)-re8?96x=@%#CYo>#edbg|btlr~Mo{|SwN($n;(O?9J5U=o{GXO?cGVtU?fT4ZvJ zrUV^scAk)xmZkNdormaGG%qTv_JHWRJdwODbZm0n4obKvp1v{Offy`yuH*{G;X;0M zrdbOavIrba)qPs2NywQ#7>L`6FqDRVKmR0$e|->O9-DrDJhM3aHrDz6Bc9hJxf3KV z_iOvC(2s(1%ieGcUc)cc+mKQ4S21nZU|4@dc67MVyz4MLLlm1dLR zM-2^7ku55t9A(f%9iPu+(sP03V+}WqOaX`k3_;j=UCs&&KHdupN`pX{6Mu( z9z#6rj3nb=)aHuXWQ@!SB{Ip*dvx*{N_=Bg*>;}1MaeRVrPc3PCU@a{H;ea+$T1Fv zKw*9xU=RwfwnHWQSU%_6TMDgQj3h6DvdCBL{NFGVX~hn+QrBQjeb{8d0DQM-S}YBU z55nE(bsA_tQIM@E=he85+9Em@_SnxD8VGaw)OpD3rGixtww%^&GHGpU15SmlmF(?` zpT=wf#RtokB&gMho8PnuxwWJg<^wTY61Ut1r1z&*&94`O1Mq+56B$EpuP1^7@=7sh zh3xgP8FU@nb%!QciaYVlX$(<+MA#;uyd2kef6stpK6I2hB#Em50!rotX@-*}_ShR! zv4&;LDwFHjQCMfTG7_#vnK$YBQdzy=h}4F510g&!js0XO6g;#7vl};-zbW|#?uF!5 zu9;P%`SvqY!*c6B4CE?zaSi*14Tp>t*ZJR;P&78k9rh<=+@(F4d4yJ4a{;mEKa{k{ zJr=d>w>#%)_>f%naPtHsY+3{5e~X>Rti!yG?#CKAzIPs|9FR$t#y+eWGMng|%Sca8@M*(oiun#5}0iNCI>Pb#YQ`R&S-} z?Fb<^5fC|B_#o;x%spH<82Ffg^LaFY6`-90F%Q~)gB0ahlDjTxKdJ=v!vMefk;Liw z+TPKns1#RPDtqY~hDo{)$!^yV8*$Rckzn-0m0R*?w;FB-BbOFq3`7!96RqT4h?Vm! z{Z*1IL47e@vcRuVX?pydXcU<20b2kA|0YcCd4nx}ZTu^oZEB@`_e5B@>$9B@Sf2pCmA6&w4)C?*&P)B$2<|J5NA#uoyVeF{ysMo& z7vo&c>v*LIN=F<{Sjey}#yq;`+}uy4I$Gx+<+ z95lpQ4112C^A0xZi;K>`dnYiEf=%ms$iAdRt_lLNK(rFsA=~}4mXDNdYu7}*mU-wb z^DqNnGh)z5A)Fu`KOzG+SzTbuCx?0*mb@lkq_)0bwLR<#5SoO`K>0bNdbc29T zFBDnZHQA9AsJ~V6=UHs7DH!F=OUn4>%)~uBkJ`SOW zsak#IE?Aatdx&8xvHp6SQOQEqTxTk1EoJkvx@X1d47qVGDdJ^AaCP78Px(Cx{mR8C zB(L=@-^RhWXmCAdNs^x4_IsJvR+W)R%l5I2yO{sR@sVS9X2SfDD?MGj`Yh((H?T`? z>NX%Zs8??d)T$V_$eheA^Y!xDaz+~qz@e^HAx4k*dGzv4a zJ@)i>kvm;Qg2Kfl(m5o_EN|zv4xW?kI+Z6*^4kpVD6|9b>kYmIKu&tkZIs+q|JGsQys^dp(wZ6j8v(lNn1Q>m{m6>xeUJTC7WAG3Wnz2` zK#P0AoPF*BK9`t?G8d`Cqrw9Kz|5%&>JQXW`dMC3ECkswN|J~Irie~l2oQP~TK)ho z;s}A*9t2ShnhChes{C74$i*t6@G0Jk4-qupJxBvUT3w@UBEpQwz!cBic-BFz6>te0 zsk5HIWS9V?0dV!CKSZYBn68FPW|r)rzv!FeC_(}4_LQ0&09|o#yI0Ud*CS@t-iLn> z)e3!Z0jLorf?0#G`^HjdvwK%{h$?mXk9Cwjh5%?ogH>f%;2f-EFYRV6YW5Yd5(UY_ zNQQP7Iz<_MOBs~|1R^?zV@Ad(9366!!zho#klTl@I);^;BchyL$sk44n9J3k1DV&F ztIxt-AH&ES!cjZIQW`RoI(#?&C}?uMY4UW0sT_m9mxkl&g~RlFbBI;WLEA*GFG040 zt%!$jsMi)bvSqF(xQv545~&psMZq!QE}8xwwR?*>hY+Dalv+-N#^ghG_K8;b*jF0fG_UFWN7$`e!NATKxyriet1fqPwD~eh0wgE zL`@**yB3P0pk1OTIi4XGEd)^e!KEnkU`kQOqtLg@!EDVzBh^CL83G9%0XBY601+U( z2t=6i?RIpw`|NYkJOjl?*~pm;{4qO~^YG=X)4fahBdEMi=)9MGnt2SG1<&{+Ygg;l ziH@a#F4wQ3Zj2SpImIsWsK)QZqKH|wmLVk%js=4wQ2xu$2KW|eW0Ax@S<5d9F&yTf zPA}FJ`2|iAI*$6@^yN}!&`6%*?6b{Xh3d^%R4DgGX<-@MYXLP+c*U|AkcC*D^pO4Y z#xWR@NTEW*mkA4in54`6o>ajxuUo&HW)VJW&)nTO-tSyigTarLK#_3LI-JkE;*1q5 zLa%kyuFjx;*eH~Ve3n2b@{*YQE++VIJj8Y?U0_6k}tyT`fcjHFaA#!wV!)YaEJ?l?xU}qSH>6rVL1|&^Mu9!e56I zSvE=7CY5>8w7M?VtDcP--b)>n?TJq`NmfdejZelc78o*07v{-SH_6~#$hcRIV z0cNPl7P=H<+Q0aq%0sZ+%k{bJjk}b6TG`kY=JqkSMw=A=+$!vSQCveC{1UBrd0){` zwT@XeATYU#{i*O(PXTHu*ZQeUF{rH2Pn9uY(Igjw}RPO)krX{sz~{FBqPZB`s$fd%~UiUrDw*d+&tE#Juq%zC}YnoeH^XeoTqy&0?N%y9<4Gs+#R&+K= z{t{5{QJWZ9SX@#Z6E72=HJO&2-&x*2*k1*&gZs_54==B-j)ZrGHx>Dxo-FVFyuQWW z+?^5ir7FSou>E_b(_I}QV{QMCOM%-r7FRK9>)J9oXm<84LH%HA=0s zjRKyhhp5BrU9!5pSxG1S)*GctNDMgUV~5MmkwUTg==Lh7UFpw27PFzOHQ4}vZla=3 zvhGf=DaKk)Q777yWKZA`Q;+G(zwkjxys6jFN0w_WG7^)$U2{W%KJ=0 za>wp~$bt-CXLBi>PuK+NL)#MVZ>TtcGDUhH4WcSk?~Ay$(_W-~l<8Ig1N>ed>gUA` z0LfS<(jP8Si)yw%ZGkKr{>lO2X3Zqe0@QAEvT-s+*vp zZNnDBGAXAIB9Vi5K|#J$j+ALGk}8DmD{snXDU_^!5XcJhv(#uh%u)xs#>-kp*-<`w zWa#4fH+_f%Jfi+cGQD*9sV$smmKf~RWVwln(|KkXn031)(Yn}VYo>?It;A@q7b_ z+#;fVfIwujqLRe+3|hx}?9RbLa1{M1N^6eQDMYu>i&YE?ro+=(ye$_Bd zRdeLK^@VvKpGqxkg=Bpt>I=2ET>}EjP1e8_vfSmclzXHjf+T7lJ36Ma14|EVCV`Q4 ztq}C>)aL}5%^Mfih`k4ZDcXxlkD?$x!HF1O->&TKN;569TvdQ7NC440AzUTjGzV^y zhe*L4L1df)O~d`DS5^8Zf)2=I1g(5SnPXpO{a0}_$?IluxAvn4!M;R7T>%70Gt0gm z*AJ|2TK#u>`7EO90yBV)t_=6ILGMM>ha$>i*E;zMet-Tn^s~O8Q_AN(EQ6Z5c#p*y z1zopE5`8}M*Oa6U`Ovdb;(<^SFiO3khHVV$og*7T~Ec}j=exaI=tVZ)m?r~f3k&I&WL)&|H!`Dc;Egx(7SvEFaqDx zX8j+RE}a_@@(y}1x~UMaVSh91qFlI%5N=gl!Uv%ZDz5~=fM?v%tF)jdpctVPXaix^ zNzrL7Ku&NF0Ak7j&`W5q?Qf)D7Ct2$-DfZ^^i-&5CRyXP1oKZi#L(xyNci*-5HT`D z7%Sxts<`$bS+Jsu^kF7Ox7_0YA|!dwR7G^5-w8`A*;;|tlq2tJ7XE! zbNGiz^zhdLoNXQu^rmc(ureW0dJ2v5-i?iSQ7U@VVUbusY!t5CA^ES>peEjVHRJ#j z%J|t{lu5LNbBK%E@>)n`=q_d1jg{)F~)3^6mx#lRx7$TrzN!1 zyM^K+D@!@q1jMu$>mrOWxM0+7^z*OWSak~+AJ1bDAv~Qesb|H5-$V@~D zND;&?np34+hTdR^7|#BMWn3N1^)i;?++&PU;?OUmmMBBbb1!tA6~jF3AG4vIfbv1Z z3FcENL(nHRE`p~km;8WJ)?QUtoU)K4bkM;>9K=i&vOVSEIRtGcH>gRB(JHN6W0=hr zA)tEEcSbocx}jpdA9&9?3csudJyY`t7fje5a+xD22vAERbD zBw2i)iKyM}fHt2k8;#?LWS$GGw&`p}(fd_|X4>ZZiX~fP$@y>RilR+xNFVTSf-QQ~ z4zL~HO~DF7V0|n*Q^XYod)&{F|E*3lMHJ^1#-NS-PB&fU``!`(2n|#l?+daYUl6^$ zt7&R!$!U`Q2wa&8Lu~2NBX$0poaatW(_58Hv6%l}D4!w?geUF8Mu4*8|J$)6pJq9{ zz;r%`NJwj?chY>Ukjj=yCql(1@({x62gly2AIa>D7n<#c8F7FGAjNI6L#|67Pq}1|A=TdI?f;ORzFw|7c0J|EkfdxFQbyj9=@P;7Y09#u=`b zk1(_qzvhz?VMWV>wB!ayiTi35d3lt`Aj_n+ut29{RF5R%LfqF6OZ zgM$}o&_lK@XnM${b3nrO(@jYUhK&0xI#X_$d2*cuKb3|SlM;{KhPr-drz!Km2?Pm3 zLc*X5#*Mn=uV|Ex@*@L)YLwsu4hWaDfan9qkAd58-4T%9s((@|Ijviy5~;gHuT<@* z_?Hnwy$2A0)C&v@@kl?g3zd~cPLwIyq=DWsqoqitmE9va zcfBSkydPIszYif7T0}`0MhJ@lgA+k36cCW=5^w`zC}}Y&yQ1kZ!IG>1^xjAUvDmMp z(Rpp4XIR(2(sE0qyZ}^4Ks!TLs4z^RRDX#J_SUN@yp}^Ta8@q*x5cnAF8dI7C3s z@|v$D{h^MEm`{mzjuMB3f?P{Pi&CoP zRD?;~eF`syX)#mGFQc4JOsXz5Sv__O4yu7Jv56NHg`4_2J#+ok=EpP09#i7&g!9TH z8&f37F(LRHluwVukGpwM6w03;zluUQrIcpzvRPdKAS)3kXF9Vyf0b+Xy|Q?q3Fqd5 z2m4AG?uueUQ9h~&=;D;~0E|0y3iXigg=)bmq@HnvmoW{eK$z@KGY(<`NE7UGc7me~ z47CZ%94KT9pp%vNLgG4H^5vBUF;F3A17ePw6%2Zr3Z7Dw0nVzPS*O~?-YyK7Nz%{D zx)jUBaPTlDeEDXw#VaPoCeq>#vuNKrqlRC&$M+@Wl^uC9^zk@<>?MI37O92rf`S21 z2F)}Eem))PG0~KOEcGek8AafIn;s+fjSY6n8CwU-lJfkn>3js0$(j}Lsf{lKS?lW5rK&r}QEusf6u{F3t`l#vQEIh@ zG!NvhIAFV?7M+CG9(vZ-i{{5jqub&q?Jh>i?pnSc86#Lh6T3o7CN`hz!t7=?Vw|1*r;$$dCE8UYrZ>db+fh#oWPoINs_ikw4G=(MQu-DfD_hfO(8JZ7(*j4Ld@E* z7+Y_6UNTPiYFk!r&)%rcm9x}5hmY9kfJ?FBh3?4z2V)@D8D`iiBEjfi*V%Or<0Y9p zm|yvwv}-^PMtj*H{iSAN17pYW+Q5HkkNbeZ;SQq=fzC0{xV_{h#CxZB{>hS3l!s zKl5upE8zgUz`z&X0WR+Wo~!}Bt^t9~0io9c5yC;Rz@WJ9prrSpbk?A3*P#67pyKPG zGU1S_z>vD`kf!&LcGi$i*N|=&EYao=EO5A;Z1}tUaJ%8KdDL)DFAh}IaMjsxqKJh9 zBCPn_urnd_5AP8lR+O{K5v=$Y*NYK#QmkCE9wYkE#LfUN_4+WIEy5Fyqh2I7@7@^0G946H3nB>3a z#o6@QRFryFz}eI;?amx^fpkwf&=7hYH*zig$sYbS{>7gD&N_1-IjhFn_&^8+y(N44 zQnh{5f~%*+&^IR|GAI5ep;0>HecdAXrtN)pq^BvW(IwLNK0VxXluiD7O^HcFR~v~f z$o@GbQ@!tWaa^rLXOpph#RY`!5TJ+og;a21fT2k>j?31pha7{ISZ`6$4N|k6B!3>d`_GBb4{zviD_`6;959>!Ne_hC2ZsNB3 z^;L_euB<6*gFH_zZ2SK5G1*xlodYCy9FT$(v;xn}AF+V7+TPe@{57Q0E!siOk@ge> z;Pxw$_Jjl-0OpxQ&@##f^uBU!tkbT7co8D&ey_#BThELNa?51v1r|Z(3C=6T*jKNs zPlfPEc}AMdb^eu)kKSanluFRlBCZNjZ~z`jH6s<-V!6x7k#w-AQ>`N<;@mkyk_)$O}?dCa77zC(^yY&sD4|Q=6)tUToG!Soi&U@bZ>qC@llwmnsh6 zray>Zj9wtRniX00(ibW*&bEMS;HKO@e5{{DqbR2Yy35A#@||seBktymhVB_{oSjHA z|18+$P~l&Js=pUp{rqLL4eC}0%OZDu$vIZK3RQljq#FZO-ihlF6J+zBoEMd!+|qBt zZMa{RzC71S(?I#^7l`PW_*kD3zAULVmS^Pno4v2)#Kh+@18sc1fW`Jc_<3dgY+H?y z#8FfOiv^nHnb-E2(yWAjH-_>OuO}BP*4yzPr))t53&j?EZum#+6m)wVh?8FkdTlAh z1$|k4<68Q42^DZaT*aJgs(5jJdpe?cu59Q!;Q{jCoL`f;Vj_m34upWg%jy&I!F*Y( zW7hUW4l$A@-}?Eblj$_^>H-7dGBEKEm{l;&Ly)T%2>Bj#;zL{g?(QyhJ(zOo4C6%= zkS9axwX{_TJst8Fa{jkI2pJ&I_6`Zz3!HrkILS$JIzPiYH4O-k%_!MaoxYUMJ1{l; zle*a27X<=diV#ymR5Y@uQh*NFX?b=6-O8>=Nc4nZ?rZu_ey(_bkmmu^?I2&$*Cyer zq9v=|7w=_BZ&YSL2k2k43_PzEZ?fyJmWDl{3~-Ize8@$BbcT?m03a7C1Y(>tI(>z# zlH9H5f?y$lg$2Z^{6(P`D53L|_54RpD3^kI<5JOOg2NSpRE||-F&T+R&o<#;`B{}m z3JlB4!jm0e^GW?mI49k?)jn9sz~|Ih8qN@!ss4p`h+q?k2At?#x&YShpZyM(iFTRT zl>f=0LU5qgcjP``SjLXfxLD}>2)R$u?LWq!>x3v|03}G z^`xidCd5=62WD?NxAKMEG!lMuStQp%(aZ2jh8!h-qNM)O}` zNOx$m5_Euwb?ww*NwvC!j`ujL$=I$0#IVZUeq(?)D0G7QYnlQOlU2( zJ3tFI90a($6lCm8g1Xu|AFcW;;4}J>QG;ubtCv8!tLRwAFCR^ zEEH@4sjP3x8&>Ih-ZT@xe~ewW(m2yC3<~|#(TK%)>;PzfQ!CUy)b}NOY}LC%T>?+u zshie`x)VKo(g0xFG){Zsm{pUUrmj^fI`xuLw0JQ)7xmcVrBeNPIiat|7teZJrb>^P zskLrv1K7hEwnxkD@hoE=$EBjDc<_FGupPVA%M5?flL3v`@tMUAtEcyQ%mn;qUiWxA zm5F65)&|@!+N?i&mcbXDL|otgG!zZb?}yWEHDB^^?=!MV+O^V5EXlf+9jG>v%q`B1oi>$%VEPrt`*pFPj>UN{T! zd?>BCr5D4yq0sA7xr4svy->N2%kSEyQ_kXaro;lw`+rz(gBNHc!N z(baAvs(1Y1S@e-XouOThXtx(@p?i33*7+; zD}16^5aH3+qL9KA+v9Y@-3*S(b`r}R26)HGBksf{4om1sv2D;XFUwHv$i0)MDk}}& zUU|Mc(RsAnS2=;3Q+kH-MEKb}Ga-n-vO?MH0TMiZAd7->KW6o>_l&e?$c9Q27G%g@{*$OWtH$lLFv0{b%X2vxn`=IovtG-l7;s!6vwL;&zLqyVT{ z{tqbJGMwa#w=*vYTmz_800Jg1ghgrH_R!y_5`ftimUIv@ZCEHQtYp9YMmv-m`}5~B zeZLuPR1hi&2mGtxnFw!}@=|;YEE}x~I@p_>=CyZFGtD;QTf1OtUJC+c0XPiC&`9ky zx&FDIjjz)S4)~@$h*`%P&Hqo=ruS)d>_MC)^)-+{+^9na&&F}&pZ`ABQJV%aH3!_f z?otEQgq7coWB}oss(8Axd`ES!fyj+?eFe2M-fjM+o)Pb(0QD} zgsTlje;QV2-xlg~I!OZ{D2;#`esU1wy#`c{Mgz%aTg9Q+CGVKNC4`b)JLQ0 zJfNtld?(cetmWUUjC+g1W7I#jcj+O`L>F z3Gj=M_JeRj1sk=iS%1S>_x>9~lF=Bq;Y2M%dr()?G!kSV%Ccythih%>+fWi0+0}6H zcr{$@{focS(-ecI-PNJ_IFSJuP5aBzriq|8P0IX8l{9M#!jm!U*jt|a2D4oa$>sBa zsbqD-1{eIME=u)sLDk~p(P+V~mOK8@u^zBg`#!mnlwK+|llI((>l)&^_)++9`geRz z|3|a6I=xrG)Ygqq-N-e9wR-Q-rb5VsUJsEl=zxD$3SN$&ujah*bgjEL=6T5@E>UP= z;r9kr*YT@>eu6zkD-Ya&1DeB~&(kZnTnP));Y4?_()4MnB2?*bIg6%LJxqLNn$=Ky z{Xgj0tu`OR|9c6%U18*zChv*lb9VP_y+I6OuVdJxEr6l^{Gkp{Ea-<+3&~x zsg8wU6MG>VmbpHHudI?Sj-y0OPcb3-X^?f@I>Hf!kH5wC&N^zw< ze;r!%6^6rVGs%He%n+F>g7AeEPTJ`)>SArQ!IaeJ(?vuk(@33=_@>(NNf{tdegyYL z%to=_hOs6ICejBl%d(a(C!4&Nsu6wop)+h>Q*m&|o1CVw&r6NWWBh~|Me6!)x_Q89{OfG!^mDX*qJuof0cJ4lej zp4-8AnmgWi1#99-+r#xg4}{jzjZvcW@`VQl<;nz;+i8~2g?fKr@)Edm2(1-iaHES3 zq(x?j;c{9%@n(^RHlje|<3lseRIf40$W0USm&t=g_SDNq zC;v-}7L{UEfff%Rf0ivn>LycC2Zkt9!|^DlO3iP`I6*CeChf2Nl>>iT2d?AO%}Le8 zKW~7rdfKpg|Lu8PBP=}&M8q`&3_!pG&TY$OiZY6PXES8zawkhVKY|peg(ir7=C9y; zA#lA7|8$cW&Q`bfK^q4Bsz5fX%BSjazcM>qEr-?(GN3 zCBJ)vgct^3E$2tpz0y)MF1a56Zt2S2hZd_NGW28?sU%W_(_#5lESBKX9ie4r^@oeZak5!BCCW06QK%0RR z15=(9j0UKcwVS;{{z-)J}Ty`&_k+8m^?50+K`3#^dU(CZWtW#aOa^B+X39$;J0e1Z{+ICQ3 zMf}JeSfGA+>h8XB_sH}i>w)A~t4FD6p7Wz&?;$@EwQeAIWPdNr-rXlsoF4Grls7im z02ZNWAf1p^OFV4nnjKaYp0Y1k*l!Qfv$Ri2CPx0SQWx1RtlahYZ&M&g3LKj`qyO{?KVIUG1*Rk70faVsj#GZeslUE6X%E2CL;=; zW(d8jYlhFQJy8#(>=CMNp1Ud&1ZiUpkBHmLCR*oD;vxbu4${Q1e*Q&EJre=cOM!`Y z@N=UVO_zuRz#(4;;1?M}AxoEw`J&Eg0~2yTX70@aj_GsS9(7s7dO&G0ooW(8kzxkh zQ^d@*j+=Bfo0BTKDmzbE+Cz-w)pI{}1k~vfv?bqe-C5q`4)Q3j{4A~S{g7_>^JTKl zkbOzC92_qK)#S;Q^tTn^C3V7NQ4i%Fhx=do{gi%=s~SUY93JgfP&2hB*GRTi8uzuY zlzUE8ur}|VBg(Cks-%<)8;W4)TCEJlXaJ)n&cCPQtwj(&{qyseisQhV*yzJk}s5TMb)m2v?;z7j_hr+Y_98OWD?d=$}e^f7JTc(oi2A zEYG|%*t}W63}MCb3^1>ho7>pu>a1G&uyYfZU~m_z}s^JQgz#d#b@w(&h#7 zp@OhNEF$>X?5_J}tQaY@QHu8b`&(u)Q(7F6#?M-7!y_{7eil8}z;4dXrngF!D(h^I zc(YM>me2;(U1qP12^L&NHroOUtgs}`-=lRc{c%HrXeRl~y zO<({9qZ}oxHY|3aLt?nRApwcUSFjyTg-O@`WB;nLu4eMqdPETAxh6^osY1$75Iq(P zS)k$YQIeRhN!_|+v&9h%|13D23WIk*4$$Z~Kwl0|0Yo~Tgr^u{{7$`#kQQy$ko(8$ z=<5{O99}(#X6@0DyU^c(ApL{nk01Hw{1;PH8T$9RqFF%z1W^Ng0dR6|oWao?7`1d; zx*|2oNRz`qvfix0^jZ1r2y+7k!E&soRp8KIAzE8O#7;E{EBE^b6?R&Tcnwm+1-Z*Q ztU492t`YBy{5)hPXV#hJB+e$D=BRW#Bn4}t}-!zBc*Xf6U%4-1WBHk3+wIiL3pE!W|hW1lR}W6{%N?c_E_ zLgAX)B&+p{&rClA1YA615F)CZL<_;(4OP+l#*HShKilumchD%eg?MbkA!S~(L?bz&VeCCILji@vuscB(wyTDsxkpM)|qII{+@fz z@NCTlzrT31Id^8)pmWQ#d)-&jvyMU|oP1bWqGunc+T()DKc}56z4gqc-!hQHSUL|4 z)G?aGO2jgsGMGHCKz-J)aQ0fmW7&qT_7|78j-;JOA8!QlK@w+8+z7rLOP)IE1J?#| zZ_Qe}q48&8h48@4ks+(^ zh&f|IQ7yt}8X%~PeH=0VaeIdDGO{;BNaTMTe^RD%bKxSS++AS2y;4x`N66-kNb(@4 zR!i~r>wViDyw6R{KF-X4QsDS0n$wZEVJ|!(M`(HF9OD}M`68!z3#cgSP%@i{`m2ec zbNl<(O8E^rAj7y5JeK+)J!?#+29CP37(+LPOQuY`V|4XSSN zGb_UlbSDeO4IOYp50@sm-VamlrI<4|&r9>=rVdvj^+$vac`5x#YUIHl78C|c=!X`u zd{0^;6>*&q`ax7mN>vgeOafFg*>uS1K~641YE(^b44V-XdB_I$XCf+T@xXLvAObFhRUc~<)(_9W@tkaT8_Zx@*LIr znQD6ItO`EfSh$=>B+$R}X?>bT_jG1n)aDh0>G;;s`b2Pbqp_!5&ay+A3C+85JZYezvmNBV~kt6^KpE)k`yLxt| zeLmMZZLI;l<2p?Iul%HLuNG;kR)hHd*aFMY4Dvi`%3F%TZlZC4d_}X+Y;dl!e(q5- zb018e97F_mF1w|cdXXW8KB8!P6vQL|rvgK{6Bja+m-4`oeURrJAdqWkpIdIhG;mvZ zIU%Bhledh-1YNZ+X4Hj$$s_-FDp3bSMWHNV-U}NO%$;B)naX3Tyk%Z%1#x)FPA@6X zN*BnR72qPn$DT68l~E8Gh6nj!!8j1OSS3_<^PEjEK!!@>0a6%>hFV1W`E=#DXF>9F z8UrJMrE)Vk1*KykiRm-`utB7YK*hYV zVOhbZj!~5Z2Gu^uYD%eY>fY?8qty>(1|j(hKDWe1@lyKZ=}RkNE)}U%>j{YYvbcYE z(&ItU%)hWiQgwO$a!L+GeowXLyAEHY*^NCj3Ke1HxoSE=CD~jkIc{kaTG5jVRcZU| zysh;LbM*rb?Cb9895U6P}>k?X2Z(x8qHhl*QE7R`(F!FH2Vw;Jq zdQ@0@%9iUem1|Z?LjdB!iMWQ{f`^9E;<|o3y2ub1#>y(fIp)H@98W!+W%bx02`yEQ z44e@?PeVNz+OV?fvbYfL9opVet=^7a0&k```ig3_Oi=&1F(4HN^$gHTYf_ZZ2{~<> zM5!;Y=c=3{@8o9k5bk5V6KBj9v6k-rJJN^c-_e=C-(}EEY}0>?0-!dlfJ$;0anG@T zw{FCy8Yop7m{#hUO&AcTF=rJXY`!x#qiN*@1BEMfK_9BeJQ_yNtiEj;`2ICjIsmv^ zGC3V)5erce8^g`KB!|5WrojMMg*iD{K-A!GETJmCl|#7|btCy8_lF_k6=O?l5DliR z{I!J`CTtOkfY1e(%hIsNyX31$1u@reFOc4}F{{uQR^{&+n8Pm0%7%d;C2a*( zK#NS&$6cg$I>%A6#L-Y{&H|hR z6FaIKM#l#VhGvwDSV*T@SY{Tt#-B$-9P>fEB{TP4gEX>?KUt=M%Z;>>vmx-7evz}Y z%QENRTAElUWZ{3f8iV4qq_OW{;d?b@Tz^E;3C74w?x5yk@z;~N(|o07tKw<1W)`6M zKKz@zYoF#JmZyIrTn65F^+zJu4kTsvh(*Z;rF@C_%^htD}$h zhYqPtfr6QESE>s=3&(|_51zywsj=oE41T6{k+S{Cp+boL0JO|XaJrL)>wti z5guuoRBlXt-IQnBfDzmpaG38}2eN`$dfobw=E@NtxpZg@aw(8gP+!%wr$@wJ&iJs3 zIMeG4D<#mR$FHIw+Btu9G82mC8h-iVeH#5dDI?dzTOwg-jLOnw$B$iZ4~G-)46;h@>b9>vJYp^hIoRXun|DxbR!DEMPxl zD{ZlRhe{o=m(|8O{e{qEr${Uk z($QMZM3y2)h3ifS1$@?$rlo_p^Q@#giw~#_`6ME{AUCcck1eTZy`~CAsK>H1R-tI6 z-CdF3NFkV+Ea$YM55(M0?X>eg_i*rN*}COEgI2tyao#VyeeqTZ&hnV}bwmn>RQ;=& z?c8J1(c`vBz^MF=DK9w~A;(fbgX$uB`%D+s*(Uj7xhCsJ17I2*b}8eRY5E1K^Uk~E zXTapk*cs?M`gv_1K?Z3ioC3@=c}M=~uf?^5t^|v+(;vbF{VHIH*6gK)_?47d2W#q; z8f$ZvudS6hjf(08kAHEV^Ow6?tC!zhD2;il;nzCP6M*|Gj!%Imn1_7!H`c0SM5bIH zEIO3UPL9#XL&Yy|(0z>cKq&#IN=>JPjU8hj0pg5*UPXVAvib|~>z}-V7*hVgW59{4 z=}HwRt4#b}tqUwnbvr<*(=@x(Ur*W=y@v|#+;X+A@2JCLvm+p1+^Io9W@4b&^9Kxj z8jBD0($omqr)RQrck4S3?qZ?{)2s9fj~5Y2$<>J4?GM2e@Ga)OKZTo1xSmqFVQOb!8bd{}1DMy;5`?+sU| zZC}1jF70nb?z>^cletJX3o4Z5pi{5cY_r^x<*3(aIv9;7obB{Z8O&Gd^kzF7b-L`0 zW(ntf`q=Ap^KKZ)aWNeT0V3dk$aOUzj=`eW{g&%yIhOKH8GOidx1P%3v|ag@=VAM! zSRw{rB;V71v09^Aw=dtzakbHWEL)_2ra-U_j$Ousgx{>(#`p1oM7zs+KOY8HEWo(? zpoG%RVPft>qsECboSx9V&kcsx!Q zc}!@gtge!$SBhSQNF=Hv2OP~hOD-$+$Va&m969^Vl8%iGfn~f6O5^+GSRS>lp)HT+ zU5icb-&t3KE>Mwn4P)-j?Qj*?guaSh3Qhxs&k-qK(xyXTMcroN5UL)R=uvS_9huX ztQLXRY4s!?=|fIm@*yQEQ*tfi)I3aybBcHqoE@60Zw49F!*fX&Hq@v-#y&}N8<((j z~((h#z> zg6?C_>myNg5cj*ShmbS&aYvxq~f44xA_P|E2F%T$bl8G zW>SB^8uP&W8v(>eA9Ks&jR6@bPm^Sg1RwwgOl5O;4;TT!A*Ygx3WeL(Jl9J|?k@*u~or~2< zNF);!8(FYDy_bVXTc-OD0)I$K2gFni^@w&$m~=WuF3OW%U-Af=*B%B*956g>S&}w% zt)d0&CJV5Zs{S*~hec(27yNm`$*fs2mRpy`PI{Ehj=+dG_jGt)wjpN4(-%Rry=JJE z+>1kCYq^H7$`xRoOK>4DaJu<(K)c$~P~|;jdV<=uOw{U+N!zNlop8mX9w_y*GHzqHYw#8xwYX=pJC$-Gb&IdS7ECv9o_aTe0$kbAu zxf>rAcbZvqRn(a|5MERyG%k_3`gx?fydrdxS_*l6T(nbux5p45%>fPPkiPFBk7Tg3 zk0-g#_C^`RIe1NUQBP&h=RHxSD#GMDj{pbCq{VX^0LK}{ScXDvJ%rrcHm+@{ZZy? zE-L=Q=LC9$20{dfzW6LljY{8NWBZh~cQcTN@FS+L&JV-N`lo2V?`oTTjfwiwGvZt) zcxlev2@ZAfh&Wec^vkmHjp^VhBC+sA|YL~=+Vj>FFNuaK}3yyF0pLOi>;nIPN zejn+P*NFs$EFs^0&j{Xi>`Tn`IzCmi&Hg%QN4g1qJt~+spOD1E_%pgzXv1yO#o8)O zph9Z~!!XrxDn^W}_M?;8O}GVUC*m0XV{k$|Wdj{2W^dr!_YzV_(B^83iQU$~TR39~ z2i6zHyr~1?HsB>pt{A7&!nWq-47?>Rmk|_pTCu{FZR^9HU+!$V~PA&}E)b+A)Q>E_7)?CPHecPN&@` zqjJ6<2c>HbMxR`%e2qI*RR+n?2mzkMy8sN>)tyhO4~1h!J0|MAsp+Y1_C1Ec5gg!h z>$N3!P=IIlC)IiJ6V*WsU}YZb5a>60C`X&wm&@^;o1+ zdSjyWqGdEqRihLAhcwiEvH3g1*cXg{rNu=aL`#xZ>=6wCbx)4-(O~!!7f0#c)7Y;M z;|Djc>`OE$%?!%_I-HQ%*q@M-mVcuRFxbGWLS<(WYwr@@S6)7aRbd3kpCG7TBfvv? z%$yNrLxV|EZ${WhtEg{(i|_lg@6b5y)P%tbtN-$60qjOwNVB1SJ4WHK1w~207(%Lb z)xE;)-gjMJtmY6Ol1i|v0V~pb$Y6wt6qtZH7NAy` z9K6ye>1f{u%uFXUly1xsQMDsF**!uw7#A0WsVmfXpJv4M5|1k)x7riS*{8Bb%ou=v zbQK~pSOqsJ2|13BuNkSv5j`aZ!{|E0;u-*pHL@S$hKvQf5Q$2kD#6r*6~=-1b#I?- z8tvy?9y(y#dj_#2k+8t*P`R;JHVvr)n(Fw41CPuMPj7NV)(MWd8uN$JFB%S5p0j-( zJLI|4TkK-$mnX=3x6 z(+{Uv9nBMmwY+x8p8PZ7bz1rNprM|-!u>=#@JXXwo(iQtV zLp?G;-66N%3GQ42Zrd=&yk?>{2EfFOvE2-S zEoXD)&g6VU5|k?U=0x|BPOuGV$Uf$lz(Jv@GgNLRUv^K(TwrZ2fp3TB!{Wrs3T2{B zCUVlEgQekTZ$$H&;||Km3f9tVF(WsKh%-~DzR*aZ0h~8n5>jNa6>tmpHg^+p;#Ots z*WqCQYti_u6{riBc0nhQ=iooYbd8KGn4l_noGw_d$;8;o^!1jjHI%N+o%!dPU~8-Q zkXaxk!(4t?Y^>E&`4}P#H52c31(2GFVDU(7bKes3uq(|(lTH;oxNGq!im__TLOf7- z?szJkBzM@wF)k2fL*ev8fiw_lj2N(wwI6;aUnRE>IFruOlOHZhw)VXp8l|64EwGnL zO>yQmgsgz4Et9t-a`cDqWkU2yOZF$us$HgghnXCd+a|I;;Ajca)Q&61Q`u-KL>W!i zgMoD8I%yIt=h4RFuoUHsEB=QA#q3nIFG|uDhdshoZ7`JH%$(q=RSLWumuus_yM#E= zipnyn;pU=RGss12F2nIh`Gzah6KP{V6lFzQ<4c=5_5??F8`7vpT#LsggR2bv{lz3i z^BhsjPs0h_9E4U?!n|^Zg@mT%TLV)7_kx zN84EJUgeqFqmBEcTDwH6j#1K?-wvK7ayDB3Jql_zN#+$3p{zMUwl_Jxg((;E8{R*L z2Z@khre6n@Jb~)nW|r*I>IgE%eG8xcJxrhP(P^?jE{6(eK3Fp|*d%##FPB(iJ(#)T zfA4Q)u55d4z%znQdrVu}A?cbRWZ4&FTON67EiTzoVA-wj3N+zc9+sJX!u{x!t>O&p z#C=cF>}3H99dx2@^DC6Jchim|KcTqmaCX5L*zK@ATrn+@(9w$)2`tsQSz$q5rp@%$ zl}a7dT7P~7Rt{xIXg zp>hZMpt0$FI?oVdmawyzAvNLijd-NC@bMfpa~78LOnSs{&vB!0v(W2sGJ5bK%Q2}u zrpqMQ;OX%5@^PEsGjGWDKQ6P+wbSU{^Ro7K!3zt(bNtkKkE{KtA3Nkt;WG)7KvhK- zz;8>C%oh~4>e>qQ;*|((twlY^As6y?t&a=5q^F(J3xORZ*44Addc;OtW2W&5qmE@D z@A6%Q?po95hL`hOGU+pO>63@GhJ76g6VAnq=GV7&k5uSV&Vw;xy>MR_8>vb>UTODn9|;|aM%AX!Et zRl~w^K;I?T*Sx4!^`AswcS%b3ZpzO`#>U>~s#=X{^+{G2Ujk@F9nAoxp%mcW7fkRPelvnD(rmM^vOnQBMAAS4uY%gYlW zlOGkH3Tsd(CY57@=TM5N>V?g^zRtMgSNzj}2S(nTtiyz?N=k&MI7QDfX|LGr(1tP! zo<(~8M4=j$xb$42Gy*xX^BG|+wuh>xgeb2}#3CXPFQ&5_ZY>tblm=k}`bh}kyxEsx z5v6#`0M}}os*)ItHt0?MmMQof^Zo_c&6c+^Ji8lGdK>n^Y#4;W*UU@TB&63QwAOeL zQ4|77wpXertkeiGs)bwLdK#)LHV9uU>dbri;WCtwL+OierN)?1!Sr8(1c=_CR$B6Z zzub&`M-KJh*ubzOXrMIz0+-Z4M68j-0br6jq?xH-EHVCR)(A)0H|@~MTB;QO)GDGi%s`^S=d5B@@-~ikrTs#p zPtua+-&A?Av*l)Sf^qtZ*XCpt)pA;ABPp zlSjHRrZ@-t71q`s#wHUD#{jKRyr9g(;}kLK(DvMbH<|WkU(e2bYf2 zkJWy2c_E(qCqA_oJ9W7__45>AR3XCHTaQN6* znh^lHHb$WXbRLf-bivDLZ#98}a5!FP(E56@wm;&M#YTfcU9O1aAA8&3JpzqqUf9~% zi(KMg5jDRovPw%!6_rXV{JbOW6jQ?xi@HiBNH;1X-LKIYHJaUqTJtJ#p+wfglg9rb zv$fjMFeX)wmSkPq6rYOwH*Ot-hzk~J7tfU~8SxHUV3yse-rgvRt~32M1$QS`b;KMw!M(`WpXYEZM0{~qAyXo0uYLXYPef@Qnbaqy;>Xe(__E6HE3DIbvPaj zN0@|2c!q$Eag%HdzaK4U&QdNAxwj5pr1;!R!z6c7hiCzDi#CG|4qfj)@r*vcl0UW; ze@m13JpN05Q73_ClPqWbFeec_B4-Cws|E;=<0OqA5%kY_h)$7(AH$OEGsX?;L*TjM z{x-~?q#R$-ecL1beN^;z`cL4j5pjPYbVHRaK(Y56+R%{$ecKA?_ZjcM_-Jg}0?xo# zbPlZZ4b8U^NGh5pTjlHf{akeLlZoNby1H!?x0eo8@Ny>HW_u*~0xd+>aO9SvQwO35 zGTXf&z=$HgUte}7C434p$PMWSfTPGx@%ayejSKsUBk&bq~`;zI0)n9G(= z9-^4KTYj1${49?B8oaDDIJ=?xL9OFHer|#o8zoh{3(vjZeRbGA3zT zPXi^(7Z}?e`Yc*ESUVFg-PlK!N9BbV6T^9XFWJiGp<-O!zF6FG3RYMb|6t*f(XsJ~ z$#tI(8BZCvla~LD6w!7!52{qnXRYtC^5Wn8V<3J8e=e)4YiManw-CX1wy>$9UDlkP z_wwfozm4rc#=s#Up%@SiquchIRos_#{N&EZkH#2BN8#ZU5E8-d9K*$DFr~Sus3yk$ zNN0XUloYeN`STab0!3EA*qP?95gIcZpR2?XZfqyh{%CXxNzXC{{WR<8Ss+b~+bTwc zDt7cj$B6bwI-MF{1;as{oF_@Km(w%S0alu#eA#rZ2R&yN4?FSeF-?uS=~U>CJhFuWHzTdFJ?VPfefZXA|0mX5~xN4o5TkF`f9_cpTC`i6-x~x?P_z2 z-0|x9I$WVJHh*!?)Wic8S1t!RIDU;j958*Be|lGvYMdwEp8IkiyQJbR7AZf+9~MLK zKV@wC@t$joYDb{Qbz7VcuR0KjCgsPSt@MZBgp>6iIc;>M7=0=ep13Z66iZRu8E(05 zf4`)nNP4>acBJ4hhr#}N^8Cm0*ZQsS&)ttyi(|tnYHxk%6=t!CRMZyYAcf$EKkelD=AgOY1(x;RLg~djfYdYm||&$kpcIgjMuqIHdl$RH0zL z($WO=F1w#`40ZbDf#7h0@?>F2&e9|?*;sDsL}6V4iX?F=B8p@=_#umQHTdp>5LtA@ z$}C33Q!88pll96ZgYb#U97{V>fGDSIgPPA4N zLUTW)O5;*vDNH8{1u=cxu(DO8;*Zn*z-4VM} zMq5gQ4b(l?JzV|>vrQc5L0O$Jw>H}+{CH3mml{k?Tz>Zl62E97@+S8{xzp*GqW0c& zKGzN}|CtgabkIK5Zd;7GEuyjO+`T>aGyGSLZBZ!Fo9iwnjJBP5lw6=sf$ztYG3aiL zuYf*DB*=kbB#NO*z%+>XB@s{ z8ciVo1K~kN>zCEC0HpjbD=eT@9xXN@_IyPEvMA^<*L9lV5aUu~!YV_F8~}?d#&I2y z?di@42xO6z*i5i`P>{>VB95!TxaKSHDcKmqys{#{e%D zxLaF|8VjzgNhEeVCJ1n+KCNRD0y1PoIK-b+7teCQq5={X&$49-iANLUo0-1kels|; ztBRWady3J)mk`!ae!C%)KS#v#KA^(yHIJiz12b2PF>s6^%w(TK(D()BpptDGAjO@O z)ln3K#vf<)ITw#8VFRSt7K2oFoo z2?0`(21YiT_9!{~MQ}RZ<~3r=j}$yPvZMz^8l|ZCiGvtD4reYRty z_3@fy_=mde*Ob2 z6)2fYhVw9z?VdR`Is}kJve$lEo$ygGKc~L#d0jL{sRna_oDJ%Ks_M%6>7;E_xMNt1 zX8P`2;x_N$jJXrd|AeDD83dGZEfPPFQf7;~KEk44Uvl~(YP%%`*!_U>F(IIB7bC{t zA%xZu+P1;pG1qahi$W=iGxu(Z-dcM6eR#HH_-;jf6g_zVu^)B*6Qivo^3{vg61k21 zuk?x#3|C@+m;mIpj(~@%4IH8X2E5nX!YQwR2ViOCWh`~}?_14=qYjl6WV;SgC<7wp zFwM802qXejQk~XFz^E@YQUc}*NYo{vh)G~cGWR674{c<~67b^X2TrjZhQ#n!UedHp zC2?k`)T<5vZk*dsO4`Pyhg@MYVo6^RWfNggG6`ilG@$^PGH&XBJ$J(R@M~>ffZ_ACS>Ts4>*?%1anaKx3vd{$1xJ{wq#3N=upUw4!+2~_U5cYN zF?iEfVgKeD5&I+))`l?>9jux{s%*ZrV4KF=k*@qZe26(^4#p6BFzs&f5F@N}a_`@Q z3-7l|>_k5hqw2iIH>+)$V*5e6|GDp=Rbf`YBrc32!{e9#AVf7I1Ve^l%c)8wl9 zn+cJ|B|ZcZr3If7)1 zgS4Q#-9I!+mq!d-&4#V*9Jh>U`DZt?MZmjaq0SLaL}zV`inUctKsxW_*1&oesp${R zPzy`_Qsq%pK~vW-${3b1nF4x;Ov$o_{fpRA)e0H=`d1$R`p%zhK=>h6=jaD)En9$O zH(9A8w%vCfnzoKFD`?V9kUjmQ&nXr1yHGYG4?)f8{;Bl6N;zgvVDwFYMEB3AFW5HB z+Yjgn-C40N^g>IN7Y{?rV&vXMc;nVsQ zyvbw9y$Qcs0-w4vT}M+AK16qUR}#OSe6?&xsYF8P78|F9SFE9eFfR&BNs0`aMQG>E zJ^&%bgxsX$uzA$N8PrCqHu-~?tBQ8iqiTrR1?QMYI^%ihO5CmICz|W@90DR-qCBqS zTy}DEYozJf3Mw`pecaX?Is59(O;8%=pNhq$bM{DX8Wmto)y?7AEE<{mtcv4g$ObCI zO-t?AZZd(A|FTJLyIQHcV2C`(LD&G)uffXA)|5`vb^<1HNV7SDy=gY4 zd92p49Xg5U3C(SOn_5j#ou;7Q+`IJbnwmV_!`DtKtD97iGM=8&lHWmz-P;$>N-i5M zYW6<@upT?&y6-L z!89N>G&6%SYjQ&;+bH0nT@5Aq)1bAXp5h<+D*2!qAhfAd9X@@o{3n$9^{>WSJ;t+zv7=uL z8zKLm=X@G}`?25fM_Yr5CW0Mee)wlfoM?{!)VO`@2;{}8{d>BKuqfxV+(~X%4S(Ai zq-YuPixaF%6|9;n{;C%YJ<`Jl`s!;n`Qd01H`)eV`2<}8kh2lARE~pWhv+bC%#3+; z_d5eUV%`zAU;;bmf5#tp2E$cGP;)hi-;Oa%(p`8wf|3yKtwZH;kMw~vlCg^+1|)&Y0pKgqX|vQZ*^h)0M5%H_ z;igj)Sy0i{L{zUvP{@UtFt|-4a56p_8c@OTyMjLAz^05uWB!S8c`|VokQc-bmi7(T zeTurqcNYi?br$!mBA`Q$4UgoBr2+^h5A))<%CaCb%V>tDjKgIh#_4fUUU9k^#QHO1 z+0F1cWuJunl!%0SQZb==@*CqMHu5qgoP;Eu#2!4@{W^yG>l03y0dBJkP4`Jqor|J5 ziF>kD48a4Gw@4_?@$!_LR#n7nYleM|Mfgjfu<-QBbTHzD!){wvAq*I;6COTrm_!8t zV2j5qU5g{HM2_A@o}R$nF4?(pfw0vD&Y#Fy1-RUSDf#2FcTXXkPw`Q=>RQV{60_Kk z<on ze3%)gJ0AMwDRztwB+m#My3Zc=V&E_nWqpoOHy~f($iSP3zt>ELb7h#i%~Hb5mb_N~ zJjBS_l)7a{ZP%?=PGD#vZg^U0q9hp8beoCUO)rs_BfMv`Rn5vDM}wTo@^ONN;{E8S z4y!Dl>my?ri!E2plg_T6F57LQ%wgQZYb;k;&}z*fZJCI^p3K3R^`|qcOD|&smpqq> zGn6r}oGV$G1Ng3mDfP@P9O81NQe%7aTh=X*yDq?$V%UlTa+v8fPXzv!Ps*zaTJc2- zLW~X_FD#TasAx-RUIKYZ!5sa`|C}MQyOukBP^1Yqc<1-#4)c||XxJDFtBx@X?F+N+ z@}RxGDb3;OFmT)>`tig1T3K-P#COHx`k5(f*+npL>2R!i9wlA&dEpimr`;Z~Rw#e$ z`0l${bE#ljZh^@MYDx@=JsuiH7NW%3Ak>oR3Bu5VuKfG+hD{;sG-{YFT@;5T*GP>?Zpj9Le`k|%9c*8N{%;lo~Tl6s>mW1CAzPIM%UJ& zB5|Vjgw|)~=+z|#=4ag+l-;kZ0U!Xe30}K#z_4e{p>JYqUNFrD$Rw*iEFb30PKxP} zwG>YQL#on;IOV&)QOSCBo<-f%83>B25$ljlNgTC43DU3@Qvd+Wg+Ms2dTtAxwG0AY z8zlvC4So(^LY`==E$T`$8tLv8g{%`>eZImV>(E(ia+ZKFDgiK4WhnWIovZF6`Aug+ zv_W;sySKnwP_rDz*Esp+O}}P3;$~1QXpct;#!;VgN}Hx8>Vl|Ey+)MroSFHBrC|ef zL)^M-*eoDNEOJ)#{8!D5OH}h7mJ*Y#vP?+?C5w+H#rOzF&j-4w+dw^r6g#tv@&0_IkSrb9yY` zjI@kk6R1IK>Pqr}Ud58muNjb_7m|kX4-IgGu!cI7MuYzXnhy&Gq*A5HUSRBMt&%ir|`6R3EkqReztu7kIWFdCeRdEFe`5 zbX85H4igv-lL1XCCGxupd6nlg8V~tIC(uuUP>n#34*kyU175}?FhbE#68&#lu`}VY zULLXSqZ6sd3P|Ikvoo>+c$^^k$cZm9(80-mOcnZ<81ZKj zuP^s*GU`eFhqu|{%Ln$I^(DO90v6cis`PN)wP9%5x5=sLX%lt%N!!d`J#HZ~B^PWt z@BO9LV+0A75pNa*!q*Obr8uYQn)I4?ePOJF9>Pn7IrtLv_-$#bx$OYwo#XM~UcGJ8llJZ|!|OidQU0I3 z60RAjj6vXtXJ@28BJAq5pDl!Up`j}kF)>gMCiE+jU6;0ny{d@(39N1B9U8ekT-$)b zh+Wd^-4BDi4K0M%@cV45C|#`k(a!tys!pltRxE7jG^*bF(Q$Vizx3w`%lGy<(0=9c zA#Q&CWpDONc6NGcoIB$Y;a2t_PMnw~**#9eLCqUM<@W*PI$3`OQ7ZW`UERg1`M?C7 z>Jk4)=hLbsI+_^0X_o7e{oA2fr)wGb$VC;2h2Nuw{+E~dvDYjj@haxW(&HZ5lOS~b zAGS6ftcZ~&C)T0C@pPVvpYgcX4pPZaMJacibWgKqv0=zF-lbXj{ihxPuhQQLH?(K! z?q@Zs$O*v+b^T|Yw`Wc02p>hsDn-wsjg;qIv*6DD^UrA~{p1%zq8B437o))!L@$?2E?0st*FIlv^j~i6T<*MG?vnrB7yW%;^7|^L+1jR0xxKeM(hGUe!H>3yuH6Z&aLn}`E+YlLP6a~ z!oPis9|E7{W_3Ptd;0s9Eyyh}-2)!u_Xkt6u?cQLu|HIoAoDfb@(M};V zax(?4YW_-c5xe|@oqi+p=r>#so6J{iR#3f@-$&*B-Ev}UyGDusaDT^BAlREeC1doT z1U8nYA3ZhS*sf5F?APRXT6ZOaSY99eLWVM?XFNlup4UK`d4I_|iB!#=DxiNi;c{v) ze)?B018v~{A%vZLVCxCd-ZS3%oHD}^WTn&i*Ssl^{@;Wk(t8hl@9TKi1ciNS>aK?C ziv#LQ#r^wjZbBnQVO+??7x@oUoQcMul(d#UoB zBPUN&_^(nWxgS)ox^YeEcWzsm86gL?jQxEnv0Z$-+jF5w=g*t(Q&~or7=1Onk)ZL& z+2kc$3>#vS(ydz>ddB~7H#Hdf}E(zsWiwmEoay4K0pT~{)2){I5<_@%8G~zNsCTLD8_Kn zKG&7X52|2Wm8!O#xNEGSS)KM-#0U|%Az`;lMVpdn*z?YjQ)}fcNwp*)=!z)jsWRnPa^;5y~gAzCU6bd3a0!eBfWuETb|C zwEu-QuA(Ox4hxD6nZdyQIc8Lbm~TCyA_c~A9n00lnx8D(s5O52hg?AQSe~mwlHXO! z&`JTgn}olcqYeciJDL3uq3n;pVp)nUVH-eO_nVPI%M;q?oKAn zP(q#`gGBUekT8nqvTN?NS!@?XOhHs^jEZO$D+q zl;9bbwq)L7b)0!-Pmjei6Xg$*y_er=5=LB3+A?Z@O*EmgEc7Sbf@MP$YDipYD!k~_ z1?ryj=F{&3&97UDmYP%h-#igr`EXhbv2J;&l(7H4wv=ch@WSZmj5_br@5iv;gCYTwEX3e352Xc48{WACUr&1px5yXWEXma$mdJA)80iO~eApsNf_d zbniJccIbx{22-Rc{Ucf$J{VJnU)PN?LQ(4JM)en^Q#q*twBIqg7xeQGk<-O177s(l{kkAdtaO$O2viMU}$jEmhRu#~JqpAsP*mh{M+c!QHY{%*# zYu}~2#5MSAXCpQx&7rTl>d@p*axEb`I@6M(&M2Xniu#!NU(J5N(Ejpn!h;0h2f9v< z$bQ&`7<>yP%~;&^Jni^cOgcT8vAp$ro^J0Ing0Vc%rQp2)84Zri{qQ7Aattg)^0_n z>*oFg5+uV~6QO|EW3#zY@^L%vqrYZF z3cLXaE^&egpMDtEz6{3hVl(>VV*0_5+O!N-h}HNFcNR@Sk|?L**^2Lygh zS>?$4dFAVL@h-gVhNv3m974s>4{*~ZuynCSXb6z-?6he2KMH71!8P5lv|$mSIdySf zqhqn&0G2s81^~FH<`S$}DytXxZdqBb#0qmfpn(J`9p*R*4Zs0+0lH^)R{e#;;tICw zeRX_Ve;jRN+D8mbNeWn_yO~G}!CLc!IxT4iTad%@Z+FiU?;_sWJQYmAHG>NViYYOAu+MopDk=ms>01 zXt0`gyCFIUIxLTlFQw?WQ*%E_0NpbIg;Zho=uh!m!Kq?DPFcz=b*QkWeMD`^|0I?3 z7!q-$u2zW-Hu$s?!{1FJH@jMa5xP!wb0BTQ?lR3zA8KTy_ZCYUaY$Fa5^CQ2P{Gsmx!n9OZrLo(XQ<`#u=C=j1Sh4oR1!o&KOQ;gX$gK9IWU^lHd za(zsApuj+hZO}r!hQx_1F?_W8FR;=p z{E-zK_BCtiwm8J_SC>DLMFNb6?5nxFlCFlVw5lYc&@LkXi#0{W+M4VO+)Ddqprbrw!-MsJ%=NRR~A zA_aoGySuwlu1O0)dFZ+7+E%k~a{uxlzvF6shz16ntV*v*RYUPon@QJ{r{dS7@fJUyaq}*6Ru?_k0cLY3l*= zTQE_fg0+5{z@j&lahkJ{FRP;jgu17nx^V+zp~sp5sU-hS zGN^z6Ze4Fppc78QvlWIJ?4k4%-!3TVZOdGusv2p9~0yWD|qsX&|vX%gjj;^6!)+pyq5sv{w zj{{oUC+ENkE@ZwPa<&l}<&0HX>Fh9e_-)S2b{L}#cY6`ZO1LeHa=mvPJA>iVsGn@T zGc5D$5dR1DK=8XhN^>**b^~jqe$~EE5*|S|MJBWuAQ0a$t*Z}j&dK--IIJZvNPhv-I(mUD~;X--Bu z^cXEHS1y!eRAe$7{WUiZ+yfA-0ePtZeh+~3q~dhGhh)KlglFTNcsw`SCZBOt{&`#z zEMU{1;`!sd6d)9n|>>^m18CbOJUxuev` zW(d6(Sza^QI*`N;LcMeeIeRB6pT?2R4V6v*H9C)>0j9DC9`o{g&+|~E(R0`y(p3R) z`EV&Y4qzi_45_*}e(7>IY4%5qU&rAVc$YNAmh>gt*iT6u*^4w;9Q0~Baux(>E3(Ya zG&H@7pdTfK?2CS*7c7mJSO%%6dSiqJNM0O*7J8#<4!Z~riDM2VKCvTCFyfH&mrEljeT(V8yOr3DJN=@sM&{t8nx2 z3Fz^RRP&h-@bfX=L7gB0&K$~m9jr7Q=d%LD)_nLiU*{@0Z5;1`1s-3au9clBF6Q5(6F?0WJ#Lei)vR4%Y}SF8NMwL}gd zaLk+FWO(W54a46Uud0(ZL)?ltKC)5UY z(P5#_3}5q7FlkeG^+gg_pW3kLVl7EY$K{#!R{FU80Y{$T7=(j^@C1*29oJQZ2=_GpM%3T2`n&-e~7-Yk_8^S5wuB%KW!{-f2U1SbXv9J!a27sZbhdtB!ap zBal| zR23EiTdWPgTgXcv{a~a3@=ccJQrfoakqe463W3q3;;Bg0wvvXV6o+TtF*Ap&DoP8I$16-67V zzoB?AiJiu$q~EuVvwLqK2@!bp7}oKQKieI(8VG&I?91jAtgU{+5TDcGL(xC22&bK6 z@LhPa>|`{=X^}GEwd9}a2sCib%WuT~0kuTZ6RzvnZp#L46D#_(z?GK{pio%|nx(rz zyer{!FyI9gOV6V=+T)U#Re*s2CwxN|?wJve;^RpFH`|%#jxc!TT=CW+O8VP{pO1*+G-;n(TKr@_WY96 zTvbAO;gogP5Y1|Pwfr%3TQzmtB>|3Fvl`H7q|WXdjP8&BVkL_IJ;pOBUC{|5jSc8z zrgSl?VZF2U%?YWmG!qhX%7MMfkVcP1yk)BPTe>s9CknSy3IF~ADh~^dmJW(TG$oD& zJ&}OukyT+OUUjhhm_^@6Ga>xU!^o!^hvko@ePP0V$BrmZ#AOu;~r} z1v(H0KChOt|YPh`Sx7G#ywq{FYS+emP%XB_jz)cT~C^OqWMHPt>Z`*fTtOw-tk3<5>M z#sNviD_WooVHZ2C+_*DMd>4(4bH7 zO|BcF5k-r1uRA@9#{AKU z!$Sk>m2N1WswMO+=Xk;S*|hPT@#W(moF?9U)ZjGXH2UND##8dN-UWKXO(zRa+CeyT z1)x=fuaU_tn~3ivW-GHm@NfA|96DOv^tRTDd_vDus+h{QOMD(3v-Z{r0bCw|<8T}U z=61(k^>9K3x6Sq?lg_xF&hv?mKt4@vy_Y$gcqJQMcH=^WOZqvzJ@uOsLxeruEaFw0 z{5q}bT8W+Q1txx9V7g6b7} z|GTi)zuBx~`M(Q$-HdF4Oe6mbfqWO^5cFRNWMYcWe-KCwmuz@RX_;lPM&YwcH($lM zys@ddu~N0RPO+oL(WK=+2xP8uky&@ATm#~H1aCF0RG=dMT-dv^EY+khUo({rBwuxt5 zrrBD7{s<4Mv({9mByt7&ml``-I+;O|RH)XTGCz^SJsI`VI7LY%Q`lRVJ^*`J5ShdC z4vH=3jnPggnsKD=_=S8rDIi+4Xah<ZBa7-w zxb+?yhZy!x1wQ8W4f;D!_12*G@%q=D{m7k>SZpqlk4BazgW+`k?53TcUNOY+IU6S4 z@(OlpGbFevzc`(xFVL$xQ(tp=H6OB*{Gqg~LnXvETHC4nrOfN`ZslZC zSu%!501*NKeA^)%neXtXx-?mF*d(DaHrkW!t&)e}Q4v~v(+?o`1!SZGod{SBfMicn zl(?%#*p`<2$yAl~Ln2_1Y}25hwcKrZh`LssG{(peZ?@_4h{^Lut1Hkb6f&wqp)A-^ zZBVv4QcI6;jJ6e4c{q9y^cS86wD$BxLOv-K{y1&5bY;W9#!2@K6&{kKzC#!Cv0byY zLcVizMeL-ryT%C)-X918Kxp>^&(OhP2t?0`rr1G|+)+F&(ai>1vySo(=6MA0Cio}r zF$zF#2=zsHQyUZ$;gOd+`FK3aZX|9wf-^YHRKcCf-GV{=?r#K`R=SrHU+UN9#YlpV zIk<^~NrS!%hx(IK3%4cWa!vwtF@$AolO!`|u7ue(se_Z0&))^B_xV^gEFP6Yo^W!D zYn~u2yJEtJ*EvUz1o*A#wHdC9zbP(q*tp;={5h`I8r+G&F`pzb=g%bWO4MiV%)cFh zNySv8j>!R@iCgUnn4|Ww?D;vz`9TQ(6FI(jUrDmhO;A45I+CM#yCLahhnonm2d@kS zNBpb;^$Aa?wVg$Mw_6?H*qN)x7OeQh)F%vBGt>Bs#wLu2yp&M8{IgiXsoHz(<<-zp zGbvjij<+&VB=H;7rzrv(q^&KFl}gtbb+uRfvW%8j>;|G1@}g|$Lp)66VFou?2p$e* zZ~&vnN<%C`@V8LkvTHJJl`cYx@AvXiXwl~pfM=5dQ$Q32pfM`LhI%R%hFJ39_NLC% z#;_NbB^XYzHGdoeIctMSNG?%T)(X%Z*J>#aJv@@8itu>_qWa!z#jaCC{7Y;aqfz$& zd%P?8CT`EZX5uEihu9%J;2)UF;s(ff?fzxlj)E*AFCz^SOCq2-6&#apFP&}I?|Bb; zS%*C_j7Di8JzY`6zt3ZWrr{Vfv2-XXyr~4+FNJA~T6HRKep zY`^i^!8OFamTX5q+hbd;YlSId!1;(AL|p^H zX!JK_&FQxY-v7JYYhTFy^|@L(N2TwFj=}|5Rgji?Xe62-wMR) z3OMrk8w}Le@YH$@RTGsz7|=L)*7cW%qs#^=m~ya}O4RQhz`#boKlwH&R3GD>ZF~VH z!h&^fo#z2+azp=!YTqX%nlm&-$%XQMOnr&~TLW~VYjDtY!X_^0!svtHN=jIP&YR8= z^-@KeG-E6dhy{1VUu;Vhp0#k0Xp>PzjbJ_ASDTu(jTN=o-@-9=k@iw-U?Nsu40Mlh zzxGWa+C_V#Xc4Bk=Cy;&o{b z>n}SytSXWjc~hZa%G~pxP5zzB-&#$b6KE0@9S2hzi|+a&{INB+BreI; z)^xgtT+ke3BD>wIV6~gRHiF?r{vez>dWs z8Ad}O=U5g_=XfNXtcl_6y@iDYz^#;m8^&#I94n@|kD?v&=L)m=G?kc~^s|HJ>iDmU zpC++I`-n;Dg+HFz_Hg6R1$vU=wSV>a>7a6@GXv6Rsd%76M+(x-oIB-AeiJDsPkc=~>5e9tX3GoA53*dX#JiLoW*T+fie=?sd#t}hmJa&iw zKFz*Zi1vL6q+WHDbBq^Tl{;j`?;nf zcZWt3FP*Pgf#Xr zn;wpop3zT#^Km35%yCbEF`Jzs5E*;Le7eD@rIc6p7}Q7W1+94V(@%?`%Kvr+Jd+Oc zqA+KvHMi`Uf~17Mohb-7Riz;O2Wzi~VL4H|op?NT;{!ygX;6CnmujA&+NmTUVXRYo z$dZ!FZ~3q_`#{`)Fl1g85oNP)?roSqw}a$P$oFPqRTyKD4&kwpbcwcq1E1vRp`DVY zz?wh!gRed@DaoOoAh|GV>JDjxOgNe{D)W6rdUiN8AW{<^*{@`Y_sNsHOK0;^=pQ=z z#zF)nme6{eaXF2O!6CADLUbc0O7S9c@r%WK8WI6x;#3%xE=G{PF`8j4l}zq?Wkw$j z%P93DDU~&U?eMT~fJmM2h$eqD9c5fpd|2WTSjr*x{7%)lD@?u%+}IJN4B(a3Rvw7~ zr#L`<+K1*<6MRDt7ODnE1Ym-UV|Oko6c)i%N73$|VzWJB?-(tE>7uKvqEazPB?5fm zIbM29s1D4rNE4;_tXqoiwAcz^A2i|EDUVnmVapcb1oTzv&QFAz%3{6u;5j_(PZ){4 zUR2s1aW>Y8CNxp~+wtbcF{-e*nIE_dxzv-HXs_|&=agcZhLg;+JvVb>ca9!t;SeI#h9!1nI=m86(a(kL|s)T zbjl@}9ZJ2~NyYt0hd)U~s6redOjOxLu7Q_if=(fF1g4Hly%L69>!fSKWA+x9U76GV z+~Y{DCvvQt9117z$CBkYlgSS^{i)2g`_J2&rF8fD?SxI=kt_IhsL5N&~V{u}@N@Y~dyhir|7eD9+qh1e{Q zIO>z?>?6OV36ifjM^$Wv?bg}y~rtjf?hm$R0M34p{Dq_xw=Py{{m~Z`)Fz|C4x0Ir zeAd9)$UtbmY5ZGJ1_C%!4lnnR5lg8LxbnHiY>K6;v|R1^8YD+u`2(81Y6K)`(pomg zlQ(>Hs1=vSg2m&9My0b_mjbl`{7VfprF=em;GP@M0DomAxkYu2`K)T<-}c705CQpc zPUc`vfHMo7LX)g@lY!mGeR6WVrKU|`sz_Z<9ld6lp0naSP#6!?Z(s=W0Nt84(NIJJ zvrQN{-M0 zP`vImGXMtyfPVoJ-Uc{`fsMUGj9O8k+kBn{HOYC63(*!Ucie7@C4}9jj^FTs|1Pu ziy*#P?rcb4nG0^bXKi_81wSLu8<E~4<1-5VR)~GBh>XVzGTQ6Q$Vwq z^EN@^$y9!TUWPrDiQ8qEPfmfByYsGVcs&@Q;n8_J4F`k+|M89(2g85GjC?_Z#c$UB zB^czE78uHqm=LR05C>c*jH;Q}13l88J#8!$Xtxyd3k1DoY9lEsLrdFZruMDd^y4

E3a!S(v=d7&wI`5ZpS*P|O|0WrK|qVPq;)hR8O(Kkhc!fkhWtB0?`$%`kcH;9@YkZTjdg1)|C;0t~aIlEBL-cr6oBWvjjTZ0b6g> znIl)w$ar_cTOWV`V?0+UFYxqaWlpw7iP_Eo_uS0iN}8$8Fs(#8cF6(^oBarbEy`p0 zLCq&`k((Ow06WiMh{%$@#Gc&x$07qyMf&$KPanmkJ^J)(UbE)Qr^TPFsb^l3HAP+Np3nwK$g6y=J`7LbBK$dx*`q5%4)6JsWh0I zGs{6pDi6?phCwMnGMRhwI0%VZ0T9zB|k@B_kv&$*-`8 z(ZPf0@cs8CS)df40a0~EZYm9;bZEGa-M=r-vlh$f!NbCV8q$$P?x?-PtsN1;m`_kx z-iioF-`Mp(1-Ps}<6&HGNnl)!?{q&H#R?UNe%t-5JjOFnR<26Eba#y2BR~ z<(p@M>$bqxXKTVvwZ4AkyPo_pm(JS0_!j)|6y(4Abxrx(vZ)Ry6R(8j?CoTqgC1oK zIB?TC?Pef^nXqGunXSSdN&E}Vs9?Jx6xK88BTKsNF8!kNquOZO4Fu5q!Zca+*6pEp zIuC^*D$=s&(NK3K*45$Kuuh1?NoCsg?DHifE;U(HgLw_RH#N#)yS;tuo=b6W1~2Ys zT<%XZ!VduenyY5&hHG^S^T=P}7E-#_3hJ>6xw+-bQ23 zTD>uK?Cci(Cf~hblm>Ud-nI_%SI+VLOT46}6JqP=3%Rz8W2KMZTrvgn*JCG0G521g zabtT4OWwx#q-t>c(-62z83 z#;pX&xH=I3cX9CTob9ccycG1AEtLyyv{MQ?7Hv5HXz!lJEW-q*_mBg!|w@4 zgolgOF@G$h!vbplrnNpR`@SU42nT7hO9yF4cJttJ`03VDQMmSzw*NlR{V}trWdJ~8s61{i+2h`u54C0 z?|D}CQRigcz1nVC&aGl(@1a-AKXeGB|lWA&UH!0MIu{QJ$|8X zqQ;w?@!-#6TLpgpoONV9-=fE&-t85{?YE56&-kl# z9#wf2iVL*d-5xaR(iLK8(4QzO%-H$5DrZ|2Wb`G-_ul=WZ!@T-0`oE->^|nyu4l5C zJ1(f-{%3&SeS@4NwTVbpa}KW}&3n;<+PAg@W*7Fp6~g>HNVO5JqC+}2Z@jqYkU~pc za({R2rPT7<;ubKjxh|hZ%BLdCba63KzF7TH|Ka<^PWR;(k0O5A%nYSy_&Y?FBLKXY z5GWX+0T6Gv&h8tp(|Z8yiuf3(C(e;GwS}L&C0jo8e;9S~!mvbCJ!|X#FzU^7|HG(1 zetXmxsU8!ZHgGd*_IvNQ5UsH2#H6U$IE@5tCp3F9KGy@MlY!3Ci^wZ4Pt{c|vIbSu z1l|kQBj}dsmescV*=saBuF}uZdD1c9hAYq}^k}r`v_%OFro3nzZr173?w@{Z9sByt ztTri-`d!k~!r`XoG3^Q4DIK9tiR&8ss4oWF8l+tfpqt9q$U85ID|mah3!kam(d0=s zh71_Q&;ts7hTL&+$AUPzw7!MHYrrQhGCUH!@FZnKgyx3&T92uoEpB&1*PU_{U|YU}&nMNz+=WKOte!XdX3trX=tkqjfXy+XF)r^6RSmA6XLK zHhL;hS26f=Zwq}sah&`@s(2~+{i>qw*o#gTid|k$)qz*%EFJjyC(waN(J!Ytqwcou zK;sAJg(UL;Dte;5?8DDv2@!t=w;wZa_4-k9GZO~(a{*%f?DJuiL32xS^t?Yrq|j^r z*w_7VhoVjusQZ+n!?E_}#7t7%rt0ATI*3aV}i#+_Q_zLw54K#_JkQRO% z0*iOQT5%E(w?QX#kSy@gafm!ewLAJ%Yq4B!mU-hhD4^A;e)y8i^#3RpoSAk#`aZZ0 zg|QVt^y-Ah61FI+_(g@5;>?Uua>*R@vcVoTSw#*L0w^+izHI4xyu4Wuu5b&1ES^t& zTg6&^MBPC0X%}?q+23P=92d7$O|GucrE%&*N*Pd?cng0$e1y4^gFGvHIi>La%0BZ= z_zz_khqJ|0*F4_vw9i!rN1)tC;Xkr(3H}l~7r+q&QaZAVx$|{dU%AqJW1+ zG)*G-{YFSyY~Fi$cl)~TjNDYEE(u1_b~aAST@gnh5Z6a%0NOpZ5uohp*MLbLvZyf% z4eG4(DJ`bV@#pPwhdv(1{~-zQ^vHi}ftWnL4S$X`C!!jiQ%Eu-9xX34HLCqa@mu4qP9T#IQM=V>Z#AJN|_GF;QcsZLzMD!aPY zWOw^K8$4g@B<>-XYFQtKA2hXBq7U1;CB%uHH)IN?OG$OfYkkY35x%CZmXC08gW7}|W(F_6;xiWvDb%S*_8>$_fNt;u_7&S{tFs<`jT*9DW*gvc1J#~@MS zi}TI{s8{|yCN5pbpHf6{W9g&oHF(uz`&}i#>sb$&9?|1tx)+)a2x6W>(J6I!$YMTF za3Du1IEJG&`Vb3lbr43)1W!xC;t@9^%aOK(VNYIcR5Av<*?FAC#fGdwkO0r-anS~; z_dWnv;=8GNZ@m5RSZ5X>ar0eP;?Mo5G5`i3sqYJ_P58pdij3nix?0bcB*k*KhmMPS zn3A6#exc3vD0fP)@XTD&Wq79}kmO~j!3Kl^gms~k>-kg&;tfqa zNd2fY#|&Bip>h|bIU*jz(USi0w>$a8U~1y*^yK4cX&Emk!+Tq+uEKL*xw8{!8Ae&I09nb%fe=Xi5rg$(%3M^O zay(fH5r-&wf);F=tmd%H(Gc;X_fP_)`6Fx2#nbhFXiZ6T`xpHR^`v)JNfu`=C}w=+ znaT!u4H+c3Bl!WplT|E0TxSiYB0xK`j&Um#wu!xB&9ZxS*a`PjKzAjbg$TiGlO-h53ie|zDi{qZPPTLi?r za%=3Iu#`tsexMNF?Jw^4ZL|!XKy@v5tPk$pxsnPm#H{u7B-ilv9X=qFx9ythQYI}P zpi?m)WyXr`JXkmiW+q8Z#)kxjZ~>t22LLBcSm2Ijd*WgQgib9KNKLyP@jYyr43m#v zdiqfJ_|Qx(FzK0dhb29&L8tfK7Hewq@;J`abqea(HVqqGLLBG#PdCjcs8pcp2g5j; zVkQuGUAv`*tn&+yPQP8Ne#|SPb9#{IJ?f7{2Y0Sdkk5UlBB`1bkw&mg$~X|~zXmc? zN598=W)Rs0&ft!cGqvZ#+{TaXaEw~A*j$U($`{LahM?un8*E*UFd+U`{~lk#`aHfZ zzBGWi?$X6>W;%3}YHM)oPtWOW!?V=Ns~F<0=<8S5@X_K126&uAKxQxg&G!^OJ=>*(_1KQFM~ZTpus5DDGweO zD{?i{Jq{c5=1!?l75%J!sO$~5zXBE{sBM`l)dArc2o-j?LG&@QT={D(sjeL2#MC)z zLiK~f^gn7V6DLZevY@T!4}xl``$;L76JDk$8V{5H_tuUJ>;kbZyy>a~cR9|~Oomon zMT%<_&b`K38O&rXcBbo*=dw)djr9e?Uo`Ri>_nTYykCK@{)!&F$`AiyKvMgv_bfi< zhHni|fQ4zQ(96rSGMZYR-*D*x-9;(&w+=2Iibni@W|p}-dhdZ7lcf_r22+;}OM#Y@ zkN{4f0`kce$j{RKzt1LnzezsiulLgZb3e!SlQr=k{fo~%$DEq2JkJ2!m`E*r^ntZS zdT;nKH0Js{?pLN&_fEO{hb8t&pPj z_aQ=-Q1%jt=(?RxQgk`S|4=cW(gyg+Ki-xQe{YNefn&MOpLc|zDIqW_LZqTz{G6_t z+O=t~1Z}4m);bn2BVKc+AodAk-6;x%23;kacwRincaq|89hOzCpe15juN#_toWvm= zFR&Nw+7NMRD%XUPQy^M#bxMXOxiT2mF2dakl`H z2uT(ZisS@nZV(iLG2$X6`(7mT*PA{fH=x`C25NKn>)uXGy*|nXE0a=D*SX3HOkXeb ziHNmlvQxbt;L5r)-K!)1KFLU9#{++y+TWKUu?2iVp7|WByfR4^Sp$6$^a9lwXF*8~{-hQ$5dBv+!(^1(ky7Jw}!)4i*Cp+v@@pSzQ4piPWq(}!@ZlHqj#JeQ{L$(0n5d18Ww!g<#s1C*~2 zdQ(4_`7Q*|>xh!hj|6zK>}1!K$QNg1sE;%8yo)F;ig5u;x$6mO zIY%)U%k@$?Oy+3*3hLH#>l1=RH^N|ue29BKF$hntuOf;o(Llsp5=w9seyq~P)(vXW za$31*7HrRoIXr`XF{OflLR0+`ZfTH|E{M*Cxt}0cGRkMYu5C+Fp8#pLg_+6~6ci}u zPwT?O2&Fl}j&7nQ&o4`3ZUM%ZKo0`-hQsngbt)o{LHy%lEq66J*2_dDA9UT#aK@MR z>EU*_b63*x6P5Fh324h{vyr9d-xp>l-)^YvNHux- zXlMcSk>tts+mqYNxu+gld>tkuAR=XIM=rV!!l8O+m2SAu{vttC~h=cWtHvA|-{`dbE1-V|f6FZBgh z3}}goKKZq1 z{H}c^Miy3V+>)#^eXDg-+Yzkv_&Cgab;hHjEL_>cI$_fvSC8ImYRVpN0*Voa6XIE| zB~wN~D(h{`(!en}3)*1&K0WB? zUd)|8IP6_^9uyh0KM-+BTLy3r1pl46`5M~6d-xcvS}|kL;Ea>DhS4d9h+JR2aWPs{ zj#&+B16+l=`xUw`4C>e31GG1yZ@lXEVedeycJUlExnbn5?ge(~tAc2mK~xi{m-p{> z+rSu-!|yf&?KoQ;4*kh3TejcVqU^eyab98hUJJ>7Db7|BH!T>NLC7T!OKB$*&H|Cr zZO3Z)BM9I)&}+xhQ=e7{^M){*Lt@XJKlqDKK(zCp0eCK4n5<%t^tFU>o-JheaKUC4 zVTjwmA5VM5h_1pc75Z)JZdD}qPn?0Do?F3EI|V!Lnr`)LC*8FU1i@o*Kh84VC1NIE zm1*yu>tj3m${|%$gYk8Mty_cXc18p-?L#taJv?~D=5CaSh5CeUr{NGBJJi7x@%(0G zrZSn>lBiX()F5BlPQ;6*2p7eknupN%?^O1_<8@bVIxj=Kpa1e6SSe?H|Hl(|Nzt?j zyW)J&pC@sHS@+SYJ~#e>f=;~5dJxvVl-BL;2ae$m&VfS1fr|nBe-zA_$JSZXFfkS@ zIYzO~O|*Z3OK0+knFW|-(a6rmNLku@+7t;SRg#79(0B=OE zp{CM2R&@*mi_YlF0j7-8U(aN% z8T=unFRQv=H?VWqPbbIfcsk#7(w6uRPuMn8VZ;OYi5(4_VWWcv$`e>_M2=ySfiQ`~ zLR`;3Qm}gspSP|jJAPw%P^TWocim`lJRtnEE{_?d$uSp3ZT`(~)qPJf7?X^hv ztJkG+dcVxfxdh-*2*ih~={z+5cZ7&Xgx|i!gQ(pw8Ud(dSiujiapgcc4Ut#EU|2ME zPPbr=Nm!ZU6~^uUgJF9G^lx2>u!8J(dr3?U<9`MxTyMS-=23aC$l|GaP8N!CZ)J>o zseODawLypdJSa8~{4;_GR&+HEGfK%R&GE?RvZnT6o8G@@V~!d({m-ej>oP7{J*P zP?sg<{{Wh94%}HykD+JjH|03_r3|2ce?1bEAeN`JN>IdtU(hUX+dw2z3zBT4^M|zb z?@&77Z@*ucEW@Eqk?fUU%AvRqZ$I87g9DedROV_pPzXs#y4gE|^0T-#scy4YL1S_d zR}`0rmHUIgA&`);RILZsvwNFWzfIO{8uq{4YuZQwpQn?vtzN?N;L9DGkUJ31GDue5 zXGE1Mqa=p~k@vnILP^^WX8hn1CJwk}cLGvGUMSzrtrGIg;jent4c%0n#C#bEk>_43 z)rH*`AX9#!Di$p(#|zRs7493E)HLcxVYhhIp@P0^&wsMAK7i}T3Cf-b!_LOB_9E6l zq*m`h5tw3UWDI@fZB!zJC+^jK< zWz6l)wpWOw*+1FVcR{DCZx6*e_{P7}Qh|Pmf^-~^^|VO7;=8G7fd;w05kLB}^-gd- zOG8m|KR#M{%YpL>c&aD=?Z$6$ZY}O+m)NaGeh06e1;^m1o0;gYV~5yS(Kx)j1Wr*xRAc9yBo7|M|S_0dmNuaU1#cc6NbTnm*vW5!3_@!#<8 z4)V?C$yKGz;rk&a9ihnH^A3el2!(h6pvp?ioCepZ+yJZ?flUZ zM&iCbK;%bfv?&39+;ciw%|5!`u;BlF)HVDA_DY&w>X_f;NBC`MM*REjD!y(!kURz| z{#`mQcfWfOeP251knp2poo;FV#}l1>F&Xsg4?Upo@r5Lmn-OVG|oe-^=GGRr%}qB5w{B83##w=zRA( z9*wy8C0SG64)K|X-p-TE%-+L1Y52cRlK|^lD&#V`JIU)ZyF0KO*0BzTS@&6MS*Z6y` z{omHj|B)cY!am&>x{ixWu_xO4sso=L9s8Bq+gkbhq8}G5|K}fRa4SB^EmkWw=#Dig zIR~#1otCPnYHZ|!dXW1lCyp{NU%x~<1Ou#W@{L11DXK-+qsp|iwZn87ng`8W+jWa| zyLBqe28O0h;`mx?Fwb-wbpSIc)syXZ?i*>bxixS z{-XZPqoLzFBPSoTYdA-I$-8(2&P7k_6CLFu^p0=X>zV2)^V6oWaf;Mna}%|22xSbt zagO-U>`*OX^bPtnT@?Gg>B*g({JEkU@jRzm_!ThQekXo9Q7Ey@&G-|#abb6^2+~MG zm!0k`+*Az<|3Ln16JCvIJn8%m7Jd}nwKxBM<|IWW7&}hc|NAJ-)|TUWzo4uIc~=Ko zM~zO=GrB3qS5U_evIqvVvuiK9Qj}j>QGi7^5!wj*QDR9eq z_Dn4V`XB#M&O&`_30t*^fYQ>7r=`uh0v|U?8viJVAB<@ieKJsE0jVb*-F>PdNvr%z ztLH;6PMhCey)^x&@C#AfYgC5v*F&UxJExcGF&<)8kplOBnyMaRP`Le`KGxGI$1ieT z*wIGTG?|Bi8Qp-6LI16Hy!-vNjA`)u+w@nTLn5QDTl-K-S7lmNM4GL$(?!vr~6&zA|MF&j^(A7+B*X%sKt00N##aL6m>Df~`;p=%R&W`eGfb-fv%{A$Z%VFYYocBFsZg{#scfKMVY%uN9T9KtNw)p zBA(DfyHPQykMl-D3yLmw=q~~fW(8UAFXju$xr%>#YG{N$9?(!jXq6ZKBXrOsY9jpy zPt`r!Lv54}xXI<u{w@+E&aE;0EnR`K4qqPf-a#U_96R^1a8a-L*Yd% znOts!B>6DoL&ou;=_`Ds+D3w{*9whU5Lt=?zutkk$V5=CDKLZ|#gT;5p%Ze-^6@EQ zgc#PZl?K#DAo^U>HIJ~`QN-B?!vK?+@Ev%Ku3 z_vIJ7*eo3(Kn$aQ@bMBI~T zB->Q{L6nt8a%WoX3w8YH>3hTnWu4FiPnb&T8a#&xj0_J1>a7WDw66B}faD0^)=kC6 zJ`ukYK9{RX(F*jio~hQzT%I^y6S=Jfa5wl##xpKV>8yXpTO9$p`L2%EtZX<)G^f^N zmE$GTjJO{0sZyQlM^@dt04l4~I!ZkNZLrv6k3?QHn*0ECp#LtnhraQOS_D$mR3CpN zOBWg_%7vY=HrK?|-ICvd8hXAhmo;g-FR>3G*(MVFkzlk(EQ|vQ=~YJnaf?C_BWcV- zgZ22va-B#eQ!3|JTG|+zWr*mMF^XlqxdH78fpf;MXp7uuy6|+-=pX*7U(_X7v3);? zIFf%ryf#6R=F8CcZENvQn=ibrf_iMZ&q>YgQNn+1V-qs-p4Bj8ZGE%WO=$}V!0WiU zJzQRT6=w0ai~`}ywH>||Cutp4#oTI9&ynd!U<`YrR(Cy~cVG~I3;C2~|KQ;(Ik*uP z;BzLzuxPk()^FYSBg-3^>-`z4ycmBOMHzTznfTUfmwL|#6YDJ&2NKAK(j%oG7{13= z-9f_g-T`h1j5u00n2A(~%h`*B`2Ogc-J1Hp4wM z-80uJ>UnkXP^$6M>eWLHL^*uOyC^RCkTXtESb3I=`A6!VX3CpyQ}88;->9#w*4?F+ zizX6anw0T_dsb5K=Y<2m-)EGLyYwyTruP6=Xbc$3vd_|U@GpYS*7y1F3n@p`&QuEj zi>$N!ih>RM?IhjZ3?0%PBEv9rmz3gwNP~0>L#Hrw!_W;wBZv$kf*_5AqJT(=h%~4V zhj*=W*8Ac77x%ia{o9)=$~2O3NqFRU=wky$Y1Ep;HoME}|jZCY$NVDq6 zCE-Z?Xd7w4p<^I+b(%n?Qw{F)@SYO!Vv9GgH5^D1Tr_fzD5yA$yux?+TH6of%lOd% z62u^9MF{IEGmv=d(hmm<)H-7tHl*#r2UNap>gm? z*7+iRKH6mFztD^J5)dg44ZIkPB&~zJOmp_kOz`x~2CdQ=XUl=#zYTli6i}iSfkZ`& z28rKlV|3TI0Ta6szk=LoH-K^|gEIl^mkItK-$mYe*7(OGg(Uzh2`*r5G=YnIHUXFi zj`A5(A9V6E;`bZUB4Aii)`a``%Ems;v!aIs=E2b|0?|BsJ`il=-#hEHi@#Rh3$PWM zKfs;(_=W9-jky3wk;%jS8MR6;6h00ShsUb+gtvk1=dwW4J+b;sFE|sTO?n}Joq=>{ ze~?R4XFSP3!5rHgX(o|eJ#JTh5Qf(BnaxA$eQ&s>|M|#4S@jc zi6_WzCDx!XD-G70H0Ba%s1Rp?Nl-P8s|mLE11FB311GCPjH6yADWvc{OtA+DYGPSP zUuBXCfi-0#^&l^PS%Hj$qb>1~Y^e0TX9(61^w*t?e$4;`K<*! zDImd|IU(8kIgO&Z>?`P>U7*swonK7)nj^@OIonxBqbM-@do5Hrn%e{bqJpE%ufu)w z139#SHU-c-!`h1wP~=2LjAB4ZR?PSA-1{z>UlJiHtNB-zNfNI#k1U)@R(wdk3#_oI zcB^*91yZxU)@2jv<@HY%u!*ZfiLTy-cj^%DR}gXnkP;ff9RP~oN&7{V-f3M_wU@Jh zo`+6CQ=lE+5T_6%P(M&F_N<2*>nQtl=+3wz=By)wR(+PNi{@iX_Nq&)>%i;Qxdik! z-2A04j7z<6#Wx+L0%u@&t_$OS((fcFDF(~ooP1Gle|t^r9F)V0&rQsQ69PgB^q*o8 za4i3#i_|_=y$frN&AQmnq78MWPfpzZNH5(}?lfDz3#{N)s?c&y@Pe0#Qz7hK-C2z- zO=F+Va-bE)N`Wa69{y`<0*!W(dqme~b5sKuAam_;*La?LiFIY!|s>IXH zNs%O3Il1IfLy=ET*|UOL>21Bk&Dv00m8%W*O`KhVZd|)_mK~tsVx9s$NT!O z!b(+aogEr!9-NUV2UMSJL~JOCz^Vq-S^reO)I$}AVVk%c{8KfnRZ#_YC?N9KM-XoZ z!BnfFo11tc>#Jg1(ITNsEV^z`u7h%uwVGwZ^cj){J51#3}>Ttj~NUju)(AW^xg^SatKv)3w9559+Z@V2g zr|!^38+^-8T^tL{fMimeZ1UkifN(mFRUekB=?$X7=i_W3R5cIh7HwJn)Udfj?5Qkpt`L@FA4Q>RE^_KEPMGM=hj(-tw$MR;`nx+_CRJO4;R+?kFN^RO7|LJ1O zZeD9}Z-jSa>L9~cuqY>?t1Me~`kq;tp54ASFgDT*2l%*K-(Cyk*yvJIZq@RZgP;`O zA16jdb!+0=iC4Q-C4iixy`&O=4>vV@cwlcKB-s5G^CYm))(#0%Nj+6~Zj90Ojv(Q3n{%;e6(M`hQG5%(YF}DSWm1L+zzHAjzKqx-Y4Z(bbZ8gTQen7ro&iHBYzj zH$Q07J$}PXYJGbZG-UWr}Ni+6yXroT~#hy zyR{z*#ItY5?McH}*c<_4+NrJnytFCmV-MbH%gF&6G#i)VpC_?dBP4*nse@_iLV+R= zG*MNd_n|*NN^2fUUb*SW9p8t&#w|R3itzK1vi7X|+iRo*k=+=Xi`4`l!?M^!>roS? z#-qk?-CIqRZi6r9OeKU3H7=z7-pwPgz6pP~-udqo48}Lks{`mZ1PUwVgV-`d4$E47 z2(TZ$4`~?KR}|D?gH4^q6b~E3(N2EBQ^x2_+^~xI31ERuebdzI>w9vD5VSPj`O;f$ zDN~PxYCKiFT^;VSeSa$UW9i;s{CIJjo|zDwW~M@I^2~#54)3amp6mr^j*ZRa%SaG! z-2Xr~-DK{*Vm?cu>GU&kdM~_XIv656KTT=CaYAO%{b(-GDa9T;_i}!QKodBvjy!XE zP4;lsi7{IEgBwA^)a2iJ3Ijf|Z_3$IdbB0RV>b2AunR^|X`&3!g8>CTcQ6kI;5r_E zYxt_TzD*PU?diRLIjRq(E*BR6NPhTcZ){vm9ZJ|TVhwH7cx?Xg*~GU8Hl8dLRA5PC za6prQ>j|L4A}QgAoW7qA|KfWN4FJ)HkH&xn!w<@xh-D7@$#5H@ux8%k7|7;DOlH1G z>iSAzkrb6NIHmCoBY(6<=qklekXHGspGs4*)KXAMxeiQv5B8X<+GguyIh$<^6}K{p zO!}T^&=C_m$79dDTuS#xMi>Dvdi){GWTEVFrit+bkmP6ic0uB^2TGSQ4hFIH&6t;| zujf7hl|usQ{#5=0&IQUm7^Q~t=R&vG*UT3sqc3B~By831ESaKQUfQb3wMa9-!tJ@} z0`<$Uum4qm_n|N1q;tXz@#GsywL|4pz@wfoqy-yX>UA$y7lTiwieJ79K@u=UKwdl} zW$_Z|!-`epjpoXL>wDq}OItWl<^`c!pVbj7C7(>F4J~nBO^>%sEWEWSB=zS5O2SbN zJy9yth2*r47>gwMo`Rf7H;Z|eXs6ltot6neoKe}6f2ZED8zw3k2SW`%t}KRonp?Za zLJSs#g(#K^%_pl7OV9Ae(WMam(w$;c{_-7j_W!_S_y}dY*aTatfCrGEFXLLqK&j*J zA+#&~1~bnwf;Jg~;uK#>PnX#~?C9M0d7o#+rvb5U`Hn<2BWI_h|L}Iw?A(gj&0uDY zBfWTZumA;aZn=nW5lsg^Uaw8+7qwtN^1gj6{POnR(Ia6Xt2NxPFO9duK_TJP)g+B9 zoIzw##^>HiM3g3k))q2V+8rh)p=nF@9`&=>pR~ICCmru$w}Uuyr$?Opk$LnX65HOE zCZ!7K)0U9!EPt{IIB@#1JyPXx)<#;6pWM3yKTkt_qi``gh3x1h6tP< zlGm;unGlg?Q*TFYj+Btl&>f=J=UzFsN*G<3dtX4)A&Tix70N3cYSy90u=4fu`=a-B z%8H#NH0XVJ$z=%sRmd-V-%ib3>O+1gHwNoOay;XNx_rG?l168>tu;<%*6^%zlIL6< z-u;{y+Uj-M-*iC=RH`;&_2xX=0InSRLU?$Ttq>%1(tmH(scO+=+x`}h)E_rcN*fOI znEk%amhRP_+K&S$>6R|P_^S0f`ezmkN5So1b#J=)nKLBpkJ0g^Eq43Q3)zSvE%!O` zP|2GORo?Vq`R`v3hY5*S{|EIpw31;78m;_2|Hw&7%f`f;OeFFaP!74r#;*R@$5K+R zY|gdo$~TasTyxFbO4KfIjq_5=CSvGg#4v=EG>2?CGZuN4_9b;Ic`xEH_BieA>TksR z*SU{A64C0srP7NG4xVLr2TS3N+Y=#GF(G{J7tr=_rok}JF0O(^*WbYcuJ-wecVt#{ad&i*m8m1JL517h!_ws@=M9;d2l3Vs}U#@Z6!LapjZf#of zj(ClZr8-F)hdE82M%wz7TGwZ}BCK+PkNRbP?JR{k9b`6y0i89Nue|Qc(*KXX&I07$ zWtHwyr2k7_SNTqOC>2H3{@<{YOh+n%#v1O9zJBs*r}K`!rkuN@uf4u_)}s0%W>oD` zy{*_|*i~s>Bqo^!MxaeYG~$pXx|rm=eDz2TZy9wE!tNmeP*78gEJBu)l_PTznROkt zsTvK>)k_grO`OeOXRV4&cfD@E_K+6E@U+>e)tF9HvucGZt~!(AL)*-TzREYt1?{HS zE!x$p?Ca{RtQ0h737eP5Z#U*Uy@);4(4=;xn|4RA?jf~(0%gt{m;1%}e>TOzN>Q!x zbaW>`d)hei$>T&Or>~TmdiHcm^MrT*2NiLinxm3W^4J4Nfp& zGiUl(>`TkX;44s2*QD*3H|fE`%%KF^-lL{L6$w6Gt8$$dQHiu;6?Eho;Id1ay3!4- zrR}i6>S`b?7{#&b$ZdN|$`%ZLBK18k6U!uBp5TtXW>XVSfOzz$T;ablqluhJmUQK@ zu|7|E(o>Lcqzc~0y-{_svPd{junj}e^QPg8E=i#H7*@#_h3^ma8U7JKl0$Hqo|2K4 zy$^p9l87|XjLW`{lFj(OK3AmSR$l*(FC^dOf1nbbba|}mEHE&jda@Od%wVV=c~ zc$5j1KT49|Gs*G5WekN9uS9fs<&yK)7re3-_7PTRT3;gFp>?;`_V)j%*rNF*h=!7= zaK{_T)Vh0*gBZqopU~8sJhk=%c?D`m4Vgs8PzVxOkH(1E*>h1#@#|F5NAdbuIDwDy zi@bSWQ}IG{sT3hEv}Vn>b)5Kw_-SYs_hPdEPFXyF^JAvZ$wI|U!^QqJ7&NsF$DFp9%LB*&xJ*t(gE^ons74+wa87yy^T)N7{=FDge z~k{t^9=zFC)Bk!Ijr*ylMd=%+ht#pjzp z&+$Pl9==1AWJA$pVpBqpT&fObpPJqWLBO&40jIYXRhh$1;Nz_S^%vD(P;p-lRy?0@hFRYG4GlQ$4N=H3(}qt?PMR?H^@MvB1lEgF3= z8{uE7Lf?0)2ATN` zHuN?NpW*~86ZzC&qv-NOX z!sFM3em1cM#Pn$0kigifI1-J@aJp^hpIRKut5~)x^Y5Hv5p(E}z_3Ui8gq zm0%9Jpm{^9EG{=sO2i#6NpP zlyYCtJYlKwYqAG?pM_Dn1kin+ZQ>A8Kyy+UQBRk={p!4tMylr zN$C3NZGcAM{<2I%W&uRg*Ve7N@M!O}EZNP%hf58ly*L+EY}5@)>iGOK3GW9Yz#n1- z^=(mhNuMxQF$7zqG|0Vd!uzXC#&^}nN<6vUjhhwu>p$uGx}3!sVvY74&$au zuu>(Vsg5+jWs!3cEU;|>jPX0NoXU|oWT+S=vfR*ZWl9rFU{+5Nys0gX1eC65OKj&& ztq<7z!jGO7kQn4uz#?hVan%MjF$83r-?WWx+SHEs0SNS}pIAtVPWi9wm|@Ifpf8A8 z;g+DBfUR0%{302=u~p<322lDM64i~2JukJLdc%-6;XUD`FZ}O_(>avn@v(oHa@ax5 zo7B#rjDTbhkr%b&&ANAuW=7WHPb>P$KsO05ZUu$M0~fMy4R%1}9>0i!wfer~X^RnI ziWku{Q;r46=kTT(FY#qtn&WWYwxR?RQ)29@**I|cT!j+ z=i3DdRS6$oXNf$S$b3i0g>$4TItXj#1MG~P*K)fhBmfG!KeHkkDE?`q4 zV%sv}d{&$n4>&sovwCwQW@VW3y@fGHCi%;X}G zNGhekQ-F_qychQ*-x@Us!tlFVZAl@F#olv6oOuvD{z1A_(b~((u71&hdoYtb7tMIW zLv2qo8AzglxGP+F4Us7Bl=wvOsaYmqd(7S8B2gU||8*fMXFNQQDdG0IL!~HKfyE&cLx7ojQ2H;L6D>%U5PZp>y&^? z0BOA(Xc0rH7%(oF@vArW_g(^nwP+DY(0?}L&v^Q%X}nr(Jg*|esv?{x-(U4(_GC|{ zrZe&eoFz$o=M~DLR?JXbO;u7CSJ}^U1!N}>r67pee(+`9x>-qR!Xx#P{0**iE1;qG zuEC!=FvE3eBIuk&=PdKYEE!{6ays?WlN?kC)PdQ{PBT}fJzq^Q^OvQMdx$^hCD_}# zz{eV*BUs>1taOLHN+c-=`sP&f2Uv$>(J{M3?dPcIKpRfkrnB80tzV`v%Z%oPq!Slt z97lN;#OAIR=^e)poC0Kz3j%|=Llg^zd-H6r^XjaV8}qzhGA_Trb9A11-2Yz=QB*UEiBBXF4qwqd)$&E?A2CPK&?h(h#UFlPj zvM);P{nVS$p3XVCwz}x@GXBo{qK*bpB!jkIJ-W>giTs`@KMz2q{pkR0%DR zR|2qML3hF_B_+s%n{0S;sXzso0*``9fn45s$^ihA#Q8=n6($W(i%_PY?fL4N)%SFT zTo$U`dZR!(Nt_Bb1=lsI8$bqJ4FUzY18}{B%e5}+{jb4lB!v_sAW=MkLk>if=uL~t zx(6-eys0e%iCdz9NQt_irtHDdb+-=cQsf;a-$0SSYgHU{%S(i#5$JkV6kuwtY03uT z*@qohs`)O|;A_*c{Sicq2_(`23ZV))l+qs)SIS8;@b@=OQ7Cl#*INyLgy%8*xr6ZJqe+8q^sE|MF)O2n^H;lxo5P!i(`Qiu4w zKlxmEgY3Nm{biLYWhIT+*rrdN09(l26llq|KH9cf3!~8f$%qh*>vRIs!hn5~IZyk+ zHBlLzx&%NHUXP+&mXFFTxYr*(y@qXsaOC%pghHxFyQbemmKvM#h>O1{Kt6vW)9UVW zeg}9R&|!bC<+cR$((2e734fGFI=CTiv;Nd5>}`s062zyz@4v8i!0T4(zU(zU$aijt zKZ%KbIY8dqNC=xyw24pGOOJW=#vaaDHUv_Va3ZjgV4WKJYX*G76e`GuYh>-^{|l*U z1aUWFTN+<#C*j$l4q@8F9|;>J^2yMloc0)jdl)axQ)Ohhk*qPs!>RRYXaU?Q zRG<01WP@sW@c7+sl`*sT8^!zMoWBk4`H!m}1GL;FDo4g?0nf)S z#t94BZ;kq!Zfz%S|9It-700GzGwpeoWIr!|9qjs+qE%qLVG0uGA=DxQ@goJPN=zcz zK;9E6wAvJ0SBk-;4giHgljnb2jxp$bY6a98{F} zfsG9G;XBYh+ma0qJkIs^QYz2*Tx0NP_Cx6Gzwl9P7U<*Wm!dI3n%E~lUO#W6w%&M% zwyqmtT<2!~DWZx2@$b!D@OqS;TQ6^q>)-~n`)Wi*r~l|q6NxSez!yXt5ybYa$|b(t zd@8pJkLI#$q36YOALa`P8Wy{F=M8=?Vvy6E_w$|!M+?H2EPjsiA7XdzFUU3{rX23~ z(0baz-!Ey(BUGTS&3r*LAl4rrwYPyjFD>b-ABD0G1bId_gbnzE33d72VvT+ z%!_7<4Kp1)g~Nx>an27w+YgdKd>dP)tl#-k zmdL(r9K86hU}uF=3By&p*<5~phNUXyl6)$*Jz5K%%Tc)mE4h7HH@`P%`l^WCazhZ_ zWfIoMPx@B+OZL9!w@{9Nmo<LZ9aJyYnKz|_0`tvprnG+0mpNMs2c!s!lT(&q~#oATz>^Pv7w}d zj@tyV{vv6h0gBIqM@f4x}-4$RdEYq1k^A zkOEJ8CJ2w7?_-N~kG_jRh94YW)E zWttr5PB3%YwR9=Lf1kWlH>Aae$p(wC(#3@84HU3Kxj{(v8@DbR0>Y@@x6Fe;s;#ou zYl_bvp0RnKow!M832qU&R#Mu4Aje=*)FlF6Pg>UgpfKrStDJ`)H#J8X|L6#sDXIA?91aQF zsmOCBJ9vMZ$B2=)805pMb%{h!y}{}rv1tVv)HI)UkQ48S*r{<1(m`BD%Mc$hFHYk-@n$7=Fa~IO2kzk&Z z;MGS-YH3&e)h<8Pmrk(E!XD$$Eyn#Co`U~=Cy+ALZW-!$j>HQ;DzpAR<=Rne6diFp zPQ#NANlqyy-aNY>$E`!wSH}36-c4rqi>*N9Uv{$^14Z6w(w+i)Q>5po9-nUyDlMj) zY*TH|?5U!htUFL}Ui(Q2n@4oWh(*9Z>$5%LsH>L0zxk7xq*SNse46<$EY{n7zY@@j zPZz5U{Ygbpi?n~}@Cnpa9$qC%*k9B*#e)g;N1itRlq1>gKaN1V(YrP&eFqGhOE=Y@ z8c%xj5udmKDOEMKqu!ts)wbTm=O@Of@(^56;`?tQyr|YgkB}IiU(?>R!|X=H_;;KZ z^#=68G(1D<;EY*rATNblMH8DUl|4brH^EL*fHmfEM93f(*YrY4kB-#U0z8$8^ znv#-^`(Yq^=f+xjn!Y4MZ}1(-T?*=+-|JLBz@w8nk77X0T{Rx4MBzAC#ao-MSQAZA zvQ+bV3Bl%0HHon>(G|1Q9DZxrqIHTj^4tE3k2Zfu=DR_J{LBslJz~_BP~RS2Y_@+7 zsWh7|vy7je(~MxQ*314YiqvOje`MMs`XzXYRheH2kuaJDqiSQqgt-an8CtrONOZ3~ zDY)apPnUxxUIovm8kG<2Rc3TAKQ)J^Njq3;!Z0(1hcS*uu>_tqiAdLO>&_n>{Pw$c z^naJ8g6DMn_QfzxRB4qKo4v{y<`XI6@nVt5{HOCLygzi4H_$tU9dzU=xR4wLGPZT7 zjZ4|*H^RQhOxZ=QKZSX%qv$+vn{m`MRzMhySp0{$x+CwssWy+wIfv%>;1by)>qdCW1|9&kgJ6fPS{bfo##ymJ*LZ zp}V=*`q19vzhtvUPhOs6*A{+8bQ1ka++oPwOtU+%`znae|3x~4S{1$W8A z1O`W z2`LicKR>jDbr-G7Y@p>%%8gtY4p*2TKpR-Xk7MK&;6gOV(R2IFcf8g(L>Pm3?&&EO zmo)_DfT^#3@bVzGdDJiLRF67Odts?oMEQ*h3D8G_koP&D{1TO8i7gMt(4(}35@sIB-HOvxc#-_l^K1jKrT_q6ZxV{+6Yn1~ zL6f#6)5Ca&Nwo{!1NE_YT%049>&jbXsB?x7K3isLSzCKYkix%%oW=nTv?q~HKkta* zxS}RfU#v=kF+CGj_tv$@^aW+&9T=#4HIDei9OeBtz^wbU?7B~jAFnLq-k20ollg)2 z&rl$R*r~@z1H!3oR=VT5_e?Huf`zGXklyq65MPsALz8X!D0)MSLsN#HSk&j8KrZSP zIQIx0KhVQF;XbdKXd-Tc{nNe?)sVlJAl4yK#%`gnMF7797bDDB)5o>lQnHMMoy}g3Takw>wl+3=l~~ z3--Whu}Z)>)YkWm)fl6q?&c6W7JMIDh$mMy+^Y?h1rhY21Wi(ogcJsK;7Bb3Gpw2X z>Fi#@tP-ezjlSONG2bKTL5h`_af8`2R`F9|nZf_M$Qaqci~tx~F78k+zB=Z9m}DX+ zFY3Xiztht!C1A;@Y>_Q*j=YDXF_|4hN5Q!$rH`}BEVp~-E1@6u-}h3M#P(UPVw+Wg zO2lgw*ORtY)i|IzSoZtC3Z8hxn-Yu=%)CANCW8v8|7S%`sxx2LzvBSM) zkHE>@TU$~MmvW;`g72A{k4iG-ImR^_$s&&dgvX*~voE-b9&MlrMHs7lst;cTHGZ|q zb|z=jMDYIJT<@NP<4cAOLcUETs9u4Ftn`N@ONl-)sc(_QO)+PB|9P4IEWd{(o;1?0 zZsZ)ulEuRY zW;(-TS)&c45Fr_>8Pi*m%+b6zF0sn=nW((ouGIpmPErSs(?sf$)nz}_vWSzr8+I99JSu{tu4uEYWOzS5}^u# zMHj=ptgB$#i>_8Rv2ORwbvb11g7q){oILZC4M;x&&0*Z|!0!^z7p;H=o`nwK2jt!o zXXtGm*em=d{5bl@`Nr;pvKz7iuQ{4ro|L05A#=S=!dMy_krm>xe~VQwpRy3DuHZvY z_8n%V#$5jM3I3+@W%Ak37Y?6PVu4 z@s(=2>TFro=OMNdXW*BBMgqVNMi+P(Sk~A@VfGIKbSh;8sBck=ZS{pee@t`y=|6X* zVL9}%F@p<^KzxTl*%;{WO{l65nGxtE!%P-C5XJ3M%E65y;Do8hAU$y%?HXt%>^9%~ zws@947)DaOcNe(@IM>=?H9u6d)!12Wkke^QyHxA$WOF+J1WXX;f;*UQ) zq9m>pXZSCL8fdcOWlZKfLq0e99Y4{rWBkrB>Qm+h^(Poj-0l^>$%q$D*k7E)`iP2E zAcpN19h{ni+k~e2I~_RV7FlsiME!RIx*FU_J5a~Ehy^{KVRENtJWmH(d~O4e%rM5( zG;B*Scu5kc{-)D4Vb(}v7BXTSH2RCqaKTA1G|sWKQuB2BF!#4Im;C;7*3e^jXWSKI zZyjcR)ka!zRF2oMq^_yEQ^M2n91B`}uG=>Y&LZNQT{Hl%j_itWHDSl$#OBX3{u%s|5 zGe`tN{_N!UT3bILjVsJ|P{e4()K?JLCYa$XM1L?-rM8$aC0y+*T;DF-JddC|5$-xU z>7GYK1O6BI$N*#l<^do6Kj5Qmb`QgUm&#fBpZ#R$;0CVu9!t^8UT1KPSO3=?xZha( zr(c(P7G5HxKh&XC=D~6CUg(766cgptyHrjBlLaUAiI81NfjnnHC(+? zz1*;|8s{CWT3fHvtN{Sn)V7(Hy)ka>)#*3v)*Kkpx?lF;A%0SSOrsSsK5sN*@hR`4 z@#3n(y77mdxxg;nO^TlsdYg!^TW-5M&pQkjf8Nm_sx-W?B&}a*12HL@)MuA7+Hf8S zsS{W2HdZ59pY7QYKX0ij4=GnKf@EQ}gPiN}T;}(3vMa})!7=E4jwT{Y} z!pW3rKa(9>vZwQKsvSd*;n5l^M@fDE`0%!coo3C`IY$fr<4bY%5oS`An^Mw#OZyo& z9_UnK`Dx;3Au>>Jcl}u#rU^l(%|HE5%jX-el@WNq==9X6KTdy{-Dyehu!V=}w!HEU z1(B-eo;=NeTD~V|5Q{YX-6qSiQ17dNV#iCh4Q!11Ue8ymch~ZzPM=}O>CpXuu-nHB z%zLy&?&`>6ScHy#KD#fY?&udZpT@h*1P(dIw=PCj&YOtV_#(W~Dw5aD=;WL5D*EGVh|-HyNUm=H3X%Z8dG7r}dsD5ZBStS3W; zU)Sc;6>ucMA}U>?^j>is^<63DY?uabrJsoH5R-uf{18v0o0{+^*oId-N z@BSd%2Q=mtC?p>L-|q%4l3*o3bY;uUfx6&G@HYVUc=5>yh%)$B*d{3_@O_VRce#<< zuse~*Ul6uQ@_9sD6v2}8@GYp4?TTs^O{kA0Q8|t|xs!G5lMa>E*weLS zG(MWhME|=WMDQs*i$&57U+`C!L9kR&!ul{^Ed0%>Ml&dLg7Q)@@iq4-2?P5N7K)cJ z6+HSl<)L}}Et*JqS=$Amz5%CM9!Gvrq=poq&{p#cB562oH7rG5XZ}Qtp~c#NuX4K5Q0||A78cb ztkJ@V?aYv@RX#-S=20RRIJCByD1;o7&(@68;H%<}JriVSR270qTo|LP9(|@ZjZ!fu zm{o18N{yw#A-QB|a*2zpMeg)}3`Z1Rnd(J+z-nS%fHb8ol@oR1bpxEn9uv2nC|X#b zVvfkl(U7T-eM$Ae)5|Z3T;EpVUciK~g>gX5&6<+RiXjUG3m`)Qgf?G69A&&D8~k5_ zYU+)CvD*Xx`&%m?Ig1|OZ^w?gBOXu*Py~pbIp01ZgOjfW#t@@EU`o}$XiyV>z-V_Q zil70ctrIhtc^a&XKI=$44)-6M|5K84-Ytjs-RtY9AW4bszJ|61X9tZ8o?tk{Lj#b` zF;utV&T~Y-!q0mx#R_Fbm{;pUg2qsw?G)gz#46%kRA+6nKAr@DY9t{;*J%J;wHMZg zC)i(NP5s?ubJ4xM!VbBD7Q_M*;=$4uC1BKA|5@ERLsDob{DQfeG zt>1jy_ZN9?97Ip?4aNIz^~@Wr z-x?FtQ&F34371=8hYEV5x1rIs=;~WCQvD6AGJUs=NVu1(YdxIXyvJ_)vlm@p5oNFv zI!cb|S1`1Vf_*^X-v3mYSgLG>4I6C|a(=OVOBp-(2rsUQB6)n~t`Pes3jtv8mQSHh zOMrZDB(sVlW;*;rXhz!lJ7AloDU-_=Y|4c(Plq}#Twq| z7rz=oIey!J_#yD3<5J%=(1;ac8vK>+#47ePiQcC^V>ARng~^LmRxXDHz1<^oH<*Aq z9MqiC@a{@*nX`KN(ZviXc2dh``+hp-^%`U+H{jM*vTThHuos#DF(40DNwg5#Tk)}M zl%L3S9Vow&nCLFlbFTmd@nccoGCI<~Nb+1?doFx51epqbg}i?M^4Q~}=^w(vM#%Zz zdaQ`onA0Py;INz6E#mE>G)#0)K5*lkqhL(&#*t_fDI3Z^Ru%54`=rmbY{0|Kxy8#Y zHi-cv>*s?SY5n){+VbTxiy$f2w(GKa-+IeY;5(J0fFOm%-w}}hE8wRmN48(Ha3QDs zz|)$);hbl0e&e6o?Fle74r)frN+g2HejW2Bad`Gu3~@oRd83JlHQ_Gq3D z{>0KqKEvJZXKUHOybj5A$flOt!KBgUPZt-i@F%B_;e-aT2n#@XWwj$u1waH7dbk_W z11NuJng4TL?k4U9oLKYL^ zD6w%vBXM7%7@ufE^70@sg?R2@s977N+7$J+nv#0c<=t*{d_v%irRNfVf}ka2F3?>A z5aJdiYI7y^$VxV%BJ6RuSd<{2h6|l;UHtK8tPxX8k0~%4DSj#d$+Jp9N<^NT`pRMw zC{1N=gQM7Uwd5RjBG2Xctj~zp^4zxP5;-mtF)q&jPkmQRlMKvKJ_e`ICwiCUM^Tu{ zHW8#o2&N{fry@~# zKFmW*p&S?BoM&kRyHKmFR9y)dm_1_EB>3J#FExRfRjnjnXLo&6%AY!K>Zd}bE|UBb z^mHh^D+ht23OE~AeQz>sY)?vDo$qlO`zIcQJ6 zKCZUAHLOZFp0I2`@&hy9%qsmu&n`WZe=YMj`gxpjDughYH zNIrdY%=JGqp!;u@qoD6Dm*h6^94tXP$4R<)m0WQZyH8IoQ?Pz<|CZ|3LV zg#poi)c~xgh&Nas1LB=6BM8Z>R3v4wXR<=G$mnuXNkOD>656w3o@@1c@!6DAwF}Or z^G;O=bgdD(VQ;@Y{02a=QCq-FW61@4Sq>PV0Fe2EeR0*dEfvO#R4kwdXwDi8ZYnRf z5vLVnZy`}CD_B&u=Bk!d703c@I4Cu6OK4Rpi*)1aV4)(J1;xF0qXVEo_(tFAOi>tU zpSsDEO8Ko1=UbA1K+W{`ZqTg6{OLa5PUh_O*ai(0;LfO}g((s?F27vK$S!C$VQE~p zuTZoExX84KZ3A|a^FsEC4q0qo`0)OKw*C}oUDXm5Lol?%{e|YxhFj4G$V{EP4NJ;sD1KPGfLAv$l#meFQgq<_$zo(@+&583$Fj1c=jP z^yU-dPJ3F96q}I%oEE%;*$wzQ1gF@D({lygzExz1WkJCt91UcE-1y=FH)1Fi_m53x zQ#ePKgSbC9AYj>B7yNu&NikHGtPX23W`iMyulzjfZVa|j#dWX=wxjDV0$6xS6}To16O^zMc8L zec$JO9*%YpXVCZV=rwf}Lo>cTYcao=j^ds|sa)Y7odZ_wImNP4DRJGB5@QTG0+}Do zsB9_VSO@f!FHHJqvLLNF0}I%%nq;k%VSo&<0;4b>g(qr1v>#)Bk9G8;Uk}w!zCLK5 z64y*GchvxPKEOs@wdQ(V==_6o-R|1nh&yfo1%yuiL zH~}Afv@bn2V+oa*_$igvRB2(L51lGJx&xU00z>rhY=r>%{J`UsO`-%Qf*8s8gX-)W zu^{LY@fgxZ^}|Yr2-}A)Q{H@)4P!mGVbO)FLU9MC#CRFm4F7_SJ*_%BpR)bJqRbrQ zUC{i=5NJ#I5^fEm&>f5k^{CtG*ny%yF4 zU35{B^9=ia{Bw>qH4UC_6p(?TI^xvLOHgwqFj1si+Xt@>>rZPR`qQn)dvyU>Csl)g zp`+!!RIxJ}b1IA-c0W_6(IT@thO^3BpooSkEZ9hsoDE^v#E+Vh!(v(a^@;Sb@u448 z7x$k?n%-PMzc65{Cph3W0jK)x`sg<@yE#x@!>_eRR9Qc(caEB?06r0?&Yh{Ft=2xP z!-oVvdkO2!kP6QaI6h5r$CEnMi13;2-=4>q39By4f_p`sesh2|N>#OC0M78auc@8M zjs4wni@k(1uBig%O^a`?6;h9tCJ!$30wohzlz;=ZZXa%Gp>5btqx5)Z7(Z+nyeTPfP}3#`Cwyq6sW6}5+r-OBP1M^l_B?7Gin*7|FF!Cn z{A&#Y0rO&?5_!YcZNS_Q8{7nsf7XRe`D&A`%CR!5j0D=T2)ek@n~Q%puPnAJG)ZY6 z9A<1f0NP-t_mD>QcToMt&|}yw^+=KtH@cmuC9-qPXQ-Q|7gbjB3t|hn0m@h=m`CMQ|K8n{d2KbUsolO9_W{`st+ypX0tg z@AUdnnDWLmlj=|(funVC>UA;XRixi?p>|He{x}hN0bY^5Wcvw#b^oO94dQDqgx#J# zH@Mo;{}Di2!MgfgPKXp^r|F-ee54|DjUEE$dP^vtlU0JUw41@!(tq?7LD9eR;BJNX z(wnN5`2x+qPMZpo9soiuafP>Oe|Uc1b0j|Ty-;O7(G(_BZ@KuF&FKBpOjGzz(Tkv< zjLQJ(a5?F6%DX?}-`cvC>fyur!`rMztJB* zXEwsbFV?g@6S~nLy&0r?`B(EMp7|RN>TcGNu)$l6W%l z6@4d{jWqghXyl}(i{WI7{X`UQL*=ti<1QD$)mgOc{oiApCTzfKVpQ;JL4z!JL=Ag9 zAVM`Bluwx;m>Q5A#LB@HOf8TU8?PWJEmT~TTvbsQ!Pw^4)iG+G2-&3hZX?AAs~q)mrbHid6LA7^OQ3D(=!2SB*+kk# zIJ$WF?D{f@F9a!F{#NdJQV)vErB%s2#SvqjiHD`AdSegiFFoKw_i_AEen}qfu`!^Bx^3Uimuyj zYt}Pbf6|%M5{y~{yCBi8V>tv$l=*Gph$f&)dasa-UPbggwyWLFpj$DDdgbZ0)pCm> zd86S}$I&B%0Z+=6@z=|edj4%1f2eK$6PV30naL_35m1Ipq5pcVi^6(J2NZj-*Lz}} z?Ee!qT;cGJM)*kXJ%wDM@FMdo!(pT89=_O*S!4Jew>{52DfX%Ujd0WMl@{6JOtzlzh#wBGU5z5tx9o z6B3--nrX&|!dc`l#$z(;uHV57U6cX zvcmQHL73uW{ZtfnNp;j(U7uPS?)?3JD?TP^hLkON?OirmsHhP=u#o=}_e(OYwML1b zRXK{d?FUF*-m!5j4x(nyR?X-Swgcgf;cjb8G=^s2a>!ngPD(Sm8x&c}$6tGy{;_c}G_X zi}BuhpG2VEfDgi2eR{-nLGt!rS-1gR@}?g{uFTa^ZN9P?rFbuys2M+d78MWJAZDV& zxaA(3N!gpjvV0PtTOXPE8zo2Bo(lZVVp`2}w$+oKMB25d4-of9*aw!6O5U`Q6h z`HYo*H0J?3Udsq)bcrcQ{=PEPgATPJhK@KqvtJ zCR9d1i{JSrZcVjd%fZ)AbELhYUVa|7toHh+w&P9H#o_a#$Eu7`anv8&l#|IYv2^ya zia6_%UCicp+p=oXu2x4J)XV-~X%7YmUI#XBhT&p%w4`eew_AHwPH2G zBS^W?fe)a8zj|<7mh;CGE@U(Y;{9Aw3i^{ckul{>oCN_P45;gOlx6@ki|?KQEp4Z$0E0 zD>sNJgxZ-0fI}Q!2Np1*N07JTE-^;4iQHk~m$bZmk~x%ySw8>59F$W46gcAic`nAmz5Si!Na)5sw-({TIewd@VZU*4CQEV$<+%*0$LL}sH*p?aNF61 zW9X%}jDsv=byGr;DA&cEq~(=)uKpCX+~p+B$$0!(aOWQgc8v#Eni0{^cJ|}*G$-SF zkY~Ap9gj0&pE7~$N(0{Y=PuSId>+q|$}%SvppL2>*%IzuR^!U@BQxpTBjpVS1zi8C zE>7cqP#~DAee*lCzLdlx3*M^adEBa6bjoq9n#@Yt#iVNWku>C9V}`XAB$~NnSS@R* z+*6JCGs)_XSFy^r_t}f_wTJI6NBf~>OkZzxvJUeU#zN!u7>8gY3Tr&M{hfM258hFd zk3=`2v_L2B`C?`NiLCNJ{hNsYmNme%!g?b`ov1<8^BdYBGhY5*=?AGz+*zs{$2CgB z6ieU!EzHwXY{81UPK9d~rW2$2^IO?#>~5%))_AZBa9Ks7Q&LC=9xN$9G84++c!Exr zjY5UGXAKs?VNoerH}=7*`tGp}_Tqp)xT$+T0}D^~-2TBK4BrX!m{^ls_*E51`IPe~ zk9M)K-az5lLbi3Gpm9?tj=%nsH2D?I+|AI4ct)X;&ki>gQK)byx-jg9G{&oIbZs+IUIQ*ijssr6{M5o)K?L7v^UQ zou0|do^=eXsRF3|HM|itfRfKZ)?t(gi&2aY(RPuYr1M{253<8xGLoO-Gr~MRs=jzr zZy^$7W=~~aiuA1?Jh>gxdH<$^m(lm!Om)eSe=joHG@prJh(IvHcmK1#r?{5{S>eB{ zd2E{{uI}~Dyw%rPDkU|oxlVYuO**`D?HF9InZBjGp-01s>#C28+cMMT>rkpFZ`G}7 z%CArG^<HDVg`{3F%v)pjZ2U%IElY13gU(RZjb3Ywbk5!NW8PTnTUctB+=ati&3J z1{jveZMAm!KY*xIsx$Y6es*$rmR)I_%MGhEFRibYmIMpAzjZH*b9fP5HrM8JN)#Dt z!Bw`}A=sy)%g*|oIO+>oU2i=V%TqVOoy7ufsgk^mo6(H)+oaCX@6r;GGAqno!9s)@ z-~D&CzXQK}{u>B8IQ@0FE6>nu3!JTm-~=4}>-wq8O>kQ#Kp(O7u&jo$|9qW%L-o#5{7QD-$VK%iJnJ;<-P9SvS+I^F{Uhpeqyi3q)s`yERaL$xSc&I< zh?fS~`>Rfm>xqvyjNg1-km;qLPC~c=`Lhlp*w{aXoiTLS4WhmE^MwZ@+=yq1@ES;0 z^J9p_5+Et(xSL+8x%xk@Td?O}5wW>6JC%eeh=f6Oi zdQ%VylI?owQxZ_>`2e*pC^F)H>tBp7r`uSHP&@fh&z=&yT~Pao&@@l5Ol4BX{9pV- zBp?xR4LJD!@DFu8x?kd2Q{ zOiDJEi&cwH&=g3?%|oQcWrnK>K=O6G-&WY9rK=PbtL7L-R=#i6uC7t8%eJL!>4mpj zwyD>>Qx@=QbY;~VRV-H)SMTX-Y5Rc6QfU}-W>)@a_!<5BL+V`n>bT-D4%#@^+-@Je9(E>qb#WTwZ{*nz>5YynMR<5H0x~fTFRhi> zcYQIc2Lf5E6jKH)%Ch9uS~0HVC7!BPVNl!?2=TC6@1@Or5brmyvk%4aF5|cW=pxhblUZ4M<>zz1nt(rT%Ja5!o56bP zBW0Yx4k#*A)f%xuLSVEQ8_qyk{vtw^UlJX(0@1`E$&Xq&KSz1lpteYfIjcqyil&;e zDXQNK>>?Ete|<|ZLAI;%u)DJkS-p|Cfx4$jw7w-1J)quhq^U( z$SA&wDyb3!0}^miIhJ_3ub5u*}Jc#O$|t22nI5&_cX*eEi5ST3;pfkc8?}7+=eCwpIyn5Y5Fe zTt&e8k40C@`ym^ZmR+Yl6~Da3c}4M!uBxQxo6pWTzZxIaD2+Qc&o*>+(Y91;0S z`9}&5(xE>~+EMg0bg|DaDEOOdtZ*!Wpw!m=4IbdX_Va>3*mht5Q)I~H(Ubcxx*3>q z#HTBDfzDrfbArmh?^kS5$p8f!QzY)5*xMOE4S?1Ypi8-m3e+y3U8tVHZ_&pYKAG5e)s-lk29vNXZ;ern78W#0>FR( zKr_iIXTVgZ6~Ge=^C9vE^PJm~!H_XH=2^bVv~NKaEkFuak9g9K45FVEMB{sC+xk}H zU3^kRTrWQsf6EYp3sng&FRw_t%4XOr$041O40yCvGNH6K~mWu z3Rl3-Fv-WYD*(iJzk~1EGx$6F!2Tk1mR-25gLc{{ojKEi&=vjB?9vD?K5MOx+F@8_ z#?3`l3Q0;o8D)FdRsbe_0ebW?kZ$SWyaBTjySoIcFw_c#-gx)(>P3nsN+eZy!MGK*^Ey5u+xkz%*#r`leZUX;{oNZ<`& zop71|Rb|sADL1CXV?%o7uqio&XfycDvcWzz7KWTd2^(WAGZO^oyp+s8BiHA z1lYv?`hpntZeqbKPScxZpsWM;-HK-EP6h8(p=c{{k24`9d0snmtkof{QN<(J%-S~J zH`$NRMdVHggkA(Qkn+E|q<@lQYY@B-k8Ud&0!6RFvA#MsynNXZ`;pkVt+VmuRn&b< z1#x%jPg9KhYbrF?zrrpk{~h{8aSJ~y;uC*-DT2s4L>uVY-3kv^@p8E}e9a4Y*=^s! z(+5Q3l@#>+*9ZXHW&+RxG%EBvhtr#Y4elNyyp8N8i9^k3jJB(L6qwY4;KZbZ(|m|9 z;5_Eby$&urJZghCC$u;vi)dHe|B3SgPE+|JZQ&d?`LZB6@um3$dEwa3ztd=&z7@Lu zs{#_K7wKC44q{IyRk+jfGheX^&9Ha)oZP^YfT^pT2`iJaybTtScRLgd$RP@7eV*8{ z4#|2DnEId%Ec%z2xqqd`;bAI7Di`<}P>0_j@VLN zK4v9!`}MQa-pp~63XN!{)#zVev~*8>M{d#5{XKys=<6Ek4L3u@n^FmMTl!Tyqj9k2 zQbT-n16{wPqinG0KDkYbkbLx}GzyZu?q4SR@94#SHXxE%yw%@f?oBVtYa|z^GaYFY?`O#6p zpQWcJ$Nlq^Qa^<}&Rt+RMW4nvgX-7Pa9nhr6T9#LCa*5NEDgG9=gj~Fy2$>d-L)N> zpB=#&t2!iA$S^75uj%FT!ylh8QuE<7QY!ED9lh)Z=qYGMq6klebk^qZdK^WDG%y#* zS2Bl+P}Iz=ToleVu_rTgcfs3F|5Y;7Pn#oTW4$k4)Zrw^UAP7{eWw3H?YZS8@tkGw z;_olppO-rnn!v*l7X<=`pwq7&vd`xJB~h3t7{{`-zi|kp1}@tG4)6eHg_QLK7vW&y zEprX5Z~iY0VD0y1yQKP1Fu!QoE2}~J3^wNEN+DUAj6u1uXwQQQ|IMqK3m^T^17@$> z(_^wz7+4DXhSYoDR}l6Pfi3c<#{&SYf@1wS{c*sUq~s5xs*FN6H(|uwmeAYf`a-V~ zfX1nl3;sB9wf`@QO83RDpplT6T1^RW5YahE=vTM~%&13_%T&}$Tt(s&lnOJP;CH(V zaT<3`SI0ta2j3(_4!Fza zK!OkQBa{uJ^0y*1kWr?jk)NEcm}mj`=TQPK#s|jHk75g{t;p4iXrOEO(^^eYK#Xu5 z5L~UPd=64YA>N8{zKs@HhkFf3lE4yiFZ@kr&O;5MftQkzleMwT6YP4%!l^!*tGj_k z+0mTdl4GMGe10GjR2;!UoNw$aWt1|MTF`}?KJKYNdQC(hn&HeP*rg`eXCl}+D|V(e zc4mkub|=gUOX`0Hi@f2)NWN&z#JHevQE#=Rxd@pQnbo%GPiR8{?)t3leKHPb3x2+}%&ZdGqqn z6etMALYaW~Z%hw02?q*rUfuxZf<<+ZVXeR2wXria0PsK@ih$PX5T( z(xQF^k~sw{%SMz-1$?&!BuE`z@j@0PmSM|t{o%r>g(%Jh*CxCd-z1*oNf+4rMlU56 zSkAv0qXcfa1|WHgAksd(>;|GEAL<0*VBtBi&PiC zx2(Jse8YvcJ&d7Tf}(pFoYHw$qXoz$54`!z$$!(0o zEkqgL5Du4OHcYQnt}=>)z>czXC#@hYz$Gc71LNh~ek z8C0Wm2fmWVj(3nEMALd(zVqp0$*m7`f=DTJRu~;sNEBq7YgZP=B|@YX$ZJilM?|0| zl5nk>Uu|`IhhSJTf9)J3>zE_yNEeg;xM_>Z2n%A-bB{KmO);gu%9YoT3>ER6i4VS@==No7lcnXZ*ww)F^~ z{@wQ~2omsyE+y8yddmTM&0C^~lK#~P-=hH5C+phoHIwwj02}HyVJ+~e7JqO4@D{<# z7zn4&Q_2OP7!p9q&_U4;epiNJ!ha6oPxGqi7pp{k-cw`x1u2=ZPi=p^7_%Gh0cXu<(^G-n12U_Nw;-zgN@g^ zzugpU)MZPwH1jqHST+Rg`ZRfObJ zegvYG3V#6X7eJ+<9RqV8DkZ`9tqt}nAVXf{&-ygMOzDUuwd7@R(|zAyOdHd)=Y;4s z5DuWb*gmzPX{}!H%P+D+C~FYOwX8)&#ZT*3E+QS?fo2Xn=`7jL3Z$QE%z%x{;-tZvLG+l#wv_5!q8v*u;F& zlhJ@@d{Gw{ML3hoB49|fQU0GDh?Dl*oA7!Jeo~|94G3N>1-z484;m4!8<7hG%Ugpt z7)DbiN8_wUqn#h?jovleLwa&yXKPRXyKgehj1+qyHd2A6u8qQ#b;bfecxEWA=u_9kIYfMoxA* zAU{AjH0KkhZymAuS|*!64_q%h)rTaQ9ye~896Omz#hJSH8^VE2X_kz-e}CbcHC3#{ z5M{)~`T;^M#;pS7=F$D+`aQ=x+p`Omm|EeJJ+)f4nO z|1$^eXxdBQKl5y^cUWb=^#@deyekFT(7AwO5Qn@i*T2W537EQNks3M4^SQ6?hpd>* zbIj~twtZ!8?17JA)0XKB?E2nREj&7f+6zGOY|VjM=oV1-pS}nh9Cr6LvPs0fbKoj< z@x@E9wH`QW17$(9G$W&1ZvFgr!Nh_5Gi&D3LSw%pr=!EAAVLW@RG3&1O|OgojO<_( zRp!L{8_C1~qCkEP{ihFY>DDlWN#QT^NVo0r%u0JM^V)!|nig&3!IX%}7aNlgglHWn zgB(3i{Ku<4nkF^nmCQ}ZYbmxgXA^z?!As2?gtqNpi9{z~2S3uQf<~MgG59YMp@k;&H zaoBiYTKR9oNpoHDhHJNE848HgNX_0=7J;nW2q>IwT|0*#U+atgcIy`h>KGRF>6P&X zFD3}=KjyZ~oBBdN1@X(BI|TFbFI;&kb3F07&Z1J+d5 zKebMMboXGEO4aud=>!5O+KV~r3}RV(>LcF`)%gR7!7H86aecM(xD{&9Kf=>b`1_$= z$1Cr_tAbz?uYCjJm2EGB-SnRQGe$JU?s|2)GDzr5@We=%#4W=8+RN?trtD4GPsL1M zEN{K!>ywIL3(UhF%foRp6Si5|4xxd;&R}m4;nwwX6@Zh4O^7n@oeusP<8IM+b_;(S1rPRsIdRb!t1JePVgHOIdJ6290( zax{XkX@#!;2tycWcQr7(uFqZ$ULEMo0u3TBp_!m$&B|v#FNGA(ZP356uYY-P{B8)j zqG$Xp{J;Pdet!i382Vuep+VwXqTWKQ=I9Im*@MCZSsvt3u|B}y@hTS$cyHBQnLe4Q z2f=xJzF}Kw_wBsH_ID=p)_>a!pqv+XRPx00w{w{gWJa>)i=UOVLH6B8VXrQsNFee0 z-LLw?Rz*mA^K9pB^CuVt!P>yjTAhnWPXHpuH8m;OHMlj%1*_eqsHJ4(r6X~% z)wQ(t9rcY(YR#>z46Gwf6Uqt+i3(DSTsfg6Lk`cq>Q-B%Oxusar3|Hc(?%(T8 zu3Io2KpebRIj+mGMUm8>7&#)Kk?fJYLKIa`#1((=XkQ$`#LaB1D9l?EC3G~KUg2b& z@ZPZJ$-&J#ye~lNx-yO_3yCVqyW_F6VmqeAa4f5?myvyV%C77s?LNu*BFeStU|Gl+ z_YlP;3Wy6TJ`P3|7%=0SK12-lgFjIXF%!89Krye`Y2L@`)819=K*6JS6loTov03Y4 z`7AH}P%PPwlX6_0)q6g|SUPEY(-I-3?KaiS=T9a8B0<9d5Lk}1=a0j8KvoP(jQ5uI zJL9VQ3ONZW|7vnhe2GtUMTmyyNn^ZIqc>^lgfbEevAOe0r%XNECIJf9#+sXNez5bL zhbE~d;%BB!(6Ju&OyFge|IoCg6GoX;h^Y*$_VT(Ae^6~_-FUX_mi%#ioZV%Qj)3@oj>nJlnK(GJ&$xTDYWumk}<7>B&d@Pnfo zuC5eOOpB?CDB16L@1OFA_6WOp!jQjN#sB>7hcwwT35A)8Jo}CSOwgO{Np2>_VMuTh zx#zHebQ55TMz~6O<}@1`vcumMsa6;QG-7bNcAcPd{?E|doV;) zGxknwXM%;2%AP5JP@E-2v;Ph_1>S&7CF@Ja8C!9)6qbt`X_VUQniwoLsj};P);+u2 z%FUUvcw=M0CLcEe1Ag6mEPTjf0Io_=tI-=Q6TR8cxyJ$W%TY2X4{}g~ROx5sInvl3 zKQ5L*)8jbq?!~T#jDAtzI>jJW`vS!$)$i7gA$HoP@5{m$Q_R1xl`qL|Apax~2Ax@C zcw4rNuq)wk_810JP}>u#KmQK0*JLX-H!i#A+xa#GQ@Hfe9P z9tT$hBt=Ed_-UG_ja!Wzt(;|Rx^5?wNAjo*~;gGNknLrxERy8zeJAsL8&)R)kz zG^vDhBJZ1_bLPGq7JU{BrA9^e{+m|{QB>R+5tr{B0g}2t2Ad~h=-xmTzm75A`Hp#F zT(+MwR$ss4EIa%(ilWv$7lErh2(q8Eom_|8CB!ff2JQa$MGh#K0U^t=y>8h;{AZ3G zy257lCmjj2t!iN265XJl-~tY40qFK=6Fw0BlKH*Sr18r91?ujch=uACzvjf-VNKx} zqVr~NKBz4?o3tc=J0n=8Bo?czMrur}nNP-i>({t{m$H_3bc6k(pWqGeh#erp{yQ=R zmY7KP+w+xt9{>$NC@UcG@t|_i4^M?hShk=+!|mIWVYC|3$LGPM?YpErU-NLyXB}7O zH^~N704%~jEZ;^j`m5TK3PO!gf3sK`G5l7wGXF0rvJ+N7QG~K6{iiq=FaV2i4ked=Lgg=wXi@f*FDUOB}%%P<;SH;|n3wu4RI=GVVBAKAkU{1W_D zgs6@n*s;}xnX1kMJw3XJ+j7B>{*8>MN$twqaBPjb18$;LZWZsGazZBnF^VoqR{y7# zIw6hBJY83NtFPZ+hb?|toRa;tiCLp8r&RVE181+1SVcsQ*R(4aiyr`Qk#bn#l@VF# zS#GVpt1B-CZ&ln|A+3T1VN6tqc&9=iRjK!qi?Z>Wq#Ds7SIfc^0(UgX-SN%7TTqGE zM0Ud=l#!a>0eT+wsCb@hsJuU)L9YdZ2=`ZBYhy_lBPq#eyZCqd5{Y@jY|nx|K+E`g z>e<>u=F$jR-r9!iM2MmrO7W5#lQlt>SpaPnXiR(Q=?UrMz}NE$0LPD`o}bHUChGhb z1A?d#-T+&!Pp2dw6^{}51R@#_SZu{m=3>VQFKzTH)u>A~km2`f%?ft6m*)WtWns^g zlH2Q6>&yJ_zFVHUe`OwJdE?m*ZKpzIly$$fA-JDk&QA2fQ6_ER+<=d>v43qWd}i(> zKZ&tcJI%Ed;662^NLbbCg+ffv6J)yy%&T;VbP52k`lGdM*Em(=k3%=S(om8&$7$H` zF`@7a0t%-`F$Fs{$oEURiPJv-b`4PrLcR<2iCwCmV4P9TtmSEzIvm{T&mNcNw*AX4 z2$!DP!QAF9fpj)-vXti{(col-GNT-jmFQ)2CAIa*#&5``i<+M|XE*4#6hEW5n;2Th zk>xwfvj8c!A^Y1;`hrESB=X+xb zm;L*2xuJO!>LVhZiQvs+u^zAds}cecETa+A*7%95cQ&|A>Nom?5Cj9eB_aG6L%oQ8 ze9jfMDAy@&$ec_BRdu+hGya;`e9?^e6PeQ^k?5ioM>UCx+%JdsHQ40%J(qrCZeOS5 zdBDL$c@=!PYqrg&U-P=DZh2AX=dZhcri)_g)O)zY{B`fW535g!+v| zM<%q%kE_UuPF%{jCjyo$_e`H66@I?|411Y5B4w^4K`bZE+!H$c`-uaK@LV|X@5d8 z&d4*-_@9?jNkrMt@wr<-&t|JeSq7dO?#Q6A64*!m;)y`sxJyVo{g&R4+5gOh6YCq+ z$eYGH*p-lu*t@e?2SQkih8F>(3oSo?;j;uhWN@gW4cGONzX|^mw)}x3J1PY86`U=V zQOB=8cOq3lR`1Dc&a=?`C&#a_+FM9uRoWe( z^suY~i~6Ccn^dvN98COtXn3~C)9lQITb5ylckx-YD@OC`KH&@cbU!~{f>3m`NJ4fb zz_0nw6MP?gvfGLn1{0vd9$eWqi6)AO>D=4a(1~g7f+4kaa#MsZOK|XfnhpqKPBWx8 zIRX?NjBz?qv+PQD`9M=ZqMk%7;f+W2=Bd?}_4SByS=j9M z=p-)}S%>n>&a_msg%4oZ^jna67Ew+WuJH?U8fO+85G{i-=izip=F9F}JT5+C+`w!u zj_t|l%f01tEa%VM)sEVk#>&MiEJ~B(t)2=ExVm_X zVlBN_#P{93)CJ;i{kS~g3T=y_^-VZC=H_V^<=7L=VHH~|=R7g?YDD8+i;5Ra3u#>` z=;ydxv(qgQk;%+XXa#VCTD~Z8`V!M)3GM^3cFJL1_F~U=V`yKKq~)w+ zis9s4iE9B~>}_G6fMp;kX8>Y1mv|A`7!y%x=QYd(+QnIVtsMa;rmYmgZ;KX=lKbQv zNm(P-aEbr*ilTFl(*h;Ux#e5}R8)K~?0~uAx;RyggTfdNMG^quSeUdjFf-Qvaa)@e zi}Z;wahu5j2fkNUxl%r@0f?ItpZzdX=-5SF7AB+B7t2*${BV;ijrS0M;~@$;7%nH9 z+Rl(9os$vkHT-F-l)venS#)(!u8ZS{bPxv&D+~K1N0X?XPJ~1Yc+DUO)mDtc!Ull( z540zJ$74dpi*TOux!ilrP%N0=E*KkOT*5ldT)S2;{HaaN4UmSKt!~eq8%U;s#eIM#j;?qM$8&2 zfi%Pwwn7kl0&o;i=KFAqOZM!1D%H}?BSsh8CvZ^xqNS`-W;(*27zz`6W(yIvp4CqU zm;js|u!LbYE^L|}mzW(RLM$%ZjV;yYYhVQE1s@e2>wX$xc@N+jydV`0Y%hYt><&@S zy?~@@iO+D12IEnx7<*hf1lAdq0|Pr=>I4xjwWCMIzz0`4O9WJn6(Wix8f>u()px;f zC*8@lk3%@SQ9H;2t)6wjo)7C==ezKIa`6}$VBZ3X!dwp#kivQKjC?5uf+u+*<&V;T z2Wt09GxvA-FaeA+F6g~jo0*4Xl1D2`BLGGM+5*(SgMd+9mRn5yEv?)_04i*++zyza zopZUF`+q8Gd!haF&2sDe+o%K=D=+wVMMs$0e97kpRzx z(5%m)8##x=&s`#8{CT#q3%e2J`JfIehg1!F5OKmLcLb4R#J*mSCF%tjj&uE0VB#DK z%ggzIk$_D+m*TYp5Ecf@L!)SLeUmhTvSCr|g)0$`M7&ZfqEf>Bnv$?91H~J~7>8iZ zo>;dfEK!v$=LK@F?@>g@)G~kKUTr^JPr2wQkIy>w=q6{8p*^F7)J+8%^&;ou}80B+;2vuHF#DLtlbdqmW z12yTVZ>W#?({QLZcTS&g2Zc(|>aKP2mP%OEHzn{4X<-v;e`tDCW~+YbuyZ|5C1S~< zx@EY26~D%BUM0ok+Gc1vUxtRJ2=#`s!PhwBZiInc_>Nk%<4Cj=p6+e#e|GU6$}6H6 z+U#a?$rGvFbECi5j^vI=v@*aNySE@P(dhMJV_|CHWa7>pAn1?tjQxsclZjBQaRQ-h z$Y^UYOggtR595rF7r#=Rv9(i%SF&C4sx&Inh{NscQ`@(=dr@e;Ut0$J)1X!zjIaQS! z&=T7*A=QusV>f{OJJP3rsz_L?H>Tf8)9x%hjhzl&B==#G5z@CsfV(WVXnFA$NcNJbr{Tsg+weFlka4<5B?Bh65cDo z5~%NLO5X?S(sO!6rB>26&95e5gu_myR!K#e<_w7rLm&Zndu=?;yYESM4F}*(WFOliGKN1Un4g|HJ!96P!^*fP4e$~to3k-q|Des zWrtSr^b>|Q4azf1hG({GMA$6VPN7}W#Zq|vL>=_sMq%-DiQN}6ox5HxT%kQlRv3I1 zj_ckRu?-Zm{nao0D}PmB&2bO7;MNB5w#8ZX|5I7sa9~k3 zjSApGx7Pc%n9THDQS66S z9P5#9UgK_IgNMW8{YpK$>w`G58sUsajP&jCC}8|qJ8KCYFyVRd-AE3MqcDv0#H#nL z+)9PqUD2)J#*fBE>s2$^{x4UgAJ#{d!lv=!?)FZm{lh+TNn=3{ao7L$yl3do`0G&V zHa^BUJIUBZM>ox-FZqNK{p}ur9ghB&(Xt}uQVxVGlvQLtY#_+50{TN^mk%<_II50;Sh<+X*A>vf5Nuj zEZfy{89E_!q`mGon8R{H3sJ!*h;n4f}=`K7JoCdowE_lTFOT z34krAznqo%z>5i7_h|l-_U{W_SntNb=0z>%Uiem8*!&Mh|BKSb>wl|%7{6Ymtff82 z#kO7O>JU>v>rf1?e%kmlOT6=ZCl}77;hWnl7P09nkJrPnEBD|oE7|?qyqr8ZtH-kr|gUY4Q%0rpY(^Q=g+{UNWCdzv&MhJS zGswoGE*X=GSIphbatWza%K3>FtgcCNHXnamSqc13M%nlqoYBSwLUfE)B_~bUq7n$- zw|8Bwj=Z3yuvqu};ZQ@)p|j8TOK2g`O)^G3r-$7-Ej`5|it+H$V!5?*qOA0|DRazn ze`YL6CdH#{)+VA#DSXO%$LM%vY12HIZqrdFv750p5s{%-*AQvR6iRazo6GhWcpEKz z7f_8fU>%IyXZxbn{f!!{Pckl0YXRqtF}^aej2v+K#~Me?4}glJq2FF31^V4!W`ZH= zWED}S6M?bO_|#}nGJ(8#g1aJ$f|`tyGm3>j0@6c~$VUH#Es2BG9GvnCPpOJrjXtWt z$qa6upZ??mw<6dC^e)!burP=b$gH0`tU+-Aht6^zyshT#bt|ai_*=RWN-8{aEOv;g$BnBZ~9d9n<8gzIZ1Gb>J}6O#yi>M0(UB| z7ak%RoEyd{tXCFJ3#RDl-lqr|XVrow9uOl#INc4x{Xf0xf7E`pPdOwJM)ERiZ~pGz z`R_C2136N4&%LEjlRu34{l!%AF7mgn&qY_mZyn~3St8)Ex5&)DBlvO!AH3f#O#R?* z=I`bo8w0ZFr~)4bi$=4x3FW|(a?R%|U`1}^uO-Xo24OTYK@-cs>^^VWKrhEB2f69oPRH<9)j?lnT8+X>%#XNFIha=z{sP*+pcI zgs+OL(g=mO;*Qm~xJAj#|9g)GCPNDjoD}n|2TzfjJY9-Z`|BlM;f3{~gNPy*6GOxg zC0U^Pj5(JBlNK6|UN88j^^YvK{~q}r%Jj%~V%x8>#|MI`bDP7S!eO`e-b_f?OEXn? z>5mA2;*HTc&i`QQEZ?GP-*7#}z|h?>bmPz^Fmxl`AobEB-7$1`_s|^z5(+q^2#BPB z0uCvHD5Zobo8SJj_g}C+tYbaLdhYwYt`jzehQ`B(j$R&z;-eI!+{YDu#Ls!ZX0;>3 z_eMgPu_*D*QI{^bBCGi+F6&ekG^lap+vZ$osrv{apSTja7fJjFQWmnQ)lphIbiA_1 zC}9JsDl5-Kg3^>dv5hx~IrK&BZ=)g*F{()x8mW4I}$O@kI!isMCfC7NtI4x zHc)Td2u;sot_qtw7s5;HCfEjIMtzU zzK$hxdXXD`$AM>ym^PSvaMmT&i^(B@)Uz2l{GALR9738bGF+fkx#k~S=rp>R2#ylFlGY`a!UlYb+aGbd0pDLHyXx?mu+u1kxtQmH zlCJgy8=3|jV&3?VG!96PU?BVoYz+|>1G;|qghXF7k_(SV^0meMJ!N{?{cAT6=X>rr zTE=vaHV5|xkZyi-F z%tEm)FSY!-I|L+Y8Q1t?YMJpy4B0#1*Lwk;N2l;5*1uAtAMeDIFt?@b<%@4;21541 zieM$Jk6rXDwUp)_R-$#3Nkfzf`x`RNPB9FD6B5Lm1SE7v7?g`dclf>@Wzdz58>N0( z%VqK%UjhIo_vdT>Rnn44sJbrBH!fO^<4loY1b6vw1y4}rKlx<+wXu?A9Nu&QvE>Z! z+sTi{2HD?D-2dRs?DUqKovJH4*P5|s8RCto)Z~z9N%9!V!4jh|f^FiiG zub#O;^a08 z^u~>M3=)X|Qjio4@=}9RnNA%7pJ`40!Z%HK@pCM6+m)y5^m0)_15zB$3DuYpz%&$= ziiN6;-McflvaE_u`zs#$rAmGa=^$$s3R(dKz_tdKR>qHQ)RVZ$M<3gXkeIw%Qt`~S zVc3;Wzj?3dHB**J{djpJL@@GPIL^)xZVkG|i&NV#x=#*s6|G#U6>t@qKTm8^(zQVN z=uOskLqtJ8iXnjcHnNZGUj*?&@gBjI8V!;iSo1OytA#xR&FRN zlpFFOpu?cB(crpqdt=U^1yG;7&bQP}RQS5aR=S>tS06OshVN|pY6 z+J$NgEnfckJjQO|<{G4ph$a@23fd*uzL>&ohZfz({`@Cbp=BYu&14%9#2?8U+R2jU zA~TMXN*|*$QUUJ<1*@3(qhlg9QR2rziudJj{lStDy+jB%sn(pC&U|5LI+tYYmFK_0 zuor0DPkkQXVEXI^Hwm*y7h!ugyl9ju?PU7rgM*cJMrm z!_{vsh;7|P^z~!}MT0~a+UgTDR$49O+)|=G2fLpUyh{afs6!#crlPK@rsNb zzTDkW?1!NMVAwxHn21J9Cp2DDEZ&&MA74MD;oL{nPEec&Vk!zbH-h-PM2|>7{QaXf zux4ymzPP_!VnocmU1LUb39`kRJk)6oXt|koWAqFAESo*IsM>aGOTGtMZptAQnvQ$@7BDccw$D(R6+ib_UjaX zv-FRLNe14k1C9Juzv$Z&lUqda`ymzwQ_1DDItHk;JxR{17isZVh`H-D+qD!5jp!3~ ztt=@mWzslRL;@!`+WCw$i91lO3wO9r!|*hNurUUviL=tvcX*o3nRkWy*25P|ia7tt96bh(eN$;1X&U+*9eyF{r5 za#g*v6~5WLzszo7&$%bYlh&r=9ynDn!Q>b^7z`#R3f-`h35%_Dp^NpVD>Us4oTe2B8Hjflg@n5$$X>@MF270JY zu2dMl6T2CdF5ggut(>PgzM9g~tyIYy5LZ;%)?X?CNsnAERRJW2)H`< zlHq#6cxE&o>8}@ABGM8hA^7^`tn8401<^KefvQ~vqbnrpDrv_eT+YqK65(TR$lwAX zNR_5uJgvAt{l%;7&upx8*b{L1oLi>|AU=M`+W$?cMa1 zxG05xCPPJvxXd_`%9TK9Ol65hrUYd*8-9htH#1VZYV$Y;O>;CO_4Mq%7X)n zpYZbb-i2u41lgd7b=?`9(fTPI4+o)G!YlrLks1SOi8HCp77b}?>4wsA6D9XlBrmu| zTG9N%$`+TgA(^E#3lcSremc(;YpKtEX`J|~IjI?Er>811rrdU2rjWhKjt^~W7o~x2 zxIbSi%sqVmu@L7dgfR(8zZDx zq$u5+a~9D$Zt3y@mJd*(LZjQmx`33R4)QJ;dKhf6ioq$0@R3=F|>FyIG-mPmGxDQj{pe|=nV3ORcEs%7ID#7ejuH$3MgVp zO;EOI3QG~+8nCLI?z*t=v`0O9;>s-Qk|M6n>Xg%6xCnH27P0#yYK2lzLBF_{mr0kI zdT`TayB0xi`g?9PlRp^bDD?8Y@rJf%_4PI6RnSxYG6d|Lbtc3iq%Z(`{$4X|JC7ga z@lmA;yg(U|=b74})d>o}sZs{oiq~C1pBn}Y+D%$&E!LlR0>DjSye(GZ zQu83oTo4!uG?fGhdwad`sNA%|xeF1un$Fes?y<~DKxuZhE%l5LFr1tXoY@afF5>(H zgwLk37m*LG8%x8H0M}n{n9<&*-u)7;l5N4gcJly}tl>?W7T#p)`=777^iv0yQtU6Z z-w>OZcfx`AsBSzX@q9-RB>=9mcXd4ry=Kra;^`i!>Gj?zdEuOIzW(T zO{nb(o8-J6$aF&aCrm-Y>{(gINs1JRl|c_sFRL|>)6;YzuPxfNC@nZUY_R1lmw=Oh zsz@@&(`*W>?~|hA7S=**NWh9wEG;w`SDO{Wp9dDOzrDZrFkNwN&_K%mP;MCFpY=pf z7$T;R&bcpKr$11Skk1me=y*ICs2bA{Bs0BbI=7Zclx+skm4?O39 z&A6}sR34YkvX0I29?!~sg;;0TUNXLauGoA>#Y!6*w{AVdLHfEt=k1qp2n3#|><;m3 zP~9tr2(?0vJ)uJbkvhk7d3dztvV#>EwN3l~u3JCI2E2b=#QMo|#>x@wYBH~m1#+Y2 zx4-3vQ7#d-sVaLXeAB_F91^8wQhm<#L6;rsqVv9E5Td;^^-pIJFeJ{7TAWugtW`4= zATnk#iE^V&t>o|)maDLI0;#{w_Cw@p6)wd$4%|z6Qi~rfi5i9RPESMeSagE@h%74A zla|Tng|z-N;R7Mj1zrlZ z&&X%s;=KMckL--6^(t2zfE^16XYfAdyU29lMdG4E6sX!FF z%SmdsE(#MYMf3F|!Mi>-xm6m&MPQqFm*}TO<4<*J5Xvkq5p)ne60&}sT?wg;5cvGs zO`HY!@!uf(__bpKA&jvXGDFT%m-|8aS=pcP>G;ugfc|0!zby3alihk>6%3H8;FAo( z3HLJcCC?h|WnDl0K;(RBqN{ibTlSah%=_dkKSo`$j93Oq1Bxsd!%tnR37eT{Zdnra z#%u)SgRU#>q5sNBuIy#fbQV^j6B~Cm(GDd60oFaG3BT%YGuUq%p$PBFwn^B(*ci!5 z+I^|tTpj!9f8e(>=kiv;B9z`0PvFOnZ)z3%oI)F~*|1S%vU(Q=T77XBsPP`5=%oWg z0PmJJ)FSsdEB4@>k*u<{wtFwk2XSSlb~bIM|Av2zV#CKkNQZRSDSmuj&!RHJ>^}XM zX)i?RD32BHeB$~K3}o~Isu|@Q7HI!a9nk+O9rD%oaZG~_Q}u%lk`q);wv7^!_fcn{b2=1JUBfP)oXzj@E?)u6xaZF~!1p0vkZw{Skn zYEWvL+aGDmYZuC996ki|Y4KuI7Uaz7^_{Aq)=G#KPKxH?JvHdaX1v{*Ge6+Pxu5olidAJQm zd?4O1^!{0@dlKca$XqmUOcaOw1={*|k}K~7_cmh;`F0@xeWdsYV(wHdi<=H(Z*!nm z-!644a`f}oRh=>%#$#w4GwF5_-?s=WobAOG_I$b0kloQ1Nu}DWg z4cM}@rp?{bM-0;k|-q;IsXtLN}#6+$iKVwSF`0d&HyNme=gU7Dn0hOE8gWp1b zlK&v}XWiE0K>Y&QnaHgvNdPF~p8TB8DCrC@QcgQddy@dx+r)Z7qK6E$h*KTknY<(2 zXX_qtiAu!lcNDZE$W};wFaHx)@pnKR|UWr1;&$-2dqQt*De&%{gN5GT}Lo{j-{$%y6|JPMMbBR~}Vf7_}b&YV^+++LP(YbUmLxt)e#b+fiJy1Q*K1+JO z>to5n)2sG}8KnxyEH)XjrC6nq{`%48!RDB(5Gi@XnVh9PgVbaqDUtTa7N^r84(6rN zaSkk;G{FC6?vrxKD9GTPnzWkalX?`Y`a4c+PhgO4m-p0~bQ4^;P={ad^{aCmq@LoS zgp`7LFrqTzw1eo2wr|X-`l(LKQmKwboN(n&ZI?A;nRvD%|IAyQjPi6VWj*AzIiHbP z=;)1^oH)5qzblrP`N;3D1;vfzUPDEX0GCEXiP`lYn>;mX(T*f0GovL90|| zI{8rYP46V@P4;&dJO&z%>I0}(jdmoMB=T9ZLwtDV1z)wvyWg+gmp^s!8jT~qzb{{F zP43-TBq{jr`=SFjHAxE1K3ncTDW($va1FWNq1j&uzWYtQ{lq2JWFSBb&bZMwxq3ZzAT%chbdRP3gAyg z-d6S9QhI_Uz>geb6z+X{Uf>;jE5R z@wJ6u{vt@2U|ty;!mfRWZJ3ZErFUxMt6;>Or`~&l>n<@dhp;FiB7iPR~nrvQq<>6795RQ+T6&a(80ysNkgo*oZAK@A(vcLAdmeo5?- zZQK2I`l!kQZG>L;Gu_m>O3uMH&TXE#{g*J!HKLE3B&BwXlG6EYK`bWganbf%jpCh8 z=Q^db4d_jB5@kRpj>XAZA@~8CI-JCr=G;O$kli%#1cF-1)W+E@App-OSKdR%QKzro zWb@cqGF#eh^+I&JslQ_{fkR2Mj+1%H!t41?7E4sG-gfm^Dy%9oW5<;nnsfYAtb3?L zfZO^YVSh=llb0!PC4KgFAS)zH?}fq&?z8?q_iAvj$AH%PJKi@(S=FT)q0(Z-!}Q{V zzvez4MYjRWle36Gy~oKuYT@)_i3df=lb_|seYp`&W8??DuW3Hl!-PPY3oKKw>v!&5 zLbjhL)@5yOa$8px)_$_DDi8f!)n+I%&=Jt?wfIxWT>My#yF6qMzk1(>tC}SYrr%LG z8v3H_ClBiO&9zC`ez?LwtN$pseA!?uOxA+=E2!_KvbR%&eQE{8JiPl_&OVYtVDv8< zgWh=W0v{6HywYeO=O!hkhOn_x2F6i9N9O{3*h+Ei%?Z}sI<FK<_xxdSI?KZ+wxbfm;CRnwQVmc? zI61_!(W$5C#kKMAZCi)k*$cEDsH=%{r){Gq5FqKPQfq(&{@OZgIZ8oNqLJZ=_YS*C zXPuh65RDNbE%U`%9Q?>ou=# z^%d1mo?i=AC~s92&JEUCp(HOhFt2mpxYjb4HwwyYbQIKGl~%Vf#D`@i5{U7}3N~@& zUGQ=LntK-~O6VVr)cPtpNc#5atVl`rWo0k?G=|L9u(XQQo?=iM$3dv7^2eWsAy5e^ zFX<&L9R{WN@s;cyYhsmZ(MVuz$V`Z3dbJijUUgrQg2(kaHPf#{_4^J#J>Cd%d`9V} zzx~~Y(!F^>r+XV5;zsXEKIJh5#prqg$)hp9&Tc!_3}DC8+$l0J zo!?9yF@jftdPUIe6`+bLw|(+%wU;TjCxpqZG=n~2bkwklV1;R29p2}2roOo7( zA?N&VBvAjW!F2*;>bTMBT`$PzzEWfu5Lx@O`wr-N`xT;}q=cv0Umy8n+JZyrNg0NS zpEAvA<3qu6(xC#7BJ<;eF33@H9vFFQUFBHpDMbuXjty3##y+ZN36sH^f zyt(HOnwKM$fx)&qalnVrl8}<9`1&mK%VGH?T?nH>ks{=i`$8!->*P@p#=R?S+OAcZm6Q>dTldztEJ9TFOHTTzNFYc7evz?NGnt_;6f8$Obvw{l!L8h;tGSV+zQv4UeTzw~9rW&%$?$>JpvH34vG68`!zlfS zreD!tf9rYGn+grYSl7duJ%v4<&dV#b+!$AC=d z(=GpQoVP^QB&f|3=OD5iMXmz5fe|0BfZo3J+~5DLb%%1Pxvk8*YciJBzEE?&wex9L zd0o2wqe4PL7?jMSr9{$pw3MFqIBT@l)(`Uhr>rR9<$?nosNe*#80!JX0Tc?uTuiUl! z-Jz+p-%G!&8OgF_0&*O1b>d17$>9$g(MbQ4=fCesd9M-!^x#E}qGiNA`8VX9N7GAM zik|^<1GTE}ATHPYWI!_{0S6ii3kL2%)IyOjjej*pw?OqPU(Ymo;WJ^khs?Nl8vEMm zHG=i_SQ-fViFW-LYkrQ2o5!mQ|H;t>&?`udWz%nEr?t*fcCcVCW z+V`>N*n^1V)pOR0pYT5E5yqXcKPP@sA+uM*pzEGA-C%847=QQm#Axtf5$W&hJGjA| z0`%s76S*z3P2M^3-EAi{Y(o-x_4*MG-m9M!T4NXC)pwV>*ItBw^N@cJ;n0j7=wx({ zkn`fO^G4R>Q6zTg^e6DL1L%tZ7ofn8?;i%?LJLR$;LI(t83Xz5xYrzaO*nt|o7JTN z`PT~zwzIq05&&cx}|)5PmRQPz~BV`e8{5#-Yeniz-=B2 zZnn-ZbRq~8*l>se;NebUYVEJcROotCEg}+y0G!4Ep&uT>^~WAJ|6Gn|oZbExi8bY0ATLLO=>bJwVbOKuxku)xg2H_~5rhi*7{&q|kU?+2o}ta$Mv+GZx1h zOT&t#h!@sf#y1G|Fv&Voo6js0a)mlzpbl6ZwRYHYJ@xNt@4Pvh#d$K>U7(cRg9MI& z%oiwy{k=C0yw$+D0aLD=;a=C~?Cdhl#IezXfj-2JlLX{l4kD%;;4f%6kuNz#7sFF{ z``tE^IUF?0#s=SUDvA;qVEwre zHy+-Nuf?l#(&3x|ycl@_dk$O-7=H<&xx~RqmW#(DrsgZMBO=0`EAlHgemaZg2#3M0 zityhH(f95DDB(~QKQZkkgb{$*uv^r&mRw^8yyq+Qja*`T;j??R+~I`rov)~1gX`m5 zh$#m!l0quB8!m^E`fppb^{n|*s`SEAU0E&*)`e{pCPTt1+JKVjo<6_;{CYt8rg5NG z7qYs(pd<>hX+K8d_<}`0xkTqLJl=Z073KHS(ipd8Y#zbQ_JFUJWHm(}Z!01*DfFuk zFG}ty6xH2BEzwNCCyKe5)Qrm@AJHglegy?1pgUG6b_vXgWkQ0xWqObiPO(n)i7H|; z`u_aDcdOo_Npj~5y67ysQBI7n$;rlEABs$jMUK%zji#$vn}=*MN% zjZ1Pht_hJTq3%n*mJ#kmt|ug(PjZbp@cvUZhpRo_7GQ*{+oaQ@xm@vRMj{SR78KXaH|A$9;9?I1b5WZOppA_mTiN>Gdb z8gax0QX8&lB#P@CuQ<7#ySOa^r(QZ}n^*#g{(%CW^Qnahsh!fRCW!^6&J&%u^VptH zySf1MdtW|Hp?1_IbaU)|fJ)t-SG(CH)u2BnsZqa(GX$RRKZ^<^=q->JxG#7K5cC|V za+x%hsqs@S4~!UImbY0Uz{fr#3IfyGc~u3tm%^S?CE97KdS3lDt3&yIpnm42Y)e=8 ztZmQxq7Kko;3sMJ(s=&^qoku)fhYg!^Dk7kF1z_&Zyo56B65Y0oJj}P`j?cmSiPWt zI*cbypv{Un-yxyBtcT0fz^2D)BE@DRmEWEbdjv(d25H6zBsvOj#JWiR#w{BU-CPPV zQUA7s=g0h3tEdm`9TZ!A#h_Cd+Te#z$sQSf#aqCc|LV$Dxga0ZMj(&%xx4a_hew>4 zzKj9ISibiW?33G*jNJ9}`3UxHBM)aa4rg_Q{#%W*M|0leQZxjXxeLnPSfxrfnYY zvYjIOpD1oH6y@*Es+>GV`*0=EyN-_5HrI&nhi#Z=SOGE~%33T^6)|fd3)<)?8tzMT zyPLJ(=(rO?Z3wMh7EXxXN=wqw8sX1tN3$B`t)QL?Y-Yo6fB;>FdLinahJ#L9?&p;> z!JTZE5eCY4bppk}G>L$W6eH^a*nycqy_B-kjl@Lj!5r14X%Aga*ub-xb$a3^J}Kuk zv}!V$H2q9b@d{NwnoelV46pLHU7>|Sq;%w@N2yPBX*?yT=wAbvP^zky#Sq4ls$#+7 zCX?#aj-O>sc(kEDr^IBd(0aF5_0Mi=wQuVK zLK~iiRt)j~{~(_Szz@Izqy_?@_n1m=4FUShsaoH6o-&z*4gU}1lc?G1{J$XIf8OG; z4-(JQU`yTqSlrGBBR@z!JyZck#Ky%Z7|A}3LOlsge2{orJyw-X)=7=>$WRH+sYJ)h zY3C^y6lxWxdQ`QwS8G1*QfVk^PSY#vcs=M`qu$l6)KH+^*RT6Zsbc8;ob5=R!g!

c=(TmMDE4z#e}$URYe-KUn*wL-)CI<>Zgr8?~QxJFLQQ1&r9) zXJ6s%yv<5`!v<(DSW28L!(#<{aW3U|R=w4bV2Kk8isU4nFy2bwk(C40H6=r+!kv-l6x`)O6=U=<^B-BDfBZh7#Xu+1L{t6ptU6!yBs+uO1@E@0Lv_r~4Q!OS& zDDv;M?u@-~IMb?cM)}Oh)vIG-|c5A&^S7XYJC@ zd!O5qq55u{KRxOn5(nDN2#EsyW<@efE>_H4Y|iF1TmvmED4CV( z@gxZ4E}?{k<)988*|cUd0|Mb#Qnuyv@nvP5)~hPZt0Cc4dlb`eL7PSW-gOEoRP?$) z@F$7JfJFukGM^{*ePp37?R{UwzXzj4EEoYXNML|kX(&wN@uB?Tp(NwgHM9xg;ZBm)e zI9%e97`nR=;=aZ)ZaZwM9fa)_rJ@qe3ff;-gJEZjN}5J9Is%akCzF6fU~BgaDXN{0 zWS!=Ug1%>&SL`6>D8M8lR7i+iQ;*JuBW7_E3)nYeE8LQbn*rKE#qUO-5(DpKLk%-S z26w4$l2nntXSl8g%R_Pc8knIP1eAPK&Jxv6FW}`WL5gIs;A~cw&I|<5QgeSZpI{F+ z#H;0~<28eTO=P<9;_tTS#(~-g8_K}M&wwL$^o&ity6gLTN`$8J*t187uyU(r0?AZC+1bwwJVzV)4iBFm57*ES1yU+T$2Y}yH;)>xML znA}Llaa)@jDpCV*1wv)82AMJb`Rkv#ANB0O3gpR(&vTIk5^$rEc4Xkg*hVEH#ejeh z0R0hbYhV?)9IK}DSSv#H;#^I#QArbo++nj}jYMb0&E@61V+hwM$Oc8^)~xTdRj=BY;#=?k%M+qQ8ol@C4wbUUY33OKLT)qF{!WH4Gg`Xd#({$}~F0g^Jw#@6RVJDnltxP}* zdqRc7GALxEdg~XqG&?--X-A420DHWH!a#|SaV-IWKP&u$5AW9N^(4cEEfPZ2i=afz znqH~pkC9G9yC^a`;BlbF^(D^m7&~|P`e-4DK%}`a8YRRW9W>mMfyu}zX4d{q4d6in zD&ZS!9_E=cCL&3!NEf_~t8v50j%1krK2={4=+QxKGzmPKDKg|a)|{U@7>*}QKsXAL z?&iZb_e2X+HF*tBg>j;da6Iki0*HYG_mNpBLvA~~`pB*d%}p16FfHg)IWT?K#kF~R zt?Q5LMcvfw=MzmC3ex{JJDO1XPQ&629R0@)r8-|p>V4gmZwvQDG%XRB`VC#3bn<(SwGObZ9H z45g7Fo~pV?hh~uCV-ML?5*2X(s8?^+#onzv>VDhqI;ec&Nz;#nUJpwWuw^+!-miYK zSviEZxOlg)4pId#zI34+_Qrwp$rSdh0#)WYQWA~ICgPt?R&v%} zA8AY-HwMUh+TYC$hvb5#pr#$@zRxuS#R26kB8fz6yP!>~?LpdR{fqU&$sbSY8Rp&v z%0^nC{Ap%~KtdWAu-cQ`g*TWBbP#apkJkw`#qCja57U?4`Z#aJQEjDzcRMvBP+A%tbl9fTrQNy4*mcKBk)4S!RQc&wpQ4}v}u;u6LK%oXXCC_`< z26yD_Ym%^l$V%9DlvcD*Pq6l*=a%~(wjV;GcJK6`|T{`=9kb_y~vUui;bx6dVI0 zK?U*AqWmOLtN@_?syo0m0AC}xWC@j_6#0x)n5@x|A_?!%CHl0}I}9kuFvXJ7#XM^l z{^K`N<*nH*XXtH1Ov62Ji))m zP*z{#I?rLqB5v2Wa@`JbkTHfp4Wd+JV*hC3&Zy)ZIB7~fCP)I*BoUM(l?pnHPfvP^ zp9P=**nu&C``p8bCCB8b8i6f+QB*Yh(Tad?lF;~km?jSsMIh6`JYQf|vT1h;8&CZ2 ztCTqNr0%37Yg$lWQfhdBnSef6SRX905+QDyEZZM2?n=V@AN|@6Y88YuvWt78oZ_u2 zSp1+kRFi597HDn^R6$$BXvA|36j zG{V_0lT-ULDadeE$gI!Uv%qfYJ8$I;%%eh0;_H3`c(GZDQbFRUfaZdyHUC-4)u~5Z zM*Qp-K0A~sxz0{j5)0ss$~JIkHj)bjgs0iST5Gi@P#clH)Istw>3{4UQwnZ%vcxiH5|3iSTNR^l&` zW37*Pdn#n`i(8^Q-x?;0XAw0W2u>%J1) z8?B(M#+j!pf3uGlKUVUQ&UWpl^b^eH-)ea8x2$dH(A}njcZrI-c>%zA>ErdX_EXh+ z$ppu?8#Ind34BkOC))4|t^hz+!rxVzJ%~HsnQ;MtOjjWa`USN?XmSe!Tj}a2b+JTR zWiQw&(RLby2NkYTg{1V4->rEJJ0s{YRaZzbGd{noxp(3>FX3suy9+Q6AKI_4TFMQ* zG+BzkFH`fD4s)!jK-FYn%$3nK6e+IK>_QXk#Q`^YSrWAezeO?mmBmwLZJNOk4CE6T z$nOAuUo)VRegQYC;I%X;Z{0}GQd4->H_ok$NfXcc6{L$M(yBXK!4j_I?o7B?yro)rXx@|z+Hm5hmzp!jf2sNV$DSnCXpYNVtc;pBr zt98OMlc(^F;``ME22-jA5C_Ylw zFg4z)-%q^alZ+OFgl<#47V4i6sGHYYhF|LyikAfHQ3e{(M zy3#0DRmt0-^AGsXbceZYzvVGVd_G-CKa_jEfBPCF)&dyOPAJ+h(S}JM>=Pcm5}f&? zf>NpZAe&ar+fF-O@20`~L$fPVR&w*tP*+P=3m>G*WBC57cIb*E>brJ^lXlBlDPOe+ z+uP3seSyaMvB3CV9Rk`ux!X6Tr|=hs!luTU_2WLJEQ}fk6Zjh}@=%Ls3W=x9nCk^m ze;<}e_2FN%L&r27pK|?vC?8WB4ak*sYvwZrLdyl{T08L%6yeBjde2N^NMCK#DIiR{O+=6Z*|BeZ%cdZHZnN#l z-Jb}wPU^OLFc${gM@f@3yJr@%LOvk=Mo zs&L^)afM-@-*TkrDb3HuJf2d(CaGW+Y}204e~LGBcexH9vE@|=G!i$jdVfgzIMxRi zOg2AO7Vrz4Me9A^&1pp@IX5!k`$h?;B5ks_q)|9@!K!RQd458V)K?h|UesBf#mVbQ zS&S-rZ=XU`_yUqls+5>T+Vgdk4FEtO!1vO+%EZ{zN{I1pkDb;#>0pZ)P5rL8ya{zd z$W9oJ&gQbMhRZ+t6)Sg7TY4}1BfMwS79y-mH=}3|8_7f}Q!z0eQLJTbU2!Y<=&-ODh{IQ?Z8{aSPZ0;Z zMvSz3VFGASwP{ubQeYlbFY2oN!ZV@0+NcF|I*vFmWYH8Nxq)e70!BUSy$er|CHh>C zp#Cwxf~&rCD=Wu={AjTJd6)=DIqv{L0N4Rq#dSkfvP}Z3zRJ&Z)H^Y%=w%&mcTGg& zA`w;%v)V{BJpb}TTSU#)iNZbAA@SfxC?o6iCcv2y0w6yHemnUL$8NQ#x>m=v-}KN<~zjiTFE*=upeHZbsueRF1Fay*la^&3#c+gM8zz(?3olEt_cul zFte=<%v*;eBcNbR+4=Lj@+n3OiLLF$G5vvodOiJnJH-9Br2Nj$(}3im@1hprobZ=f zK|YMyOM!YBbTp(%mbJH{3LNGY_nZA#KL`;kgIEYbAL)R80$fqBOp;*m>}KiOQYR&fgu5MmDG0Q zG~#1fy|}#mgl?L>dxkhwj(H#h;%fo3-D9d%_jE{UMv-tDq(SJY_5n1@c!@pUx2E?` z_uX~Mpo?eET2XwTAY zAb!2jest!7d;cG$8+r;h)9+e@(GJ!Y)q3;|?@j7QoL}N_%MhGA<0ro~F@Pzm*RL_Z zRFSJq!&v5i@;_1#K<3HZ;;tCkHh0zUqC?-3?n_!Bpd{&);nxlr@(H}|J_)}O=GRoyAKU;E}A9gzmAVcIg4|4CmnBiPHk}^3RMUr%Ec^&5s`VqB(y%p zm`#(k^WOYJ!3-5S-2TkdSfX-)eWGO3_Fl(lz`B89>n!AN#h0rutk;ykL8q=sB5^|0 zkKzKES%V^jdHDI`@wo&;{=x4PgcSbLpQVsTWw{nW%J6Gc>H*CUA#J=@-tpGsqe@Cn ztQ!Dg2D>X~$ zzuS9fFKg!KF!deY5Oo_q6TZ@(G_!a}G9}pS87l%69~*vaJ)Y07I->U)5XF)8;!&ew zTo^eiRhi4AC`=>YQZz^RvylcHeirGV?gx`rj=p-?_^!=qo>S-i{5xk2x=Qb_rusvc zZ)0D}GHv8Vs6&|(VtpjXSoz$@>vf}~wia9+P2=-^2A674b-z<78|k|HZaA9RrJz9| zoC}Y6G|)2Ap?4+|{b9i8zvG!9+wC9nv23@tvr^YftTc>9ZJ*xzcJF7FEP09sn)@ip znAcxd;U9C1{m2j{PZDfDH3g3-kt#`zh?m=*kj63mj={xvsBO~n%p)6b)U58G&M_Ua3#1N)Zu7DhKz7j6p|_W3 zB}5{31vw`M{A|=f)cV|4BVQa*l> zn-|Ngb5A^MqX+cVk)e#rxQLD8i3Z&=dK0le8pnKT+>I>%WoeGp$L4 zpZ*AppZ`N_hbzq9Q4WYg#g7QKqNCSHzVP}?7&Y{sbsFRtu-CcW{U(vTzaSNI{h*Nf zxoIGoXQ-sMfZ6<=oH@-v+NymNHcrUxt-kWuz*~>2D4MIG18gc<5lBu=j1JybSr61; zEW9sskgw`f3#}b-mXo(mB>Kdlcmv3Zaf~PVFJ9Sh<_`1nLT(rQt$XWs&!|n6F$R)G zHy2rCuh78Lp?>49+`PmGb=UJofDsk~Y7QusR;IR|38T00*ZBk>S*z+4;j7%JKHq^Y$ zO@NgOq)p2%m84=70ZRU5utQ!f)uVU$AxfRc9MHxi`j8fveJ*vcY->x(hF|`jczeK} z4(K@f`?NEN#=7P`1c67lFTg;~gSy)@e6#{!N~2vKtf5V<9V%97g~?X~Q#dqsrQG z3TC7vOhzr6zV%LJsiz45WmLvh7)U0tyeOej5tAEkd>9W2@l6r@^RBq;VcEBYgZ8qQ zi?3zfn6FlG-A#?+jl;jeUub}E{IRq?jbQz7AQ1OjHz=s_ztG5%YP9L1O{#;Vfn4(w zKo7DO^Ug)HJVjkjC7+JBm5=Jh0B$tXks13M5<)7Q*m2GV8X=vc+t^uRx#Vn{=SgEu zaFZjmUgR&`;~;m_M^U2;{le$D*>#%DTy<7DAQ4kco!{CaOwBU5m=Sza)Y>?oDJ~a$ z%y9`#gZ|D+nEzifOM>)T-4GS5LQarfV?Ku1VYd5?^n>I5g{9mz6^Z6eEETR*IUN?; z+yB1J>$Q8#CQ=t3S`=-daz?Xz3miV7JW`e-xL=i&mjnpX3Yw`rIIYIfP{Kpk(u&m0 z4A(1?_P>x|+!?m>0-CN(=u1X^~C=IlO1B zv(~%T`L;hjU-pM*|MtG_>rQl^jvy1eNLgC_DN($>di2GunQpN^k6pw1rw0Z}Cwdw~ z#1FA!lh+6kM>A<5ly3HAfk!+7X_tvMJ`fld-(_o}DZecn_oCt0iUI8DF_8IsaZI-O z7|#SoD?tWr39LC1Dx=@{ZA$9z_NA31Sv-o8AA@D}uN5@h$19k#)E*RE=RYuwX^gxjHhFQ~Guv-@h9xY5AMmYUP3uhz*z5N}>85FV-qV)4cf5T@SIpq( zV&oHte&mz!K*$E8*v?u6kM#5IZLH(?hEQi-khtmg4FM2=EejM_c z_3v>he`TRQ7x3hx8)kupT{Yw56(^(3dUV2*F5&m?r^${G5Q*n9va$ z{L;f|kH186{M4a4)|+Hg?2HXgymhxBTRhd_>z`g>z{4=;SLt_(yJM_M8C)hA)ptUc zB*E)vUx*aPhPEZF_P^~g7j1LiGbXjNRIZqZgdGHJZ;zi+j{n7&^CACG$jBKQ9$2}s z6KvrRA;C{%uBQ;67?Wh8_Q^40K2#B_(MZ(vf2B7w>7k5k@mWShw^a#52}o!c-zYVr zz5i%Pl_!`vPB?aKjjmHw?)JWvpf zgc=DXWR2Oz|=CT5kvR=iS*g;-LqNIh*Jgwc`;1yX_;V_e4ht zgn;bgoe)F=KOVK^suIDx{Mh)JeWz(Y>JSAt8*h60r+b1^Q8+hzW@X?0-N7%2OCd$m zGj;Vn5X7{S`h;Y-5sMC}_xOnfJ2v=4G1#lK`O85R3aroe4d$$vW9rpLNnPAUD$u zC;d;L-qB{R4oNZdNbpR#0_OD83rpK6LM~0rr-25QMx5J1JcO?sdhkn>pNKd@VR}yl z{`|qI>KPz5ir;$87wA|k_3<*X@7p%#Cm~z zf!=D6JjM>JU&?0-`ACA?kEt`zo9G;IhQRQ@DW8gNF%*=tSMRcOc++BqGy2Vb6xJh2 z)w458<2=(=xRzz>PGh^8jP(%+?AmCocgZ23d$R3d=m>BGMy~l0W2qg-`^u`nE$}z}X;r z=y6gXS%-6JO&j&@OaYvP_J3NjJO&yeKO~TuTl=VIX)tF=AAa2?;xw(kU~fe=0|Fg+ zEG?MYf$*2(Ox~+ZZ5jnqns!*p^mFWv_Vd$Ve_TD>)<2L`_V4>fRkM8mbu3spf`!3?FnV_EkOL-mPvpK~knx9qNl=H^7k zV)4&ZG0)g3IzbaU8zU@X{ptmp`WfN+@)d~&U{j!@ua1L3(VRikkan_xfsdBOG@1E( zLn6FvPMfzc^V&4>z5plEUPk|THq-G45juOgzE2u7G5*Dfw*yogl{*|L#2b3MhPD#W zmjq@#gZLsm$;mI!=2V>$MZl6T0$>#S)i(p1r|)dSpy00)^_v&j+!$<^YAosvwSF+= zlei~;J0u-4&EDY}%kMtFf}xVsb!|nrMg=lmI#pcsSa7ST?r0#Y!;oM#aMv5}+cDNXT zV?jd%x$|m8^L{2yo_{Vq3{PL?52!!GbEPqKy}$IV|NYyIlAi(w_-ZH#jdRm}3!(3a ze4S6E_miiuCs3PL3m_|4`#wNzMXF#2YNw z&hpi+0{vC=UO+qlN`EUL_C|!tKi)>S#myd@Ra|r3KM|l?{N00n-rIWLUE%x-6=!|0hqOV3S@?x?^(RWim`W=3NDM$tOEG}yajTD9P7Dc ztc~Qwf+H6tY>jkUo`_erN=lN5hx!G~{m8oHNx*kb_{=TWKla*ii0~`S&u`J2FK4GF zJopzXZcH38a&2}->3Q)v!%lYVpiXy{x>IM&mOAQ*4GxSRk#j8moCO2)@(U8_3X%c( zl%P=fc}7#z8WLwU2deRW{W@L-KE0%$*q5T80wS0dV(5`E=_7@~)=*M3vWq(9ff@x4 z5W;@AL1`~#794k{KQ0on%p~X#)>s|B*_s{*&Tbx_06V}=-~i;sYgq0@ju^OxFX$W+ zZc_Aa&MGw5{-V}3nk|nUvFij;q7@`mSDx!i zo@u7`1!pI@rbU_Ed0REEQwyQ+FU4t&J*PA}4SUH_+d2y61;42c#7q?kmLV*dF}VN- z@kJuN%TjF#o%NeCfxjNB5J9v4toKjj5~x?m{i7=gmHwF~@X=J__Mn;3?}=TZp$&^z z&rpGjx%M4Z?)+J4oMetiBQ{7NBwK*83Oc_SxmlqEj|2D#RIpB!sM4bMsC^qAM%8jV zc#9-KUijEN$pq##b??lqTkm3mTc z+0mB}%~~(1_xd9Ut{|bfzpWN!>EOQ=rpO#VHeXVhmmK6p9$iz3)OULHV}tT=1(4Pt zsH1YqoZ_YiZ>9IcU+f>+z3w9dKD~WA4p{(v)kcmk5xR`^6}e5i4A%$e?q8VNv)+G~ zy&}CcO*gRqawAXkl{D@89zwu?Cje~8&)1S1Du}jbp-0V0F)pqk`RPAe0K5)tAdkd- z{@wpt}uS`OJ{beE_ zPhf_RpZGo2T0&p;wex8XhoLz*_?pM;Myi7|>gY$Yj;5aQO@^|QVgcO;>ABx(d|>KA zc}q+&Lm_5Ez9$iO<-OhVuW*D%zJ7adpfE6e65Na%lwtXE0oh7Ex~l1em^_S^!m;L8i$~4h4W0ixy7+*v!S!5#QY? zy~+jAOZL22?6DIJN>`F)KjqeXZefG1y96#=B8*h)?_;+-Nq$|UPn|w)bO0*Y~Hrzgqxt{b)upZl*0P(8I2efTEMw6^~lGBT+&P|{65#HcLy zTWkDZfaE<{`bUBqDiOJUijp>>p@oyi%DUtup05xf zEChhRLY0r2C<1zz>eFK$rtcegXkzp9nH82Z(@G`iDxUH582M+N z=->~?_AlY9wwrG`B%t4?P5|>0iz`LIt?b9=OZm}3v70Sm96bn8+O^cb7vyYhpEJeF zXOZnLA8gu|dBp;|O+IZ1bi0YN4w$c{?Su}kKP(cY`;rSQD)(!Ho-(YGKOqeyW`iaB zFzoS4zLZl^vw;?xTH0jWx7-g0e4LtFWzfABKE1d{p~ML&KI$cn3vy{JuWfA0Ih$#Mlw|h;!+z09{Y}qk>Uc61AVR~MDp+zU zJECK3PDNt(%&i{8_%;%s(+iRBjV1JYJu~GACx;6vPQ5c}i4hRWrc>kBq>~VGclTL7 zf}3a{oxOuzBfb`&NE%c2f{_!bxVLzIxV`DmOwZ01tj*~gpfJ3DvD zKeg*}fQAjfy_}n)a{pA}H=fqx8?u^ovj@dw-<8h_&fhyhON`;%S0r?GMl%5c*OA*K zey?8ZIkRunLzr#;n3j7{PLCwGu4}!1c9Z?HI?ew8UQMW~5gT~JxFR`YAT$_5&EM{2*i5d9DMz4KzHd?nWIfv%~%9RXJwS)Z`Zwh-zy<2M+8!jNX3RcDz zT*nnF44~9R7YDKma|{^Q46|EtX?hu!#4N<0jE6EsP;amSE=QM;pJ?Ke{LgTeOhAN; zVzNtF|%fua3eq_dvX5uZ^tyO>P7}Jftf>?{wy)E`a9AXD* z&X{aA#Fi!}5Z7andPh-D%e2y8kA6H#DnPBum@35k%NB)OCd+Palu`A8aox+cLp9B;RAEwz2qMH$$p2Wx{r;E9v$amZSzh01DPX3}Fj>q}_ANnAfd; z_x`ZEz7yuM?wWRRY`E`__uMJ1j1FD!yoX@?hN9t2m+qkB%(CU(ho27F_<8m*L70T0 zvcO`{ew{h8{%|(Wp)YH8<)N9ZHxRTz*Sp_(WO-lb#9c-Png$K*rDL$iw)RSoiwGj0 zrI2w;y)w@+@m0@oQ{)nGAl!#`Xj08>`>Dls-melO`b9ps zgcg-9qSHPIuQ*m)h^J}hYSJ{?8Z(G}vkI9WSbfXH-?|{K`PUBXkGR9&EljMqn3@>giG`eAxwZzEtZ2OD)$ zXHaK%_jA0Ay4TKMH2LxPt*{@f15UCUJe7hhXG5n;Z}wE&yT+}K`UIr=fl1MC2QMVi*XP0=-!pJUqU4^R!{SyY z=}9jgnXbF1)c`*+KnKh)$5%9TPu~h>XcT^Qj(Vx^N`bidx*Bh}A^M-bO%^B)$oWzi z7*x*EK|S6&YoF$3an3>+x>&*kchE3YvGHQ}W=;s*YM z_)20PRFReSP985do0CVp6_ggPfM;RqEB z_OX-Mb;IL+w93r)marB%Ygsfm7#X*26H%k5+#;gXzUOBNuI}{5u76G0vBMMA%++F_ zRFl;5-x1|CNU)3e&XxF+BjoSWP#6m{THFRCD}aHRUbbp<&~wO3xujQc>C>EQ;K|Am z7e&sJWuBPVzy2ZO^DgeVJ@98Yq>~d1k!g5{>$r zK(2)xpn%}b*}m$qWOo6XukIVSsWCUUct@C|=`7Z)Q8Xd5*sUJ+O?X}yHj~}US_>dd zZ-Ot(Q&)MYXsJynMF(2TKJa9<1AerLWVh9A4Jw%Po6Tm=*C@|9>s|FMuV`&_ptIa5 zsT0k|Ko_;<;%;Kl)j4BK zOZ&p*@xDr$u&sAS6D0P(8P_EpX1dg{7*ZPEP)uUb|F?glyD=V&+hX_XRJ&4Bnn|`e zC}4Oq?IB-d`GOU6UNs}elSUw<@;dHw27sS?#lO9-pyG#?$lHDWDjimX3)Bli{^~hd z9`m&o?h4mzU;UuURk;J6yzYx^ExX_IDv9z|B7q5S1j|;l{8{%`r7p+xpL=zaY?)j& z=d}}m6Y#h*iI1`ik3~MCt??%Ro*n*_awFaG^G8oszMjQv;eD14eaC@9(>B*e$`Ac- zIrc?mfA#P+8TFm{tzguA?xE6W3j-d>8$Icb|B>Ht zDm{L00Wqmwy)AZT5N^Qr$<6kwkbH$v0APqD2N9T&)?#HnB7DMx^j8tK)Q7OEfWZVf zs0YMbCP8tCbGU}Tb(juZ#hPM8V#h?ImyHt?%cQie85bckJ|1jV)3rgdVi8B2r1*mq z2-PBAqk9f1$=5iAnE}~p>{bq)T#m63+!BuT!_rse#pVY2 zH4~5d&c>$qfEJu z`Ynq!w^a9j-AI{q>HbdBfM7s9Y>eI7mD09x+^tP-zNY^PnT8G+%mg8JZ=HX={-8ls z_m}&CLfEcgx2#*j9ODH-(j7wR?hr!|)#8c7KCOn|sie0fxSoBG-)5$Me6$4!g4>wi z{Y1CE0f*E&c-CII>G1={<4-uuv`|=2!<{084CoKBu?-Ha+Y!NtHzZ7{;|iY5($73%*0>Tim#R?#@3;&7$9i)3zb6b=*~ah1+7AU5d|@l`&}Hg_}u0N4kx_0zM# zx}xqSWW)XzAgJ{G33yd87BS0%*OKsI_RV8lag8$4tS$)d9TdzkvFz?&L--O?AG9k= zP8YWr-W&n|AP88gQ@w_{c}|k-?|>JffDuup8S5%%LsD2L`?Jo6UqRb0*j3ZV(uZ#a z+z7jJNruIh1XED>PUmZm{9bL$T_?%)>E-lk@G;3X7O?JTxMM$nymktm7*1XROM{QI z6Q5@43T%+jIJX%!{z=nom}E;uR~b7G#TO*W!|HX^IMAm#wQPfqFVT+!Yim}D59_p9 zbgP8XEE}5>FnkdRrAyJnq1(-Ybbi+KNY_i!0c>-bBg6l=f6EdWwHjo!!}o z1mW>d@dh8_EKNE9J0+q#{F73 zz24SWU2~UB6cOGfj&m_!Zs>ofp5^)~1F+D$ebEL%!e7ecn!J(21;{0%t=~p2UJ|3E zk_@e>zN$qdXq#J~jlVOKs9zEp&1#kdxEpXGBi+(P>z5;~X;Yg&7C_RZCSSX2(G)y+ z4r3(?gXy}=bqeTyr`0NlS$00z zPl4ROcSIp5$+5ANj)^o75lsBoBU=m+0sqzMv9%kwhrI2-$BVb#b`dANYL5tI*jXQm z$W>-07kDntqrnQx9pSMAC0WsfGnT2_VdLA_c!00?D_7W4_fW$+5j!J_rE%p^<+wRr zwrYXKcvT8Hh|#1C!!81cb-b-Oo`37K6W|8vI&~aSiqH?ti&5Zb`V&E)Ech#i*72ie zesU>t@rx{lhHrD>p4$!+9D^N5*irK^cDn(_z(8P}M)dy>HRr8Cag1`g@pA8tAzi%I zal$U_AM!@MD>dKSoRjSHKycvwz%s4NVhfEmlE)`db~yiHD8il1v%C zG1)C8q$vB-)ynEBMowkRI2I8h6|}ratRh=1`|dyo-x@-Q^loP*j$no?FPCTz5CwMs zG37g?vDJz!FG4cCPAzD`BMz^`7qB_twN7U666=#Ej*wuIT_W%gCp@3Bfjr#)rwHH; zZ7)*t_`ZjkRuLbeFx-s�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

VI`Lp0%xm3hhZ?pBl$IoObF<(AaBR}2V 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 literal 0 HcmV?d00001 diff --git a/xmidas/gui/resources/images/pancake.ico b/xmidas/gui/resources/images/pancake.ico new file mode 100755 index 0000000000000000000000000000000000000000..9d118f4f2a79d9492741a3143a7b36c9de7db4da GIT binary patch literal 4158 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 P|H#Qd{b&6D;pYDU1f=H& literal 0 HcmV?d00001 diff --git a/xmidas/gui/resources/images/splash.gif b/xmidas/gui/resources/images/splash.gif new file mode 100755 index 0000000000000000000000000000000000000000..800ffdb41fb58b5cb783a3581771bfc43b03d605 GIT binary patch literal 40659 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 ZyJyLT z7B{VjZuYsRx|9GjB#ZXw22{Lzd+9;0ecU@0OYWO}IA+^wG9-6JZ^K>bw|9bP;B*85 z!+NV5yd}d&*>LOdj?auM>QQ2`&agcBZZ5EQwcup57*p@ZcTLl0UQkdLP!h5N<8;K8 zPuKm5jTg3lYIg1VGDd{le^QCok{Qn9quxEeDw+O9FuY2HhApU1^&wyAxhEK@_aRsJ zC)h*ESBsw7mzm8wXX(v3&;J^z`>+YdF+yT40lGXd2Rgr52k*i3!2`KzO#SvU;c_`} zh3fPkCT~ica(DV?$Q`blSAHLdJi`NIv)5s}J@XtV0|ejwh%5JO>-~OzwTk!A*-0kdpZMfrAwQX?W;*94&s7E7D}il_yi?)eDoaPN;tY2Npb-aACuTmsYikRja_R zULiC5I{6_(iDucJO`8#8M$U6bt|WO^^vSy^ZN}6I6LD+TuVKfQJ^QEPtyLX&wHleA z{>6dnO>({YoZ*6<=?W_bJHxxVhYgmQH#7_)< z5$*7|Y?Irys}dzCkk6f?i@rLw{&xTW0Sr*UofP8=EAPC6j5psNf+#)V(Aw;+jEsv9 zwEO0(>$#ZnQjNL+K@3sE5ee%~D+IYxki27j8?UnR$ZAhU_dN3m8*D6Ojy}9j+lxb+ zVB)5x=}0Wn$Rm;DiMz%UR1vJ+#4;~N2;1ANqY2@&P_E^6OsPk`ejKtJA$KA&$urSR z(>khBY;vIR$QzHmvR<5$%FKv?3rpmd)5g9&xA`-#`<&wtotvZ^Q_Y=7S(K?p1M~(` zN1?in%>)_q%ChpndJ)Du(K0Tsi$2S7H2O}(4>i7S5|h%Mym=KVZ(@zqFj8nevcLlw z%hXBAIK2#1_Bh+~I8&Mao3Aug5j~VOL|uKgR#~a7Rw+vx`|j6HfeqHO%2*s0zRo7p zk}fY#`t!>|_p{dBci|lhQ}DKpvq7@VS}!vz$E{Jz&_uI~6#Lc%lQmZlj@Q3w6>j(` z6MYR&%1xv67GH6*q$p1b|CJBbf?HyhLss?k(BbNEJy~U@9Q)4AgkZM#Q;bK|hL}Cy zOHRkoxMUX0)XX%KCx%xp+UPYAgwsh+H?6GBJ2`TT*tpE~i09`DhIUn;i6Z*wufayl zQaF{S7)nlqH7nfA+@rc&fB8HY!=CYLNla*SO4z4K!|prYlwpgwAYmkvGrhxUo~YPT zt&|H#kqD(LYefE6-8xafG0)uV!%}Sd*TO-!SlG7H>i0ORKYCm_WzjvYByK7PQtQlV zuidpbl|}}=wC9ZI(ca2^|?=JaH12ioMtEC6su-AbKCwTCqBJoEo2>XUaL+9I0VLKfkpFN#p3iNrsYe5 ziksT8s+PPAElX7%VpY%zXsr^CkT5%}jt>QMLQM@(PU?xEW~4?g)WL0aJDMTEnDrye zq3=uwfPGxvrQHurC6PmK+gzMFkbkMPFgjgT%!>3B6~DIpUGe%J&jN<_$Ym zOynm;v`F0*@p^QM;Mx?oN8#x&gUu-op~&aKzT8baa0KNo{X@jwm2z}0j1Y}#=0^;Y z;&>;4o#hM(LR{X`mYIXn?poxB12=t=4EreePd<9aA~ zmOPcKl5rymF)^u^nLNv6;I!xT=!iBvMzUYktWb`K$+~S$PIg?278~!G(3P3(i`bK9 z{_r@qL~M>mpc#rK^9;sGgx*tu3N@N|xMe*S4vTvh#L`6NcF91&GIsPtSdql(QJDtu zNp|F=@7UHhoDqk3s^gyw`xj5jNwFIxBT+MjBEp$2bti^nsBlm@L7i%&LfG^vMVA%O zy>!r!?NX-0+=#`nGSxZ|EM?jvsmD>}42Bd9D)InWxlDp^qhwXeSnWC+6_QeP6HFqh zh~p9c0W4rUiz_#^hQqurwu(s2N$6VGO9<(SvK)&~pD+YZ!g#0LrbotYNjb=yVH9uTEWhXtw0(05YuEVy{NVK-g+P30m`v?mMcNE;GWRYs_IzGbZwmG`W!dUm^s#B03F z^B{d`rg5aYpw7hiT6Dp7fHo{{d#k0?^wI8jMvN+z(xO_b`VmkTbsb8Mxf+pa7r;j9 z?$BoXt$XeBW=fPA_{>GviaHTYTrDI4KU?7{s<^4W!)f_TWbT+BX z9otG;JXX^~sX3g$8Uq_;?3nTPn>8R2*UUWmah(Apsiur>zLp)Ad4K*IlIg~hv&$=_ z^O}d}!c-ZwjPAxhp_a!|x%on?3pAl+8J!L(^tP|*G_3BdXrh#pW~Y0P>ezZ-j%d|1 zX{_Na%cRgy17_BuhKh6fHR=0#WY9={tIy_1*D>3g*#B`5YA0DiVV+B+``wxi>sf4R zlL*pP`rbcyIzGtM@ zn(Hm=?57S+$uVo#pJCIR;6nLyQpCv9eQ)W=`c3b*yIF9FL#5U}iDa%VxbJP&X$Fo#bx&Am1bD85hO7DrK)8rym z+~)V3uiG{zSY*vjCEWH|L4}T_gBLxoF8p3Z+Zs17{n6Rn3{%jl9`@@z_s{peFO99s z^mt#6wtp$P*rgrg_N;T~tc7B~=~k%g&Kd4fwzqN-tZzUMG$l^Ii;3|D>zVhR@rF@3 z+}er3Q_=A0bEd1v8$X-3_hjlUwF}dwRS6D3F>ep!t-npBpUV16Tg_jZ#fz zYyHyo>7Se>%wFt||1b6x{lXzvk~BV;SrKSszaE$r_s8vv`;37~0i9#dV zYWCPog9e4G5>3pCjsRKg{{UpC(60Cd<>ll`@1hL^UE>3rLI>Zava(LqnC)ZcO1&H~ z>Tqx{cyKBHZiHYk#70cGhKmE+ZdQ&EDOeD|-i9KsO8PFXu(~eO#IFj)Fe!YH=jNum z^loc;zk^Y>p_%@4tr0DW64>4#Z5%CNd>x{MZi}(&J-tMLlYcVMf(Y@kf z9jbvR)&UxKFevyd(~VGSsu8>WRGqTvjpF(-(|8`8lY zr-fm>#tdB!4Jn5uu&Wozs^&tZ8D&Zx=z$*Q;S;DK9?XCe)?px}VHD!w5u!jIu0a&& zAs*zR639dyg7wX{)>cJ5hp&sIZ zD(gTJ>Om=2vdc8hKg}vd)#jHL+5o4nC50CF>FtvMHs8{}agVj(cyG7doV3(lb)&>$XA0SM}04l=i-SzzA#-4W<$rbdxyyu!#b3t8VD)5KRw}%V_-3Icwq? zSb-Jfp)KVh3eMmh=7A`SU>)S32+koE&_Et?;2aV249r0ureO|?IRsIhoVsez6T(4{|;{&J}ZSQV;c0Ya$>306Rxm*r@;j literal 0 HcmV?d00001 diff --git a/xmidas/gui/windows/decomposition_viewer.py b/xmidas/gui/windows/decomposition_viewer.py new file mode 100644 index 0000000..8b87b35 --- /dev/null +++ b/xmidas/gui/windows/decomposition_viewer.py @@ -0,0 +1,391 @@ +import logging +import sys +import os +import json +import scipy.stats as stats +import numpy as np +import pandas as pd +import tifffile as tf +import pyqtgraph as pg +import pyqtgraph.exporters +from glob import glob +from scipy.stats import linregress +from packaging import version + +from PyQt6 import QtWidgets, QtCore, QtGui, uic, QtTest +from PyQt6.QtGui import QMovie +from PyQt6.QtWidgets import QMessageBox, QFileDialog, QApplication +from PyQt6.QtCore import QObject, pyqtSignal, pyqtSlot, QRunnable, QThreadPool, PYQT_VERSION_STR + +from gui.windows.multichannel_viewer import MultiChannelWindow +from utils import * +from utils.color_maps import * +from models.encoders import jsonEncoder +cmap_dict = create_color_maps() + +ui_dir = os.path.normpath(os.path.join( + os.path.dirname(os.path.abspath(__file__)), + "../layout" +)) + +from gui.windows.singleStackViewer import * + + +class DecomposeViewer(QtWidgets.QMainWindow): + mask_signal: pyqtSignal = QtCore.pyqtSignal(np.ndarray) + mask_and_path_signal: pyqtSignal = QtCore.pyqtSignal(list) + def __init__(self, to_decompose, im_stack, energy): + super(DecomposeViewer, self).__init__() + + # Load the UI Page + uic.loadUi(os.path.join(ui_dir, "decomposeViewer.ui"), self) + self.centralwidget.setStyleSheet(open(os.path.join(ui_dir, "css/defaultStyle.css")).read()) + self.user_wd = os.path.abspath("~") + + self.to_decompose = to_decompose + if im_stack is None: + self.im_stack = self.to_decompose + else: + self.im_stack = im_stack + self.energy = energy + self.eigen_img = None + self.eigen_spectra = None + self.decon_spectra = None + self.decon_map = None + + if self.to_decompose.ndim==2: + self.to_decompose = np.expand_dims(self.to_decompose, axis=0) + + + (self.dim1, self.dim3, self.dim2) = self.to_decompose.shape + #self.hs_comp_number.setMaximum(self.dim1 - 1) + self.eigen_image_view.ui.menuBtn.hide() + self.eigen_image_view.ui.roiBtn.hide() + self.eigen_image_view.setPredefinedGradient("viridis") + + self.eigen_masked_spectrum_view.setLabel("bottom", "Energy") + self.eigen_masked_spectrum_view.setLabel("left", "Intensity", "A.U.") + + self.eigen_spectrum_view.setLabel("bottom", "Energy") + self.eigen_spectrum_view.setLabel("left", "Weight", "A.U.") + + self.pb_view_stack.clicked.connect(self.view_stack) + + + # connection + self.pb_show_all.clicked.connect(lambda:self.show_all_spec(norm_to_max = True, add_offset = True)) + self.hs_comp_number.valueChanged.connect(self.update_plots) + self.actionSave.triggered.connect(self.save_comp_data) + self.pb_send_mask.clicked.connect(self.send_mask) + #self.pb_openScatterPlot.clicked.connect(self.openScatterPlot) + # self.pb_showMultiColor.clicked.connect(lambda: self.generateMultiColorView(withSpectra=False)) + # self.pb_showMultiImageXANESView.clicked.connect(lambda: self.generateMultiColorView(withSpectra=True)) + self.pb_calc_components.clicked.connect(self.decompose_and_display) + self.pb_calc_cluster.clicked.connect(self.cluster_decomposed) + self.sldr_mask_low.valueChanged.connect(lambda value: self.dsb_low_threshold.setValue(value / 100.0)) + self.sldr_mask_high.valueChanged.connect(lambda value: self.dsb_high_threshold.setValue(value / 100.0)) + self.pb_apply_threshold.clicked.connect(lambda:self.create_mask(self.hs_comp_number.value())) + self.pb_browse_save_path.clicked.connect(self.browse_folder) + self.pb_send_all_and_save.clicked.connect(self.send_mask_and_save) + + + def view_stack(self): + self.newWindow = singleStackViewer(self.im_stack) + self.newWindow.show() + + def decompose_and_display(self): + self.eigen_img,self.eigen_spectra,self.decon_spectra,self.decon_map = decompose_stack( + self.to_decompose, + decompose_method=self.cb_comp_method.currentText(), + n_components_=self.sb_ncomp.value()) + + self.hs_comp_number.setMaximum(self.eigen_img.shape[0]-1) + self.update_plots(0) + + def cluster_decomposed(self): + + self.eigen_img, X_cluster, self.decon_spectra = cluster_stack( + self.to_decompose, + method=self.cb_clust_method.currentText(), + n_clusters_=self.sb_ncluster.value(), + decomposed=self.cb_use_comp_for_cluster.isChecked(), + decompose_method=self.cb_comp_method.currentText(), + decompose_comp=self.sb_ncomp.value()) + self.eigen_spectra = self.decon_spectra + self.hs_comp_number.setMaximum((self.eigen_img.shape)[0]-1) + self.update_plots(0) + + + def update_plots(self, im_index): + self.eigen_image_view.setImage(self.eigen_img[im_index]) + + try: + self.eigen_masked_spectrum_view.plot(self.energy, self.decon_spectra[:, im_index], clear=True) + self.eigen_spectrum_view.plot(self.energy, self.eigen_spectra[:, im_index], clear=True) + except: + pass + self.label_comp_number.setText(f"{im_index + 1}/{self.eigen_img.shape[0]}") + #print(f"{self.eigen_img.shape = }") + self.create_mask(im_index) + + def create_mask(self, im_index): + + self.threshold_low = self.dsb_low_threshold.value() + self.threshold_high = self.dsb_high_threshold.value() + self.dsb_low_threshold.setMaximum(self.threshold_high-1e-10) + self.dsb_high_threshold.setMinimum(self.threshold_low+1e-10) + + self.norm_mask = remove_nan_inf(self.eigen_img[im_index]) / np.nanmax(self.eigen_img[im_index]) + self.norm_mask[(self.norm_mask < self.threshold_low) | + (self.norm_mask > self.threshold_high)] = 0 + + self.mask = self.norm_mask + self.binary_mask = np.where(self.mask > 0, 1, 0) + self.eigen_mask_image_view.setImage(self.binary_mask) + + def send_mask(self): + + """ Send masked xanes viewer""" + + if self.cb_use_binary_mask.isChecked(): + self.mask_signal.emit(self.im_stack*self.binary_mask[np.newaxis,:,:]) + else: + self.mask_signal.emit(self.im_stack*self.mask[np.newaxis,:,:]) + + def browse_folder(self): + folder_path = QFileDialog.getExistingDirectory(self, "Select Folder") + if folder_path: + self.le_save_path.setText(folder_path) + + def send_mask_and_save(self): + + save_path = os.path.join(self.le_save_path.text(), f"Cluster_{self.hs_comp_number.value()}") + if self.cb_use_binary_mask.isChecked(): + self.mask_and_path_signal.emit([self.im_stack*self.binary_mask[np.newaxis,:,:], save_path]) + else: + self.mask_and_path_signal.emit([self.im_stack*self.mask[np.newaxis,:,:], save_path]) + + + def show_all_spec(self, norm_to_max = True, add_offset = True): + self.eigen_masked_spectrum_view.clear() + self.plt_colors = ["g", "b", "r", "c", "m", "y", "w"] * 10 + offsets = np.arange(0, 2, 0.2) + self.eigen_masked_spectrum_view.addLegend() + for ii in range(self.decon_spectra.shape[1]): + to_plot = self.decon_spectra[:, ii] + if norm_to_max: + to_plot = self.decon_spectra[:, ii] / self.decon_spectra[:, ii].max() + if add_offset: + to_plot = to_plot+ + offsets[ii] + + self.eigen_masked_spectrum_view.plot( + self.energy, + to_plot, + pen=self.plt_colors[ii], + name="component" + str(ii + 1), + ) + self.eigen_spectrum_view.clear() + self.eigen_spectrum_view.addLegend() + for ii in range(self.eigen_spectra.shape[1]): + to_plot = self.eigen_spectra[:, ii] + if norm_to_max: + to_plot = self.eigen_spectra[:, ii] / self.eigen_spectra[:, ii].max() + if add_offset: + to_plot = to_plot+ + offsets[ii] + self.eigen_spectrum_view.plot( + self.energy, + to_plot, + pen=self.plt_colors[ii], + name="eigen_vector" + str(ii + 1), + ) + + def save_comp_data(self): + file_name = QFileDialog().getSaveFileName(self, "save all data", self.user_wd, "data(*tiff *tif *txt *png )") + if file_name[0]: + self.show_all_spec(norm_to_max = False, add_offset = False) + tf.imwrite(file_name[0] + "_eigen_weights.tiff", np.float32(self.self.eigen_img)) + tf.imwrite(file_name[0] + "_eigen_masks.tiff", np.float32(self.decon_map)) + exporter_spec = pg.exporters.CSVExporter(self.eigen_masked_spectrum_view.plotItem) + exporter_spec.parameters()["columnMode"] = "(x,y) per plot" + exporter_spec.export(file_name[0] + "_deconv_spec.csv") + exporter_eigen = pg.exporters.CSVExporter(self.eigen_spectrum_view.plotItem) + exporter_eigen.parameters()["columnMode"] = "(x,y) per plot" + exporter_eigen.export(file_name[0] + "_eigen_vectors.csv") + self.user_wd = os.path.dirname(file_name[0]) + else: + pass + + def generateMultiColorView(self, withSpectra=False): + self.multichanneldict = {} + + for n, (colorName, image) in enumerate(zip(cmap_dict.keys(), self.to_decompose.transpose(0, 1, 2))): + low, high = np.min(image), np.max(image) + self.multichanneldict[f'Image {n + 1}'] = {'ImageName': f'Image {n + 1}', + 'ImageDir': '.', + 'Image': image, + 'Color': colorName, + 'CmapLimits': (low, high), + 'Opacity': 1.0 + } + + if withSpectra: + compXanesSpetraAll = pd.DataFrame() + compXanesSpetraAll['Energy'] = self.energy + + for n, spec in enumerate(self.decon_spectra.T): + compXanesSpetraAll[f'Component_{n + 1}'] = spec + + # self.muli_color_window = MultiXANESWindow(image_dict=self.multichanneldict, + # spec_df=compXanesSpetraAll) + else: + self.muli_color_window = MultiChannelWindow(image_dict=self.multichanneldict) + + self.muli_color_window.show() + + # add energy column +class ComponentScatterPlot(QtWidgets.QMainWindow): + def __init__(self, decomp_stack, specs): + super(ComponentScatterPlot, self).__init__() + + uic.loadUi(os.path.join(ui_dir, "ComponentScatterPlot.ui"), self) + self.user_wd = os.path.abspath("~") + self.centralwidget.setStyleSheet(open(os.path.join(ui_dir, "css/defaultStyle.css")).read()) + self.w1 = self.scatterViewer.addPlot() + self.decomp_stack = decomp_stack + self.specs = specs + (self.dim1, self.dim3, self.dim2) = self.decomp_stack.shape + # fill the combonbox depending in the number of components for scatter plot + for n, combs in enumerate(combinations(np.arange(self.dim1), 2)): + self.cb_scatter_comp.addItem(str(combs)) + self.cb_scatter_comp.setItemData(n, combs) + + self.s1 = pg.ScatterPlotItem(size=3, pen=pg.mkPen(None), brush=pg.mkBrush(255, 255, 0, 120)) + + self.setImageAndScatterPlot() + # connections + self.actionSave_Plot.triggered.connect(self.pg_export_correlation) + self.actionSave_Images.triggered.connect(self.tiff_export_images) + self.pb_updateComponents.clicked.connect(self.setImageAndScatterPlot) + self.pb_define_mask.clicked.connect(self.createMask) + self.pb_apply_mask.clicked.connect(self.getMaskRegion) + self.pb_reset_mask.clicked.connect(self.resetMask) + self.pb_addALine.clicked.connect(lambda: self.createMask(Line=True)) + + def setImageAndScatterPlot(self): + + try: + self.s1.clear() + except Exception: + pass + + comp_tuple = self.cb_scatter_comp.currentData() + self.img1, self.img2 = self.decomp_stack[comp_tuple[0]], self.decomp_stack[comp_tuple[-1]] + self.image_view.setImage(self.decomp_stack[comp_tuple[0]]) + self.image_view.ui.menuBtn.hide() + self.image_view.ui.roiBtn.hide() + self.image_view.setPredefinedGradient("bipolar") + + self.image_view2.setImage(self.decomp_stack[comp_tuple[-1]]) + self.image_view2.ui.menuBtn.hide() + self.image_view2.ui.roiBtn.hide() + self.image_view2.setPredefinedGradient("bipolar") + + points = [] + for i, j in zip(self.img1.flatten(), self.img2.flatten()): + + points.append( + { + "pos": (i, j), + "data": "id", + "size": 5, + "pen": pg.mkPen(None), + "brush": pg.mkBrush(255, 255, 0, 160), + } + ) + + self.s1.addPoints(points) + self.w1.addItem(self.s1) + # self.s1.setData(self.specs[:, comp_tuple[0]], self.specs[:, comp_tuple[-1]]) + self.w1.setLabel("bottom", f"PC{comp_tuple[0]+1}") + self.w1.setLabel("left", f"PC{comp_tuple[-1]+1}") + self.label_im1.setText(f"PC{comp_tuple[0]+1}") + self.label_im2.setText(f"PC{comp_tuple[-1]+1}") + + def createMask(self, Line=False): + + self.size = self.img1.max() / 10 + self.pos = int(self.img1.mean()) + + if Line: + self.lineROI = pg.LineSegmentROI( + [0, 1], + pos=(self.pos, self.pos), + pen=pg.mkPen("r", width=4), + hoverPen=pg.mkPen("g", width=4), + removable=True, + ) + self.w1.addItem(self.lineROI) + + else: + + self.scatter_mask = pg.PolyLineROI( + [[0, 0], [0, self.size], [self.size, self.size], [self.size, 0]], + pos=(self.pos, self.pos), + pen=pg.mkPen("r", width=4), + hoverPen=pg.mkPen("g", width=4), + closed=True, + removable=True, + ) + + self.w1.addItem(self.scatter_mask) + + def resetMask(self): + self.clearMask() + self.createMask() + + def clearMask(self): + try: + self.w1.removeItem(self.scatter_mask) + except AttributeError: + pass + + def clearPgPlot(self): + try: + self.masked_img.close() + except Exception: + pass + + def getMaskRegion(self): + + # Ref : https://stackoverflow.com/questions/57719303/how-to-map-mouse-position-on-a-scatterplot + + roiShape = self.scatter_mask.mapToItem(self.s1, self.scatter_mask.shape()) + self._points = list() + logger.info("Building Scatter Plot Window; Please wait..") + for i in range(len(self.img1.flatten())): + self._points.append(QtCore.QPointF(self.img1.flatten()[i], self.img2.flatten()[i])) + + selected = [roiShape.contains(pt) for pt in self._points] + img_selected = np.reshape(selected, (self.img1.shape)) + + self.masked_img = singleStackViewer(img_selected * self.img1, gradient="bipolar") + self.masked_img.show() + + def pg_export_correlation(self): + + exporter = pg.exporters.CSVExporter(self.w1) + exporter.parameters()["columnMode"] = "(x,y,y,y) for all plots" + file_name = QFileDialog().getSaveFileName(self, "save correlation", "", "spectrum and fit (*csv)") + if file_name[0]: + exporter.export(file_name[0] + ".csv") + self.statusbar.showMessage(f"Data saved to {file_name[0]}") + else: + pass + + def tiff_export_images(self): + file_name = QFileDialog().getSaveFileName(self, "save images", "", "spectrum and fit (*tiff)") + if file_name[0]: + tf.imwrite(file_name[0] + ".tiff", np.dstack([self.img1, self.img2]).T) + self.statusbar.showMessage(f"Images saved to {file_name[0]}") + else: + pass \ No newline at end of file diff --git a/xmidas/gui/windows/mask_maker.py b/xmidas/gui/windows/mask_maker.py new file mode 100644 index 0000000..0eea3cf --- /dev/null +++ b/xmidas/gui/windows/mask_maker.py @@ -0,0 +1,287 @@ +import argparse +import logging +import sys +import webbrowser +import traceback +import os +import json +import scipy.stats as stats +import numpy as np +import pandas as pd +import tifffile as tf +import pyqtgraph as pg +import pyqtgraph.exporters +from glob import glob +from pyqtgraph import plot +from itertools import combinations +from scipy.stats import linregress +from packaging import version + + +from PyQt6 import QtWidgets, QtCore, QtGui, uic, QtTest +from PyQt6.QtGui import QMovie +from PyQt6.QtWidgets import QMessageBox, QFileDialog, QApplication +from PyQt6.QtCore import QObject, pyqtSignal, pyqtSlot, QRunnable, QThreadPool, PYQT_VERSION_STR +from utils import * +from utils.color_maps import * +from models.encoders import jsonEncoder +cmap_dict = create_color_maps() +ui_dir = os.path.normpath(os.path.join( + os.path.dirname(os.path.abspath(__file__)), + "../layout" +)) + + + +class MaskSpecViewer(QtWidgets.QMainWindow): + mask_signal: pyqtSignal = QtCore.pyqtSignal(np.ndarray) + def __init__(self, xanes_stack=None, mask_map=None, energy=[], refs = None): + super(MaskSpecViewer, self).__init__() + uic.loadUi(os.path.join(ui_dir, "MaskSpecViewer.ui"), self) + self.user_wd = os.path.abspath("~") + + self.xanes_stack = xanes_stack + self.mask_map = mask_map + self.energy = energy + #self.mask_map = self.xanes_stack[-1] + self.refs = refs #TODO fitting option + self.view_data() + + # connections + self.dsb_low_threshold.valueChanged.connect(self.create_mask) + self.dsb_high_threshold.valueChanged.connect(self.create_mask) + self.pb_apply_mask.clicked.connect(self.apply_mask_to_xanes) + self.action_export_mask.triggered.connect(self.export_mask) + self.action_import_mask.triggered.connect(self.import_a_mask) + self.actionLoad_Energy_List.triggered.connect(self.load_energy) + self.actionLoad_XANES_Stack.triggered.connect(self.load_xanes_stack) + self.actionLoad_XRF_Map.triggered.connect(lambda:self.load_mask_map()) + self.pb_send_mask.clicked.connect(self.send_mask) + self.sldr_mask_low.valueChanged.connect(lambda value: self.dsb_low_threshold.setValue(value / 100.0)) + self.sldr_mask_high.valueChanged.connect(lambda value: self.dsb_high_threshold.setValue(value / 100.0)) + + def view_data(self): + + self.xanes_view.setImage(self.xanes_stack) + self.xanes_view.ui.menuBtn.hide() + self.xanes_view.ui.roiBtn.hide() + (self.dim1, self.dim3, self.dim2) = self.xanes_stack.shape + self.xanes_view.setPredefinedGradient("viridis") + self.xanes_view.setCurrentIndex(self.dim1 // 2) + self.statusbar.showMessage("One image from the XANES stack is used as mask") + self.xrf_view.setImage(self.mask_map) + self.xrf_view.ui.menuBtn.hide() + self.xrf_view.ui.roiBtn.hide() + self.xrf_view.setPredefinedGradient("viridis") + + self.mask_view.ui.menuBtn.hide() + self.mask_view.ui.roiBtn.hide() + + def create_mask(self): + + self.threshold_low = self.dsb_low_threshold.value() + self.threshold_high = self.dsb_high_threshold.value() + self.dsb_low_threshold.setMaximum(self.threshold_high-0.001) + self.dsb_high_threshold.setMinimum(self.threshold_low+0.001) + + self.norm_mask = remove_nan_inf(self.mask_map) / np.nanmax(self.mask_map) + self.norm_mask[(self.norm_mask < self.threshold_low) | + (self.norm_mask > self.threshold_high)] = 0 + + # self.norm_mask[self.norm_mask < self.threshold_low] = 0 + # self.norm_mask[self.norm_mask > self.threshold_high] = 0 + self.xrf_view.setImage(self.norm_mask) + self.statusbar.showMessage("New Threshold Applied") + self.binary_mask = np.where(self.norm_mask > 0, 1, 0) + self.mask_view.setImage(self.binary_mask) + + + def load_xanes_stack(self): + """loading a new xanes stack""" + filename = QFileDialog().getOpenFileName(self, "Select image data", "", "image file(*tiff *tif )") + self.file_name = str(filename[0]) + self.xanes_stack = tf.imread(self.file_name).transpose(0, 2, 1) + self.view_data() + + def load_energy(self): + """To load energy list that will be used for plotting the spectra. + number of stack should match length of energy list""" + + file_name = QFileDialog().getOpenFileName(self, "Open energy list", "", "text file (*.txt)") + + try: + self.energy = np.loadtxt(file_name[0]) + logger.info("Energy file loaded") + assert len(self.energy) == self.dim1 + self.view_data() + + except OSError: + logger.error("No File selected") + pass + + def load_mask_map(self, z = -1): + """Array for masking.Z will be used if 3D """ + + filename = QFileDialog().getOpenFileName(self, "Select image data", "", "image file(*tiff *tif )") + self.xrf_file_name = str(filename[0]) + self.mask_map = tf.imread(self.xrf_file_name) + if self.mask_map.ndim == 3: + self.mask_map = self.mask_map[z] + + else: + self.mask_map = self.mask_map.T + + assert ( + self.dim3, + self.dim2, + ) == self.mask_map.shape, f"Unexpected image dimensions: {self.mask_map.shape} vs {(self.dim2,self.dim3)}" + + self.view_data() + self.create_mask() + + def send_mask(self): + + """ Apply mask to xanes viewer""" + + if self.cb_use_binary_mask.isChecked(): + self.mask_signal.emit(self.binary_mask) + else: + self.mask_signal.emit(self.norm_mask) + + def apply_mask_to_xanes(self): + + """Generates a mask with 0 and 1 from the choosen threshold and multply with the xanes stack. + A spectrum will be generated from the new masked stack""" + if self.cb_use_binary_mask.isChecked(): + self.masked_xanes = self.xanes_stack * self.binary_mask[np.newaxis,:,:] + + else: + self.masked_xanes = self.xanes_stack * self.norm_mask[np.newaxis,:,:] + + self.xanes_view.setImage(self.masked_xanes) + self.xanes_view.setCurrentIndex(self.dim1 // 2) + self.statusbar.showMessage("Mask Applied to XANES") + self.mask_spec = get_mean_spectra(self.masked_xanes) + + if len(self.energy) != 0: + self.xdata = self.energy + else: + self.xdata = np.arange(0, self.dim1) + self.statusbar.showMessage("No Energy List Available; Integer values are used for plotting") + + self.spectrum_view.plot(self.xdata, self.mask_spec, clear=True) + + def import_a_mask(self): + filename = QFileDialog().getOpenFileName(self, "Select image data", "", "image file(*tiff *tif )") + xrf_file_name = str(filename[0]) + self.binary_mask = tf.imread(xrf_file_name).T + self.statusbar.showMessage("A New Mask Imported") + self.mask_view.setImage(self.binary_mask) + self.apply_mask_to_xanes() + + def export_mask(self): + try: + file_name = QFileDialog().getSaveFileName(self, "Save image data", "", "image file(*tiff *tif )") + tf.imwrite(file_name[0] + ".tiff", self.binary_mask.T) + logger.info(f"Updated Image Saved: {file_name[0]}") + self.statusbar.showMessage("Mask Exported") + except Exception: + logger.error("No file to save") + pass + + +class MaskMaker(QtWidgets.QMainWindow): + mask_signal: pyqtSignal = QtCore.pyqtSignal(np.ndarray) + def __init__(self, im_stack = None, mask_map=None): + super(MaskMaker, self).__init__() + uic.loadUi(os.path.join(ui_dir, "MaskMaker.ui"), self) + self.user_wd = os.path.abspath("~") + + self.im_stack = im_stack + self.mask_map = mask_map + self.view_data() + + # connections + self.dsb_low_threshold.valueChanged.connect(self.create_mask) + self.dsb_high_threshold.valueChanged.connect(self.create_mask) + self.action_export_mask.triggered.connect(self.export_mask) + self.action_import_mask.triggered.connect(self.import_a_mask) + self.actionLoad_XRF_Map.triggered.connect(lambda:self.load_mask_map()) + self.pb_send_mask.clicked.connect(self.send_mask) + self.sldr_mask_low.valueChanged.connect(lambda value: self.dsb_low_threshold.setValue(value / 100.0)) + self.sldr_mask_high.valueChanged.connect(lambda value: self.dsb_high_threshold.setValue(value / 100.0)) + + def view_data(self): + self.xrf_view.setImage(self.mask_map) + self.xrf_view.ui.menuBtn.hide() + self.xrf_view.ui.roiBtn.hide() + self.xrf_view.setPredefinedGradient("viridis") + + self.mask_view.ui.menuBtn.hide() + self.mask_view.ui.roiBtn.hide() + + def create_mask(self): + + self.threshold_low = self.dsb_low_threshold.value() + self.threshold_high = self.dsb_high_threshold.value() + self.dsb_low_threshold.setMaximum(self.threshold_high-0.001) + self.dsb_high_threshold.setMinimum(self.threshold_low+0.001) + + self.norm_mask = remove_nan_inf(self.mask_map) / np.nanmax(self.mask_map) + self.norm_mask[(self.norm_mask < self.threshold_low) | + (self.norm_mask > self.threshold_high)] = 0 + + # self.norm_mask[self.norm_mask < self.threshold_low] = 0 + # self.norm_mask[self.norm_mask > self.threshold_high] = 0 + self.xrf_view.setImage(self.norm_mask) + self.statusbar.showMessage("New Threshold Applied") + self.binary_mask = np.where(self.norm_mask > 0, 1, 0) + self.mask_view.setImage(self.binary_mask) + + + def load_mask_map(self, z = -1): + """Array for masking.Z will be used if 3D """ + + filename = QFileDialog().getOpenFileName(self, "Select image data", "", "image file(*tiff *tif )") + self.xrf_file_name = str(filename[0]) + self.mask_map = tf.imread(self.xrf_file_name) + if self.mask_map.ndim == 3: + self.mask_map = self.mask_map[z] + + else: + self.mask_map = self.mask_map.T + + assert ( + self.dim3, + self.dim2, + ) == self.mask_map.shape, f"Unexpected image dimensions: {self.mask_map.shape} vs {(self.dim2,self.dim3)}" + + self.view_data() + self.create_mask() + + def send_mask(self): + + """ Apply mask to xanes viewer""" + + if self.cb_use_binary_mask.isChecked(): + self.mask_signal.emit(self.im_stack*self.binary_mask[np.newaxis,:,:]) + else: + self.mask_signal.emit(self.im_stack*self.norm_mask[np.newaxis,:,:]) + + def import_a_mask(self): + filename = QFileDialog().getOpenFileName(self, "Select image data", "", "image file(*tiff *tif )") + xrf_file_name = str(filename[0]) + self.binary_mask = tf.imread(xrf_file_name).T + self.statusbar.showMessage("A New Mask Imported") + self.mask_view.setImage(self.binary_mask) + self.apply_mask_to_xanes() + + def export_mask(self): + try: + file_name = QFileDialog().getSaveFileName(self, "Save image data", "", "image file(*tiff *tif )") + tf.imwrite(file_name[0] + ".tiff", self.binary_mask.T) + logger.info(f"Updated Image Saved: {file_name[0]}") + self.statusbar.showMessage("Mask Exported") + except Exception: + logger.error("No file to save") + pass diff --git a/xmidas/gui/windows/multichannel_viewer.py b/xmidas/gui/windows/multichannel_viewer.py new file mode 100644 index 0000000..fccbd98 --- /dev/null +++ b/xmidas/gui/windows/multichannel_viewer.py @@ -0,0 +1,319 @@ +import os,sys,json +import numpy as np +import pandas as pd +import tifffile as tf +import pyqtgraph as pg +import pyqtgraph.exporters +from glob import glob +from pyqtgraph import plot +from itertools import combinations +from scipy.stats import linregress +from packaging import version + +from PyQt6 import QtWidgets, QtCore, QtGui, uic, QtTest +from PyQt6.QtGui import QMovie +from PyQt6.QtWidgets import QMessageBox, QFileDialog, QApplication +from PyQt6.QtCore import QObject, pyqtSignal, pyqtSlot, QRunnable, QThreadPool, PYQT_VERSION_STR +ui_dir = os.path.normpath(os.path.join( + os.path.dirname(os.path.abspath(__file__)), + "../layout" +)) +from utils.color_maps import * +from models.encoders import jsonEncoder +cmap_dict = create_color_maps() + +class MultiChannelWindow(QtWidgets.QMainWindow): + def __init__(self, image_dict=None): + super(MultiChannelWindow, self).__init__() + if image_dict is None: + image_dict = {} + uic.loadUi(os.path.join(ui_dir, "mutlichannel.ui"), self) + self.user_wd = os.path.abspath("~") + + self.canvas = self.img_view.addPlot(title="") + self.canvas.getViewBox().invertY(True) + self.canvas.setAspectLocked(True) + self.cb_choose_color.addItems([i for i in cmap_dict.keys()]) + #self.canvas.set + self.sliderSetUp() + self.image_dict = image_dict + self.buildFromDictionary() + + # connections + self.actionLoad.triggered.connect(self.createMuliColorAndList) + self.actionLoad_Stack.triggered.connect(self.createMuliColorAndList) + self.actionSave_Stack_tiff.triggered.connect(self.saveTiffData) + self.cb_choose_color.currentTextChanged.connect(self.updateImageDictionary) + self.pb_update_low_high.clicked.connect(self.updateImageDictionary) + self.listWidget.itemClicked.connect(self.editImageProperties) + self.listWidget.itemDoubleClicked.connect(self.showOneImageOnly) + self.pb_show_selected.clicked.connect(self.showOneImageOnly) + self.pb_show_all.clicked.connect(self.showAllItems) + self.actionLoad_State_File.triggered.connect(self.importState) + self.actionSave_State.triggered.connect(self.exportState) + self.actionSave_View.triggered.connect(self.saveImage) + + def buildFromDictionary(self): + if self.image_dict is not None: + self.createMultiColorView(self.image_dict) + self.displayImageNames(self.image_dict) + else: + pass + + def generateImageDictionary(self): + """Creates a dictionary contains image path, color scheme chosen, throshold limits etc. + when user edits the parameters dictionary will be updated and unwrapped for display later. + This dictionary is saved as json file while saving the state. Two image loading options are possible. + User can either select multiple 2D array images or one 3D array (stack)""" + + clickedAction = self.sender() + + if clickedAction.text() == "Load Images": + # multiple images are selected + self.loadMultipleImageFiles() + + elif clickedAction.text() == "Load Stack": + # an image stack is selected + self.loadAsStack() + + def loadMultipleImageFiles(self): + + filter = "TIFF (*.tiff);;TIF (*.tif)" + QtWidgets.QFileDialog().setFileMode(QtWidgets.QFileDialog.ExistingFiles) + # choose mutliple tiff files + names = QtWidgets.QFileDialog().getOpenFileNames(self, "Open files", " ", filter) + if names[0]: + self.image_dict = {} + # select the file directory. Image files are expected to be in the same folder + self.imageDir = os.path.dirname(names[0][0]) + + # create the dictionary + for colorName, image in zip(cmap_dict.keys(), names[0]): + # squeeze to allow with pseudo 3D axis from some tomo recon (eg. 1, 100,100 array) + im_array = np.squeeze(tf.imread(image)) + # set values for thresholding as image min and max + low, high = 0, 1 + # name of the tiff file is chosen as key for the dictionary, + # inner keys are properties set for that image + im_name = os.path.basename(image) + # construct the dictionary + self.image_dict[f"{os.path.basename(image)}"] = { + "ImageName": im_name, + "ImageDir": self.imageDir, + "Image": im_array, + "Color": colorName, + "CmapLimits": (low, high), + "Opacity": 1.0, + } + else: + pass + + def loadAsStack(self): + """construct the dictionary with image +number as the key. + All other steps are similar to the loadMultipleImageFiles function""" + + filter = "TIFF (*.tiff);;TIF (*.tif)" + file_name = QtWidgets.QFileDialog().getOpenFileName( + self, "Open a Stack", "", "TIFF(*tiff *tif);;all_files (*)", filter + ) + if file_name[0]: + self.imageDir = os.path.dirname(file_name[0]) + self.image_dict = {} + im_stack = np.squeeze(tf.imread(file_name[0])) + # asset the file is a stack + assert im_stack.ndim == 3, "Not a stack" + # construct the dictionary + for n, (colorName, image) in enumerate(zip(cmap_dict.keys(), im_stack)): + low, high = np.min(image), np.max(image) + self.image_dict[f"Image {n+1}"] = { + "ImageName": f"Image {n+1}", + "ImageDir": self.imageDir, + "Image": image, + "Color": colorName, + "CmapLimits": (low, high), + "Opacity": 1.0, + } + + def loadAnImage(self, image, colormap, cmap_limits, opacity=1): + """load single image and colorbar to the widget. This function will be looped for + multiple images later + """ + # get pg image item + img = pg.ImageItem() + # add image to the graphicsview widget + self.canvas.addItem(img) + # set the color map + cmap = pg.ColorMap(pos=np.linspace(0, 1, len(colormap)), color=colormap) + # image = np.squeeze(tf.imread(image_path)) + # set image to the image item with cmap + + lower_limit = np.nanmax(image)*cmap_limits[0] + upper_limit = np.nanmax(image)*cmap_limits[1] + img_ = np.where((image < lower_limit) | (image > upper_limit), 0, image) + + img.setImage(img_, + lut=cmap.getLookupTable(), + opacity=opacity) + + # set colorbar for thresholding + bar = pg.ColorBarItem(values=(lower_limit,upper_limit), cmap=cmap, + limits=None, orientation="vertical") + bar.setImageItem(img_) + # set composition mode to plus for overlaying + img.setCompositionMode(QtGui.QPainter.CompositionMode_Plus) + + def createMultiColorView(self, image_dictionary): + """Function creates multi color image view by taking image + data and parameters from the dictionary""" + + # clear the plots and list in case of re-loading + self.canvas.clear() + self.listWidget.clear() + + # display individual images in for loop + for path_and_color in image_dictionary.values(): + self.loadAnImage( + path_and_color["Image"], + cmap_dict[path_and_color["Color"]], + path_and_color["CmapLimits"], + path_and_color["Opacity"], + ) + + def showOneImageOnly(self): + editItem = self.listWidget.currentItem() + editRow = self.listWidget.currentRow() + for i in range(self.listWidget.count()): + if self.listWidget.item(i) == editItem: + editItemName = self.listWidget.item(i).text().split(",")[0] + self.image_dict[editItemName]["Opacity"] = 1 + + elif self.listWidget.item(i) != editItem: + editItemName = self.listWidget.item(i).text().split(",")[0] + self.image_dict[editItemName]["Opacity"] = 0 + + self.createMultiColorView(self.image_dict) + self.displayImageNames(self.image_dict) + self.listWidget.setCurrentRow(editRow) + + def showAllItems(self): + + editItem = self.listWidget.currentItem() + editRow = self.listWidget.currentRow() + for i in range(self.listWidget.count()): + editItemName = self.listWidget.item(i).text().split(",")[0] + self.image_dict[editItemName]["Opacity"] = 1 + + self.createMultiColorView(self.image_dict) + self.displayImageNames(self.image_dict) + self.listWidget.setCurrentRow(editRow) + + def displayImageNames(self, image_dictionary): + """Populate the list widget table with image name and color used to plot, + using image dictionary input""" + + for im_name, vals in image_dictionary.items(): + self.listWidget.addItem(f"{im_name},{vals['Color']}") + self.listWidget.setCurrentRow(0) + + def createMuliColorAndList(self): + """Finally Load Images and poplulate the list widget from the dictionary""" + with pg.BusyCursor(): # gives the circle showing gui is doing something + self.generateImageDictionary() + if self.image_dict: + self.createMultiColorView(self.image_dict) + self.displayImageNames(self.image_dict) + + else: + pass + + def sliderSetUp(self): + """Setting the slider min and max from image values""" + self.sldr_low.setMaximum(1) + self.sldr_low.setMinimum(0) + self.sldr_high.setMaximum(1) + self.sldr_high.setMinimum(0) + + def editImageProperties(self, item): + """function to control the assigned properties such as color, + threshold limits, opacity etc of a single image selected using the list widget item""" + editItem = item.text() + # get the dictionary key from item text + editItemName = editItem.split(",")[0] + editItemColor = editItem.split(",")[1] + im_array = self.image_dict[editItemName]["Image"] + + self.cb_choose_color.setCurrentText(editItemColor) + + def updateImageDictionary(self): + newColor = self.cb_choose_color.currentText() + editItem = self.listWidget.currentItem().text() + editRow = self.listWidget.currentRow() + editItemName = editItem.split(",")[0] + self.imageDir = self.image_dict[editItemName]["ImageDir"] + im_array = self.image_dict[editItemName]["Image"] + cmap_limits = (self.sldr_low.value(),self.sldr_high.value()) + self.low_high_vals.setText(f"low:{cmap_limits[0]:.3f},high:{cmap_limits[1]:.3f}") + opacity = self.sldr_opacity.value() / 100 + self.opacity_val.setText(str(opacity)) + self.image_dict[editItemName] = { + "ImageName": editItemName, + "ImageDir": self.imageDir, + "Image": im_array, + "Color": newColor, + "CmapLimits": cmap_limits, + "Opacity": opacity, + } + + self.createMultiColorView(self.image_dict) + self.displayImageNames(self.image_dict) + self.listWidget.setCurrentRow(editRow) + + def exportState(self): + + file_name = QtWidgets.QFileDialog().getSaveFileName( + self, "Save Current State", "multicolor_params.json", "json file(*json)" + ) + """ + for val in self.image_dict.values(): + val['CmapLimits'] = json.dumps(str(val['CmapLimits'])) + """ + + if file_name[0]: + + with open(f"{file_name[0]}", "w") as fp: + json.dump(self.image_dict, fp, indent=4, cls=jsonEncoder) + + else: + pass + + def importState(self): + file_name = QtWidgets.QFileDialog().getOpenFileName( + self, "Open a State File", "", "json file(*json);;all_files (*)" + ) + if file_name[0]: + with open(file_name[0], "r") as fp: + self.image_dict = json.load(fp) + + self.createMultiColorView(self.image_dict) + self.displayImageNames(self.image_dict) + else: + pass + + def saveImage(self): + file_name = QtWidgets.QFileDialog().getSaveFileName( + self, "Save Image", "multicolor_image.png", "PNG(*.png);; TIFF(*.tiff);; JPG(*.jpg)" + ) + exporter = pg.exporters.ImageExporter(self.canvas.getViewBox()) + exporter.export(file_name[0]) + + def saveTiffData(self): + file_name = QtWidgets.QFileDialog().getSaveFileName(self, "Save Image", 'stack_image_data.tiff', + 'TIFF(*.tiff)') + saveStack = [image_property['Image'] for image_property in self.image_dict.values()] + print(np.shape(saveStack)) + + if file_name[0]: + tf.imwrite(file_name[0], saveStack) + else: + return + diff --git a/xmidas/gui/windows/singleStackViewer.py b/xmidas/gui/windows/singleStackViewer.py new file mode 100644 index 0000000..e1ddf86 --- /dev/null +++ b/xmidas/gui/windows/singleStackViewer.py @@ -0,0 +1,95 @@ +import argparse +import logging +import datetime +import sys +import webbrowser +import traceback +import os +import json + +import numpy as np +import pandas as pd +import tifffile as tf +import pyqtgraph as pg + + +from PyQt6 import QtWidgets, QtCore, QtGui, uic, QtTest +from PyQt6.QtGui import QMovie +from PyQt6.QtWidgets import QMessageBox, QFileDialog, QApplication +from PyQt6.QtCore import QObject, pyqtSignal, pyqtSlot, QRunnable, QThreadPool, PYQT_VERSION_STR + +from utils import * +from utils.color_maps import * + +cmap_dict = create_color_maps() + +#from . import __version__ + +logger = logging.getLogger() +try: + import cv2 # noqa: F401 +except Exception: + logger.warning("openCV module not found") + pass +if hasattr(QtCore.Qt, "AA_EnableHighDpiScaling"): + QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True) + +if hasattr(QtCore.Qt, "AA_UseHighDpiPixmaps"): + QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True) + +ui_dir = os.path.normpath(os.path.join( + os.path.dirname(os.path.abspath(__file__)), + "../layout" +)) + + +class singleStackViewer(QtWidgets.QMainWindow): + def __init__(self, img_stack, gradient="viridis"): + super(singleStackViewer, self).__init__() + + # Load the UI Page + uic.loadUi(os.path.join(ui_dir, "singleStackView.ui"), self) + self.user_wd = os.path.abspath("~") + + self.image_view.ui.menuBtn.hide() + self.image_view.ui.roiBtn.hide() + + self.img_stack = img_stack + self.gradient = gradient + self.image_view.setPredefinedGradient(gradient) + + if self.img_stack.ndim == 3: + self.dim1, self.dim3, self.dim2 = img_stack.shape + elif self.img_stack.ndim == 2: + self.dim3, self.dim2 = img_stack.shape + self.dim1 = 1 + self.hs_img_stack.setMaximum(self.dim1 - 1) + self.hs_img_stack.setValue(np.round(self.dim1 / 2)) + self.displayStack() + + # connections + self.hs_img_stack.valueChanged.connect(self.displayStack) + self.actionSave.triggered.connect(self.saveImageStackAsTIFF) + + def displayStack(self): + im_index = self.hs_img_stack.value() + if self.img_stack.ndim == 2: + self.image_view.setImage(self.img_stack) + else: + self.image_view.setImage(self.img_stack[im_index]) + self.label_img_count.setText(f"{im_index + 1}/{self.dim1}") + + def saveImageStackAsTIFF(self): + file_name = QFileDialog().getSaveFileName(self, + "Export Stack", + os.path.join(self.user_wd, "image_stack.tiff"), + "*.tiff;;*.tif") + if file_name[0]: + if self.img_stack.ndim == 3: + tf.imwrite(file_name[0], np.float32(self.img_stack.transpose(0, 2, 1))) + elif self.img_stack.ndim == 2: + tf.imwrite(file_name[0], np.float32(self.img_stack.T)) + + self.user_wd = os.path.dirname(file_name[0]) + else: + pass diff --git a/xmidas/gui/windows/xanes_viewer.py b/xmidas/gui/windows/xanes_viewer.py new file mode 100644 index 0000000..49b9d87 --- /dev/null +++ b/xmidas/gui/windows/xanes_viewer.py @@ -0,0 +1,1320 @@ +import argparse +import logging +import sys +import webbrowser +import traceback +import os +import json +import scipy.stats as stats +import numpy as np +import pandas as pd +import tifffile as tf +import pyqtgraph as pg +import pyqtgraph.exporters +from glob import glob +from pyqtgraph import plot +from itertools import combinations +from scipy.stats import linregress +from packaging import version + + +from PyQt6 import QtWidgets, QtCore, QtGui, uic, QtTest +from PyQt6.QtGui import QMovie +from PyQt6.QtWidgets import QMessageBox, QFileDialog, QApplication +from PyQt6.QtCore import QObject, pyqtSignal, pyqtSlot, QRunnable, QThreadPool, PYQT_VERSION_STR + +from utils import * +from utils.color_maps import * +from models.encoders import jsonEncoder +from utils.utils import xanes_fitting, xanes_fitting_1D, xanes_fitting_Binned +cmap_dict = create_color_maps() +ui_dir = os.path.normpath(os.path.join( + os.path.dirname(os.path.abspath(__file__)), + "../layout" +)) + +from gui.windows.multichannel_viewer import MultiChannelWindow +from gui.windows.decomposition_viewer import * + + +class XANESViewer(QtWidgets.QMainWindow): + def __init__(self, im_stack=None, e_list=None, refs=None, ref_names=None): + super(XANESViewer, self).__init__() + + uic.loadUi(os.path.join(ui_dir, "XANESViewer.ui"), self) + self.user_wd = os.path.abspath("~") + self.centralwidget.setStyleSheet(open(os.path.join(ui_dir, "css/defaultStyle.css")).read()) + + self.im_stack = im_stack + self.e_list = e_list + self.refs = refs + self.ref_names = ref_names + self.selected = self.ref_names + self.fitResultDict = {} + self.fit_method = self.cb_xanes_fit_model.currentText() + self.alphaForLM = self.dsb_alphaForLM.value() + self.xpixel = None + self.ypixel = None + self.xdata_eshifted= self.e_list + self.sb_e_shift.value() + self.decon_ims, self.rfactor, self.coeffs_arr = xanes_fitting( + self.im_stack, + self.xdata_eshifted, + self.refs, + method=self.fit_method, + alphaForLM=self.alphaForLM) + + self.add_roi() + self.add_point_item() + self.scrollBar_setup() + self.display_image_data() + self.display_references() + self.fit_roi_spectrum() + + # connections + self.sb_e_shift.valueChanged.connect(self.fit_roi_spectrum) + self.pb_re_fit.clicked.connect(self.re_fit_xanes) + self.pb_edit_refs.clicked.connect(self.choose_refs) + self.image_roi.sigRegionChanged.connect(self.fit_roi_spectrum) + self.hsb_xanes_stk.valueChanged.connect(self.display_image_data) + self.hsb_chem_map.valueChanged.connect(self.display_image_data) + # self.pb_showMultiColor.clicked.connect(self.generateMultiColorView) + # self.pb_showCompSpec.clicked.connect(self.showComponentXANES) + self.pb_showCompSpec.clicked.connect(self.generateCompoisteImageSpectrumView) + self.image_view.mousePressEvent = self.fit_point_spectrum + #self.image_view_maps.mousePressEvent = self.fit_point_spectrum + + # menu + self.actionSave_Chem_Map.triggered.connect(self.save_chem_map) + self.actionSave_R_factor_Image.triggered.connect(self.save_rfactor_img) + #self.actionSave_Live_Fit_Data.triggered.connect(self.pg_export_spec_fit) + self.actionSave_Live_Fit_Data.triggered.connect(lambda:self.export_data_and_params(folder=None)) + self.actionExport_Fit_Stats.triggered.connect(self.exportFitResults) + self.actionExport_Ref_Plot.triggered.connect(self.pg_export_references) + self.action_export_sum_fit_data.triggered.connect(lambda:self.plot_sum_spectrum_and_save(save_to=None)) + self.pb_open_mask_maker.clicked.connect(self.create_masked_xanes) + self.pb_open_cluster_mask.clicked.connect(self.create_decmpose_mask) + self.pb_norm_chem_map.clicked.connect(self.normalize_chem_map) + self.pb_cluster_chem_map.clicked.connect(self.cluster_chem_map) + + def add_roi(self): + (self.dim1, self.dim2, self.dim3) = self.im_stack.shape + self.cn = int(self.dim2 // 2) + self.sz = np.max([int(self.dim2 * 0.15), int(self.dim3 * 0.15)]) + self.stack_center = int(self.dim1 // 2) + self.image_roi = pg.RectROI( + [int(self.dim3 // 2), int(self.dim2 // 2)], + [self.sz, self.sz], + pen="w", + maxBounds=QtCore.QRectF(0, 0, self.dim3, self.dim2), + ) + self.image_roi.addTranslateHandle([0, 0], [2, 2]) + self.image_roi.addRotateHandle([0, 1], [2, 2]) + try: + self.image_view.removeItem(self.image_roi) + except: pass + + self.image_view.addItem(self.image_roi) + + def add_point_item(self): + self.clicked_point = pg.ScatterPlotItem( + size=9, + pen=pg.mkPen(None), + brush=pg.mkBrush(255, 255, 255), + hoverable=True, + hoverBrush=pg.mkBrush(255, 16, 240) + ) + self.clicked_point_for_map = pg.ScatterPlotItem( + size=9, + pen=pg.mkPen(None), + brush=pg.mkBrush(255, 255, 255), + hoverable=True, + hoverBrush=pg.mkBrush(255, 16, 240) + ) + try: + self.image_view.removeItem(self.clicked_point) + self.image_view_maps.removeItem(self.clicked_point_for_map) + except: pass + + self.image_view.addItem(self.clicked_point) + self.image_view_maps.addItem(self.clicked_point_for_map) + # Ensure scatterPlotItem is always at top + self.clicked_point.setZValue(2) + + + def scrollBar_setup(self): + self.hsb_xanes_stk.setValue(self.stack_center) + self.hsb_xanes_stk.setMaximum(self.dim1 - 1) + self.hsb_chem_map.setValue(0) + self.hsb_chem_map.setMaximum(self.decon_ims.shape[-1] - 1) + + + def import_stack(self): + filename = QFileDialog().getOpenFileName( + self, "Select image data", self.user_wd, "image file( *tiff *tif )" + ) + self.file_name = str(filename[0]) + self.user_wd = os.path.dirname(self.file_name) + + if filename[0]: + self.im_stack = tf.imread(filename[0]) + + #TODO import energy, look for default files first, if not open file dialogue, + #raise cannot proceed + + # if str(self.efilePath).endswith("log_tiff.txt"): + # self.energy = energy_from_logfile(logfile=str(self.efilePath)) + # logger.info("Log file from pyxrf processing") + + # else: + # self.energy = np.loadtxt(str(self.efilePath)) + # self.change_color_on_load(self.pb_elist_xanes) + # logger.info("Energy file loaded") + + self.decon_ims, self.rfactor, self.coeffs_arr = xanes_fitting(self.im_stack, + self.xdata_eshifted, + self.refs, + method=self.fit_method, + alphaForLM=self.alphaForLM + ) + + self.add_roi() + self.add_point_item() + self.scrollBar_setup() + self.display_image_data() + self.display_references() + self.fit_roi_spectrum() + + def display_image_data(self): + + self.image_view.setImage(self.im_stack[self.hsb_xanes_stk.value()]) + self.image_view.ui.menuBtn.hide() + self.image_view.ui.roiBtn.hide() + self.image_view.setPredefinedGradient("viridis") + + self.image_view_maps.setImage(self.decon_ims.transpose(2, 0, 1)[self.hsb_chem_map.value()]) + self.image_view_maps.setPredefinedGradient("bipolar") + self.image_view_maps.ui.menuBtn.hide() + self.image_view_maps.ui.roiBtn.hide() + + def display_references(self): + + self.inter_ref = interploate_E(self.refs, self.xdata_eshifted) + self.plt_colors = ["c", "m", "y", "w"] * 10 + self.spectrum_view_refs.addLegend() + for ii in range(self.inter_ref.shape[0]): + if len(self.selected) != 0: + self.spectrum_view_refs.plot( + self.xdata_eshifted, + self.inter_ref[ii], + pen=pg.mkPen(self.plt_colors[ii], width=2), + name=self.selected[1:][ii], + ) + else: + self.spectrum_view_refs.plot( + self.xdata_eshifted, + self.inter_ref[ii], + pen=pg.mkPen(self.plt_colors[ii], width=2), + name="ref" + str(ii + 1), + ) + + def choose_refs(self): + "Interactively exclude some standards from the reference file" + self.ref_edit_window = RefChooser( + self.ref_names, + self.im_stack, + self.e_list, + self.refs, + self.sb_e_shift.value(), + self.cb_xanes_fit_model.currentText(), + ) + self.ref_edit_window.show() + # self.rf_plot = pg.plot(title="RFactor Tracker") + + # connections + self.ref_edit_window.choosenRefsSignal.connect(self.update_refs) + self.ref_edit_window.fitResultsSignal.connect(self.plotFitResults) + + + def create_masked_xanes(self): + "create mask and apply to xanes 3d array" + + self.mask_creator = MaskMaker(self.im_stack,self.decon_ims.transpose(2, 0, 1)[self.hsb_chem_map.value()]) + self.mask_creator.show() + + #connections + self.mask_creator.mask_signal.connect(self.apply_mask_to_xanes) + + def create_decmpose_mask(self): + + self.decomposer = DecomposeViewer(self.im_stack,None,self.xdata_eshifted) + self.decomposer.show() + #connections + self.decomposer.mask_signal.connect(self.apply_mask_to_xanes) + self.decomposer.mask_and_path_signal.connect(self.recieve_mask_and_save) + + def cluster_chem_map(self): + + self.decomposer2 = DecomposeViewer(self.decon_ims.transpose(2, 0, 1)[self.hsb_chem_map.value()], + self.im_stack, + self.xdata_eshifted) + + + # self.decomposer2 = DecomposeViewer(self.decon_ims.transpose(2, 0, 1), + # self.im_stack, + # self.xdata_eshifted) + self.decomposer2.show() + #connections + self.decomposer2.mask_signal.connect(self.apply_mask_to_xanes) + self.decomposer2.mask_and_path_signal.connect(self.recieve_mask_and_save) + + def plot_sum_spectrum(self): + self.xdata_eshifted = self.e_list + self.sb_e_shift.value() + self.ydata1 = get_sum_spectra(self.im_stack) + self.plot_data_and_fit() + self.re_fit_xanes() + + + def plot_sum_spectrum_and_save(self, save_to = None): + self.xdata_eshifted = self.e_list + self.sb_e_shift.value() + self.ydata1 = get_sum_spectra(self.im_stack) + self.plot_data_and_fit(plot_name="Sum Spectrum") + self.re_fit_xanes() + self.export_data_and_params(folder=save_to) + + def recieve_mask_and_save(self,signals): + self.apply_mask_to_xanes(signals[0]) + QtTest.QTest.qWait(5000) + self.plot_sum_spectrum_and_save(save_to = signals[1]) + QtTest.QTest.qWait(2000) + + + def normalize_chem_map(self): + + stack_ = normalize_and_scale(self.decon_ims.transpose(2, 0, 1)) + self.decon_ims = stack_.transpose(1, 2, 0) + self.display_image_data() + + + def apply_mask_to_xanes(self, masked_array): + + """ Apply the recieved mask and plot mean spectrum and fit """ + + #self.im_stack = self.im_stack*mask[np.newaxis,:,:] + self.im_stack = masked_array + self.display_image_data() + self.xdata_eshifted = self.e_list + self.sb_e_shift.value() + self.ydata1 = get_mean_spectra(self.im_stack) + self.plot_data_and_fit() + self.re_fit_xanes() + + def update_refs(self, list_): + self.selected = list_ # list_ is the signal from ref chooser + self.fit_roi_spectrum() + self.re_fit_xanes() + + def fit_point_spectrum(self, event): + if event.type() == QtCore.QEvent.MouseButtonDblClick: + if event.button() == QtCore.Qt.LeftButton: + self.xpixel = int(self.image_view.view.mapSceneToView(event.pos()).x()) + zlim, ylim, xlim = self.im_stack.shape + + if self.xpixel > xlim: + self.xpixel = xlim + + self.ypixel = int(self.image_view.view.mapSceneToView(event.pos()).y()) + if self.ypixel > ylim: + self.ypixel = ylim + + self.clicked_point.setData(pos=[[self.xpixel+0.5,self.ypixel+0.5],]) + self.clicked_point_for_map.setData(pos=[[self.xpixel+0.5,self.ypixel+0.5],]) + self.xdata_eshifted = self.e_list + self.sb_e_shift.value() + self.ydata1 = self.im_stack[:, self.ypixel, self.xpixel] + + self.plot_data_and_fit(plot_name=f"Point Spectrum; x= {self.xpixel}, y= {self.ypixel}") + + def plot_data_and_fit(self, plot_name = "Data"): + + if self.cb_normalize_before_fit.isChecked(): + self.ydata1 =self.ydata1/self.ydata1[-1] + + self.fit_method = self.cb_xanes_fit_model.currentText() + self.spectrum_view.addLegend() + if len(self.selected) != 0: + + self.inter_ref = interploate_E(self.refs[self.selected], self.xdata_eshifted) + stats, coeffs = xanes_fitting_1D( + self.ydata1, + self.xdata_eshifted, + self.refs[self.selected], + method=self.fit_method, + alphaForLM=self.alphaForLM, + ) + + else: + self.inter_ref = interploate_E(self.refs, self.xdata_eshifted) + stats, coeffs = xanes_fitting_1D( + self.ydata1, self.xdata_eshifted, self.refs, method=self.fit_method, alphaForLM=self.alphaForLM + ) + + self.fit_ = np.dot(coeffs, self.inter_ref) + pen = pg.mkPen("b", width=1.5) + pen2 = pg.mkPen("r", width=1.5) + # pen3 = pg.mkPen("y", width=1.5) + self.spectrum_view.addLegend() + self.spectrum_view.setLabel("bottom", "Energy") + self.spectrum_view.setLabel("left", "Intensity", "A.U.") + self.spectrum_view.plot(self.xdata_eshifted, + self.ydata1, + pen=pen, + clear=True, + symbol="o", + symbolSize=6, + symbolBrush="b", + name=f"{plot_name}") + + self.spectrum_view.plot(self.xdata_eshifted, self.fit_, name="Fit", pen=pen2) + + for n, (coff, ref, plt_clr) in enumerate(zip(coeffs, self.inter_ref, self.plt_colors)): + + if len(self.selected) != 0: + + self.spectrum_view.plot(self.xdata_eshifted, np.dot(coff, ref), name=self.selected[1:][n], pen=plt_clr) + else: + self.spectrum_view.plot(self.xdata_eshifted, np.dot(coff, ref), name="ref" + str(n + 1), pen=plt_clr) + # set the rfactor value to the line edit slot + self.results = { + "ref_stds":self.selected[1:], + "Coefficients":coeffs, + "R-Factor": stats['R_Factor'], + "R-Square": stats['R_Square'], + "Chi-Square": stats['Chi_Square'], + "Reduced Chi-Square": stats['Reduced Chi_Square']} + + self.fit_results.setText("\n".join(f"{key}: {value}" for key, value in self.results.items())) + + def fit_roi_spectrum(self): + + self.roi_img = self.image_roi.getArrayRegion(self.im_stack, self.image_view.imageItem, axes=(1, 2)) + sizex, sizey = self.roi_img.shape[1], self.roi_img.shape[2] + posx, posy = self.image_roi.pos() + self.roi_info.setText(f"ROI_Pos: {int(posx)},{int(posy)} ROI_Size: {sizex},{sizey}") + + self.xdata_eshifted = self.e_list + self.sb_e_shift.value() + self.ydata1 = get_mean_spectra(self.roi_img) + + self.plot_data_and_fit(plot_name="ROI Spectrum") + + def re_fit_xanes(self): + self.fit_params = {"e_shit":self.sb_e_shift.value(), + "method":self.cb_xanes_fit_model.currentText(), + "regularization":self.dsb_alphaForLM.value()} + + + if len(self.selected) != 0: + self.decon_ims, self.rfactor, self.coeffs_arr = xanes_fitting( + self.im_stack, + self.e_list + self.sb_e_shift.value(), + self.refs[self.selected], + method=self.cb_xanes_fit_model.currentText(), + alphaForLM=self.alphaForLM, + ) + else: + # if non athena file with no header is loaded no ref file cannot be edited + self.decon_ims, self.rfactor, self.coeffs_arr = xanes_fitting( + self.im_stack, + self.e_list + self.sb_e_shift.value(), + self.refs, + method=self.cb_xanes_fit_model.currentText(), + alphaForLM=self.alphaForLM, + ) + + # rfactor is a list of all spectra so take the mean + self.rfactor_mean = np.mean(self.rfactor) + self.image_view_maps.setImage(self.decon_ims.transpose(2, 0, 1)) + self.scrollBar_setup() + + def plotFitResults(self, decon_ims, rfactor_mean, coeff_array): + # upadte the chem maps and scrollbar params + self.image_view_maps.setImage(decon_ims.transpose(2, 0, 1)) + self.hsb_chem_map.setValue(0) + self.hsb_chem_map.setMaximum(decon_ims.shape[-1]-1) + + # set the rfactor value to the line edit slot + self.le_r_sq.setText(f"{rfactor_mean :.4f}") + + def showComponentXANES(self): + compNum = self.hsb_chem_map.value() + currentComp = self.decon_ims.transpose(2, 0, 1)[compNum] + currentCompMask = currentComp > 0 + yData = applyMaskGetMeanSpectrum(self.im_stack, currentCompMask) + xanes_comp_plot = pg.plot( + self.e_list + self.sb_e_shift.value(), + yData, + title=f"Component_{compNum}", + pen=pg.mkPen("y", width=2, style=QtCore.Qt.DotLine), + symbol="o", + ) + xanes_comp_plot.setLabel("bottom", "Energy (keV)") + xanes_comp_plot.setLabel("left", "Intensity") + + def plotDeconvSpectrum(self, clusterSigma=0): + + try: + self.ref_plot.close() + + except: + pass + + self.ref_plot = plot(title="Deconvoluted XANES Spectra") + self.ref_plot.setLabel("bottom", "Energy") + self.ref_plot.setLabel("left", "Intensity") + self.ref_plot.addLegend() + + for n, compImage in enumerate(self.decon_ims.transpose(2, 0, 1)): + mask = np.where(compImage > clusterSigma * np.std(compImage), compImage, 0) + + self.ref_plot.plot( + self.xdata_eshifted, + get_mean_spectra(self.im_stack * mask), + pen=pg.mkPen(self.plt_colors[n], width=2), + name=f'Component_{n + 1}' + ) + + def generateCompoisteImageSpectrumView(self): + self.multichanneldict = {} + + spectrumDF = getDeconvolutedXANESSpectrum(self.im_stack, self.decon_ims.transpose(2, 0, 1), + self.xdata_eshifted, clusterSigma=0) + + for n, (colorName, image) in enumerate(zip(cmap_dict.keys(), self.decon_ims.transpose((2, 0, 1)))): + low, high = np.min(image), np.max(image) + self.multichanneldict[f'Image {n + 1}'] = {'ImageName': f'Image {n + 1}', + 'ImageDir': '.', + 'Image': image, + 'Color': colorName, + 'CmapLimits': (low, high), + 'Opacity': 1.0 + } + self.muli_color_window = MultiXANESWindow(image_dict=self.multichanneldict, spec_df=spectrumDF) + self.muli_color_window.show() + + def generateMultiColorView(self): + self.multichanneldict = {} + + for n, (colorName, image) in enumerate(zip(cmap_dict.keys(), self.decon_ims.transpose((2, 0, 1)))): + low, high = np.min(image), np.max(image) + self.multichanneldict[f"Image {n + 1}"] = { + "ImageName": f"Image {n + 1}", + "ImageDir": ".", + "Image": image, + "Color": colorName, + "CmapLimits": (low, high), + "Opacity": 1.0, + } + self.muli_color_window = MultiChannelWindow(image_dict=self.multichanneldict) + self.muli_color_window.show() + + def save_chem_map(self): + file_name = QFileDialog().getSaveFileName(self, + "save image", + os.path.join(self.user_wd,"chemical_map.tiff"), + "image data (*tiff)") + if file_name[0]: + tf.imwrite(file_name[0], np.float32(self.decon_ims.transpose(2, 0, 1))) + self.user_wd = os.path.dirname(file_name[0]) + else: + logger.error("No file to save") + pass + + def save_rfactor_img(self): + file_name = QFileDialog().getSaveFileName(self, + "save image", + os.path.join(self.user_wd,"r-factor_map.tiff"), + "image data (*tiff)") + if file_name[0]: + tf.imwrite(file_name[0], np.float32(self.rfactor), imagej=True) + self.user_wd = os.path.dirname(file_name[0]) + else: + logger.error("No file to save") + pass + + def save_spec_fit(self): + try: + to_save = np.column_stack([self.xdata_eshifted, self.ydata1, self.fit_]) + file_name = QFileDialog().getSaveFileName(self, + "save spectrum", + os.path.join(self.user_wd,"spec_fit.txt"), + "spectrum and fit (*txt)") + if file_name[0]: + np.savetxt(file_name[0] + ".txt", to_save) + self.user_wd = os.path.dirname(file_name[0]) + else: + pass + except Exception: + logger.error("No file to save") + pass + + def pg_export_spec_fit(self): + + exporter = pg.exporters.CSVExporter(self.spectrum_view.plotItem) + exporter.parameters()["columnMode"] = "(x,y,y,y) for all plots" + file_name = QFileDialog().getSaveFileName(self, + "save spectrum", + os.path.join(self.user_wd,"spec_fit.txt"), + "spectrum and fit (*csv)") + if file_name[0]: + exporter.export(file_name[0] + ".csv") + self.user_wd = os.path.dirname(file_name[0]) + else: + pass + + def pg_export_references(self): + + exporter = pg.exporters.CSVExporter(self.spectrum_view_refs.plotItem) + exporter.parameters()["columnMode"] = "(x,y,y,y) for all plots" + file_name = QFileDialog().getSaveFileName(self, + "save references", + os.path.join(self.user_wd,"xanes_references.csv"), + "column data (*csv)" + ) + if file_name[0]: + exporter.export(file_name[0]) + self.user_wd = os.path.dirname(file_name[0]) + else: + pass + + def exportFitResults(self): + file_name = QFileDialog().getSaveFileName(self, + "save txt", + os.path.join(self.user_wd,"xanes_1D_fit_results.json"), + "txt data (*txt)") + if file_name[0]: + with open(file_name[0], "w") as file: + json.dump(self.results, file, indent=4) + self.user_wd = os.path.dirname(file_name[0]) + else: + pass + + def export_data_and_params(self, folder = None): + + if folder is None: + file_name,_ = QFileDialog().getSaveFileName(self, + "save to folder", + os.path.join(self.user_wd, "xanes_data"), + options = QFileDialog.ShowDirsOnly) + + else: + file_name = folder + exporter_csv = pg.exporters.CSVExporter(self.spectrum_view.plotItem) + exporter_csv.parameters()["columnMode"] = '(x,y) per plot' + exporter_csv.parameters()["separator"] = 'comma' + + exporter_png = pg.exporters.ImageExporter(self.spectrum_view.getViewBox()) + exporter_img_png = pg.exporters.ImageExporter(self.image_view.getView()) + + exporter_svg = pg.exporters.SVGExporter(self.spectrum_view.getViewBox()) + exporter_img_svg = pg.exporters.SVGExporter(self.image_view.getView()) + + if file_name: + os.makedirs(file_name[0], exist_ok=True) + os.makedirs(os.path.join(file_name+"/csv_files"), exist_ok=True) + os.makedirs(os.path.join(file_name+"/png_files"), exist_ok=True) + os.makedirs(os.path.join(file_name+"/svg_files"), exist_ok=True) + os.makedirs(os.path.join(file_name+"/tiff_files"), exist_ok=True) + exporter_csv.export(os.path.join(file_name+"/csv_files/xanes_fit.csv")) + exporter_png.export(os.path.join(file_name+"/png_files/xanes_fit_image.png")) + exporter_img_png.export(os.path.join(file_name+"/png_files/stack_image.png")) + exporter_svg.export(os.path.join(file_name+"/svg_files/xanes_fit.svg")) + exporter_img_svg.export(os.path.join(file_name+"/svg_files/stack_image.svg")) + + tf.imwrite(os.path.join(file_name+"/tiff_files/chem_map.tiff"), np.float32(self.decon_ims.transpose(2, 0, 1))) + tf.imwrite(os.path.join(file_name+"/tiff_files/rfactor.tiff"), np.float32(self.rfactor), imagej=True) + tf.imwrite(os.path.join(file_name+"/tiff_files/stack_image.tiff"), np.float32(self.im_stack[self.hsb_xanes_stk.value()])) + + roi_and_pixel_params = {"sizex":self.roi_img.shape[1],"sizey":self.roi_img.shape[2], + "posx":self.image_roi.pos()[0],"posy":self.image_roi.pos()[1], + "pixelx":self.xpixel, "pixely":self.ypixel} + + self.fit_params = {"e_shit":self.sb_e_shift.value(), + "method":self.cb_xanes_fit_model.currentText(), + "regularization":self.dsb_alphaForLM.value()} + export_params = {"fit_params":self.fit_params, + "roi_or_pixel_params":roi_and_pixel_params, + "fit_results":self.results} + + with open(os.path.join(file_name+"/fit_params.json"), "w") as fp: + json.dump(export_params, fp, indent=4, cls = jsonEncoder) + self.user_wd = os.path.dirname(file_name) + QMessageBox.information(self,"Saved", f"data saved to {self.user_wd}") + +class RefChooser(QtWidgets.QMainWindow): + choosenRefsSignal: pyqtSignal = QtCore.pyqtSignal(list) + fitResultsSignal: pyqtSignal = QtCore.pyqtSignal(np.ndarray, float, np.ndarray) + + def __init__(self, ref_names, im_stack, e_list, refs, e_shift, fit_model): + super(RefChooser, self).__init__() + uic.loadUi(os.path.join(ui_dir, "RefChooser.ui"), self) + self.user_wd = os.path.abspath("~") + self.centralwidget.setStyleSheet(open(os.path.join(ui_dir, "css/defaultStyle.css")).read()) + self.ref_names = ref_names + self.refs = refs + self.im_stack = im_stack + self.e_list = e_list + self.e_shift = e_shift + self.fit_model = fit_model + + self.all_boxes = [] + self.rFactorList = [] + + self.displayCombinations() + + # selection become more apparent than default with red-ish color + self.tableWidget.setStyleSheet("background-color: white; selection-background-color: rgb(200,0,0);") + + # add a line to the plot to walk through the table. Note that the table is not sorted + self.selectionLine = pg.InfiniteLine( + pos=1, angle=90, pen=pg.mkPen("m", width=2.5), movable=True, bounds=None, label="Move Me!" + ) + self.stat_view.setLabel("bottom", "Fit ID") + self.stat_view.setLabel("left", "Reduced Chi^2") + + for n, i in enumerate(self.ref_names): + self.cb_i = QtWidgets.QCheckBox(self.ref_box_frame) + if n == 0: + self.cb_i.setChecked(True) + self.cb_i.setEnabled(False) + self.cb_i.setObjectName(i) + self.cb_i.setText(i) + self.gridLayout_2.addWidget(self.cb_i, n, 0, 1, 1) + self.cb_i.toggled.connect(self.enableApply) + self.all_boxes.append(self.cb_i) + + # connections + self.pb_apply.clicked.connect(self.clickedWhichAre) + self.pb_combo.clicked.connect(self.tryAllCombo) + self.actionExport_Results_csv.triggered.connect(self.exportFitResults) + self.selectionLine.sigPositionChanged.connect(self.updateFitWithLine) + self.tableWidget.itemSelectionChanged.connect(self.updateWithTableSelection) + # self.stat_view.scene().sigMouseClicked.connect(self.moveSelectionLine) + self.stat_view.mouseDoubleClickEvent = self.moveSelectionLine + self.sb_max_combo.valueChanged.connect(self.displayCombinations) + # self.pb_sort_with_r.clicked.connect(lambda: self.tableWidget.sortItems(3, QtCore.Qt.AscendingOrder)) + self.pb_sort_with_r.clicked.connect(self.sortTable) + self.cb_sorter.currentTextChanged.connect(self.sortTable) + + def clickedWhich(self): + button_name = self.sender() + + def populateChecked(self): + self.onlyCheckedBoxes = [] + for names in self.all_boxes: + if names.isChecked(): + self.onlyCheckedBoxes.append(names.objectName()) + + QtCore.pyqtSlot() + + def clickedWhichAre(self): + self.populateChecked() + self.choosenRefsSignal.emit(self.onlyCheckedBoxes) + + def generateRefList(self, ref_list, maxCombo, minCombo=1): + + """ + Creates a list of reference combinations for xanes fitting + + Paramaters; + + ref_list (list): list of ref names from the header + maxCombo (int): maximum number of ref lists in combination + minCombo (int): min number of ref lists in combination + + returns; + + 1. int: length of total number of combinations + 2. list: all the combinations + + """ + + if not maxCombo > len(ref_list): + + iter_list = [] + while minCombo < maxCombo + 1: + iter_list += list(combinations(ref_list, minCombo)) + minCombo += 1 + return len(iter_list), iter_list + + else: + raise ValueError(" Maximum numbinations cannot be larger than number of list items") + + def displayCombinations(self): + niter, self.iter_list = self.generateRefList(self.ref_names[1:], self.sb_max_combo.value()) + self.label_nComb.setText(str(niter) + " Combinations") + + @QtCore.pyqtSlot() + def tryAllCombo(self): + # empty list to to keep track and plot of reduced chi2 of all the fits + self.rfactor_list = [] + + # create dataframe for the table + self.df = pd.DataFrame( + columns=["Fit Number", "References", "Coefficients", "R-Factor", "R^2", "chi^2", "red-chi^2", "Score"] + ) + + # df columns is the header for the table widget + self.tableWidget.setHorizontalHeaderLabels(self.df.columns) + # self.iter_list = list(combinations(self.ref_names[1:],self.sb_max_combo.value())) + + niter, self.iter_list = self.generateRefList(self.ref_names[1:], self.sb_max_combo.value()) + tot_combo = len(self.iter_list) + for n, refs in enumerate(self.iter_list): + self.statusbar.showMessage(f"{n + 1}/{tot_combo}") + selectedRefs = list((str(self.ref_names[0]),) + refs) + self.fit_combo_progress.setValue((n + 1) * 100 / tot_combo) + self.stat, self.coeffs_arr = xanes_fitting_Binned( + self.im_stack, self.e_list + self.e_shift, self.refs[selectedRefs], method=self.fit_model + ) + + self.rfactor_list.append(self.stat["Reduced Chi_Square"]) + self.stat_view.plot( + x=np.arange(n + 1), + y=self.rfactor_list, + clear=True, + title="Reduced Chi^2", + pen=pg.mkPen("y", width=2, style=QtCore.Qt.DotLine), + symbol="o", + ) + + # arbitary number to rank the best fit + fit_score = (self.stat["R_Square"] + np.sum(self.coeffs_arr)) / ( + self.stat["R_Factor"] + self.stat["Reduced Chi_Square"] + ) + + resultsDict = { + "Fit Number": n, + "References": str(selectedRefs[1:]), + "Coefficients": str(np.around(self.coeffs_arr, 4)), + "Sum of Coefficients": str(np.around(np.sum(self.coeffs_arr), 4)), + "R-Factor": self.stat["R_Factor"], + "R^2": self.stat["R_Square"], + "chi^2": self.stat["Chi_Square"], + "red-chi^2": self.stat["Reduced Chi_Square"], + "Score": np.around(fit_score, 4), + } + + self.df = pd.concat([self.df, pd.DataFrame([resultsDict])], ignore_index=True) + + self.dataFrametoQTable(self.df) + QtTest.QTest.qWait(0.1) # hepls with real time plotting + + self.stat_view.addItem(self.selectionLine) + + def dataFrametoQTable(self, df_: pd.DataFrame): + nRows = len(df_.index) + nColumns = len(df_.columns) + self.tableWidget.setRowCount(nRows) + self.tableWidget.setColumnCount(nColumns) + self.tableWidget.setHorizontalHeaderLabels(df_.columns) + + for i in range(nRows): + for j in range(nColumns): + cell = QtWidgets.QTableWidgetItem(str(df_.values[i][j])) + self.tableWidget.setItem(i, j, cell) + + # set the property of the table view. Size policy to make the contents justified + self.tableWidget.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents) + self.tableWidget.resizeColumnsToContents() + + def exportFitResults(self): + file_name = QFileDialog().getSaveFileName(self, "save csv", "xanes_fit_results_log.csv", "txt data (*csv)") + if file_name[0]: + with open(file_name[0], "w") as fp: + self.df.to_csv(fp) + else: + pass + + def selectTableAndCheckBox(self, x): + nSelection = int(round(x)) + self.tableWidget.selectRow(nSelection) + fit_num = int(self.tableWidget.item(nSelection, 0).text()) + refs_selected = self.iter_list[fit_num] + + # reset all the checkboxes to uncheck state, except the energy + for checkstate in self.findChildren(QtWidgets.QCheckBox): + if checkstate.isEnabled(): + checkstate.setChecked(False) + + for cb_names in refs_selected: + checkbox = self.findChild(QtWidgets.QCheckBox, name=cb_names) + checkbox.setChecked(True) + + def updateFitWithLine(self): + pos_x, pos_y = self.selectionLine.pos() + x = self.df.index[self.df[str("Fit Number")] == np.round(pos_x)][0] + self.selectTableAndCheckBox(x) + + def updateWithTableSelection(self): + x = self.tableWidget.currentRow() + self.selectTableAndCheckBox(x) + + def moveSelectionLine(self, event): + if event.button() == QtCore.Qt.LeftButton: + Pos = self.stat_view.plotItem.vb.mapSceneToView(event.pos()) + self.selectionLine.setPos(Pos.x()) + + def sortTable(self): + sorter_dict = { + "R-Factor": "R-Factor", + "R-Square": "R^2", + "Chi-Square": "chi^2", + "Reduced Chi-Square": "red-chi^2", + "Fit Number": "Fit Number", + } + sorter = sorter_dict[self.cb_sorter.currentText()] + self.df = self.df.sort_values(sorter, ignore_index=True) + self.dataFrametoQTable(self.df) + + def enableApply(self): + + """ """ + self.populateChecked() + if len(self.onlyCheckedBoxes) > 1: + self.pb_apply.setEnabled(True) + else: + self.pb_apply.setEnabled(False) + + + +class MultiXANESWindow(MultiChannelWindow): + + def __init__(self, image_dict=None, spec_df=None, references = None, ): + super().__init__(image_dict=None) + + self.image_dict = image_dict + self.spec_df = spec_df + + uic.loadUi(os.path.join(ui_dir, 'MultiImageSpectrumView.ui'), self) + self.user_wd = os.path.abspath("~") + # Copy from MultiChannelWindow Start here + self.canvas = self.img_view.addPlot(title="") + self.canvas.getViewBox().invertY(True) + #self.canvas.setZValue(-10) + self.canvas.setAspectLocked(True) + self.cb_choose_color.addItems([i for i in cmap_dict.keys()]) + #self.canvas.getViewBox().setBackgroundColor(pg.mkColor(222,222,222)) + #self.canvas.getViewBox().setOpacity(0.5) + + self.image_dict = image_dict + self.buildFromDictionary() + + self.actionLoad.triggered.connect(self.createMuliColorAndList) + self.actionLoad_Stack.triggered.connect(self.createMuliColorAndList) + self.cb_choose_color.currentTextChanged.connect(self.updateImageDictionary) + self.pb_update_low_high.clicked.connect(self.updateImageDictionary) + self.listWidget.itemClicked.connect(self.editImageProperties) + self.listWidget.itemDoubleClicked.connect(self.showOneImageOnly) + self.pb_show_selected.clicked.connect(self.showOneImageOnly) + self.pb_show_all.clicked.connect(self.showAllItems) + self.actionLoad_State_File.triggered.connect(self.importState) + self.actionSave_State.triggered.connect(self.exportState) + self.actionSave_View.triggered.connect(self.saveImage) + # Copy from MultiChannelWindow End here + self.actionSave_Spectrum_Data.triggered.connect(self.exportDisplayedSpectra) + self.listWidget_Spectrum.itemClicked.connect(self.plotNormSpectrum) + self.pb_apply_xanes_norm.clicked.connect(lambda: self.updateSpecData(plotNorm=True)) + self.createMultiSpectrumLibrary() + + [dsb.valueChanged.connect(lambda: self.updateSpecData()) for dsb in + [self.dsb_norm_Eo, self.dsb_norm_pre1, self.dsb_norm_pre2, self.dsb_norm_post1, + self.dsb_norm_post2, self.sb_norm_order]] + + def createSpectrumPropertyDict(self, specName, xdata, ydata, e0, pre1, pre2, norm1, norm2, normOrder): + SingleSpecProperty = {'Name': specName, + 'Data': (xdata, ydata), + 'NormParams': [e0, pre1, pre2, norm1, norm2, normOrder]} + + return SingleSpecProperty + + def createMultiSpectrumLibrary(self): + self.spec_dict = {} + column_names = self.spec_df.columns + spec_array = self.spec_df.to_numpy() + energy = spec_array[:, 0] + for i in range(self.spec_df.shape[1]): + if i != 0: + specData = spec_array[:, i] + e0_init = energy[np.argmax(np.gradient(specData))] + + pre1, pre2, post1, post2 = xanesNormalization( + energy, + specData, + e0=e0_init, + step=None, + nnorm=1, + nvict=0, + method = "guess" + ) + + self.spec_dict[column_names[i]] = self.createSpectrumPropertyDict(column_names[i], energy, specData, + e0_init, pre1, pre2, post1, post2, 1) + self.nomalizeSpectraAndPlot(self.spec_dict) + self.spectrumDictToListWidget() + + def nomalizeSpectraAndPlot(self, spectrumParamDict): + # print(self.spec_dict) + try: + self.spectrum_view.clear() + except: + pass + self.spectrum_view.setLabel("bottom", "Energy") + self.spectrum_view.setLabel("left", "Intensity") + self.spectrum_view.addLegend() + plt_colors = ['r', 'g', (31, 81, 255), 'c', 'm', 'y', 'w'] + for n, params in enumerate(spectrumParamDict.values()): + e0_ = params['NormParams'][0] + pre1_ = params['NormParams'][1] + pre2_ = params['NormParams'][2] + norm1_ = params['NormParams'][3] + norm2_ = params['NormParams'][4] + normOrder_ = params['NormParams'][5] + + preLine, postLine, self.normData = xanesNormalization( + params['Data'][0], + params['Data'][1], + e0=e0_, + step=None, + nnorm=normOrder_, + nvict=0, + pre1=pre1_, + pre2=pre2_, + norm1=norm1_, + norm2=norm2_ + ) + + # 'NormParams': (e0, pre1, pre2, norm1, norm2, normOrder)} + self.spectrum_view.plot(params['Data'][0], self.normData, + pen=pg.mkPen(plt_colors[n], width=2), + name=f"Norm._{params['Name']}") + + def loadAndPlotSpectrumData(self): + filter = 'txt (*.tiff);;csv (*.csv)' + file_name = QtWidgets.QFileDialog().getOpenFileName(self, "Open a spectrum file", '', + 'txt (*.tiff);;csv (*.csv);;all_files (*)', filter) + + if file_name[0]: + self.spec_df = pd.read_csv(file_name[0], index_col=None) + # print(self.spec_df.head()) + # print(self.spec_df.shape[1]) + self.createMultiSpectrumLibrary() + else: + return + + def spectrumDictToListWidget(self): + for params in self.spec_dict.values(): + # Creates a QListWidgetItem + specItem = QtWidgets.QListWidgetItem() + + # Setting QListWidgetItem Text + specItem.setText(params['Name']) + + # Setting your QListWidgetItem Data + specItem.setData(QtCore.Qt.UserRole, params) + + # Add the new rule to the QListWidget + self.listWidget_Spectrum.addItem(specItem) + + def plotNormSpectrum(self, item): + self.selectedItem = item + self.editItemName = self.selectedItem.text() + self.editItemData = self.selectedItem.data(QtCore.Qt.UserRole) + + e0_ = self.editItemData['NormParams'][0] + pre1_ = self.editItemData['NormParams'][1] + pre2_ = self.editItemData['NormParams'][2] + norm1_ = self.editItemData['NormParams'][3] + norm2_ = self.editItemData['NormParams'][4] + normOrder_ = self.editItemData['NormParams'][5] + + self.dsb_norm_Eo.setValue(e0_) # loop later + self.dsb_norm_pre1.setValue(pre1_) + self.dsb_norm_pre2.setValue(pre2_) + self.dsb_norm_post1.setValue(norm1_) + self.dsb_norm_post2.setValue(norm2_) + self.sb_norm_order.setValue(normOrder_) + + preLine, postLine, normSpec = xanesNormalization( + self.editItemData['Data'][0], + self.editItemData['Data'][1], + e0=e0_, + step=None, + nnorm=normOrder_, + nvict=0, + pre1=pre1_, + pre2=pre2_, + norm1=norm1_, + norm2=norm2_ + ) + + self.spectrum_view.clear() + self.spectrum_view.plot(self.editItemData['Data'][0], self.editItemData['Data'][1], + title=f"Normalization Plot_{self.editItemData['Name']}", + pen=pg.mkPen('y', width=2), name=self.editItemData['Name']) + self.spectrum_view.plot(self.editItemData['Data'][0], preLine, pen=pg.mkPen('c', width=2), name='Pre') + self.spectrum_view.plot(self.editItemData['Data'][0], postLine, pen=pg.mkPen('m', width=2), name='Norm') + + # def updateNormParamaters(self): + + def updateSpecData(self, plotNorm=False): + + # loop later + self.editItemData['NormParams'][0] = self.dsb_norm_Eo.value() + self.editItemData['NormParams'][1] = self.dsb_norm_pre1.value() + self.editItemData['NormParams'][2] = self.dsb_norm_pre2.value() + self.editItemData['NormParams'][3] = self.dsb_norm_post1.value() + self.editItemData['NormParams'][4] = self.dsb_norm_post2.value() + self.editItemData['NormParams'][5] = self.sb_norm_order.value() + + self.spec_dict[self.editItemName] = self.editItemData + self.selectedItem.setData(QtCore.Qt.UserRole, self.editItemData) + if plotNorm: + self.nomalizeSpectraAndPlot(self.spec_dict) + else: + self.plotNormSpectrum(self.selectedItem) + + def exportDisplayedSpectra(self): + exporter = pg.exporters.CSVExporter(self.spectrum_view.plotItem) + exporter.parameters()['columnMode'] = '(x,y,y,y) for all plots' + file_name = QFileDialog().getSaveFileName(self, "save spectra", 'xanes.csv', 'spectra (*csv)') + if file_name[0]: + exporter.export(file_name[0]) + else: + self.statusbar_main.showMessage('Saving cancelled') + pass + +class ChemMapViewer(MultiChannelWindow): + + def __init__(self, im_stack = None, + e_list=None, + refs = None, + ref_names = None, + chem_map = None, + fit_params = None): + + super().__init__(image_dict=None) + + self.im_stack = im_stack + self.e_list = e_list + self.refs = refs + self.ref_names = ref_names + self.chem_map = chem_map + self.fit_params = fit_params + + for n, (colorName, image) in enumerate(zip(cmap_dict.keys(), self.chem_map.transpose((2, 0, 1)))): + low, high = np.min(image), np.max(image) + self.image_dict[f'Image {n + 1}'] = {'ImageName': self.ref_names[n], + 'ImageDir': '.', + 'Image': image, + 'Color': colorName, + 'CmapLimits': (low, high), + 'Opacity': 1.0 + } + + uic.loadUi(os.path.join(ui_dir, 'MultiImageSpectrumView.ui'), self) + self.user_wd = os.path.abspath("~") + # Copy from MultiChannelWindow Start here + self.canvas = self.img_view.addPlot(title="") + self.canvas.getViewBox().invertY(True) + #self.canvas.setZValue(-10) + self.canvas.setAspectLocked(True) + self.cb_choose_color.addItems([i for i in cmap_dict.keys()]) + #self.canvas.getViewBox().setBackgroundColor(pg.mkColor(222,222,222)) + #self.canvas.getViewBox().setOpacity(0.5) + + self.buildFromDictionary() + + self.actionLoad.triggered.connect(self.createMuliColorAndList) + self.actionLoad_Stack.triggered.connect(self.createMuliColorAndList) + self.cb_choose_color.currentTextChanged.connect(self.updateImageDictionary) + self.pb_update_low_high.clicked.connect(self.updateImageDictionary) + self.listWidget.itemClicked.connect(self.editImageProperties) + self.listWidget.itemDoubleClicked.connect(self.showOneImageOnly) + self.pb_show_selected.clicked.connect(self.showOneImageOnly) + self.pb_show_all.clicked.connect(self.showAllItems) + self.actionLoad_State_File.triggered.connect(self.importState) + self.actionSave_State.triggered.connect(self.exportState) + self.actionSave_View.triggered.connect(self.saveImage) + + + # Copy from MultiChannelWindow End here + self.actionSave_Spectrum_Data.triggered.connect(self.exportDisplayedSpectra) + self.listWidget_Spectrum.itemClicked.connect(self.plotNormSpectrum) + self.pb_apply_xanes_norm.clicked.connect(lambda: self.updateSpecData(plotNorm=True)) + self.createMultiSpectrumLibrary() + + [dsb.valueChanged.connect(lambda: self.updateSpecData()) for dsb in + [self.dsb_norm_Eo, self.dsb_norm_pre1, self.dsb_norm_pre2, self.dsb_norm_post1, + self.dsb_norm_post2, self.sb_norm_order]] + + def createSpectrumPropertyDict(self, specName, xdata, ydata, e0, pre1, pre2, norm1, norm2, normOrder): + SingleSpecProperty = {'Name': specName, + 'Data': (xdata, ydata), + 'NormParams': [e0, pre1, pre2, norm1, norm2, normOrder]} + + return SingleSpecProperty + + def createMultiSpectrumLibrary(self): + self.spec_dict = {} + column_names = self.spec_df.columns + spec_array = self.spec_df.to_numpy() + energy = spec_array[:, 0] + for i in range(self.spec_df.shape[1]): + if i != 0: + specData = spec_array[:, i] + e0_init = energy[np.argmax(np.gradient(specData))] + + pre1, pre2, post1, post2 = xanesNormalization( + energy, + specData, + e0=e0_init, + step=None, + nnorm=1, + nvict=0, + method = "guess" + ) + + self.spec_dict[column_names[i]] = self.createSpectrumPropertyDict(column_names[i], energy, specData, + e0_init, pre1, pre2, post1, post2, 1) + self.nomalizeSpectraAndPlot(self.spec_dict) + self.spectrumDictToListWidget() + + def nomalizeSpectraAndPlot(self, spectrumParamDict): + # print(self.spec_dict) + try: + self.spectrum_view.clear() + except: + pass + self.spectrum_view.setLabel("bottom", "Energy") + self.spectrum_view.setLabel("left", "Intensity") + self.spectrum_view.addLegend() + plt_colors = ['r', 'g', (31, 81, 255), 'c', 'm', 'y', 'w'] + for n, params in enumerate(spectrumParamDict.values()): + e0_ = params['NormParams'][0] + pre1_ = params['NormParams'][1] + pre2_ = params['NormParams'][2] + norm1_ = params['NormParams'][3] + norm2_ = params['NormParams'][4] + normOrder_ = params['NormParams'][5] + + preLine, postLine, self.normData = xanesNormalization( + params['Data'][0], + params['Data'][1], + e0=e0_, + step=None, + nnorm=normOrder_, + nvict=0, + pre1=pre1_, + pre2=pre2_, + norm1=norm1_, + norm2=norm2_ + ) + + # 'NormParams': (e0, pre1, pre2, norm1, norm2, normOrder)} + self.spectrum_view.plot(params['Data'][0], self.normData, + pen=pg.mkPen(plt_colors[n], width=2), + name=f"Norm._{params['Name']}") + + def loadAndPlotSpectrumData(self): + filter = 'txt (*.tiff);;csv (*.csv)' + file_name = QtWidgets.QFileDialog().getOpenFileName(self, "Open a spectrum file", '', + 'txt (*.tiff);;csv (*.csv);;all_files (*)', filter) + + if file_name[0]: + self.spec_df = pd.read_csv(file_name[0], index_col=None) + # print(self.spec_df.head()) + # print(self.spec_df.shape[1]) + self.createMultiSpectrumLibrary() + else: + return + + def spectrumDictToListWidget(self): + for params in self.spec_dict.values(): + # Creates a QListWidgetItem + specItem = QtWidgets.QListWidgetItem() + + # Setting QListWidgetItem Text + specItem.setText(params['Name']) + + # Setting your QListWidgetItem Data + specItem.setData(QtCore.Qt.UserRole, params) + + # Add the new rule to the QListWidget + self.listWidget_Spectrum.addItem(specItem) + + def plotNormSpectrum(self, item): + self.selectedItem = item + self.editItemName = self.selectedItem.text() + self.editItemData = self.selectedItem.data(QtCore.Qt.UserRole) + + e0_ = self.editItemData['NormParams'][0] + pre1_ = self.editItemData['NormParams'][1] + pre2_ = self.editItemData['NormParams'][2] + norm1_ = self.editItemData['NormParams'][3] + norm2_ = self.editItemData['NormParams'][4] + normOrder_ = self.editItemData['NormParams'][5] + + self.dsb_norm_Eo.setValue(e0_) # loop later + self.dsb_norm_pre1.setValue(pre1_) + self.dsb_norm_pre2.setValue(pre2_) + self.dsb_norm_post1.setValue(norm1_) + self.dsb_norm_post2.setValue(norm2_) + self.sb_norm_order.setValue(normOrder_) + + preLine, postLine, normSpec = xanesNormalization( + self.editItemData['Data'][0], + self.editItemData['Data'][1], + e0=e0_, + step=None, + nnorm=normOrder_, + nvict=0, + pre1=pre1_, + pre2=pre2_, + norm1=norm1_, + norm2=norm2_ + ) + + self.spectrum_view.clear() + self.spectrum_view.plot(self.editItemData['Data'][0], self.editItemData['Data'][1], + title=f"Normalization Plot_{self.editItemData['Name']}", + pen=pg.mkPen('y', width=2), name=self.editItemData['Name']) + self.spectrum_view.plot(self.editItemData['Data'][0], preLine, pen=pg.mkPen('c', width=2), name='Pre') + self.spectrum_view.plot(self.editItemData['Data'][0], postLine, pen=pg.mkPen('m', width=2), name='Norm') + + # def updateNormParamaters(self): + + def updateSpecData(self, plotNorm=False): + + # loop later + self.editItemData['NormParams'][0] = self.dsb_norm_Eo.value() + self.editItemData['NormParams'][1] = self.dsb_norm_pre1.value() + self.editItemData['NormParams'][2] = self.dsb_norm_pre2.value() + self.editItemData['NormParams'][3] = self.dsb_norm_post1.value() + self.editItemData['NormParams'][4] = self.dsb_norm_post2.value() + self.editItemData['NormParams'][5] = self.sb_norm_order.value() + + self.spec_dict[self.editItemName] = self.editItemData + self.selectedItem.setData(QtCore.Qt.UserRole, self.editItemData) + if plotNorm: + self.nomalizeSpectraAndPlot(self.spec_dict) + else: + self.plotNormSpectrum(self.selectedItem) + + def exportDisplayedSpectra(self): + exporter = pg.exporters.CSVExporter(self.spectrum_view.plotItem) + exporter.parameters()['columnMode'] = '(x,y,y,y) for all plots' + file_name = QFileDialog().getSaveFileName(self, "save spectra", 'xanes.csv', 'spectra (*csv)') + if file_name[0]: + exporter.export(file_name[0]) + else: + self.statusbar_main.showMessage('Saving cancelled') + pass + + diff --git a/xmidas/models/encoders.py b/xmidas/models/encoders.py new file mode 100644 index 0000000..4f5dcc0 --- /dev/null +++ b/xmidas/models/encoders.py @@ -0,0 +1,13 @@ +import json +import numpy as np + +class jsonEncoder(json.JSONEncoder): + def default(self, obj): + if isinstance(obj, np.integer): + return int(obj) + elif isinstance(obj, np.floating): + return float(obj) + elif isinstance(obj, np.ndarray): + return obj.tolist() + else: + return super(jsonEncoder, self).default(obj) \ No newline at end of file diff --git a/xmidas/utils/color_maps.py b/xmidas/utils/color_maps.py new file mode 100644 index 0000000..9c9742c --- /dev/null +++ b/xmidas/utils/color_maps.py @@ -0,0 +1,28 @@ +from itertools import combinations +import pyqtgraph as pg + +def create_color_maps(): + cmap_names = ["CET-L13", "CET-L14", "CET-L15"] + cmap_combo = combinations(cmap_names, 2) + cmap_label1 = ["red", "green", "blue"] + cmap_label2 = ["yellow", "magenta", "cyan"] + cmap_dict = {} + for i, name in zip(cmap_names, cmap_label1): + cmap_dict[name] = pg.colormap.get(i).getLookupTable(alpha=True) + + for i, name in zip(cmap_combo, cmap_label2): + cmap_dict[name] = pg.colormap.get(i[0]).getLookupTable(alpha=True) + pg.colormap.get(i[1]).getLookupTable( + alpha=True + ) + cmap_dict[name][:, 3] = 255 + + grey = ( + pg.colormap.get("CET-L13").getLookupTable(alpha=True) + + pg.colormap.get("CET-L14").getLookupTable(alpha=True) + + pg.colormap.get("CET-L15").getLookupTable(alpha=True) + ) + + grey[:, 3] = 255 + cmap_dict["grey"] = grey + + return cmap_dict \ No newline at end of file diff --git a/xmidas/utils/larch_norm.py b/xmidas/utils/larch_norm.py new file mode 100644 index 0000000..37dda6c --- /dev/null +++ b/xmidas/utils/larch_norm.py @@ -0,0 +1,119 @@ +import numpy as np + +def preedge(energy, mu, e0=None, npre=1, pre1=None, pre2=None, nvict=0): + energy = np.asarray(energy) + mu = np.asarray(mu) + + # 1) determine e0 + if e0 is None: + deriv = np.gradient(mu, energy) + ie0 = np.nanargmax(np.abs(deriv)) + e0 = energy[ie0] + else: + ie0 = np.argmin(np.abs(energy - e0)) + e0 = energy[ie0] + + # 2) default regions + dE = energy[1] - energy[0] + pre1 = -2 * dE if pre1 is None else pre1 + pre2 = -0.5 * dE if pre2 is None else pre2 + + # 3) ensure ordering + if pre1 > pre2: + pre1, pre2 = pre2, pre1 + + low, high = e0 + pre1, e0 + pre2 + mask = (energy >= low) & (energy <= high) + + # 4) fallback if too few points + if np.sum(mask) < (npre + 1): + idx0 = max(ie0 - (npre + 1), 0) + mask = np.zeros_like(mask, bool) + mask[idx0:ie0] = True + + x = energy[mask] + y = mu[mask] * x**nvict + + # 5) fit baseline + if npre == 0 or x.size == 0: + val = np.mean(y) if y.size else np.mean(mu[:2]) + pre_edge = np.full_like(mu, val) + else: + coef = np.polyfit(x, y, 1) + baseline = np.polyval(coef, energy) + pre_edge = baseline * energy**(-nvict) + + return e0, ie0, pre_edge + + +def normalize(energy, mu, pre_edge, e0, + norm1=None, norm2=None, nnorm=1): + energy = np.asarray(energy) + mu = np.asarray(mu) + dE = energy[1] - energy[0] + + # 1) default norms + norm1 = 2 * dE if norm1 is None else norm1 + norm2 = 10 * dE if norm2 is None else norm2 + + # 2) ensure ordering + if norm1 > norm2: + norm1, norm2 = norm2, norm1 + + low, high = e0 + norm1, e0 + norm2 + mask = (energy >= low) & (energy <= high) + + # 3) fallback to points just above edge + min_pts = nnorm + 1 + if np.sum(mask) < min_pts: + i0 = np.argmin(np.abs(energy - e0)) + start = min(i0 + 1, len(energy) - min_pts) + mask = np.zeros_like(mask, bool) + mask[start:start + min_pts] = True + + x = energy[mask] + y = (mu - pre_edge)[mask] + + # 4) fit poly + coef = ([0] * (nnorm + 1) if x.size == 0 + else np.polyfit(x, y, nnorm)) + poly = np.polyval(coef, energy) + post_edge = pre_edge + poly + + # 5) compute step & norm + ie0 = np.argmin(np.abs(energy - e0)) + edge_step = post_edge[ie0] - pre_edge[ie0] + edge_step = abs(edge_step) if edge_step != 0 else 1e-12 + norm = (mu - pre_edge) / edge_step + + return post_edge, norm, edge_step + + + +def pre_edge_simple(energy, mu, **kwargs): + """ + Combined pre-edge subtraction and normalization. + + Returns + ------- + dict with keys: e0, edge_step, pre_edge, post_edge, norm + """ + e0, ie0, pre_edge_arr = preedge(energy, mu, + e0=kwargs.get('e0', None), + npre=kwargs.get('npre', 1), + pre1=kwargs.get('pre1', None), + pre2=kwargs.get('pre2', None), + nvict=kwargs.get('nvict', 0)) + post_edge, norm_arr, edge_step = normalize( + energy, mu, pre_edge_arr, e0, + norm1=kwargs.get('norm1', None), + norm2=kwargs.get('norm2', None), + nnorm=kwargs.get('nnorm', 1) + ) + return { + 'e0': e0, + 'edge_step': edge_step, + 'pre_edge': pre_edge_arr, + 'post_edge': post_edge, + 'norm': norm_arr + } diff --git a/xmidas/utils/utils.py b/xmidas/utils/utils.py new file mode 100644 index 0000000..151e852 --- /dev/null +++ b/xmidas/utils/utils.py @@ -0,0 +1,1153 @@ +""" Helper Functions (make a class later)""" + + +import h5py +import logging +import numpy as np +import pandas as pd +import os +import scipy.optimize as opt +import scipy.stats as stats + +import sklearn.decomposition as sd +import sklearn.cluster as sc +from scipy.signal import savgol_filter +from skimage.transform import resize +from skimage import filters +from sklearn import linear_model +from utils.larch_norm import pre_edge_simple +# from larch.xafs import pre_edge, preedge, mback +# from larch.io import read_ascii, read_athena +# from larch import Group +import xraydb +from pystackreg import StackReg + +logger = logging.getLogger() + +def get_xrf_data(h='h5file'): + """ + get xrf stack from h5 data generated at NSLS-II beamlines + + Arguments: + h5/hdf5 file + + Returns: + norm_xrf_stack - xrf stack image normalized with Io + mono_e - excitation enegy used for xrf + beamline - identity of the beamline + Io_avg - an average Io value, used before taking log + + """ + + f = h5py.File(h, "r") + + if list(f.keys())[0] == "xrfmap": + logger.info("Data from HXN/TES/SRX") + beamline = f["xrfmap/scan_metadata"].attrs["scan_instrument_id"] + + try: + + beamline_scalar = {"HXN": 2, "SRX": 0, "TES": 0} + + if beamline in beamline_scalar.keys(): + + Io = np.array(f["xrfmap/scalers/val"])[:, :, beamline_scalar[beamline]] + raw_xrf_stack = np.array(f["xrfmap/detsum/counts"]) + norm_xrf_stack = raw_xrf_stack + Io_avg = int(remove_nan_inf(Io).mean()) + else: + logger.error("Unknown Beamline Scalar") + except Exception: + logger.warning("Unknown Scalar: Raw Detector count in use") + norm_xrf_stack = np.array(f["xrfmap/detsum/counts"]) + + elif list(f.keys())[0] == "xrmmap": + logger.info("Data from XFM") + beamline = "XFM" + raw_xrf_stack = np.array(f["xrmmap/mcasum/counts"]) + Io = np.array(f["xrmmap/scalars/I0"]) + norm_xrf_stack = raw_xrf_stack + Io_avg = int(remove_nan_inf(Io).mean()) + + elif list(f.keys())[0] == "MAPS": + logger.info("MAPS file") + beamline = "APS" + raw_xrf_stack = np.array(f["MAPS/Spectra/mca_arr"]) + Io = 1 #have to find the name of the scalar + norm_xrf_stack = raw_xrf_stack.transpose((1, 2, 0)) + Io_avg = int(remove_nan_inf(Io).mean()) + + else: + logger.error("Unknown Data Format") + + try: + mono_e = int(f["xrfmap/scan_metadata"].attrs["instrument_mono_incident_energy"] * 1000) + logger.info("Excitation energy was taken from the h5 data") + + except Exception: + mono_e = 12000 + logger.info(f"Unable to get Excitation energy from the h5 data; using default value {mono_e} KeV") + + return remove_nan_inf(norm_xrf_stack.transpose((2, 0, 1))), mono_e + 1500, beamline, Io_avg + + +def remove_nan_inf(im): + im = np.array(im, dtype=np.float32) + im[np.isnan(im)] = 0 + im[np.isinf(im)] = 0 + return im + + +def rebin_image(im, bin_factor): + arrx, arry = np.shape(im) + if arrx / bin_factor != int or arrx / bin_factor != int: + logger.error("Invalid Binning") + + else: + shape = (arrx / bin_factor, arry / bin_factor) + return im.reshape(shape).mean(-1).mean(1) + + +def remove_hot_pixels(image_array, NSigma=5): + image_array = remove_nan_inf(image_array) + a, b, c = np.shape(image_array) + img_stack2 = np.zeros((a, b, c)) + for i in range(a): + im = image_array[i, :, :] + im[abs(im) > np.std(im) * NSigma] = im.mean() + img_stack2[i, :, :] = im + return img_stack2 + + +def smoothen(image_array, w_size=5): + a, b, c = np.shape(image_array) + spec2D_Matrix = np.reshape(image_array, (a, (b * c))) + smooth2D_Matrix = savgol_filter(spec2D_Matrix, w_size, w_size - 2, axis=0) + return remove_nan_inf(np.reshape(smooth2D_Matrix, (a, b, c))) + + +def resize_stack(image_array, upscaling=False, scaling_factor=2): + en, im1, im2 = np.shape(image_array) + + if upscaling: + im1_ = im1 * scaling_factor + im2_ = im2 * scaling_factor + img_stack_resized = resize(image_array, (en, im1_, im2_)) + + else: + im1_ = int(im1 / scaling_factor) + im2_ = int(im2 / scaling_factor) + img_stack_resized = resize(image_array, (en, im1_, im2_)) + + return img_stack_resized + + +def normalize(image_array, norm_point=-1): + norm_stack = image_array / image_array[norm_point] + return remove_nan_inf(norm_stack) + + +def remove_edges(image_array): + # z, x, y = np.shape(image_array) + return image_array[:, 1:-1, 1:-1] + + +def background_value(image_array): + img = image_array.mean(0) + img_h = img.mean(0) + img_v = img.mean(1) + h = np.gradient(img_h) + v = np.gradient(img_v) + bg = np.min([img_h[h == h.max()], img_v[v == v.max()]]) + return bg + + +def background_subtraction(img_stack, bg_percentage=10): + img_stack = remove_nan_inf(img_stack) + a, b, c = np.shape(img_stack) + ref_image = np.reshape(img_stack.mean(0), (b * c)) + bg_ratio = int((b * c) * 0.01 * bg_percentage) + bg_ = np.max(sorted(ref_image)[0:bg_ratio]) + bged_img_stack = img_stack - bg_[:, np.newaxis, np.newaxis] + return bged_img_stack + + +def background_subtraction2(img_stack, bg_percentage=10): + img_stack = remove_nan_inf(img_stack) + a, b, c = np.shape(img_stack) + bg_ratio = int((b * c) * 0.01 * bg_percentage) + bged_img_stack = img_stack.copy() + + for n, img in enumerate(img_stack): + bg_ = np.max(sorted(img.flatten())[0:bg_ratio]) + print(bg_) + bged_img_stack[n] = img - bg_ + + return remove_nan_inf(bged_img_stack) + + +def background1(img_stack): + img = img_stack.sum(0) + img_h = img.mean(0) + img_v = img.mean(1) + h = np.gradient(img_h) + v = np.gradient(img_v) + bg = np.min([img_h[h == h.max()], img_v[v == v.max()]]) + return bg + + +def get_sum_spectra(image_array): + spec = np.nansum(image_array, axis=(1, 2)) + return spec + + +def get_mean_spectra(image_array): + spec = np.nanmean(image_array, axis=(1, 2)) + return spec + + +def flatten_(image_array): + z, x, y = np.shape(image_array) + flat_array = np.reshape(image_array, (x * y, z)) + return flat_array + + +def image_to_pandas(image_array): + a, b, c = np.shape(image_array) + im_array = np.reshape(image_array, ((b * c), a)) + a, b = im_array.shape + df = pd.DataFrame( + data=im_array[:, :], columns=["e" + str(i) for i in range(b)], + index=["s" + str(i) for i in range(a)] + ) + return df + + +def image_to_pandas2(image_array): + a, b, c = np.shape(image_array) + im_array = np.reshape(image_array, (a, (b * c))) + a, b = im_array.shape + df = pd.DataFrame( + data=im_array[:, :], index=["e" + str(i) for i in range(a)], + columns=["s" + str(i) for i in range(b)] + ) + return df + + +def neg_log(image_array): + absorb = -1 * np.log(image_array) + return remove_nan_inf(absorb) + + +def clean_stack(img_stack, auto_bg=False, bg_percentage=5): + a, b, c = np.shape(img_stack) + + if auto_bg is True: + bg_ = background1(img_stack) + + else: + sum_spec = (img_stack.sum(1)).sum(1) + ref_stk_num = np.where(sum_spec == sum_spec.max())[-1] + + ref_image = np.reshape(img_stack[ref_stk_num], (b * c)) + bg_ratio = int((b * c) * 0.01 * bg_percentage) + bg_ = np.max(sorted(ref_image)[0:bg_ratio]) + + bg = np.where(img_stack[ref_stk_num] > bg_, img_stack[ref_stk_num], 0) + bg2 = np.where(bg < bg_, bg, 1) + + bged_img_stack = img_stack * bg2 + + return remove_nan_inf(bged_img_stack) + + +def subtractBackground(im_stack, bg_region): + if bg_region.ndim == 3: + bg_region_ = np.mean(bg_region, axis=(1, 2)) + + elif bg_region.ndim == 2: + bg_region_ = np.mean(bg_region, axis=1) + + else: + bg_region_ = bg_region + + return im_stack - bg_region_[:, np.newaxis, np.newaxis] + + +def classify(img_stack, correlation="Pearson"): + img_stack_ = img_stack + a, b, c = np.shape(img_stack_) + norm_img_stack = normalize(img_stack_) + f = np.reshape(norm_img_stack, (a, (b * c))) + + max_x, max_y = np.where(norm_img_stack.sum(0) == (norm_img_stack.sum(0)).max()) + ref = norm_img_stack[:, int(max_x), int(max_y)] + corr = np.zeros(len(f.T)) + for s in range(len(f.T)): + if correlation == "Kendall": + r, p = stats.kendalltau(ref, f.T[s]) + elif correlation == "Pearson": + r, p = stats.pearsonr(ref, f.T[s]) + + corr[s] = r + + cluster_image = np.reshape(corr, (b, c)) + return (cluster_image ** 3), img_stack_ + + +def correlation_kmeans(img_stack, n_clusters, correlation="Pearson"): + img, bg_image = classify(img_stack, correlation) + img[np.isnan(img)] = -99999 + X = img.reshape((-1, 1)) + k_means = sc.KMeans(n_clusters) + k_means.fit(X) + + X_cluster = k_means.labels_ + X_cluster = X_cluster.reshape(img.shape) + 1 + + return X_cluster + + +def cluster_stack( + im_array, method="KMeans", n_clusters_=4, decomposed=False, + decompose_method="PCA", decompose_comp=2 + ): + a, b, c = im_array.shape + + if method == "Correlation-Kmeans": + + X_cluster = correlation_kmeans(im_array, n_clusters_, correlation="Pearson") + + else: + + methods = { + "MiniBatchKMeans": sc.MiniBatchKMeans, + "KMeans": sc.KMeans, + "MeanShift": sc.MeanShift, + "Spectral Clustering": sc.SpectralClustering, + "Affinity Propagation": sc.AffinityPropagation, + } + + if decomposed: + im_array = denoise_with_decomposition(im_array, method_=decompose_method, + n_components=decompose_comp) + + flat_array = np.reshape(im_array, (a, (b * c))) + init_cluster = methods[method](n_clusters=n_clusters_) + init_cluster.fit(np.transpose(flat_array)) + X_cluster = init_cluster.labels_.reshape(b, c) + 1 + + decon_spectra = np.zeros((a, n_clusters_)) + decon_images = np.zeros((n_clusters_, b, c)) + + for i in range(n_clusters_): + mask_i = np.where(X_cluster == (i + 1), X_cluster, 0) + spec_i = get_sum_spectra(im_array * mask_i) + decon_spectra[:, i] = spec_i + decon_images[i] = im_array.sum(0) * mask_i + + return decon_images, X_cluster, decon_spectra + +def kmeans_variance(im_array): + a, b, c = im_array.shape + flat_array = np.reshape(im_array, (a, (b * c))) + var = np.arange(24) + clust_n = np.arange(24) + 2 + + for clust in var: + init_cluster = sc.KMeans(n_clusters=int(clust + 2)) + init_cluster.fit(np.transpose(flat_array)) + var_ = init_cluster.inertia_ + var[clust] = np.float64(var_) + + return clust_n, var + + +def pca_scree(im_stack): + new_image = im_stack.transpose(2, 1, 0) + x, y, z = np.shape(new_image) + img_ = np.reshape(new_image, (x * y, z)) + # pca = sd.PCA(z) + # pca.fit(img_) + pca = sd.TruncatedSVD(z - 1) + pca.fit(img_) + var = pca.singular_values_ + # var = pca.singular_values_ + return var + + +def decompose_stack(im_stack, decompose_method="PCA", + n_components_=3, generate_label_img = True): + + new_image = im_stack.transpose(2, 1, 0) + new_image[new_image<0] = 0 + + x, y, z = np.shape(new_image) + img_ = np.reshape(new_image, (x * y, z)) + methods_dict = { + "PCA": sd.PCA, + "IncrementalPCA": sd.IncrementalPCA, + "NMF": sd.NMF, + "FastICA": sd.FastICA, + "DictionaryLearning": sd.MiniBatchDictionaryLearning, + "FactorAnalysis": sd.FactorAnalysis, + "TruncatedSVD": sd.TruncatedSVD, + } + + _mdl = methods_dict[decompose_method](n_components=n_components_) + + ims = (_mdl.fit_transform(img_).reshape(x, y, n_components_)).transpose(2, 1, 0) + spcs = _mdl.components_.transpose() + decon_spetra = np.zeros((z, n_components_)) + decom_map = np.zeros((ims.shape)) + + if generate_label_img: + for i in range(n_components_): + f = ims.copy()[i] + f[f < 0] = 0 + f = np.where(f > 0 * np.std(f), f, 0) + spec_i = ((new_image.T * f).sum(1)).sum(1) + decon_spetra[:, i] = spec_i + + f[f > 0] = i + 1 + decom_map[i] = f + decom_map = decom_map.sum(0) + + return np.float32(ims), spcs, decon_spetra, decom_map + + + +def denoise_with_decomposition(img_stack, method_="PCA", n_components=4): + new_image = img_stack.transpose(2, 1, 0) + x, y, z = np.shape(new_image) + img_ = np.reshape(new_image, (x * y, z)) + + methods_dict = { + "PCA": sd.PCA, + "IncrementalPCA": sd.IncrementalPCA, + "NMF": sd.NMF, + "FastICA": sd.FastICA, + "DictionaryLearning": sd.DictionaryLearning, + "FactorAnalysis": sd.FactorAnalysis, + "TruncatedSVD": sd.TruncatedSVD, + } + + decomposed = methods_dict[method_](n_components=n_components) + + ims = (decomposed.fit_transform(img_).reshape(x, y, n_components)).transpose(2, 1, 0) + ims[ims < 0] = 0 + ims[ims > 0] = 1 + mask = ims.sum(0) + mask[mask > 1] = 1 + # mask = uniform_filter(mask) + filtered = img_stack * mask + # plt.figure() + # plt.imshow(filtered.sum(0)) + # plt.title('background removed') + # plt.show() + return remove_nan_inf(filtered) + + +def interploate_E(refs, e): + n = np.shape(refs)[1] + refs = np.array(refs) + ref_e = refs[:, 0] + ref = refs[:, 1:n] + all_ref = [] + for i in range(n - 1): + ref_i = np.interp(e, ref_e, ref[:, i]) + all_ref.append(ref_i) + return np.array(all_ref) + +def rfactor(spectrum_experimental, spectrum_fit): + r""" + Computes R-factor based on two spectra + + Parameters + ---------- + spectrum_experimental : ndarray + spectrum data on which fitting is performed (N elements) + + spectrum_fit : ndarray + fitted spectrum (weighted sum of spectrum components, N elements) + + Returns + ------- + float, the value of R-factor + """ + + # Compute R-factor + dif = spectrum_experimental - spectrum_fit + dif_sum = np.sum(np.abs(dif), axis=0) + data_sum = np.sum(np.abs(spectrum_experimental), axis=0) + + # Avoid accidental division by zero (or a very small number) + data_sum = np.clip(data_sum, a_min=1e-30, a_max=None) + + return dif_sum / data_sum + +def rfactor_compute(spectrum, fit_results, ref_spectra): + r""" + Computes R-factor for the fitting results + + Parameters + ---------- + spectrum : ndarray + spectrum data on which fitting is performed (N elements) + + fit_results : ndarray + results of fitting (coefficients, K elements) + + ref_spectra : 2D ndarray + reference spectra used for fitting (NxK element array) + + Returns + ------- + float, the value of R-factor + """ + + # Check if input parameters are valid + assert ( + spectrum.ndim == 1 or spectrum.ndim == 2 + ), "Parameter 'spectrum' must be 1D or 2D array, ({spectrum.ndim})" + assert spectrum.ndim == fit_results.ndim, ( + f"Spectrum data (ndim = {spectrum.ndim}) and fitting results " + f"(ndim = {fit_results.ndim}) must have the same number of dimensions" + ) + assert ref_spectra.ndim == 2, "Parameter 'ref_spectra' must be 2D array, ({ref_spectra.ndim})" + assert spectrum.shape[0] == ref_spectra.shape[0], ( + f"Arrays 'spectrum' ({spectrum.shape}) and 'ref_spectra' ({ref_spectra.shape}) " + "must have the same number of data points" + ) + assert fit_results.shape[0] == ref_spectra.shape[1], ( + f"Arrays 'fit_results' ({fit_results.shape}) and 'ref_spectra' ({ref_spectra.shape}) " + "must have the same number of spectrum points" + ) + if spectrum.ndim == 2: # Only if multiple spectra are processed + assert spectrum.shape[1] == fit_results.shape[1], ( + f"Arrays 'spectrum' {spectrum.shape} and 'fit_results' {fit_results.shape}" + "must have the same number of columns" + ) + + spectrum_fit = np.matmul(ref_spectra, fit_results) + return rfactor(spectrum, spectrum_fit) + + +def fitting_admm(data, ref_spectra, *, rate=0.2, maxiter=100, epsilon=1e-30, + non_negative=True, weight_to_whiteline = False): + r""" + Fitting of multiple spectra using ADMM method. + + Parameters + ---------- + + data : ndarray(float), 2D + array holding multiple observed spectra, shape (K, N), where K is the number of energy points, + and N is the number of spectra + + absorption_refs : ndarray(float), 2D + array of references, shape (K, Q), where Q is the number of references. + + maxiter : int + maximum number of iterations. Optimization may stop prematurely if convergence criteria are met. + + rate : float + descent rate for optimization algorithm. Currently is used only for ADMM fitting (1/lambda). + + epsilon : float + small value used in stopping criterion of ADMM optimization algorithm. + + non_negative : bool + if True, then the solution is guaranteed to be non-negative + + Returns + ------- + + map_data_fitted : ndarray(float), 2D + fitting results, shape (Q, N), where Q is the number of references and N is the number of spectra. + + map_rfactor : ndarray(float), 2D + map that represents R-factor for the fitting, shape (M,N). + + convergence : ndarray(float), 1D + convergence data returned by ADMM algorithm + + feasibility : ndarray(float), 1D + feasibility data returned by ADMM algorithm + + The prototype for the ADMM fitting function was implemented by Hanfei Yan in Matlab. + """ + #print(type(data)) + if data.ndim == 1: + data = np.expand_dims(data, axis=1) #"Data array 'data' must have 2 dimensions" + #print(type(data)) + assert ref_spectra.ndim == 2, "Data array 'ref_spectra' must have 2 dimensions" + + n_pts = data.shape[0] + n_pixels = data.shape[1] + n_pts_2 = ref_spectra.shape[0] + n_refs = ref_spectra.shape[1] + + assert ( + n_pts == n_pts_2 + ), f"ADMM fitting: number of spectrum points in data ({n_pts}) and references ({n_pts_2}) do not match." + + assert rate > 0.0, f"ADMM fitting: parameter 'rate' is zero or negative ({rate:.6g})" + + assert maxiter > 0, f"ADMM fitting: parameter 'maxiter' is zero or negative ({rate})" + + assert epsilon > 0.0, f"ADMM fitting: parameter 'epsilon' is zero or negative ({rate:.6g})" + + wgt = np.ones(len(data)) + + #print(wgt) + + if weight_to_whiteline: + wgt[0:-15] = 0.4 + wgt[-25:-1]=0.5 + + #print(wgt) + + y = data + # Calculate some quantity to be used in the iteration + A = ref_spectra + At = np.transpose(A) + #print(np.shape(At), np.shape(y), np.shape(np.diag(wgt))) + #print(np.diag(wgt)) + + z = A.T @ np.diag(wgt) @ y + c = A.T @ np.diag(wgt) @ A + + # Initialize variables + w = np.ones(shape=[n_refs, n_pixels]) + u = np.zeros(shape=[n_refs, n_pixels]) + + # Feasibility test: x == w + convergence = np.zeros(shape=[maxiter]) + feasibility = np.zeros(shape=[maxiter]) + + dg = np.eye(n_refs, dtype=float) * rate + m1 = np.linalg.inv((c + dg)) + + n_iter = 0 + for i in range(maxiter): + m2 = z + (w - u) * rate + x = np.matmul(m1, m2) + w_updated = x + u + if non_negative: + w_updated = w_updated.clip(min=0) + u = u + x - w_updated + + conv = np.linalg.norm(w_updated - w) / np.linalg.norm(w_updated) + convergence[i] = conv + feasibility[i] = np.linalg.norm(x - w_updated) + + w = w_updated + + if conv < epsilon: + n_iter = i + 1 + break + + # Compute R-factor + rfactor = rfactor_compute(data, w, ref_spectra) + #rfactor = 1 + + convergence = convergence[:n_iter] + feasibility = feasibility[:n_iter] + + return w, rfactor, convergence, feasibility + + +def getStats(spec, fit, num_refs=2): + stats = {} + + SS_tot = np.sum((spec - np.mean(spec))**2) + SS_res = np.sum((spec - fit) ** 2) + #r_factor = (np.sum(spec - fit) ** 2) / np.sum(spec ** 2) + r_factor = 1 - (SS_res / SS_tot) #temp to get r2 array for paper + stats["R_Factor"] = np.around(r_factor, 5) + + y_mean = np.sum(spec) / len(spec) + #SS_tot = np.sum((spec - y_mean) ** 2) + + r_square = 1 - (SS_res / SS_tot) + stats["R_Square"] = np.around(r_square, 4) + + # https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.chisquare.html + # https://en.wikipedia.org/wiki/Chi-squared_distribution + # https://ned.ipac.caltech.edu/level5/Leo/Stats2_4.html + chisq = np.sum(((spec - fit) ** 2) / np.var(spec)) + # chisq = np.sum((spec - fit) ** 2) + stats["Chi_Square"] = np.around(chisq, 5) + + red_chisq = chisq / (len(spec) - num_refs) + stats["Reduced Chi_Square"] = np.around(red_chisq, 5) + + return stats + + +def xanes_fitting_1D(spec, e_list, refs, + method="NNLS", alphaForLM=0.01): + + """Linear combination fit of image data with reference standards""" + + #check for energy unit in e_list vs ref + #print(f"at 1D fit function{e_list[0]}") + + + # #energy list should be corrected for shifts before passing here + # if len(str(int(e_list[0]))) <3: + # e_list *=1000 + # #print(e_list) + + # #print(refs[0][0]) + # if len(str(int(refs[0][0]))) <3: + # refs[:,0] =refs[:,0]*1000 + # #print(refs[0]) + + spec = np.nan_to_num(spec) + refs = np.nan_to_num(refs) + int_refs = interploate_E(refs, e_list) + + + if method == "NNLS": + coeffs, r = opt.nnls(int_refs.T, spec) + #print(f"{coeffs}: nnls") + + elif method == "LASSO": + lasso = linear_model.Lasso(positive=True, alpha=alphaForLM) # lowering alpha helps with 1D fits + fit_results = lasso.fit(int_refs.T, spec) + coeffs = fit_results.coef_ + + elif method == "RIDGE": + ridge = linear_model.Ridge(alpha=alphaForLM) + fit_results = ridge.fit(int_refs.T, spec) + coeffs = fit_results.coef_ + + elif method == "ADMM": + coeffs,r_factor,convergence, feasibility = fitting_admm(spec, + int_refs.T, + maxiter=100, + rate=alphaForLM, + epsilon=1e-30) + coeffs = np.squeeze(coeffs.T) + # print(f"{coeffs}; ADMM") + + fit = np.dot(coeffs , int_refs) + stats = getStats(spec, fit, num_refs=np.min(np.shape(int_refs.T))) + + return stats, coeffs + + +def xanes_fitting(im_stack, e_list, refs, method="NNLS", alphaForLM=0.1, binStack=False): + """Linear combination fit of image data with reference standards""" + + if binStack: + im_stack = resize_stack(im_stack, scaling_factor=4) + + en, im1, im2 = np.shape(im_stack) + im_array = im_stack.reshape(en, im1 * im2) + coeffs_arr = [] + r_factor_arr = [] + lasso = linear_model.Lasso(positive=True, alpha=alphaForLM) + if not method=="ADMM": + for n, i in enumerate(range(im1 * im2)): + stats, coeffs = xanes_fitting_1D(im_array[:, i], + e_list, + refs, + method=method, + alphaForLM=alphaForLM) + + coeffs_arr.append(coeffs) + r_factor_arr.append(stats["R_Factor"]) + + abundance_map = np.reshape(coeffs_arr, (im1, im2, -1)) + r_factor_im = np.reshape(r_factor_arr, (im1, im2)) + + elif method=="ADMM": + int_refs = interploate_E(refs,e_list) + coeffs_arr,r_factor_im,convergence, feasibility = fitting_admm(im_array, + int_refs.T, + maxiter=100, + rate=alphaForLM, + epsilon=1e-30) + # print(coeffs_arr.shape) + + #plt.imshow(coeffs_arr[1].reshape(im1, im2)) + + abundance_map = np.reshape((coeffs_arr.T), (im1, im2, -1)) + + return abundance_map, r_factor_im, np.mean(coeffs_arr, axis=0) + + +def xanes_fitting_Line(im_stack, e_list, refs, method="NNLS", alphaForLM=0.05): + """Linear combination fit of image data with reference standards""" + en, im1, im2 = np.shape(im_stack) + im_array = np.mean(im_stack, 2) + coeffs_arr = [] + meanStats = {"R_Factor": 0, "R_Square": 0, "Chi_Square": 0, "Reduced Chi_Square": 0} + + for i in range(im1): + stats, coeffs = xanes_fitting_1D(im_array[:, i], e_list, refs, + method=method, alphaForLM=alphaForLM) + coeffs_arr.append(coeffs) + for key in stats.keys(): + meanStats[key] += stats[key] + + for key, vals in meanStats.items(): + meanStats[key] = np.around((vals / im1), 5) + + return meanStats, np.mean(coeffs_arr, axis=0) + +#TODO ADMM maybe faster here +def xanes_fitting_Binned(im_stack, e_list, refs, method="NNLS", alphaForLM=0.05): + """Linear combination fit of image data with reference standards""" + + im_stack = resize_stack(im_stack, scaling_factor=10) + # use a simple filter to find threshold value + val = filters.threshold_otsu(im_stack[-1]) + en, im1, im2 = np.shape(im_stack) + im_array = im_stack.reshape(en, im1 * im2) + coeffs_arr = [] + meanStats = {"R_Factor": 0, "R_Square": 0, "Chi_Square": 0, "Reduced Chi_Square": 0} + + specs_fitted = 0 + total_spec = im1 * im2 + for i in range(total_spec): + spec = im_array[:, i] + # do not fit low intensity/background regions + if spec[-1] > val: + specs_fitted += 1 + stats, coeffs = xanes_fitting_1D(spec / spec[-1], e_list, refs, + method=method, alphaForLM=alphaForLM) + coeffs_arr.append(coeffs) + for key in stats.keys(): + meanStats[key] += stats[key] + else: + pass + + for key, vals in meanStats.items(): + meanStats[key] = np.around((vals / specs_fitted), 6) + # print(f"{specs_fitted}/{total_spec}") + return meanStats, np.mean(coeffs_arr, axis=0) + + +def create_df_from_nor(athenafile="fe_refs.nor"): + """create pandas dataframe from athena nor file, first column + is energy and headers are sample names""" + + refs = np.loadtxt(athenafile) + n_refs = refs.shape[-1] + skip_raw_n = n_refs + 6 + + df = pd.read_table( + athenafile, delim_whitespace=True, skiprows=skip_raw_n, header=None, usecols=np.arange(0, n_refs) + ) + df2 = pd.read_table( + athenafile, delim_whitespace=True, skiprows=skip_raw_n - 1, usecols=np.arange(0, n_refs + 1) + ) + new_col = df2.columns.drop("#") + df.columns = new_col + return df, list(new_col) + + +def create_df_from_nor_try2(athenafile="fe_refs.nor"): + """create pandas dataframe from athena nor file, first column + is energy and headers are sample names""" + + refs = np.loadtxt(athenafile) + n_refs = refs.shape[-1] + df_refs = pd.DataFrame(refs) + + df = pd.read_csv(athenafile, header=None) + new_col = list((str(df.iloc[n_refs + 5].values)).split(" ")[2::2]) + df_refs.columns = new_col + + return df_refs, list(new_col) + + +def energy_from_logfile(logfile="maps_log_tiff.txt"): + df = pd.read_csv(logfile, header=None, delim_whitespace=True, skiprows=9) + return df[9][df[7] == "energy"].values.astype(float) + + +# def xanesNormalization(e, mu, e0=7125, step=None, +# nnorm=2, nvict=0, pre1=None, pre2=-50, +# norm1=100, norm2=None, method="pre_edge", +# useFlattened=False, Elemline = "Fe_K"): + +# elem, line = Elemline.split('_') +# elemZ = xraydb.atomic_number(elem) +# dat = Group(name='larchgroup', col1=e, col2=mu) + + +# if method == "guess": +# result = preedge(e, mu, e0, step=step, nnorm=nnorm, nvict=nvict) + +# return result["pre1"], result["pre2"], result["norm1"], result["norm2"] + +# elif method == "mback": +# mback(e,mu, group=dat, z=elemZ, edge=line, e0=e0,fit_erfc=False) +# return dat.f2, dat.fpp + +# else: +# pre_edge(e, mu,group=dat,e0=e0, step=step, nnorm=nnorm,nvict=nvict, pre1=pre1, +# pre2=pre2, norm1=norm1,norm2=norm2, make_flat = True) + +# if useFlattened: +# normSpec = dat.flat +# else: +# normSpec = dat.norm + +# return dat.pre_edge, dat.post_edge, normSpec + +def xanesNormalization(e, mu, e0=7125, nnorm=2, nvict=0, + pre1=None, pre2=-50, norm1=None, norm2=None, + useFlattened=False, Elemline="Fe_K"): + """ + e, mu : energy & absorption arrays + e0 : edge energy (float) + nnorm : degree of post-edge polynomial + nvict : exponent for pre-edge fit weighting + pre1, pre2 : relative pre-edge fitting bounds + norm1, norm2: relative post-edge fitting bounds + useFlattened: ignored in this simple version + Elemline : placeholder, no longer used + """ + # perform pre-edge subtraction + normalization + res = pre_edge_simple( + e, mu, + e0=e0, nnorm=nnorm, nvict=nvict, + pre1=pre1, pre2=pre2, + norm1=norm1, norm2=norm2 + ) + + pre_edge_arr = res["pre_edge"] + post_edge_arr = res["post_edge"] + norm_arr = res["norm"] + + return pre_edge_arr, post_edge_arr, norm_arr + +# def xanesNormStack(e_list, im_stack, e0=7125, step=None, +# nnorm=2, nvict=0, pre1=None, pre2=-50, +# norm1=100, norm2=None, useFlattened=False, ignorePostEdgeNorm=False): +# en, im1, im2 = np.shape(im_stack) +# im_array = im_stack.reshape(en, im1 * im2) +# normedStackArray = np.zeros_like(im_array) +# dat = Group(name='larchgroup', col1=e_list, col2=get_mean_spectra(im_stack)) + + +# for i in range(im1 * im2): +# pre_edge(e_list, im_array[:, i], e0=e0, group=dat, step=step, nnorm=nnorm, +# nvict=nvict, pre1=pre1, pre2=pre2, norm1=norm1, norm2=norm2,make_flat = True) + +# if useFlattened: +# normSpec = dat.flat +# else: +# normSpec = dat.norm + +# if ignorePostEdgeNorm: +# normedStackArray[:, i] = normSpec * dat.post_edge +# else: +# normedStackArray[:, i] = normSpec + +# return remove_nan_inf(np.reshape(normedStackArray, (en, im1, im2))) + + + +def xanesNormStack(e_list, im_stack, + e0=7125, nnorm=2, nvict=0, + pre1=None, pre2=-50, + norm1=None, norm2=None, + ignorePostEdgeNorm=False): + """ + Apply XANES normalization to every spectrum in a 3D stack. + + Parameters + ---------- + e_list : 1D array + Energy grid. + im_stack : 3D array, shape (nE, nX, nY) + Raw absorption stack. + e0, nnorm, nvict, pre1, pre2, norm1, norm2 : fit params + Passed to pre_edge_simple. + ignorePostEdgeNorm : bool + If True, multiply normalized spec by post-edge baseline. + + Returns + ------- + normed_stack : 3D array, same shape as im_stack + """ + nE, nX, nY = im_stack.shape + flat_in = im_stack.reshape(nE, -1) + flat_out = np.zeros_like(flat_in) + + for i in range(flat_in.shape[1]): + spec = flat_in[:, i] + res = pre_edge_simple( + e_list, spec, + e0=e0, nnorm=nnorm, nvict=nvict, + pre1=pre1, pre2=pre2, + norm1=norm1, norm2=norm2 + ) + norm_spec = res["norm"] + post_edge = res["post_edge"] + + if ignorePostEdgeNorm: + flat_out[:, i] = norm_spec * post_edge + else: + flat_out[:, i] = norm_spec + + # reshape back and remove any NaN/inf + return remove_nan_inf(flat_out.reshape(nE, nX, nY)) + +def getDeconvolutedXANESSpectrum(xanesStack, chemMapStack, energy, clusterSigma=1): + compXanesSpetraAll = pd.DataFrame() + compXanesSpetraAll['Energy'] = energy + + for n, compImage in enumerate(chemMapStack): + mask = np.where(compImage > clusterSigma * np.std(compImage), compImage, 0) + compXanesSpetraAll[f'Component_{n + 1}'] = get_mean_spectra(xanesStack * mask) + return compXanesSpetraAll + + +def align_stack( + stack_img, ref_image_void=True, ref_stack=None, + transformation=StackReg.TRANSLATION, reference="previous" +): + + """Image registration flow using pystack reg""" + + # all the options are in one function + + sr = StackReg(transformation) + + if ref_image_void: + tmats_ = sr.register_stack(stack_img, reference=reference) + + else: + tmats_ = sr.register_stack(ref_stack, reference=reference) + out_ref = sr.transform_stack(ref_stack) + + out_stk = sr.transform_stack(stack_img, tmats=tmats_) + return np.float32(out_stk), tmats_ + + +def align_simple(stack_img, transformation=StackReg.TRANSLATION, reference="previous"): + + sr = StackReg(transformation) + tmats_ = sr.register_stack(stack_img, reference="previous") + for i in range(10): + out_stk = sr.transform_stack(stack_img, tmats=tmats_) + return np.float32(out_stk) + + +def align_with_tmat(stack_img, tmat_file, transformation=StackReg.TRANSLATION): + + sr = StackReg(transformation) + out_stk = sr.transform_stack(stack_img, tmats=tmat_file) + return np.float32(out_stk) + + +def align_stack_iter( + stack, + ref_stack_void=True, + ref_stack=None, + transformation=StackReg.TRANSLATION, + method=("previous", "first"), + max_iter=2, +): + if ref_stack_void: + ref_stack = stack + + for i in range(max_iter): + sr = StackReg(transformation) + for ii in range(len(method)): + print(ii, method[ii]) + tmats = sr.register_stack(ref_stack, reference=method[ii]) + ref_stack = sr.transform_stack(ref_stack) + stack = sr.transform_stack(stack, tmats=tmats) + + return np.float32(stack) + +def normalize_and_scale(stack): + return (stack**2/stack.sum(0)[np.newaxis,:,:])/stack.max() + + +def applyMaskGetMeanSpectrum(im_stack, mask): + """A 2d mask to multiply with the 3d xanes stack and returns mean spectrum""" + + masked_stack = im_stack * mask + return get_mean_spectra(masked_stack) + + +def modifyStack( + raw_stack, + normalizeStack=False, + normToPoint=-1, + applySmooth=False, + smoothWindowSize=3, + applyThreshold=False, + thresholdValue=0, + removeOutliers=False, + nSigmaOutlier=3, + applyTranspose=False, + transposeVals=(0, 1, 2), + applyCrop=False, + cropVals=(0, 1, 2), + removeEdges=False, + resizeStack=False, + upScaling=False, + binFactor=2, +): + + """A giant function to modify the stack with many possible operations. + all the changes can be saved to a jason file as a config file. Enabling and + distabling the sliders is a problem""" + + """ + normStack = normalize(raw_stack, norm_point=normToPoint) + smoothStack = smoothen(raw_stack, w_size= smoothWindowSize) + thresholdStack = clean_stack(raw_stack, auto_bg=False, bg_percentage = thresholdValue) + outlierStack = remove_hot_pixels(raw_stack, NSigma=nSigmaOutlier) + transposeStack = np.transpose(raw_stack, transposeVals) + croppedStack = raw_stack[cropVals] + edgeStack = remove_edges(raw_stack) + binnedStack = resize_stack(raw_stack,upscaling=upScaling,scaling_factor=binFactor) + + """ + + if removeOutliers: + modStack = remove_hot_pixels(raw_stack, NSigma=nSigmaOutlier) + + else: + modStack = raw_stack + + if applyThreshold: + modStack = clean_stack(modStack, auto_bg=False, bg_percentage=thresholdValue) + + else: + pass + + if applySmooth: + modStack = smoothen(modStack, w_size=smoothWindowSize) + + else: + pass + + if applyTranspose: + modStack = np.transpose(modStack, transposeVals) + + else: + pass + + if applyCrop: + modStack = modStack[cropVals] + + else: + pass + + if normalizeStack: + modStack = normalize(raw_stack, norm_point=normToPoint) + else: + pass From 04d491ad2563e86b57e906e6a2f93eea4442b3c4 Mon Sep 17 00:00:00 2001 From: Ajith Pattammattel Date: Tue, 22 Jul 2025 14:29:55 -0400 Subject: [PATCH 03/18] pyqt6 added to requirements --- xmidas/gui/windows/mask_maker.py | 7 ++++--- xmidas/gui/windows/multichannel_viewer.py | 4 ++-- xmidas/gui/windows/singleStackViewer.py | 4 ++-- xmidas/gui/windows/xanes_viewer.py | 15 +++++++-------- xmidas/main.py | 16 ++++++++-------- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/xmidas/gui/windows/mask_maker.py b/xmidas/gui/windows/mask_maker.py index 0eea3cf..84e3a0b 100644 --- a/xmidas/gui/windows/mask_maker.py +++ b/xmidas/gui/windows/mask_maker.py @@ -22,9 +22,10 @@ from PyQt6.QtGui import QMovie from PyQt6.QtWidgets import QMessageBox, QFileDialog, QApplication from PyQt6.QtCore import QObject, pyqtSignal, pyqtSlot, QRunnable, QThreadPool, PYQT_VERSION_STR -from utils import * -from utils.color_maps import * -from models.encoders import jsonEncoder + +from xmidas.utils import * +from xmidas.utils.color_maps import * +from xmidas.models.encoders import jsonEncoder cmap_dict = create_color_maps() ui_dir = os.path.normpath(os.path.join( os.path.dirname(os.path.abspath(__file__)), diff --git a/xmidas/gui/windows/multichannel_viewer.py b/xmidas/gui/windows/multichannel_viewer.py index fccbd98..4258543 100644 --- a/xmidas/gui/windows/multichannel_viewer.py +++ b/xmidas/gui/windows/multichannel_viewer.py @@ -18,8 +18,8 @@ os.path.dirname(os.path.abspath(__file__)), "../layout" )) -from utils.color_maps import * -from models.encoders import jsonEncoder +from xmidas.utils.color_maps import * +from xmidas.models.encoders import jsonEncoder cmap_dict = create_color_maps() class MultiChannelWindow(QtWidgets.QMainWindow): diff --git a/xmidas/gui/windows/singleStackViewer.py b/xmidas/gui/windows/singleStackViewer.py index e1ddf86..af70c54 100644 --- a/xmidas/gui/windows/singleStackViewer.py +++ b/xmidas/gui/windows/singleStackViewer.py @@ -18,8 +18,8 @@ from PyQt6.QtWidgets import QMessageBox, QFileDialog, QApplication from PyQt6.QtCore import QObject, pyqtSignal, pyqtSlot, QRunnable, QThreadPool, PYQT_VERSION_STR -from utils import * -from utils.color_maps import * +from xmidas.utils import * +from xmidas.utils.color_maps import * cmap_dict = create_color_maps() diff --git a/xmidas/gui/windows/xanes_viewer.py b/xmidas/gui/windows/xanes_viewer.py index 49b9d87..1a28e57 100644 --- a/xmidas/gui/windows/xanes_viewer.py +++ b/xmidas/gui/windows/xanes_viewer.py @@ -23,20 +23,19 @@ from PyQt6.QtWidgets import QMessageBox, QFileDialog, QApplication from PyQt6.QtCore import QObject, pyqtSignal, pyqtSlot, QRunnable, QThreadPool, PYQT_VERSION_STR -from utils import * -from utils.color_maps import * -from models.encoders import jsonEncoder -from utils.utils import xanes_fitting, xanes_fitting_1D, xanes_fitting_Binned +from xmidas.utils import * +from xmidas.utils.color_maps import * +from xmidas.models.encoders import jsonEncoder +from xmidas.utils.utils import xanes_fitting, xanes_fitting_1D, xanes_fitting_Binned +from xmidas.gui.windows.multichannel_viewer import MultiChannelWindow +from xmidas.gui.windows.decomposition_viewer import * + cmap_dict = create_color_maps() ui_dir = os.path.normpath(os.path.join( os.path.dirname(os.path.abspath(__file__)), "../layout" )) -from gui.windows.multichannel_viewer import MultiChannelWindow -from gui.windows.decomposition_viewer import * - - class XANESViewer(QtWidgets.QMainWindow): def __init__(self, im_stack=None, e_list=None, refs=None, ref_names=None): super(XANESViewer, self).__init__() diff --git a/xmidas/main.py b/xmidas/main.py index 7073849..f0b248b 100644 --- a/xmidas/main.py +++ b/xmidas/main.py @@ -2,7 +2,7 @@ # Author: Ajith Pattammattel # First Version on:06-23-2020 - +#python 3.12 update on July 2025 __version__ = "1.0.0" import argparse @@ -35,14 +35,14 @@ from PyQt6.QtCore import QObject, pyqtSignal, pyqtSlot, QRunnable, QThreadPool, PYQT_VERSION_STR -from utils.utils import * -from utils.color_maps import create_color_maps -from models.encoders import jsonEncoder +from xmidas.utils.utils import * +from xmidas.utils.color_maps import create_color_maps +from xmidas.models.encoders import jsonEncoder -from gui.windows.xanes_viewer import XANESViewer -from gui.windows.multichannel_viewer import MultiChannelWindow -from gui.windows.mask_maker import MaskSpecViewer -from gui.windows.singleStackViewer import * +from xmidas.gui.windows.xanes_viewer import XANESViewer +from xmidas.gui.windows.multichannel_viewer import MultiChannelWindow +from xmidas.gui.windows.mask_maker import MaskSpecViewer +from xmidas.gui.windows.singleStackViewer import * cmap_dict = create_color_maps() From 0d440120b7ee9ed1217f274df5afd911fc97bb4e Mon Sep 17 00:00:00 2001 From: Ajith Pattammattel Date: Tue, 22 Jul 2025 14:31:16 -0400 Subject: [PATCH 04/18] pyqt6 added to requirements --- xmidas/gui/windows/decomposition_viewer.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/xmidas/gui/windows/decomposition_viewer.py b/xmidas/gui/windows/decomposition_viewer.py index 8b87b35..89c19d9 100644 --- a/xmidas/gui/windows/decomposition_viewer.py +++ b/xmidas/gui/windows/decomposition_viewer.py @@ -17,10 +17,11 @@ from PyQt6.QtWidgets import QMessageBox, QFileDialog, QApplication from PyQt6.QtCore import QObject, pyqtSignal, pyqtSlot, QRunnable, QThreadPool, PYQT_VERSION_STR -from gui.windows.multichannel_viewer import MultiChannelWindow -from utils import * -from utils.color_maps import * -from models.encoders import jsonEncoder +from xmidas.gui.windows.multichannel_viewer import MultiChannelWindow +from xmidas.utils import * +from xmidas.utils.color_maps import * +from xmidas.models.encoders import jsonEncoder +from xmidas.gui.windows.singleStackViewer import * cmap_dict = create_color_maps() ui_dir = os.path.normpath(os.path.join( @@ -28,7 +29,7 @@ "../layout" )) -from gui.windows.singleStackViewer import * + class DecomposeViewer(QtWidgets.QMainWindow): From a59253e2c6df141cdb72d44c8cbb2899bd8387f3 Mon Sep 17 00:00:00 2001 From: Ajith Pattammattel Date: Tue, 22 Jul 2025 14:34:01 -0400 Subject: [PATCH 05/18] pyqt6 added to requirements --- xmidas/utils/utils.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/xmidas/utils/utils.py b/xmidas/utils/utils.py index 151e852..97b8e5e 100644 --- a/xmidas/utils/utils.py +++ b/xmidas/utils/utils.py @@ -15,13 +15,16 @@ from skimage.transform import resize from skimage import filters from sklearn import linear_model -from utils.larch_norm import pre_edge_simple + # from larch.xafs import pre_edge, preedge, mback # from larch.io import read_ascii, read_athena # from larch import Group import xraydb from pystackreg import StackReg +from xmidas.utils.larch_norm import pre_edge_simple + + logger = logging.getLogger() def get_xrf_data(h='h5file'): From 3c82f8e95f49f6141a1ce82a0bf778e1b70ad8ae Mon Sep 17 00:00:00 2001 From: Ajith Pattammattel Date: Tue, 22 Jul 2025 14:37:25 -0400 Subject: [PATCH 06/18] pyqt6 added to requirements --- xmidas/main.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/xmidas/main.py b/xmidas/main.py index f0b248b..4cbee39 100644 --- a/xmidas/main.py +++ b/xmidas/main.py @@ -1279,11 +1279,11 @@ def plotCorrelationsAllCombinations(self): f"maxiumum number of " f"plot windows. First {len(self.scWindowDict)} " f"combinations will be plotted. \n Proceed?", - QMessageBox.Yes | QMessageBox.No, - QMessageBox.No, + QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No, + QMessageBox.StandardButton.No, ) - if reply == QMessageBox.Yes: + if reply == QMessageBox.StandardButton.Yes: for i, pair in enumerate(allElemCombNum): im1 = self.displayedStack[pair[0]] @@ -1294,7 +1294,7 @@ def plotCorrelationsAllCombinations(self): self.scWindowDict[i] = ScatterPlot(im1, im2, (str(im1Name), str(im2Name))) self.scWindowDict[i].show() - if reply == QMessageBox.No: + if reply == QMessageBox.StandardButton.No: return else: @@ -1681,11 +1681,11 @@ def closeEvent(self, event): self, "Window Close", "Are you sure you want to close?", - QMessageBox.Yes | QMessageBox.No, - QMessageBox.No, + QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No, + QMessageBox.StandardButton.No, ) - if reply == QMessageBox.Yes: + if reply == QMessageBox.StandardButton.Yes: event.accept() QApplication.closeAllWindows() else: From 438ae40911152f133338e4257d6aa2627393a40f Mon Sep 17 00:00:00 2001 From: Ajith Pattammattel Date: Tue, 22 Jul 2025 14:47:39 -0400 Subject: [PATCH 07/18] source installation instrction file added --- SourceInstallationGuide.md | 107 +++++++++++++++++++++++++++++++++++++ requirements.txt | 3 +- 2 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 SourceInstallationGuide.md diff --git a/SourceInstallationGuide.md b/SourceInstallationGuide.md new file mode 100644 index 0000000..6902931 --- /dev/null +++ b/SourceInstallationGuide.md @@ -0,0 +1,107 @@ +# XMIDAS - Windows Installation Guide + +This guide will walk Windows users through installing and running the **XMIDAS** (X-ray Multimodal Image Data Analysis Software) application from source. + +--- + +## 📦 Requirements + +* [Miniconda or Anaconda (64-bit)](https://docs.conda.io/en/latest/miniconda.html) +* (Optional) [Git for Windows](https://git-scm.com/download/win) + +--- + +## 🧰 Step-by-Step Installation + +### 1. Clone or Download the Repository + +**Option A – With Git (recommended):** + +```bash +git clone https://github.com/pattammattel/xmidas.git +cd xmidas +``` + +**Option B – Without Git:** + +1. Visit: [https://github.com/pattammattel/xmidas](https://github.com/pattammattel/xmidas) +2. Click **Code → Download ZIP** +3. Extract ZIP +4. **Open Anaconda Prompt and navigate into the extracted `xmidas/` folder**: + + ```bash + cd path\to\extracted\xmidas + ``` + +🚨 **IMPORTANT:** You **must** be inside the `xmidas` folder before continuing! All commands in the next steps assume this location. + +--- + +### 2. Create a Conda Environment + +```bash +conda create -n xmidas-env python=3.12 +conda activate xmidas-env +``` + +--- + +### 3. Install Dependencies + +```bash +pip install -r requirements.txt +``` + +If you prefer Conda-based installation: + +```bash +conda env update -f MiscFiles-FindProperLocation/environment.yml +conda activate xmidas-env +``` + +--- + +### 4. Run XMIDAS + +```bash +python -m xmidas.main +``` + +Or if entry point is configured: + +```bash +xmidas +``` + +--- + +## 📌 Troubleshooting + +* ✅ **Double-check that you're in the `xmidas/` folder** before running anything. +* If you see `ModuleNotFoundError: No module named 'xmidas'`, you are probably in the wrong directory. +* If PyQt-related errors occur, ensure `PyQt6` is installed and compatible with Python 3.12. + +--- + +## 🗂 Optional: Create a Desktop Shortcut (Windows only) + +Inside `MiscFiles-FindProperLocation/`, you’ll find a helper script: + +```bash +python create_shortcut.py +``` + +This will generate a Windows `.bat` shortcut to launch the GUI. + +--- + +## 🔗 Resources + +* 📖 Documentation: See `docs/source/index.rst` +* 🐞 Issues / Bugs: [GitHub Issues](https://github.com/pattammattel/xmidas/issues) + +--- + +Happy analyzing! + +*– XMIDAS Development Team* diff --git a/requirements.txt b/requirements.txt index 9a22f05..45351af 100755 --- a/requirements.txt +++ b/requirements.txt @@ -8,5 +8,6 @@ scikit-image scikit-learn scipy tifffile -packaging +packaging pyqt6 +xraydb From 3037b5be280f5c3aa7a055621a7e65fa595a4890 Mon Sep 17 00:00:00 2001 From: Ajith Pattammattel Date: Tue, 22 Jul 2025 14:51:36 -0400 Subject: [PATCH 08/18] source installation instrction file added --- SourceInstallationGuide.md | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/SourceInstallationGuide.md b/SourceInstallationGuide.md index 6902931..cc2a333 100644 --- a/SourceInstallationGuide.md +++ b/SourceInstallationGuide.md @@ -52,12 +52,6 @@ conda activate xmidas-env pip install -r requirements.txt ``` -If you prefer Conda-based installation: - -```bash -conda env update -f MiscFiles-FindProperLocation/environment.yml -conda activate xmidas-env -``` --- @@ -67,11 +61,6 @@ conda activate xmidas-env python -m xmidas.main ``` -Or if entry point is configured: - -```bash -xmidas -``` --- From 9b173c8145bf87fdc4fed6d942f3fc2327208ad0 Mon Sep 17 00:00:00 2001 From: Ajith Pattammattel Date: Tue, 22 Jul 2025 14:58:22 -0400 Subject: [PATCH 09/18] source installation instrction file added --- docs/installation/windows_install_xmidas.bat | 38 ++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 docs/installation/windows_install_xmidas.bat diff --git a/docs/installation/windows_install_xmidas.bat b/docs/installation/windows_install_xmidas.bat new file mode 100644 index 0000000..e90580f --- /dev/null +++ b/docs/installation/windows_install_xmidas.bat @@ -0,0 +1,38 @@ +@echo off +setlocal + +REM --- Clone repo if not already present --- +IF NOT EXIST xmidas ( + echo Cloning XMIDAS from GitHub... + git clone https://github.com/pattammattel/xmidas.git +) + +REM --- Change to xmidas directory --- +cd xmidas + +REM --- Confirm location --- +IF NOT EXIST requirements.txt ( + echo You are not in the xmidas folder. Exiting. + pause + exit /b +) + +REM --- Create Conda env if it doesn't exist --- +echo Creating Conda environment xmidas-env... +conda info --envs | findstr "xmidas-env" >nul +IF %ERRORLEVEL% NEQ 0 ( + conda create -n xmidas-env python=3.12 -y +) + +REM --- Activate the environment --- +call conda activate xmidas-env + +REM --- Install dependencies --- +echo Installing Python dependencies... +pip install -r requirements.txt + +REM --- Launch XMIDAS --- +echo Starting XMIDAS... +python -m xmidas.main + +pause From 30cb4334d0df97195bfe2c643206256809768916 Mon Sep 17 00:00:00 2001 From: Ajith Pattammattel Date: Tue, 22 Jul 2025 15:05:20 -0400 Subject: [PATCH 10/18] source installation instrction file added --- AUTHORS.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/AUTHORS.rst b/AUTHORS.rst index e4ddda0..fb41671 100755 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -4,9 +4,11 @@ Credits Maintainer ---------- +Ajit Pattammattel , pattammattel@bnl.gov * Brookhaven National Lab <> + Contributors ------------ From 86383c35d13747a132ab50d000e1a6cddd2ea092 Mon Sep 17 00:00:00 2001 From: Ajith Pattammattel Date: Tue, 22 Jul 2025 15:06:32 -0400 Subject: [PATCH 11/18] source installation instrction file added --- AUTHORS.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS.rst b/AUTHORS.rst index fb41671..12c3506 100755 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -5,6 +5,7 @@ Credits Maintainer ---------- Ajit Pattammattel , pattammattel@bnl.gov +Dmitri Garvilov ,dgavrilov@bnl.gov * Brookhaven National Lab <> From c11f212e0046371e1555690d40cd6610b622dfb8 Mon Sep 17 00:00:00 2001 From: Ajith Pattammattel Date: Tue, 22 Jul 2025 15:23:12 -0400 Subject: [PATCH 12/18] source installation instrction file added --- AUTHORS.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/AUTHORS.rst b/AUTHORS.rst index 12c3506..e9b117d 100755 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -2,12 +2,13 @@ Credits ======= -Maintainer +Maintainers ---------- -Ajit Pattammattel , pattammattel@bnl.gov -Dmitri Garvilov ,dgavrilov@bnl.gov -* Brookhaven National Lab <> +- Ajith Pattammattel +- Dmitri Gavrilov + +*Brookhaven National Laboratory* Contributors From fb71343dd9290d3a6662055f8699ed4ffb4f355a Mon Sep 17 00:00:00 2001 From: Ajith Pattammattel Date: Tue, 22 Jul 2025 15:47:54 -0400 Subject: [PATCH 13/18] documentation --- README.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.rst b/README.rst index c4a226e..625b9bd 100755 --- a/README.rst +++ b/README.rst @@ -10,3 +10,5 @@ Brookhaven National Laboratory * Free software: 3-clause BSD license * Documentation: https://nsls-ii.github.io/xmidas/. + +* Citation: Ajith Pattammattel, Ryan Tappero, Dmitri Gavrilov, Hongqiao Zhang, Paul Aronstein, Henry Jay Forman, Peggy A O'Day, Hanfei Yan, Yong S Chu, Multimodal X-ray nano-spectromicroscopy analysis of chemically heterogeneous systems, Metallomics, Volume 14, Issue 10, October 2022, mfac078, https://doi.org/10.1093/mtomcs/mfac078 From 751deb674d67a7c291bd5be202a79c20ffde150b Mon Sep 17 00:00:00 2001 From: Ajith Pattammattel Date: Tue, 19 Aug 2025 15:38:28 -0400 Subject: [PATCH 14/18] bug in installtion folder fixed --- SourceInstallationGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SourceInstallationGuide.md b/SourceInstallationGuide.md index cc2a333..6332cb1 100644 --- a/SourceInstallationGuide.md +++ b/SourceInstallationGuide.md @@ -58,7 +58,7 @@ pip install -r requirements.txt ### 4. Run XMIDAS ```bash -python -m xmidas.main +python -m main ``` From 3f8d842f62ada91a081d19cb383269c8a0755c00 Mon Sep 17 00:00:00 2001 From: Ajith Pattammattel Date: Tue, 19 Aug 2025 15:43:18 -0400 Subject: [PATCH 15/18] bug in the installation file fixed --- SourceInstallationGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SourceInstallationGuide.md b/SourceInstallationGuide.md index 6332cb1..cc2a333 100644 --- a/SourceInstallationGuide.md +++ b/SourceInstallationGuide.md @@ -58,7 +58,7 @@ pip install -r requirements.txt ### 4. Run XMIDAS ```bash -python -m main +python -m xmidas.main ``` From 069f4d94978fe671fbd3332100c18bb24e7bb9be Mon Sep 17 00:00:00 2001 From: Ajith Pattammattel Date: Thu, 21 Aug 2025 12:02:09 -0400 Subject: [PATCH 16/18] pyqt6 changes to xanes window --- xmidas/gui/windows/xanes_viewer.py | 230 +++++++++++------------------ 1 file changed, 89 insertions(+), 141 deletions(-) diff --git a/xmidas/gui/windows/xanes_viewer.py b/xmidas/gui/windows/xanes_viewer.py index 1a28e57..f155067 100644 --- a/xmidas/gui/windows/xanes_viewer.py +++ b/xmidas/gui/windows/xanes_viewer.py @@ -20,13 +20,13 @@ from PyQt6 import QtWidgets, QtCore, QtGui, uic, QtTest from PyQt6.QtGui import QMovie -from PyQt6.QtWidgets import QMessageBox, QFileDialog, QApplication +from PyQt6.QtWidgets import QMessageBox, QFileDialog, QApplication, QAbstractItemView, QTableWidgetItem from PyQt6.QtCore import QObject, pyqtSignal, pyqtSlot, QRunnable, QThreadPool, PYQT_VERSION_STR from xmidas.utils import * from xmidas.utils.color_maps import * from xmidas.models.encoders import jsonEncoder -from xmidas.utils.utils import xanes_fitting, xanes_fitting_1D, xanes_fitting_Binned +from xmidas.utils.utils import xanes_fitting, xanes_fitting_1D, xanes_fitting_Binned, interploate_E, get_sum_spectra, get_mean_spectra, normalize_and_scale from xmidas.gui.windows.multichannel_viewer import MultiChannelWindow from xmidas.gui.windows.decomposition_viewer import * @@ -312,7 +312,7 @@ def update_refs(self, list_): self.re_fit_xanes() def fit_point_spectrum(self, event): - if event.type() == QtCore.QEvent.MouseButtonDblClick: + if event.type() == QtCore.QEvent.Type.MouseButtonDblClick: if event.button() == QtCore.Qt.LeftButton: self.xpixel = int(self.image_view.view.mapSceneToView(event.pos()).x()) zlim, ylim, xlim = self.im_stack.shape @@ -646,15 +646,18 @@ def export_data_and_params(self, folder = None): self.user_wd = os.path.dirname(file_name) QMessageBox.information(self,"Saved", f"data saved to {self.user_wd}") + class RefChooser(QtWidgets.QMainWindow): - choosenRefsSignal: pyqtSignal = QtCore.pyqtSignal(list) - fitResultsSignal: pyqtSignal = QtCore.pyqtSignal(np.ndarray, float, np.ndarray) + choosenRefsSignal = QtCore.pyqtSignal(list) + fitResultsSignal = QtCore.pyqtSignal(np.ndarray, float, np.ndarray) def __init__(self, ref_names, im_stack, e_list, refs, e_shift, fit_model): - super(RefChooser, self).__init__() + super().__init__() uic.loadUi(os.path.join(ui_dir, "RefChooser.ui"), self) + self.user_wd = os.path.abspath("~") - self.centralwidget.setStyleSheet(open(os.path.join(ui_dir, "css/defaultStyle.css")).read()) + self.setStyleSheet(open(os.path.join(ui_dir, "css/defaultStyle.css")).read()) + self.ref_names = ref_names self.refs = refs self.im_stack = im_stack @@ -665,128 +668,90 @@ def __init__(self, ref_names, im_stack, e_list, refs, e_shift, fit_model): self.all_boxes = [] self.rFactorList = [] + self.setupUI() + + def setupUI(self): self.displayCombinations() - # selection become more apparent than default with red-ish color - self.tableWidget.setStyleSheet("background-color: white; selection-background-color: rgb(200,0,0);") + self.tableWidget.setStyleSheet( + "background-color: white; selection-background-color: rgb(200,0,0);" + ) - # add a line to the plot to walk through the table. Note that the table is not sorted self.selectionLine = pg.InfiniteLine( - pos=1, angle=90, pen=pg.mkPen("m", width=2.5), movable=True, bounds=None, label="Move Me!" + pos=1, angle=90, pen=pg.mkPen("m", width=2.5), movable=True, label="Move Me!" ) self.stat_view.setLabel("bottom", "Fit ID") self.stat_view.setLabel("left", "Reduced Chi^2") - for n, i in enumerate(self.ref_names): - self.cb_i = QtWidgets.QCheckBox(self.ref_box_frame) - if n == 0: - self.cb_i.setChecked(True) - self.cb_i.setEnabled(False) - self.cb_i.setObjectName(i) - self.cb_i.setText(i) - self.gridLayout_2.addWidget(self.cb_i, n, 0, 1, 1) - self.cb_i.toggled.connect(self.enableApply) - self.all_boxes.append(self.cb_i) + for n, name in enumerate(self.ref_names): + checkbox = QtWidgets.QCheckBox(self.ref_box_frame) + checkbox.setObjectName(name) + checkbox.setText(name) + checkbox.setChecked(n == 0) + checkbox.setEnabled(n != 0) + checkbox.toggled.connect(self.enableApply) + self.gridLayout_2.addWidget(checkbox, n, 0, 1, 1) + self.all_boxes.append(checkbox) - # connections self.pb_apply.clicked.connect(self.clickedWhichAre) self.pb_combo.clicked.connect(self.tryAllCombo) self.actionExport_Results_csv.triggered.connect(self.exportFitResults) self.selectionLine.sigPositionChanged.connect(self.updateFitWithLine) self.tableWidget.itemSelectionChanged.connect(self.updateWithTableSelection) - # self.stat_view.scene().sigMouseClicked.connect(self.moveSelectionLine) self.stat_view.mouseDoubleClickEvent = self.moveSelectionLine self.sb_max_combo.valueChanged.connect(self.displayCombinations) - # self.pb_sort_with_r.clicked.connect(lambda: self.tableWidget.sortItems(3, QtCore.Qt.AscendingOrder)) self.pb_sort_with_r.clicked.connect(self.sortTable) self.cb_sorter.currentTextChanged.connect(self.sortTable) - def clickedWhich(self): - button_name = self.sender() - def populateChecked(self): - self.onlyCheckedBoxes = [] - for names in self.all_boxes: - if names.isChecked(): - self.onlyCheckedBoxes.append(names.objectName()) - - QtCore.pyqtSlot() + self.onlyCheckedBoxes = [cb.objectName() for cb in self.all_boxes if cb.isChecked()] + @QtCore.pyqtSlot() def clickedWhichAre(self): self.populateChecked() self.choosenRefsSignal.emit(self.onlyCheckedBoxes) def generateRefList(self, ref_list, maxCombo, minCombo=1): - - """ - Creates a list of reference combinations for xanes fitting - - Paramaters; - - ref_list (list): list of ref names from the header - maxCombo (int): maximum number of ref lists in combination - minCombo (int): min number of ref lists in combination - - returns; - - 1. int: length of total number of combinations - 2. list: all the combinations - - """ - - if not maxCombo > len(ref_list): - - iter_list = [] - while minCombo < maxCombo + 1: - iter_list += list(combinations(ref_list, minCombo)) - minCombo += 1 - return len(iter_list), iter_list - - else: - raise ValueError(" Maximum numbinations cannot be larger than number of list items") + if maxCombo > len(ref_list): + raise ValueError("Maximum combinations cannot exceed number of references") + combinations_list = [combo for i in range(minCombo, maxCombo + 1) for combo in combinations(ref_list, i)] + return len(combinations_list), combinations_list def displayCombinations(self): niter, self.iter_list = self.generateRefList(self.ref_names[1:], self.sb_max_combo.value()) - self.label_nComb.setText(str(niter) + " Combinations") + self.label_nComb.setText(f"{niter} Combinations") @QtCore.pyqtSlot() def tryAllCombo(self): - # empty list to to keep track and plot of reduced chi2 of all the fits self.rfactor_list = [] + self.results_data = [] - # create dataframe for the table - self.df = pd.DataFrame( - columns=["Fit Number", "References", "Coefficients", "R-Factor", "R^2", "chi^2", "red-chi^2", "Score"] - ) - - # df columns is the header for the table widget - self.tableWidget.setHorizontalHeaderLabels(self.df.columns) - # self.iter_list = list(combinations(self.ref_names[1:],self.sb_max_combo.value())) + self.tableWidget.setRowCount(0) + self.tableWidget.setColumnCount(9) + self.tableWidget.setHorizontalHeaderLabels([ + "Fit Number", "References", "Coefficients", "Sum of Coefficients", + "R-Factor", "R^2", "chi^2", "red-chi^2", "Score" + ]) niter, self.iter_list = self.generateRefList(self.ref_names[1:], self.sb_max_combo.value()) - tot_combo = len(self.iter_list) + for n, refs in enumerate(self.iter_list): - self.statusbar.showMessage(f"{n + 1}/{tot_combo}") - selectedRefs = list((str(self.ref_names[0]),) + refs) - self.fit_combo_progress.setValue((n + 1) * 100 / tot_combo) + self.statusbar.showMessage(f"{n + 1}/{niter}") + selectedRefs = [self.ref_names[0]] + list(refs) + self.fit_combo_progress.setValue(int((n + 1) * 100 / niter)) + self.stat, self.coeffs_arr = xanes_fitting_Binned( self.im_stack, self.e_list + self.e_shift, self.refs[selectedRefs], method=self.fit_model ) self.rfactor_list.append(self.stat["Reduced Chi_Square"]) self.stat_view.plot( - x=np.arange(n + 1), - y=self.rfactor_list, - clear=True, - title="Reduced Chi^2", - pen=pg.mkPen("y", width=2, style=QtCore.Qt.DotLine), - symbol="o", + x=np.arange(n + 1), y=self.rfactor_list, clear=True, + title="Reduced Chi^2", pen=pg.mkPen("y", width=2, style=QtCore.Qt.PenStyle.DotLine), symbol="o" ) - # arbitary number to rank the best fit fit_score = (self.stat["R_Square"] + np.sum(self.coeffs_arr)) / ( - self.stat["R_Factor"] + self.stat["Reduced Chi_Square"] - ) + self.stat["R_Factor"] + self.stat["Reduced Chi_Square"]) resultsDict = { "Fit Number": n, @@ -800,88 +765,71 @@ def tryAllCombo(self): "Score": np.around(fit_score, 4), } - self.df = pd.concat([self.df, pd.DataFrame([resultsDict])], ignore_index=True) - - self.dataFrametoQTable(self.df) - QtTest.QTest.qWait(0.1) # hepls with real time plotting + self.results_data.append(resultsDict) + self.appendToTableWidget(resultsDict) + QtTest.QTest.qWait(100) self.stat_view.addItem(self.selectionLine) - def dataFrametoQTable(self, df_: pd.DataFrame): - nRows = len(df_.index) - nColumns = len(df_.columns) - self.tableWidget.setRowCount(nRows) - self.tableWidget.setColumnCount(nColumns) - self.tableWidget.setHorizontalHeaderLabels(df_.columns) - - for i in range(nRows): - for j in range(nColumns): - cell = QtWidgets.QTableWidgetItem(str(df_.values[i][j])) - self.tableWidget.setItem(i, j, cell) - - # set the property of the table view. Size policy to make the contents justified - self.tableWidget.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents) - self.tableWidget.resizeColumnsToContents() + def appendToTableWidget(self, row_dict): + row_position = self.tableWidget.rowCount() + self.tableWidget.insertRow(row_position) + for col, key in enumerate([ + "Fit Number", "References", "Coefficients", "Sum of Coefficients", + "R-Factor", "R^2", "chi^2", "red-chi^2", "Score" + ]): + item = QtWidgets.QTableWidgetItem(str(row_dict[key])) + self.tableWidget.setItem(row_position, col, item) def exportFitResults(self): - file_name = QFileDialog().getSaveFileName(self, "save csv", "xanes_fit_results_log.csv", "txt data (*csv)") - if file_name[0]: - with open(file_name[0], "w") as fp: - self.df.to_csv(fp) - else: - pass + if not hasattr(self, "results_data"): + return + df = pd.DataFrame(self.results_data) + file_name, _ = QFileDialog.getSaveFileName(self, "Save CSV", "xanes_fit_results_log.csv", "CSV Files (*.csv)") + if file_name: + df.to_csv(file_name, index=False) def selectTableAndCheckBox(self, x): nSelection = int(round(x)) self.tableWidget.selectRow(nSelection) - fit_num = int(self.tableWidget.item(nSelection, 0).text()) - refs_selected = self.iter_list[fit_num] + refs_selected = self.iter_list[int(self.tableWidget.item(nSelection, 0).text())] - # reset all the checkboxes to uncheck state, except the energy - for checkstate in self.findChildren(QtWidgets.QCheckBox): - if checkstate.isEnabled(): - checkstate.setChecked(False) + for cb in self.findChildren(QtWidgets.QCheckBox): + if cb.isEnabled(): + cb.setChecked(False) - for cb_names in refs_selected: - checkbox = self.findChild(QtWidgets.QCheckBox, name=cb_names) - checkbox.setChecked(True) + for name in refs_selected: + cb = self.findChild(QtWidgets.QCheckBox, name=name) + if cb: + cb.setChecked(True) def updateFitWithLine(self): - pos_x, pos_y = self.selectionLine.pos() - x = self.df.index[self.df[str("Fit Number")] == np.round(pos_x)][0] + pos_x, _ = self.selectionLine.pos() + x = int(round(pos_x)) self.selectTableAndCheckBox(x) def updateWithTableSelection(self): - x = self.tableWidget.currentRow() - self.selectTableAndCheckBox(x) + self.selectTableAndCheckBox(self.tableWidget.currentRow()) def moveSelectionLine(self, event): - if event.button() == QtCore.Qt.LeftButton: - Pos = self.stat_view.plotItem.vb.mapSceneToView(event.pos()) - self.selectionLine.setPos(Pos.x()) + if event.button() == QtCore.Qt.MouseButton.LeftButton: + pos = self.stat_view.plotItem.vb.mapSceneToView(event.pos()) + self.selectionLine.setPos(pos.x()) def sortTable(self): - sorter_dict = { - "R-Factor": "R-Factor", - "R-Square": "R^2", - "Chi-Square": "chi^2", - "Reduced Chi-Square": "red-chi^2", - "Fit Number": "Fit Number", + key_map = { + "R-Factor": 4, + "R-Square": 5, + "Chi-Square": 6, + "Reduced Chi-Square": 7, + "Fit Number": 0, } - sorter = sorter_dict[self.cb_sorter.currentText()] - self.df = self.df.sort_values(sorter, ignore_index=True) - self.dataFrametoQTable(self.df) + col_index = key_map.get(self.cb_sorter.currentText(), 0) + self.tableWidget.sortItems(col_index, QtCore.Qt.SortOrder.AscendingOrder) def enableApply(self): - - """ """ self.populateChecked() - if len(self.onlyCheckedBoxes) > 1: - self.pb_apply.setEnabled(True) - else: - self.pb_apply.setEnabled(False) - - + self.pb_apply.setEnabled(len(self.onlyCheckedBoxes) > 1) class MultiXANESWindow(MultiChannelWindow): From 5fb2ea611938e9823c2116b6717d117267f235f4 Mon Sep 17 00:00:00 2001 From: Ajith Pattammattel Date: Mon, 9 Feb 2026 17:31:44 -0500 Subject: [PATCH 17/18] pixi migration-success --- .gitattributes | 2 + .gitignore | 3 + pixi.lock | 1499 +++++++++++++++++++++++++++++++++++++++++ pixi.toml | 25 + xmidas/main.py | 16 +- xmidas/utils/utils.py | 6 +- 6 files changed, 1540 insertions(+), 11 deletions(-) create mode 100644 pixi.lock create mode 100644 pixi.toml diff --git a/.gitattributes b/.gitattributes index 636a0b3..3f6730e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,3 @@ xmidas/_version.py export-subst +# SCM syntax highlighting & preventing 3-way merges +pixi.lock merge=binary linguist-language=YAML linguist-generated=true -diff diff --git a/.gitignore b/.gitignore index 9a3e787..adc5511 100644 --- a/.gitignore +++ b/.gitignore @@ -86,3 +86,6 @@ target/ *.png *.nor *.ipynb +# pixi environments +.pixi/* +!.pixi/config.toml diff --git a/pixi.lock b/pixi.lock new file mode 100644 index 0000000..d647cd2 --- /dev/null +++ b/pixi.lock @@ -0,0 +1,1499 @@ +version: 6 +environments: + default: + channels: + - url: https://conda.anaconda.org/conda-forge/ + indexes: + - https://pypi.org/simple + options: + pypi-prerelease-mode: if-necessary-or-explicit + packages: + osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/_openmp_mutex-4.5-7_kmp_llvm.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aom-3.9.1-h7bae524_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/blosc-1.21.6-h7dd00d9_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brunsli-0.1-he0dfb12_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_8.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.34.6-hc919400_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-blosc2-2.23.0-hf9886e1_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/charls-2.4.2-h13dd4ca_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/dav1d-1.2.1-hb547adb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/giflib-5.2.2-h93a5062_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/h5py-3.15.1-nompi_py312h4eecd6b_101.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/hdf5-1.14.6-nompi_had3affe_106.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.2-h38cb7af_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/imagecodecs-2026.1.14-py312h04e8b9b_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/imageio-2.37.0-pyhfb79c49_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/jxrlib-1.1-h93a5062_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.21.3-h237132a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/lazy-loader-0.4-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lcms2-2.18-hdfa7624_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lerc-4.0.0-hd64df32_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libaec-1.1.5-h8664d51_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libavif16-1.3.0-hde9513d_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.11.0-5_h51639a9_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlicommon-1.2.0-hc919400_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlidec-1.2.0-hc919400_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlienc-1.2.0-hc919400_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.11.0-5_hb0561ab_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.18.0-he38603e_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-21.1.8-h55c6f16_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libdeflate-1.25-hc11a715_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.3-haf25636_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype-2.14.1-hce30654_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype6-2.14.1-h6da58f4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgcc-15.2.0-hcbb3090_17.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-15.2.0-h07b0088_17.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_17.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libhwy-1.3.0-h48b13b8_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libjpeg-turbo-3.1.2-hc919400_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libjxl-0.11.1-h913acd8_8.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblapack-3.11.0-5_hd9741b5_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.2-h8088a28_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.67.0-hc438710_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.30-openmp_ha158390_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libpng-1.6.54-h132b30e_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.51.2-h1ae2325_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.1-h1590b86_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libtiff-4.7.1-h4030677_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libwebp-base-1.6.0-h07db88b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxcb-1.17.0-hdb1d25a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzopfli-1.0.3-h9f76cd9_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-21.1.8-h4a912ad_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lz4-c-1.10.0-h286801f_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-2.4.2-py312he281c53_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openjpeg-2.5.4-hbfb3c88_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openjph-0.26.0-h2a4d681_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.1-hd24854e_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pandas-3.0.0-py312hae6be28_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pillow-12.1.0-py312h4e908a4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pthread-stubs-0.4-hd74edd7_1002.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.12.12-h18782d2_2_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rav1e-0.7.1-h0716509_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/scikit-image-0.26.0-np2py312ha921b1d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/scikit-learn-1.8.0-np2py312he5ca3e3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/scipy-1.17.0-py312h0f234b1_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.0-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/snappy-1.2.2-hada39a4_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/svt-av1-4.0.0-h0cb729a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tifffile-2026.1.28-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xorg-libxau-1.0.12-hc919400_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xorg-libxdmcp-1.1.5-hc919400_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zfp-1.0.1-ha86207d_5.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-ng-2.3.3-hed4e4f5_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda + - pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cb/28/3bfe2fa5a7b9c46fe7e13c97bda14c895fb10fa2ebf1d0abb90e0cea7ee1/platformdirs-4.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/3f/f073a980969aa485ef288eb2e3b94c223ba9c7ac9941543f19b51659b98d/pyqt6-6.10.2-cp39-abi3-macosx_10_14_universal2.whl + - pypi: https://files.pythonhosted.org/packages/ce/c8/d99e65ab01c2402fb6bc4f77abef7244f7d5fb2f2e6d5b0abdf71bb2e4fc/pyqt6_qt6-6.10.2-py3-none-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/53/a6/0e4d8fa7d6deb750bd0fdf89024e39c71fb127efb5eeedfab6830ad6679a/pyqt6_sip-13.11.0-cp312-cp312-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/32/36/4c242f81fdcbfa4fb62a5645f6af79191f4097a0577bd5460c24f19cc4ef/pyqtgraph-0.14.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c1/00/5d8ddccbddc28871f40b5c84b55e121dac836e5efa407c11d3a00002e85d/pystackreg-0.2.8-cp312-cp312-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/b6/35/d16bfa235c8b7caba3730bba43e20b1e376d2224f407c178fbf59559f23e/sqlalchemy-2.0.46-cp312-cp312-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/16/e1/3079a9ff9b8e11b846c6ac5c8b5bfb7ff225eee721825310c91b3b50304f/tqdm-4.67.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl +packages: +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/_openmp_mutex-4.5-7_kmp_llvm.conda + build_number: 7 + sha256: 7acaa2e0782cad032bdaf756b536874346ac1375745fb250e9bdd6a48a7ab3cd + md5: a44032f282e7d2acdeb1c240308052dd + depends: + - llvm-openmp >=9.0.1 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 8325 + timestamp: 1764092507920 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/aom-3.9.1-h7bae524_0.conda + sha256: ec238f18ce8140485645252351a0eca9ef4f7a1c568a420f240a585229bc12ef + md5: 7adba36492a1bb22d98ffffe4f6fc6de + depends: + - __osx >=11.0 + - libcxx >=16 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 2235747 + timestamp: 1718551382432 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/blosc-1.21.6-h7dd00d9_1.conda + sha256: c3fe902114b9a3ac837e1a32408cc2142c147ec054c1038d37aec6814343f48a + md5: 925acfb50a750aa178f7a0aced77f351 + depends: + - __osx >=11.0 + - libcxx >=18 + - libzlib >=1.3.1,<2.0a0 + - lz4-c >=1.10.0,<1.11.0a0 + - snappy >=1.2.1,<1.3.0a0 + - zstd >=1.5.6,<1.6.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 33602 + timestamp: 1733513285902 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/brunsli-0.1-he0dfb12_2.conda + sha256: f32d7c6285601ac3f6baf0715b225fd017702cf24260c6f7f14f7b6e721d92bc + md5: 4cfe5258439d88ce2ef0b159007ee067 + depends: + - __osx >=11.0 + - libbrotlicommon >=1.2.0,<1.3.0a0 + - libbrotlidec >=1.2.0,<1.3.0a0 + - libbrotlienc >=1.2.0,<1.3.0a0 + - libcxx >=19 + license: MIT + license_family: MIT + purls: [] + size: 141089 + timestamp: 1761759272675 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_8.conda + sha256: b456200636bd5fecb2bec63f7e0985ad2097cf1b83d60ce0b6968dffa6d02aa1 + md5: 58fd217444c2a5701a44244faf518206 + depends: + - __osx >=11.0 + license: bzip2-1.0.6 + license_family: BSD + purls: [] + size: 125061 + timestamp: 1757437486465 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.34.6-hc919400_0.conda + sha256: 2995f2aed4e53725e5efbc28199b46bf311c3cab2648fc4f10c2227d6d5fa196 + md5: bcb3cba70cf1eec964a03b4ba7775f01 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: [] + size: 180327 + timestamp: 1765215064054 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-blosc2-2.23.0-hf9886e1_0.conda + sha256: 81c20499764e5fe801319c0e89bb473749497bd2327d68fbfeee5d13ece30486 + md5: d834074f69cd126ef3a86100480c21e2 + depends: + - __osx >=11.0 + - libcxx >=19 + - lz4-c >=1.10.0,<1.11.0a0 + - zlib-ng >=2.3.2,<2.4.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 254753 + timestamp: 1769992339050 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.1.4-hbd8a1cb_0.conda + sha256: b5974ec9b50e3c514a382335efa81ed02b05906849827a34061c496f4defa0b2 + md5: bddacf101bb4dd0e51811cb69c7790e2 + depends: + - __unix + license: ISC + purls: [] + size: 146519 + timestamp: 1767500828366 +- conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 + noarch: python + sha256: 561e6660f26c35d137ee150187d89767c988413c978e1b712d53f27ddf70ea17 + md5: 9b347a7ec10940d3f7941ff6c460b551 + depends: + - cached_property >=1.5.2,<1.5.3.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 4134 + timestamp: 1615209571450 +- conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 + sha256: 6dbf7a5070cc43d90a1e4c2ec0c541c69d8e30a0e25f50ce9f6e4a432e42c5d7 + md5: 576d629e47797577ab0f1b351297ef4a + depends: + - python >=3.6 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/cached-property?source=hash-mapping + size: 11065 + timestamp: 1615209567874 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/charls-2.4.2-h13dd4ca_0.conda + sha256: b9f79954e6d37ad59016b434abfdd096a75ff08c6de14e5198bcea497a10fae5 + md5: 6faf3cf8df25572c7f70138a45f37363 + depends: + - libcxx >=15.0.7 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 116255 + timestamp: 1684263271583 +- pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl + name: colorama + version: 0.4.6 + sha256: 4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 + requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*' +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/dav1d-1.2.1-hb547adb_0.conda + sha256: 93e077b880a85baec8227e8c72199220c7f87849ad32d02c14fb3807368260b8 + md5: 5a74cdee497e6b65173e10d94582fae6 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 316394 + timestamp: 1685695959391 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/giflib-5.2.2-h93a5062_0.conda + sha256: 843b3f364ff844137e37d5c0a181f11f6d51adcedd216f019d074e5aa5d7e09c + md5: 95fa1486c77505330c20f7202492b913 + license: MIT + license_family: MIT + purls: [] + size: 71613 + timestamp: 1712692611426 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/h5py-3.15.1-nompi_py312h4eecd6b_101.conda + sha256: 914d4f00a4d8cb86a70ce60241acc631a0e9d0cd939c0091b06de2d6cef51a3b + md5: 1f19a033f9c3f388c8f3d3c1643d6611 + depends: + - __osx >=11.0 + - cached-property + - hdf5 >=1.14.6,<1.14.7.0a0 + - numpy >=1.23,<3 + - python >=3.12,<3.13.0a0 + - python >=3.12,<3.13.0a0 *_cpython + - python_abi 3.12.* *_cp312 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/h5py?source=hash-mapping + size: 1139768 + timestamp: 1764017732485 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/hdf5-1.14.6-nompi_had3affe_106.conda + sha256: e91c2b8fe62d73bb56bdb9b5adcdcbedbd164ced288e0f361b8eb3f017ddcd7b + md5: 2d1270d283403c542680e969bea70355 + depends: + - __osx >=11.0 + - libaec >=1.1.5,<2.0a0 + - libcurl >=8.18.0,<9.0a0 + - libcxx >=19 + - libgfortran + - libgfortran5 >=14.3.0 + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.5.5,<4.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 3299759 + timestamp: 1770390513189 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.2-h38cb7af_0.conda + sha256: d4cefbca587429d1192509edc52c88de52bc96c2447771ddc1f8bee928aed5ef + md5: 1e93aca311da0210e660d2247812fa02 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: [] + size: 12358010 + timestamp: 1767970350308 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/imagecodecs-2026.1.14-py312h04e8b9b_1.conda + sha256: 92eb5f53637ec0a658cb1f6ed4bb21589255b05bcfeb9ceb625a484aa4c9e03e + md5: 74b6cccaa4457a6eaf84b28b3ba59391 + depends: + - __osx >=11.0 + - blosc >=1.21.6,<2.0a0 + - brunsli >=0.1,<1.0a0 + - bzip2 >=1.0.8,<2.0a0 + - c-blosc2 >=2.23.0,<2.24.0a0 + - charls >=2.4.2,<2.5.0a0 + - giflib >=5.2.2,<5.3.0a0 + - jxrlib >=1.1,<1.2.0a0 + - lcms2 >=2.18,<3.0a0 + - lerc >=4.0.0,<5.0a0 + - libaec >=1.1.5,<2.0a0 + - libavif16 >=1.3.0,<2.0a0 + - libbrotlicommon >=1.2.0,<1.3.0a0 + - libbrotlidec >=1.2.0,<1.3.0a0 + - libbrotlienc >=1.2.0,<1.3.0a0 + - libcxx >=19 + - libdeflate >=1.25,<1.26.0a0 + - libjpeg-turbo >=3.1.2,<4.0a0 + - libjxl >=0.11,<1.0a0 + - liblzma >=5.8.2,<6.0a0 + - libpng >=1.6.54,<1.7.0a0 + - libtiff >=4.7.1,<4.8.0a0 + - libwebp-base >=1.6.0,<2.0a0 + - libzlib >=1.3.1,<2.0a0 + - libzopfli >=1.0.3,<1.1.0a0 + - lz4-c >=1.10.0,<1.11.0a0 + - numpy >=1.23,<3 + - openjpeg >=2.5.4,<3.0a0 + - openjph >=0.26.0,<0.27.0a0 + - python >=3.12,<3.13.0a0 + - python >=3.12,<3.13.0a0 *_cpython + - python_abi 3.12.* *_cp312 + - snappy >=1.2.2,<1.3.0a0 + - zfp >=1.0.1,<2.0a0 + - zlib-ng >=2.3.2,<2.4.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/imagecodecs?source=hash-mapping + size: 1552322 + timestamp: 1770036954956 +- conda: https://conda.anaconda.org/conda-forge/noarch/imageio-2.37.0-pyhfb79c49_0.conda + sha256: 8ef69fa00c68fad34a3b7b260ea774fda9bd9274fd706d3baffb9519fd0063fe + md5: b5577bc2212219566578fd5af9993af6 + depends: + - numpy + - pillow >=8.3.2 + - python >=3.9 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/imageio?source=hash-mapping + size: 293226 + timestamp: 1738273949742 +- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda + sha256: c18ab120a0613ada4391b15981d86ff777b5690ca461ea7e9e49531e8f374745 + md5: 63ccfdc3a3ce25b027b8767eb722fca8 + depends: + - python >=3.9 + - zipp >=3.20 + - python + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/importlib-metadata?source=hash-mapping + size: 34641 + timestamp: 1747934053147 +- conda: https://conda.anaconda.org/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda + sha256: 301539229d7be6420c084490b8145583291123f0ce6b92f56be5948a2c83a379 + md5: 615de2a4d97af50c350e5cf160149e77 + depends: + - python >=3.10 + - setuptools + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/joblib?source=hash-mapping + size: 226448 + timestamp: 1765794135253 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/jxrlib-1.1-h93a5062_3.conda + sha256: c9e0d3cf9255d4585fa9b3d07ace3bd934fdc6a67ef4532e5507282eff2364ab + md5: 879997fd868f8e9e4c2a12aec8583799 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 197843 + timestamp: 1703334079437 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.21.3-h237132a_0.conda + sha256: 4442f957c3c77d69d9da3521268cad5d54c9033f1a73f99cde0a3658937b159b + md5: c6dc8a0fdec13a0565936655c33069a1 + depends: + - __osx >=11.0 + - libcxx >=16 + - libedit >=3.1.20191231,<3.2.0a0 + - libedit >=3.1.20191231,<4.0a0 + - openssl >=3.3.1,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 1155530 + timestamp: 1719463474401 +- conda: https://conda.anaconda.org/conda-forge/noarch/lazy-loader-0.4-pyhd8ed1ab_2.conda + sha256: d7ea986507090fff801604867ef8e79c8fda8ec21314ba27c032ab18df9c3411 + md5: d10d9393680734a8febc4b362a4c94f2 + depends: + - importlib-metadata + - packaging + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/lazy-loader?source=hash-mapping + size: 16298 + timestamp: 1733636905835 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/lcms2-2.18-hdfa7624_0.conda + sha256: d768da024ab74a4b30642401877fa914a68bdc238667f16b1ec2e0e98b2451a6 + md5: 6631a7bd2335bb9699b1dbc234b19784 + depends: + - __osx >=11.0 + - libjpeg-turbo >=3.1.2,<4.0a0 + - libtiff >=4.7.1,<4.8.0a0 + license: MIT + license_family: MIT + purls: [] + size: 211756 + timestamp: 1768184994800 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/lerc-4.0.0-hd64df32_1.conda + sha256: 12361697f8ffc9968907d1a7b5830e34c670e4a59b638117a2cdfed8f63a38f8 + md5: a74332d9b60b62905e3d30709df08bf1 + depends: + - __osx >=11.0 + - libcxx >=18 + license: Apache-2.0 + license_family: Apache + purls: [] + size: 188306 + timestamp: 1745264362794 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libaec-1.1.5-h8664d51_0.conda + sha256: af9cd8db11eb719e38a3340c88bb4882cf19b5b4237d93845224489fc2a13b46 + md5: 13e6d9ae0efbc9d2e9a01a91f4372b41 + depends: + - __osx >=11.0 + - libcxx >=19 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 30390 + timestamp: 1769222133373 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libavif16-1.3.0-hde9513d_3.conda + sha256: 92eb3f8134586972145378b21ac789a65ee232d7c1ef01ce5bfc9e850d0e0e60 + md5: 6e9bcb90cfd20178a52f355030aba237 + depends: + - __osx >=11.0 + - aom >=3.9.1,<3.10.0a0 + - dav1d >=1.2.1,<1.2.2.0a0 + - rav1e >=0.7.1,<0.8.0a0 + - svt-av1 >=4.0.0,<4.0.1.0a0 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 111474 + timestamp: 1769477399074 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.11.0-5_h51639a9_openblas.conda + build_number: 5 + sha256: 620a6278f194dcabc7962277da6835b1e968e46ad0c8e757736255f5ddbfca8d + md5: bcc025e2bbaf8a92982d20863fe1fb69 + depends: + - libopenblas >=0.3.30,<0.3.31.0a0 + - libopenblas >=0.3.30,<1.0a0 + constrains: + - libcblas 3.11.0 5*_openblas + - liblapack 3.11.0 5*_openblas + - liblapacke 3.11.0 5*_openblas + - blas 2.305 openblas + - mkl <2026 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 18546 + timestamp: 1765819094137 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlicommon-1.2.0-hc919400_1.conda + sha256: a7cb9e660531cf6fbd4148cff608c85738d0b76f0975c5fc3e7d5e92840b7229 + md5: 006e7ddd8a110771134fcc4e1e3a6ffa + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: [] + size: 79443 + timestamp: 1764017945924 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlidec-1.2.0-hc919400_1.conda + sha256: 2eae444039826db0454b19b52a3390f63bfe24f6b3e63089778dd5a5bf48b6bf + md5: 079e88933963f3f149054eec2c487bc2 + depends: + - __osx >=11.0 + - libbrotlicommon 1.2.0 hc919400_1 + license: MIT + license_family: MIT + purls: [] + size: 29452 + timestamp: 1764017979099 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlienc-1.2.0-hc919400_1.conda + sha256: 01436c32bb41f9cb4bcf07dda647ce4e5deb8307abfc3abdc8da5317db8189d1 + md5: b2b7c8288ca1a2d71ff97a8e6a1e8883 + depends: + - __osx >=11.0 + - libbrotlicommon 1.2.0 hc919400_1 + license: MIT + license_family: MIT + purls: [] + size: 290754 + timestamp: 1764018009077 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.11.0-5_hb0561ab_openblas.conda + build_number: 5 + sha256: 38809c361bbd165ecf83f7f05fae9b791e1baa11e4447367f38ae1327f402fc0 + md5: efd8bd15ca56e9d01748a3beab8404eb + depends: + - libblas 3.11.0 5_h51639a9_openblas + constrains: + - liblapacke 3.11.0 5*_openblas + - liblapack 3.11.0 5*_openblas + - blas 2.305 openblas + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 18548 + timestamp: 1765819108956 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.18.0-he38603e_0.conda + sha256: 11c78b3e89bc332933386f0a11ac60d9200afb7a811b9e3bec98aef8d4a6389b + md5: 36190179a799f3aee3c2d20a8a2b970d + depends: + - __osx >=11.0 + - krb5 >=1.21.3,<1.22.0a0 + - libnghttp2 >=1.67.0,<2.0a0 + - libssh2 >=1.11.1,<2.0a0 + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.5.4,<4.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: curl + license_family: MIT + purls: [] + size: 402681 + timestamp: 1767822693908 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-21.1.8-h55c6f16_2.conda + sha256: 5fbeb2fc2673f0455af6079abf93faaf27f11a92574ad51565fa1ecac9a4e2aa + md5: 4cb5878bdb9ebfa65b7cdff5445087c5 + depends: + - __osx >=11.0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + purls: [] + size: 570068 + timestamp: 1770238262922 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libdeflate-1.25-hc11a715_0.conda + sha256: 5e0b6961be3304a5f027a8c00bd0967fc46ae162cffb7553ff45c70f51b8314c + md5: a6130c709305cd9828b4e1bd9ba0000c + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: [] + size: 55420 + timestamp: 1761980066242 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_0.conda + sha256: 66aa216a403de0bb0c1340a88d1a06adaff66bae2cfd196731aa24db9859d631 + md5: 44083d2d2c2025afca315c7a172eab2b + depends: + - ncurses + - __osx >=11.0 + - ncurses >=6.5,<7.0a0 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 107691 + timestamp: 1738479560845 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda + sha256: 95cecb3902fbe0399c3a7e67a5bed1db813e5ab0e22f4023a5e0f722f2cc214f + md5: 36d33e440c31857372a72137f78bacf5 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 107458 + timestamp: 1702146414478 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.3-haf25636_0.conda + sha256: fce22610ecc95e6d149e42a42fbc3cc9d9179bd4eb6232639a60f06e080eec98 + md5: b79875dbb5b1db9a4a22a4520f918e1a + depends: + - __osx >=11.0 + constrains: + - expat 2.7.3.* + license: MIT + license_family: MIT + purls: [] + size: 67800 + timestamp: 1763549994166 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda + sha256: 6686a26466a527585e6a75cc2a242bf4a3d97d6d6c86424a441677917f28bec7 + md5: 43c04d9cb46ef176bb2a4c77e324d599 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: [] + size: 40979 + timestamp: 1769456747661 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype-2.14.1-hce30654_0.conda + sha256: 9de25a86066f078822d8dd95a83048d7dc2897d5d655c0e04a8a54fca13ef1ef + md5: f35fb38e89e2776994131fbf961fa44b + depends: + - libfreetype6 >=2.14.1 + license: GPL-2.0-only OR FTL + purls: [] + size: 7810 + timestamp: 1757947168537 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype6-2.14.1-h6da58f4_0.conda + sha256: cc4aec4c490123c0f248c1acd1aeab592afb6a44b1536734e20937cda748f7cd + md5: 6d4ede03e2a8e20eb51f7f681d2a2550 + depends: + - __osx >=11.0 + - libpng >=1.6.50,<1.7.0a0 + - libzlib >=1.3.1,<2.0a0 + constrains: + - freetype >=2.14.1 + license: GPL-2.0-only OR FTL + purls: [] + size: 346703 + timestamp: 1757947166116 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgcc-15.2.0-hcbb3090_17.conda + sha256: 07ba27f2ef1ce444ce5c99d0f9590772fc5b58ba73c993477bfad74b17dfaa79 + md5: 65c07cee234440ae4d5d340fc4b2e69a + depends: + - _openmp_mutex + constrains: + - libgomp 15.2.0 17 + - libgcc-ng ==15.2.0=*_17 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 402928 + timestamp: 1770254186829 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-15.2.0-h07b0088_17.conda + sha256: 7b96f428cb932df8d7c1aa4e433ed29b779dd9571934afdf4f9093a85155a142 + md5: 45ba22eb5381fb602a45233d89ba27ae + depends: + - libgfortran5 15.2.0 hdae7583_17 + constrains: + - libgfortran-ng ==15.2.0=*_17 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 139757 + timestamp: 1770254394473 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_17.conda + sha256: 9c41ff08f61c953cee13fc3df3c6245741e5a71e453b2c094a6d55b0eeda3669 + md5: c6329d871fb3207e9657c384128f5488 + depends: + - libgcc >=15.2.0 + constrains: + - libgfortran 15.2.0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 599374 + timestamp: 1770254196706 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libhwy-1.3.0-h48b13b8_1.conda + sha256: 837fe775ba8ec9f08655bb924e28dba390d917423350333a75fd5eeac0776174 + md5: 6375717f5fcd756de929a06d0e40fab0 + depends: + - __osx >=11.0 + - libcxx >=19 + license: Apache-2.0 OR BSD-3-Clause + purls: [] + size: 581579 + timestamp: 1758894814983 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libjpeg-turbo-3.1.2-hc919400_0.conda + sha256: 6c061c56058bb10374daaef50e81b39cf43e8aee21f0037022c0c39c4f31872f + md5: f0695fbecf1006f27f4395d64bd0c4b8 + depends: + - __osx >=11.0 + constrains: + - jpeg <0.0.0a + license: IJG AND BSD-3-Clause AND Zlib + purls: [] + size: 551197 + timestamp: 1762095054358 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libjxl-0.11.1-h913acd8_8.conda + sha256: cb3713aa91c9271e1992d2a7234447f6da84ec0d59a5cf2f92ba850f808becb9 + md5: c41ad4bd5cb936fd7662426753ff1784 + depends: + - libcxx >=19 + - __osx >=11.0 + - libhwy >=1.3.0,<1.4.0a0 + - libbrotlienc >=1.2.0,<1.3.0a0 + - libbrotlidec >=1.2.0,<1.3.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 1030574 + timestamp: 1768822131848 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblapack-3.11.0-5_hd9741b5_openblas.conda + build_number: 5 + sha256: 735a6e6f7d7da6f718b6690b7c0a8ae4815afb89138aa5793abe78128e951dbb + md5: ca9d752201b7fa1225bca036ee300f2b + depends: + - libblas 3.11.0 5_h51639a9_openblas + constrains: + - libcblas 3.11.0 5*_openblas + - blas 2.305 openblas + - liblapacke 3.11.0 5*_openblas + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 18551 + timestamp: 1765819121855 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.2-h8088a28_0.conda + sha256: 7bfc7ffb2d6a9629357a70d4eadeadb6f88fa26ebc28f606b1c1e5e5ed99dc7e + md5: 009f0d956d7bfb00de86901d16e486c7 + depends: + - __osx >=11.0 + constrains: + - xz 5.8.2.* + license: 0BSD + purls: [] + size: 92242 + timestamp: 1768752982486 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.67.0-hc438710_0.conda + sha256: a07cb53b5ffa2d5a18afc6fd5a526a5a53dd9523fbc022148bd2f9395697c46d + md5: a4b4dd73c67df470d091312ab87bf6ae + depends: + - __osx >=11.0 + - c-ares >=1.34.5,<2.0a0 + - libcxx >=19 + - libev >=4.33,<4.34.0a0 + - libev >=4.33,<5.0a0 + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.5.2,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 575454 + timestamp: 1756835746393 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.30-openmp_ha158390_4.conda + sha256: ebbbc089b70bcde87c4121a083c724330f02a690fb9d7c6cd18c30f1b12504fa + md5: a6f6d3a31bb29e48d37ce65de54e2df0 + depends: + - __osx >=11.0 + - libgfortran + - libgfortran5 >=14.3.0 + - llvm-openmp >=19.1.7 + constrains: + - openblas >=0.3.30,<0.3.31.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 4284132 + timestamp: 1768547079205 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libpng-1.6.54-h132b30e_0.conda + sha256: 1c271c0ec73b69f7570c5da67d0e47ddf7ff079bc1ca2dfaccd267ea39314b06 + md5: 1b80fd1eecb98f1cb7de4239f5d7dc15 + depends: + - __osx >=11.0 + - libzlib >=1.3.1,<2.0a0 + license: zlib-acknowledgement + purls: [] + size: 288910 + timestamp: 1768285694469 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.51.2-h1ae2325_0.conda + sha256: 6e9b9f269732cbc4698c7984aa5b9682c168e2a8d1e0406e1ff10091ca046167 + md5: 4b0bf313c53c3e89692f020fb55d5f2c + depends: + - __osx >=11.0 + - icu >=78.2,<79.0a0 + - libzlib >=1.3.1,<2.0a0 + license: blessing + purls: [] + size: 909777 + timestamp: 1768148320535 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.1-h1590b86_0.conda + sha256: 8bfe837221390ffc6f111ecca24fa12d4a6325da0c8d131333d63d6c37f27e0a + md5: b68e8f66b94b44aaa8de4583d3d4cc40 + depends: + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.5.0,<4.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 279193 + timestamp: 1745608793272 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libtiff-4.7.1-h4030677_1.conda + sha256: e9248077b3fa63db94caca42c8dbc6949c6f32f94d1cafad127f9005d9b1507f + md5: e2a72ab2fa54ecb6abab2b26cde93500 + depends: + - __osx >=11.0 + - lerc >=4.0.0,<5.0a0 + - libcxx >=19 + - libdeflate >=1.25,<1.26.0a0 + - libjpeg-turbo >=3.1.0,<4.0a0 + - liblzma >=5.8.1,<6.0a0 + - libwebp-base >=1.6.0,<2.0a0 + - libzlib >=1.3.1,<2.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: HPND + purls: [] + size: 373892 + timestamp: 1762022345545 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libwebp-base-1.6.0-h07db88b_0.conda + sha256: a4de3f371bb7ada325e1f27a4ef7bcc81b2b6a330e46fac9c2f78ac0755ea3dd + md5: e5e7d467f80da752be17796b87fe6385 + depends: + - __osx >=11.0 + constrains: + - libwebp 1.6.0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 294974 + timestamp: 1752159906788 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxcb-1.17.0-hdb1d25a_0.conda + sha256: bd3816218924b1e43b275863e21a3e13a5db4a6da74cca8e60bc3c213eb62f71 + md5: af523aae2eca6dfa1c8eec693f5b9a79 + depends: + - __osx >=11.0 + - pthread-stubs + - xorg-libxau >=1.0.11,<2.0a0 + - xorg-libxdmcp + license: MIT + license_family: MIT + purls: [] + size: 323658 + timestamp: 1727278733917 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda + sha256: ce34669eadaba351cd54910743e6a2261b67009624dbc7daeeafdef93616711b + md5: 369964e85dc26bfe78f41399b366c435 + depends: + - __osx >=11.0 + constrains: + - zlib 1.3.1 *_2 + license: Zlib + license_family: Other + purls: [] + size: 46438 + timestamp: 1727963202283 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzopfli-1.0.3-h9f76cd9_0.tar.bz2 + sha256: e3003b8efe551902dc60b21c81d7164b291b26b7862704421368d26ba5c10fa0 + md5: a0758d74f57741aa0d9ede13fd592e56 + depends: + - libcxx >=11.0.0 + license: Apache-2.0 + license_family: Apache + purls: [] + size: 147901 + timestamp: 1607309166373 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-21.1.8-h4a912ad_0.conda + sha256: 56bcd20a0a44ddd143b6ce605700fdf876bcf5c509adc50bf27e76673407a070 + md5: 206ad2df1b5550526e386087bef543c7 + depends: + - __osx >=11.0 + constrains: + - openmp 21.1.8|21.1.8.* + - intel-openmp <0.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + purls: [] + size: 285974 + timestamp: 1765964756583 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/lz4-c-1.10.0-h286801f_1.conda + sha256: 94d3e2a485dab8bdfdd4837880bde3dd0d701e2b97d6134b8806b7c8e69c8652 + md5: 01511afc6cc1909c5303cf31be17b44f + depends: + - __osx >=11.0 + - libcxx >=18 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 148824 + timestamp: 1733741047892 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda + sha256: 2827ada40e8d9ca69a153a45f7fd14f32b2ead7045d3bbb5d10964898fe65733 + md5: 068d497125e4bf8a66bf707254fff5ae + depends: + - __osx >=11.0 + license: X11 AND BSD-3-Clause + purls: [] + size: 797030 + timestamp: 1738196177597 +- conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda + sha256: f6a82172afc50e54741f6f84527ef10424326611503c64e359e25a19a8e4c1c6 + md5: a2c1eeadae7a309daed9d62c96012a2b + depends: + - python >=3.11 + - python + constrains: + - numpy >=1.25 + - scipy >=1.11.2 + - matplotlib-base >=3.8 + - pandas >=2.0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/networkx?source=compressed-mapping + size: 1587439 + timestamp: 1765215107045 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-2.4.2-py312he281c53_1.conda + sha256: 7fd2f1a33b244129dcc2163304d103a7062fc38f01fe13945c9ea95cef12b954 + md5: 4afbe6ffff0335d25f3c5cc78b1350a4 + depends: + - python + - libcxx >=19 + - __osx >=11.0 + - python 3.12.* *_cpython + - libblas >=3.9.0,<4.0a0 + - python_abi 3.12.* *_cp312 + - liblapack >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + constrains: + - numpy-base <0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/numpy?source=hash-mapping + size: 6840961 + timestamp: 1770098400654 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/openjpeg-2.5.4-hbfb3c88_0.conda + sha256: dd73e8f1da7dd6a5494c5586b835cbe2ec68bace55610b1c4bf927400fe9c0d7 + md5: 6bf3d24692c157a41c01ce0bd17daeea + depends: + - __osx >=11.0 + - libcxx >=19 + - libpng >=1.6.50,<1.7.0a0 + - libtiff >=4.7.1,<4.8.0a0 + - libzlib >=1.3.1,<2.0a0 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 319967 + timestamp: 1758489514651 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/openjph-0.26.0-h2a4d681_0.conda + sha256: 151443d08ec9149c3547eb1b066bfee8d15af6e8cf1724f100a1efe96ffba8be + md5: 165b7d49b821d421d057dbb35897df32 + depends: + - libcxx >=19 + - __osx >=11.0 + - libtiff >=4.7.1,<4.8.0a0 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 181565 + timestamp: 1766578508827 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.1-hd24854e_1.conda + sha256: 361f5c5e60052abc12bdd1b50d7a1a43e6a6653aab99a2263bf2288d709dcf67 + md5: f4f6ad63f98f64191c3e77c5f5f29d76 + depends: + - __osx >=11.0 + - ca-certificates + license: Apache-2.0 + license_family: Apache + purls: [] + size: 3104268 + timestamp: 1769556384749 +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda + sha256: c1fc0f953048f743385d31c468b4a678b3ad20caffdeaa94bed85ba63049fd58 + md5: b76541e68fea4d511b1ac46a28dcd2c6 + depends: + - python >=3.8 + - python + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/packaging?source=compressed-mapping + size: 72010 + timestamp: 1769093650580 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pandas-3.0.0-py312hae6be28_0.conda + sha256: e77a102f752d66a4afbda7ba4746689ec3083723d5d6fc7d5af8ddef25ff5655 + md5: 2b38a1d070dff7f0f92641a5fa130e23 + depends: + - python + - numpy >=1.26.0 + - python-dateutil >=2.8.2 + - __osx >=11.0 + - python 3.12.* *_cpython + - libcxx >=19 + - numpy >=1.23,<3 + - python_abi 3.12.* *_cp312 + constrains: + - adbc-driver-postgresql >=1.2.0 + - adbc-driver-sqlite >=1.2.0 + - beautifulsoup4 >=4.12.3 + - blosc >=1.21.3 + - bottleneck >=1.4.2 + - fastparquet >=2024.11.0 + - fsspec >=2024.10.0 + - gcsfs >=2024.10.0 + - html5lib >=1.1 + - hypothesis >=6.116.0 + - jinja2 >=3.1.5 + - lxml >=5.3.0 + - matplotlib >=3.9.3 + - numba >=0.60.0 + - numexpr >=2.10.2 + - odfpy >=1.4.1 + - openpyxl >=3.1.5 + - psycopg2 >=2.9.10 + - pyarrow >=13.0.0 + - pyiceberg >=0.8.1 + - pymysql >=1.1.1 + - pyqt5 >=5.15.9 + - pyreadstat >=1.2.8 + - pytables >=3.10.1 + - pytest >=8.3.4 + - pytest-xdist >=3.6.1 + - python-calamine >=0.3.0 + - pytz >=2024.2 + - pyxlsb >=1.0.10 + - qtpy >=2.4.2 + - scipy >=1.14.1 + - s3fs >=2024.10.0 + - sqlalchemy >=2.0.36 + - tabulate >=0.9.0 + - xarray >=2024.10.0 + - xlrd >=2.0.1 + - xlsxwriter >=3.2.0 + - zstandard >=0.23.0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/pandas?source=hash-mapping + size: 13876050 + timestamp: 1769076491884 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pillow-12.1.0-py312h4e908a4_0.conda + sha256: 8cf9e79ad0ba1206f716dd3f6ca9c48e2864882e0c514d1fe4dbfebe63f25ac0 + md5: d831c4844e7a04eab4aa91a2c26dbbdd + depends: + - python + - __osx >=11.0 + - python 3.12.* *_cpython + - zlib-ng >=2.3.2,<2.4.0a0 + - python_abi 3.12.* *_cp312 + - tk >=8.6.13,<8.7.0a0 + - libwebp-base >=1.6.0,<2.0a0 + - openjpeg >=2.5.4,<3.0a0 + - lcms2 >=2.17,<3.0a0 + - libxcb >=1.17.0,<2.0a0 + - libtiff >=4.7.1,<4.8.0a0 + - libjpeg-turbo >=3.1.2,<4.0a0 + - libfreetype >=2.14.1 + - libfreetype6 >=2.14.1 + license: HPND + purls: + - pkg:pypi/pillow?source=hash-mapping + size: 953450 + timestamp: 1767353279678 +- pypi: https://files.pythonhosted.org/packages/cb/28/3bfe2fa5a7b9c46fe7e13c97bda14c895fb10fa2ebf1d0abb90e0cea7ee1/platformdirs-4.5.1-py3-none-any.whl + name: platformdirs + version: 4.5.1 + sha256: d03afa3963c806a9bed9d5125c8f4cb2fdaf74a55ab60e5d59b3fde758104d31 + requires_dist: + - furo>=2025.9.25 ; extra == 'docs' + - proselint>=0.14 ; extra == 'docs' + - sphinx-autodoc-typehints>=3.2 ; extra == 'docs' + - sphinx>=8.2.3 ; extra == 'docs' + - appdirs==1.4.4 ; extra == 'test' + - covdefaults>=2.3 ; extra == 'test' + - pytest-cov>=7 ; extra == 'test' + - pytest-mock>=3.15.1 ; extra == 'test' + - pytest>=8.4.2 ; extra == 'test' + - mypy>=1.18.2 ; extra == 'type' + requires_python: '>=3.10' +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pthread-stubs-0.4-hd74edd7_1002.conda + sha256: 8ed65e17fbb0ca944bfb8093b60086e3f9dd678c3448b5de212017394c247ee3 + md5: 415816daf82e0b23a736a069a75e9da7 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: [] + size: 8381 + timestamp: 1726802424786 +- pypi: https://files.pythonhosted.org/packages/fb/3f/f073a980969aa485ef288eb2e3b94c223ba9c7ac9941543f19b51659b98d/pyqt6-6.10.2-cp39-abi3-macosx_10_14_universal2.whl + name: pyqt6 + version: 6.10.2 + sha256: 37ae7c1183fe4dd0c6aefd2006a35731245de1cb6f817bb9e414a3e4848dfd6d + requires_dist: + - pyqt6-sip>=13.8,<14 + - pyqt6-qt6>=6.10.0,<6.11.0 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/ce/c8/d99e65ab01c2402fb6bc4f77abef7244f7d5fb2f2e6d5b0abdf71bb2e4fc/pyqt6_qt6-6.10.2-py3-none-macosx_11_0_arm64.whl + name: pyqt6-qt6 + version: 6.10.2 + sha256: 6dda853a8db1b8d1a2ddbbe76cc6c3aa86614cad14056bd3c0435d8feea73b2d +- pypi: https://files.pythonhosted.org/packages/53/a6/0e4d8fa7d6deb750bd0fdf89024e39c71fb127efb5eeedfab6830ad6679a/pyqt6_sip-13.11.0-cp312-cp312-macosx_10_9_universal2.whl + name: pyqt6-sip + version: 13.11.0 + sha256: 6b3267cd93b7f4da6fdf9a6a26f3baed8faae06e5cdd76235f2acc2116c40a54 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/32/36/4c242f81fdcbfa4fb62a5645f6af79191f4097a0577bd5460c24f19cc4ef/pyqtgraph-0.14.0-py3-none-any.whl + name: pyqtgraph + version: 0.14.0 + sha256: 7abb7c3e17362add64f8711b474dffac5e7b0e9245abdf992e9a44119b7aa4f5 + requires_dist: + - numpy>=1.25.0 + - colorama + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/c1/00/5d8ddccbddc28871f40b5c84b55e121dac836e5efa407c11d3a00002e85d/pystackreg-0.2.8-cp312-cp312-macosx_11_0_arm64.whl + name: pystackreg + version: 0.2.8 + sha256: cc82203cde0a1909180d0ab7067071ac13d9558632f602ca72cce40415a3f339 + requires_dist: + - numpy + - tqdm +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.12.12-h18782d2_2_cpython.conda + build_number: 2 + sha256: 765e5d0f92dabc8c468d078a4409490e08181a6f9be6f5d5802a4e3131b9a69c + md5: e198b8f74b12292d138eb4eceb004fa3 + depends: + - __osx >=11.0 + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.7.3,<3.0a0 + - libffi >=3.5.2,<3.6.0a0 + - liblzma >=5.8.2,<6.0a0 + - libsqlite >=3.51.2,<4.0a0 + - libzlib >=1.3.1,<2.0a0 + - ncurses >=6.5,<7.0a0 + - openssl >=3.5.4,<4.0a0 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + constrains: + - python_abi 3.12.* *_cp312 + license: Python-2.0 + purls: [] + size: 12953358 + timestamp: 1769472376612 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda + sha256: d6a17ece93bbd5139e02d2bd7dbfa80bee1a4261dced63f65f679121686bf664 + md5: 5b8d21249ff20967101ffa321cab24e8 + depends: + - python >=3.9 + - six >=1.5 + - python + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/python-dateutil?source=hash-mapping + size: 233310 + timestamp: 1751104122689 +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda + build_number: 8 + sha256: 80677180dd3c22deb7426ca89d6203f1c7f1f256f2d5a94dc210f6e758229809 + md5: c3efd25ac4d74b1584d2f7a57195ddf1 + constrains: + - python 3.12.* *_cpython + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 6958 + timestamp: 1752805918820 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/rav1e-0.7.1-h0716509_3.conda + sha256: 65f862b2b31ef2b557990a82015cbd41e5a66041c2f79b4451dd14b4595d4c04 + md5: 7b37f30516100b86ea522350c8cab44c + depends: + - __osx >=11.0 + constrains: + - __osx >=11.0 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 856271 + timestamp: 1746622200646 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda + sha256: a77010528efb4b548ac2a4484eaf7e1c3907f2aec86123ed9c5212ae44502477 + md5: f8381319127120ce51e081dce4865cf4 + depends: + - __osx >=11.0 + - ncurses >=6.5,<7.0a0 + license: GPL-3.0-only + license_family: GPL + purls: [] + size: 313930 + timestamp: 1765813902568 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/scikit-image-0.26.0-np2py312ha921b1d_0.conda + sha256: 87f56777c91af0849bbcfc0f9f0d53cbf8eb651151975782fd4f744b7ccd1739 + md5: c582406829218aa701e9ce61aa57973e + depends: + - imageio >=2.33,!=2.35.0 + - lazy-loader >=0.4 + - networkx >=3.0 + - numpy >=1.24 + - packaging >=21.0 + - pillow >=10.1 + - python + - scipy >=1.11.4 + - tifffile >=2022.8.12 + - __osx >=11.0 + - libcxx >=19 + - python 3.12.* *_cpython + - python_abi 3.12.* *_cp312 + - numpy >=1.23,<3 + constrains: + - astropy-base >=6.0 + - dask-core >=2023.2.0,!=2024.8.0 + - matplotlib-base >=3.7 + - pooch >=1.6.0 + - pyamg >=5.2 + - pywavelets >=1.6 + - scikit-learn >=1.2 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/scikit-image?source=hash-mapping + size: 17963697 + timestamp: 1766684388162 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/scikit-learn-1.8.0-np2py312he5ca3e3_1.conda + sha256: 5f640a06e001666f9d4dca7cca992f1753e722e9f6e50899d7d250c02ddf7398 + md5: ed7887c51edfa304c69a424279cec675 + depends: + - python + - numpy >=1.24.1 + - scipy >=1.10.0 + - joblib >=1.3.0 + - threadpoolctl >=3.2.0 + - libcxx >=19 + - python 3.12.* *_cpython + - __osx >=11.0 + - llvm-openmp >=19.1.7 + - numpy >=1.23,<3 + - python_abi 3.12.* *_cp312 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/scikit-learn?source=hash-mapping + size: 9124177 + timestamp: 1766550900752 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/scipy-1.17.0-py312h0f234b1_1.conda + sha256: a204b9b3a59a88a320d9da772eecda58242cfaaf785119927eb59c4bdc6fa66f + md5: 1f5a9253e1c3484a5c1df0b8145a9ce3 + depends: + - __osx >=11.0 + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - libcxx >=19 + - libgfortran + - libgfortran5 >=14.3.0 + - liblapack >=3.9.0,<4.0a0 + - numpy <2.7 + - numpy >=1.23,<3 + - numpy >=1.25.2 + - python >=3.12,<3.13.0a0 + - python >=3.12,<3.13.0a0 *_cpython + - python_abi 3.12.* *_cp312 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/scipy?source=hash-mapping + size: 13802410 + timestamp: 1768801119235 +- conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.0-pyh332efcf_0.conda + sha256: fd7201e38e38bf7f25818d624ca8da97b8998957ca9ae3fb7fdc9c17e6b25fcd + md5: 1d00d46c634177fc8ede8b99d6089239 + depends: + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/setuptools?source=compressed-mapping + size: 637506 + timestamp: 1770634745653 +- conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + sha256: 458227f759d5e3fcec5d9b7acce54e10c9e1f4f4b7ec978f3bfd54ce4ee9853d + md5: 3339e3b65d58accf4ca4fb8748ab16b3 + depends: + - python >=3.9 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/six?source=hash-mapping + size: 18455 + timestamp: 1753199211006 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/snappy-1.2.2-hada39a4_1.conda + sha256: cb9305ede19584115f43baecdf09a3866bfcd5bcca0d9e527bd76d9a1dbe2d8d + md5: fca4a2222994acd7f691e57f94b750c5 + depends: + - libcxx >=19 + - __osx >=11.0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 38883 + timestamp: 1762948066818 +- pypi: https://files.pythonhosted.org/packages/b6/35/d16bfa235c8b7caba3730bba43e20b1e376d2224f407c178fbf59559f23e/sqlalchemy-2.0.46-cp312-cp312-macosx_11_0_arm64.whl + name: sqlalchemy + version: 2.0.46 + sha256: 3a9a72b0da8387f15d5810f1facca8f879de9b85af8c645138cba61ea147968c + requires_dist: + - importlib-metadata ; python_full_version < '3.8' + - greenlet>=1 ; platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64' + - typing-extensions>=4.6.0 + - greenlet>=1 ; extra == 'asyncio' + - mypy>=0.910 ; extra == 'mypy' + - pyodbc ; extra == 'mssql' + - pymssql ; extra == 'mssql-pymssql' + - pyodbc ; extra == 'mssql-pyodbc' + - mysqlclient>=1.4.0 ; extra == 'mysql' + - mysql-connector-python ; extra == 'mysql-connector' + - mariadb>=1.0.1,!=1.1.2,!=1.1.5,!=1.1.10 ; extra == 'mariadb-connector' + - cx-oracle>=8 ; extra == 'oracle' + - oracledb>=1.0.1 ; extra == 'oracle-oracledb' + - psycopg2>=2.7 ; extra == 'postgresql' + - pg8000>=1.29.1 ; extra == 'postgresql-pg8000' + - greenlet>=1 ; extra == 'postgresql-asyncpg' + - asyncpg ; extra == 'postgresql-asyncpg' + - psycopg2-binary ; extra == 'postgresql-psycopg2binary' + - psycopg2cffi ; extra == 'postgresql-psycopg2cffi' + - psycopg>=3.0.7 ; extra == 'postgresql-psycopg' + - psycopg[binary]>=3.0.7 ; extra == 'postgresql-psycopgbinary' + - pymysql ; extra == 'pymysql' + - greenlet>=1 ; extra == 'aiomysql' + - aiomysql>=0.2.0 ; extra == 'aiomysql' + - greenlet>=1 ; extra == 'aioodbc' + - aioodbc ; extra == 'aioodbc' + - greenlet>=1 ; extra == 'asyncmy' + - asyncmy>=0.2.3,!=0.2.4,!=0.2.6 ; extra == 'asyncmy' + - greenlet>=1 ; extra == 'aiosqlite' + - aiosqlite ; extra == 'aiosqlite' + - typing-extensions!=3.10.0.1 ; extra == 'aiosqlite' + - sqlcipher3-binary ; extra == 'sqlcipher' + requires_python: '>=3.7' +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/svt-av1-4.0.0-h0cb729a_0.conda + sha256: f7fc5a18f4a6cf61fa4b6697c6aa28426b07a3df2b53a96b25dda28641991532 + md5: 3dc1d4f4c9829c82c7f6660878abcd32 + depends: + - __osx >=11.0 + - libcxx >=19 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 1455052 + timestamp: 1769280806030 +- conda: https://conda.anaconda.org/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda + sha256: 6016672e0e72c4cf23c0cf7b1986283bd86a9c17e8d319212d78d8e9ae42fdfd + md5: 9d64911b31d57ca443e9f1e36b04385f + depends: + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/threadpoolctl?source=hash-mapping + size: 23869 + timestamp: 1741878358548 +- conda: https://conda.anaconda.org/conda-forge/noarch/tifffile-2026.1.28-pyhd8ed1ab_0.conda + sha256: efd8a9d2b57678e5efb41cc261dace3341ddd877ac514bfccab579f437efd826 + md5: e8d6529858171ac4babb28c334306c0d + depends: + - imagecodecs >=2025.11.11 + - numpy >=1.19.2 + - python >=3.11 + constrains: + - matplotlib-base >=3.3 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/tifffile?source=compressed-mapping + size: 183339 + timestamp: 1769690244546 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda + sha256: 799cab4b6cde62f91f750149995d149bc9db525ec12595e8a1d91b9317f038b3 + md5: a9d86bc62f39b94c4661716624eb21b0 + depends: + - __osx >=11.0 + - libzlib >=1.3.1,<2.0a0 + license: TCL + license_family: BSD + purls: [] + size: 3127137 + timestamp: 1769460817696 +- pypi: https://files.pythonhosted.org/packages/16/e1/3079a9ff9b8e11b846c6ac5c8b5bfb7ff225eee721825310c91b3b50304f/tqdm-4.67.3-py3-none-any.whl + name: tqdm + version: 4.67.3 + sha256: ee1e4c0e59148062281c49d80b25b67771a127c85fc9676d3be5f243206826bf + requires_dist: + - colorama ; sys_platform == 'win32' + - importlib-metadata ; python_full_version < '3.8' + - pytest>=6 ; extra == 'dev' + - pytest-cov ; extra == 'dev' + - pytest-timeout ; extra == 'dev' + - pytest-asyncio>=0.24 ; extra == 'dev' + - nbval ; extra == 'dev' + - requests ; extra == 'discord' + - slack-sdk ; extra == 'slack' + - requests ; extra == 'telegram' + - ipywidgets>=6 ; extra == 'notebook' + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl + name: typing-extensions + version: 4.15.0 + sha256: f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548 + requires_python: '>=3.9' +- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + sha256: 1d30098909076af33a35017eed6f2953af1c769e273a0626a04722ac4acaba3c + md5: ad659d0a2b3e47e38d829aa8cad2d610 + license: LicenseRef-Public-Domain + purls: [] + size: 119135 + timestamp: 1767016325805 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/xorg-libxau-1.0.12-hc919400_1.conda + sha256: adae11db0f66f86156569415ed79cda75b2dbf4bea48d1577831db701438164f + md5: 78b548eed8227a689f93775d5d23ae09 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: [] + size: 14105 + timestamp: 1762976976084 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/xorg-libxdmcp-1.1.5-hc919400_1.conda + sha256: f7fa0de519d8da589995a1fe78ef74556bb8bc4172079ae3a8d20c3c81354906 + md5: 9d1299ace1924aa8f4e0bc8e71dd0cf7 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: [] + size: 19156 + timestamp: 1762977035194 +- pypi: https://files.pythonhosted.org/packages/38/8b/7ec325b4e9e78beefc2d025b01ee8a2fde771ef7c957c3bff99b9e1fbffa/xraydb-4.5.8-py3-none-any.whl + name: xraydb + version: 4.5.8 + sha256: 2215baafa6a03d00d0254a94525aafc6493c8c285e4ac4477fbd6271b25e6a51 + requires_dist: + - numpy>=1.19 + - scipy>=1.6 + - sqlalchemy>=2.0.1 + - platformdirs + - build ; extra == 'dev' + - twine ; extra == 'dev' + - sphinx ; extra == 'doc' + - pytest ; extra == 'test' + - pytest-cov ; extra == 'test' + - coverage ; extra == 'test' + - xraydb[dev,doc,test] ; extra == 'all' + requires_python: '>=3.9' +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/zfp-1.0.1-ha86207d_5.conda + sha256: 5b8bc86ca206f456ca9fe9e1a629f68b949ac47070211bccf4b44d29141c85d7 + md5: 581bd74656ccd460cf2bbe152292a1eb + depends: + - __osx >=11.0 + - libcxx >=19 + - llvm-openmp >=19.1.7 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 204043 + timestamp: 1766549790975 +- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda + sha256: b4533f7d9efc976511a73ef7d4a2473406d7f4c750884be8e8620b0ce70f4dae + md5: 30cd29cb87d819caead4d55184c1d115 + depends: + - python >=3.10 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/zipp?source=compressed-mapping + size: 24194 + timestamp: 1764460141901 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-ng-2.3.3-hed4e4f5_1.conda + sha256: a339606a6b224bb230ff3d711e801934f3b3844271df9720165e0353716580d4 + md5: d99c2a23a31b0172e90f456f580b695e + depends: + - __osx >=11.0 + - libcxx >=19 + license: Zlib + license_family: Other + purls: [] + size: 94375 + timestamp: 1770168363685 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda + sha256: 9485ba49e8f47d2b597dd399e88f4802e100851b27c21d7525625b0b4025a5d9 + md5: ab136e4c34e97f34fb621d2592a393d8 + depends: + - __osx >=11.0 + - libzlib >=1.3.1,<2.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 433413 + timestamp: 1764777166076 diff --git a/pixi.toml b/pixi.toml new file mode 100644 index 0000000..c77e500 --- /dev/null +++ b/pixi.toml @@ -0,0 +1,25 @@ +[workspace] +authors = ["Ajith Pattammattel "] +channels = ["conda-forge"] +name = "xmidas" +platforms = ["osx-arm64"] +version = "0.1.0" + +[tasks] + +[dependencies] +python = "3.12.*" +h5py = ">=3.15.1,<4" +numpy = ">=2.4.2,<3" +pandas = ">=3.0.0,<4" +scikit-image = ">=0.26.0,<0.27" +scikit-learn = ">=1.8.0,<2" +scipy = ">=1.17.0,<2" +tifffile = ">=2026.1.28,<2027" +packaging = ">=26.0,<27" + +[pypi-dependencies] +pyqt6 = ">=6.10.2, <7" +pystackreg = ">=0.2.8, <0.3" +xraydb = ">=4.5.8, <5" +pyqtgraph = ">=0.14.0, <0.15" diff --git a/xmidas/main.py b/xmidas/main.py index 4cbee39..a9f68c0 100644 --- a/xmidas/main.py +++ b/xmidas/main.py @@ -32,7 +32,7 @@ from PyQt6 import QtWidgets, QtCore, QtGui, uic, QtTest from PyQt6.QtGui import QMovie from PyQt6.QtWidgets import QMessageBox, QFileDialog, QApplication -from PyQt6.QtCore import QObject, pyqtSignal, pyqtSlot, QRunnable, QThreadPool, PYQT_VERSION_STR +from PyQt6.QtCore import QObject, pyqtSignal, pyqtSlot, QRunnable, QThreadPool, PYQT_VERSION_STR, QTimer from xmidas.utils.utils import * @@ -1396,17 +1396,19 @@ def findEo(self): def initNormVals(self): self.getLivePlotData() e0_init = self.e_[np.argmax(np.gradient(self.mu_))] - pre1, pre2, post1, post2 = xanesNormalization( + pre_edge, post_edge, norm = xanesNormalization( self.e_, self.mu_, e0=e0_init, nnorm=1, nvict=0, ) - self.dsb_norm_pre1.setValue(pre1) - self.dsb_norm_pre2.setValue(pre2) - self.dsb_norm_post1.setValue(post1) - self.dsb_norm_post2.setValue(post2) + # xanesNormalization now returns arrays, not scalar bounds + # Set reasonable default bounds for the UI based on standard XANES practice + self.dsb_norm_pre1.setValue(-50) # 50 eV before edge + self.dsb_norm_pre2.setValue(-20) # 20 eV before edge + self.dsb_norm_post1.setValue(50) # 50 eV after edge + self.dsb_norm_post2.setValue(150) # 150 eV after edge self.dsb_norm_Eo.setValue(e0_init) def getNormParams(self): @@ -1515,14 +1517,12 @@ def normalizeStack(self): self.e_, self.displayedStack, e0=eo_, - step=None, nnorm=norm_order, nvict=0, pre1=pre1_, pre2=pre2_, norm1=norm1_, norm2=norm2_, - useFlattened=self.cb_xanes_flat.isChecked(), ignorePostEdgeNorm=self.cb_xanes_postedge.isChecked() ) # self.im_stack = self.displayedStack diff --git a/xmidas/utils/utils.py b/xmidas/utils/utils.py index 97b8e5e..ceba360 100644 --- a/xmidas/utils/utils.py +++ b/xmidas/utils/utils.py @@ -844,10 +844,10 @@ def create_df_from_nor(athenafile="fe_refs.nor"): skip_raw_n = n_refs + 6 df = pd.read_table( - athenafile, delim_whitespace=True, skiprows=skip_raw_n, header=None, usecols=np.arange(0, n_refs) + athenafile, sep=r'\s+', skiprows=skip_raw_n, header=None, usecols=np.arange(0, n_refs) ) df2 = pd.read_table( - athenafile, delim_whitespace=True, skiprows=skip_raw_n - 1, usecols=np.arange(0, n_refs + 1) + athenafile, sep=r'\s+', skiprows=skip_raw_n - 1, usecols=np.arange(0, n_refs + 1) ) new_col = df2.columns.drop("#") df.columns = new_col @@ -870,7 +870,7 @@ def create_df_from_nor_try2(athenafile="fe_refs.nor"): def energy_from_logfile(logfile="maps_log_tiff.txt"): - df = pd.read_csv(logfile, header=None, delim_whitespace=True, skiprows=9) + df = pd.read_csv(logfile, header=None, sep=r'\s+', skiprows=9) return df[9][df[7] == "energy"].values.astype(float) From c3e9137cf63b60d2054d3b7f7e1a11783a46b805 Mon Sep 17 00:00:00 2001 From: Ajith Pattammattel Date: Tue, 10 Feb 2026 11:00:54 -0500 Subject: [PATCH 18/18] live update enhancement --- xmidas/main.py | 223 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 158 insertions(+), 65 deletions(-) diff --git a/xmidas/main.py b/xmidas/main.py index a9f68c0..f3c9353 100644 --- a/xmidas/main.py +++ b/xmidas/main.py @@ -84,6 +84,20 @@ def __init__(self, im_stack=None, energy=[], refs=[]): self.plotWidth = 2 self.stackStatusDict = {} + # Performance optimization: debounce timer and cache + self.update_timer = QTimer() + self.update_timer.setSingleShot(True) + self.update_timer.timeout.connect(self._do_update_stack) + self._pending_update = False + + # Cache for expensive operations + self._cache = { + 'resize': {}, # {scaling_factor: processed_stack} + 'outliers': {}, # {nsigma: processed_stack} + 'smooth': {}, # {window_size: processed_stack} + 'last_params': {} # Track last used parameters + } + self.user_wd = os.path.expanduser("~") # self.user_config_path = os.path.join(ui_path,"user_config.json") @@ -156,8 +170,9 @@ def __init__(self, im_stack=None, energy=[], refs=[]): # batchjobs self.actionPlotAllCorrelations.triggered.connect(self.plotCorrelationsAllCombinations) + # Use debounced updates for sliders to prevent rapid successive processing [ - uis.valueChanged.connect(self.replot_image) + uis.valueChanged.connect(self.schedule_update) for uis in [self.hs_smooth_size, self.hs_nsigma, self.hs_bg_threshold] ] @@ -304,6 +319,9 @@ def load_stack(self): The output 'self.im_stack' is the unmodified data file """ + # Invalidate cache when loading new data + self.invalidate_cache() + self.log_warning = False # for the Qmessage box in cb_log self.image_roi2_flag = False self.cb_log.setChecked(False) @@ -619,71 +637,146 @@ def reloadImageStack(self): self.isAReload = True self.load_stack() + def schedule_update(self): + """Schedule a debounced update to prevent rapid successive processing.""" + self.update_timer.stop() + self.update_timer.start(300) # 300ms delay + + def _do_update_stack(self): + """Internal method called by timer to perform the actual update.""" + self.replot_image() + + def invalidate_cache(self): + """Clear all cached results when base stack changes.""" + self._cache = { + 'resize': {}, + 'outliers': {}, + 'smooth': {}, + 'last_params': {} + } + logger.info("Cache invalidated") + def update_stack(self): - self.displayedStack = self.im_stack - self.crop_to_dim() - - if self.cb_rebin.isChecked(): - self.cb_upscale.setChecked(False) - self.sb_scaling_factor.setEnabled(True) - self.displayedStack = resize_stack(self.displayedStack, scaling_factor=self.sb_scaling_factor.value()) - self.update_stack_info() - - elif self.cb_upscale.isChecked(): - self.cb_rebin.setChecked(False) - self.sb_scaling_factor.setEnabled(True) - self.displayedStack = resize_stack( - self.displayedStack, upscaling=True, scaling_factor=self.sb_scaling_factor.value() - ) - self.update_stack_info() - - if self.cb_remove_outliers.isChecked(): - self.hs_nsigma.setEnabled(True) - nsigma = self.hs_nsigma.value() / 10 - self.displayedStack = remove_hot_pixels(self.displayedStack, NSigma=nsigma) - self.label_nsigma.setText(str(nsigma)) - logger.info(f"Removing Outliers with NSigma {nsigma}") - - elif self.cb_remove_outliers.isChecked() is False: - self.hs_nsigma.setEnabled(False) - - if self.cb_remove_edges.isChecked(): - self.displayedStack = remove_edges(self.displayedStack) - logger.info(f"Removed edges, new shape {self.displayedStack.shape}") - self.update_stack_info() - - if self.cb_remove_bg.isChecked(): - self.hs_bg_threshold.setEnabled(True) - logger.info("Removing background") - bg_threshold = self.hs_bg_threshold.value() - self.label_bg_threshold.setText(str(bg_threshold) + "%") - self.displayedStack = clean_stack(self.displayedStack, auto_bg=False, bg_percentage=bg_threshold) - - elif self.cb_remove_bg.isChecked() is False: - self.hs_bg_threshold.setEnabled(False) - - if self.cb_log.isChecked(): - - self.displayedStack = remove_nan_inf(np.log10(self.displayedStack)) - logger.info("Log Stack is in use") - - if self.cb_smooth.isChecked(): - self.hs_smooth_size.setEnabled(True) - window = self.hs_smooth_size.value() - if window % 2 == 0: - window = +1 - self.smooth_winow_size.setText("Window size: " + str(window)) - self.displayedStack = smoothen(self.displayedStack, w_size=window) - logger.info("Spectrum Smoothening Applied") - - elif self.cb_smooth.isChecked() is False: - self.hs_smooth_size.setEnabled(False) - - if self.cb_norm.isChecked(): - logger.info("Normalizing spectra") - self.displayedStack = normalize(self.displayedStack, norm_point=-1) - - logger.info("Updated image is in use") + """Update the displayed stack with all selected modifications. + + Uses caching to avoid redundant processing of expensive operations. + + OPERATION ORDER (FIXED): + The operations are applied in a specific order optimized for: + 1. Performance (reduce data size early) + 2. Correctness (irreversible operations like log/edge removal in proper sequence) + + Order: + 1. Resize/Rebin - Reduces data size for faster subsequent operations + 2. Remove Edges - Reduces data size, IRREVERSIBLE + 3. Remove Outliers - Pixel-level operation + 4. Remove Background - Threshold-based filtering + 5. Log Transform - IRREVERSIBLE, changes data scale + 6. Smoothing - Works on any scale + 7. Normalization - Final scaling step + + Note: If you need a different order, you'll need to apply operations + manually in sequence rather than using checkboxes simultaneously. + """ + # Show busy cursor during processing + QApplication.setOverrideCursor(QtCore.Qt.CursorShape.WaitCursor) + + try: + self.displayedStack = self.im_stack + self.crop_to_dim() + + # OPTIMIZATION 1: Resize/rebin first to reduce data size for subsequent operations + if self.cb_rebin.isChecked(): + self.cb_upscale.setChecked(False) + self.sb_scaling_factor.setEnabled(True) + scaling_factor = self.sb_scaling_factor.value() + + # Check cache + cache_key = f"rebin_{scaling_factor}" + if cache_key in self._cache['resize']: + self.displayedStack = self._cache['resize'][cache_key] + logger.info(f"Using cached rebin result (factor={scaling_factor})") + else: + self.displayedStack = resize_stack(self.displayedStack, scaling_factor=scaling_factor) + self._cache['resize'][cache_key] = self.displayedStack.copy() + self.update_stack_info() + + elif self.cb_upscale.isChecked(): + self.cb_rebin.setChecked(False) + self.sb_scaling_factor.setEnabled(True) + scaling_factor = self.sb_scaling_factor.value() + + # Check cache + cache_key = f"upscale_{scaling_factor}" + if cache_key in self._cache['resize']: + self.displayedStack = self._cache['resize'][cache_key] + logger.info(f"Using cached upscale result (factor={scaling_factor})") + else: + self.displayedStack = resize_stack( + self.displayedStack, upscaling=True, scaling_factor=scaling_factor + ) + self._cache['resize'][cache_key] = self.displayedStack.copy() + self.update_stack_info() + + # OPTIMIZATION 2: Remove edges early to reduce data size + if self.cb_remove_edges.isChecked(): + self.displayedStack = remove_edges(self.displayedStack) + logger.info(f"Removed edges, new shape {self.displayedStack.shape}") + self.update_stack_info() + + # Outlier removal with caching + if self.cb_remove_outliers.isChecked(): + self.hs_nsigma.setEnabled(True) + nsigma = self.hs_nsigma.value() / 10 + + # Only cache if this is the ONLY operation (no subsequent ops that would be skipped) + # Otherwise the cache would bypass operations like log transform + self.displayedStack = remove_hot_pixels(self.displayedStack, NSigma=nsigma) + + self.label_nsigma.setText(str(nsigma)) + logger.info(f"Removing Outliers with NSigma {nsigma}") + else: + self.hs_nsigma.setEnabled(False) + + # Background removal + if self.cb_remove_bg.isChecked(): + self.hs_bg_threshold.setEnabled(True) + logger.info("Removing background") + bg_threshold = self.hs_bg_threshold.value() + self.label_bg_threshold.setText(str(bg_threshold) + "%") + self.displayedStack = clean_stack(self.displayedStack, auto_bg=False, bg_percentage=bg_threshold) + else: + self.hs_bg_threshold.setEnabled(False) + + # Log transform + if self.cb_log.isChecked(): + self.displayedStack = remove_nan_inf(np.log10(self.displayedStack)) + logger.info("Log Stack is in use") + + # Smoothing (removed caching to prevent pipeline issues) + if self.cb_smooth.isChecked(): + self.hs_smooth_size.setEnabled(True) + window = self.hs_smooth_size.value() + if window % 2 == 0: + window += 1 + + self.displayedStack = smoothen(self.displayedStack, w_size=window) + + self.smooth_winow_size.setText("Window size: " + str(window)) + logger.info("Spectrum Smoothening Applied") + else: + self.hs_smooth_size.setEnabled(False) + + # Normalization (fast operation, no caching needed) + if self.cb_norm.isChecked(): + logger.info("Normalizing spectra") + self.displayedStack = normalize(self.displayedStack, norm_point=-1) + + logger.info("Updated image is in use") + + finally: + # Always restore cursor + QApplication.restoreOverrideCursor() # ImageView

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