diff --git a/.buildinfo b/.buildinfo new file mode 100644 index 00000000..7bf2ba6c --- /dev/null +++ b/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file records the configuration used when building these files. When it is not found, a full rebuild will be done. +config: 07fe860521014b94c4617b9f18eae529 +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/.codecov.yml b/.codecov.yml deleted file mode 100644 index 4af5eb24..00000000 --- a/.codecov.yml +++ /dev/null @@ -1,14 +0,0 @@ -coverage: - status: - project: # more options at https://docs.codecov.com/docs/commit-status - default: - target: auto # use the coverage from the base commit, fail if coverage is lower - threshold: 0% # allow the coverage to drop by - -comment: - layout: " diff, flags, files" - behavior: default - require_changes: false - require_base: false # [true :: must have a base report to post] - require_head: false # [true :: must have a head report to post] - hide_project_coverage: false # [true :: only show coverage on the git diff aka patch coverage] diff --git a/.codespell/ignore_lines.txt b/.codespell/ignore_lines.txt deleted file mode 100644 index 07fa7c8c..00000000 --- a/.codespell/ignore_lines.txt +++ /dev/null @@ -1,2 +0,0 @@ -;; Please include filenames and explanations for each ignored line. -;; See https://docs.openverse.org/meta/codespell.html for docs. diff --git a/.codespell/ignore_words.txt b/.codespell/ignore_words.txt deleted file mode 100644 index bf5b7379..00000000 --- a/.codespell/ignore_words.txt +++ /dev/null @@ -1,20 +0,0 @@ -;; Please include explanations for each ignored word (lowercase). -;; See https://docs.openverse.org/meta/codespell.html for docs. - -;; abbreviation for "materials" often used in a journal title -mater - -;; alternative use of socioeconomic -socio-economic - -;; Frobenius norm used in np.linalg.norm -fro - -;; abbreviation for "structure" -struc - -;; method name within JournalPanel class -onText - -;; a method name within JournalPanel class -delt diff --git a/.flake8 b/.flake8 deleted file mode 100644 index 04d2d0b0..00000000 --- a/.flake8 +++ /dev/null @@ -1,13 +0,0 @@ -# As of now, flake8 does not natively support configuration via pyproject.toml -# https://github.com/microsoft/vscode-flake8/issues/135 -[flake8] -exclude = - .git, - __pycache__, - build, - dist, - doc/source/conf.py -max-line-length = 115 -# Ignore some style 'errors' produced while formatting by 'black' -# https://black.readthedocs.io/en/stable/guides/using_black_with_other_tools.html#labels-why-pycodestyle-warnings -extend-ignore = E203 diff --git a/.github/ISSUE_TEMPLATE/bug_feature.md b/.github/ISSUE_TEMPLATE/bug_feature.md deleted file mode 100644 index b3454deb..00000000 --- a/.github/ISSUE_TEMPLATE/bug_feature.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -name: Bug Report or Feature Request -about: Report a bug or suggest a new feature! -title: "" -labels: "" -assignees: "" ---- - -### Problem - - - -### Proposed solution diff --git a/.github/ISSUE_TEMPLATE/release_checklist.md b/.github/ISSUE_TEMPLATE/release_checklist.md deleted file mode 100644 index fa94779e..00000000 --- a/.github/ISSUE_TEMPLATE/release_checklist.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -name: Release -about: Checklist and communication channel for PyPI and GitHub release -title: "Ready for PyPI/GitHub release" -labels: "release" -assignees: "" ---- - -### PyPI/GitHub rc-release preparation checklist: - -- [ ] All PRs/issues attached to the release are merged. -- [ ] All the badges on the README are passing. -- [ ] License information is verified as correct. If you are unsure, please comment below. -- [ ] Locally rendered documentation contains all appropriate pages, including API references (check no modules are - missing), tutorials, and other human-written text is up-to-date with any changes in the code. -- [ ] Installation instructions in the README, documentation, and the website (e.g., diffpy.org) are updated. -- [ ] Successfully run any tutorial examples or do functional testing with the latest Python version. -- [ ] Grammar and writing quality are checked (no typos). -- [ ] Install `pip install build twine`, run `python -m build` and `twine check dist/*` to ensure that the package can be built and is correctly formatted for PyPI release. - -Please mention @sbillinge here when you are ready for PyPI/GitHub release. Include any additional comments necessary, such as version information and details about the pre-release here: - -### PyPI/GitHub full-release preparation checklist: - -- [ ] Create a new conda environment and install the rc from PyPI (`pip install ==??`) -- [ ] License information on PyPI is correct. -- [ ] Docs are deployed successfully to `https://www.diffpy.org/`. -- [ ] Successfully run all tests, tutorial examples or do functional testing. - -Please let @sbillinge know that all checks are done and the package is ready for full release. - -### conda-forge release preparation checklist: - - - -- [ ] Ensure that the full release has appeared on PyPI successfully. -- [ ] New package dependencies listed in `conda.txt` and `test.txt` are added to `meta.yaml` in the feedstock. -- [ ] Close any open issues on the feedstock. Reach out to @bobleesj if you have questions. -- [ ] Tag @sbillinge and @bobleesj for conda-forge release. - -### Post-release checklist - - - -- [ ] Run tutorial examples and conduct functional testing using the installation guide in the README. Attach screenshots/results as comments. -- [ ] Documentation (README, tutorials, API references, and websites) is deployed without broken links or missing figures. diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md deleted file mode 100644 index 1099d862..00000000 --- a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +++ /dev/null @@ -1,15 +0,0 @@ -### What problem does this PR address? - - - -### What should the reviewer(s) do? - - - - diff --git a/.github/workflows/build-wheel-release-upload.yml b/.github/workflows/build-wheel-release-upload.yml deleted file mode 100644 index 76ad272e..00000000 --- a/.github/workflows/build-wheel-release-upload.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: Release (GitHub/PyPI) and Deploy Docs - -on: - workflow_dispatch: - push: - tags: - - "*" # Trigger on all tags initially, but tag and release privilege are verified in _build-wheel-release-upload.yml - -jobs: - release: - uses: scikit-package/release-scripts/.github/workflows/_build-wheel-release-upload.yml@v0 - with: - project: diffpy.pdfgui - c_extension: false - maintainer_GITHUB_username: sbillinge - secrets: - PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} - PAT_TOKEN: ${{ secrets.PAT_TOKEN }} diff --git a/.github/workflows/check-news-item.yml b/.github/workflows/check-news-item.yml deleted file mode 100644 index 63692232..00000000 --- a/.github/workflows/check-news-item.yml +++ /dev/null @@ -1,12 +0,0 @@ -name: Check for News - -on: - pull_request_target: - branches: - - main - -jobs: - check-news-item: - uses: scikit-package/release-scripts/.github/workflows/_check-news-item.yml@v0 - with: - project: diffpy.pdfgui diff --git a/.github/workflows/matrix-and-codecov-on-merge-to-main.yml b/.github/workflows/matrix-and-codecov-on-merge-to-main.yml deleted file mode 100644 index ac39241b..00000000 --- a/.github/workflows/matrix-and-codecov-on-merge-to-main.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: CI - -on: - push: - branches: - - main - release: - types: - - prereleased - - published - workflow_dispatch: - -jobs: - matrix-coverage: - uses: scikit-package/release-scripts/.github/workflows/_matrix-and-codecov-on-merge-to-main.yml@v0 - with: - project: diffpy.pdfgui - c_extension: false - headless: true - secrets: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/publish-docs-on-release.yml b/.github/workflows/publish-docs-on-release.yml deleted file mode 100644 index e0f24785..00000000 --- a/.github/workflows/publish-docs-on-release.yml +++ /dev/null @@ -1,14 +0,0 @@ -name: Deploy Documentation on Release - -on: - release: - types: [published] - workflow_dispatch: - -jobs: - docs: - uses: scikit-package/release-scripts/.github/workflows/_publish-docs-on-release.yml@v0 - with: - project: diffpy.pdfgui - c_extension: false - headless: true diff --git a/.github/workflows/tests-on-pr.yml b/.github/workflows/tests-on-pr.yml deleted file mode 100644 index 69180175..00000000 --- a/.github/workflows/tests-on-pr.yml +++ /dev/null @@ -1,60 +0,0 @@ -name: Tests on PR - -on: - push: - branches: - - main - pull_request: - workflow_dispatch: - -jobs: - validate: - defaults: - run: - shell: bash -l {0} - - runs-on: ubuntu-latest - steps: - - name: Check out diffpy.pdfgui - uses: actions/checkout@v4 - - - name: Initialize miniconda - uses: conda-incubator/setup-miniconda@v3 - with: - activate-environment: test - auto-update-conda: true - environment-file: environment.yml - auto-activate-base: false - python-version: 3.13 - - - name: Conda config - run: >- - conda config --set always_yes yes - --set changeps1 no - - - name: Install diffpy.pdfgui and requirements - run: | - conda install --file requirements/test.txt - conda install wxpython diffpy.utils matplotlib-base - pip install diffpy.pdffit2==1.5.0rc1 - python -m pip install . --no-deps - - - name: Start Xvfb - run: | - sudo apt-get install -y xvfb - export DISPLAY=:99 - Xvfb :99 -screen 0 1024x768x16 & - - - name: Validate diffpy.pdfgui - run: | - export DISPLAY=:99 - pytest --cov - coverage report -m - codecov - - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4 - with: - verbose: true - fail_ci_if_error: true - token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.gitignore b/.gitignore index 90d4ef7a..619d5cfd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,100 +1,6 @@ -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -env/ -build/ -_build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -venv/ -*.egg-info/ -.installed.cfg -*.egg -bin/ -temp/ -tags/ -errors.err - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt -MANIFEST - -# Unit test / coverage reports -htmlcov/ -.tox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*,cover -.hypothesis/ - -# Translations -*.mo -*.pot - -# Mr Developer -.mr.developer.cfg -.project -.pydevproject - -# Django stuff: -*.log - -# Sphinx documentation -docs/build/ -docs/source/generated/ - -# pytest -.pytest_cache/ - -# PyBuilder -target/ - -# Editor files -# mac -.DS_Store -*~ - -# vim -*.swp -*.swo - -# pycharm -.idea/ - -# VSCode -.vscode/ - -# Ipython Notebook -.ipynb_checkpoints - -# version information -setup.cfg -/src/diffpy/*/version.cfg - -# Rever -rever/ +pdfgui.aux +pdfgui.cp +pdfgui.cps +pdfgui.toc +pdfgui.vr +pdfgui.vrs diff --git a/.isort.cfg b/.isort.cfg deleted file mode 100644 index e0926f42..00000000 --- a/.isort.cfg +++ /dev/null @@ -1,4 +0,0 @@ -[settings] -line_length = 115 -multi_line_output = 3 -include_trailing_comma = True diff --git a/doc/source/_static/.placeholder b/.nojekyll similarity index 100% rename from doc/source/_static/.placeholder rename to .nojekyll diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml deleted file mode 100644 index 0e4a84d1..00000000 --- a/.pre-commit-config.yaml +++ /dev/null @@ -1,66 +0,0 @@ -default_language_version: - python: python3 -ci: - autofix_commit_msg: | - [pre-commit.ci] auto fixes from pre-commit hooks - autofix_prs: true - autoupdate_branch: "pre-commit-autoupdate" - autoupdate_commit_msg: "[pre-commit.ci] pre-commit autoupdate" - autoupdate_schedule: monthly - skip: [no-commit-to-branch] - submodules: false -repos: - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.6.0 - hooks: - - id: check-yaml - - id: end-of-file-fixer - - id: trailing-whitespace - - id: check-case-conflict - - id: check-merge-conflict - - id: check-toml - - id: check-added-large-files - - repo: https://github.com/psf/black - rev: 24.4.2 - hooks: - - id: black - - repo: https://github.com/pycqa/flake8 - rev: 7.0.0 - hooks: - - id: flake8 - - repo: https://github.com/pycqa/isort - rev: 5.13.2 - hooks: - - id: isort - args: ["--profile", "black"] - - repo: https://github.com/kynan/nbstripout - rev: 0.7.1 - hooks: - - id: nbstripout - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 - hooks: - - id: no-commit-to-branch - name: Prevent Commit to Main Branch - args: ["--branch", "main"] - stages: [pre-commit] - - repo: https://github.com/codespell-project/codespell - rev: v2.3.0 - hooks: - - id: codespell - additional_dependencies: - - tomli - # prettier - multi formatter for .json, .yml, and .md files - - repo: https://github.com/pre-commit/mirrors-prettier - rev: f12edd9c7be1c20cfa42420fd0e6df71e42b51ea # frozen: v4.0.0-alpha.8 - hooks: - - id: prettier - additional_dependencies: - - "prettier@^3.2.4" - # docformatter - PEP 257 compliant docstring formatter - - repo: https://github.com/s-weigand/docformatter - rev: 5757c5190d95e5449f102ace83df92e7d3b06c6c - hooks: - - id: docformatter - additional_dependencies: [tomli] - args: [--in-place, --config, ./pyproject.toml] diff --git a/.readthedocs.yaml b/.readthedocs.yaml deleted file mode 100644 index 47f7a017..00000000 --- a/.readthedocs.yaml +++ /dev/null @@ -1,13 +0,0 @@ -version: 2 - -build: - os: "ubuntu-22.04" - tools: - python: "latest" - -python: - install: - - requirements: requirements/docs.txt - -sphinx: - configuration: doc/source/conf.py diff --git a/AUTHORS.rst b/AUTHORS.rst deleted file mode 100644 index 8d20fa4f..00000000 --- a/AUTHORS.rst +++ /dev/null @@ -1,62 +0,0 @@ -Authors -======= - -DiffPy was initiated as part of the Distributed Data Analysis of Neutron -Scattering Experiments (DANSE) project, funded by the National Science -Foundation under grant DMR-0520547. More information on DANSE can be -found at `DANSE Project Legacy Page `_. -Any opinions, findings, and conclusions or recommendations expressed -in this material are those of the author(s) and do not necessarily reflect -the views of the NSF. - -Main Contributors ------------------ - -This code was developed as part of the DiffPy project to create python -modules for structure investigations from diffraction data. The main -contributors to this package were - - Chris Farrow, - Jiwu Liu, - Pavol Juhas, - Dmitriy Bryndin - -Other current and former contributors of the DiffPy project include - - Simon Billinge, - Chris Farrow, - Emil Bozin, - Wenduo Zhou, - Peng Tian - -The DiffPy team is part of the Billinge Group at Columbia University in New York, -within the Department of Applied Physics and Applied Mathematics. - -Contributors ------------- -Please see the header of each source file for a detailed list of -contributors. This is an open-source project and we hope and expect -that the list of contributors will expand with time. Many thanks to -all current and future contributors! - -For more information on the DiffPy project email sb2896@columbia.edu - -For a list of contributors, visit -https://github.com/diffpy/diffpy.pdfgui/graphs/contributors - -Acknowledgments ---------------- - -We are truly grateful to all the people who have contributed, in all -different ways, to this project: Thomas Proffen, Xiangyun Qiu, Pete -Peterson and Jacques Bloch, previous Billinge-group members whose -contributions to the codes are living well beyond their affiliation with -the group; The hard working DANSE group at Caltech, University of -Maryland, Iowa State and University of Tennessee, especially Brent Fultz -for doggedly putting DANSE all together and Michael Aivazis, and the -indomitable Mike McKerns for their design input and MM's gargantuan -excel spreadsheets; The former members of the Billinge-group members, -especially HyunJeong Kim and Ahmad Masadeh for enthusiastic testing and -feature requests; Last but not least, our long suffering family members, -and the whole coffee and tea industries at large, without whom none of -this would have been possible. diff --git a/CHANGELOG.rst b/CHANGELOG.rst deleted file mode 100644 index b0f0c142..00000000 --- a/CHANGELOG.rst +++ /dev/null @@ -1,77 +0,0 @@ -============= -Release notes -============= - -.. current developments - -3.1.0 -===== - -**Added:** - -* numpy >= 2.0 support -* Codecov coverage report in PRs -* Spelling check with Codespell in pre-commit -* Added Whittaker-Shannon interpolation option for grid_interpolation. -* Added support for python 3.13 -* no-news needed: just tweaking installation instructions - -**Changed:** - -* Package reformatted to comply with new Billinge Group package structure -* Changed the removed local manual link to the online page. -* Use WS interpolation for Nyquist grid. -* Refreshed tutorial manual and brought documentation up to date -* Plots now use colors from the billinge-group matplotlib stylesheet, bg-mpl-stylesheets -* Updated install instructions in README.rst. - -**Fixed:** - -* Change background color to match system settings in `Phase Configuration`. -* inability to find gui resources bug in py < 3.12 -* fixed date rendering in 'about' dialog box -* fix "absent from setuptools' packages configuration" warnings during python -m build -* use conda.txt instead of run.txt for conda package dependencies -* remove conda-recipe folder - feedstock repo has the latest version -* two warnings with (1) linestyle redundantly defined and (2) no artists with labels found to put in legend -* Use miniforge in CI to avoid strange error of incorrect MacOS version logged from base env -* Re-cookiecut to include GH issues templates, getting started, and install updates -* Fixed TypeError when using Nyquist interp. -* Fixed online manual not showing images. -* Code linted up to PEP8 and group standards - -**Removed:** - -* Removed wx3 support that was previously deprecated. -* Remove diffpy.structure and numpy in macOS Arm64 readme installation since they are installed by other conda-forge dependencies. -* six dependency in run.txt - - -v3.0.5 -==================== - - - - -Version 2.0.3 – 2023-05-18 -========================== -**Added** - -* Support for Python 3.8, 3.9. -* Use `.ddp3` instead of `.ddp` to store project files. - -**Changed** - -* Update wxpython to 4.1.1 and remove incompatible align flags. -* Update configparser use strict as False. -* Update tutorial project files for py3. - -**Deprecated** - -**Removed** - -**Fixed** - -- Incompatible conversion between bytes and str from py2 to py3. -- The `listCtrlFiles.InsertItem` error in windows. -- Make the string parser in doping series working. diff --git a/CODE_OF_CONDUCT.rst b/CODE_OF_CONDUCT.rst deleted file mode 100644 index e8199ca5..00000000 --- a/CODE_OF_CONDUCT.rst +++ /dev/null @@ -1,133 +0,0 @@ -===================================== - Contributor Covenant Code of Conduct -===================================== - -Our Pledge ----------- - -We as members, contributors, and leaders pledge to make participation in our -community a harassment-free experience for everyone, regardless of age, body -size, visible or invisible disability, ethnicity, sex characteristics, gender -identity and expression, level of experience, education, socioeconomic status, -nationality, personal appearance, race, caste, color, religion, or sexual -identity and orientation. - -We pledge to act and interact in ways that contribute to an open, welcoming, -diverse, inclusive, and healthy community. - -Our Standards -------------- - -Examples of behavior that contributes to a positive environment for our -community include: - -* Demonstrating empathy and kindness toward other people -* Being respectful of differing opinions, viewpoints, and experiences -* Giving and gracefully accepting constructive feedback -* Accepting responsibility and apologizing to those affected by our mistakes, - and learning from the experience -* Focusing on what is best not just for us as individuals, but for the overall - community - -Examples of unacceptable behavior include: - -* The use of sexualized language or imagery, and sexual attention or advances of - any kind -* Trolling, insulting or derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or email address, - without their explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting - -Enforcement Responsibilities ----------------------------- - -Community leaders are responsible for clarifying and enforcing our standards of -acceptable behavior and will take appropriate and fair corrective action in -response to any behavior that they deem inappropriate, threatening, offensive, -or harmful. - -Community leaders have the right and responsibility to remove, edit, or reject -comments, commits, code, wiki edits, issues, and other contributions that are -not aligned to this Code of Conduct, and will communicate reasons for moderation -decisions when appropriate. - -Scope ------ - -This Code of Conduct applies within all community spaces, and also applies when -an individual is officially representing the community in public spaces. -Examples of representing our community include using an official email address, -posting via an official social media account, or acting as an appointed -representative at an online or offline event. - -Enforcement ------------ - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported to the community leaders responsible for enforcement at -sb2896@columbia.edu. All complaints will be reviewed and investigated promptly and fairly. - -All community leaders are obligated to respect the privacy and security of the -reporter of any incident. - -Enforcement Guidelines ----------------------- - -Community leaders will follow these Community Impact Guidelines in determining -the consequences for any action they deem in violation of this Code of Conduct: - -1. Correction -**************** - -**Community Impact**: Use of inappropriate language or other behavior deemed -unprofessional or unwelcome in the community. - -**Consequence**: A private, written warning from community leaders, providing -clarity around the nature of the violation and an explanation of why the -behavior was inappropriate. A public apology may be requested. - -2. Warning -************* - -**Community Impact**: A violation through a single incident or series of -actions. - -**Consequence**: A warning with consequences for continued behavior. No -interaction with the people involved, including unsolicited interaction with -those enforcing the Code of Conduct, for a specified period of time. This -includes avoiding interactions in community spaces as well as external channels -like social media. Violating these terms may lead to a temporary or permanent -ban. - -3. Temporary Ban -****************** - -**Community Impact**: A serious violation of community standards, including -sustained inappropriate behavior. - -**Consequence**: A temporary ban from any sort of interaction or public -communication with the community for a specified period of time. No public or -private interaction with the people involved, including unsolicited interaction -with those enforcing the Code of Conduct, is allowed during this period. -Violating these terms may lead to a permanent ban. - -4. Permanent Ban -****************** - -**Community Impact**: Demonstrating a pattern of violation of community -standards, including sustained inappropriate behavior, harassment of an -individual, or aggression toward or disparagement of classes of individuals. - -**Consequence**: A permanent ban from any sort of public interaction within the -community. - -Attribution ------------ - -This Code of Conduct is adapted from the `Contributor Covenant `_. - -Community Impact Guidelines were inspired by `Mozilla's code of conduct enforcement ladder `_. - -For answers to common questions about this code of conduct, see the `FAQ `_. `Translations are available `_ diff --git a/doc/source/Farrow-jpcm-2007.pdf b/Farrow-jpcm-2007.pdf similarity index 100% rename from doc/source/Farrow-jpcm-2007.pdf rename to Farrow-jpcm-2007.pdf diff --git a/LICENSE.rst b/LICENSE.rst deleted file mode 100644 index 51d7148a..00000000 --- a/LICENSE.rst +++ /dev/null @@ -1,80 +0,0 @@ -.. code-block:: text - - This software was originally developed by the Billinge group as part - of the Distributed Data Analysis of Neutron Scattering Experiments - (DANSE) project funded by the US National Science Foundation under - grant DMR-0520547. Developments of PDFfit2 were funded by NSF grant - DMR-0304391 in the Billinge group, and with support from Michigan State - University and Columbia University. Any opinions, findings, and conclusions - or recommendations expressed in this material are those of the author(s) - and do not necessarily reflect the views of the respective funding bodies. - Subsequent development was done in the Billinge group at Columbia University - and then in collaboration between the Billinge group at Columbia and Pavol - Juhas at Brookhaven National Laboratory. Moving forward, PDFgui will be - maintained as a community project with contributions welcomed from many people. - - If you use this program to do productive scientific research that leads - to publication, we ask that you acknowledge use of the program by citing - the following paper in your publication: - - C. L. Farrow, P. Juhas, J. W. Liu, D. Bryndin, E. S. Bozin, - J. Bloch, Th. Proffen and S. J. L. Billinge, PDFfit2 and - PDFgui: computer programs for studying nanostructure in - crystals, J. Phys.: Condens. Matter 19, 335219 (2007) - - Up to the release 1.1.2 (February 2017) the copyright was held by - the institutions that hosted the work as follows: - Copyright 2006-2007, Board of Trustees of Michigan State University, - Copyright 2008-2012, Board of Trustees of Columbia University in the - city of New York. - Copyright 2013, Brookhaven National Laboratory (Copyright holder - indicated in each source file). - - As of February 2017, and the 1.1.2 release, PDFgui has moved to a shared copyright model. - - PDFgui uses a shared copyright model. Each contributor maintains copyright over their - contributions to PDFgui. But, it is important to note that these contributions are - typically only changes to the repositories. Thus, the PDFgui source code, in its entirety, - is not the copyright of any single person or institution. Instead, it is the collective - copyright of the entire PDFgui Development Team. If individual contributors want to - maintain a record of what changes/contributions they have specific copyright on, they - should indicate their copyright in the commit message of the change, when they commit - the change to one of the PDFgui repositories. - - The PDFgui Development Team is the set of all contributors to the PDFgui project. - A full list can be obtained from the git version control logs. - - For more information please visit the project web-page: - https://www.diffpy.org - or email Prof. Simon Billinge at sb2896@columbia.edu - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * 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. - - * 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 COPYRIGHT HOLDER "AS IS". COPYRIGHT HOLDER - EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES AND CONDITIONS, EITHER - EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY, TITLE, FITNESS, ADEQUACY OR SUITABILITY - FOR A PARTICULAR PURPOSE, AND ANY WARRANTIES OF FREEDOM FROM - INFRINGEMENT OF ANY DOMESTIC OR FOREIGN PATENT, COPYRIGHTS, TRADE - SECRETS OR OTHER PROPRIETARY RIGHTS OF ANY PARTY. IN NO EVENT SHALL - COPYRIGHT HOLDER BE LIABLE TO ANY PARTY 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 OR RELATING TO THIS AGREEMENT, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index f1a78eec..00000000 --- a/MANIFEST.in +++ /dev/null @@ -1,12 +0,0 @@ -graft src -graft tests -graft requirements - -include AUTHORS.rst LICENSE*.rst README.rst - -# Exclude all bytecode files and __pycache__ directories -global-exclude *.py[cod] # Exclude all .pyc, .pyo, and .pyd files. -global-exclude .DS_Store # Exclude Mac filesystem artifacts. -global-exclude __pycache__ # Exclude Python cache directories. -global-exclude .git* # Exclude git files and directories. -global-exclude .idea # Exclude PyCharm project settings. diff --git a/doc/source/Proffen-jac-1999.pdf b/Proffen-jac-1999.pdf similarity index 100% rename from doc/source/Proffen-jac-1999.pdf rename to Proffen-jac-1999.pdf diff --git a/README.rst b/README.rst deleted file mode 100644 index dac60867..00000000 --- a/README.rst +++ /dev/null @@ -1,175 +0,0 @@ -|Icon| |title|_ -=============== - -.. |title| replace:: diffpy.pdfgui -.. _title: https://diffpy.github.io/diffpy.pdfgui - -.. |Icon| image:: https://avatars.githubusercontent.com/diffpy - :target: https://diffpy.github.io/diffpy.pdfgui - :height: 100px - -|PyPI| |Forge| |PythonVersion| |PR| - -|CI| |Codecov| |Black| |Tracking| - -.. |Black| image:: https://img.shields.io/badge/code_style-black-black - :target: https://github.com/psf/black - -.. |CI| image:: https://github.com/diffpy/diffpy.pdfgui/actions/workflows/matrix-and-codecov-on-merge-to-main.yml/badge.svg - :target: https://github.com/diffpy/diffpy.pdfgui/actions/workflows/matrix-and-codecov-on-merge-to-main.yml - -.. |Codecov| image:: https://codecov.io/gh/diffpy/diffpy.pdfgui/branch/main/graph/badge.svg - :target: https://codecov.io/gh/diffpy/diffpy.pdfgui - -.. |Forge| image:: https://img.shields.io/conda/vn/conda-forge/diffpy.pdfgui - :target: https://anaconda.org/conda-forge/diffpy.pdfgui - -.. |PR| image:: https://img.shields.io/badge/PR-Welcome-29ab47ff - -.. |PyPI| image:: https://img.shields.io/pypi/v/diffpy.pdfgui - :target: https://pypi.org/project/diffpy.pdfgui/ - -.. |PythonVersion| image:: https://img.shields.io/pypi/pyversions/diffpy.pdfgui - :target: https://pypi.org/project/diffpy.pdfgui/ - -.. |Tracking| image:: https://img.shields.io/badge/issue_tracking-github-blue - :target: https://github.com/diffpy/diffpy.pdfgui/issues - -Graphical user interface program for structure refinements to the atomic -pair distribution function. - -For users who do not have the expertise or necessity for command -line analysis, PDFgui is a convenient and easy to use graphical front -end for the PDFfit2 refinement program. It is capable of full-profile -fitting of the atomic pair distribution function (PDF) derived from x-ray -or neutron diffraction data and comes with built in graphical and structure -visualization capabilities. - -PDFgui is a friendly interface to the PDFfit2 refinement engine, with many -powerful extensions. To get started, please open the manual from the -help menu and follow the tutorial instructions. A detailed description -is available in `this paper `_. - -For more information about diffpy.pdfgui, please consult our -`online documentation `_. - -Citation --------- - -If you use diffpy.pdfgui in a scientific publication, we would like you to -cite this package as - - C L Farrow, P Juhas, J W Liu, D Bryndin, E S Božin, - J Bloch, Th Proffen and S J L Billinge, PDFfit2 and PDFgui: - computer programs for studying nanostructure in crystals, J. Phys.: - Condens. Matter 19 (2007) 335219. doi:10.1088/0953-8984/19/33/335219 - -Installation ------------- - -Windows, macOS (non-Arm64), Linux -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The preferred method is to use `Miniconda Python -`_ -and install from the "conda-forge" channel of Conda packages. - -Add the "conda-forge" channel by running the following command in a terminal: :: - - conda config --add channels conda-forge - -Create a new environment named ``diffpy.pdfgui_env`` and install ``diffpy.pdfgui``: :: - - conda create -n diffpy.pdfgui_env diffpy.pdfgui - -Activate the environment: :: - - conda activate diffpy.pdfgui_env - -Confirm that the installation was successful: :: - - python -c "import diffpy.pdfgui; print(diffpy.pdfgui.__version__)" - -macOS (Arm64) -~~~~~~~~~~~~~ - -Create a new conda environment ``diffpy.pdfgui_env``: :: - - conda config --add channels conda-forge - conda create -n diffpy.pdfgui_env python=3.13 - -Activate the environment: :: - - conda activate diffpy.pdfgui_env - -It is necessary to get versions of pdffit2 built for Mac from Python package index (Pypi). To install -pdffit2 from Pypi using ``pip`` to download and install the latest version from `Python Package Index `_: :: - - conda install wxpython diffpy.utils matplotlib-base pycifrw - pip install diffpy.pdffit2 - -Now we want to install PDFgui from conda-forge: :: - - conda install diffpy.pdfgui --no-deps - - -Build from source -~~~~~~~~~~~~~~~~~ - -For advanced users, obtain the source archive, and in the ``diffpy.pdffit2`` directory, run :: - - conda create -n diffpy.pdffit2_env python=3.13 \ - --file requirements/test.txt \ - --file requirements/conda.txt \ - --file requirements/build.txt - -Activate the environment, build the package, and run unit tests by following commands sequentially: :: - - conda activate diffpy.pdffit2_env - pip install . --no-deps - pytest - -Getting Started ---------------- - -You may consult our `online documentation `_ for tutorials and API references. - -Support and Contribute ----------------------- - -`Diffpy user group `_ is the discussion forum for general questions and discussions about the use of diffpy.pdfgui. Please join the diffpy.pdfgui users community by joining the Google group. The diffpy.pdfgui project welcomes your expertise and enthusiasm! - -If you see a bug or want to request a feature, please `report it as an issue `_ and/or `submit a fix as a PR `_. You can also post it to the `Diffpy user group `_. - -Feel free to fork the project and contribute. To install diffpy.pdfgui -in a development mode, with its sources being directly used by Python -rather than copied to a package directory, use the following in the root -directory :: - - pip install -e . - -To ensure code quality and to prevent accidental commits into the default branch, please set up the use of our pre-commit -hooks. - -1. Install pre-commit in your working environment by running ``conda install pre-commit``. - -2. Initialize pre-commit (one time only) ``pre-commit install``. - -Thereafter your code will be linted by black and isort and checked against flake8 before you can commit. -If it fails by black or isort, just rerun and it should pass (black and isort will modify the files so should -pass after they are modified). If the flake8 test fails please see the error messages and fix them manually before -trying to commit again. - -Improvements and fixes are always appreciated. - -Before contributing, please read our `Code of Conduct `_. - -Contact -------- - -For more information on diffpy.pdfgui please visit the project `web-page `_ or email Simon Billinge at sb2896@columbia.edu. - -Acknowledgements ----------------- - -``diffpy.pdfgui`` is built and maintained with `scikit-package `_. diff --git a/doc/source/manual_resources/Ni data.zip b/_downloads/032062351bf34c8fe361e08dc302b237/Ni data.zip similarity index 100% rename from doc/source/manual_resources/Ni data.zip rename to _downloads/032062351bf34c8fe361e08dc302b237/Ni data.zip diff --git a/doc/source/manual_resources/Doping data series.zip b/_downloads/0ef3e2edfca13d573862b655df0a2b60/Doping data series.zip similarity index 100% rename from doc/source/manual_resources/Doping data series.zip rename to _downloads/0ef3e2edfca13d573862b655df0a2b60/Doping data series.zip diff --git a/doc/source/manual_resources/tui_mno_bond_lengths.py b/_downloads/2c50488e54890de4446320c8083064d0/tui_mno_bond_lengths.py old mode 100755 new mode 100644 similarity index 99% rename from doc/source/manual_resources/tui_mno_bond_lengths.py rename to _downloads/2c50488e54890de4446320c8083064d0/tui_mno_bond_lengths.py index a1d1f679..febd0b51 --- a/doc/source/manual_resources/tui_mno_bond_lengths.py +++ b/_downloads/2c50488e54890de4446320c8083064d0/tui_mno_bond_lengths.py @@ -1,7 +1,6 @@ #!/usr/bin/env python -"""Extract the shortest Mn-O bond lengths from all fits in PDFgui -project. +"""Extract the shortest Mn-O bond lengths from all fits in PDFgui project. This script loops through all refined phases in PDFgui project and calculates their shortest Mn-O bond lengths using diffpy.pdffit2 diff --git a/doc/source/manual_resources/Nanoparticle structure.zip b/_downloads/74679939e242a632e3c46d39852bd6c9/Nanoparticle structure.zip similarity index 100% rename from doc/source/manual_resources/Nanoparticle structure.zip rename to _downloads/74679939e242a632e3c46d39852bd6c9/Nanoparticle structure.zip diff --git a/doc/source/pdfgui.pdf b/_downloads/76e8006107ff24750316fcdaf694095d/pdfgui.pdf similarity index 100% rename from doc/source/pdfgui.pdf rename to _downloads/76e8006107ff24750316fcdaf694095d/pdfgui.pdf diff --git a/_downloads/7f278b2b470f8adf60991438dc3db388/Farrow-jpcm-2007.pdf b/_downloads/7f278b2b470f8adf60991438dc3db388/Farrow-jpcm-2007.pdf new file mode 100644 index 00000000..07493cc0 Binary files /dev/null and b/_downloads/7f278b2b470f8adf60991438dc3db388/Farrow-jpcm-2007.pdf differ diff --git a/_downloads/86e7a143ba2ff8e0416b42c2c6919e14/Proffen-jac-1999.pdf b/_downloads/86e7a143ba2ff8e0416b42c2c6919e14/Proffen-jac-1999.pdf new file mode 100644 index 00000000..0dcee711 Binary files /dev/null and b/_downloads/86e7a143ba2ff8e0416b42c2c6919e14/Proffen-jac-1999.pdf differ diff --git a/doc/source/manual_resources/Temperature data series.zip b/_downloads/96f93e59ce2c84278c696ef7f0b09a4e/Temperature data series.zip similarity index 100% rename from doc/source/manual_resources/Temperature data series.zip rename to _downloads/96f93e59ce2c84278c696ef7f0b09a4e/Temperature data series.zip diff --git a/_modules/diffpy/pdfgui/applications/pdfgui.html b/_modules/diffpy/pdfgui/applications/pdfgui.html new file mode 100644 index 00000000..6122ab9d --- /dev/null +++ b/_modules/diffpy/pdfgui/applications/pdfgui.html @@ -0,0 +1,252 @@ + + + + + + + + diffpy.pdfgui.applications.pdfgui — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.applications.pdfgui

+#!/usr/bin/env python
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Pavol Juhas
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+"""
+PDFgui Graphical User Interface for Pair Distribution Function fitting
+Usage: pdfgui [project.dpp]
+
+PDFgui is graphical user interface to PDFfit2 - a Python library for PDF
+simulation and structure refinement.  PDFgui has many nice features such
+as control of multiple fits, integrated plotting, easy setup of sequential
+refinements, and saving of entire project in a single file.
+
+Options:
+  -h, --help      display this message
+  -V, --version   show program version
+
+Debugging options:
+  --db-noed       disable exceptions catching to ErrorReportDialog
+  --db-nocf       exit without asking to save modified project
+  --db-pdb        use Python debugger to handle error exceptions
+"""
+
+from __future__ import print_function
+
+import getopt
+import os
+import sys
+
+
+
+[docs] +def usage(): + """Show usage info.""" + myname = os.path.basename(sys.argv[0]) + msg = __doc__.replace("pdfgui", myname) + print(msg) + return
+ + + +
+[docs] +def version(): + from diffpy.pdfgui import __version__ + + print("PDFgui", __version__) + return
+ + + +
+[docs] +def processArguments(argv1): + """Process command line arguments and store results in pdfguiglobals. This + method updates cmdopts, cmdargs and dbopts attributes in the pdfguiglobals + module. + + argv1 -- list of command line arguments excluding the executable + + Returns boolean flag to indicate if the execution should continue. + The flag is False, when options contain --help or --version. + Raises GetoptError for invalid options. + Raises ValueError for more than one project file arguments or + when project is not a valid file. + """ + from diffpy.pdfgui.gui import pdfguiglobals + + dbopts = pdfguiglobals.dbopts + dboptions = [("db-" + o[0]) for o in dbopts.alldebugoptions] + # default parameters + opts, args = getopt.gnu_getopt(sys.argv[1:], "hV", ["help", "version"] + dboptions) + # process options + proceed = True + for o, a in opts: + if o in ("-h", "--help"): + usage() + proceed = False + elif o in ("-V", "--version"): + version() + proceed = False + elif o.startswith("--") and o[2:] in dboptions: + # strip "--db-" + dbo = o[5:] + setattr(dbopts, dbo, True) + pdfguiglobals.cmdopts = opts + # bail-out here if options contain --help or --version + if not proceed: + return False + # otherwise continue checking arguments + if len(args) == 1 and not os.path.isfile(args[0]): + emsg = "Project file %s does not exist." % args[0] + raise ValueError(emsg) + elif len(args) > 1: + emsg = "Too many project files." + raise ValueError(emsg) + # ready to go + pdfguiglobals.cmdargs = args + return proceed
+ + + +
+[docs] +def main(): + """Main entry point to PDFgui.""" + # process arguments + proceed = False + try: + proceed = processArguments(sys.argv[1:]) + except (getopt.GetoptError, ValueError) as err: + print(err, file=sys.stderr) + sys.exit(1) + # bail out when no gui is needed + if not proceed: + sys.exit() + # initialize gui + import diffpy.pdfgui.gui.main as guimain + + # Catch control errors, that may happen during project + # loading, before the GUI gets running + from diffpy.pdfgui.control.controlerrors import ControlError + + try: + guimain.main() + except ControlError as err: + print(err, file=sys.stderr) + sys.exit(1) + return
+ + + +if __name__ == "__main__": + main() + +# End of file +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/control/calculation.html b/_modules/diffpy/pdfgui/control/calculation.html new file mode 100644 index 00000000..0422c21c --- /dev/null +++ b/_modules/diffpy/pdfgui/control/calculation.html @@ -0,0 +1,523 @@ + + + + + + + + diffpy.pdfgui.control.calculation — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.control.calculation

+#!/usr/bin/env python
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Pavol Juhas, Jiwu Liu
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+"""Class Calculation for performing PDF simulation from model structure."""
+
+import copy
+import math
+import pickle
+
+from diffpy.pdfgui.control.controlerrors import ControlConfigError, ControlKeyError, ControlValueError
+from diffpy.pdfgui.control.pdfcomponent import PDFComponent
+from diffpy.pdfgui.utils import safeCPickleDumps
+
+
+
+[docs] +class Calculation(PDFComponent): + """Perform a theoretical computation of PDF from model structure. + + Data members: + + rmin -- read-only lower boundary of rcalc, change with setRGrid() + rstep -- read-only r-grid step, use setRGrid() to change it + rmax -- read-only upper boundary of rcalc, change with setRGrid() + rlen -- read-only number of r points, set by setRGrid(). + To be used in PdfFit.alloc() + rcalc -- list of r values, this is set after calculation is finished + Gcalc -- list of calculated G values + stype -- scattering type, 'X' or 'N' + qmax -- maximum value of Q in inverse Angstroms. Termination ripples + are ignored for qmax=0. + qdamp -- specifies width of Gaussian damping factor in pdf_obs due + to imperfect Q resolution + qbroad -- quadratic peak broadening factor related to dataset + spdiameter -- particle diameter for shape damping function. + Note: this attribute has been moved to FitStructure and is + maintained only for backward compatible reading of PDFgui + project files. + dscale -- total scale factor + """ + + def __init__(self, name): + """Initialize Calculation. + + name -- calculation name + """ + PDFComponent.__init__(self, name) + + # rmin, rstep, rmax, rlen, rcalc + self.setRGrid(rmin=0.1, rstep=0.01, rmax=10.0) + self.rcalc = [] + self.Gcalc = [] + self.stype = "X" + # user must specify qmax to get termination ripples + self.qmax = 0.0 + self.qdamp = 0.001 + self.qbroad = 0.0 + self.spdiameter = None + self.dscale = 1.0 + return + + def _getStrId(self): + """Make a string identifier. + + return value: string id + """ + return "c_" + self.name + +
+[docs] + def setRGrid(self, rmin=None, rstep=None, rmax=None): + """Change specified r-grid parameters (rmin, rstep, rmax). Adjust rmax + for integer number of steps. + + rmin -- new low rcalc boundary + rstep -- new r-grid step + rmax -- new maximum rcalc, slightly adjusted to accommodate rstep + + No return value. + Raise ControlValueError for invalid range specification. + """ + if rmin is None: + rmin = self.rmin + if rstep is None: + rstep = self.rstep + if rmax is None: + rmax = self.rmax + rstep = float(rstep) + # check if arguments are valid + if not rmin > 0: + emsg = "Low range boundary must be positive." + raise ControlValueError(emsg) + if not rmin < rmax: + emsg = "Invalid range boundaries." + raise ControlValueError(emsg) + if rstep <= 0.0: + emsg = "Invalid value of rstep, rstep must be positive." + raise ControlValueError(emsg) + # find number of r bins + nbins = int(math.ceil((rmax - rmin) / rstep)) + # check for overshot due to round-off + epsilonr = 1.0e-8 * rstep + deltarmax = abs(rmin + (nbins - 1) * rstep - rmax) + if nbins > 1 and deltarmax < epsilonr: + nbins -= 1 + # All went well, let us go ahead and set the attributes. + self.rmin = rmin + self.rstep = rstep + self.rmax = rmin + nbins * rstep + self.rlen = nbins + 1 + return
+ + +
+[docs] + def start(self): + """Entry function for calculation.""" + from diffpy.pdfgui.control.fitting import getEngineExceptions, handleEngineException + + try: + self.calculate() + except getEngineExceptions() as error: + gui = self.owner.controlCenter.gui + handleEngineException(error, gui) + + # inform gui of change ( when engine calculation fails, it will update gui as well ) + gui = self.owner.controlCenter.gui + if gui: + gui.postEvent(gui.OUTPUT, None) + gui.postEvent(gui.PLOTNOW, self) + return
+ + +
+[docs] + def calculate(self): + """Do the real calculation.""" + # clean up old results + self.rcalc = [] + self.Gcalc = [] + + # do the job + if len(self.owner.strucs) == 0: + raise ControlConfigError("No structure is given for calculation") + + # make sure parameters are initialized + self.owner.updateParameters() + from diffpy.pdffit2 import PdfFit + + server = PdfFit() + + # structure needs to be read before dataset allocation + for struc in self.owner.strucs: + server.read_struct_string(struc.writeStr("pdffit")) + for key, var in struc.constraints.items(): + server.constrain(key, var.formula) + + # set up dataset + server.alloc(self.stype, self.qmax, self.qdamp, self.rmin, self.rmax, self.rlen) + server.setvar("qbroad", self.qbroad) + server.setvar("dscale", self.dscale) + + # phase related variables + # pair selection applies to current dataset, + # therefore it has to be done after alloc + for phaseidx0, struc in enumerate(self.owner.strucs): + phaseidx1 = phaseidx0 + 1 + server.setphase(phaseidx1) + server.setvar("pscale", struc.getvar("pscale")) + server.setvar("spdiameter", struc.getvar("spdiameter")) + struc.applyPairSelection(server, phaseidx1) + + # set up parameters + for index, par in self.owner.parameters.items(): + server.setpar(index, par.initialValue()) # info[0] = init value + # fix if fixed. Note: all parameters are free after server.reset(). + if par.fixed: + server.fixpar(index) + + # all ready here + server.calc() + + # get results + self.rcalc = server.getR() + self.Gcalc = server.getpdf_fit()
+ + +
+[docs] + def write(self, filename): + """Write this calculated PDF to a file. + + filename -- name of file to write to + + No return value. + """ + txt = self.writeStr() + f = open(filename, "w") + f.write(txt) + f.close() + return
+ + +
+[docs] + def writeStr(self): + """String representation of calculated PDF. + + Returns data string + """ + import time + from getpass import getuser + + lines = [] + # write metadata + lines.extend( + [ + "History written: " + time.ctime(), + "produced by " + getuser(), + "##### PDFgui calculation", + ] + ) + # stype + if self.stype == "X": + lines.append("stype=X x-ray scattering") + elif self.stype == "N": + lines.append("stype=N neutron scattering") + # dscale + if self.dscale: + lines.append("dscale=%g" % self.dscale) + # qmax + if self.qmax == 0: + qmax_line = "qmax=0 correction not applied" + else: + qmax_line = "qmax=%.2f" % self.qmax + lines.append(qmax_line) + # qdamp + if isinstance(self.qdamp, float): + lines.append("qdamp=%g" % self.qdamp) + # qbroad + if self.qbroad: + lines.append("qbroad=%g" % self.qbroad) + # write data: + lines.append("##### start data") + lines.append("#L r(A) G(r)") + for i in range(len(self.rcalc)): + lines.append("%g %g" % (self.rcalc[i], self.Gcalc[i])) + # lines are ready here + datastring = "\n".join(lines) + "\n" + return datastring
+ + +
+[docs] + def load(self, z, subpath): + """Load data from a zipped project file. + + z -- zipped project file + subpath -- path to its own storage within project file + + returns a tree of internal hierarchy + """ + config = pickle.loads(z.read(subpath + "config"), encoding="latin1") + self.rmin = config["rmin"] + self.rstep = config["rstep"] + self.rmax = config["rmax"] + self.rlen = config["rlen"] + self.rcalc = config["rcalc"] + self.Gcalc = config["Gcalc"] + self.stype = config["stype"] + self.qmax = config["qmax"] + self.qdamp = config.get("qdamp", config.get("qsig")) + self.qbroad = config.get("qbroad", config.get("qalp", 0.0)) + self.spdiameter = config.get("spdiameter") + self.dscale = config["dscale"] + return
+ + +
+[docs] + def save(self, z, subpath): + """Save data from a zipped project file. + + z -- zipped project file + subpath -- path to its own storage within project file + """ + config = { + "rmin": self.rmin, + "rstep": self.rstep, + "rmax": self.rmax, + "rlen": self.rlen, + "rcalc": self.rcalc, + "Gcalc": self.Gcalc, + "stype": self.stype, + "qmax": self.qmax, + "qdamp": self.qdamp, + "qbroad": self.qbroad, + "dscale": self.dscale, + } + z.writestr(subpath + "config", safeCPickleDumps(config)) + return
+ + +
+[docs] + def copy(self, other=None): + """Copy self to other. if other is None, create new instance. + + other -- reference to other object + + returns reference to copied object + """ + if other is None: + other = Calculation(self.name) + + # rcalc and Gcalc may be assigned, they get replaced by new lists + # after every calculation + assign_attributes = ( + "rmin", + "rstep", + "rmax", + "rlen", + "rcalc", + "Gcalc", + "stype", + "qmax", + "qdamp", + "qbroad", + "dscale", + ) + copy_attributes = () + for a in assign_attributes: + setattr(other, a, getattr(self, a)) + for a in copy_attributes: + setattr(other, a, copy.copy(getattr(self, a))) + return other
+ + +
+[docs] + def getYNames(self): + """Get names of data item which can be plotted as y. + + returns a name str list + """ + return [ + "Gcalc", + ]
+ + +
+[docs] + def getXNames(self): + """Get names of data item which can be plotted as x. + + returns a name str list + """ + return [ + "r", + ]
+ + +
+[docs] + def getData(self, dataname, step=None): + """Get Calculation data member. + + name -- data item name + step -- ignored, just for compatibility with Organizer.getData() + + returns data object, be it a single number, a list, or a list of list + """ + if dataname not in ["rcalc", "Gcalc"]: + emsg = "%s is not valid dataname" % dataname + raise ControlKeyError(emsg) + return self.__dict__[dataname]
+ + +
+[docs] + def getMetaDataNames(self): + """Return all applicable meta data names.""" + # FIXME: Currently we haven't thought about this + return []
+ + +
+[docs] + def getMetaData(self, name): + """Get meta data value. + + name -- meta data name + returns meta data value + """ + return None
+
+ + + +# End of class Calculation + +# simple test code +if __name__ == "__main__": + Calculation("name") + +# End of file +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/control/constraint.html b/_modules/diffpy/pdfgui/control/constraint.html new file mode 100644 index 00000000..3228b21a --- /dev/null +++ b/_modules/diffpy/pdfgui/control/constraint.html @@ -0,0 +1,266 @@ + + + + + + + + diffpy.pdfgui.control.constraint — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.control.constraint

+#!/usr/bin/env python
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Pavol Juhas
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+"""Class Constraint for storage of a single constraint equation constraints
+will be stored in { variable : constraint } dictionary."""
+
+import math
+import re
+
+from diffpy.pdfgui.control.controlerrors import ControlSyntaxError
+
+
+
+[docs] +class Constraint: + """Constraint --> storage and check of a single constraint equation. + + Data members: + formula -- right-side of constraint equation (string). When + assigned it is checked for math correctness and updates + the parguess dictionary + parguess -- read-only dictionary of parameter indices and their + estimated initial values. Values are None if they + cannot be estimated. + + Private members: + __lhs -- last value of constrained variable passed to guess() + """ + + def __init__(self, formula, value=None): + """Initialize the Constraint. + + formula -- (string) right-side of constraint equation + value -- (optional) current value of the variable + + __init__ raises ControlSyntaxError when formula is incorrect + """ + # initialize private members firsts + self.__lhs = None + self.parguess = {} + # initialize formula member avoid __setattr__ + self.__dict__["formula"] = "None" + # formula should be assigned as a last one + self.formula = formula + if value is not None: + self.guess(value) + return + +
+[docs] + def evalFormula(self, parvalues): + """Evaluate constraint formula. + + parvalues -- dictionary of int parameter indices and float values. + + returns formula result + """ + fncp = self.lambdaFormula() + result = fncp(parvalues) + return result
+ + +
+[docs] + def lambdaFormula(self): + """Build lambda function from constraint formula. Lambda function + expects dictionary argument. + + returns lambda function + """ + expr = re.sub(r"@(\d*)", r"p[\1]", self.formula) + f = eval("lambda p:" + expr, vars(math)) + return f
+ + +
+[docs] + def guess(self, value): + """Guess the initial values of parameters contained in parguess. + + value -- current value of the constrained variable + + The keys of self.parguess are indices of parameters used in formula, + and the values are suggested parameter values (None if they cannot + be estimated). + + returns a copy of self.parguess + """ + self.__lhs = float(value) + for k in self.parguess: + self.parguess[k] = None + # solve linear formulas of one variable + if len(self.parguess) == 1: + fncp = self.lambdaFormula() + # check if fncp is linear with eps precision + try: + eps = 1.0e-8 + lo, hi = 1.0 - eps, 1.0 + eps + (k,) = self.parguess.keys() + y = [fncp({k: 0.25}), fncp({k: 0.5}), fncp({k: 0.75})] + dy = [y[1] - y[0], y[2] - y[1]] + ady = [abs(z) for z in dy] + if lo * ady[0] <= ady[1] <= hi * ady[0] and dy[0] != 0.0: + a = 4 * dy[0] + b = y[1] - 0.5 * a + self.parguess[k] = (value - b) / a + except (ValueError, ZeroDivisionError): + pass + return dict(self.parguess)
+ + + def __setattr__(self, name, value): + """Check math and update parguess when formula is assigned.""" + if name != "formula": + self.__dict__[name] = value + return + # here we are assigning to formula + # first we need to check it it is valid + newformula = value + pars = re.findall(r"@\d+", newformula) + # require at least one parameter in the formula + if len(pars) == 0: + message = "No parameter in formula '%s'" % newformula + raise ControlSyntaxError(message) + try: + # this raises ControlSyntaxError if newformula is invalid + # define fncx in math module namespace + fncx = eval("lambda x:" + re.sub(r"@\d+", "x", newformula), vars(math)) + # check if fncx(0.25) is float + fncx(0.25) + 0.0 + except (ValueError, SyntaxError, TypeError, NameError): + message = "invalid constraint formula '%s'" % newformula + raise ControlSyntaxError(message) + # few more checks of the formula: + if newformula.find("**") != -1: + emsg = ("invalid constraint formula '{}', " "operator '**' not supported.").format(newformula) + raise ControlSyntaxError(emsg) + # checks checked + self.__dict__["formula"] = newformula + self.parguess = dict.fromkeys([int(p[1:]) for p in pars]) + if self.__lhs is not None: + self.guess(self.__lhs) + return
+ + + +# End of class Constraint + +# End of file +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/control/controlerrors.html b/_modules/diffpy/pdfgui/control/controlerrors.html new file mode 100644 index 00000000..ac670da0 --- /dev/null +++ b/_modules/diffpy/pdfgui/control/controlerrors.html @@ -0,0 +1,233 @@ + + + + + + + + diffpy.pdfgui.control.controlerrors — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.control.controlerrors

+#!/usr/bin/env python
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Jiwu Liu
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+
+
+[docs] +class ControlError(Exception): + """Basic PDFGuiControl exception class.""" + + def __init__(self, info): + """initialize. + + info -- description string + """ + Exception.__init__(self) + self.info = info + + def __str__(self): + return self.info
+ + + +
+[docs] +class ControlConfigError(ControlError): + """PDFGuiControl exception class -- object config is invalid.""" + + pass
+ + + +
+[docs] +class ControlFileError(ControlError): + """PDFGuiControl exception class -- object config is invalid.""" + + pass
+ + + +
+[docs] +class ControlKeyError(ControlError): + """PDFGuiControl exception class -- requested object can't be found.""" + + pass
+ + + +
+[docs] +class ControlValueError(ControlError): + """PDFGuiControl exception class -- Invalid value.""" + + pass
+ + + +
+[docs] +class ControlTypeError(ControlError): + """PDFGuiControl exception class -- Type mismatch.""" + + pass
+ + + +
+[docs] +class ControlStatusError(ControlError): + """PDFGuiControl exception class -- Fitting status doesn't match.""" + + pass
+ + + +
+[docs] +class ControlRuntimeError(ControlError): + """PDFGuiControl exception class -- various irrecoverable runtime error.""" + + pass
+ + + +
+[docs] +class ControlIndexError(ControlError): + """PDFGuiControl exception class -- index out of bound.""" + + pass
+ + + +
+[docs] +class ControlSyntaxError(ControlError): + """PDFGuiControl exception class -- invalid syntax of constraint + formula.""" + + pass
+ + + +
+[docs] +class TempControlSelectError(ControlError): + """Temporary define this error to identify the select-control error in + python3.""" + + pass
+ + + +# End of file +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/control/fitdataset.html b/_modules/diffpy/pdfgui/control/fitdataset.html new file mode 100644 index 00000000..1b37634f --- /dev/null +++ b/_modules/diffpy/pdfgui/control/fitdataset.html @@ -0,0 +1,1061 @@ + + + + + + + + diffpy.pdfgui.control.fitdataset — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.control.fitdataset

+#!/usr/bin/env python
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Pavol Juhas
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+"""Class FitDataSet for experimental PDF data and related fitting
+parameters."""
+
+import copy
+
+import numpy
+
+from diffpy.pdfgui.control.controlerrors import ControlStatusError
+from diffpy.pdfgui.control.parameter import Parameter
+from diffpy.pdfgui.control.pdfdataset import PDFDataSet
+from diffpy.utils.resampler import wsinterp
+
+
+
+[docs] +class FitDataSet(PDFDataSet): + """FitDataSet stores experimental and calculated PDF data and related + fitting parameters. Inherited from PDFDataSet. + + Data members (in addition to those in PDFDataSet): + + fitrmin -- lower boundary for data fitting, property + fitrmax -- upper boundary for data fitting, property + fitrstep -- r-step used for fitted data, property + constraints -- dictionary of { var_string : Constraint_instance } + initial -- dictionary of initial values of refinable variables + refined -- dictionary of refined values of refinable variables + + Calculated members: + + rcalc -- list of r points where Gcalc is calculated, cached property + Gcalc -- list of calculated G values, cached property + dGcalc -- list of standard deviations of Gcalc, cached property + Gtrunc -- Gobs resampled to rcalc grid, cached property + dGtrunc -- dGobs resampled to rcalc grid, cached property + Gdiff -- difference curve, Gdiff = Gtrunc - Gcalc, property + crw -- cumulative rw of the fit + + The data in rcalc, Gcalc, dGcalc, Gtrunc, dGtrunc are recalculated + and cached when r-sampling changes. Any change to fitrmin, + fitrmax and fitrstep sets the _rcalc_changed flag. + + Refinable variables: qdamp, qbroad, dscale + Note: self.refvar is the same as self.initial[refvar]. + + Class data: + + persistentItems -- list of attributes saved in project file + """ + + persistentItems = [ + "rcalc", + "Gcalc", + "dGcalc", + "fitrmin", + "fitrmax", + "fitrstep", + "initial", + "refined", + ] + + def __init__(self, name): + """Initialize FitDataSet. + + name -- name of the data set. It must be a unique identifier. + """ + self.initial = {} + self.refined = {} + PDFDataSet.__init__(self, name) + self.clear() + return + + def __setattr__(self, name, value): + """Assign refinable variables to self.initial.""" + if name in PDFDataSet.refinableVars: + self.initial[name] = value + else: + PDFDataSet.__setattr__(self, name, value) + return + + def __getattr__(self, name): + """Obtain refinable variables from self.initial. + + This is called only when normal attribute lookup fails. + """ + if name in PDFDataSet.refinableVars: + value = self.initial[name] + else: + emsg = "A instance has no attribute '%s'" % name + raise AttributeError(emsg) + return value + + def _getStrId(self): + """Make a string identifier. + + return value: string id + """ + return "d_" + self.name + +
+[docs] + def getYNames(self): + """Get names of data item which can be plotted as y. + + returns list of strings + """ + ynames = ["Gobs", "Gcalc", "Gdiff", "Gtrunc", "dGcalc", "crw"] + list(self.constraints.keys()) + return ynames
+ + +
+[docs] + def getXNames(self): + """Get names of data item which can be plotted as x. + + returns list of strings + """ + return [ + "r", + ]
+ + +
+[docs] + def getData(self, name, step=-1): + """Get self's data member. + + name -- data item name + step -- step info, it can be: + (1) a number ( -1 means latest step ): for single step + (2) a list of numbers: for multiple steps + (3) None: for all steps + + returns data object, be it a single number, a list, or a list of list + """ + # FIXME: for next plot interface, we need find how many steps the + # plotter is requiring for and make exact same number of copies of + # data in below + if name in self.metadata: + return self.metadata[name] + elif name in ("Gobs", "Gcalc", "Gtrunc", "Gdiff", "crw", "robs", "rcalc"): + d = getattr(self, name) + + # for Gtrunc and rcalc, we can use Gobs and robs instead when they + # are not ready. + if not d: + if name == "Gtrunc": + return getattr(self, "Gobs") + if name == "rcalc": + return getattr(self, "robs") + + return d + + # otherwise fitting's repository is preferred + return self.owner._getData(self, name, step)
+ + +
+[docs] + def clear(self): + """Reset all data members to initial empty values.""" + PDFDataSet.clear(self) + self._rcalc_changed = True + self._rcalc = [] + self._Gcalc = [] + self._dGcalc = [] + self._Gtrunc = [] + self._dGtrunc = [] + self._crw = [] + self._fitrmin = 0.5 + self._fitrmax = None + self._fitrstep = None + self.constraints = {} + self.refined = {} + return
+ + +
+[docs] + def clearRefined(self): + """Clear all refinement results.""" + self.Gcalc = [] + self.dGcalc = [] + self.crw = [] + self.refined = {} + return
+ + +
+[docs] + def obtainRefined(self, server, idataset): + """Upload refined datataset from PdfFit server instance. + + server -- instance of PdfFit server + idataset -- index of this dataset in server + """ + server.setdata(idataset) + # obtain Gcalc, dGcalc and crw from the server + self.Gcalc = server.getpdf_fit() + self.dGcalc = server.getpdf_diff() + self.crw = server.getcrw() + # get variables from the server + for var in PDFDataSet.refinableVars: + self.refined[var] = server.getvar(var) + return
+ + +
+[docs] + def read(self, filename): + """Same as readObs().""" + return self.readObs(filename)
+ + + def _updateRcalcRange(self): + """Helper method for updating fitrmin, fitrmax and fitrstep just after + reading observed values. + + No return value. + """ + frmin = self.fitrmin or self.rmin + self.fitrmin = max(frmin, self.rmin) + frmax = self.fitrmax or self.rmax + self.fitrmax = min(frmax, self.rmax) + self.fitrstep = self.fitrstep or self.getObsSampling() + return + +
+[docs] + def readObs(self, filename): + """Load experimental PDF data from PDFGetX2 or PDFGetN gr file. + + filename -- file to read from + + returns self + """ + PDFDataSet.read(self, filename) + self._updateRcalcRange() + return self
+ + +
+[docs] + def readStr(self, datastring): + """Same as readObsStr().""" + return self.readObsStr(datastring)
+ + +
+[docs] + def readObsStr(self, datastring): + """Read experimental PDF data from a string. + + datastring -- string of raw data + + returns self + """ + PDFDataSet.readStr(self, datastring) + self._updateRcalcRange() + return self
+ + +
+[docs] + def write(self, filename): + """Same as writeCalc(). Use writeObs() to save experimental PDF data. + + filename -- name of file to write to + + No return value. + """ + self.writeCalc(filename) + return
+ + +
+[docs] + def writeCalc(self, filename): + """Write calculated PDF data to a file. + + filename -- name of file to write to + + No return value. + """ + txt = self.writeCalcStr() + f = open(filename, "w") + f.write(txt) + f.close() + return
+ + +
+[docs] + def writeStr(self): + """Same as writeCalcStr. Use writeObsStr() for experimental PDF. + + Return data string. + """ + return self.writeCalcStr()
+ + +
+[docs] + def writeCalcStr(self): + """String representation of calculated PDF data. + + Return data string. + """ + if self.Gcalc == []: + raise ControlStatusError("Gcalc not available") + import time + from getpass import getuser + + lines = [] + # write metadata + lines.extend( + [ + "History written: " + time.ctime(), + "produced by " + getuser(), + "##### PDFgui fit", + ] + ) + # stype + if self.stype == "X": + lines.append("stype=X x-ray scattering") + elif self.stype == "N": + lines.append("stype=N neutron scattering") + # qmax + if self.qmax: + lines.append("qmax=%.2f" % self.qmax) + # qdamp + lines.append("qdamp=%g" % self.refined["qdamp"]) + # qbroad + lines.append("qbroad=%g" % self.refined["qbroad"]) + # dscale + lines.append("dscale=%g" % self.refined["dscale"]) + # fitrmin, fitrmax + if self.fitrmin is not None and self.fitrmax is not None: + lines.append("fitrmin=%g" % self.fitrmin) + lines.append("fitrmax=%g" % self.fitrmax) + # metadata + if len(self.metadata) > 0: + lines.append("# metadata") + for k, v in self.metadata.items(): + lines.append("%s=%s" % (k, v)) + # write data: + lines.append("##### start data") + lines.append("#L r(A) G(r) d_r d_Gr Gdiff") + # cache Gdiff here so it is not calculated many times + Gdiff = self.Gdiff + drcalc = 0.0 + for i in range(len(self.rcalc)): + lines.append("%g %g %.1f %g %g" % (self.rcalc[i], self.Gcalc[i], drcalc, self.dGcalc[i], Gdiff[i])) + # lines are ready here + datastring = "\n".join(lines) + "\n" + return datastring
+ + +
+[docs] + def writeObs(self, filename): + """Write observed PDF data to a file. + + filename -- name of file to write to + + No return value. + """ + PDFDataSet.write(self, filename) + return
+ + +
+[docs] + def writeObsStr(self): + """String representation of observed PDF data. + + Return data string. + """ + return PDFDataSet.writeStr(self)
+ + + def _resampledPDFDataSet(self): + """Return instance of PDFDataSet with resampled observed data. + + Helper method for writeResampledObs and writeResampledObsStr. + """ + resampled = PDFDataSet(self.name) + self.copy(resampled) + resampled.robs = self.rcalc + resampled.drobs = len(self.rcalc) * [0.0] + resampled.Gobs = self.Gtrunc + resampled.dGobs = self.dGtrunc + return resampled + +
+[docs] + def writeResampledObs(self, filename): + """Write resampled PDF data in Gtrunc to a file. + + filename -- name of the file to write to + + No return value. + """ + resampled = self._resampledPDFDataSet() + resampled.write(filename) + return
+ + +
+[docs] + def writeResampledObsStr(self): + """String representation of resampled PDF data in Gtrunc. + + Return data string. + """ + resampled = self._resampledPDFDataSet() + s = resampled.writeStr() + return s
+ + +
+[docs] + def findParameters(self): + """Obtain dictionary of parameters used by self.constraints. The keys + of returned dictionary are integer parameter indices, and their values + Parameter instances, with guessed initial values. + + returns dictionary of indices and Parameter instances + """ + foundpars = {} + for var, con in self.constraints.items(): + con.guess(self.getvar(var)) + for pidx, pguess in con.parguess.items(): + # skip if already found + if pidx in foundpars: + continue + # insert to foundpars otherwise + if pguess is not None: + foundpars[pidx] = Parameter(pidx, initial=pguess) + else: + foundpars[pidx] = Parameter(pidx, initial=0.0) + return foundpars
+ + +
+[docs] + def applyParameters(self, parameters): + """Evaluate constraint formulas and adjust self.initial. + + parameters -- dictionary of parameter indices with Parameter instances. + Dictionary may also have float-type values. + """ + # convert values to floats + parvalues = {} + for pidx, par in parameters.items(): + if isinstance(par, Parameter): + parvalues[pidx] = par.initialValue() + else: + parvalues[pidx] = float(par) + # evaluate constraints + for var, con in self.constraints.items(): + # __setattr__ assigns var in self.initial + self.setvar(var, con.evalFormula(parvalues)) + return
+ + +
+[docs] + def changeParameterIndex(self, oldidx, newidx): + """Change a parameter index to a new value. + + This will replace all instances of one parameter name with + another in this fit. + """ + import re + + for var in self.constraints: + formula = self.constraints[var].formula + pat = r"@%i\b" % oldidx + newformula = re.sub(pat, "@%i" % newidx, formula) + self.constraints[var].formula = newformula + return
+ + +
+[docs] + def copy(self, other=None): + """Copy self to other. if other is None, create new instance. + + other -- ref to other object + + returns reference to copied object + """ + # check arguments + if other is None: + other = FitDataSet(self.name) + PDFDataSet.copy(self, other) + if isinstance(other, FitDataSet): + # assigned attributes + other._fitrmin = self._fitrmin + other._fitrmax = self._fitrmax + other._fitrstep = self._fitrstep + other._rcalc_changed = self._rcalc_changed + # copied attributes + other.constraints = copy.deepcopy(self.constraints) + other.initial = copy.deepcopy(self.initial) + other.refined = copy.deepcopy(self.refined) + # must also update the sampling on the new object + st = self.getFitSamplingType() + other.setFitSamplingType(st, self.fitrstep) + return other
+ + +
+[docs] + def load(self, z, subpath): + """Load data from a zipped project file. + + z -- zipped project file + subpath -- path to its own storage within project file + """ + import pickle + + from diffpy.pdfgui.utils import asunicode + + self.clear() + subs = subpath.split("/") + rootDict = z.fileTree[subs[0]][subs[1]][subs[2]][subs[3]] + # raw data + obsdata = asunicode(z.read(subpath + "obs")) + self.readObsStr(obsdata) + + # data from calculation + content = pickle.loads(z.read(subpath + "calc"), encoding="latin1") + for item in FitDataSet.persistentItems: + # skip items which are not in the project file + if item not in content: + continue + # update dictionaries so that old project files load fine + if item == "initial": + self.initial.update(content[item]) + elif item == "refined": + self.refined.update(content[item]) + else: + setattr(self, item, content[item]) + self._updateRcalcRange() + + # constraints + if "constraints" in rootDict: + from diffpy.pdfgui.control.pdfguicontrol import CtrlUnpickler + + self.constraints = CtrlUnpickler.loads(z.read(subpath + "constraints")) + # handle renamed variable from old project files + translate = {"qsig": "qdamp", "qalp": "qbroad"} + for old, new in translate.items(): + if old in self.constraints: + self.constraints[new] = self.constraints.pop(old) + + return
+ + +
+[docs] + def save(self, z, subpath): + """Save data to a zipped project file. + + z -- zipped project file + subpath -- path to its own storage within project file + """ + from diffpy.pdfgui.utils import safeCPickleDumps + + # write raw data + z.writestr(subpath + "obs", self.writeObsStr()) + content = {} + for item in FitDataSet.persistentItems: + content[item] = getattr(self, item, None) + spkl = safeCPickleDumps(content) + z.writestr(subpath + "calc", spkl) + + # make a picklable dictionary of constraints + if self.constraints: + spkl = safeCPickleDumps(self.constraints) + z.writestr(subpath + "constraints", spkl) + return
+ + + # interface for data sampling + +
+[docs] + def getFitSamplingType(self): + """Description of r-sampling used in the fit. This method compares + self.fitrstep with r-sampling in the observed data and with Nyquist r + step. + + Return a string, possible values are "data", "Nyquist" or + "custom". + """ + eps = 1e-8 + if abs(self.fitrstep - self.getObsSampling()) < eps: + rv = "data" + elif abs(self.fitrstep - self.getNyquistSampling()) < eps: + rv = "Nyquist" + else: + rv = "custom" + return rv
+ + +
+[docs] + def setFitSamplingType(self, tp, value=None): + """GUI interface to set fitrstep, i.e., r-grid for fitting. + + tp -- description of fit sampling type. Possible values are + "data" ... same as used in experimental PDF + "Nyquist" ... sampling at Nyquist spacing + "custom" ... user specified value + value -- new value of fitrstep, only used when tp is "custom". + + No return value. + + Raises ValueError for unknown tp string. + """ + if tp == "data": + self.fitrstep = self.getObsSampling() + elif tp == "Nyquist": + self.fitrstep = self.getNyquistSampling() + elif tp == "custom": + self.fitrstep = max(value, self.getObsSampling()) + else: + emsg = "Invalid value for fit sampling type." + raise ValueError(emsg) + return
+ + +
+[docs] + def getObsSampling(self): + """Return the average r-step used in robs or zero when not defined.""" + n = len(self.robs) + if n > 1: + rv = (self.robs[-1] - self.robs[0]) / (n - 1.0) + else: + rv = 0.0 + return rv
+ + +
+[docs] + def getNyquistSampling(self): + """Return r-step corresponding to Nyquist sampling at the qmax value. + + When qmax is zero, return r-step in the observed data. + """ + if self.qmax > 0.0: + rv = numpy.pi / self.qmax + else: + rv = self.getObsSampling() + return rv
+ + + # Property Attributes + + def _updateRcalcSampling(self): + """Helper method for resampling rcalc and interpolating related data. + This method interpolates Gcalc, dGcalc, Gtrunc, dGtrunc, crw to new r + grid. + + No return value. + """ + if not self._rcalc_changed: + return + frmin, frmax = self.fitrmin, self.fitrmax + frstep = float(self.fitrstep) + # new rcalc must cover the whole [fitrmin, fitrmax] interval + # otherwise pdffit2 would complain + robs_below = [ri for ri in self.robs if ri < frmin] + if robs_below: + rcalcfirst = robs_below[-1] + else: + rcalcfirst = self.robs[0] + nrcalc = numpy.round(1.0 * (frmax - rcalcfirst) / frstep) + if frmax - (rcalcfirst + nrcalc * frstep) > frstep * 1e-8: + nrcalc += 1 + newrcalc = rcalcfirst + frstep * numpy.arange(nrcalc + 1) + tp = self.getFitSamplingType() + # Gcalc: + if len(self._Gcalc) > 0: + newGcalc = grid_interpolation(self._rcalc, self._Gcalc, newrcalc, tp=tp) + self._Gcalc = list(newGcalc) + # dGcalc + if len(self._dGcalc) > 0: + newdGcalc = grid_interpolation(self._rcalc, self._dGcalc, newrcalc, tp=tp) + self._dGcalc = list(newdGcalc) + # invalidate Gtrunc and dGtrunc + self._Gtrunc = [] + self._dGtrunc = [] + # everything has been interpolated here, we can overwrite _rcalc + self._rcalc = list(newrcalc) + # and finally set flag for up to date cache + self._rcalc_changed = False + return + + # fitrmin + + def _get_fitrmin(self): + return self._fitrmin + + def _set_fitrmin(self, value): + self._rcalc_changed = True + self._fitrmin = float(value) + return + + fitrmin = property(_get_fitrmin, _set_fitrmin, doc="Lower boundary for simulated PDF curve.") + + # fitrmax + + def _get_fitrmax(self): + return self._fitrmax + + def _set_fitrmax(self, value): + self._rcalc_changed = True + self._fitrmax = float(value) + return + + fitrmax = property(_get_fitrmax, _set_fitrmax, doc="Upper boundary for simulated PDF curve.") + + # fitrstep + + def _get_fitrstep(self): + return self._fitrstep + + def _set_fitrstep(self, value): + self._rcalc_changed = True + self._fitrstep = float(value) + return + + fitrstep = property(_get_fitrstep, _set_fitrstep, doc="R-step used for simulated PDF curve.") + + # rcalc + + def _get_rcalc(self): + self._updateRcalcSampling() + return self._rcalc + + def _set_rcalc(self, value): + self._rcalc = value + return + + rcalc = property( + _get_rcalc, + _set_rcalc, + doc="""R-grid for refined data, read-only. + Use fitrmin, fitrmax, fitrstep to change it""", + ) + + # Gcalc + + def _get_Gcalc(self): + self._updateRcalcSampling() + return self._Gcalc + + def _set_Gcalc(self, value): + self._Gcalc = value + return + + Gcalc = property(_get_Gcalc, _set_Gcalc, doc="List of calculate G values.") + + # dGcalc + + def _get_dGcalc(self): + self._updateRcalcSampling() + return self._dGcalc + + def _set_dGcalc(self, value): + self._dGcalc = value + return + + dGcalc = property(_get_dGcalc, _set_dGcalc, doc="List of standard deviations of Gcalc.") + + # Gtrunc + + def _get_Gtrunc(self): + self._updateRcalcSampling() + if not self._Gtrunc: + tp = self.getFitSamplingType() + newGtrunc = grid_interpolation(self.robs, self.Gobs, self.rcalc, tp=tp) + self._Gtrunc = list(newGtrunc) + return self._Gtrunc + + def _set_Gtrunc(self, value): + self._Gtrunc = value + return + + Gtrunc = property(_get_Gtrunc, _set_Gtrunc, doc="Gobs resampled to rcalc grid.") + + # dGtrunc + + def _get_dGtrunc(self): + self._updateRcalcSampling() + if not self._dGtrunc: + tp = self.getFitSamplingType() + # use sum to avoid index error for empty arrays + newdGtrunc = grid_interpolation( + self.robs, + self.dGobs, + self.rcalc, + left=sum(self.dGobs[:1]), + right=sum(self.dGobs[-1:]), + tp=tp, + ) + self._dGtrunc = list(newdGtrunc) + return self._dGtrunc + + def _set_dGtrunc(self, value): + self._dGtrunc = value + return + + dGtrunc = property(_get_dGtrunc, _set_dGtrunc, doc="dGobs resampled to rcalc grid.") + + # Gdiff + + def _get_Gdiff(self): + if len(self.Gcalc): + rv = [(yo - yc) for yo, yc in zip(self.Gtrunc, self.Gcalc)] + else: + rv = [] + return rv + + Gdiff = property(_get_Gdiff, doc="Difference between observed and calculated PDF on rcalc grid.") + + # crw + def _get_crw(self): + # crw comes from the engine, so it doesn't need rescaling + return self._crw + + def _set_crw(self, value): + if len(value) != len(self.rcalc): + self._crw = [0.0] * len(self.rcalc) + else: + self._crw = value[:] + return + + crw = property(_get_crw, _set_crw, doc="cumulative rw on rcalc grid")
+ + + # End of Property Attributes + + +# End of class FitDataSet + + +############################################################################## +# helper functions +############################################################################## +def _linear_interpolation(x0, y0, x1, youtleft, youtright): + + x0 = numpy.asarray(x0, copy=None, dtype=float) + y0 = numpy.asarray(y0, copy=None, dtype=float) + n0 = len(x0) + x1 = numpy.asarray(x1, copy=None, dtype=float) + n1 = len(x1) + y1 = youtright * numpy.ones(n1, dtype=float) + if n0: + y1[x1 < x0.min()] = youtleft + # take care of special n0 lengths + if n0 == 0: + return y1 + elif n0 == 1: + y1[x1 == x0[0]] = y0[0] + return y1 + # here n0 > 1 so we can safely calculate dx0 + dx0 = (x0[-1] - x0[0]) / (n0 - 1.0) + epsx = dx0 * 1e-8 + # find covered values in x1 + (m1,) = numpy.where(numpy.logical_and(x0[0] - epsx < x1, x1 < x0[-1] + epsx)) + ilo0 = numpy.floor((x1[m1] - x0[0]) / dx0) + ilo0 = numpy.array(ilo0, dtype=int) + # ilo0 may be out of bounds for x1 close to the edge + ilo0[ilo0 < 0] = 0 + ilo0[ilo0 > n0 - 2] = n0 - 2 + ihi0 = ilo0 + 1 + # make sure hi indices remain valid + w0hi = (x1[m1] - x0[ilo0]) / dx0 + w0lo = 1.0 - w0hi + y1[m1] = w0lo * y0[ilo0] + w0hi * y0[ihi0] + return y1 + + +
+[docs] +def grid_interpolation(x0, y0, x1, left=None, right=None, tp=None): + """Interpolate values from one grid onto another using either linear or + Whittaker–Shannon interpolation. + + Parameters + ---------- + x0 : array_like + Original x-grid, must be equally spaced. + y0 : array_like + Original values defined on x0. + x1 : array_like + New x-grid upon which to interpolate. + tp : {'data', 'Nyquist', 'custom'}, optional + Corresponding fit sampling type. Use Whittaker–Shannon interpolation + for Nyquist resampling and linear interpolation otherwise. + If not provided, linear interpolation is used. + left : float, optional + Value for interpolated y1 for x1 below the x0 range. + Default: if tp='Nyquist' then y1[0] is used. Otherwise 0.0 is used. + right : float, optional + Value for interpolated y1 for x1 above the x0 range. + Default: if tp='Nyquist' then y1[-1] is used. Otherwise 0.0 is used. + + Returns + ------- + numpy.ndarray + Array of interpolated values on the new grid x1. + + Notes + ----- + When tp='Nyquist', the function calls :func:`wsinterp` to perform Whittaker–Shannon interpolation. + Otherwise it uses the internal :func:`_linear_interpolation` routine. + """ + if tp == "Nyquist": + x0 = numpy.asarray(x0) + x1 = numpy.asarray(x1) + y0 = numpy.asarray(y0) + return wsinterp(x1, x0, y0, left, right) + else: + left = 0.0 if left is None else left + right = 0.0 if right is None else right + return _linear_interpolation(x0, y0, x1, left, right)
+ + + +# simple test code +if __name__ == "__main__": + FitDataSet("name") + +# End of file +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/control/fitstructure.html b/_modules/diffpy/pdfgui/control/fitstructure.html new file mode 100644 index 00000000..71e5bc78 --- /dev/null +++ b/_modules/diffpy/pdfgui/control/fitstructure.html @@ -0,0 +1,1081 @@ + + + + + + + + diffpy.pdfgui.control.fitstructure — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.control.fitstructure

+#!/usr/bin/env python
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Pavol Juhas
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+"""Class FitStructure for storage of one phase and related fitting
+parameters."""
+
+import copy
+import re
+
+import numpy
+
+from diffpy.pdfgui.control.constraint import Constraint
+from diffpy.pdfgui.control.controlerrors import ControlTypeError, ControlValueError
+from diffpy.pdfgui.control.parameter import Parameter
+from diffpy.pdfgui.control.pdfstructure import PDFStructure
+from diffpy.structure import Atom
+
+
+
+[docs] +class FitStructure(PDFStructure): + """FitStructure holds initial and refined structure and related fit + parameters. Inherited from PDFStructure. + + Class data members: + symposeps -- tolerance for recognizing site as symmetry position + + Data members (in addition to those in PDFStructure): + owner -- instance of parent Fitting (set in Organizer.add()) + initial -- initial structure, same as self + refined -- refined structure when available or None + constraints -- dictionary of { refvar_string : Constraint_instance } + selected_pairs -- string of selected pairs, by default "all-all". + Use setSelectedPairs() and getSelectedPairs() methods + to access its value. + custom_spacegroup -- instance of SpaceGroup which has no equivalent + in diffpy.structure.spacegroups module. This can happen + after reading from a CIF file. When equivalent space + group exists, custom_spacegroup is None. + + Refinable variables: pscale, spdiameter, delta1, delta2, sratio, lat(n), + where n=1..6, x(i), y(i), z(i), occ(i), u11(i), u22(i), u33(i), + u12(i), u13(i), u23(i), where i=1..Natoms + + Non-refinable variable: rcut, stepcut + """ + + # class data members: + symposeps = 0.001 + # evaluation of sorted_standard_space_groups deferred when necessary + sorted_standard_space_groups = [] + + def __init__(self, name, *args, **kwargs): + """Initialize FitDataSet. + + name -- name of the data set. The same name is used for + self.initial and self.final. + args, kwargs -- optional arguments passed to parent PDFStructure + """ + PDFStructure.__init__(self, name) + self.owner = None + # self.initial deliberately not assigned, + # it gets mapped to self by __getattr__ + self.refined = None + self.constraints = {} + self.selected_pairs = "all-all" + self.initial.pdffit["sgoffset"] = [0.0, 0.0, 0.0] + self.custom_spacegroup = None + return + + def _update_custom_spacegroup(self, parser): + """Helper method for read() and readStr(), which takes care of setting + custom_spacegroup after successful reading. + + parser -- instance of StructureParser used in reading. + + No return value. + """ + self.custom_spacegroup = None + self.initial.pdffit["sgoffset"] = [0.0, 0.0, 0.0] + if hasattr(parser, "spacegroup"): + sg = parser.spacegroup + # when sg.number is None or 0, we have a custom spacegroup + if not sg.number: + # overwrite sg.number with 0, an identifier for custom SG + sg.number = 0 + self.custom_spacegroup = sg + # here sg.number is 0 or positive integer + self.initial.pdffit["spcgr"] = sg.short_name + return + +
+[docs] + def read(self, filename, format="auto"): + """Load structure from a file, raise ControlFileError for invalid or + unknown structure format. Overloads PDFStructure.read() to handle + custom_spacegroup attribute. + + filename -- file to be loaded + format -- structure format such as 'pdffit', 'pdb', 'xyz'. When + 'auto' all available formats are tried in a row. + + Return instance of StructureParser used to load the data. + See Structure.read() for more info. + """ + p = PDFStructure.read(self, filename, format) + # update data only after successful reading + self._update_custom_spacegroup(p) + # FIXME Temporary workaround to prevent forced isotropy of the Uij + # values. To be removed and handled by atom isotropy column. + self.anisotropy = True + return p
+ + +
+[docs] + def readStr(self, s, format="auto"): + """Same as PDFStructure.readStr, but handle the custom_spacegroup data. + + Return instance of StructureParser used to load the data. See + Structure.readStr() for more info. + """ + p = PDFStructure.readStr(self, s, format) + # update data only after successful reading + self._update_custom_spacegroup(p) + # FIXME Temporary workaround to prevent forced isotropy of the Uij + # values. To be removed and handled by atom isotropy column. + self.anisotropy = True + return p
+ + + def __getattr__(self, name): + """Map self.initial to self. + + This is called only when normal attribute lookup fails. + """ + if name == "initial": + value = self + else: + emsg = "A instance has no attribute '%s'" % name + raise AttributeError(emsg) + return value + + def _getStrId(self): + """Make a string identifier. + + return value: string id + """ + return "p_" + self.name + +
+[docs] + def clearRefined(self): + """Clear all refinement results.""" + self.refined = None + return
+ + +
+[docs] + def obtainRefined(self, server, iphase): + """Upload refined phase from PdfFit server instance. + + server -- instance of PdfFit server + iphase -- index of this phase in server + """ + server.setphase(iphase) + if self.refined is None: + self.refined = PDFStructure(self.name) + self.refined.readStr(server.save_struct_string(iphase), "pdffit") + return
+ + +
+[docs] + def findParameters(self): + """Obtain dictionary of parameters used by self.constraints. The keys + of returned dictionary are integer parameter indices, and the values + are Parameter instances, with guessed initial values. + + returns dictionary of indices and Parameter instances + """ + foundpars = {} + for var, con in self.constraints.items(): + con.guess(self.initial.getvar(var)) + for pidx, pguess in con.parguess.items(): + # skip if already found + if pidx in foundpars: + continue + # insert to foundpars otherwise + if pguess is not None: + foundpars[pidx] = Parameter(pidx, initial=pguess) + else: + foundpars[pidx] = Parameter(pidx, initial=0.0) + return foundpars
+ + +
+[docs] + def applyParameters(self, parameters): + """Evaluate constraint formulas and adjust initial PDFStructure. + + parameters -- dictionary of parameter indices with Parameter + instance values. Values may also be float type. + """ + # convert values to floats + parvalues = {} + for pidx, par in parameters.items(): + if isinstance(par, Parameter): + parvalues[pidx] = par.initialValue() + else: + parvalues[pidx] = float(par) + # evaluate constraints + for var, con in self.constraints.items(): + self.initial.setvar(var, con.evalFormula(parvalues)) + return
+ + +
+[docs] + def changeParameterIndex(self, oldidx, newidx): + """Change a parameter index to a new value. + + This will replace all instances of one parameter name with + another in this fit. + """ + for var in self.constraints: + formula = self.constraints[var].formula + pat = r"@%i\b" % oldidx + newformula = re.sub(pat, "@%i" % newidx, formula) + self.constraints[var].formula = newformula + return
+ + + def _popAtomConstraints(self): + """Take out atom-related items from the constraints dictionary. + + This is useful when atom indices are going to change due to + insertion or removal of atoms. See also _restoreAtomConstraints(). + + Return a dictionary of atom instances vs dictionary of related + refinable variables (stripped of "(siteindex)") and Constraint + instances - for example {atom : {'u13' : constraint}}. + """ + rv = {} + # atom variable pattern + avpat = re.compile(r"^([xyz]|occ|u11|u22|u33|u12|u13|u23)\((\d+)\)") + for var in list(self.constraints.keys()): + m = avpat.match(var) + if not m: + continue + barevar = m.group(1) + atomidx = int(m.group(2)) - 1 + cnts = rv.setdefault(self.initial[atomidx], {}) + cnts[barevar] = self.constraints.pop(var) + return rv + + def _restoreAtomConstraints(self, acd): + """Restore self.constraints from atom constraints dictionary. This is + useful for getting correct atom indices into refvar strings. See also + _popAtomConstraints() + + acd -- dictionary obtained from _popAtomConstraints() + """ + for i, a in enumerate(self.initial): + if a not in acd: + continue + # there are some constraints for atom a + siteindex = i + 1 + cnts = acd[a] + for barevar, con in cnts.items(): + var = barevar + "(%i)" % siteindex + self.constraints[var] = con + return + +
+[docs] + def insertAtoms(self, index, atomlist): + """Insert list of atoms before index and adjust self.constraints. + + index -- position in the initial structure, atoms are appended + when larger than len(self.initial). + atomlist -- list of atom instances. + """ + acd = self._popAtomConstraints() + # FIXME Temporary workaround to prevent forced isotropy of the Uij + # values. To be removed and handled by atom isotropy column. + for a in atomlist: + a.anisotropy = True + # workaround ends here. + self.initial[index:index] = atomlist + self._restoreAtomConstraints(acd) + return
+ + +
+[docs] + def deleteAtoms(self, indices): + """Removed atoms at given indices and adjust self.constraints. + + indices -- list of integer indices of atoms to be deleted + """ + acd = self._popAtomConstraints() + # get unique, reverse sorted indices + ruindices = sorted(set(indices), reverse=True) + for i in ruindices: + self.initial.pop(i) + self._restoreAtomConstraints(acd) + return
+ + +
+[docs] + def expandSuperCell(self, mno): + """Perform supercell expansion for this structure and adjust + constraints for positions and lattice parameters. New lattice + parameters are multiplied and fractional coordinates divided by + corresponding multiplier. New atoms are grouped with their source in + the original cell. + + mno -- tuple or list of three positive integer cell multipliers along + the a, b, c axis + """ + # check argument + if tuple(mno) == (1, 1, 1): + return + if min(mno) < 1: + raise ControlValueError("mno must contain 3 positive integers") + # back to business + acd = self._popAtomConstraints() + mnofloats = numpy.array(mno[:3], dtype=float) + ijklist = [(i, j, k) for i in range(mno[0]) for j in range(mno[1]) for k in range(mno[2])] + # build a list of new atoms + newatoms = [] + for a in self.initial: + for ijk in ijklist: + adup = Atom(a) + adup.xyz = (a.xyz + ijk) / mnofloats + newatoms.append(adup) + # does atom a have any constraint? + if a not in acd: + continue + # add empty constraint dictionary for duplicate atom + acd[adup] = {} + for barevar, con in acd[a].items(): + formula = con.formula + if barevar in ("x", "y", "z"): + symidx = "xyz".index(barevar) + if ijk[symidx] != 0: + formula += " + %i" % ijk[symidx] + if mno[symidx] > 1: + formula = "(%s)/%.1f" % (formula, mno[symidx]) + formula = re.sub(r"\((@\d+)\)", r"\1", formula) + # keep other formulas intact and add constraint + # for barevar of the duplicate atom + acd[adup][barevar] = Constraint(formula) + # replace original atoms with newatoms + self.initial[:] = newatoms + for ai, an in zip(self.initial, newatoms): + if an in acd: + acd[ai] = acd[an] + # and rebuild their constraints + self._restoreAtomConstraints(acd) + # take care of lattice parameters + self.initial.lattice.setLatPar( + a=mno[0] * self.initial.lattice.a, + b=mno[1] * self.initial.lattice.b, + c=mno[2] * self.initial.lattice.c, + ) + # adjust lattice constraints if present + latvars = ("lat(1)", "lat(2)", "lat(3)") + for var, multiplier in zip(latvars, mno): + if var in self.constraints and multiplier > 1: + con = self.constraints[var] + formula = "%.0f*(%s)" % (multiplier, con.formula) + formula = re.sub(r"\((@\d+)\)", r"\1", formula) + con.formula = formula + return
+ + +
+[docs] + def isSpaceGroupPossible(self, spacegroup): + """Check if space group is consistent with lattice parameters. + + spacegroup -- instance of SpaceGroup + + Return bool. + """ + from diffpy.structure.symmetryutilities import isSpaceGroupLatPar + + return isSpaceGroupLatPar(spacegroup, *self.initial.lattice.abcABG())
+ + +
+[docs] + def getSpaceGroupList(self): + """Return a list of SpaceGroup instances sorted by International Tables + number. + + When custom_spacegroup is defined, the list starts with + custom_spacegroup. + """ + if not FitStructure.sorted_standard_space_groups: + import diffpy.structure.spacegroups as SG + + existing_names = {} + unique_named_list = [] + for sg in SG.SpaceGroupList: + if sg.short_name not in existing_names: + unique_named_list.append(sg) + existing_names[sg.short_name] = True + # sort by International Tables number, stay compatible with 2.3 + n_sg = [(sg.number % 1000, sg) for sg in unique_named_list] + n_sg = sorted(n_sg, key=lambda x: x[0]) # sort by the first element of tuple. + FitStructure.sorted_standard_space_groups = [sg for n, sg in n_sg] + sglist = list(FitStructure.sorted_standard_space_groups) + if self.custom_spacegroup: + sglist.insert(0, self.custom_spacegroup) + return sglist
+ + +
+[docs] + def getSpaceGroup(self, sgname): + """Find space group in getSpaceGroupList() by short_name or number. + sgname can be non-standard in case of CIF file defined space group. + + Return instance of SpaceGroup. Raise ValueError if sgname cannot + be found or when it is not present in getSpaceGroupList(). + """ + import diffpy.structure.spacegroups as SG + + # this should match the "CIF data" sgname + sgmatch = [sg for sg in self.getSpaceGroupList() if sg.short_name == sgname] + # use standard lookup function when not matched by short_name + if not sgmatch: + sgmatch.append(SG.GetSpaceGroup(sgname)) + if not sgmatch: + emsg = "Unknown space group %r" % sgname + raise ValueError(emsg) + sgfound = sgmatch[0] + return sgfound
+ + +
+[docs] + def expandAsymmetricUnit(self, spacegroup, indices, sgoffset=[0, 0, 0]): + """Perform symmetry expansion for atoms at given indices. Temperature + factors may be corrected to reflect the symmetry. All constraints for + expanded atoms are erased with the exception of the occupancy("occ". + Constraints of unaffected atoms are adjusted for new positions + self.initial. + + spacegroup -- instance of SpaceGroup from diffpy.structure + indices -- list of integer indices of atoms to be expanded + sgoffset -- optional offset of space group origin [0,0,0] + """ + from diffpy.structure.symmetryutilities import ExpandAsymmetricUnit + + acd = self._popAtomConstraints() + # get unique, reverse sorted indices + ruindices = sorted(set(indices), reverse=True) + coreatoms = [self.initial[i] for i in ruindices] + corepos = [a.xyz for a in coreatoms] + coreUijs = [a.U for a in coreatoms] + eau = ExpandAsymmetricUnit(spacegroup, corepos, coreUijs, sgoffset=sgoffset, eps=self.symposeps) + # build a nested list of new atoms: + newatoms = [] + for i in range(len(coreatoms)): + ca = coreatoms[i] + caocc_con = None + if ca in acd and "occ" in acd[ca]: + caocc_con = acd[ca]["occ"] + eca = [] # expanded core atom + for j in range(eau.multiplicity[i]): + a = Atom(ca) + a.xyz = eau.expandedpos[i][j] + a.U = eau.expandedUijs[i][j] + eca.append(a) + if caocc_con is None: + continue + # make a copy of occupancy constraint + acd[a] = {"occ": copy.copy(caocc_con)} + newatoms.append(eca) + # insert new atoms where they belong + for i, atomlist in zip(ruindices, newatoms): + self.initial[i : i + 1] = atomlist + # remember this spacegroup as the last one used + self.initial.pdffit["spcgr"] = spacegroup.short_name + self.initial.pdffit["sgoffset"] = list(sgoffset) + # tidy constraints + self._restoreAtomConstraints(acd) + return
+ + +
+[docs] + def applySymmetryConstraints(self, spacegroup, indices, posflag, Uijflag, sgoffset=[0, 0, 0]): + """Generate symmetry constraints for positions and thermal factors. + Both positions and thermal factors may get corrected to reflect space + group symmetry. Old positional and thermal constraints get erased. New + parameter indices start at fist decade after the last used parameter. + + spacegroup -- instance of SpaceGroup from diffpy.structure + indices -- list of integer indices of atoms to be expanded + posflag -- required bool flag for constraining positions + Uijflag -- required bool flag for Uij constrainment + sgoffset -- optional offset of space group origin [0,0,0] + """ + if not posflag and not Uijflag: + return + # need to do something + from diffpy.structure.symmetryutilities import SymmetryConstraints + + # get unique sorted indices + tobeconstrained = dict.fromkeys(indices) + uindices = sorted(tobeconstrained.keys()) + # remove old constraints + pospat = re.compile(r"^([xyz])\((\d+)\)") + Uijpat = re.compile(r"^(u11|u22|u33|u12|u13|u23)\((\d+)\)") + for var in list(self.constraints.keys()): + mpos = posflag and pospat.match(var) + mUij = Uijflag and Uijpat.match(var) + if mpos and (int(mpos.group(2)) - 1) in tobeconstrained: + del self.constraints[var] + elif mUij and (int(mUij.group(2)) - 1) in tobeconstrained: + del self.constraints[var] + # find the largest used parameter index; pidxused must have an element + pidxused = [i for i in self.owner.updateParameters()] + [0] + # new parameters will start at the next decade + parzeroidx = 10 * (int(max(pidxused) / 10)) + 10 + # dictionary of parameter indices and their values + newparvalues = {} + selatoms = [self.initial[i] for i in uindices] + selpos = [a.xyz for a in selatoms] + selUijs = [a.U for a in selatoms] + symcon = SymmetryConstraints(spacegroup, selpos, selUijs, sgoffset=sgoffset, eps=self.symposeps) + # deal with positions + if posflag: + # fix positions: + for a, xyz in zip(selatoms, symcon.positions): + a.xyz = xyz + possymbols, parvalues = _makeParNames(symcon.pospars, parzeroidx) + newparvalues.update(parvalues) + eqns = symcon.positionFormulasPruned(possymbols) + for aidx, eq in zip(uindices, eqns): + siteidx = aidx + 1 + for barevar, formula in eq.items(): + var = barevar + "(%i)" % siteidx + self.constraints[var] = Constraint(formula) + # deal with temperature factors + if Uijflag: + # fix thermals + for a, Uij in zip(selatoms, symcon.Uijs): + a.U = Uij + Usymbols, parvalues = _makeParNames(symcon.Upars, parzeroidx) + newparvalues.update(parvalues) + eqns = symcon.UFormulasPruned(Usymbols) + for aidx, eq in zip(uindices, eqns): + siteidx = aidx + 1 + for barevar, formula in eq.items(): + # keys in formula dictionary are uppercase + var = barevar.lower() + "(%i)" % siteidx + self.constraints[var] = Constraint(formula) + # update parameter values in parent Fitting + self.owner.updateParameters() + for pidx, pvalue in newparvalues.items(): + parobj = self.owner.parameters[pidx] + parobj.setInitial(pvalue) + # and finally remember this space group + self.initial.pdffit["spcgr"] = spacegroup.short_name + self.initial.pdffit["sgoffset"] = list(sgoffset) + return
+ + +
+[docs] + def setSelectedPairs(self, s): + """Set the value of selected_pairs to s, raise ControlValueError when s + has invalid syntax. The selected_pairs is a comma separated list of + words formatted as. + + [!]{element|indexOrRange|all}-[!]{element|indexOrRange|all} + + where '!' excludes the given atoms from first or second pair. + + Examples: + + all-all all possible pairs + Na-Na only Na-Na pairs + all-all, !Na- all pairs except Na-Na (first index skips Na) + all-all, -!Na same as previous (second index skips Na) + Na-1:4 pairs of Na and first 4 atoms + all-all, !Cl-!Cl exclude any pairs containing Cl + all-all, !Cl-, -!Cl same as previous + 1-all only pairs including the first atom + + Use getPairSelectionFlags() method to get a list of included values + for first and second pair index. + """ + # check syntax of s + psf = self.getPairSelectionFlags(s) + self.selected_pairs = psf["fixed_pair_string"] + return
+ + +
+[docs] + def getSelectedPairs(self): + return self.selected_pairs
+ + +
+[docs] + def getPairSelectionFlags(self, s=None): + """Translate string s to a list of allowed values for first and second + pair index. Raise ControlValueError for invalid syntax of s. See + setSelectedPairs() docstring for a definition of pair selection syntax. + + s -- string describing selected pairs (default: self.selected_pairs) + + Return a dictionary with following keys: + + firstflags -- list of selection flags for first indices + secondflags -- list of selection flags for second indices + fixed_pair_string -- argument corrected to standard syntax + """ + if s is None: + s = self.selected_pairs + Natoms = len(self.initial) + # sets of first and second indices + firstflags = Natoms * [False] + secondflags = Natoms * [False] + # words of fixed_pair_string + words_fixed = [] + s1 = s.strip(" \t,") + words = re.split(r" *, *", s1) + for w in words: + wparts = w.split("-") + if len(wparts) != 2: + emsg = "Selection word '%s' must contain one dash '-'." % w + raise ControlValueError(emsg) + sel0 = self._parseAtomSelectionString(wparts[0]) + sel1 = self._parseAtomSelectionString(wparts[1]) + wfixed = sel0["fixedstring"] + "-" + sel1["fixedstring"] + words_fixed.append(wfixed) + for idx, flg in sel0["flags"].items(): + firstflags[idx] = flg + for idx, flg in sel1["flags"].items(): + secondflags[idx] = flg + # build returned dictionary + rv = { + "firstflags": firstflags, + "secondflags": secondflags, + "fixed_pair_string": ", ".join(words_fixed), + } + return rv
+ + +
+[docs] + def applyPairSelection(self, server, phaseidx): + """Apply pair selection for calculations of partial PDF. + + server -- instance of PdfFit engine + phaseidx -- phase index in PdfFit engine starting from 1 + """ + psf = self.getPairSelectionFlags() + idx = 0 + for iflag, jflag in zip(psf["firstflags"], psf["secondflags"]): + idx += 1 + server.selectAtomIndex(phaseidx, "i", idx, iflag) + server.selectAtomIndex(phaseidx, "j", idx, jflag) + return
+ + +
+[docs] + def getSelectedIndices(self, s): + """Indices of the atoms that match the specified selection string. + + s -- selection string consisting of one or more atom selection + words formatted as [!]{element|indexOrRange|all} + Example: "1:4, 7, Cl". + + Return a list of integers. + Raise ControlValueError for invalid selection string format. + """ + s1 = "".join(c for c in s if not c.isspace()) + words = s1.split(",") + indices = set() + for w in words: + asd = self._parseAtomSelectionString(w) + for idx, flg in asd["flags"].items(): + if flg: + indices.add(idx) + else: + indices.discard(idx) + rv = sorted(indices) + return rv
+ + + # Regular expression object for matching atom selection strings. + # Will be assign with the first call to _parseAtomSelectionString. + _rxatomselection = None + + def _parseAtomSelectionString(self, s): + """Process string that describes a set of atoms in the structure. + + s -- selection string formatted as [!]{element|indexOrRange|all} + "!" negates the selection, indexOrRange can be 1, 1:4, + where atom indices starts from 1, and "all" matches all atoms. + + Return a dictionary with following keys: + 'fixedstring' -- selection string adjusted to standard formatting + 'flags' -- dictionary of atom indices and boolean flags for + normal or negated selection. + Raise ControlValueError for invalid string format. + """ + # delayed initialization of the class variable + if self._rxatomselection is None: + FitStructure._rxatomselection = re.compile( + r""" + (?P<negate>!?) # exclamation point + (?:(?P<element>[a-zA-Z]+)$| # element|all or + (?P<start>\d+)(?P<stop>:\d+)?$ # number range + )""", + re.VERBOSE, + ) + assert self._rxatomselection + Natoms = len(self.initial) + flags = {} + rv = {"fixedstring": "", "flags": flags} + # allow empty string and return an empty flags dictionary + s1 = s.replace(" ", "") + if not s1: + return rv + mx = self._rxatomselection.match(s1) + if not mx: + emsg = "Invalid selection syntax in '%s'" % s + raise ControlValueError(emsg) + if mx.group("negate"): + rv["fixedstring"] = "!" + flg = not mx.group("negate") + # process atom type + if mx.group("element"): + elfixed = mx.group("element") + elfixed = elfixed[0:1].upper() + elfixed[1:].lower() + if elfixed == "All": + flags.update(dict.fromkeys(range(Natoms), flg)) + rv["fixedstring"] += elfixed.lower() + else: + for idx in range(Natoms): + if self.initial[idx].element == elfixed: + flags[idx] = flg + rv["fixedstring"] += elfixed + # process range + else: + lo = max(int(mx.group("start")) - 1, 0) + rv["fixedstring"] += mx.group("start") + hi = lo + 1 + if mx.group("stop"): + hi = int(mx.group("stop")[1:]) + rv["fixedstring"] += mx.group("stop") + hi = min(hi, Natoms) + flags.update(dict.fromkeys(range(lo, hi), flg)) + return rv + +
+[docs] + def copy(self, other=None): + """Copy self to other. if other is None, create new instance. + + other -- reference to other object + + returns reference to copied object + """ + # check arguments + if other is None: + other = FitStructure(self.name) + elif not isinstance(other, PDFStructure): + emsg = "other must be PDFStructure or FitStructure" + raise ControlTypeError(emsg) + # copy initial structure (self) to other + PDFStructure.copy(self, other) + # copy refined structure to other when it is FitStructure + if isinstance(other, FitStructure): + if self.refined is None: + other.refined = None + else: + other.refined = self.refined.copy(other.refined) + # copy constraints + other.constraints = copy.deepcopy(self.constraints) + other.selected_pairs = self.selected_pairs + return other
+ + +
+[docs] + def load(self, z, subpath): + """Load structure from a zipped project file. + + z -- zipped project file + subpath -- path to its own storage within project file + """ + # subpath = projname/fitname/structure/myname/ + from diffpy.pdfgui.control.pdfguicontrol import CtrlUnpickler + from diffpy.pdfgui.utils import asunicode + + subs = subpath.split("/") + rootDict = z.fileTree[subs[0]][subs[1]][subs[2]][subs[3]] + strudata = asunicode(z.read(subpath + "initial")) + self.initial.readStr(strudata, "pdffit") + # refined + if "refined" in rootDict: + self.refined = PDFStructure(self.name) + refdata = asunicode(z.read(subpath + "refined")) + self.refined.readStr(refdata, "pdffit") + # constraints + if "constraints" in rootDict: + self.constraints = CtrlUnpickler.loads(z.read(subpath + "constraints")) + translate = {"gamma": "delta1", "delta": "delta2", "srat": "sratio"} + for old, new in translate.items(): + if old in self.constraints: + self.constraints[new] = self.constraints.pop(old) + # selected_pairs + if "selected_pairs" in rootDict: + self.selected_pairs = asunicode(z.read(subpath + "selected_pairs")) + # sgoffset + if "sgoffset" in rootDict: + sgoffsetstr = asunicode(z.read(subpath + "sgoffset")) + sgoffset = [float(w) for w in sgoffsetstr.split()] + self.initial.pdffit["sgoffset"] = sgoffset + # custom_spacegroup + if "custom_spacegroup" in rootDict: + spkl = z.read(subpath + "custom_spacegroup") + self.custom_spacegroup = CtrlUnpickler.loads(spkl) + return
+ + +
+[docs] + def save(self, z, subpath): + """Save structure to a zipped project file. + + z -- zipped project file + subpath -- path to its own storage within project file + """ + from diffpy.pdfgui.utils import safeCPickleDumps + + z.writestr(subpath + "initial", self.initial.writeStr("pdffit")) + if self.refined: + z.writestr(subpath + "refined", self.refined.writeStr("pdffit")) + if self.constraints: + spkl = safeCPickleDumps(self.constraints) + z.writestr(subpath + "constraints", spkl) + z.writestr(subpath + "selected_pairs", self.selected_pairs) + # sgoffset + sgoffset = self.initial.pdffit.get("sgoffset", [0.0, 0.0, 0.0]) + sgoffsetstr = "%g %g %g" % tuple(sgoffset) + z.writestr(subpath + "sgoffset", sgoffsetstr) + if self.custom_spacegroup: + spkl = safeCPickleDumps(self.custom_spacegroup) + z.writestr(subpath + "custom_spacegroup", spkl) + return
+ + +
+[docs] + def getYNames(self): + """Get names of data item which can be plotted as y. + + returns a name str list + """ + return list(self.constraints.keys())
+ + +
+[docs] + def getXNames(self): + """Get names of data item which can be plotted as x. + + returns a name str list + """ + # in fact nothing + return []
+ + +
+[docs] + def getData(self, name, step=-1): + """Get self's data member. + + name -- data item name + step -- step info, it can be: + (1) a number ( -1 means latest step ): for single step + (2) a list of numbers: for multiple steps + (3) None: for all steps + + returns data object, be it a single number, a list, or a list of list + """ + # FIXME: for next plot interface, we need find how many steps the + # plotter is requiring for and make exact same number of copies of + # data by name + data = self.owner.getMetaData(name) + if data is not None: + return data + return self.owner._getData(self, name, step)
+
+ + + +# End of class FitStructure + +# Local helper functions ----------------------------------------------------- + + +def _makeParNames(sympars, parzeroindex): + """Return a tuple of (symbols, parvalues), where symbols is a list of + unique PDFFit parameter strings in "@%i" format and parvalues is a + dictionary of parameter indices and their values. The symbols have indices + 10n + (1, 2, 3) when referring to x, y, z, or 10n + (4, 5, 6, 7, 8, 9) when + referring to Uij. + + sympars -- pospars or Upars attribute of a SymmetryConstraints object + Must be a sequence of symbols and values. + parzeroindex -- the offset of all parameter indices. + Must be a multiple of 10. + + Return a tuple of (possymbols, Usymbols, parvalues). + This function is only used in FitStructure.applySymmetryConstraints method. + """ + if parzeroindex % 10: + raise ValueError("parzeroindex must be a multiple of 10.") + smbindex = { + "x": 1, + "y": 2, + "z": 3, + "U11": 4, + "U22": 5, + "U33": 6, + "U12": 7, + "U13": 8, + "U23": 9, + } + symbols = [] + parvalues = {} + for smb, value in sympars: + if smb[:1] == "U": + nsite = 10 * int(smb[3:]) + nvar = smbindex[smb[:3]] + else: + nsite = 10 * int(smb[1:]) + nvar = smbindex[smb[:1]] + pidx = parzeroindex + nsite + nvar + symbols.append("@%i" % pidx) + parvalues[pidx] = value + assert len(symbols) == len(parvalues) + rv = (symbols, parvalues) + return rv + + +# End of file +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/control/fitting.html b/_modules/diffpy/pdfgui/control/fitting.html new file mode 100644 index 00000000..5bd6b83a --- /dev/null +++ b/_modules/diffpy/pdfgui/control/fitting.html @@ -0,0 +1,1029 @@ + + + + + + + + diffpy.pdfgui.control.fitting — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.control.fitting

+#!/usr/bin/env python
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Jiwu Liu
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+from __future__ import print_function
+
+import pickle
+import threading
+import time
+
+from diffpy.pdfgui.control.controlerrors import ControlError, ControlStatusError, ControlValueError
+from diffpy.pdfgui.control.organizer import Organizer
+from diffpy.pdfgui.utils import safeCPickleDumps
+
+# helper routines to deal with PDFfit2 exceptions
+
+
+
+[docs] +def getEngineExceptions(): + """Return a tuple of possible exceptions from diffpy.pdffit2.pdffit2.""" + from diffpy.pdffit2.pdffit2 import ( + calculationError, + constraintError, + dataError, + structureError, + unassignedError, + ) + + engine_exceptions = ( + dataError, + unassignedError, + constraintError, + structureError, + calculationError, + ) + return engine_exceptions
+ + + +
+[docs] +def handleEngineException(error, gui=None): + """Common handler of PDFfit2 engine exceptions. + + error -- instance of PDFfit2 exception + gui -- reference to GUI when active + """ + errorInfo = "(%s)\n%s" % (error.__class__.__name__, str(error)) + # be more verbose for Singular matrix exception + if "singular matrix" in errorInfo.lower(): + errorInfo += ( + "\n\n" + "Common reasons are degeneracy in fit parameters,\n" + "zero thermal factors or fit range starting at zero." + ) + if gui: + gui.postEvent(gui.ERROR, "<Engine exception> %s" % errorInfo) + else: + print("<Engine exception> %s" % errorInfo) + return
+ + + +############################################################################## +
+[docs] +class Fitting(Organizer): + """Fitting is the class to control a PdfFit process running locally. + Fitting will start a new thread to interact with the PdfFit server. + + rw: fitness parameter + tolerancy: accuracy requirement + step: current refinement step + res: fitting result string + parameters: parameter dictionary + """ + + # Fit status -- mask 0xff + INITIALIZED = 1 + CONNECTED = 1 << 1 + CONFIGURED = 1 << 2 + DONE = 1 << 3 + + # JOB Status -- mask 0xff00 + VOID = 1 << 8 + QUEUED = 1 << 9 + RUNNING = 1 << 10 + PAUSED = 1 << 11 + +
+[docs] + class Worker(threading.Thread): + """Worker is the daemon thread of fitting.""" + + def __init__(self, fitting): + """Worker ( self, fitting) --> initialize. + + fitting -- fitting object + """ + threading.Thread.__init__(self) + self.fitting = fitting + +
+[docs] + def run(self): + """Overload function from Thread.""" + try: + self.fitting.run() + except ControlError as error: + gui = self.fitting.controlCenter.gui + if gui: + gui.postEvent(gui.ERROR, "<Fitting exception> %s" % error.info) + else: + print("<Fitting exception> %s" % error.info) + except getEngineExceptions() as error: + gui = self.fitting.controlCenter.gui + handleEngineException(error, gui) + return
+
+ + + def __init__(self, name): + """initialize. + + name -- name of this fitting + """ + Organizer.__init__(self, name) + + # Thread, status, and control variables + self.thread = None + self.pauseEvent = threading.Event() + self.fitStatus = Fitting.INITIALIZED + self.jobStatus = Fitting.VOID + self.stopped = False + self.paused = False + + # the PDFfit2 server instance. + self.server = None + + # public data members + self.step = 0 + self.parameters = {} + self.rw = 1.0 + self.tolerancy = 0.001 + self.res = "" + self.snapshots = [] + self.res = "" + + # All the calculated data are to be stored in a list. + # Such flat storage require unique index for each data item + # self.dataNameDict translate named data to an index + self.dataNameDict = {} + self.itemIndex = 0 + + def __changeStatus(self, fitStatus=None, jobStatus=None): + """Change current status of fitting. + + fitStatus -- new fitting status + jobStatus -- new thread status + """ + self.fitStatus = fitStatus or self.fitStatus + self.jobStatus = jobStatus or self.jobStatus + if fitStatus or jobStatus: # either of them is not None + gui = self.controlCenter.gui + if gui: + gui.postEvent(gui.UPDATE, self) + gui.postEvent(gui.OUTPUT, None) + + def _release(self): + """Release resources.""" + if self.server: # server has been allocated, we need free the memory + self.server.reset() + + def _getStrId(self): + """Make a string identifier. + + return value: string id + """ + return "f_" + self.name + +
+[docs] + def copy(self, other=None): + """Copy self to other. if other is None, create an instance. + + other -- ref to other object + return value: reference to copied object + """ + if other is None: + other = Fitting(self.name) + import copy + + Organizer.copy(self, other) + other.parameters = copy.deepcopy(self.parameters) + other.snapshots = copy.deepcopy(self.snapshots) + other.res = copy.deepcopy(self.res) + other.dataNameDict = copy.deepcopy(self.dataNameDict) + other.itemIndex = self.itemIndex + return other
+ + +
+[docs] + def load(self, z, subpath): + """Load data from a zipped project file. + + z -- zipped project file + subpath -- path to its own storage within project file + + returns a tree of internal hierarchy + """ + # subpath = projName/fitName/ + subs = subpath.split("/") + rootDict = z.fileTree[subs[0]][subs[1]] + + if "parameters" in rootDict: + from diffpy.pdfgui.control.pdfguicontrol import CtrlUnpickler + + self.parameters = CtrlUnpickler.loads(z.read(subpath + "parameters")) + if "steps" in rootDict: + self.itemIndex, self.dataNameDict, self.snapshots = pickle.loads( + z.read(subpath + "steps"), encoding="latin1" + ) + if "result" in rootDict: + self.rw, self.res = pickle.loads(z.read(subpath + "result"), encoding="latin1") + + return Organizer.load(self, z, subpath)
+ + +
+[docs] + def save(self, z, subpath): + """Save data from a zipped project file. + + z -- zipped project file + subpath -- path to its own storage within project file + """ + if self.parameters: + spkl = safeCPickleDumps(self.parameters) + z.writestr(subpath + "parameters", spkl) + if self.res: + spkl = safeCPickleDumps((self.rw, self.res)) + z.writestr(subpath + "result", spkl) + if self.snapshots: + spkl = safeCPickleDumps((self.itemIndex, self.dataNameDict, self.snapshots)) + z.writestr(subpath + "steps", spkl) + Organizer.save(self, z, subpath) + return
+ + +
+[docs] + def stripped(self): + """Make a copy stripped of all unpickleable data members. + The copy should be suitable for pickling and has the + following data members removed: + controlCenter, lock, pauseEvent, thread + + returns reference to stripped copy + """ + unpickleables = ("controlCenter", "lock", "pauseEvent", "thread") + naked = self.copy() + for a in unpickleables: + if a in self.__dict__: + delattr(naked, a) + return naked
+ + +
+[docs] + def updateParameters(self): + """Update parameters dictionary from active constraints. + + returns self.parameters + """ + # create dictionary of parameters used in constraints + cpars = {} + for struc in self.strucs: + for idx, par in struc.findParameters().items(): + if idx not in cpars: + cpars[idx] = par + for dataset in self.datasets: + for idx, par in dataset.findParameters().items(): + if idx not in cpars: + cpars[idx] = par + # add new parameters + for idx, par in cpars.items(): + if idx not in self.parameters: + self.parameters[idx] = par + # remove unused parameters + unused = [idx for idx in self.parameters if idx not in cpars] + for idx in unused: + del self.parameters[idx] + return self.parameters
+ + +
+[docs] + def applyParameters(self): + """Evaluate all constrained variables using current parameters.""" + for struc in self.strucs: + struc.applyParameters(self.parameters) + for dataset in self.datasets: + dataset.applyParameters(self.parameters) + return
+ + +
+[docs] + def changeParameterIndex(self, oldidx, newidx): + """Change a parameter index to a new value. + + This will replace all instances of one parameter name with + another in the containing fit. + """ + # Change the index in the current structure + for struc in self.strucs: + struc.changeParameterIndex(oldidx, newidx) + for dataset in self.datasets: + dataset.changeParameterIndex(oldidx, newidx) + + # Change the index if appears in linking equation initial values, e.g. + # '=thisfitname:oldidx' -> '=thisfitname:newidx' + fiteq = "=%s:%i" % (self.name, oldidx) + newfiteq = "=%s:%i" % (self.name, newidx) + + from diffpy.pdfgui.control.pdfguicontrol import pdfguicontrol + + fits = pdfguicontrol().fits + for fit in fits: + parameters = fit.parameters + for par in parameters.values(): + if par.initialStr() == fiteq: + par.setInitial(newfiteq) + + return
+ + +
+[docs] + def queue(self, enter=True): + """Queue or dequeue self. + + enter -- True to queue, False to dequeue + """ + if enter: + if self.jobStatus == Fitting.VOID: + self.__changeStatus(jobStatus=Fitting.QUEUED) + else: + if self.jobStatus == Fitting.QUEUED: + self.__changeStatus(jobStatus=Fitting.VOID)
+ + +
+[docs] + def getServer(self): + """Get a PDFfit2 instance either locally or remotely.""" + if self.fitStatus != Fitting.INITIALIZED: + return + # create a new instance of calculation server + from diffpy.pdffit2 import PdfFit + + self.server = PdfFit() + self.__changeStatus(fitStatus=Fitting.CONNECTED)
+ + +
+[docs] + def configure(self): + """Configure fitting.""" + if self.fitStatus != Fitting.CONNECTED: + return + + # make sure parameters are initialized + self.updateParameters() + self.server.reset() + for struc in self.strucs: + struc.clearRefined() + self.server.read_struct_string(struc.initial.writeStr("pdffit")) + for key, var in struc.constraints.items(): + self.server.constrain(key, var.formula) + + # phase parameters configured + + for dataset in self.datasets: + dataset.clearRefined() + self.server.read_data_string( + dataset.writeResampledObsStr(), + dataset.stype, + dataset.qmax, + dataset.qdamp, + ) + self.server.setvar("qbroad", dataset.qbroad) + for key, var in dataset.constraints.items(): + self.server.constrain(key, var.formula) + # Removed call to pdfrange call, because data were already + # resampled to at fit range. + # + # Pair selection applies only to the current dataset, + # therefore it has to be done here. + nstrucs = len(self.strucs) + for phaseidx, struc in zip(range(1, nstrucs + 1), self.strucs): + struc.applyPairSelection(self.server, phaseidx) + + for index, par in self.parameters.items(): + # clean any refined value + par.refined = None + self.server.setpar(index, par.initialValue()) # info[0] = init value + # fix if fixed. Note: all parameters are free after self.server.reset(). + if par.fixed: + self.server.fixpar(index) + + # build name dict + self.buildNameDict() + + self.__changeStatus(fitStatus=Fitting.CONFIGURED) + return
+ + +
+[docs] + def resetStatus(self): + """Reset status back to initialized.""" + self.snapshots = [] + self.step = 0 + if self.fitStatus == Fitting.INITIALIZED: + return # already reset + + # This status will mandate allocation of a new PdfFit instance + self.__changeStatus(fitStatus=Fitting.INITIALIZED)
+ + +
+[docs] + def run(self): + """Function to be run in daemon thread.""" + # Begin + self.__changeStatus(jobStatus=Fitting.RUNNING) + try: + for calc in self.calcs: + calc.start() + + while not self.stopped and self.datasets: + if not self.paused: + # quick check to make sure status is right + # will do nothing if status is CONFIGURED + self.getServer() + self.configure() + + # if self.refine_step return True, fitting is finished + if self.refine_step(): + break + else: + # Wait on an event, pause for a while + self.__changeStatus(jobStatus=Fitting.PAUSED) + self.pauseEvent.wait() + + # Recover from pause now + self.__changeStatus(jobStatus=Fitting.RUNNING) + + finally: + # whatever happened, resource should be released. + self._release() + + # job status should be changed because of thread exit + self.__changeStatus(jobStatus=Fitting.VOID) + return
+ + + def _configureBondCalculation(self, struc): + """Prepare server for bond angle or bond length calculation. + + struc -- instance of PDFStructure + + No return value. + """ + # struc can be handle to FitStructure.initial + # let's make sure it is synchronized with current parameters + self.applyParameters() + self.getServer() + self.server.reset() + strucstr = struc.writeStr("pdffit") + self.server.read_struct_string(strucstr) + return + +
+[docs] + def outputBondAngle(self, struc, i, j, k): + """Output bond angle defined by atoms i, j, k. The angle is calculated + using the shortest lengths ji and jk with respect to periodic boundary + conditions. + + struc -- instance of PDFStructure + i, j, k -- atom indices starting at 1 + + No return value. The result should be automatically added to + the Output Window, because all server output is sent there. + + Raise ControlValueError for invalid indices i, j, k. + """ + try: + self._configureBondCalculation(struc) + self.server.bang(i, j, k) + self._release() + except getEngineExceptions() as error: + gui = self.controlCenter.gui + handleEngineException(error, gui) + except ValueError as error: + raise ControlValueError(str(error)) + return
+ + +
+[docs] + def outputBondLengthAtoms(self, struc, i, j): + """Output shortest bond between atoms i, j. Periodic boundary + conditions are applied to find the shortest bond. + + struc -- instance of PDFStructure + i, j -- atom indices starting at 1 + + No return value. The result should be automatically added to + the Output Window, because all server output is sent there. + + Raise ControlValueError for invalid indices i, j. + """ + try: + self._configureBondCalculation(struc) + self.server.blen(i, j) + self._release() + except getEngineExceptions() as error: + gui = self.controlCenter.gui + handleEngineException(error, gui) + except ValueError as error: + raise ControlValueError(str(error)) + return
+ + +
+[docs] + def outputBondLengthTypes(self, struc, a1, a2, lb, ub): + """Output all a1-a2 bond lengths within specified range. + + struc -- instance of PDFStructure + a1 -- symbol of the first element in pair or "ALL" + a2 -- symbol of the second element in pair or "ALL" + lb -- lower bond length boundary + ub -- upper bond length boundary + + No return value. The result should be automatically added to + the Output Window, because all server output is sent there. + + Raise ControlValueError for invalid element symbols. + """ + try: + self._configureBondCalculation(struc) + self.server.blen(a1, a2, lb, ub) + self._release() + except getEngineExceptions() as error: + gui = self.controlCenter.gui + handleEngineException(error, gui) + except ValueError as error: + raise ControlValueError(str(error)) + return
+ + +
+[docs] + def pause(self, bPause=None): + """Pause ( self, bPause = None ) --> pause a fitting process. + + bPause -- True to pause, False to restart. If None, it will figure out + by itself. + """ + if bPause is None: + bPause = self.jobStatus == Fitting.RUNNING + + if bPause: + self.paused = True + else: + self.paused = False + self.pauseEvent.set()
+ + +
+[docs] + def start(self): + """Start fitting.""" + # check if paused + if self.jobStatus == Fitting.PAUSED: + self.pause(False) + return + + # clean up control variable + self.stopped = False + self.paused = False + self.resetStatus() + + # Restart fitting require another thread instance. + self.thread = Fitting.Worker(self) + self.thread.start()
+ + +
+[docs] + def stop(self): + """Stop the fitting.""" + self.stopped = True + + # wake up daemon thread if it is paused + if self.jobStatus == Fitting.PAUSED: + self.pause(False)
+ + +
+[docs] + def isThreadRunning(self): + """Check if fitting thread is running. + + return: True if running, False otherwise + """ + return self.thread is not None and self.thread.is_alive()
+ + +
+[docs] + def join(self): + """Wait for current fitting to finish.""" + if self.thread: + self.thread.join() + self.thread = None
+ + +
+[docs] + def close(self, force=False): + """Close up the fitting in order to exit. + + force -- if force to exit + """ + if force: + if self.isThreadRunning(): + self.stop() + # NOTE: Not waiting for thread to stop. There's no graceful + # way while user choose to stop forcefully + else: + if self.isThreadRunning(): + raise ControlStatusError("Fitting: Fitting %s is still running" % self.name) + if self.thread is not None: + self.thread.join()
+ + +
+[docs] + def buildNameDict(self): + """Build up a data name dictionary, which will map data name to a + unique index. + + The private dataNameDict has such structure: + { 'd_data1':{'Gobs':12, 'Gcalc':11, ....}, + 'd_data2':{'Gobs':10, 'Gcalc':9, ....}, + ... + 'p_ph1':{'lat(1)':1,'lat(2)':2, .....}, + 'p_ph1':{'lat(1)':3,'lat(2)':4, .....}, + ... + 'f_fit':{'rw':100, 1:101, 2:102} + } + + The value of each sub-dict is the corresponding index of this data + item in the snapshot. + The prefix d_ p_ f_ make dataset,struc,fitname unique within the + shared name space of dictionary + """ + self.itemIndex = 0 + dataNameDict = {} + + # dataNameDict for datasets + for dataset in self.datasets: + id = dataset._getStrId() + dataNameDict[id] = {} + for itemName in list(dataset.constraints.keys()) + ["Gcalc", "crw"]: + dataNameDict[id][itemName] = self.itemIndex + self.itemIndex += 1 + + # dataNameDict for strucs + for struc in self.strucs: + id = struc._getStrId() + dataNameDict[id] = {} + for itemName in struc.constraints.keys(): + dataNameDict[id][itemName] = self.itemIndex + self.itemIndex += 1 + + # dataNameDict for self + id = self._getStrId() + dataNameDict[id] = {} + dataNameDict[id]["rw"] = self.itemIndex + self.itemIndex += 1 + for parameter in self.parameters.keys(): + dataNameDict[id][parameter] = self.itemIndex + self.itemIndex += 1 + + # assign to self + self.dataNameDict = dataNameDict
+ + +
+[docs] + def appendStep(self, source): + """After a refinement step is done, append all data from self to the + historical storage, i.e., self.snapshots. + + source -- where to get the fitted data, in deed it's a PdfFit2 instance + """ + # self.itemIndex should store total number of items + snapshot = [None] * self.itemIndex + + # update datasets + seq = 1 + for dataset in self.datasets: + id = dataset._getStrId() + # set current dataset + source.setdata(seq) + # use nameDict for current dataset + nameDict = self.dataNameDict[id] + # get values for constrained variables + for name in dataset.constraints.keys(): + snapshot[nameDict[name]] = source.getvar(name) + + snapshot[nameDict["Gcalc"]] = dataset.Gcalc + snapshot[nameDict["crw"]] = dataset.crw + seq += 1 + + # update strucs + seq = 1 + for struc in self.strucs: + id = struc._getStrId() + # set current struc + source.setphase(seq) + # use nameDict for current struc + nameDict = self.dataNameDict[id] + # get values for constrained variables + for name in struc.constraints.keys(): + snapshot[nameDict[name]] = source.getvar(name) + seq += 1 + + # update global data + id = self._getStrId() + nameDict = self.dataNameDict[id] + snapshot[nameDict["rw"]] = self.rw + for parameter in self.parameters.keys(): + snapshot[nameDict[parameter]] = source.getpar(parameter) + + self.snapshots.append(snapshot)
+ + +
+[docs] + def refine_step(self): + """Run a single step of the fit. + + return value: True if refinement is finished, otherwise False + """ + if self.fitStatus == Fitting.DONE: + # do nothing but return finished + return True + + finished = self.server.refine_step(self.tolerancy) + + # get fitted data + idataset = 1 + for dataset in self.datasets: + dataset.obtainRefined(self.server, idataset) + idataset += 1 + + # get refined structure + istruc = 1 + for struc in self.strucs: + struc.obtainRefined(self.server, istruc) + istruc += 1 + + # update parameters + for idx, par in self.parameters.items(): + par.refined = self.server.getpar(idx) + + self.rw = self.server.getrw() + + self.step += 1 + self.appendStep(self.server) + + # update plots and structure renderer + gui = self.controlCenter.gui + if gui: + gui.postEvent(gui.OUTPUT, None) + gui.postEvent(gui.PLOTNOW, self) + + if finished: + self.res = "* %s\n\n" % time.ctime() + self.server.save_res_string() + self.__changeStatus(fitStatus=Fitting.DONE) + + return finished
+ + +
+[docs] + def getYNames(self): + """Get names of data item which can be plotted as y. + + returns a name str list + """ + names = list(self.parameters.keys()) + names.append("rw") + return names
+ + +
+[docs] + def getXNames(self): + """Get names of data item which can be plotted as x. + + returns a name str list + """ + return []
+ + +
+[docs] + def getData(self, name, step=-1): + """Get self's data member. + + name -- data item name + step -- step info, it can be: + (1) a number ( -1 means latest step ): for single step + (2) a list of numbers: for multiple steps + (3) None: for all steps + + returns data object, be it a single number, a list, or a list of list + """ + # FIXME: for next plot interface, we need find how many steps the + # plotter is requiring for and make exact same number of copies of + # data by name + data = self.getMetaData(name) + if data is not None: + return data + + return self._getData(self, name, step)
+ + +
+[docs] + def getMetaDataNames(self): + """Return all applicable meta data names.""" + names = [] + for dataset in self.datasets: + # build up the name list + if not names: + names = list(dataset.metadata.keys()) + else: + for name in names[:]: + if name not in dataset.metadata: + names.remove(name) + return names
+ + +
+[docs] + def getMetaData(self, name): + """Get meta data value. + + name -- meta data name + returns meta data value + """ + try: + return self.datasets[0].metadata[name] + except (KeyError, IndexError): + return None
+ + + def _getData(self, id, name, step=-1): + """Get any data member from snapshots. + + id -- reference to a Fitting/Calculation/Phase/DataSet object + name -- data item name + step -- step info, it can be: + (1) a number ( -1 means latest step ): for single step + (2) a list of numbers: for multiple steps + (3) None: for all steps + + returns data object, be it a single number, a list, or a list of list + """ + # find the unique index + if len(self.snapshots) == 0: + return None + try: + # if it is a 'int', it must be parameter. So only fitting has its value. + if isinstance(name, int): + id = self + nameDict = self.dataNameDict[id._getStrId()] + index = nameDict[name] + except KeyError: + return None # data is not ready + + if step is None: + return [snapshot[index] for snapshot in self.snapshots] + elif isinstance(step, list): + return [self.snapshots[i][index] for i in step] + else: + return self.snapshots[step][index]
+ + + +# End of file +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/control/organizer.html b/_modules/diffpy/pdfgui/control/organizer.html new file mode 100644 index 00000000..6c78ac4b --- /dev/null +++ b/_modules/diffpy/pdfgui/control/organizer.html @@ -0,0 +1,444 @@ + + + + + + + + diffpy.pdfgui.control.organizer — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.control.organizer

+#!/usr/bin/env python
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Jiwu Liu
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+from diffpy.pdfgui.control.calculation import Calculation
+from diffpy.pdfgui.control.controlerrors import ControlTypeError
+from diffpy.pdfgui.control.fitdataset import FitDataSet
+from diffpy.pdfgui.control.fitstructure import FitStructure
+from diffpy.pdfgui.control.pdfcomponent import PDFComponent
+
+
+# Search datasets for spdiameter and its constraints
+
+[docs] +def spd_assigned(ds): + return bool(ds.spdiameter)
+ + + +
+[docs] +def spd_constrained(ds): + return "spdiameter" in ds.constraints
+ + + +
+[docs] +class Organizer(PDFComponent): + """Base class for Fitting. It holds separate lists of datasets, strucs and + calculations. + + datasets: dataset list + strucs: structure list + calcs: calculation list + """ + + def __init__(self, name): + """initialize. + + name -- component name + """ + from diffpy.pdfgui.control.pdflist import PDFList + + PDFComponent.__init__(self, name) + + self.datasets = PDFList() + self.strucs = PDFList() + self.calcs = PDFList() + + # self.metadata is created but not pickled only for the purpose + # of plotting. It holds common metadata from all its datasets + self.metadata = {} + + # controlCenter is the reference to global PDFGuiControl object + from diffpy.pdfgui.control.pdfguicontrol import pdfguicontrol + + self.controlCenter = pdfguicontrol() + + def __findList(self, id): + if isinstance(id, FitDataSet): + return self.datasets + elif isinstance(id, FitStructure): + return self.strucs + elif isinstance(id, Calculation): + return self.calcs + else: + emsg = "Unknown type object '%s'" % id.name + raise ControlTypeError(emsg) + +
+[docs] + def add(self, id, position=None): + """Add structure/dataset/calculation. + + id -- reference to structure/dataset/calculation + position -- position to insert, by default the last one + """ + objList = self.__findList(id) + if position is None: + position = len(objList) + objList.insert(position, id) + + # successfully added, set the object owner + id.owner = self
+ + +
+[docs] + def remove(self, id): + """Remove structure/dataset/calculation. + + id -- reference to structure/dataset/calculation + """ + objList = self.__findList(id) + objList.remove(id) + return id
+ + +
+[docs] + def rename(self, id, newname): + """Rename structure/dataset/calculation. + + id -- reference to structure/dataset/calculation + newname -- new name to be given + """ + objList = self.__findList(id) + objList.rename(id.name, newname)
+ + +
+[docs] + def index(self, id): + """Find the position of item in the list. + + id -- id of object + return : object position + """ + objList = self.__findList(id) + return objList.index(id.name)
+ + +
+[docs] + def hasStructures(self): + """Check to see if there are structures.""" + return len(self.strucs) > 0
+ + +
+[docs] + def getStructure(self, pos): + """Get structure by position. + + pos -- the position of structure in the list + """ + # The function can only be called by gui code. So don't catch IndexError + # Any IndexError is a program bug thus should be propagated as is. + return self.strucs[pos]
+ + +
+[docs] + def hasDataSets(self): + """Check to see if there are datasets.""" + return len(self.datasets) > 0
+ + +
+[docs] + def getDataSet(self, pos): + """Get dataset by position. + + pos -- the position of dataset in the list + """ + # The function can only be called by gui code. So don't catch IndexError + # Any IndexError is a program bug thus should be propagated as is. + return self.datasets[pos]
+ + +
+[docs] + def hasCalculations(self): + """Check to see if there are calculations.""" + return len(self.calcs) > 0
+ + +
+[docs] + def getCalculation(self, pos): + """Get calculation by position. + + pos -- the position of calculation in the list + """ + # The function can only be called by gui code. So don't catch IndexError + # Any IndexError is a program bug thus should be propagated as is. + return self.calcs[pos]
+ + +
+[docs] + def load(self, z, subpath): + """Load data from a zipped project file. + + z -- zipped project file + subpath -- path to its own storage within project file + + returns a tree of internal hierarchy + """ + # subpath = projName/myName/ + from urllib.parse import unquote_plus + + subs = subpath.split("/") + rootDict = z.fileTree[subs[0]][subs[1]] + if "structure" in rootDict: + for strucName in rootDict["structure"].keys(): + struc = FitStructure(unquote_plus(strucName)) + struc.load(z, subpath + "structure/" + strucName + "/") + self.add(struc) + + if "dataset" in rootDict: + for datasetName in rootDict["dataset"].keys(): + dataset = FitDataSet(unquote_plus(datasetName)) + dataset.load(z, subpath + "dataset/" + datasetName + "/") + self.add(dataset) + + if "calculation" in rootDict: + for calcName in rootDict["calculation"].keys(): + calc = Calculation(unquote_plus(calcName)) + calc.load(z, subpath + "calculation/" + calcName + "/") + self.add(calc) + + self.__forward_spdiameter() + + return self.organization()
+ + +
+[docs] + def save(self, z, subpath): + """Save data from a zipped project file. + + z -- zipped project file + subpath -- path to its own storage within project file + """ + # strucs and datasets + from urllib.parse import quote_plus + + for struc in self.strucs: + struc.save(z, subpath + "structure/" + quote_plus(struc.name) + "/") + for dataset in self.datasets: + dataset.save(z, subpath + "dataset/" + quote_plus(dataset.name) + "/") + for calc in self.calcs: + calc.save(z, subpath + "calculation/" + quote_plus(calc.name) + "/") + return
+ + +
+[docs] + def copy(self, other=None): + """Copy self to other. if other is None, create an instance. + + other -- ref to other object + returns reference to copied object + """ + if other is None: + other = Organizer(self.name) + + for dataset in self.datasets: + other.add(dataset.copy()) + for struc in self.strucs: + other.add(struc.copy()) + for calc in self.calcs: + other.add(calc.copy()) + return other
+ + +
+[docs] + def organization(self): + """Get internal organization. + + returns a tree of internal hierarchy + """ + org = [None] * 4 + org[0] = self + org[1] = [] + for dataset in self.datasets: + org[1].append((dataset.name, dataset)) + org[2] = [] + for struc in self.strucs: + org[2].append((struc.name, struc)) + org[3] = [] + for calc in self.calcs: + org[3].append((calc.name, calc)) + + return org
+ + + def __forward_spdiameter(self): + """Copy spdiameter value loaded from fit or calculation to phase. + + This method takes care of loading old PDFgui projects where + spdiameter belonged to FitDataSet or Calculation classes. It + should be called only from the Organizer.load method. + """ + # Jump out if any of structures has spdiameter set + for stru in self.strucs: + if stru.getvar("spdiameter"): + return + + # Figure out the value and constraint for spdiameter. + # The highest priority is for a dataset with constrained spdiameter, + # then for dataset with assigned spdiameter and finally from + # a calculation. + spd_val = spd_cns = None + constrained_datas = list(filter(spd_constrained, self.datasets)) + assigned_datas = list(filter(spd_assigned, self.datasets)) + assigned_calcs = list(filter(spd_assigned, self.calcs)) + if constrained_datas: + spd_val = constrained_datas[0].spdiameter + spd_cns = constrained_datas[0].constraints["spdiameter"] + elif assigned_datas: + spd_val = assigned_datas[0].spdiameter + elif assigned_calcs: + spd_val = assigned_calcs[0].spdiameter + # assign spd_val to all structures that don't have it set + for stru in self.strucs: + if spd_val and not stru.getvar("spdiameter"): + stru.setvar("spdiameter", spd_val) + if spd_cns: + stru.constraints.setdefault("spdiameter", spd_cns) + # finally remove any spdiameter constraints from all datasets + for ds in self.datasets: + ds.constraints.pop("spdiameter", None) + return
+ + + +# End of class Organizer + +# simple test code +if __name__ == "__main__": + Organizer("name") + +# End of file +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/control/parameter.html b/_modules/diffpy/pdfgui/control/parameter.html new file mode 100644 index 00000000..b3a416b3 --- /dev/null +++ b/_modules/diffpy/pdfgui/control/parameter.html @@ -0,0 +1,309 @@ + + + + + + + + diffpy.pdfgui.control.parameter — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.control.parameter

+#!/usr/bin/env python
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Pavol Juhas
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+"""Class Parameter for handling one refined parameter To be stored in
+Fitting.parameters { idx : parameter } dictionary."""
+
+from diffpy.pdfgui.control.controlerrors import (
+    ControlError,
+    ControlKeyError,
+    ControlRuntimeError,
+    ControlTypeError,
+)
+
+
+
+[docs] +class Parameter: + """Parameter is class for value and properties of refined parameter. + Because the initial value of Parameter may come from another Fitting, it is + accessed by setInitial(), initialStr() and initialValue() methods. + + Data members: + idx -- integer identifier of this parameter in PdfFit + name -- optional description + refined -- refined value of the parameter, float or None. + fixed -- flag for fixing the parameter in refinement [False] + + Private members: + __initial -- stores the initial value, float, or "=fitname:idx" string + __fitrepr -- None or string representation of Fitting instance + """ + + # fits should reference PDFGuiControl.fits + + def __init__(self, idx, initial=0.0): + """Initialize new parameter. + + idx -- idx of this parameter in PdfFit + initial -- optional initial value of the parameter. + It can be float, Fitting, "=fitname" or "=fitname:idx" string. + """ + self.idx = idx + self.name = "" + self.refined = None + self.fixed = False + self.__initial = None + self.__fitrepr = None + self.setInitial(initial) + return + +
+[docs] + def setInitial(self, initial): + """Set initial value to float or refined value from another Fitting. + + initial -- initial value, it can be something convertible to float, + Fitting reference or string in "=fitname" or + "=fitname:idx" format. + """ + self.__fitrepr = None + from diffpy.pdfgui.control.fitting import Fitting + + try: + self.__initial = float(initial) + return + except (ValueError, TypeError): + pass + if isinstance(initial, Fitting): + self.__initial = "=" + initial.name + self.__fitrepr = repr(initial) + elif isinstance(initial, str) and initial[:1] == "=": + self.__initial = initial + self.__findLinkedFitting() + else: + raise ControlTypeError("invalid type of Parameter initial value") + return
+ + +
+[docs] + def initialStr(self): + """Convert initial value to string. + + returns string in "=fitname:idx" or "%f" format + """ + if isinstance(self.__initial, float): + s = str(self.__initial) + else: + self.__findLinkedFitting() + s = self.__initial + return s
+ + +
+[docs] + def initialValue(self): + """Convert initial value to float. + For linked parameters it may raise: + ControlKeyError if source Fitting does not exist + KeyError when parameter does not exist + ControlRunTimeError for self-dependent parameters + + returns the initial value + """ + if isinstance(self.__initial, float): + value = self.__initial + else: + try: + value = self.__getLinkedValue() + except RuntimeError as v: + # we will catch only recursion RuntimeError + if "maximum recursion" in str(v): + raise ControlRuntimeError("self-dependent parameter") + # other RuntimeError should be left alone + else: + raise + return float(value)
+ + + def __getLinkedValue(self): + """Private retrieval of parameter value from linked Fitting.""" + # Check to see if the fit name has a ':' in it + isplit = self.__initial.split(":") + # Who needs regular expressions? + try: + if len(isplit) == 1: + srcidx = self.idx + fitname = self.__initial[1:] + else: + srcidx = int(isplit[-1]) + fitname = (":".join(isplit[:-1]))[1:] + except ValueError: + # __initial should be in the form "=fitname[:srcidx]" + raise ControlError("Malformed linked parameter %s" % self.__initial) + srcfit = self.__findLinkedFitting() + if srcfit is None: + raise ControlKeyError("Fitting '%s' does not exist" % fitname) + # Check to see if srcfit has parameter srcidx + try: + srcpar = srcfit.parameters[srcidx] + except KeyError: + raise ControlKeyError("Fitting '%s' has no parameter %s" % (fitname, srcidx)) + + if srcpar.refined is not None: + value = srcpar.refined + elif isinstance(srcpar.__initial, float): + value = srcpar.__initial + else: + value = srcpar.__getLinkedValue() + return value + + def __findLinkedFitting(self): + """Private search for linked Fitting by name and by representation. + Should be called only when initial value is linked to another Fitting. + Updates self.__initial and self.__fitrepr. + + returns reference to Fitting when found or None + """ + # Check to see if the fit name has a ':' in it + isplit = self.__initial.split(":") + try: + srcidx = int(isplit[-1]) + fitname = (":".join(isplit[:-1]))[1:] + except ValueError: + fitname = self.__initial[1:] + srcidx = self.idx + self.__initial += ":%i" % srcidx + from diffpy.pdfgui.control.pdfguicontrol import pdfguicontrol + + fits = pdfguicontrol().fits + fitnames = [f.name for f in fits] + fitrepres = [repr(f) for f in fits] + # first find linked fitting by name + if fitname in fitnames: + idx = fitnames.index(fitname) + self.__fitrepr = fitrepres[idx] + ref = fits[idx] + # if not found by name, look up by representation + elif self.__fitrepr in fitrepres: + idx = fitrepres.index(self.__fitrepr) + self.__initial = "=%s:%i" % (fitnames[idx], srcidx) + ref = fits[idx] + # here self.__initial was not found, but let it pass + # maybe the linked fitting will be defined later + else: + self.__fitrepr = None + ref = None + return ref
+ + + +# End of class Parameter +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/control/pdfcomponent.html b/_modules/diffpy/pdfgui/control/pdfcomponent.html new file mode 100644 index 00000000..850e33cd --- /dev/null +++ b/_modules/diffpy/pdfgui/control/pdfcomponent.html @@ -0,0 +1,147 @@ + + + + + + + + diffpy.pdfgui.control.pdfcomponent — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.control.pdfcomponent

+#!/usr/bin/env python
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Jiwu Liu
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+
+
+[docs] +class PDFComponent(object): + """Common base class.""" + + def __init__(self, name): + """initialize. + + name -- object name + """ + self.name = name + +
+[docs] + def close(self, force=False): + """Close myself. + + force -- if forcibly (no wait) + """ + pass
+
+ + + +# End of file +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/control/pdfdataset.html b/_modules/diffpy/pdfgui/control/pdfdataset.html new file mode 100644 index 00000000..c0730d66 --- /dev/null +++ b/_modules/diffpy/pdfgui/control/pdfdataset.html @@ -0,0 +1,516 @@ + + + + + + + + diffpy.pdfgui.control.pdfdataset — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.control.pdfdataset

+#!/usr/bin/env python
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Pavol Juhas
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+"""Class PDFDataSet for experimental PDF data."""
+
+import copy
+import os.path
+import re
+import time
+from getpass import getuser
+
+from diffpy.pdfgui.control.controlerrors import ControlFileError, ControlKeyError
+from diffpy.pdfgui.control.pdfcomponent import PDFComponent
+
+
+
+[docs] +class PDFDataSet(PDFComponent): + """PDFDataSet is a class for experimental PDF data. + + Data members: + robs -- list of observed r points + Gobs -- list of observed G values + drobs -- list of standard deviations of robs + dGobs -- list of standard deviations of Gobs + stype -- scattering type, 'X' or 'N' + qmax -- maximum value of Q in inverse Angstroms. Termination + ripples are neglected for qmax=0. + qdamp -- specifies width of Gaussian damping factor in pdf_obs due + to imperfect Q resolution + qbroad -- quadratic peak broadening factor related to dataset + spdiameter -- particle diameter for shape damping function + Note: This attribute was moved to PDFStructure. + It is kept for backward compatibility when reading + PDFgui project files. + dscale -- scale factor of this dataset + rmin -- same as robs[0] + rmax -- same as robs[-1] + filename -- set to absolute path after reading from file + metadata -- dictionary for other experimental conditions, such as + temperature or doping + + Global member: + persistentItems -- list of attributes saved in project file + refinableVars -- set (dict) of refinable variable names. + """ + + persistentItems = [ + "robs", + "Gobs", + "drobs", + "dGobs", + "stype", + "qmax", + "qdamp", + "qbroad", + "dscale", + "rmin", + "rmax", + "metadata", + ] + refinableVars = dict.fromkeys(("qdamp", "qbroad", "dscale")) + + def __init__(self, name): + """Initialize. + + name -- name of the data set. It must be a unique identifier. + """ + PDFComponent.__init__(self, name) + self.clear() + return + +
+[docs] + def clear(self): + """Reset all data members to initial empty values.""" + self.robs = [] + self.Gobs = [] + self.drobs = [] + self.dGobs = [] + self.stype = "X" + # user must specify qmax to get termination ripples + self.qmax = 0.0 + self.qdamp = 0.001 + self.qbroad = 0.0 + self.spdiameter = None + self.dscale = 1.0 + self.rmin = None + self.rmax = None + self.filename = None + self.metadata = {} + return
+ + +
+[docs] + def setvar(self, var, value): + """Assign data member using PdfFit-style variable. Used by + applyParameters(). + + var -- string representation of dataset PdfFit variable. + Possible values: qdamp, qbroad, dscale + value -- new value of the variable + """ + barevar = var.strip() + fvalue = float(value) + if barevar in PDFDataSet.refinableVars: + setattr(self, barevar, fvalue) + else: + emsg = "Invalid PdfFit dataset variable %r" % barevar + raise ControlKeyError(emsg) + return
+ + +
+[docs] + def getvar(self, var): + """Obtain value corresponding to PdfFit dataset variable. Used by + findParameters(). + + var -- string representation of dataset PdfFit variable. + Possible values: qdamp, qbroad, dscale + + returns value of var + """ + barevar = var.strip() + if barevar in PDFDataSet.refinableVars: + value = getattr(self, barevar) + else: + emsg = "Invalid PdfFit dataset variable %r" % barevar + raise ControlKeyError(emsg) + return value
+ + +
+[docs] + def read(self, filename): + """Load data from PDFGetX2 or PDFGetN gr file. + + filename -- file to read from + + returns self + """ + try: + with open(filename) as fp: + self.readStr(fp.read()) + except PDFDataFormatError as err: + basename = os.path.basename(filename) + emsg = ("Could not open '%s' due to unsupported file format " + "or corrupted data. [%s]") % ( + basename, + err, + ) + raise ControlFileError(emsg) + self.filename = os.path.abspath(filename) + return self
+ + +
+[docs] + def readStr(self, datastring): + """Read experimental PDF data from a string. + + datastring -- string of raw data + + returns self + """ + self.clear() + # useful regex patterns: + rx = {"f": r"[-+]?(\d+(\.\d*)?|\d*\.\d+)([eE][-+]?\d+)?"} + # find where does the data start + res = re.search(r"^#+ start data\s*(?:#.*\s+)*", datastring, re.M) + # start_data is position where the first data line starts + if res: + start_data = res.end() + else: + # find line that starts with a floating point number + regexp = r"^\s*%(f)s" % rx + res = re.search(regexp, datastring, re.M) + if res: + start_data = res.start() + else: + start_data = 0 + header = datastring[:start_data] + databody = datastring[start_data:].strip() + + # find where the metadata starts + metadata = "" + res = re.search(r"^#+\ +metadata\b\n", header, re.M) + if res: + metadata = header[res.end() :] + header = header[: res.start()] + + # parse header + # stype + if re.search("(x-?ray|PDFgetX)", header, re.I): + self.stype = "X" + elif re.search("(neutron|PDFgetN)", header, re.I): + self.stype = "N" + # qmax + regexp = r"\bqmax *= *(%(f)s)\b" % rx + res = re.search(regexp, header, re.I) + if res: + self.qmax = float(res.groups()[0]) + # qdamp + regexp = r"\b(?:qdamp|qsig) *= *(%(f)s)\b" % rx + res = re.search(regexp, header, re.I) + if res: + self.qdamp = float(res.groups()[0]) + # qbroad + regexp = r"\b(?:qbroad|qalp) *= *(%(f)s)\b" % rx + res = re.search(regexp, header, re.I) + if res: + self.qbroad = float(res.groups()[0]) + # spdiameter + regexp = r"\bspdiameter *= *(%(f)s)\b" % rx + res = re.search(regexp, header, re.I) + if res: + self.spdiameter = float(res.groups()[0]) + # dscale + regexp = r"\bdscale *= *(%(f)s)\b" % rx + res = re.search(regexp, header, re.I) + if res: + self.dscale = float(res.groups()[0]) + # temperature + regexp = r"\b(?:temp|temperature|T)\ *=\ *(%(f)s)\b" % rx + res = re.search(regexp, header) + if res: + self.metadata["temperature"] = float(res.groups()[0]) + # doping + regexp = r"\b(?:x|doping)\ *=\ *(%(f)s)\b" % rx + res = re.search(regexp, header) + if res: + self.metadata["doping"] = float(res.groups()[0]) + + # parsing general metadata + if metadata: + regexp = r"\b(\w+)\ *=\ *(%(f)s)\b" % rx + while True: + res = re.search(regexp, metadata, re.M) + if res: + self.metadata[res.groups()[0]] = float(res.groups()[1]) + metadata = metadata[res.end() :] + else: + break + + # read actual data - robs, Gobs, drobs, dGobs + inf_or_nan = re.compile("(?i)^[+-]?(NaN|Inf)\\b") + has_drobs = True + has_dGobs = True + # raise PDFDataFormatError if something goes wrong + try: + for line in databody.split("\n"): + v = line.split() + # there should be at least 2 value in the line + self.robs.append(float(v[0])) + self.Gobs.append(float(v[1])) + # drobs is valid if all values are defined and positive + has_drobs = has_drobs and len(v) > 2 and not inf_or_nan.match(v[2]) + if has_drobs: + v2 = float(v[2]) + has_drobs = v2 > 0.0 + self.drobs.append(v2) + # dGobs is valid if all values are defined and positive + has_dGobs = has_dGobs and len(v) > 3 and not inf_or_nan.match(v[3]) + if has_dGobs: + v3 = float(v[3]) + has_dGobs = v3 > 0.0 + self.dGobs.append(v3) + if not has_drobs: + self.drobs = len(self.robs) * [0.0] + if not has_dGobs: + self.dGobs = len(self.robs) * [0.0] + except (ValueError, IndexError) as err: + raise PDFDataFormatError(err) + self.rmin = self.robs[0] + self.rmax = self.robs[-1] + if not has_drobs: + self.drobs = len(self.robs) * [0.0] + if not has_dGobs: + self.dGobs = len(self.robs) * [0.0] + return self
+ + +
+[docs] + def write(self, filename): + """Write experimental PDF data to a file. + + filename -- name of file to write to + + No return value. + """ + txt = self.writeStr() + f = open(filename, "w") + f.write(txt) + f.close() + return
+ + +
+[docs] + def writeStr(self): + """String representation of experimental PDF data. + + Return data string. + """ + lines = [] + # write metadata + lines.extend( + [ + "History written: " + time.ctime(), + "produced by " + getuser(), + "##### PDFgui", + ] + ) + # stype + if self.stype == "X": + lines.append("stype=X x-ray scattering") + elif self.stype == "N": + lines.append("stype=N neutron scattering") + # qmax + if self.qmax == 0: + qmax_line = "qmax=0 correction not applied" + else: + qmax_line = "qmax=%.2f" % self.qmax + lines.append(qmax_line) + # qdamp + lines.append("qdamp=%g" % self.qdamp) + # qbroad + lines.append("qbroad=%g" % self.qbroad) + # dscale + lines.append("dscale=%g" % self.dscale) + # metadata + if len(self.metadata) > 0: + lines.append("# metadata") + for k, v in self.metadata.items(): + lines.append("%s=%s" % (k, v)) + # write data: + lines.append("##### start data") + lines.append("#L r(A) G(r) d_r d_Gr") + for i in range(len(self.robs)): + lines.append("%g %g %g %g" % (self.robs[i], self.Gobs[i], self.drobs[i], self.dGobs[i])) + # that should be it + datastring = "\n".join(lines) + "\n" + return datastring
+ + +
+[docs] + def copy(self, other=None): + """Copy self to other. if other is None, create new instance. + + other -- ref to other object + returns reference to copied object + """ + if other is None: + other = PDFDataSet(self.name) + elif isinstance(other, PDFDataSet): + other.clear() + # some attributes can be assigned, e.g., robs, Gobs, drobs, dGobs are + # constant so they can be shared between copies. + assign_attributes = ( + "robs", + "Gobs", + "drobs", + "dGobs", + "stype", + "qmax", + "qdamp", + "qbroad", + "dscale", + "rmin", + "rmax", + "filename", + ) + # for others we will assign a copy + copy_attributes = ("metadata",) + for a in assign_attributes: + setattr(other, a, getattr(self, a)) + for a in copy_attributes: + setattr(other, a, copy.deepcopy(getattr(self, a))) + return other
+
+ + + +# End of class PDFDataSet + + +
+[docs] +class PDFDataFormatError(Exception): + """Exception class marking failure to process PDF data string.""" + + pass
+ + + +# End of file +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/control/pdfguicontrol.html b/_modules/diffpy/pdfgui/control/pdfguicontrol.html new file mode 100644 index 00000000..ba5e862f --- /dev/null +++ b/_modules/diffpy/pdfgui/control/pdfguicontrol.html @@ -0,0 +1,776 @@ + + + + + + + + diffpy.pdfgui.control.pdfguicontrol — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.control.pdfguicontrol

+#!/usr/bin/env python
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Jiwu Liu
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+from __future__ import print_function
+
+import io
+import os
+import pickle
+import sys
+import threading
+import time
+from urllib.parse import quote_plus
+
+from diffpy.pdfgui.control.calculation import Calculation
+from diffpy.pdfgui.control.controlerrors import ControlError, ControlFileError, ControlTypeError
+from diffpy.pdfgui.control.fitdataset import FitDataSet
+from diffpy.pdfgui.control.fitstructure import FitStructure
+from diffpy.pdfgui.control.fitting import Fitting
+from diffpy.pdfgui.control.organizer import Organizer
+from diffpy.pdfgui.control.pdflist import PDFList
+from diffpy.pdfgui.utils import asunicode
+
+
+
+[docs] +class PDFGuiControl: + """PDFGuiControl holds all the data GUI needs to access or change It has a + container of Calculation and Fitting instances. + + Each Calculation and Fitting has a unique name. + """ + + def __init__(self, gui=None): + """initialize. + + gui: main panel of GUI + """ + self.lock = threading.RLock() + self.gui = gui + + # clean up local data + self.reset() + + # Queue stuff + self.fittingQueue = [] + self.currentFitting = None + self.queueManager = PDFGuiControl.QueueManager(self) + # self.startQueue() + +
+[docs] + def reset(self): + """Clean up for a new project.""" + self.fits = PDFList() + self.plots = PDFList() + self.journal = "" + + self.projfile = None
+ + # self.saved = False + + # a simple thread to handle fitting queue +
+[docs] + class QueueManager(threading.Thread): + def __init__(self, control): + threading.Thread.__init__(self) + self.control = control + self.running = True + +
+[docs] + def run(self): + while self.running: + try: + self.control.checkQueue() + except ControlError as error: + gui = self.control.gui + if gui: + gui.postEvent(gui.ERROR, "<Queue exception> %s" % error.info) + else: + print("<Queue exception> %s" % error.info) + # another check before go to sleep + if not self.running: + break + time.sleep(1)
+
+ + +
+[docs] + def startQueue(self): + """Start queue manager.""" + self.queueManager.daemon = True + self.queueManager.start()
+ + +
+[docs] + def checkQueue(self): + """Find next fitting in the queue and start it.""" + if self.currentFitting: + # wait for currentFitting + self.currentFitting.join() + + # No fitting in the queue is running. + try: + self.lock.acquire() + if len(self.fittingQueue) > 0: + self.currentFitting = self.fittingQueue.pop(0) + else: + self.currentFitting = None + return + finally: + self.lock.release() + + self.currentFitting.start()
+ + +
+[docs] + def enqueue(self, fits, enter=True): + """Enqueue or dequeue fittings. + + fits -- list of fittings to be queued/dequeued + enter -- True to queue, False to dequeue + """ + try: + self.lock.acquire() + for fit in fits: + if enter: + try: + self.fittingQueue.index(fit) + # if no exception, then it already in the queue, + # continue to next + continue + except ValueError: + # not in the queue + self.fittingQueue.append(fit) + else: + try: + # try to remove even if it may not be in the queue + self.fittingQueue.remove(fit) + except ValueError: + # do nothing if it's not in the queue, continue to next. + continue + + # When this is called, GUI lock is in possess for sure, so + # no dead lock can happen. + fit.queue(enter) + finally: + self.lock.release()
+ + +
+[docs] + def close(self, force=True): + """Close a project. + + force -- if exit forciably + """ + self.stop() + for plot in self.plots: + plot.close(force) + for fit in self.fits: + fit.close(force) + + self.reset()
+ + +
+[docs] + def exit(self): + """Exit when program finished.""" + self.close() + if self.queueManager.is_alive(): + self.queueManager.running = False
+ + +
+[docs] + def newFitting(self, name, position=None): + """Insert a new instance of Fitting. + + name -- unique name for this Fitting + position -- where Fitting is inserted, default is last place + + return: Fitting reference + """ + fitting = Fitting(name) + self.add(fitting, position) + return fitting
+ + +
+[docs] + def newCalculation(self, targetID, name, position=None): + """Insert a new instance of Calculation to a Fitting. + + targetID -- reference to Fitting + name -- unique name for this Calculation + position -- where Calculation is inserted, default is last place + + return: Calculation reference + """ + calculation = Calculation(name) + targetID.add(calculation, position) + + return calculation
+ + +
+[docs] + def newStructure(self, targetID, name, position=None): + """Add blank structure to a Fitting. + + targetID -- reference to Fitting + name -- name of the new Structure + position -- where the structure is to be inserted, default is last + + return: Structure reference + """ + self.__validateType(targetID) + + # insert to target + struct = FitStructure(name) + targetID.add(struct, position) + return struct
+ + +
+[docs] + def loadStructure(self, targetID, filename, name=None, position=None): + """Add blank structure to a Fitting. + + targetID -- reference to Fitting + name -- name of the new Structure, default is file basename + + return: Structure reference + """ + self.__validateType(targetID) + if name is None: + name = os.path.basename(filename) + + # insert to target + struct = FitStructure(name) + struct.initial.read(filename) + targetID.add(struct, position) + return struct
+ + +
+[docs] + def loadDataset(self, targetID, filename, name=None, position=None): + """Load Dataset from a file to a Fitting. + + targetID -- reference to Fitting + name -- name of the new Dataset, default is file basename + position -- where the dataset is to be inserted, default is last + + return: Dataset reference + """ + self.__validateType(targetID) + + if name is None: + name = os.path.basename(filename) + + # insert to target + dataset = FitDataSet(name) + dataset.readObs(filename) + targetID.add(dataset, position) + return dataset
+ + +
+[docs] + def add(self, ID, position=None): + """Add fitting/calculation to internal list. + + Id -- reference to the object to be inserted + position -- where the object is to be inserted, default is last + """ + if not isinstance(ID, Fitting) and not isinstance(ID, Calculation): + raise ControlTypeError("Can't add %s to list" % self.__class__.__name__) + if position is not None: + self.fits.insert(position, ID) + else: + self.fits.append(ID) + # added successfully + ID.owner = self + return ID
+ + + def __findOwner(self, ID): + """Find where the ID belongs. + + ID -- object which can be Fitting,Calculation,FitDataSet or FitStructure + return: a PDFList holding that object + """ + if isinstance(ID, Organizer): + return self.fits + else: + try: + return ID.owner + except AttributeError: + raise ControlTypeError("Object %s doesn't exit in the list" % ID.name) + +
+[docs] + def rename(self, ID, new_name): + """Rename Fitting, Calculation, Dataset or Structure identified by ID. + + ID: reference to the object to be renamed + new_name: new name to be given to the object + """ + container = self.__findOwner(ID) + container.rename(ID, new_name)
+ + +
+[docs] + def remove(self, ID): + """Remove Fitting, Calculation, Dataset or Structure identified by ID. + + ID: reference to the object to be removed + return: removed object + """ + container = self.__findOwner(ID) + container.remove(ID) + return ID
+ + +
+[docs] + def index(self, ID): + """Return position index of an object in its owner list. + + ID -- ID of object + return: index + """ + container = self.__findOwner(ID) + return container.index(ID)
+ + +
+[docs] + def copy(self, src): + """Copy src object. + + src -- reference to the source object + return: reference to the copy + """ + newObject = src.copy() + return newObject
+ + +
+[docs] + def paste(self, dup, target=None, new_name=None, position=None): + """Paste copied object to target under new_name, the default new_name + will be name of src. + + dup -- reference to the copied object + target -- target object where the copy should be inserted + new_name -- new name to be given to the copy + position -- where in the target object should the copy be inserted + + return: reference to the pasted object + """ + if target is None: + target = self + else: + self.__validateType(target) + + o = dup.copy() + if new_name is not None: + o.name = new_name + target.add(o, position) + return o
+ + +
+[docs] + def load(self, projfile): + """Load project from projfile. + + projfile -- a zip file of everything + """ + + def _nameParser(namelist): + """Parse the zipfile name list to get a file tree.""" + fileTree = {} + for name in namelist: + subs = name.split("/") + pathDict = fileTree + for x in subs[:-1]: + # if no node has been created + if x not in pathDict: + pathDict[x] = {} + pathDict = pathDict[x] + + # check if the entry is a leaf(file, not folder) + if subs[-1] != "": + pathDict[subs[-1]] = None + return fileTree + + self.projfile = projfile + organizations = [] + import zipfile + + # IOError can be raised when reading invalid zipfile + # check for file existence here. + if not os.path.isfile(projfile): + emsg = "Project file %s does not exist." % projfile + raise ControlFileError(emsg) + + emsg_invalid_file = "Invalid or corrupted project %s." % projfile + z = None + try: + z = zipfile.ZipFile(projfile, "r") + z.fileTree = _nameParser(z.namelist()) + + if len(z.fileTree) == 0: + raise ControlFileError(emsg_invalid_file) + # The first layer has only one folder + rootDict = next(iter(z.fileTree.values())) + projName = next(iter(z.fileTree.keys())) + + if "journal" in rootDict: + self.journal = asunicode(z.read(projName + "/journal")) + + # all the fitting and calculations + # NOTE: It doesn't hurt to keep backward compatibility + # old test project may not have file 'fits' + if "fits" in rootDict: + ftxt = asunicode(z.read(projName + "/fits")) + fitnames = ftxt.splitlines() + else: + fitnames = [x for x in rootDict.keys() if rootDict[x] is not None] + + for name in fitnames: + if not name: # empty string + continue + fit = Fitting(name) + # fitting name stored in rootDict should be quoted + rdname = quote_plus(name) + # but let's also handle old project files + if rdname not in rootDict: + rdname = name + if rdname in rootDict: + org = fit.load(z, projName + "/" + rdname + "/") + else: + # it's simply a blank fitting, has no info in proj file yet + org = fit.organization() + organizations.append(org) + self.add(fit) + + except (IOError, zipfile.error, pickle.PickleError): + raise ControlFileError(emsg_invalid_file) + + # close input file if opened + finally: + if z: + z.close() + + return organizations
+ + +
+[docs] + def save(self, projfile=None): + """Save project to projfile, default projfile is self.projfile. + + This method first writes to a temporary file and only when + successful, it overwrites projfile with the temporary file + content. These steps prevent corruption of existing projects + should something go wrong in the middle of save. As an added + benefit, all permissions and ownership flags in an existing + projfile are preserved. + """ + if projfile is not None: + self.projfile = projfile + + # self.projfile is unset here only due to a bug. + assert self.projfile is not None + + import shutil + import tempfile + import zipfile + + projbase = os.path.basename(self.projfile) + projName = os.path.splitext(projbase)[0] + # prepare to write + fitnames = [] + z = None + tmpfilename = None + try: + tmpfd, tmpfilename = tempfile.mkstemp() + os.close(tmpfd) + z = zipfile.ZipFile(tmpfilename, "w", zipfile.ZIP_DEFLATED) + # fits also contain calculations + for fit in self.fits: + name = fit.name + fit.save(z, projName + "/" + quote_plus(fit.name) + "/") + fitnames.append(name) + if self.journal: + z.writestr(projName + "/journal", asunicode(self.journal)) + ftxt = "\n".join(fitnames) + z.writestr(projName + "/fits", asunicode(ftxt)) + z.close() + shutil.copyfile(tmpfilename, self.projfile) + + except (IOError, pickle.PickleError): + emsg = "Error when writing to %s" % self.projfile + raise ControlFileError(emsg) + + finally: + if z is not None: + z.close() + if tmpfilename is not None: + os.remove(tmpfilename) + + return
+ + +
+[docs] + def plot(self, xItem, yItems, Ids, shift=1.0, dry=False): + """Make a 2D plot. + + xItem -- x data item name + yItems -- list of y data item names + Ids -- Objects where y data items are taken from + shift -- y displacement for each curve + dry -- not a real plot, only check if plot is valid + """ + from diffpy.pdfgui.control.plotter import Plotter + + plotter = Plotter() + plotter.plot(xItem, yItems, Ids, shift, dry) + self.plots.append(plotter)
+ + +
+[docs] + def start(self, IDlist): + """Execute Calculations and Fittings in IDlist.""" + self.redirectStdout() + fits = [ID for ID in IDlist if isinstance(ID, Fitting)] + # only add calcs which is not in fits, because fits will automatically run calcs under it anyway + calcs = [ID for ID in IDlist if isinstance(ID, Calculation) and ID.owner not in fits] + for calc in calcs: + calc.start() + self.enqueue(fits)
+ + +
+[docs] + def stop(self): + """Stop all Fittings.""" + self.enqueue(self.fits, False) + for id in self.fits: + if isinstance(id, Fitting): + id.stop()
+ + + def __validateType(self, targetID): + """Check if targetID is a Fitting class.""" + if not isinstance(targetID, Organizer): + raise ControlTypeError("Can't insert to %s" % self.__class__.__name__) + +
+[docs] + def redirectStdout(self): + """Redirect standard out. + + This redirect engine output to StringIO if not done yet. + """ + from diffpy.pdffit2 import output, redirect_stdout + + if output.stdout is sys.stdout: + redirect_stdout(io.StringIO()) + return
+ + +
+[docs] + def getEngineOutput(self): + """Get the output from the engine.""" + from diffpy.pdffit2 import output, redirect_stdout + + txt = output.stdout.getvalue() + output.stdout.close() + redirect_stdout(io.StringIO()) + return txt
+
+ + + +_pdfguicontrol = None + + +
+[docs] +def pdfguicontrol(*args, **kwargs): + """This function will return the single instance of class PDFGuiControl.""" + global _pdfguicontrol + if _pdfguicontrol is None: + _pdfguicontrol = PDFGuiControl(*args, **kwargs) + return _pdfguicontrol
+ + + +def _importByName(mname, name): + try: + module = __import__(mname, globals(), locals(), [name]) + except ImportError: + return None + return getattr(module, name) + + +def _find_global(moduleName, clsName): + # from diffpy.pdfgui.control.parameter import Parameter + moduleName = "diffpy.pdfgui.control." + moduleName.split(".")[-1] + m = _importByName(moduleName, clsName) + return m + + +
+[docs] +class CtrlUnpickler: + """Occasionally the project file may be generated on a platform where + PYTHONPATH is not correctly set up. + + CtrlUnpickler will transform the module path in the project file to + be relative to diffpy so that it can be safely loaded. Only + constraints and parameters need this class to un- pickle. + """ + +
+[docs] + @staticmethod + def loads(s): + try: + return pickle.loads(s) + except ImportError as err: + missedModule = str(err).split(" ")[-1] + if missedModule.find("pdfgui.control") == -1: + raise err + f = io.StringIO(s) + unpickler = pickle.Unpickler(f) + unpickler.find_global = _find_global + return unpickler.load()
+
+ + + +# End of file +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/control/pdfguimacros.html b/_modules/diffpy/pdfgui/control/pdfguimacros.html new file mode 100644 index 00000000..b7d0ed59 --- /dev/null +++ b/_modules/diffpy/pdfgui/control/pdfguimacros.html @@ -0,0 +1,503 @@ + + + + + + + + diffpy.pdfgui.control.pdfguimacros — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.control.pdfguimacros

+#!/usr/bin/env python
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+"""Methods for macros used in pdfgui."""
+
+from __future__ import print_function
+
+import copy
+import os
+
+from diffpy.pdfgui.control.controlerrors import ControlValueError
+from diffpy.pdfgui.control.fitdataset import FitDataSet
+
+
+
+[docs] +def makeRSeries( + control, + fit, + maxfirst=None, + maxlast=None, + maxstep=None, + minfirst=None, + minlast=None, + minstep=None, +): + """Make an series of fits with an increasing r-range. + + The new fits are appended to the end of any current fits in the control. + + control -- The control object that will contain the fits + fit -- The prototype fit + maxfirst -- The first value of the maximum of the fit range + maxlast -- The last value of the maximum of the fit range + maxstep -- The step size of the maximum of the fit range + minfirst -- The first value of the minimum of the fit range + minlast -- The last value of the minimum of the fit range + minstep -- The step size of the minimum of the fit range + + returns a list of the new fit organization objects + """ + # Check to see if the input values are correct. + + # MIN-MIN: FIRST < LAST + if minfirst is not None and minlast is not None and not minfirst < minlast: + message = ( + "The first value of the minimum (%.2f)\ + \nmust be less than the last value of the\ + \nminimum (%.2f)" + % (minfirst, minlast) + ) + raise ControlValueError(message) + + # MAX-MAX: FIRST < LAST + if maxfirst is not None and maxlast is not None and not maxfirst < maxlast: + message = ( + "The first value of the maximum (%.2f)\ + \nmust be less than the last value of the\ + \nmaximum (%.2f)" + % (maxfirst, maxlast) + ) + raise ControlValueError(message) + + # MAX > MIN: FIRST-FIRST + if maxfirst is not None and minfirst is not None and not maxfirst > minfirst: + message = ( + "The first value of the fit maximum (%.2f)\ + \nmust be greater than first value of the fit\ + \nminimum (%.2f)." + % (maxfirst, minfirst) + ) + raise ControlValueError(message) + + # MAX > MIN: LAST-LAST + if maxlast is not None and minlast is not None and not maxlast > minlast: + message = ( + "The last value of the fit maximum (%.2f)\ + \nmust be greater than last value of the fit\ + \nminimum (%.2f)." + % (maxlast, minlast) + ) + raise ControlValueError(message) + + # STEP > 0 + message = "Step size (%.2f) must be greater than 0." + if maxstep is not None and not maxstep > 0: + raise ControlValueError(message % maxstep) + if minstep is not None and not minstep > 0: + raise ControlValueError(message % minstep) + + # Check to see that either max or min is fully specified + maxlist = [maxfirst, maxlast] + minlist = [minfirst, minlast] + if maxlist.count(None) == 1 or minlist.count(None) == 1: + raise ControlValueError("First and last values are partially specified") + if maxstep is None and minstep is None: + raise ControlValueError("Either minstep or maxstep must be specified.") + + maxlist = [] + minlist = [] + if maxfirst is not None: + if maxstep is None: + maxstep = minstep + maxrange = int((maxlast - maxfirst) / (1.0 * maxstep) + 1) + maxlist = [maxfirst + i * maxstep for i in range(maxrange)] + if minfirst is not None: + if minstep is None: + minstep = maxstep + minrange = int((minlast - minfirst) / (1.0 * minstep) + 1) + minlist = [minfirst + i * minstep for i in range(minrange)] + + # Resize the lists to the length of the shortest + serieslen = min(len(maxlist), len(minlist)) + if serieslen != 0: + maxlist = maxlist[:serieslen] + minlist = minlist[:serieslen] + else: + serieslen = max(len(maxlist), len(minlist)) + + basename = fit.name + fits = [] + + newname = "" + lastname = "" + fitcopy = control.copy(fit) + # Duplicate the original fit and change the appropriate parameters. + for i in range(serieslen): + lastname = newname + + # Loop over datasets + for ds in fitcopy.datasets: + + if minlist: + fitrmin = minlist[i] + else: + fitrmin = ds.fitrmin + if maxlist: + fitrmax = maxlist[i] + else: + fitrmax = ds.fitrmax + + # Check to see that the values are in bounds and sensical + if fitrmin < ds.rmin or fitrmin >= ds.rmax: + message = ( + "Fit minimum (%.2f) is outside the data range\ + \n[%.2f, %.2f].\ + \nAdjust the range of the series." + % (fitrmin, ds.rmin, ds.rmax) + ) + raise ControlValueError(message) + if fitrmax <= ds.rmin or fitrmax > ds.rmax: + message = ( + "Fit maximum (%.2f) is outside the data range\ + \n[%.2f, %.2f].\ + \nAdjust the range of the series." + % (fitrmax, ds.rmin, ds.rmax) + ) + raise ControlValueError(message) + if fitrmin >= fitrmax: + message = ( + "Fit minimum (%.2f) is greater than the\ + \nmaximum (%.2f).\ + \nIncrease maxstep or reduce minstep." + % (fitrmin, fitrmax) + ) + raise ControlValueError(message) + + # Set the values if all is well + if minlist: + ds.fitrmin = fitrmin + if maxlist: + ds.fitrmax = fitrmax + + # Set the parameters to the previous fit's name, if one exists. + if lastname: + parval = "=%s" % lastname + for par in fitcopy.parameters.values(): + par.setInitial(parval) + + # Now paste the copy into the control. + newname = "%s-(%.2f,%.2f)" % (basename, fitrmin, fitrmax) + o = control.paste(fitcopy, new_name=newname) + fits.append(o) + + return [f.organization() for f in fits]
+ + + +# Temperature Series +
+[docs] +def makeTemperatureSeries(control, fit, paths, temperatures): + """Make a temperature series. + + control -- pdguicontrol instance + fit -- The template fit + paths -- list of path names of new datasets + temperatures -- list of temperatures corresponding to the datasets + + returns a list of the new fit organization objects + """ + + if len(fit.datasets) != 1: + message = "Can't apply macro to fits with multiple datasets." + raise ControlValueError(message) + + fits = [] + # holds all of the other information about the dataset + fitbasename = fit.name + fitnewname = fit.name + fitlastname = fit.name + dataset = fit.datasets[0] + for i in range(len(paths)): + filename = paths[i] + fitlastname = fitnewname + + fitcopy = control.copy(fit) + + # Get rid of the old dataset + temp = fitcopy.datasets[0] + fitcopy.remove(temp) + + # Configure the new dataset + dsname = os.path.basename(filename) + newdataset = FitDataSet(dsname) + newdataset.readObs(filename) + + newdataset.qdamp = dataset.qdamp + newdataset.qbroad = dataset.qbroad + newdataset.dscale = dataset.dscale + newdataset.fitrmin = dataset.fitrmin + newdataset.fitrmax = dataset.fitrmax + rstep = dataset.fitrstep + st = dataset.getFitSamplingType() + newdataset.setFitSamplingType(st, rstep) + doping = dataset.metadata.get("doping") + if doping is None: + doping = 0.0 + newdataset.metadata["doping"] = doping + newdataset.constraints = copy.deepcopy(dataset.constraints) + + # Set the chosen temperature + newdataset.metadata["temperature"] = temperatures[i] + + # Add the dataset to the fitcopy + fitcopy.add(newdataset, None) + + # Set the parameters to the previous fit's name, if one exists. + if fitlastname: + parval = "=%s" % fitlastname + for par in fitcopy.parameters.values(): + par.setInitial(parval) + + # Now paste the copy into the control. + fitnewname = "%s-T%i=%g" % (fitbasename, i + 1, temperatures[i]) + o = control.paste(fitcopy, new_name=fitnewname) + fits.append(o) + + return [f.organization() for f in fits]
+ + + +# Doping Series +
+[docs] +def makeDopingSeries(control, fit, base, dopant, paths, doping): + """Make a temperature series. + + control -- pdguicontrol instance + fit -- The template fit + base -- Name of the base element + dopant -- Name of the dopant element + paths -- list of path names of new datasets + doping -- list of doping values corresponding to the datasets + + returns a list of the new fit organization objects + """ + from diffpy.pdffit2 import is_element + + # Make sure that base and dopant are elements + base = base.title() + dopant = dopant.title() + if not is_element(base): + raise ControlValueError("'%s' is not an element!" % base) + if not is_element(dopant): + raise ControlValueError("'%s' is not an element!" % dopant) + + # Make sure that base and dopant are in the structure file(s) + hasBase = False + hasDopant = False + for S in fit.strucs: + for atom in S: + if atom.element == base: + hasBase = True + if atom.element == dopant: + hasDopant = True + if hasBase and hasDopant: + break + + if not hasBase: + message = "The template structure does not contain the base atom." + raise ControlValueError(message) + + if not hasDopant: + message = "The template structure does not contain the dopant atom." + raise ControlValueError(message) + + # Make sure we're only replacing a single dataset + if len(fit.datasets) != 1: + message = "Can't apply macro to fits with multiple datasets." + raise ControlValueError(message) + + fits = [] + # holds all of the other information about the dataset + fitbasename = fit.name + fitnewname = fit.name + fitlastname = fit.name + dataset = fit.datasets[0] + for i in range(len(paths)): + filename = paths[i] + fitlastname = fitnewname + + fitcopy = control.copy(fit) + + # Get rid of the old dataset + temp = fitcopy.datasets[0] + fitcopy.remove(temp) + + # Configure the new dataset + dsname = os.path.basename(filename) + newdataset = FitDataSet(dsname) + newdataset.readObs(filename) + + newdataset.qdamp = dataset.qdamp + newdataset.qbroad = dataset.qbroad + newdataset.dscale = dataset.dscale + newdataset.fitrmin = dataset.fitrmin + newdataset.fitrmax = dataset.fitrmax + rstep = dataset.fitrstep + st = dataset.getFitSamplingType() + newdataset.setFitSamplingType(st, rstep) + temperature = dataset.metadata.get("temperature") + if temperature is None: + temperature = 300.0 + newdataset.metadata["temperature"] = temperature + newdataset.constraints = copy.deepcopy(dataset.constraints) + + # Set the chosen temperature + newdataset.metadata["doping"] = doping[i] + + # Add the dataset to the fitcopy + fitcopy.add(newdataset, None) + + # Update the doping information in the structures + for S in fitcopy.strucs: + for A in S: + if A.element == dopant: + A.occupancy = doping[i] + if A.element == base: + A.occupancy = 1 - doping[i] + + # Set the parameters to the previous fit's name, if one exists. + if fitlastname: + parval = "=%s" % fitlastname + for par in fitcopy.parameters.values(): + par.setInitial(parval) + + # Now paste the copy into the control. + fitnewname = "%s-%1.4f" % (fitbasename, doping[i]) + o = control.paste(fitcopy, new_name=fitnewname) + fits.append(o) + + return [f.organization() for f in fits]
+ + + +if __name__ == "__main__": + from diffpy.pdfgui.control.pdfguicontrol import PDFGuiControl + + control = PDFGuiControl() + control.load("../../tests/testdata/ni.ddp") + fit = control.fits[0] + olist = makeRSeries(control, fit, 5, 20, 5) + print("\n".join(f[0].name for f in olist)) + +# End of file +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/control/pdflist.html b/_modules/diffpy/pdfgui/control/pdflist.html new file mode 100644 index 00000000..f57a8153 --- /dev/null +++ b/_modules/diffpy/pdfgui/control/pdflist.html @@ -0,0 +1,235 @@ + + + + + + + + diffpy.pdfgui.control.pdflist — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.control.pdflist

+#!/usr/bin/env python
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Jiwu Liu
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+from diffpy.pdfgui.control.controlerrors import ControlKeyError
+
+
+
+[docs] +class PDFList(list): + """List class of PDFComponent, which can be accessed through index or a + name string.""" + + def __init__(self, *args): + """Initialize. + + args -- argument list + """ + list.__init__(self, args) + return + + def __getitem__(self, idnm): + """Get the item by idnm. + + idnm -- The index or name of the item + return: The requested object + """ + try: + return list.__getitem__(self, idnm) + except TypeError: + for item in self: + if item.name == idnm: + return item + else: + raise ControlKeyError("'%s' does not exist" % idnm) + + def __setitem__(self, idnm, obj): + """Set the item by idnm. + + idnm -- The index or name of the item + obj -- The object to be inserted + """ + if obj.name in self.keys(): + raise ControlKeyError("'%s' already exists" % obj.name) + try: + list.__setitem__(self, idnm, obj) + return + except TypeError: + self.append(obj) + return + + def __delitem__(self, idnm): + """Delete the item by idnm. + + idnm -- The index or name of the item + """ + try: + list.__delitem__(self, idnm) + return + except TypeError: + try: + index = self.keys.index(idnm) + list.__delitem__(self, index) + except IndexError: + raise ControlKeyError("'%s' does not exist" % idnm) + +
+[docs] + def rename(self, idnmrf, newname): + """Rename an item. + + idnmrf -- index,name or reference to the object + newname -- new name + """ + if newname in self.keys(): + raise ControlKeyError("'%s' already exists" % newname) + try: + self.index(idnmrf) + # if no exception, it is a object in the list. + idnmrf.name = newname + except ValueError: + self[idnmrf].name = newname + return
+ + +
+[docs] + def keys(self): + """Get the names of the held objects. + + return: list of names + """ + return [x.name for x in self]
+ + +
+[docs] + def values(self): + """Get all held objects. + + return: list of objects + """ + return self[:]
+ + +
+[docs] + def items(self): + """Get name-object pairs. + + return: a list of tuple ( name, object) + """ + return [(x.name, x) for x in self]
+
+ + + +# End of file +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/control/pdfstructure.html b/_modules/diffpy/pdfgui/control/pdfstructure.html new file mode 100644 index 00000000..e35ccd29 --- /dev/null +++ b/_modules/diffpy/pdfgui/control/pdfstructure.html @@ -0,0 +1,308 @@ + + + + + + + + diffpy.pdfgui.control.pdfstructure — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.control.pdfstructure

+#!/usr/bin/env python
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Pavol Juhas
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+import copy
+import re
+
+from diffpy.pdfgui.control.controlerrors import ControlFileError, ControlKeyError
+from diffpy.pdfgui.control.pdfcomponent import PDFComponent
+from diffpy.structure import PDFFitStructure
+
+
+
+[docs] +class PDFStructure(PDFComponent, PDFFitStructure): + """PDFStructure contains structure information, which can be used for 3D + rendering as well as structure refinement.""" + + def __init__(self, name, *args, **kwargs): + """Initialize PDFStructure. + + name -- name of this PDFStructure. + args, kwargs -- optional arguments passed to parent Structure class + """ + PDFComponent.__init__(self, name) + PDFFitStructure.__init__(self, *args, **kwargs) + return + +
+[docs] + def read(self, filename, format="auto"): + """Load structure from a file, raise ControlFileError for invalid or + unknown structure format. + + filename -- file to be loaded + format -- structure format such as 'pdffit', 'pdb', 'xyz'. When + 'auto' all available formats are tried in a row. + + Return instance of StructureParser used to load the data. + See Structure.read() for more info. + """ + from diffpy.structure import StructureFormatError + + try: + p = PDFFitStructure.read(self, filename, format) + except StructureFormatError as err: + import os.path + + emsg = "Unable to read file '%s'\n%s." % (os.path.basename(filename), err) + raise ControlFileError(emsg) + return p
+ + +
+[docs] + def copy(self, other=None): + """Copy self to other. if other is None, create an instance. + + other -- ref to other object + + returns reference to copied object + """ + if other is None: + other = PDFStructure(self.name) + for a in PDFFitStructure().__dict__: + setattr(other, a, copy.deepcopy(getattr(self, a))) + other[:] = copy.deepcopy(self[:]) + return other
+ + + # dictionary of allowed keys from self.pdffit dictionary, + # that can be used in setvar and getvar methods. + _allowed_pdffit_vars = dict.fromkeys(("spdiameter", "stepcut", "delta1", "delta2", "sratio", "rcut")) + +
+[docs] + def setvar(self, var, value): + """Assign to data member using PdfFit-style variable This can be used + when applying constraint equations with particular parameter values. + + var -- string representation of PdfFit variable. Possible values: + pscale, spdiameter, stepcut, delta1, delta2, sratio, rcut, + lat(n), where n=1..6, x(i), y(i), z(i), occ(i), u11(i), + u22(i), u33(i), u12(i), u13(i), u23(i), where i=1..Natoms + value -- new value of the variable + """ + barevar = var.strip() + fvalue = float(value) + parenthesis = re.match(r"^(\w+)\((\d+)\)$", barevar) + # common error message + emsg = "Invalid PdfFit phase variable %r" % barevar + if barevar in ("pscale"): + self.pdffit["scale"] = fvalue + elif barevar in PDFStructure._allowed_pdffit_vars: + self.pdffit[barevar] = fvalue + elif barevar == "lat(1)": + self.lattice.setLatPar(a=fvalue) + elif barevar == "lat(2)": + self.lattice.setLatPar(b=fvalue) + elif barevar == "lat(3)": + self.lattice.setLatPar(c=fvalue) + elif barevar == "lat(4)": + self.lattice.setLatPar(alpha=fvalue) + elif barevar == "lat(5)": + self.lattice.setLatPar(beta=fvalue) + elif barevar == "lat(6)": + self.lattice.setLatPar(gamma=fvalue) + elif parenthesis: + pvar = parenthesis.group(1) + idx = int(parenthesis.group(2)) + atom = self[idx - 1] + if pvar == "x": + atom.xyz[0] = fvalue + elif pvar == "y": + atom.xyz[1] = fvalue + elif pvar == "z": + atom.xyz[2] = fvalue + elif pvar == "occ": + atom.occupancy = fvalue + elif pvar in ("u11", "u22", "u33", "u12", "u13", "u23"): + i, j = int(pvar[1]) - 1, int(pvar[2]) - 1 + atom.U[i, j], atom.U[j, i] = fvalue, fvalue + else: + raise ControlKeyError(emsg) + else: + raise ControlKeyError(emsg) + return
+ + +
+[docs] + def getvar(self, var): + """Obtain value corresponding to PdfFit phase variable var This can be + used when guessing Parameter values from constraints dictionary. + + var -- string representation of PdfFit variable. Possible values: + pscale, spdiameter, stepcut, delta1, delta2, sratio, rcut, + lat(n), where n = 1..6, x(i), y(i), z(i), occ(i), u11(i), + u22(i), u33(i), u12(i), u13(i), u23(i), where i=1..Natoms + + returns value of var + """ + barevar = var.strip() + parenthesis = re.match(r"^(\w+)\((\d+)\)$", barevar) + # common error message + emsg = "Invalid PdfFit phase variable %r" % barevar + if barevar in ("pscale"): + value = self.pdffit["scale"] + elif barevar in PDFStructure._allowed_pdffit_vars: + value = self.pdffit[barevar] + elif barevar == "lat(1)": + value = self.lattice.a + elif barevar == "lat(2)": + value = self.lattice.b + elif barevar == "lat(3)": + value = self.lattice.c + elif barevar == "lat(4)": + value = self.lattice.alpha + elif barevar == "lat(5)": + value = self.lattice.beta + elif barevar == "lat(6)": + value = self.lattice.gamma + elif parenthesis: + pvar = parenthesis.group(1) + idx = int(parenthesis.group(2)) + atom = self[idx - 1] + if pvar == "x": + value = atom.xyz[0] + elif pvar == "y": + value = atom.xyz[1] + elif pvar == "z": + value = atom.xyz[2] + elif pvar == "occ": + value = atom.occupancy + elif pvar in ("u11", "u22", "u33", "u12", "u13", "u23"): + i, j = int(pvar[1]) - 1, int(pvar[2]) - 1 + value = atom.U[i, j] + else: + raise ControlKeyError(emsg) + else: + raise ControlKeyError(emsg) + # all should be fine here, but value may be NumPy.float64scalar type + value = float(value) + return value
+
+ + + +# End of class PDFStructure + +# End of file +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/control/plotter.html b/_modules/diffpy/pdfgui/control/plotter.html new file mode 100644 index 00000000..949c4c25 --- /dev/null +++ b/_modules/diffpy/pdfgui/control/plotter.html @@ -0,0 +1,849 @@ + + + + + + + + diffpy.pdfgui.control.plotter — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.control.plotter

+#!/usr/bin/env python
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Jiwu Liu
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+from diffpy.pdfgui.control.controlerrors import ControlConfigError, ControlStatusError
+from diffpy.pdfgui.control.pdfcomponent import PDFComponent
+from diffpy.pdfgui.gui.extendedplotframe import ExtendedPlotFrame
+
+# Preset plotting style
+colors = (
+    "red",
+    "blue",
+    "magenta",
+    "cyan",
+    "green",
+    "yellow",  # "black",
+    "darkRed",
+    "darkBlue",
+    "darkMagenta",
+    "darkCyan",
+    "darkGreen",
+    "darkYellow",
+)
+lines = ("solid", "dash", "dot", "dashDot")
+symbols = ("circle", "square", "triangle", "diamond")  # ,"cross","xCross")
+
+# this is to map 'r' to what it is supposed to be. For example, when user asks
+# for plotting 'Gobs' against 'r', the real data objects are 'Gobs' and 'robs'
+transdict = {
+    "Gobs": "robs",
+    "Gcalc": "rcalc",
+    "Gdiff": "rcalc",
+    "Gtrunc": "rcalc",
+    "crw": "rcalc",
+}
+baselineStyle = {
+    "with": "lines",
+    "line": "solid",
+    "color": "black",
+    "width": 1,
+    "legend": "_nolegend_",
+}
+
+
+def _transName(name):
+    """Translate name of y object.
+
+    This is mainly for plotting of parameters. GUI will pass in a integer to
+    indicate which parameter to be plotted. However, in data storage the
+    parameter is denoted as '@n'
+
+    name -- name of data item
+    """
+    if isinstance(name, int):
+        rv = "@" + str(name)
+    else:
+        rv = str(name)
+    return rv
+
+
+def _fullName(dataId):
+    """Construct full name."""
+    from diffpy.pdfgui.control.fitting import Fitting
+
+    if hasattr(dataId, "owner") and isinstance(dataId.owner, Fitting):
+        return _fullName(dataId.owner) + "/" + dataId.name
+    else:
+        return dataId.name
+
+
+def _buildStyle(plotter, name, group, yNames):
+    """Trying to figure out a good style.
+
+    1. generally we want line style for Gcalc, Gdiff, crw, symbol style for Gobs,
+    and line-symbol style for the rest
+    2. there is a preferred style for plotting a single PDF curve
+
+    plotter -- A plotter instance
+    name -- what is to be plotted (y name)
+    group -- which group the curve is in (group = -1 means it is the only group)
+    yNames -- all y to be plotted
+    return: style dictionary
+    """
+    if name in ("Gcalc", "Gdiff", "crw"):
+        style = plotter.buildLineStyle()
+        style["line"] = "solid"
+    elif name in ("Gobs", "Gtrunc"):
+        style = plotter.buildSymbolStyle()
+
+        # Use open circle always
+        style["symbolColor"] = "white"
+        style["symbol"] = "circle"
+        style["symbolSize"] = 6
+    else:
+        style = plotter.buildLineSymbolStyle()
+        style["line"] = "dash"
+        style["symbol"] = "circle"
+        style["symbolSize"] = 8
+
+    # We only care about how to arrange Gdiff Gobs Gcalc Gtrunc crw nicely
+    if group < 0:
+        # use fixed style for single PDFFit picture
+        if name == "Gcalc":
+            style["color"] = "red"
+        elif name in ("Gobs", "Gtrunc"):
+            style["color"] = "blue"
+        elif name in ("Gdiff", "crw"):
+            style["color"] = "green"
+    else:
+        # make sure Gdiff, Gtrunc, Gobs, crw are having same color
+        if name in ("Gobs", "Gtrunc", "Gdiff", "Gcalc", "crw"):
+            style["color"] = colors[group % len(colors)]
+        if name == "Gcalc":
+            # for visual effect, change Gcalc to black if it's going to be plotted against Gobs/Gtrunc
+            if "Gobs" in yNames or "Gtrunc" in yNames:
+                style["color"] = "black"
+
+    return style
+
+
+
+[docs] +def deblank(s): + """Remove all whitespace from the given string.""" + return "".join(s.split())
+ + + +
+[docs] +class Plotter(PDFComponent): + """Plots a single graph. + + It can have multiple curves. + """ + + __plotWindowNumber = 1 + +
+[docs] + class Curve: + """Curve stores the information for a curve in the plot. + + There are three ways of forming x and y data lists. + (1) r and g(r) from a single refinement are vectors by themselves + (2) A scalar data item (any item other than r and g(r)) can form a + vector if multiple timeSteps (refinement steps) are specified. + (3) A scalar data item (any item other than r and g(r)) can form a + vector if multiple refinement (multiple ids) are specified + + name -- The curve name + plotwnd -- The window where the curve is drawn + xStr -- Data name (string) for x axis + yStr -- Data name (string) for y axis + steps -- refinement step list + ids -- The list of object ids that the curve is related to + offset -- curve displacement in y direction + style --The drawing style of the curve + xData, yData -- data to be plotted + x, y -- original data for exporting (curve could be shifted) + bMultiData -- if the curve data comes from multiple data objects + bMultiStep -- if the curve data comes from multiple refinement step + ref -- reference of curve in the plot window + initialized -- if curve has been inserted + dataChanged -- if curve data has changed + """ + + def __init__(self, name, plotwnd, xStr, yStr, steps, ids, offset, style): + """initialize. + + name -- The curve name + plotwnd -- The window where the curve is drawn + xStr -- Data name (string) for x axis + yStr -- Data name (string) for y axis + steps -- refinement step list + ids -- The list of object ids that the curve is related to + offset -- curve displacement in y direction + style --The drawing style of the curve + """ + self.name = name + self.plotwnd = plotwnd + self.ids = ids + self.steps = steps + self.xStr = xStr + self.yStr = yStr + self.offset = offset + self.style = style + + self.bMultiData = len(self.ids) > 1 + self.bMultiStep = False + if self.steps is None or isinstance(self.steps, list): + self.bMultiStep = True + + self.xData = None + self.yData = None + self.x = None + self.y = None + + # Reference to the curve object in the underlying plotting library + self.ref = None + self.initialized = False + self.dataChanged = False + + # validate user's choice + self.validate() + +
+[docs] + def validate(self): + """Validate(self) --> check if the curve is valid. + + Validity + is broken: + (1) when xStr or yStr doesn't refer to a legal vector + (2) when sizes of xStr and yStr don't match + """ + bItemIsVector = False + if self.xStr in ("r", "rcalc", "robs"): + if self.yStr not in ("Gobs", "Gcalc", "Gdiff", "Gtrunc", "crw"): + emsg = "x={}, y={} don't match".format(self.xStr, self.yStr) + raise ControlConfigError(emsg) + bItemIsVector = True + elif self.xStr in ("Gobs", "Gcalc", "Gdiff", "Gtrunc", "crw"): + raise ControlConfigError("%s can't be x axis" % self.xStr) + elif self.yStr in ("Gobs", "Gcalc", "Gdiff", "Gtrunc", "crw"): + # Get called when x is not r but y is not Gobs, Gtrunc Gdiff... + raise ControlConfigError("%s can only be plotted against r" % self.yStr) + + # There are three booleans + # (1) bItemIsVector + # (2) self.ids has only one element + # (3) self.allSteps + # The logic below make sure only one of them can be true. + if bItemIsVector: + if self.bMultiData or self.bMultiStep: + emsg = ("({}, {}) can't be plotted with multiple " "refinements/steps").format( + self.xStr, self.yStr + ) + raise ControlConfigError(emsg) + else: + if not self.bMultiData and not self.bMultiStep: + raise ControlConfigError("(%s, %s) is a single point" % (self.xStr, self.yStr)) + elif self.bMultiData and self.bMultiStep: + emsg = ( + "({}, {}) can't be plotted with both multiple " "refinements and multiple steps" + ).format(self.xStr, self.yStr) + raise ControlConfigError(emsg)
+ + +
+[docs] + def notify(self, changedIds=None, plotwnd=None): + """Notify Curve object certain data is updated. + + changedIds -- objects to which changed data is associated with + """ + if plotwnd: + self.plotwnd = plotwnd + + # in the case when changedIds are given explicitly, use it. + if changedIds: + affectedIds = [] + for id in self.ids: + for changedId in changedIds: + if id is changedId or id.owner is changedId: + affectedIds.append(id) + break + + # If the change doesn't affect any id, do nothing + if not affectedIds: + return False + else: + affectedIds = self.ids + + # translation may be required + xStr = self.xStr + if xStr == "r": + xStr = transdict.get(self.yStr, xStr) + + if self.bMultiData: + # Local list is maintained here + if self.xData is None: + self.xData = [None] * len(self.ids) + if self.yData is None: + self.yData = [None] * len(self.ids) + for id in affectedIds: + i = self.ids.index(id) + self.yData[i] = id.getData(self.yStr, -1) + if xStr == "step": + raise AssertionError("Can not plot against step") + elif xStr == "index": + self.xData[i] = i + else: + self.xData[i] = id.getData(xStr, -1) + else: + # affectedIds has only one member + if self.bMultiStep: + steps = None # None to get the whole steps + else: + steps = -1 # + + # plot multiple refinement steps for a single dataId + # in deed, the reference is not gonna change + self.yData = affectedIds[0].getData(self.yStr, steps) + if xStr == "step": + if self.yData is None: + self.xData = None + else: + self.xData = list(range(len(self.yData))) + else: + self.xData = affectedIds[0].getData(xStr, steps) + + self.x = self.xData + self.y = self.yData + + def _shift(y): + return y + self.offset + + if self.yData and self.offset: # not zero + self.yData = [_shift(yi) for yi in self.yData] + + if self.xData and self.yData: # not empty or None + return self.draw() + else: + return False
+ + +
+[docs] + def draw(self): + """Draw the curve in the graph. + + It will make sure the data is OK, and plot to the screen. + """ + if self.bMultiData: + # xs and ys initialize here. They are actual data object to be + # used for plotting + xs = [] + ys = [] + plotData = sorted(zip(self.xData, self.yData)) + for x, y in plotData: + if x is not None and y is not None: + xs.append(x) + ys.append(y) + self.x = xs + self.y = ys + else: + xs = self.xData + ys = self.yData + + if not xs or not ys: + return False + + # If it can get here, data is ready now. + if self.ref is None: + self.ref = self.plotwnd.insertCurve(xs, ys, self.style) + if self.yStr == "Gdiff": + # add a baseline for any Gdiff + rs = self.ids[0].rcalc + if not rs: + rs = self.ids[0].robs + hMin = min(rs) + hMax = max(rs) + + self.plotwnd.insertCurve([hMin, hMax], [self.offset, self.offset], baselineStyle) + else: + # update only + self.plotwnd.updateData(self.ref, xs, ys) + + return True
+
+ + + def __init__(self, name=None): + """initialize. + + name -- name of plot + """ + if name is None: + name = "Plot [%i]" % Plotter.__plotWindowNumber + + PDFComponent.__init__(self, name) + import threading + + self.lock = threading.RLock() + self.curves = [] + self.window = None + self.isShown = False + from diffpy.pdfgui.control.pdfguicontrol import pdfguicontrol + + self.controlCenter = pdfguicontrol() + + # add some flavor by starting with random style + import random + + self.symbolStyleIndex = random.randint(0, 100) + self.lineStyleIndex = random.randint(0, 100) + return + +
+[docs] + def close(self, force=True): + """Close up the plot. + + force -- if True, close forcibly + """ + if self.window is not None: + # self.window.Close(True) + self.window.Destroy() + self.window = None
+ + +
+[docs] + def onWindowClose(self): + """Get called when self.window is closed by user.""" + self.window = None + try: + self.controlCenter.plots.remove(self) + except ValueError: + # if controlCenter doesn't know me, I'm just fine to bail out + pass
+ + +
+[docs] + def buildSymbolStyle(self, index=-1): + """Generate a symbol style. + + index -- plotting style index + """ + # To build different symbol style, we first change color then the symbol + i = index + if i == -1: + i = self.symbolStyleIndex + self.symbolStyleIndex += 1 + + symbolIndex = i % len(symbols) + colorIndex = i % len(colors) + return { + "with": "points", + "color": colors[colorIndex], + "symbolColor": colors[colorIndex], + "symbol": symbols[symbolIndex], + "symbolSize": 3, + }
+ + +
+[docs] + def buildLineStyle(self, index=-1): + """Generate a line style. + + index -- plotting style index + """ + # To build different line style, we first change color then the line + i = index + if i == -1: + i = self.lineStyleIndex + self.lineStyleIndex += 1 + + lineIndex = i % len(lines) + colorIndex = i % len(colors) + return { + "with": "lines", + "color": colors[colorIndex], + "line": lines[lineIndex], + "width": 2, + }
+ + +
+[docs] + def buildLineSymbolStyle(self, index=-1): + """Generate a linesymbol style. + + index -- plotting style index + """ + style = self.buildLineStyle(index) + style.update(self.buildSymbolStyle(index)) + style["with"] = "linespoints" + return style
+ + +
+[docs] + def plot(self, xName, yNames, ids, shift, dry): + """Make a 2D plot. + + xName -- x data item name + yNames -- list of y data item names + ids -- Objects where y data items are taken from + shift -- y spacing for different ids + dry -- dry run + """ + + def _addCurve(dataIds): + # Identify the plot type. This is used to automatically modify + # 'Gdiff' and 'crw' in certain types of plots. + yset = set(yNames) + if "Gdiff" in yset: + yset.remove("Gdiff") + if "crw" in yset: + yset.remove("crw") + + # add yNames one by one for given dataIds + for y in yNames: + _offset = offset + legend = None + style = None + if not dry: + if len(dataIds) == 1 and group != -1: + # legend = dataIds[0].name + ": " + _transName(y) + legend = _fullName(dataIds[0]) + ": " + _transName(y) + else: + # 1.Group = -1, multiple ids give a single curve + # 2.there is only one dataId so that prefix unneeded + legend = _transName(y) + + style = _buildStyle(self, y, group, yNames) + style["legend"] = legend + + # automatically apply offset if we're plotting more than + # just 'Gdiff' and 'crw' + if y in ("Gdiff", "crw") and group == -1 and len(yset) > 0: + _offset = shift + # Create curve, get data for it and update it in the plot + curve = Plotter.Curve(legend, self.window, xName, y, step, dataIds, _offset, style) + self.curves.append(curve) + return + + if not ids: # empty + raise ControlConfigError("Plotter: No data is selected") + if not yNames: + raise ControlConfigError("Plotter: No y item is selected") + + # bSeparateID indicates if we want data from different ID to be + # plotted in different curve or not + bSeparateID = False + if len(ids) > 1 and xName in ("r", "rcalc", "step"): + # multi ID and within each ID we wants a vector, so curve can + # only be plotted separately. + bSeparateID = True + + # set up the step + if xName == "step": + step = None + else: + step = -1 + + self.curves = [] + + if "Gcalc" in yNames: + yNames.remove("Gcalc") + yNames.append("Gcalc") + + # default is no shift, single group. + offset = 0.0 + group = -1 + if bSeparateID: + for id in ids: + group += 1 + _addCurve( + [ + id, + ] + ) + offset += shift + else: + _addCurve(ids) + + # clean up, it's only a dry run + if dry: + self.curves = [] + return + + # Real plot starts + if self.window is None: + # plotWindown may either not be ready or it has been closed + self.window = ExtendedPlotFrame(self.controlCenter.gui) + Plotter.__plotWindowNumber += 1 + self.window.plotter = self + else: + self.window.clear() + + for curve in self.curves: + # Initial notification, don't plot immediately, wait for last line to be added + # This is to optimize plotting multiple curves. + curve.notify(plotwnd=self.window) + + # make the graph title, x, y label + yStrs = [_transName(yName) for yName in yNames] + if yStrs[0].startswith("G"): + # then all are Gs + yLabel = "G" + else: + yLabel = ",".join(yStrs) + title = "" + if len(ids) == 1: + title = ids[0].name + ": " + title += yLabel + self.window.setTitle(self.name + " " + title, title) + self.window.setXLabel(_transName(xName)) + self.window.setYLabel(yLabel) + + # show the graph + self.window.replot() + self.show(True)
+ + +
+[docs] + def show(self, bShow=None): + """Show the plot on screen. + + bShow -- True to show, False to Hide. None to toggle + return value: current status of window + """ + if self.window is None: + raise ControlStatusError("Plot: %s has no window" % self.name) + if bShow is None: + bShow = not self.isShown + self.window.Show(bShow) + if bShow: # True + # further bring it to top + self.window.Raise() + self.isShown = bShow + return self.isShown
+ + +
+[docs] + def notify(self, data): + """Change of the data is notified. + + data -- data object that has changed + """ + if not self.curves or self.window is None: + return + ret = False + for curve in self.curves: + ret |= curve.notify( + changedIds=[ + data, + ] + ) + if ret: + self.window.replot()
+ + +
+[docs] + def export(self, filename): + """Export current data to external file. + + filename -- the name of the file to save data + """ + # Check if any curve + if len(self.curves) == 0: + return + import getpass + import time + + outfile = open(filename, "w") + header = "# Generated on %s by %s.\n" % (time.ctime(), getpass.getuser()) + header += "# This file was created by PDFgui.\n" + outfile.write(header) + xylist = [(c.x, c.y) for c in self.curves] + xynames = [(_transName(c.xStr), deblank(c.name)) for c in self.curves] + _exportCompactData(outfile, xylist, xynames) + outfile.close() + return
+
+ + + +# End of class Plotter + + +def _exportCompactData(fp, xylist, xynames=None): + """Write the xylist data in a text format to the file object fp. + The curves with the same x are grouped in the same datasets. + The datasets are marked with "#S 1", "#S 2", etc. labels according + to the spec format http://www.certif.com/cplot_manual/ch0c_C_11_3.html + + fp -- file type object that is writable + xylist -- list of (x, y) tuples of x and y arrays. Items with + empty x or empty y are ignored. + xynames -- list of tuples of (xname, yname) strings. These are + used as a header in the dataset blocks. + + No return value. + """ + dataformat = "%g" + # build the default xynames: + if xynames is None: + xynames = [("x%i" % i, "y%i" % i) for i in range(len(xylist))] + datasets = [] + datanames = [] + xt2idx = {} + for (x, y), (xn, yn) in zip(xylist, xynames): + if x is None or not len(x): + continue + if y is None or not len(y): + continue + xt = tuple(x) + i = xt2idx.setdefault(xt, len(xt2idx)) + if not i < len(datasets): + datasets.append([]) + datanames.append([]) + ds = datasets[i] + dn = datanames[i] + if not ds: + ds.append(x) + dn.append(xn) + ds.append(y) + dn.append(yn) + for i, (ds, dn) in enumerate(zip(datasets, datanames)): + # separate datasets with a blank line: + if i > 0: + fp.write("\n") + fp.write("#S %i\n" % (i + 1)) + fp.write("#L %s\n" % (" ".join(dn))) + ncols = len(ds) + fmt = " ".join(ncols * [dataformat]) + "\n" + for cols in zip(*ds): + line = fmt % cols + fp.write(line) + return + + +# End of file +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/control/structureviewer.html b/_modules/diffpy/pdfgui/control/structureviewer.html new file mode 100644 index 00000000..c7db31a8 --- /dev/null +++ b/_modules/diffpy/pdfgui/control/structureviewer.html @@ -0,0 +1,358 @@ + + + + + + + + diffpy.pdfgui.control.structureviewer — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.control.structureviewer

+#!/usr/bin/env python
+##############################################################################
+#
+# diffpy.pdfgui     by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2009-2024 Trustees of the Columbia University
+#                   in the City of New York.  All rights reserved.
+#
+# File coded by:    Pavol Juhas
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+"""Structure plotting in an external viewer process."""
+
+from __future__ import print_function
+
+import os.path
+import shutil
+import sys
+import tempfile
+
+from diffpy.pdfgui.control.controlerrors import ControlConfigError
+
+
+
+[docs] +def getStructureViewer(): + """Factory returning singleton instance of the StructureViewer class.""" + global _struviewer + if _struviewer is None: + _struviewer = StructureViewer() + return _struviewer
+ + + +_struviewer = None + + +
+[docs] +class StructureViewer(object): + """Class for plotting structure in general structure viewer. It takes care + of creating temporary structure file in a desired format and launching + structure viewer as a background process. The temporary files are removed + when StructureViewer instance goes out of scope. + + Data attributes: + + executable -- full path to the structure viewer executable or an executable + that can be found in system PATH. By default '' (not set). + argstr -- argument string for the viewer program, it can use shell + quoting. Instances of '%s' in the string are replaced with + temporary structure file. By default '%s' + fileformat -- structure format that can be loaded by the viewer. + Must be one of output formats supported by diffpy.structure + package. By default 'pdb'. + _tmpdir -- Temporary directory for structure files opened by the viewer. + tmpdir is None before the first call to plot. The directory + and everything inside is removed when StructureViewer goes + out of the scope. + _plotcount -- Number of plots created by this viewer. + """ + + def __init__(self, executable=None, argstr=None, fileformat=None): + """Create StructureViewer instance. All arguments are optional, they + override defaults described in class docstring. The configuration can + be changed later using setConfig method. + + executable -- path to the structure viewer executable + argstr -- argument string for the viewer program, it can use + shell quoting. Instances of '%s' are replaced with + temporary structure file. + fileformat -- structure format supported by diffpy.structure package. + """ + # declare instance data + self.executable = "" + self.argstr = "%s" + self.fileformat = "pdb" + self._tmpdir = None + self._plotcount = 0 + # process arguments: + if executable is not None: + self.executable = executable + if argstr is not None: + self.argstr = argstr + if fileformat is not None: + self.fileformat = fileformat + # finish every method with return + return + +
+[docs] + def getConfig(self): + """Return current configuration of StructureViewer instance. + + Returns new dictionary with the following keys: + ('executable', 'argstr', 'fileformat') + """ + cfgkeys = ("executable", "argstr", "fileformat") + kv = [(k, getattr(self, k)) for k in cfgkeys] + rv = dict(kv) + return rv
+ + +
+[docs] + def setConfig(self, cfg): + """Configure StructureViewer instance using values in a dictionary. + + cfg -- configuration dictionary, with the same keys as returned + by getConfig(). Any other keys are ignored. + + No return value. + """ + # iterate over keys from getConfig dictionary + for k in self.getConfig(): + if k in cfg: + setattr(self, k, cfg[k]) + return
+ + +
+[docs] + def getFileFormats(): + """Return list of valid values for the fileformat attribute.""" + from diffpy.structure.parsers import outputFormats + + return outputFormats()
+ + + getFileFormats = staticmethod(getFileFormats) + +
+[docs] + def plot(self, stru): + """Launch new structure viewer and open a temporary copy of stru. + + stru -- instance of Structure class from diffpy.structure + + No return value. + Raise ControlConfigError if structure viewer could not be launched. + """ + import subprocess + + # check if executable has been set + if not self.executable: + emsg = "StructureViewer program has not been set." + raise ControlConfigError(emsg) + # create temporary structure file + strupath = self._writeTemporaryStructure(stru) + args = [self.executable] + self._getArgumentList(strupath) + try: + subprocess.Popen(args) + except OSError as err: + emsg = "Error executing StructureViewer %s: %s" % (self.executable, err) + raise ControlConfigError(emsg) + return
+ + + def __del__(self): + """Remove temporary files created by this instance of + StructureViewer.""" + # short circuit if nothing has been created + if self._tmpdir is None: + return + + # Function for showing unremovable files + def onerror(fnc, path, error): + print(("Cannot remove %s - %s" % (path, error)), file=sys.stderr) + return + + # For safety remove _tmpdir subdirectories by their names + for i in range(self._plotcount): + di = os.path.join(self._tmpdir, "%04i" % i) + shutil.rmtree(di, True, onerror) + # finally remove _tmpdir, which should now be empty + try: + os.rmdir(self._tmpdir) + except OSError as err: + onerror(None, self._tmpdir, err) + pass + return + + def _getArgumentList(self, strupath): + """Convert self.argstr to a list of string arguments. + + strupath -- path to temporary structure file. Replaces every + instance of '%s' in self.argstr. + + Return list of arguments (not including the viewer executable). + """ + import re + import shlex + + # make sure shlex.split is not called with None, because + # it would read standard input + s = self.argstr and self.argstr or "" + args = shlex.split(s) + # substitute strupath in args using % operator + pat = re.compile(r"(?<!%)(%%)*%s") + for i, a in enumerate(args): + # count instances of '%s' in argument a + cnt = len(pat.findall(a)) + tpl = cnt * (strupath,) + args[i] = a % tpl + return args + + def _writeTemporaryStructure(self, stru): + """Create new temporary structure file in specified fileformat. + + stru -- instance of Structure class + + Return full path to the temporary file. + """ + # get extension preferred by fileformat + from diffpy.structure.parsers import parser_index + + ffext = parser_index[self.fileformat]["file_extension"] + d = self._createTemporaryDirectory() + # Use a simple file name to avoid naming errors. It is common to put + # the space group name, such as "C2\m" in the structure title. This + # may lead to invalid posix file names. + strutail = "structure" + os.path.basename(d) + struext = os.path.splitext(strutail)[-1] + if struext.lower() != ffext.lower(): + strutail += ffext + strupath = os.path.join(d, strutail) + stru.write(strupath, format=self.fileformat) + return strupath + + def _createTemporaryDirectory(self): + """Create new numbered temporary directory below self._tmpdir. + + Create _tmpdir if it does not exist yet. + + Return full path to the new temporary directory. + """ + if self._tmpdir is None: + self._tmpdir = tempfile.mkdtemp() + dname = "%04i" % self._plotcount + dpath = os.path.join(self._tmpdir, dname) + os.mkdir(dpath) + self._plotcount += 1 + return dpath
+ + + +# End of class StructureViewer + +# End of file. +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/aboutdialog.html b/_modules/diffpy/pdfgui/gui/aboutdialog.html new file mode 100644 index 00000000..0a91d536 --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/aboutdialog.html @@ -0,0 +1,367 @@ + + + + + + + + diffpy.pdfgui.gui.aboutdialog — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.aboutdialog

+#!/usr/bin/env python
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 Trustees of the Michigan State University.
+#                   (c) 2024 Trustees of the Columbia University in the City
+#                   of New York
+#                   All rights reserved.
+#
+# File coded by:    Dmitriy Bryndin
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+import random
+
+import wx
+import wx.lib.agw.hyperlink
+
+from diffpy.pdfgui.gui.pdfguiglobals import iconpath
+from diffpy.pdfgui.version import __date__, __version__
+
+_acknowledgement = """\
+This software was developed by the Billinge-group as part of the Distributed
+Data Analysis of Neutron Scattering Experiments (DANSE) project funded by the US
+National Science Foundation under grant DMR-0520547.  Developments of PDFfit2
+were funded by NSF grant DMR-0304391 in the Billinge-group, and with support
+from Michigan State University and Columbia University.  Any opinions, findings,
+and conclusions or recommendations expressed in this material are those of the
+author(s) and do not necessarily reflect the views of the respective funding
+bodies.
+
+If you use this program to do productive scientific research that leads to
+publication, we ask that you acknowledge use of the program by citing the
+following paper in your publication:
+
+    C. L. Farrow, P. Juhas, J. W. Liu, D. Bryndin, E. S. Bozin,
+    J. Bloch, Th. Proffen and S. J. L. Billinge, PDFfit2 and PDFgui:
+    computer programs for studying nanostructure in crystals,
+    J. Phys.: Condens. Matter 19, 335219 (2007)."""
+
+_copyright = f"(c) 2005-{__date__[-4:]},"
+
+_homepage = "https://www.diffpy.org"
+
+# authors list is shuffled randomly every time
+_authors = [
+    "S. J. L. Billinge",
+    "E. S. Bozin",
+    "D. Bryndin",
+    "C. L. Farrow",
+    "P. Juhas",
+    "J. W. Liu",
+]
+_paper = "https://stacks.iop.org/0953-8984/19/335219"
+_license = ""
+
+
+
+[docs] +def launchBrowser(url): + """Launches browser and opens specified url. + + In some cases may require BROWSER environment variable to be set up. + + @param url: URL to open + """ + import webbrowser + + webbrowser.open(url)
+ + + +
+[docs] +class DialogAbout(wx.Dialog): + """The "About" Dialog. + + Shows product name, current version, authors, and link to the + product page. Current version is taken from version.py + """ + + def __init__(self, *args, **kwds): + + # begin wxGlade: DialogAbout.__init__ + kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_DIALOG_STYLE + wx.Dialog.__init__(self, *args, **kwds) + self.SetSize((600, 595)) + self.bitmap_logo = wx.StaticBitmap(self, wx.ID_ANY, wx.Bitmap(iconpath("logo.png"))) + self.label_title = wx.StaticText(self, wx.ID_ANY, "PDFgui") + self.label_version = wx.StaticText(self, wx.ID_ANY, "") + self.label_build = wx.StaticText(self, wx.ID_ANY, "Build:") + self.label_svnrevision = wx.StaticText(self, wx.ID_ANY, "") + self.label_copyright = wx.StaticText(self, wx.ID_ANY, "") + self.label_author = wx.StaticText(self, wx.ID_ANY, "author") + self.hyperlink = wx.lib.agw.hyperlink.HyperLinkCtrl(self, wx.ID_ANY, _homepage, URL=_homepage) + self.hyperlink_license = wx.lib.agw.hyperlink.HyperLinkCtrl(self, wx.ID_ANY, _license, URL=_license) + self.static_line_1 = wx.StaticLine(self, wx.ID_ANY) + self.label_acknowledgement = wx.StaticText(self, wx.ID_ANY, "") + self.hyperlink_paper = wx.lib.agw.hyperlink.HyperLinkCtrl(self, wx.ID_ANY, _paper, URL=_paper) + self.static_line_2 = wx.StaticLine(self, wx.ID_ANY) + self.bitmap_button_nsf = wx.BitmapButton(self, wx.ID_ANY, wx.NullBitmap, style=wx.BU_AUTODRAW) + self.bitmap_button_danse = wx.BitmapButton(self, wx.ID_ANY, wx.NullBitmap, style=wx.BU_AUTODRAW) + self.bitmap_button_msu = wx.BitmapButton(self, wx.ID_ANY, wx.NullBitmap, style=wx.BU_AUTODRAW) + self.bitmap_button_columbia = wx.BitmapButton(self, wx.ID_ANY, wx.NullBitmap, style=wx.BU_AUTODRAW) + self.static_line_3 = wx.StaticLine(self, wx.ID_ANY) + self.button_OK = wx.Button(self, wx.ID_OK, "OK") + + self.__set_properties() + self.__do_layout() + + self.Bind(wx.EVT_BUTTON, self.onNsfLogo, self.bitmap_button_nsf) + self.Bind(wx.EVT_BUTTON, self.onDanseLogo, self.bitmap_button_danse) + self.Bind(wx.EVT_BUTTON, self.onMsuLogo, self.bitmap_button_msu) + self.Bind(wx.EVT_BUTTON, self.onColumbiaLogo, self.bitmap_button_columbia) + # end wxGlade + + # randomly shuffle authors' names + random.shuffle(_authors) + strLabel = ", ".join(_authors) + self.label_author.SetLabel(strLabel) + # setup acknowledgement and copyright text labels + self.label_acknowledgement.SetLabel(_acknowledgement) + self.label_copyright.SetLabel(_copyright) + # display version and svn revision numbers + verwords = __version__.split(".post", 1) + version = verwords[0] + revision = "0" if len(verwords) == 1 else verwords[1] + self.label_version.SetLabel(version) + self.label_svnrevision.SetLabel(revision) + + # set bitmaps for logo buttons + logo = wx.Bitmap(iconpath("nsf_logo.png")) + self.bitmap_button_nsf.SetBitmapLabel(logo) + logo = wx.Bitmap(iconpath("danse_logo.png")) + self.bitmap_button_danse.SetBitmapLabel(logo) + logo = wx.Bitmap(iconpath("msu_logo.png")) + self.bitmap_button_msu.SetBitmapLabel(logo) + logo = wx.Bitmap(iconpath("columbia_logo.png")) + self.bitmap_button_columbia.SetBitmapLabel(logo) + + # resize dialog window to fit version number nicely + self.Fit() + return + + def __set_properties(self): + # begin wxGlade: DialogAbout.__set_properties + self.SetTitle("About") + self.SetSize((600, 595)) + self.label_title.SetFont( + wx.Font( + 26, + wx.FONTFAMILY_DEFAULT, + wx.FONTSTYLE_NORMAL, + wx.FONTWEIGHT_BOLD, + 0, + "", + ) + ) + self.label_version.SetFont( + wx.Font( + 26, + wx.FONTFAMILY_DEFAULT, + wx.FONTSTYLE_NORMAL, + wx.FONTWEIGHT_NORMAL, + 0, + "", + ) + ) + self.hyperlink_license.Enable(False) + self.hyperlink_license.Hide() + self.bitmap_button_nsf.SetSize(self.bitmap_button_nsf.GetBestSize()) + self.bitmap_button_danse.SetSize(self.bitmap_button_danse.GetBestSize()) + self.bitmap_button_msu.SetSize(self.bitmap_button_msu.GetBestSize()) + self.bitmap_button_columbia.SetSize(self.bitmap_button_columbia.GetBestSize()) + # end wxGlade + + def __do_layout(self): + # begin wxGlade: DialogAbout.__do_layout + sizer_main = wx.BoxSizer(wx.VERTICAL) + sizer_button = wx.BoxSizer(wx.HORIZONTAL) + sizer_logos = wx.BoxSizer(wx.HORIZONTAL) + sizer_header = wx.BoxSizer(wx.HORIZONTAL) + sizer_titles = wx.BoxSizer(wx.VERTICAL) + sizer_build = wx.BoxSizer(wx.HORIZONTAL) + sizer_title = wx.BoxSizer(wx.HORIZONTAL) + sizer_header.Add(self.bitmap_logo, 0, wx.EXPAND, 0) + sizer_title.Add(self.label_title, 0, wx.EXPAND | wx.LEFT | wx.TOP, 10) + sizer_title.Add((20, 20), 0, wx.EXPAND, 0) + sizer_title.Add(self.label_version, 0, wx.ALIGN_BOTTOM | wx.RIGHT, 10) + sizer_titles.Add(sizer_title, 0, wx.EXPAND, 0) + sizer_build.Add(self.label_build, 0, wx.LEFT | wx.RIGHT, 10) + sizer_build.Add(self.label_svnrevision, 0, 0, 0) + sizer_titles.Add(sizer_build, 0, wx.EXPAND | wx.TOP, 5) + sizer_titles.Add(self.label_copyright, 0, wx.LEFT | wx.RIGHT | wx.TOP, 10) + sizer_titles.Add(self.label_author, 0, wx.LEFT | wx.RIGHT, 10) + sizer_titles.Add(self.hyperlink, 0, wx.LEFT | wx.RIGHT, 10) + sizer_titles.Add((20, 20), 0, 0, 0) + sizer_titles.Add(self.hyperlink_license, 0, wx.LEFT | wx.RIGHT, 10) + sizer_header.Add(sizer_titles, 0, wx.EXPAND, 0) + sizer_main.Add(sizer_header, 0, wx.BOTTOM | wx.EXPAND, 3) + sizer_main.Add(self.static_line_1, 0, wx.EXPAND, 0) + sizer_main.Add(self.label_acknowledgement, 0, wx.BOTTOM | wx.LEFT | wx.TOP, 7) + sizer_main.Add(self.hyperlink_paper, 0, wx.BOTTOM | wx.LEFT | wx.TOP, 7) + sizer_main.Add(self.static_line_2, 0, wx.EXPAND, 0) + sizer_logos.Add(self.bitmap_button_nsf, 0, wx.LEFT, 2) + sizer_logos.Add(self.bitmap_button_danse, 0, wx.LEFT, 2) + sizer_logos.Add(self.bitmap_button_msu, 0, wx.LEFT, 2) + sizer_logos.Add(self.bitmap_button_columbia, 0, wx.LEFT, 2) + sizer_logos.Add((50, 50), 0, 0, 0) + sizer_main.Add(sizer_logos, 0, wx.EXPAND, 0) + sizer_main.Add(self.static_line_3, 0, wx.EXPAND, 0) + sizer_button.Add((20, 20), 1, wx.EXPAND, 0) + sizer_button.Add(self.button_OK, 0, wx.RIGHT, 10) + sizer_main.Add(sizer_button, 0, wx.EXPAND, 0) + self.SetSizer(sizer_main) + self.Layout() + self.Centre() + # end wxGlade + + + + + + + + + + + +
+ + + +# end of class DialogAbout + +# testing code ########################################################### + +if __name__ == "__main__": + app = wx.App() + dialog = DialogAbout(None, -1, "") + dialog.ShowModal() +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/adddatapanel.html b/_modules/diffpy/pdfgui/gui/adddatapanel.html new file mode 100644 index 00000000..b45d3905 --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/adddatapanel.html @@ -0,0 +1,349 @@ + + + + + + + + diffpy.pdfgui.gui.adddatapanel — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.adddatapanel

+#!/usr/bin/env python
+# -*- coding: ISO-8859-1 -*-
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   (c) 2024 trustees of the Columbia University in the City
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+# generated by wxGlade 0.9.3 on Fri Jul 19 15:56:56 2019
+
+import wx
+
+from diffpy.pdfgui.gui.fittree import incrementName
+from diffpy.pdfgui.gui.pdfpanel import PDFPanel
+
+
+
+[docs] +class AddDataPanel(wx.Panel, PDFPanel): + """Panel for adding or changing data. + + Data members: + Several items must be known to this panel so it knows where to try to insert + the dataset. + entrypoint -- The FitTree item id from which we entered this panel. + entryfit -- The parent of the new dataset. + entryset -- The dataset below which to place the new set. This can be + None, which means the new dataset is appended to the end of + the entryfit. + """ + + def __init__(self, *args, **kwds): + PDFPanel.__init__(self) + # begin wxGlade: AddDataPanel.__init__ + kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL + wx.Panel.__init__(self, *args, **kwds) + + sizer_1 = wx.BoxSizer(wx.VERTICAL) + + sizer_4 = wx.BoxSizer(wx.HORIZONTAL) + sizer_1.Add(sizer_4, 0, wx.BOTTOM | wx.EXPAND | wx.TOP, 5) + + self.textLoadData = wx.StaticText(self, wx.ID_ANY, "Load a data set from file.") + self.textLoadData.SetFont( + wx.Font( + 12, + wx.FONTFAMILY_DEFAULT, + wx.FONTSTYLE_NORMAL, + wx.FONTWEIGHT_NORMAL, + 0, + "Sans", + ) + ) + sizer_4.Add(self.textLoadData, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) + + self.buttonOpen = wx.Button(self, wx.ID_OPEN, "Open") + sizer_4.Add(self.buttonOpen, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) + + self.static_line_2 = wx.StaticLine(self, wx.ID_ANY) + sizer_1.Add(self.static_line_2, 0, wx.BOTTOM | wx.EXPAND, 10) + + self.buttonCancel = wx.Button(self, wx.ID_CANCEL, "Cancel") + sizer_1.Add(self.buttonCancel, 0, wx.ALIGN_RIGHT | wx.ALL, 5) + + sizer_1.Add((450, 0), 0, 0, 0) + + self.SetSizer(sizer_1) + sizer_1.Fit(self) + + self.Layout() + + self.Bind(wx.EVT_BUTTON, self.onOpen, self.buttonOpen) + self.Bind(wx.EVT_BUTTON, self.onCancel, self.buttonCancel) + # end wxGlade + self.__customProperties() + + # UTILITY FUNCTIONS #### + + def __customProperties(self): + """Custom Properties go here.""" + self.entrypoint = None # The entrypoint on the tree + self.entryfit = None # The fit under which to insert an item + self.entryset = None # The dataset in which to insert an item + self.fullpath = "" # The last loaded dataset + return + +
+[docs] + def readConfiguration(self): + """Read the 'DATASET' configuration. + + In the 'DATASET' section of the project ConfigurationParser the + following is set by this panel. + + 'last' -- The last dataset file added to the project. This is + stored in the class variable fullpath. + """ + remember = False + if self.cP.has_option("DATASET", "remember"): + remember = self.cP.getboolean("DATASET", "remember") + + if remember: + if self.cP.has_option("DATASET", "last"): + self.fullpath = self.cP.get("DATASET", "last") + import os.path + + if not os.path.exists(self.fullpath): + self.fullpath = "" + else: + self.fullpath = "" + return
+ + +
+[docs] + def updateConfiguration(self): + """Update the configuration for the 'DATASET'.""" + if not self.cP.has_section("DATASET"): + self.cP.add_section("DATASET") + self.cP.set("DATASET", "last", self.fullpath) + return
+ + + # EVENT CODE #### + +
+[docs] + def onOpen(self, event): # wxGlade: AddDataPanel.<event_handler> + """Add a dataset to the tree from a file.""" + import os.path + + newnode = None + dir, filename = os.path.split(self.fullpath) + if not dir: + dir = self.mainFrame.workpath + matchstring = "|".join( + ( + "PDF files", + "*.gr;*.fgr;*.fit;*.cgr;*.calc", + "PDF data files (*.gr)", + "*.gr", + "PDF fit files (*.fgr)", + "*.fgr", + "PDF fit files (*.fit)", + "*.fit", + "PDF calculation files (*.cgr)", + "*.cgr", + "PDF calculation files (*.calc)", + "*.calc", + "All Files", + "*", + ) + ) + d = wx.FileDialog(None, "Choose a file", dir, "", matchstring) + if d.ShowModal() == wx.ID_OK: + self.fullpath = d.GetPath() + self.mainFrame.workpath = os.path.dirname(self.fullpath) + + # Update the configuration + self.updateConfiguration() + + # Add the item to the tree. + name = os.path.basename(self.fullpath) + + # Check the name and alter it if necessary + siblings = self.treeCtrlMain.GetChildren(self.entryfit) + names = [self.treeCtrlMain.GetItemText(i) for i in siblings] + name = incrementName(name, names) + newnode = self.treeCtrlMain.AddDataSet( + self.entryfit, name, insertafter=self.entryset, filename=self.fullpath + ) + + self.mainFrame.setMode("fitting") + self.treeCtrlMain.SetItemBold(self.entrypoint, False) + self.treeCtrlMain.UnselectAll() + self.mainFrame.makeTreeSelection(newnode) + d.Destroy() + return
+ + +
+[docs] + def onCancel(self, event): # wxGlade: AddDataPanel.<event_handler> + """Cancel this addition. + + Go back to the last panel. + """ + if self.entrypoint is None: + return + self.mainFrame.setMode("fitting") + self.treeCtrlMain.SetItemBold(self.entrypoint, False) + self.treeCtrlMain.UnselectAll() + self.mainFrame.makeTreeSelection(self.entrypoint) + return
+ + + # Methods overloaded from PDFPanel +
+[docs] + def refresh(self): + """Check the necessary tree nodes and bold text the entry point. + + Update the configuration + """ + self.readConfiguration() + + selections = self.treeCtrlMain.GetSelections() + entrypoint = selections[0] + entryset = entrypoint + entryfit = self.treeCtrlMain.GetFitRoot(entrypoint) + + # Check on the entryset and entryfit. Data sets can only be + # inserted from datasets or fits. If the entry is on a dataset, the + # entryset is the id of that dataset. Otherwise it is None. If the + # entry is on a fit, this is the entryfit. If the entry is on a + # dataset, the entryfit is its parent. + entrytype = self.treeCtrlMain.GetNodeType(entrypoint) + if entrytype != "dataset": + entryset = None + + # Prepare the window + self.entrypoint = entrypoint + self.entryset = entryset + self.entryfit = entryfit + + # Let's see it! + self.treeCtrlMain.SetItemBold(entrypoint) + self.treeCtrlMain.UnselectAll() + return
+
+ + + +# end of class AddDataPanel +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/addphasepanel.html b/_modules/diffpy/pdfgui/gui/addphasepanel.html new file mode 100644 index 00000000..0ebbcbcf --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/addphasepanel.html @@ -0,0 +1,408 @@ + + + + + + + + diffpy.pdfgui.gui.addphasepanel — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.addphasepanel

+#!/usr/bin/env python
+# -*- coding: ISO-8859-1 -*-
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+# generated by wxGlade 0.9.3 on Fri Jul 19 15:59:31 2019
+
+import wx
+
+from diffpy.pdfgui.gui.fittree import incrementName
+from diffpy.pdfgui.gui.pdfpanel import PDFPanel
+
+
+
+[docs] +class AddPhasePanel(wx.Panel, PDFPanel): + """Panel for adding a phase. + + Several items must know to this panel so it knows where to try to insert the + phase. + entrypoint -- The FitTree item id from which we entered this panel. + dataset or a calculation item. + entryfit -- The parent of the new dataset. + entryphase -- The phase below which to place the new phase. This can be + None, which means the new phase is appended to the end of + the phase section of the entryfit. + """ + + def __init__(self, *args, **kwds): + PDFPanel.__init__(self) + # begin wxGlade: AddPhasePanel.__init__ + kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL + wx.Panel.__init__(self, *args, **kwds) + + sizer_1 = wx.BoxSizer(wx.VERTICAL) + + sizer_4 = wx.BoxSizer(wx.HORIZONTAL) + sizer_1.Add(sizer_4, 0, wx.BOTTOM | wx.EXPAND | wx.TOP, 5) + + self.labelOpenPhase = wx.StaticText(self, wx.ID_ANY, "Load a structure from file.") + self.labelOpenPhase.SetFont( + wx.Font( + 12, + wx.FONTFAMILY_DEFAULT, + wx.FONTSTYLE_NORMAL, + wx.FONTWEIGHT_NORMAL, + 0, + "Sans", + ) + ) + sizer_4.Add(self.labelOpenPhase, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) + + self.buttonOpen = wx.Button(self, wx.ID_OPEN, "Open") + sizer_4.Add(self.buttonOpen, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) + + self.static_line_5 = wx.StaticLine(self, wx.ID_ANY) + sizer_1.Add(self.static_line_5, 0, wx.EXPAND, 0) + + sizer_5 = wx.BoxSizer(wx.HORIZONTAL) + sizer_1.Add(sizer_5, 0, wx.BOTTOM | wx.EXPAND | wx.TOP, 5) + + self.labelCreatePhase = wx.StaticText(self, wx.ID_ANY, "Create a structure from scratch.") + self.labelCreatePhase.SetFont( + wx.Font( + 12, + wx.FONTFAMILY_DEFAULT, + wx.FONTSTYLE_NORMAL, + wx.FONTWEIGHT_NORMAL, + 0, + "Sans", + ) + ) + sizer_5.Add(self.labelCreatePhase, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) + + self.buttonNew = wx.Button(self, wx.ID_NEW, "New") + sizer_5.Add(self.buttonNew, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) + + self.static_line_6 = wx.StaticLine(self, wx.ID_ANY) + sizer_1.Add(self.static_line_6, 0, wx.BOTTOM | wx.EXPAND, 10) + + self.buttonCancel = wx.Button(self, wx.ID_CANCEL, "Cancel") + sizer_1.Add(self.buttonCancel, 0, wx.ALIGN_RIGHT | wx.ALL, 5) + + sizer_1.Add((450, 10), 0, 0, 0) + + self.SetSizer(sizer_1) + sizer_1.Fit(self) + + self.Layout() + + self.Bind(wx.EVT_BUTTON, self.onOpen, self.buttonOpen) + self.Bind(wx.EVT_BUTTON, self.onNew, self.buttonNew) + self.Bind(wx.EVT_BUTTON, self.onCancel, self.buttonCancel) + # end wxGlade + self.__customProperties() + + # UTILITY FUNCTIONS #### + + def __customProperties(self): + """Custom Properties go here.""" + self.entrypoint = None # The entrypoint on the tree + self.entryfit = None # The fit in which to insert an item + self.entryphase = None # The phase under which to insert an item + self.fullpath = "" # The last loaded structure + return + +
+[docs] + def readConfiguration(self): + """Read the 'PHASE' configuration. + + In the 'PHASE' section of the project ConfigurationParser the + following is set by this panel. + + 'last' -- The last structure file added to the project. This is + stored in the class variable fullpath. + """ + remember = False + if self.cP.has_option("PHASE", "remember"): + remember = self.cP.getboolean("PHASE", "remember") + + if remember: + if self.cP.has_option("PHASE", "last"): + self.fullpath = self.cP.get("PHASE", "last") + import os.path + + if not os.path.exists(self.fullpath): + self.fullpath = "" + else: + self.fullpath = "" + return
+ + +
+[docs] + def updateConfiguration(self): + """Update the configuration for the 'DATASET'.""" + if not self.cP.has_section("PHASE"): + self.cP.add_section("PHASE") + self.cP.set("PHASE", "last", self.fullpath) + return
+ + + # EVENT CODE #### + +
+[docs] + def onOpen(self, event): # wxGlade: AddPhasePanel.<event_handler> + """Add a the new phase to the tree. + + The phase is added as a child of entryfit, right after the + entryphase, if it exists. If entryphase is None, the new phase + is appended to the end of the children of entryfit. + """ + import os.path + + newnode = None + dir, filename = os.path.split(self.fullpath) + if not dir: + dir = self.mainFrame.workpath + matchstring = "|".join( + ( + "Structure file", + "*.cif;*CIF;*.stru;*.STRU;*.pdb;*.PDB;*.xyz;*.XYZ", + "Crystallographic Information File (*.cif)", + "*.cif;*.CIF", + "PDFfit structure files (*.stru)", + "*.stru;*.STRU", + "Protein Data Bank files (*.pdb)", + "*.pdb;*.PDB", + "Coordinate files (*.xyz)", + "*.xyz;*.XYZ", + "All Files", + "*", + ) + ) + d = wx.FileDialog(None, "Choose a file", dir, "", matchstring) + if d.ShowModal() == wx.ID_OK: + self.fullpath = d.GetPath() + self.mainFrame.workpath = os.path.dirname(self.fullpath) + + # Update the configuration + self.updateConfiguration() + + # Add the item to the tree. + name = os.path.basename(self.fullpath) + + # Check the name and alter it if necessary + siblings = self.treeCtrlMain.GetChildren(self.entryfit) + names = [self.treeCtrlMain.GetItemText(i) for i in siblings] + name = incrementName(name, names) + + newnode = self.treeCtrlMain.AddPhase( + self.entryfit, name, insertafter=self.entryphase, filename=self.fullpath + ) + + self.mainFrame.setMode("fitting") + self.treeCtrlMain.SetItemBold(self.entrypoint, False) + self.treeCtrlMain.UnselectAll() + self.mainFrame.makeTreeSelection(newnode) + self.validateStructure(newnode) + d.Destroy() + return
+ + +
+[docs] + def onNew(self, event): # wxGlade: AddPhasePanel.<event_handler> + """Add a new item to be created from scratch.""" + # Set the name of the new phase + siblings = self.treeCtrlMain.GetChildren(self.entryfit) + names = [self.treeCtrlMain.GetItemText(i) for i in siblings] + label = "New Phase" + label = incrementName(label, names) + + # Create the phase + newnode = self.treeCtrlMain.AddPhase(self.entryfit, label, insertafter=self.entryphase) + + # Go to the new node + self.mainFrame.setMode("fitting") + self.treeCtrlMain.SetItemBold(self.entrypoint, False) + self.treeCtrlMain.UnselectAll() + self.mainFrame.makeTreeSelection(newnode) + self.treeCtrlMain.EditLabel(newnode) + return
+ + +
+[docs] + def onCancel(self, event): # wxGlade: AddPhasePanel.<event_handler> + """Cancel this addition. + + Go back to the last panel. + """ + self.mainFrame.setMode("fitting") + self.treeCtrlMain.SetItemBold(self.entrypoint, False) + self.treeCtrlMain.UnselectAll() + self.mainFrame.makeTreeSelection(self.entrypoint) + return
+ + +
+[docs] + def validateStructure(self, node): + """Make sure that the structure is valid.""" + from diffpy.pdfgui.control.controlerrors import ControlError + + dataobject = self.treeCtrlMain.GetControlData(node) + stru = dataobject.initial + for a in stru: + nonzero = 0 + for row in a.U: + nonzero += row.any() + if not nonzero: + raise ControlError("Structure has atoms with all zero ADP values.") + return
+ + + # Methods overloaded from PDFPanel +
+[docs] + def refresh(self): + """Bold text the entrypoint on the tree. + + This also reads the configuration. + """ + self.readConfiguration() + + selections = self.treeCtrlMain.GetSelections() + entrypoint = selections[0] + entryphase = entrypoint + entryfit = self.treeCtrlMain.GetFitRoot(entrypoint) + + entrytype = self.treeCtrlMain.GetNodeType(entryphase) + if entrytype != "phase": + entryphase = None + + # Prepare the window + self.entrypoint = entrypoint + self.entryphase = entryphase + self.entryfit = entryfit + + # Make the entry point bold. + self.treeCtrlMain.SetItemBold(self.entrypoint) + self.treeCtrlMain.UnselectAll() + return
+
+ + + +# end of class AddPhasePanel +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/blankpanel.html b/_modules/diffpy/pdfgui/gui/blankpanel.html new file mode 100644 index 00000000..149d0171 --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/blankpanel.html @@ -0,0 +1,145 @@ + + + + + + + + diffpy.pdfgui.gui.blankpanel — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for diffpy.pdfgui.gui.blankpanel

+#!/usr/bin/env python
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+"""This module contains the BlankPanel class."""
+
+import wx
+
+from diffpy.pdfgui.gui.pdfpanel import PDFPanel
+
+
+
+[docs] +class BlankPanel(wx.Panel, PDFPanel): + """A blank panel needed as a right panel in mainframe.py.""" + + def __init__(self, *args, **kwds): + PDFPanel.__init__(self) + wx.Panel.__init__(self, *args, **kwds) + +
+[docs] + def refresh(self): + return
+
+ + + +# end of class BlankPanel +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/bondangledialog.html b/_modules/diffpy/pdfgui/gui/bondangledialog.html new file mode 100644 index 00000000..be7f96f8 --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/bondangledialog.html @@ -0,0 +1,291 @@ + + + + + + + + diffpy.pdfgui.gui.bondangledialog — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.bondangledialog

+#!/usr/bin/env python
+# -*- coding: ISO-8859-1 -*-
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+
+import wx
+
+from diffpy.pdfgui.gui.pdfpanel import PDFPanel
+
+
+
+[docs] +class BondAngleDialog(wx.Dialog, PDFPanel): + def __init__(self, *args, **kwds): + PDFPanel.__init__(self) + kwds["style"] = wx.DEFAULT_DIALOG_STYLE + wx.Dialog.__init__(self, *args, **kwds) + self.sizer_2_staticbox = wx.StaticBox(self, -1, "Bond Angle Calculation") + self.instructionsLabel = wx.StaticText(self, -1, "Calculate the angle defined by three atoms.") + self.atomsLabel = wx.StaticText(self, -1, "Atom Indices") + self.aSpinCtrl = wx.SpinCtrl(self, -1, "1", min=1, max=1) + self.bSpinCtrl = wx.SpinCtrl(self, -1, "1", min=1, max=1) + self.cSpinCtrl = wx.SpinCtrl(self, -1, "1", min=1, max=1) + self.static_line_1 = wx.StaticLine(self, -1) + self.cancelButton = wx.Button(self, wx.ID_CANCEL, "Cancel") + self.okButton = wx.Button(self, wx.ID_OK, "OK") + + self.__set_properties() + self.__do_layout() + + self.Bind(wx.EVT_BUTTON, self.onCancel, id=wx.ID_CANCEL) + self.Bind(wx.EVT_BUTTON, self.onOk, id=wx.ID_OK) + self.Bind(wx.EVT_SPINCTRL, self.onSpin, self.aSpinCtrl) + self.Bind(wx.EVT_SPINCTRL, self.onSpin, self.bSpinCtrl) + self.Bind(wx.EVT_SPINCTRL, self.onSpin, self.cSpinCtrl) + self.__customProperties() + + def __set_properties(self): + self.SetTitle("Calculate Bond Angles") + # end wxGlade + + def __do_layout(self): + # begin wxGlade: SGStructureDialog.__do_layout + sizer_2 = wx.StaticBoxSizer(self.sizer_2_staticbox, wx.VERTICAL) + sizer_4_copy = wx.BoxSizer(wx.HORIZONTAL) + sizer_4 = wx.BoxSizer(wx.HORIZONTAL) + sizer_3 = wx.BoxSizer(wx.HORIZONTAL) + sizer_2.Add( + self.instructionsLabel, + 0, + wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.ADJUST_MINSIZE, + 5, + ) + sizer_2.Add(sizer_3, 0, wx.EXPAND, 0) + sizer_4.Add(self.atomsLabel, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.ADJUST_MINSIZE, 5) + sizer_4.Add(self.aSpinCtrl, 0, wx.ALL | wx.ADJUST_MINSIZE, 5) + sizer_4.Add(self.bSpinCtrl, 0, wx.ALL | wx.ADJUST_MINSIZE, 5) + sizer_4.Add(self.cSpinCtrl, 0, wx.ALL | wx.ADJUST_MINSIZE, 5) + sizer_2.Add(sizer_4, 0, wx.EXPAND, 0) + sizer_2.Add(self.static_line_1, 0, wx.EXPAND, 0) + sizer_4_copy.Add((0, 0), 1, wx.EXPAND | wx.ADJUST_MINSIZE, 0) + sizer_4_copy.Add(self.cancelButton, 0, wx.ALL | wx.ADJUST_MINSIZE, 5) + sizer_4_copy.Add(self.okButton, 0, wx.ALL | wx.ADJUST_MINSIZE, 5) + sizer_2.Add(sizer_4_copy, 0, wx.EXPAND, 0) + self.SetAutoLayout(True) + self.SetSizer(sizer_2) + sizer_2.Fit(self) + sizer_2.SetSizeHints(self) + self.Layout() + # end wxGlade + + # ######################################################################### + + def __customProperties(self): + """Set the custom properties.""" + self.a = 1 + self.b = 2 + self.c = 3 + return + +
+[docs] + def setStructure(self, structure): + """Set the structure and update the widgets. + + This must be called before the spin control boxes will be + settable to anything other than 1. + """ + natoms = len(structure) + self.aSpinCtrl.SetRange(1, natoms) + self.bSpinCtrl.SetRange(1, natoms) + self.cSpinCtrl.SetRange(1, natoms) + self.aSpinCtrl.SetValue(min(1, natoms)) + self.bSpinCtrl.SetValue(min(2, natoms)) + self.cSpinCtrl.SetValue(min(3, natoms)) + self.okButton.Enable(True) + if natoms < 3: + self.okButton.Enable(False) + return
+ + +
+[docs] + def getCtrlLetter(self, ctrl): + """Get the letter associated with the control.""" + if ctrl is self.aSpinCtrl: + return "a" + if ctrl is self.bSpinCtrl: + return "b" + return "c"
+ + +
+[docs] + def onSpin(self, event): + """Handle atom selection events. + + This makes sure that no two controls can have the same value. + """ + letters = ["a", "b", "c"] + ctrl = event.GetEventObject() + val = event.GetSelection() + + atomLetter = self.getCtrlLetter(ctrl) + + # Check to see if the value is increasing or decreasing + increasing = True + oldval = getattr(self, atomLetter) + if val < oldval: + increasing = False + + # Check to see if the value is equal to another. If so, move it along in + # the direction it was going. + letters.remove(atomLetter) + newval = val + loop = True + while loop: + loop = False + for letter in letters: + if newval == getattr(self, letter): + loop = True + if increasing: + newval += 1 + else: + newval -= 1 + + # Set the new value, depending on what it is. + if newval > 0 and newval <= ctrl.GetMax(): + setattr(self, atomLetter, newval) + wx.CallAfter(ctrl.SetValue, newval) + else: + setattr(self, atomLetter, oldval) + wx.CallAfter(ctrl.SetValue, oldval) + return
+ + +
+[docs] + def onOk(self, event): + event.Skip() + return
+ + +
+[docs] + def onCancel(self, event): # wxGlade: SGStructureDialog.<event_handler> + event.Skip() + return
+
+ + + +# end of class SGStructureDialog +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/bondlengthdialog.html b/_modules/diffpy/pdfgui/gui/bondlengthdialog.html new file mode 100644 index 00000000..622a18be --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/bondlengthdialog.html @@ -0,0 +1,386 @@ + + + + + + + + diffpy.pdfgui.gui.bondlengthdialog — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.bondlengthdialog

+#!/usr/bin/env python
+# -*- coding: ISO-8859-1 -*-
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2007 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+# generated by wxGlade 0.9.3 on Fri Jul 19 16:00:05 2019
+
+import wx
+
+from diffpy.pdfgui.gui.wxextensions.validators import FLOAT_ONLY, TextValidator
+
+# begin wxGlade: extracode
+# end wxGlade
+
+
+
+[docs] +class BondLengthDialog(wx.Dialog): + def __init__(self, *args, **kwds): + # begin wxGlade: BondLengthDialog.__init__ + kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_DIALOG_STYLE + wx.Dialog.__init__(self, *args, **kwds) + self.SetTitle("Calculate Bond Lengths") + + sizer_2 = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.VERTICAL) + + self.instructionsLabel = wx.StaticText(self, wx.ID_ANY, "Enter the indices of two atoms.") + sizer_2.Add(self.instructionsLabel, 0, wx.ALL, 5) + + sizer_3 = wx.BoxSizer(wx.HORIZONTAL) + sizer_2.Add(sizer_3, 0, wx.EXPAND, 0) + + self.indicesLabel = wx.StaticText(self, wx.ID_ANY, "Atom Indices") + sizer_3.Add(self.indicesLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) + + self.aSpinCtrl = wx.SpinCtrl(self, wx.ID_ANY, "", min=0, max=100, style=0) + self.aSpinCtrl.SetMinSize((80, 27)) + sizer_3.Add(self.aSpinCtrl, 0, wx.ALL, 5) + + self.bSpinCtrl = wx.SpinCtrl(self, wx.ID_ANY, "", min=0, max=100, style=0) + self.bSpinCtrl.SetMinSize((80, 27)) + sizer_3.Add(self.bSpinCtrl, 0, wx.ALL, 5) + + self.static_line_2 = wx.StaticLine(self, wx.ID_ANY) + sizer_2.Add(self.static_line_2, 0, wx.BOTTOM | wx.EXPAND, 5) + + self.instructionsLabel2 = wx.StaticText( + self, + wx.ID_ANY, + "Or enter the elemental symbols of two atoms and\nthe range over which to calculate the bond lengths.", + ) + sizer_2.Add(self.instructionsLabel2, 0, wx.ALL, 5) + + sizer_4 = wx.BoxSizer(wx.HORIZONTAL) + sizer_2.Add(sizer_4, 0, wx.EXPAND, 0) + + self.elementLabel = wx.StaticText(self, wx.ID_ANY, "Elements") + sizer_4.Add(self.elementLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) + + self.aComboBox = wx.ComboBox(self, wx.ID_ANY, choices=[], style=0) + self.aComboBox.SetMinSize((80, 27)) + sizer_4.Add(self.aComboBox, 0, wx.ALL, 5) + + self.bComboBox = wx.ComboBox(self, wx.ID_ANY, choices=[], style=0) + self.bComboBox.SetMinSize((80, 27)) + sizer_4.Add(self.bComboBox, 0, wx.ALL, 5) + + sizer_4_copy_1 = wx.BoxSizer(wx.HORIZONTAL) + sizer_2.Add(sizer_4_copy_1, 0, wx.EXPAND, 0) + + self.rangeLabel = wx.StaticText(self, wx.ID_ANY, "Range") + sizer_4_copy_1.Add(self.rangeLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) + + self.lbTextCtrl = wx.TextCtrl(self, wx.ID_ANY, "") + self.lbTextCtrl.SetMinSize((80, 27)) + sizer_4_copy_1.Add(self.lbTextCtrl, 0, wx.ALL, 5) + + self.toLabel = wx.StaticText(self, wx.ID_ANY, "to") + sizer_4_copy_1.Add(self.toLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) + + self.ubTextCtrl = wx.TextCtrl(self, wx.ID_ANY, "") + self.ubTextCtrl.SetMinSize((80, 27)) + sizer_4_copy_1.Add(self.ubTextCtrl, 0, wx.ALL, 5) + + self.static_line_1 = wx.StaticLine(self, wx.ID_ANY) + sizer_2.Add(self.static_line_1, 0, wx.EXPAND, 0) + + sizer_4_copy = wx.BoxSizer(wx.HORIZONTAL) + sizer_2.Add(sizer_4_copy, 0, wx.EXPAND, 0) + + sizer_4_copy.Add((0, 0), 1, wx.EXPAND, 0) + + self.cancelButton = wx.Button(self, wx.ID_CANCEL, "Cancel") + sizer_4_copy.Add(self.cancelButton, 0, wx.ALL, 5) + + self.okButton = wx.Button(self, wx.ID_OK, "OK") + sizer_4_copy.Add(self.okButton, 0, wx.ALL, 5) + + self.SetSizer(sizer_2) + sizer_2.Fit(self) + + self.Layout() + + self.Bind(wx.EVT_SPINCTRL, self.onSpin, self.aSpinCtrl) + self.Bind(wx.EVT_SPINCTRL, self.onSpin, self.bSpinCtrl) + self.Bind(wx.EVT_BUTTON, self.onCancel, self.cancelButton) + self.Bind(wx.EVT_BUTTON, self.onOk, self.okButton) + # end wxGlade + self.__customProperties() + + def __customProperties(self): + """Set the custom properties.""" + self.a = 1 + self.b = 2 + self.ea = "ALL" + self.eb = "ALL" + self.lb = 0 + self.ub = 0 + + # Set the textCtrl validators and focus events + textCtrls = [self.lbTextCtrl, self.ubTextCtrl] + for ctrl in textCtrls: + ctrl.SetValidator(TextValidator(FLOAT_ONLY)) + ctrl.Bind(wx.EVT_KILL_FOCUS, self.onTextKillFocus) + + self.comboBoxes = [self.aComboBox, self.bComboBox] + for cbox in self.comboBoxes: + cbox.Bind(wx.EVT_KILL_FOCUS, self.onComboKillFocus) + cbox.Bind(wx.EVT_COMBOBOX, self.onComboKillFocus) + return + +
+[docs] + def setStructure(self, structure): + """Set the structure and update the widgets. + + This must be called before the spin control boxes will be + settable to anything other than 1. + """ + self.okButton.Enable(True) + + natoms = len(structure) + if natoms < 2: + self.okButton.Enable(False) + return + + # Fill the spin controls + self.aSpinCtrl.SetRange(1, natoms) + self.bSpinCtrl.SetRange(1, natoms) + self.aSpinCtrl.SetValue(min(1, natoms)) + self.bSpinCtrl.SetValue(min(2, natoms)) + + # Fill the combo boxes + self.eList = sorted(set(a.element for a in structure)) + self.eList.insert(0, "All") + + self.aComboBox.Clear() + self.bComboBox.Clear() + for el in self.eList: + self.aComboBox.Append(el) + self.bComboBox.Append(el) + self.aComboBox.SetValue("All") + self.bComboBox.SetValue("All") + + self.lbTextCtrl.SetValue("0.0") + self.ubTextCtrl.SetValue("0.0") + return
+ + +
+[docs] + def onTextKillFocus(self, event): + self.lb = float(self.lbTextCtrl.GetValue()) + self.ub = float(self.ubTextCtrl.GetValue()) + event.Skip() + return
+ + +
+[docs] + def onComboKillFocus(self, event): + + # Verify that the combo boxes are valid + for cbox in self.comboBoxes: + val = cbox.GetValue() + if val not in self.eList: + val = "All" + cbox.SetValue(val) + + self.ea = self.aComboBox.GetValue() + self.eb = self.bComboBox.GetValue() + event.Skip() + return
+ + +
+[docs] + def getCtrlLetter(self, ctrl): + """Get the letter associated with the control.""" + if ctrl is self.aSpinCtrl: + return "a" + return "b"
+ + +
+[docs] + def onSpin(self, event): # wxGlade: BondLengthDialog.<event_handler> + letters = ["a", "b"] + ctrl = event.GetEventObject() + val = event.GetSelection() + + atomLetter = self.getCtrlLetter(ctrl) + + # Check to see if the value is increasing or decreasing + increasing = True + oldval = getattr(self, atomLetter) + if val < oldval: + increasing = False + + # Check to see if the value is equal to another. If so, move it along in + # the direction it was going. + letters.remove(atomLetter) + newval = val + loop = True + while loop: + loop = False + for letter in letters: + if newval == getattr(self, letter): + loop = True + if increasing: + newval += 1 + else: + newval -= 1 + + # Set the new value, depending on what it is. + if newval > 0 and newval <= ctrl.GetMax(): + setattr(self, atomLetter, newval) + wx.CallAfter(ctrl.SetValue, newval) + else: + setattr(self, atomLetter, oldval) + wx.CallAfter(ctrl.SetValue, oldval) + return
+ + +
+[docs] + def onCancel(self, event): # wxGlade: BondLengthDialog.<event_handler> + event.Skip()
+ + +
+[docs] + def onOk(self, event): # wxGlade: BondLengthDialog.<event_handler> + self.onTextKillFocus(event) + self.onComboKillFocus(event) + event.Skip()
+
+ + + +# end of class BondLengthDialog + + +if __name__ == "__main__": + app = wx.PySimpleApp(0) + blenDialog = BondLengthDialog(None, -1, "") + app.SetTopWindow(blenDialog) + blenDialog.Show() + app.MainLoop() +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/calculationpanel.html b/_modules/diffpy/pdfgui/gui/calculationpanel.html new file mode 100644 index 00000000..b01f193e --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/calculationpanel.html @@ -0,0 +1,427 @@ + + + + + + + + diffpy.pdfgui.gui.calculationpanel — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.calculationpanel

+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+# generated by wxGlade 0.9.3 on Fri Jul 19 16:00:20 2019
+
+import wx
+
+from diffpy.pdfgui.gui.pdfpanel import PDFPanel
+from diffpy.pdfgui.gui.wxextensions.textctrlutils import textCtrlAsGridCell
+from diffpy.pdfgui.gui.wxextensions.validators import FLOAT_ONLY, TextValidator
+
+
+
+[docs] +class CalculationPanel(wx.Panel, PDFPanel): + def __init__(self, *args, **kwds): + PDFPanel.__init__(self) + # begin wxGlade: CalculationPanel.__init__ + kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL + wx.Panel.__init__(self, *args, **kwds) + + sizer_1 = wx.BoxSizer(wx.HORIZONTAL) + + outerSizer = wx.BoxSizer(wx.VERTICAL) + sizer_1.Add(outerSizer, 1, wx.EXPAND, 0) + + sizer_panelname = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.HORIZONTAL) + outerSizer.Add(sizer_panelname, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) + + self.panelNameLabel = wx.StaticText(self, wx.ID_ANY, "Calculation Configuration") + self.panelNameLabel.SetFont( + wx.Font( + 18, + wx.FONTFAMILY_DEFAULT, + wx.FONTSTYLE_NORMAL, + wx.FONTWEIGHT_BOLD, + 0, + "", + ) + ) + sizer_panelname.Add(self.panelNameLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT, 5) + + outerSizer.Add((450, 5), 0, 0, 0) + + self.radioBoxStype = wx.RadioBox( + self, + wx.ID_ANY, + "Scatterer Type", + choices=["Neutron", "X-ray"], + majorDimension=2, + style=wx.RA_SPECIFY_COLS, + ) + self.radioBoxStype.SetMinSize((330, 43)) + self.radioBoxStype.SetSelection(0) + outerSizer.Add(self.radioBoxStype, 0, wx.ALL, 5) + + grid_sizer_1 = wx.FlexGridSizer(4, 6, 5, 10) + outerSizer.Add(grid_sizer_1, 0, wx.ALL | wx.EXPAND, 5) + + self.labelCalcRange = wx.StaticText(self, wx.ID_ANY, "Range", style=wx.ALIGN_RIGHT) + grid_sizer_1.Add( + self.labelCalcRange, + 0, + wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, + 5, + ) + + self.textCtrlCalcFrom = wx.TextCtrl(self, wx.ID_ANY, "1.0") + grid_sizer_1.Add(self.textCtrlCalcFrom, 0, wx.ALIGN_CENTER_VERTICAL, 0) + + self.labelTo = wx.StaticText(self, wx.ID_ANY, "to", style=wx.ALIGN_RIGHT) + grid_sizer_1.Add(self.labelTo, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, 20) + + self.textCtrlCalcTo = wx.TextCtrl(self, wx.ID_ANY, "10.0") + grid_sizer_1.Add(self.textCtrlCalcTo, 0, wx.ALIGN_CENTER_VERTICAL, 0) + + self.labelRStep = wx.StaticText(self, wx.ID_ANY, "spacing", style=wx.ALIGN_RIGHT) + grid_sizer_1.Add(self.labelRStep, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, 5) + + self.textCtrlRStep = wx.TextCtrl(self, wx.ID_ANY, "0.01") + grid_sizer_1.Add(self.textCtrlRStep, 0, wx.ALIGN_CENTER_VERTICAL, 0) + + self.labelScaleFactor = wx.StaticText(self, wx.ID_ANY, "Scale Factor", style=wx.ALIGN_RIGHT) + grid_sizer_1.Add( + self.labelScaleFactor, + 0, + wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, + 5, + ) + + self.textCtrlScaleFactor = wx.TextCtrl(self, wx.ID_ANY, "1.0") + grid_sizer_1.Add(self.textCtrlScaleFactor, 0, wx.ALIGN_CENTER_VERTICAL, 0) + + self.labelQmax = wx.StaticText(self, wx.ID_ANY, "Qmax", style=wx.ALIGN_RIGHT) + grid_sizer_1.Add(self.labelQmax, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, 20) + + self.textCtrlQmax = wx.TextCtrl(self, wx.ID_ANY, "25.0") + grid_sizer_1.Add(self.textCtrlQmax, 0, wx.ALIGN_CENTER_VERTICAL, 0) + + self.label_1 = wx.StaticText(self, wx.ID_ANY, "") + grid_sizer_1.Add(self.label_1, 0, 0, 0) + + self.label_1_copy = wx.StaticText(self, wx.ID_ANY, "") + grid_sizer_1.Add(self.label_1_copy, 0, 0, 0) + + self.labelQdamp = wx.StaticText(self, wx.ID_ANY, "Qdamp", style=wx.ALIGN_RIGHT) + grid_sizer_1.Add(self.labelQdamp, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, 5) + + self.textCtrlQdamp = wx.TextCtrl(self, wx.ID_ANY, "0.0") + grid_sizer_1.Add(self.textCtrlQdamp, 0, wx.ALIGN_CENTER_VERTICAL, 0) + + self.labelQbroad = wx.StaticText(self, wx.ID_ANY, "Qbroad", style=wx.ALIGN_RIGHT) + grid_sizer_1.Add(self.labelQbroad, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, 5) + + self.textCtrlQbroad = wx.TextCtrl(self, wx.ID_ANY, "0.0") + grid_sizer_1.Add(self.textCtrlQbroad, 0, wx.ALIGN_CENTER_VERTICAL, 0) + + self.label_1_copy_2 = wx.StaticText(self, wx.ID_ANY, "") + grid_sizer_1.Add(self.label_1_copy_2, 0, 0, 0) + + self.label_1_copy_1 = wx.StaticText(self, wx.ID_ANY, "") + grid_sizer_1.Add(self.label_1_copy_1, 0, 0, 0) + + self.label_1_copy_6 = wx.StaticText(self, wx.ID_ANY, "") + grid_sizer_1.Add(self.label_1_copy_6, 0, 0, 0) + + self.label_1_copy_5 = wx.StaticText(self, wx.ID_ANY, "") + grid_sizer_1.Add(self.label_1_copy_5, 0, 0, 0) + + self.label_1_copy_3 = wx.StaticText(self, wx.ID_ANY, "") + grid_sizer_1.Add(self.label_1_copy_3, 0, 0, 0) + + self.label_1_copy_4 = wx.StaticText(self, wx.ID_ANY, "") + grid_sizer_1.Add(self.label_1_copy_4, 0, 0, 0) + + self.SetSizer(sizer_1) + sizer_1.Fit(self) + + self.Layout() + + self.Bind(wx.EVT_RADIOBOX, self.onStype, self.radioBoxStype) + # end wxGlade + self.__customProperties() + + # USER CONFIGURATION CODE ################################################# + + def __customProperties(self): + """Set up the custom properties.""" + self._focusedText = None + self.calculation = None + self.stypeMap = {0: "N", 1: "X"} + + self.ctrlMap = { + "rmin": "textCtrlCalcFrom", + "rmax": "textCtrlCalcTo", + "qmax": "textCtrlQmax", + "qdamp": "textCtrlQdamp", + "qbroad": "textCtrlQbroad", + "rstep": "textCtrlRStep", + "dscale": "textCtrlScaleFactor", + } + + # Give each textCtrl a name that can be referenced and setup the + # validator + for key, value in self.ctrlMap.items(): + textCtrl = getattr(self, value) + textCtrl.SetName(key) + textCtrl.SetValidator(TextValidator(FLOAT_ONLY)) + + # Create specific bindings for the textCtrls + self.textCtrlCalcFrom.Bind(wx.EVT_KILL_FOCUS, self.onCalcRange) + self.textCtrlCalcTo.Bind(wx.EVT_KILL_FOCUS, self.onCalcRange) + self.textCtrlQmax.Bind(wx.EVT_KILL_FOCUS, self.onKillFocus) + self.textCtrlQdamp.Bind(wx.EVT_KILL_FOCUS, self.onKillFocus) + self.textCtrlQbroad.Bind(wx.EVT_KILL_FOCUS, self.onKillFocus) + self.textCtrlScaleFactor.Bind(wx.EVT_KILL_FOCUS, self.onKillFocus) + self.textCtrlRStep.Bind(wx.EVT_KILL_FOCUS, self.onCalcRange) + + # Bind the focus and key events + for key, value in self.ctrlMap.items(): + textCtrl = getattr(self, value) + textCtrl.Bind(wx.EVT_SET_FOCUS, self.onSetFocus) + textCtrl.Bind(wx.EVT_KEY_DOWN, self.onTextCtrlKey) + + return + + # Create the onTextCtrlKey event handler from textCtrlAsGridCell from + # wxextensions.textctrlutils + onTextCtrlKey = textCtrlAsGridCell + +
+[docs] + def setConfigurationData(self): + """Set the data in the panel.""" + if self.calculation: + stype = self.calculation.stype + + if stype == "N": + self.radioBoxStype.SetSelection(0) + elif stype == "X": + self.radioBoxStype.SetSelection(1) + + for key, value in self.ctrlMap.items(): + textCtrl = getattr(self, value) + + value = getattr(self.calculation, key) + + if value is not None: + textCtrl.SetValue(str(value)) + else: + textCtrl.SetValue("0.0") + return
+ + + def __coerseText(self, value): + if not value: + value = "0" + if value[-1].lower() in ("-", "e"): + value += "0" + return float(value) + + # EVENT CODE ############################################################# + +
+[docs] + def onStype(self, event): # wxGlade: CalculationPanel.<event_handler> + value = event.GetInt() + self.calculation.stype = self.stypeMap[value] + self.mainFrame.needsSave() + return
+ + +
+[docs] + def onCalcRange(self, event): # wxGlade: CalculationPanel.<event_handler> + event.Skip() + if self.calculation is None: + return + from diffpy.pdfgui.control.controlerrors import ControlValueError + + # Since calculation.rmax gets adjusted by setRGrid, + # always obtain all range parameters. + rminvalue = self.textCtrlCalcFrom.GetValue() + rstepvalue = self.textCtrlRStep.GetValue() + rmaxvalue = self.textCtrlCalcTo.GetValue() + rmin = self.__coerseText(rminvalue) + rstep = self.__coerseText(rstepvalue) + rmax = self.__coerseText(rmaxvalue) + oldrmin = self.calculation.rmin + oldrstep = self.calculation.rstep + oldrmax = self.calculation.rmax + if oldrmin == rmin and oldrstep == rstep and oldrmax == rmax: + return + + try: + self.calculation.setRGrid(rmin, rstep, rmax) + except ControlValueError: + pass + # Make sure the panels and the control are consistent + self.textCtrlCalcFrom.SetValue(str(self.calculation.rmin)) + self.textCtrlRStep.SetValue(str(self.calculation.rstep)) + self.textCtrlCalcTo.SetValue(str(self.calculation.rmax)) + self.mainFrame.needsSave() + return
+ + +
+[docs] + def onSetFocus(self, event): + """Saves a TextCtrl value, to be used later.""" + self._focusedText = event.GetEventObject().GetValue() + event.Skip() + return
+ + +
+[docs] + def onKillFocus(self, event): + textCtrl = event.GetEventObject() + value = textCtrl.GetValue() + value = self.__coerseText(value) + name = textCtrl.GetName() + oldval = getattr(self.calculation, name) + if oldval != value: + setattr(self.calculation, name, value) + self.mainFrame.needsSave() + event.Skip() + return
+ + +
+[docs] + def onExport(self, event): # wxGlade: CalculationPanel.<event_handler> + event.Skip()
+ + + # Methods overloaded from PDFPanel +
+[docs] + def refresh(self): + """Refresh the panel.""" + self.setConfigurationData() + return
+
+ + + +# end of class CalculationPanel +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/datasetconfigurepanel.html b/_modules/diffpy/pdfgui/gui/datasetconfigurepanel.html new file mode 100644 index 00000000..e35b2685 --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/datasetconfigurepanel.html @@ -0,0 +1,601 @@ + + + + + + + + diffpy.pdfgui.gui.datasetconfigurepanel — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.datasetconfigurepanel

+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+# generated by wxGlade 0.9.3 on Fri Jul 19 16:00:35 2019
+
+import wx
+
+from diffpy.pdfgui.gui import tooltips
+from diffpy.pdfgui.gui.pdfpanel import PDFPanel
+from diffpy.pdfgui.gui.wxextensions.textctrlutils import textCtrlAsGridCell
+from diffpy.pdfgui.gui.wxextensions.validators import FLOAT_ONLY, TextValidator
+
+
+
+[docs] +class DataSetConfigurePanel(wx.Panel, PDFPanel): + def __init__(self, *args, **kwds): + PDFPanel.__init__(self) + # begin wxGlade: DataSetConfigurePanel.__init__ + kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL + wx.Panel.__init__(self, *args, **kwds) + + sizer_1 = wx.BoxSizer(wx.HORIZONTAL) + + outerSizer = wx.BoxSizer(wx.VERTICAL) + sizer_1.Add(outerSizer, 1, wx.EXPAND, 0) + + sizer_panelname = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.HORIZONTAL) + outerSizer.Add(sizer_panelname, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) + + self.panelNameLabel = wx.StaticText(self, wx.ID_ANY, "Data Set Configuration") + self.panelNameLabel.SetFont( + wx.Font( + 18, + wx.FONTFAMILY_DEFAULT, + wx.FONTSTYLE_NORMAL, + wx.FONTWEIGHT_BOLD, + 0, + "", + ) + ) + sizer_panelname.Add(self.panelNameLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT, 5) + + outerSizer.Add((450, 5), 0, 0, 0) + + self.radioBoxStype = wx.RadioBox( + self, + wx.ID_ANY, + "Scatterer Type", + choices=["Neutron", "X-ray"], + majorDimension=2, + style=wx.RA_SPECIFY_COLS, + ) + self.radioBoxStype.SetMinSize((330, 43)) + self.radioBoxStype.SetSelection(0) + outerSizer.Add(self.radioBoxStype, 0, wx.ALL, 5) + + self.radioBoxSampling = wx.RadioBox( + self, + wx.ID_ANY, + "Data Sampling", + choices=["Data", "Nyquist", "Custom"], + majorDimension=3, + style=wx.RA_SPECIFY_COLS, + ) + self.radioBoxSampling.SetMinSize((232, 44)) + self.radioBoxSampling.SetSelection(0) + outerSizer.Add(self.radioBoxSampling, 0, wx.ALL, 5) + + grid_sizer_1 = wx.FlexGridSizer(5, 6, 5, 10) + outerSizer.Add(grid_sizer_1, 0, wx.ALL | wx.EXPAND, 5) + + self.labelDataRange = wx.StaticText(self, wx.ID_ANY, "Data Range") + grid_sizer_1.Add( + self.labelDataRange, + 0, + wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, + 5, + ) + + self.textCtrlDataFrom = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) + self.textCtrlDataFrom.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT)) + grid_sizer_1.Add(self.textCtrlDataFrom, 0, 0, 0) + + self.labelDataTo = wx.StaticText(self, wx.ID_ANY, "to") + grid_sizer_1.Add(self.labelDataTo, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, 20) + + self.textCtrlDataTo = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) + self.textCtrlDataTo.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT)) + grid_sizer_1.Add(self.textCtrlDataTo, 0, 0, 0) + + self.labelDataStep = wx.StaticText(self, wx.ID_ANY, "spacing") + grid_sizer_1.Add( + self.labelDataStep, + 0, + wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, + 20, + ) + + self.textCtrlDataStep = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) + self.textCtrlDataStep.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT)) + grid_sizer_1.Add(self.textCtrlDataStep, 0, 0, 0) + + self.labelFitRange = wx.StaticText(self, wx.ID_ANY, "Fit Range", style=wx.ALIGN_RIGHT) + grid_sizer_1.Add( + self.labelFitRange, + 0, + wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, + 5, + ) + + self.textCtrlFitFrom = wx.TextCtrl(self, wx.ID_ANY, "1.0") + grid_sizer_1.Add(self.textCtrlFitFrom, 0, wx.ALIGN_CENTER_VERTICAL, 0) + + self.labelFitTo = wx.StaticText(self, wx.ID_ANY, "to", style=wx.ALIGN_RIGHT) + grid_sizer_1.Add(self.labelFitTo, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, 20) + + self.textCtrlFitTo = wx.TextCtrl(self, wx.ID_ANY, "10.0") + grid_sizer_1.Add(self.textCtrlFitTo, 0, wx.ALIGN_CENTER_VERTICAL, 0) + + self.labelFitStep = wx.StaticText(self, wx.ID_ANY, "spacing") + grid_sizer_1.Add( + self.labelFitStep, + 0, + wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, + 20, + ) + + self.textCtrlFitStep = wx.TextCtrl(self, wx.ID_ANY, "0") + grid_sizer_1.Add(self.textCtrlFitStep, 0, wx.ALIGN_CENTER_VERTICAL, 0) + + self.labelScaleFactor = wx.StaticText(self, wx.ID_ANY, "Scale Factor", style=wx.ALIGN_RIGHT) + grid_sizer_1.Add( + self.labelScaleFactor, + 0, + wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, + 5, + ) + + self.textCtrlScaleFactor = wx.TextCtrl(self, wx.ID_ANY, "1.0") + grid_sizer_1.Add(self.textCtrlScaleFactor, 0, wx.ALIGN_CENTER_VERTICAL, 0) + + self.labelQmax = wx.StaticText(self, wx.ID_ANY, "Qmax", style=wx.ALIGN_RIGHT) + grid_sizer_1.Add(self.labelQmax, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, 20) + + self.textCtrlQmax = wx.TextCtrl(self, wx.ID_ANY, "25.0") + grid_sizer_1.Add(self.textCtrlQmax, 0, wx.ALIGN_CENTER_VERTICAL, 0) + + self.blank1_copy = wx.StaticText(self, wx.ID_ANY, "") + grid_sizer_1.Add(self.blank1_copy, 0, 0, 0) + + self.blank1_copy_4 = wx.StaticText(self, wx.ID_ANY, "") + grid_sizer_1.Add(self.blank1_copy_4, 0, 0, 0) + + self.labelQdamp = wx.StaticText(self, wx.ID_ANY, "Qdamp", style=wx.ALIGN_RIGHT) + grid_sizer_1.Add(self.labelQdamp, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, 5) + + self.textCtrlQdamp = wx.TextCtrl(self, wx.ID_ANY, "0.0") + grid_sizer_1.Add(self.textCtrlQdamp, 0, wx.ALIGN_CENTER_VERTICAL, 0) + + self.labelQbroad = wx.StaticText(self, wx.ID_ANY, "Qbroad", style=wx.ALIGN_RIGHT) + grid_sizer_1.Add(self.labelQbroad, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, 20) + + self.textCtrlQbroad = wx.TextCtrl(self, wx.ID_ANY, "0.0") + grid_sizer_1.Add(self.textCtrlQbroad, 0, wx.ALIGN_CENTER_VERTICAL, 0) + + self.blank1_copy_1 = wx.StaticText(self, wx.ID_ANY, "") + grid_sizer_1.Add(self.blank1_copy_1, 0, 0, 0) + + self.blank1_copy_5 = wx.StaticText(self, wx.ID_ANY, "") + grid_sizer_1.Add(self.blank1_copy_5, 0, 0, 0) + + self.labelTemperature = wx.StaticText(self, wx.ID_ANY, "Temperature", style=wx.ALIGN_RIGHT) + grid_sizer_1.Add( + self.labelTemperature, + 0, + wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, + 5, + ) + + self.textCtrlTemperature = wx.TextCtrl(self, wx.ID_ANY, "300.0") + grid_sizer_1.Add(self.textCtrlTemperature, 0, wx.ALIGN_CENTER_VERTICAL, 0) + + self.labelDoping = wx.StaticText(self, wx.ID_ANY, "Doping", style=wx.ALIGN_RIGHT) + grid_sizer_1.Add(self.labelDoping, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, 20) + + self.textCtrlDoping = wx.TextCtrl(self, wx.ID_ANY, "1.0") + grid_sizer_1.Add(self.textCtrlDoping, 0, wx.ALIGN_CENTER_VERTICAL, 0) + + self.blank1_copy_3 = wx.StaticText(self, wx.ID_ANY, "") + grid_sizer_1.Add(self.blank1_copy_3, 0, 0, 0) + + self.blank1_copy_7 = wx.StaticText(self, wx.ID_ANY, "") + grid_sizer_1.Add(self.blank1_copy_7, 0, 0, 0) + + self.SetSizer(sizer_1) + sizer_1.Fit(self) + + self.Layout() + + self.Bind(wx.EVT_RADIOBOX, self.onStype, self.radioBoxStype) + self.Bind(wx.EVT_RADIOBOX, self.onSampling, self.radioBoxSampling) + # end wxGlade + self.__customProperties() + + # USER CONFIGURATION CODE ################################################# + + def __customProperties(self): + # Set some reasonable defaults + self.configuration = None + self.constraints = {} + self.stypeMap = {0: "N", 1: "X"} + self.metaNames = ["doping", "temperature"] + self.constrainables = ["dscale", "qdamp", "qbroad"] + self.sampList = ["data", "Nyquist", "custom"] + self._focusedText = None + + # Note that the rstep and fitrstep attributes are special cases, so they + # are handled separately. Qmax is also handled with these. + self.ctrlMap = { + "fitrmin": "textCtrlFitFrom", + "fitrmax": "textCtrlFitTo", + "rmin": "textCtrlDataFrom", + "rmax": "textCtrlDataTo", + "dscale": "textCtrlScaleFactor", + "qdamp": "textCtrlQdamp", + "qbroad": "textCtrlQbroad", + "temperature": "textCtrlTemperature", + "doping": "textCtrlDoping", + } + + # Give each textCtrl a name that can be referenced and setup the + # validator + for key, value in self.ctrlMap.items(): + textCtrl = getattr(self, value) + textCtrl.SetName(key) + textCtrl.SetValidator(TextValidator(FLOAT_ONLY)) + self.textCtrlFitStep.SetValidator(TextValidator(FLOAT_ONLY)) + + # Setup the event code. + for ctrlName in self.ctrlMap.values(): + textCtrl = getattr(self, ctrlName) + textCtrl.Bind(wx.EVT_SET_FOCUS, self.onSetFocus) + textCtrl.Bind(wx.EVT_KILL_FOCUS, self.onLoseFocus) + textCtrl.Bind(wx.EVT_KEY_DOWN, self.onTextCtrlKey) + + self.textCtrlFitStep.Bind(wx.EVT_KILL_FOCUS, self.onSampling) + self.textCtrlQmax.Bind(wx.EVT_KILL_FOCUS, self.onSampling) + self.textCtrlFitStep.Bind(wx.EVT_KEY_DOWN, self.onTextCtrlKey) + self.textCtrlQmax.Bind(wx.EVT_KEY_DOWN, self.onTextCtrlKey) + + # define tooltips + self.setToolTips(tooltips.datasetconfigurepanel) + # make sure tooltips exist for all controls in `constrainables` as + # this is later assumed in restrictConstrainedParameters code + for tname in map(self.ctrlMap.get, self.constrainables): + assert getattr(self, tname).GetToolTip() is not None + + # For blocked text controls. + self.message = "This variable is constrained. Edit the associated parameter." + return + + # Create the onTextCtrlKey event handler from textCtrlAsGridCell from + # wxextensions.textctrlutils + onTextCtrlKey = textCtrlAsGridCell + +
+[docs] + def setConfigurationData(self): + """Set the values in the configuration panel. + + The values come from the configuration member dictionary. + stype -- 'N' or 'X' + dscale -- float + qmax -- float + qdamp -- float + rmin -- float + rmax -- float + fitrmin -- float + fitrmax -- float + temperature -- float + doping -- float + """ + if not self.configuration: + return + + stype = self.configuration.stype + + if stype == "N": + self.radioBoxStype.SetSelection(0) + elif stype == "X": + self.radioBoxStype.SetSelection(1) + else: + self.configuration.stype = "N" + self.radioBoxStype.SetSelection(0) + + # iterate over all configurable items + for key, value in self.ctrlMap.items(): + textCtrl = getattr(self, value) + + if key in self.metaNames: + value = self.configuration.metadata.get(key) + else: + value = getattr(self.configuration, key) + + if value is not None: + textCtrl.SetValue(str(value)) + else: + textCtrl.SetValue("0.0") + + # Set qmax + val = self.configuration.qmax + self.textCtrlQmax.SetValue(str(val)) + + # Set the data step + val = self.configuration.getObsSampling() + self.textCtrlDataStep.SetValue(str(val)) + + # Set up the sampling type and fit step type + st = self.configuration.getFitSamplingType() + si = self.sampList.index(st) + self.radioBoxSampling.SetSelection(si) + val = self.configuration.fitrstep + self.textCtrlFitStep.SetValue(str(val)) + + # Make sure the sampling info is consistent + self.onSampling(None) + return
+ + +
+[docs] + def restrictConstrainedParameters(self): + """Set 'read-only' boxes that correspond to constrained parameters.""" + if not self.configuration: + return + + self.setToolTips(tooltips.datasetconfigurepanel) + txtbg = self.textCtrlScaleFactor.DefaultStyle.BackgroundColour + + for key in self.constrainables: + value = self.ctrlMap[key] + textCtrl = getattr(self, value) + if key in self.constraints: + textCtrl.SetEditable(False) + textCtrl.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT)) + tt = textCtrl.GetToolTip() + tt.SetTip(self.constraints[key].formula) + else: + textCtrl.SetEditable(True) + textCtrl.SetBackgroundColour(txtbg) + + return
+ + + def __coerseText(self, value): + """Turn the text representation of a float into a float.""" + if not value: + value = "0" + if value[-1].lower() in ("-", "e"): + value += "0" + return float(value) + + def __adjustFitRange(self, name, value): + """Check the fit range values. + + The fit range values are set to their defaults (the data range) + when the fit range is nonsensical. + """ + if name == "fitrmin": + if value < self.configuration.rmin or value >= self.configuration.fitrmax: + value = self.configuration.rmin + self.textCtrlFitFrom.SetValue(str(value)) + elif name == "fitrmax": + if value < self.configuration.fitrmin or value >= self.configuration.rmax: + value = self.configuration.rmax + self.textCtrlFitTo.SetValue(str(value)) + return value + + # EVENT CODE ############################################################# + +
+[docs] + def onStype(self, event): # wxGlade: DataSetConfigurePanel.<event_handler> + """Record the user's selection for stype.""" + value = event.GetInt() + self.configuration.stype = self.stypeMap[value] + self.mainFrame.needsSave() + return
+ + +
+[docs] + def onSampling(self, event): # wxGlade: DataSetConfigurePanel.<event_handler> + """Record how the data is to be sampled during the fit. + + This does not use the event argument, so feel free to call this + method programmatically. + """ + si = self.radioBoxSampling.GetSelection() + oldsampling = self.configuration.getFitSamplingType() + sampling = self.sampList[si] + oldstep = self.configuration.fitrstep + # Get the value of the custom sampling and enable/disable status + if sampling == "custom": # "custom" + txtbg = self.textCtrlFitStep.DefaultStyle.BackgroundColour + step = self.__coerseText(self.textCtrlFitStep.GetValue()) + self.textCtrlFitStep.SetEditable(True) + self.textCtrlFitStep.SetBackgroundColour(txtbg) + else: + step = None + self.textCtrlFitStep.SetEditable(False) + self.textCtrlFitStep.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT)) + + # Set the value of qmax + val = self.__coerseText(self.textCtrlQmax.GetValue()) + oldqmax = self.configuration.qmax + if oldqmax != val: + self.configuration.qmax = val + self.mainFrame.needsSave() + + # Set the configured value + if oldsampling != sampling or (sampling == "custom" and oldstep != step): + self.configuration.setFitSamplingType(sampling, step) + self.mainFrame.needsSave() + # Update the text control + self.textCtrlFitStep.SetValue(str(self.configuration.fitrstep)) + + if event is not None: + event.Skip() + return
+ + +
+[docs] + def onSetFocus(self, event): + """Saves a TextCtrl value, to be used later.""" + self._focusedText = event.GetEventObject().GetValue() + event.Skip() + return
+ + +
+[docs] + def onLoseFocus(self, event): + """Record the user's selection for the text ctrl data.""" + event.Skip() + if not self.configuration: + return + textCtrl = event.GetEventObject() + value = textCtrl.GetValue() + value = self.__coerseText(value) + name = textCtrl.GetName() + # Check the fit range + value = self.__adjustFitRange(name, value) + if name in self.metaNames: + temp = self.configuration.metadata.get(name) + if temp != value: + self.configuration.metadata[name] = value + self.mainFrame.needsSave() + else: + temp = getattr(self.configuration, name) + if temp != value: + setattr(self.configuration, name, value) + self.mainFrame.needsSave() + return
+ + + # Methods overloaded from PDFPanel + +
+[docs] + def refresh(self): + """Refresh the panel.""" + self.setConfigurationData() + self.restrictConstrainedParameters() + return
+
+ + + +# end of class DataSetConfigurePanel +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/datasetconstraintpanel.html b/_modules/diffpy/pdfgui/gui/datasetconstraintpanel.html new file mode 100644 index 00000000..aa162d65 --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/datasetconstraintpanel.html @@ -0,0 +1,299 @@ + + + + + + + + diffpy.pdfgui.gui.datasetconstraintpanel — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.datasetconstraintpanel

+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+# generated by wxGlade 0.9.3 on Fri Jul 19 16:01:02 2019
+
+import wx
+
+from diffpy.pdfgui.control.constraint import Constraint
+from diffpy.pdfgui.gui import tooltips
+from diffpy.pdfgui.gui.pdfpanel import PDFPanel
+from diffpy.pdfgui.gui.wxextensions.textctrlutils import textCtrlAsGridCell
+
+
+
+[docs] +class DataSetConstraintPanel(wx.Panel, PDFPanel): + def __init__(self, *args, **kwds): + PDFPanel.__init__(self) + # begin wxGlade: DataSetConstraintPanel.__init__ + kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL + wx.Panel.__init__(self, *args, **kwds) + self.panelNameLabel = wx.StaticText(self, wx.ID_ANY, "Data Set Constraints") + self.labelScaleFactor = wx.StaticText(self, wx.ID_ANY, "Scale Factor") + self.textCtrlScaleFactor = wx.TextCtrl(self, wx.ID_ANY, "") + self.labelQdamp = wx.StaticText(self, wx.ID_ANY, "Qdamp") + self.textCtrlQdamp = wx.TextCtrl(self, wx.ID_ANY, "") + self.labelQbroad = wx.StaticText(self, wx.ID_ANY, "Qbroad") + self.textCtrlQbroad = wx.TextCtrl(self, wx.ID_ANY, "") + + self.__set_properties() + self.__do_layout() + # end wxGlade + self.__customProperties() + + def __set_properties(self): + # begin wxGlade: DataSetConstraintPanel.__set_properties + self.panelNameLabel.SetFont( + wx.Font( + 18, + wx.FONTFAMILY_DEFAULT, + wx.FONTSTYLE_NORMAL, + wx.FONTWEIGHT_BOLD, + 0, + "", + ) + ) + # end wxGlade + + def __do_layout(self): + # begin wxGlade: DataSetConstraintPanel.__do_layout + sizer_1 = wx.BoxSizer(wx.VERTICAL) + grid_sizer_1 = wx.FlexGridSizer(3, 2, 5, 10) + sizer_panelname = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.HORIZONTAL) + sizer_panelname.Add(self.panelNameLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT, 5) + sizer_1.Add(sizer_panelname, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) + grid_sizer_1.Add( + self.labelScaleFactor, + 0, + wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, + 5, + ) + grid_sizer_1.Add(self.textCtrlScaleFactor, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + grid_sizer_1.Add(self.labelQdamp, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, 5) + grid_sizer_1.Add(self.textCtrlQdamp, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + grid_sizer_1.Add(self.labelQbroad, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, 5) + grid_sizer_1.Add(self.textCtrlQbroad, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + sizer_1.Add(grid_sizer_1, 0, wx.ALL | wx.EXPAND, 5) + self.SetSizer(sizer_1) + sizer_1.Fit(self) + self.Layout() + # end wxGlade + + # USER CONFIGURATION CODE ################################################# + + def __customProperties(self): + self._focusedText = None + self.constraints = {} + self.ctrlMap = { + "dscale": "textCtrlScaleFactor", + "qdamp": "textCtrlQdamp", + "qbroad": "textCtrlQbroad", + } + + # Give each textCtrl a name that can be referenced + for key, value in self.ctrlMap.items(): + textCtrl = getattr(self, value) + textCtrl.SetName(key) + + # Setup the event code. + for ctrlName in self.ctrlMap.values(): + textCtrl = getattr(self, ctrlName) + textCtrl.Bind(wx.EVT_SET_FOCUS, self.onSetFocus) + textCtrl.Bind(wx.EVT_KILL_FOCUS, self.onLoseFocus) + textCtrl.Bind(wx.EVT_KEY_DOWN, self.onTextCtrlKey) + + # Define tooltips. + self.setToolTips(tooltips.datasetconstraintpanel) + return + + # Create the onTextCtrlKey event handler from textCtrlAsGridCell from + # wxextensions.textctrlutils + onTextCtrlKey = textCtrlAsGridCell + +
+[docs] + def setConstraintsData(self): + """Set the values in the constraints panel. + + The values come from the constraints member dictionary. dscale + qdamp qbroad + """ + for par, ctrlName in self.ctrlMap.items(): + textCtrl = getattr(self, ctrlName) + if par in self.constraints: + val = self.constraints[par].formula + textCtrl.SetValue(val) + else: + textCtrl.SetValue("") + return
+ + +
+[docs] + def processFormula(self, value, parname): + """Process a formula that was entered into a textCtrl.""" + formula = value.strip() + oldconst = self.constraints.get(parname) + oldformula = "" + if oldconst: + oldformula = oldconst.formula + if formula == "": + self.constraints.pop(parname, None) + elif oldformula != formula: + # Let the PDFGui error handler take care of this + self.constraints[parname] = Constraint(formula) + self.mainFrame.needsSave() + + return
+ + + # EVENT CODE ############################################################# +
+[docs] + def onSetFocus(self, event): + """Saves a TextCtrl value, to be compared in onKillFocus later.""" + self._focusedText = event.GetEventObject().GetValue() + event.Skip() + return
+ + +
+[docs] + def onLoseFocus(self, event): + """Record the user's selection for the text ctrl data.""" + textCtrl = event.GetEventObject() + value = textCtrl.GetValue() + par = textCtrl.GetName() + self.processFormula(value, par) + if par in self.constraints: + val = self.constraints[par].formula + textCtrl.SetValue(val) + else: + textCtrl.SetValue("") + event.Skip() + return
+ + + # Methods overloaded from PDFPanel +
+[docs] + def refresh(self): + """Refresh the panel.""" + # Set the constraints data + self.setConstraintsData() + return
+
+ + + +# end of class DataSetConstraintPanel +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/datasetpanel.html b/_modules/diffpy/pdfgui/gui/datasetpanel.html new file mode 100644 index 00000000..0bdedff1 --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/datasetpanel.html @@ -0,0 +1,249 @@ + + + + + + + + diffpy.pdfgui.gui.datasetpanel — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.datasetpanel

+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+# generated by wxGlade 0.9.3 on Fri Jul 19 16:01:11 2019
+
+import wx
+
+from diffpy.pdfgui.gui.datasetconfigurepanel import DataSetConfigurePanel
+from diffpy.pdfgui.gui.datasetconstraintpanel import DataSetConstraintPanel
+from diffpy.pdfgui.gui.datasetresultspanel import DataSetResultsPanel
+from diffpy.pdfgui.gui.pdfpanel import PDFPanel
+
+
+
+[docs] +class DataSetPanel(wx.Panel, PDFPanel): + def __init__(self, *args, **kwds): + PDFPanel.__init__(self) + # begin wxGlade: DataSetPanel.__init__ + kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL + wx.Panel.__init__(self, *args, **kwds) + self.dataSetNotebook = wx.Notebook(self, wx.ID_ANY, style=0) + self.configurePage = wx.Panel(self.dataSetNotebook, wx.ID_ANY) + self.configurePanel = DataSetConfigurePanel(self.configurePage, wx.ID_ANY) + self.constraintsPage = wx.Panel(self.dataSetNotebook, wx.ID_ANY) + self.constraintPanel = DataSetConstraintPanel(self.constraintsPage, wx.ID_ANY) + self.resultsPage = wx.Panel(self.dataSetNotebook, wx.ID_ANY) + self.resultsPanel = DataSetResultsPanel(self.resultsPage, wx.ID_ANY) + + self.__set_properties() + self.__do_layout() + + self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.onNotebookChanged, self.dataSetNotebook) + # end wxGlade + self.__customProperties() + + def __set_properties(self): + # begin wxGlade: DataSetPanel.__set_properties + pass + # end wxGlade + + def __do_layout(self): + # begin wxGlade: DataSetPanel.__do_layout + sizer_3 = wx.BoxSizer(wx.VERTICAL) + sizer_7 = wx.BoxSizer(wx.HORIZONTAL) + sizer_6 = wx.BoxSizer(wx.HORIZONTAL) + sizer_1 = wx.BoxSizer(wx.HORIZONTAL) + sizer_1.Add(self.configurePanel, 1, wx.EXPAND, 0) + self.configurePage.SetSizer(sizer_1) + sizer_6.Add(self.constraintPanel, 1, wx.EXPAND, 0) + self.constraintsPage.SetSizer(sizer_6) + sizer_7.Add(self.resultsPanel, 1, wx.EXPAND, 0) + self.resultsPage.SetSizer(sizer_7) + self.dataSetNotebook.AddPage(self.configurePage, "Configure") + self.dataSetNotebook.AddPage(self.constraintsPage, "Constraints") + self.dataSetNotebook.AddPage(self.resultsPage, "Results") + sizer_3.Add(self.dataSetNotebook, 1, wx.EXPAND, 0) + self.SetSizer(sizer_3) + sizer_3.Fit(self) + self.Layout() + # end wxGlade + + # USER CONFIGURATION CODE ################################################# + + def __customProperties(self): + self.configuration = {} + self.constraints = {} + self.results = {} + + # Methods overloaded from PDFPanel +
+[docs] + def refresh(self): + self.configurePanel.treeCtrlMain = self.treeCtrlMain + self.constraintPanel.treeCtrlMain = self.treeCtrlMain + self.resultsPanel.treeCtrlMain = self.treeCtrlMain + self.configurePanel.mainFrame = self.mainFrame + self.constraintPanel.mainFrame = self.mainFrame + self.resultsPanel.mainFrame = self.mainFrame + self.configurePanel.configuration = self.configuration + self.configurePanel.constraints = self.constraints + self.constraintPanel.constraints = self.constraints + self.resultsPanel.results = self.results + + # Refresh the visible panel + self.refreshSelectedPage() + return
+ + +
+[docs] + def refreshSelectedPage(self): + """Refresh the panel corresponding to the currently selected page.""" + # self.configurePanel.refresh() + # self.constraintPanel.refresh() + # self.resultsPanel.refresh() + id = self.dataSetNotebook.GetCurrentPage().GetId() + if id == self.configurePage.GetId(): + self.configurePanel.refresh() + elif id == self.constraintsPage.GetId(): + self.constraintPanel.refresh() + elif id == self.resultsPage.GetId(): + self.resultsPanel.refresh() + return id
+ + + # EVENT CODE ############################################################# + +
+[docs] + def onNotebookChanged(self, event): # wxGlade: DataSetPanel.<event_handler> + """Refresh the selected panel.""" + self.refreshSelectedPage() + return
+ + + # Overloaded from Panel. +
+[docs] + def Enable(self, enable=True): + """Keep the notebook enabled, just not the panels.""" + self.configurePanel.Enable(enable) + self.constraintPanel.Enable(enable) + self.resultsPanel.Enable(enable) + return
+
+ + + +# end of class DataSetPanel +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/datasetresultspanel.html b/_modules/diffpy/pdfgui/gui/datasetresultspanel.html new file mode 100644 index 00000000..bba31942 --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/datasetresultspanel.html @@ -0,0 +1,253 @@ + + + + + + + + diffpy.pdfgui.gui.datasetresultspanel — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.datasetresultspanel

+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+# generated by wxGlade 0.9.3 on Fri Jul 19 16:01:22 2019
+
+from __future__ import print_function
+
+import wx
+
+from diffpy.pdfgui.gui import tooltips
+from diffpy.pdfgui.gui.pdfpanel import PDFPanel
+
+
+
+[docs] +class DataSetResultsPanel(wx.Panel, PDFPanel): + def __init__(self, *args, **kwds): + # begin wxGlade: DataSetResultsPanel.__init__ + kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL + wx.Panel.__init__(self, *args, **kwds) + + sizer_7 = wx.BoxSizer(wx.VERTICAL) + + sizer_panelname = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.HORIZONTAL) + sizer_7.Add(sizer_panelname, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) + + self.panelNameLabel = wx.StaticText(self, wx.ID_ANY, "Data Set Results") + self.panelNameLabel.SetFont( + wx.Font( + 18, + wx.FONTFAMILY_DEFAULT, + wx.FONTSTYLE_NORMAL, + wx.FONTWEIGHT_BOLD, + 0, + "", + ) + ) + sizer_panelname.Add(self.panelNameLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT, 5) + + grid_sizer_1 = wx.FlexGridSizer(3, 2, 5, 10) + sizer_7.Add(grid_sizer_1, 0, wx.ALL | wx.EXPAND, 5) + + self.labelScaleFactor = wx.StaticText(self, wx.ID_ANY, "Scale Factor") + grid_sizer_1.Add( + self.labelScaleFactor, + 0, + wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, + 5, + ) + + self.textCtrlScaleFactor = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) + grid_sizer_1.Add(self.textCtrlScaleFactor, 0, wx.ALIGN_CENTER_VERTICAL, 20) + + self.labelQdamp = wx.StaticText(self, wx.ID_ANY, "Qdamp") + grid_sizer_1.Add(self.labelQdamp, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, 5) + + self.textCtrlQdamp = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) + grid_sizer_1.Add(self.textCtrlQdamp, 0, wx.ALIGN_CENTER_VERTICAL, 20) + + self.labelQbroad = wx.StaticText(self, wx.ID_ANY, "Qbroad") + grid_sizer_1.Add(self.labelQbroad, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, 5) + + self.textCtrlQbroad = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) + grid_sizer_1.Add(self.textCtrlQbroad, 0, wx.ALIGN_CENTER_VERTICAL, 20) + + self.buttonExport = wx.Button(self, wx.ID_OPEN, "Export PDF") + self.buttonExport.Hide() + sizer_7.Add(self.buttonExport, 0, wx.ALIGN_RIGHT | wx.ALL, 5) + + self.SetSizer(sizer_7) + sizer_7.Fit(self) + + self.Layout() + + self.Bind(wx.EVT_BUTTON, self.onExport, self.buttonExport) + # end wxGlade + self.__customProperties() + + # USER CONFIGURATION CODE ################################################# + + def __customProperties(self): + self.results = {} + self.ctrlMap = { + "dscale": "textCtrlScaleFactor", + "qdamp": "textCtrlQdamp", + "qbroad": "textCtrlQbroad", + } + # Define tooltips. + self.setToolTips(tooltips.datasetresultspanel) + return + +
+[docs] + def setResultsData(self): + """Set the values in the results panel. + + The values are taken from the results member dictionary. + dscale -- float + qdamp -- float + qbroad -- float + """ + for name in self.ctrlMap: + value = self.results.get(name, None) + ctrlName = self.ctrlMap[name] + textCtrl = getattr(self, ctrlName) + if value is not None: + textCtrl.SetValue(str(value)) + else: + textCtrl.SetValue("") + return
+ + + # EVENT CODE ############################################################# + +
+[docs] + def onExport(self, event): # wxGlade: DataSetResultsPanel.<event_handler> + print("Event handler `onExport' not implemented") + event.Skip()
+ + + # Methods overloaded from PDFPanel +
+[docs] + def refresh(self): + """Refresh the panel.""" + # Set the results data + self.setResultsData() + return
+
+ + + +# end of class DataSetResultsPanel +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/debugoptions.html b/_modules/diffpy/pdfgui/gui/debugoptions.html new file mode 100644 index 00000000..cb7ffcd6 --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/debugoptions.html @@ -0,0 +1,186 @@ + + + + + + + + diffpy.pdfgui.gui.debugoptions — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.debugoptions

+#!/usr/bin/env python
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Pavol Juhas
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+"""DebugOptions class for storing guess three time what.
+
+There should be exactly one instance of DebugOptions in pdfguiglobals
+module.
+"""
+
+
+
+[docs] +class DebugOptions: + """DebugOptions is a place to store various debugging options. There should + be just one instance defined in pdfguiglobals module. It would be nice to + have a simple way of setting them on command line. + + Options in short and long forms: + noed, noerrordialog -- [False], disable exceptions catching and + display in ErrorReportDialog + nocf, noconfirm -- boolean (default False), exit without asking to + save modified project file + pdb, pythondebugger -- use python debugger to handle error exceptions + instead of ErrorReportDialog + """ + + # global list of all options + alldebugoptions = ( + ("noed", "noerrordialog"), + ("nocf", "noconfirm"), + ("pdb", "pythondebugger"), + ) + # global dictionary for converting long options to short + short2long = dict(alldebugoptions) + + def __init__(self): + """Initialize DebugOptions, by default all of them are off.""" + self.noerrordialog = False + self.noconfirm = False + self.pythondebugger = False + return + + def __setattr__(self, name, value): + """Map short options to their long equivalents.""" + if name in DebugOptions.short2long: + longname = DebugOptions.short2long[name] + else: + longname = name + self.__dict__[longname] = value + return + + def __getattr__(self, name): + """Resolve values of short options. This is called only when normal + lookup fails. + + returns value of short debug option + """ + if name in DebugOptions.short2long: + longname = DebugOptions.short2long[name] + value = getattr(self, longname) + else: + raise AttributeError("An instance has no attribute %r" % name) + return value
+ + + +# End of class DebugOptions + +# End of file +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/dopingseriespanel.html b/_modules/diffpy/pdfgui/gui/dopingseriespanel.html new file mode 100644 index 00000000..515c5fdd --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/dopingseriespanel.html @@ -0,0 +1,525 @@ + + + + + + + + diffpy.pdfgui.gui.dopingseriespanel — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.dopingseriespanel

+#!/usr/bin/env python
+# -*- coding: ISO-8859-1 -*-
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+# generated by wxGlade 0.9.3 on Fri Jul 19 16:14:31 2019
+
+import os.path
+import re
+
+import wx
+
+from diffpy.pdfgui.control.pdfguimacros import makeDopingSeries
+from diffpy.pdfgui.gui import tooltips
+from diffpy.pdfgui.gui.pdfpanel import PDFPanel
+from diffpy.pdfgui.gui.wxextensions.listctrls import AutoWidthListCtrl
+from diffpy.pdfgui.gui.wxextensions.validators import ALPHA_ONLY, TextValidator
+
+
+
+[docs] +class DopingSeriesPanel(wx.Panel, PDFPanel): + def __init__(self, *args, **kwds): + PDFPanel.__init__(self) + # begin wxGlade: DopingSeriesPanel.__init__ + kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL + wx.Panel.__init__(self, *args, **kwds) + + sizer_1 = wx.BoxSizer(wx.VERTICAL) + + self.instructionsLabel = wx.StaticText( + self, + wx.ID_ANY, + "Select a fit from the tree on the left then add datasets and " + + "assign\ndoping elements and values below. " + + "If you have not set up a fit to be\nthe template for the series, " + + "hit cancel and rerun this macro once a\nfit has been created.", + ) + self.instructionsLabel.SetFont( + wx.Font( + 10, + wx.FONTFAMILY_DEFAULT, + wx.FONTSTYLE_NORMAL, + wx.FONTWEIGHT_NORMAL, + 0, + "Sans", + ) + ) + sizer_1.Add(self.instructionsLabel, 0, wx.ALL | wx.EXPAND, 5) + + sizer_6 = wx.BoxSizer(wx.HORIZONTAL) + sizer_1.Add(sizer_6, 0, wx.EXPAND, 0) + + self.labelBaseElement = wx.StaticText(self, wx.ID_ANY, "Base element") + sizer_6.Add(self.labelBaseElement, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) + + self.textCtrlBaseElement = wx.TextCtrl(self, wx.ID_ANY, "") + sizer_6.Add(self.textCtrlBaseElement, 0, wx.ALL, 5) + + self.labelDopant = wx.StaticText(self, wx.ID_ANY, "Dopant") + sizer_6.Add(self.labelDopant, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) + + self.textCtrlDopant = wx.TextCtrl(self, wx.ID_ANY, "") + sizer_6.Add(self.textCtrlDopant, 0, wx.ALL, 5) + + sizer_2 = wx.BoxSizer(wx.VERTICAL) + sizer_1.Add(sizer_2, 1, wx.EXPAND, 0) + + sizer_4 = wx.BoxSizer(wx.HORIZONTAL) + sizer_2.Add(sizer_4, 1, wx.EXPAND, 0) + + self.listCtrlFiles = AutoWidthListCtrl( + self, wx.ID_ANY, style=wx.BORDER_SUNKEN | wx.LC_EDIT_LABELS | wx.LC_REPORT + ) + sizer_4.Add(self.listCtrlFiles, 1, wx.ALL | wx.EXPAND, 5) + + sizer_5 = wx.BoxSizer(wx.VERTICAL) + sizer_4.Add(sizer_5, 0, wx.EXPAND, 0) + + sizer_5.Add((0, 0), 1, 0, 0) + + self.buttonUp = wx.BitmapButton(self, wx.ID_ANY, wx.NullBitmap) + self.buttonUp.SetSize(self.buttonUp.GetBestSize()) + sizer_5.Add(self.buttonUp, 0, wx.ALL, 5) + + self.buttonDown = wx.BitmapButton(self, wx.ID_ANY, wx.NullBitmap) + self.buttonDown.SetSize(self.buttonDown.GetBestSize()) + sizer_5.Add(self.buttonDown, 0, wx.ALL, 5) + + sizer_5.Add((0, 0), 1, 0, 0) + + grid_sizer_1 = wx.GridSizer(1, 2, 10, 10) + sizer_1.Add(grid_sizer_1, 0, wx.ALL, 5) + + self.buttonAdd = wx.Button(self, wx.ID_ADD, "Add") + grid_sizer_1.Add(self.buttonAdd, 0, 0, 0) + + self.buttonDelete = wx.Button(self, wx.ID_DELETE, "Delete") + grid_sizer_1.Add(self.buttonDelete, 0, 0, 0) + + self.static_line_1 = wx.StaticLine(self, wx.ID_ANY) + sizer_1.Add(self.static_line_1, 0, wx.EXPAND, 0) + + sizer_3 = wx.BoxSizer(wx.HORIZONTAL) + sizer_1.Add(sizer_3, 0, wx.EXPAND, 0) + + sizer_3.Add((20, 20), 1, wx.EXPAND, 0) + + self.goButton = wx.Button(self, wx.ID_OK, "OK") + sizer_3.Add(self.goButton, 0, wx.ALL, 5) + + self.cancelButton = wx.Button(self, wx.ID_CANCEL, "Cancel") + sizer_3.Add(self.cancelButton, 0, wx.ALL, 5) + + self.SetSizer(sizer_1) + sizer_1.Fit(self) + + self.Layout() + + self.Bind(wx.EVT_LIST_COL_CLICK, self.onColClick, self.listCtrlFiles) + self.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.onEndLabelEdit, self.listCtrlFiles) + self.Bind(wx.EVT_BUTTON, self.onUp, self.buttonUp) + self.Bind(wx.EVT_BUTTON, self.onDown, self.buttonDown) + self.Bind(wx.EVT_BUTTON, self.onAdd, self.buttonAdd) + self.Bind(wx.EVT_BUTTON, self.onDelete, self.buttonDelete) + self.Bind(wx.EVT_BUTTON, self.onOK, self.goButton) + self.Bind(wx.EVT_BUTTON, self.onCancel, self.cancelButton) + # end wxGlade + self.__customProperties() + + def __customProperties(self): + """Set the custom properties.""" + self.fit = None + self.reverse = False # Reverse the sort? + self.fullpath = "" + self.datasets = [] # Contains (doping, filename) tuples + # doping comes first for easy sorting + + self.listCtrlFiles.InsertColumn(0, "Doping") + self.listCtrlFiles.InsertColumn(1, "Data Set") + self.listCtrlFiles.SetColumnWidth(0, -2) + + # Set the validators + self.textCtrlBaseElement.SetValidator(TextValidator(ALPHA_ONLY)) + self.textCtrlDopant.SetValidator(TextValidator(ALPHA_ONLY)) + + # Define tooltips. + self.setToolTips(tooltips.dopingseriespanel) + return + +
+[docs] + def onColClick(self, event): # wxGlade: DopingSeriesPanel.<event_handler> + """Sort by doping.""" + self.datasets.sort() + if self.reverse: + self.datasets.reverse() + self.reverse = not self.reverse + self.fillList() + return
+ + +
+[docs] + def onEndLabelEdit(self, event): # wxGlade: DopingSeriesPanel.<event_handler> + """Update the doping in the datasets.""" + index = event.GetIndex() + text = event.GetText() + doping = 0.0 + try: + doping = float(text) + except ValueError: + event.Veto() + return + if doping < 0 or doping > 1: + event.Veto() + return + # update the internal information + self.datasets[index][0] = doping + self.reverse = False + return
+ + +
+[docs] + def onUp(self, event): # wxGlade: DopingSeriesPanel.<event_handler> + """Move an item in the list up.""" + index = self.listCtrlFiles.GetFirstSelected() + if index > 0: + temp = self.datasets[index] + self.datasets[index] = self.datasets[index - 1] + self.datasets[index - 1] = temp + self.fillList() + self.listCtrlFiles.Select(index - 1) + return
+ + +
+[docs] + def onDown(self, event): # wxGlade: DopingSeriesPanel.<event_handler> + """Move an item in the list down.""" + index = self.listCtrlFiles.GetFirstSelected() + if index > -1 and index != len(self.datasets) - 1: + temp = self.datasets[index] + self.datasets[index] = self.datasets[index + 1] + self.datasets[index + 1] = temp + self.fillList() + self.listCtrlFiles.Select(index + 1) + return
+ + +
+[docs] + def onAdd(self, event): # wxGlade: DopingSeriesPanel.<event_handler> + """Append files to the list.""" + dir, filename = os.path.split(self.fullpath) + if not dir: + dir = self.mainFrame.workpath + + matchstring = ( + "PDF data files (*.gr)|*.gr|PDF fit files (*.fgr)|*.fgr|PDF fit files (*.fit)|" + "*.fit|PDF calculation files (*.cgr)|*.cgr|PDF calculation files (*.calc)|*.calc|" + "All Files|*" + ) + d = wx.FileDialog( + None, + "Choose files", + dir, + "", + matchstring, + wx.FD_OPEN | wx.FD_FILE_MUST_EXIST | wx.FD_MULTIPLE, + ) + paths = [] + if d.ShowModal() == wx.ID_OK: + paths = d.GetPaths() + d.Destroy() + + # Assign the doping. Default to 0.0 + newdatasets = [] + for path in paths: + self.fullpath = path + self.mainFrame.workpath = os.path.dirname(self.fullpath) + + # Look for the doping in the filename + doping = 0.0 + rx = {"f": r"(?:\d+(?:\.\d*)?|\d*\.\d+)"} + # Search for x123, X123, doping123, Doping123. + # Is there a better regexp? Probably... + regexp = r"(?:X|x|Doping|doping)(%(f)s)" % rx + res = re.search(regexp, os.path.basename(path)) + if res: + doping = float(res.groups()[0]) + else: + # Look in the file + infile = open(path, "r") + datastring = infile.read() + infile.close() + # Look for it first in the file + res = re.search(r"^#+ start data\s*(?:#.*\s+)*", datastring, re.M) + # start_data is position where the first data line starts + if res: + start_data = res.end() + else: + res = re.search(r"^[^#]", datastring, re.M) + if res: + start_data = res.start() + else: + start_data = 0 + header = datastring[:start_data] + # parse header to get doping + regexp = r"\b(?:x|doping)\ *=\ *(%(f)s)\b" % rx + res = re.search(regexp, header) + if res: + doping = float(res.groups()[0]) + # Add the new path + if doping < 0: + doping = 0.0 + newdatasets.append([doping, path]) + + self.datasets.extend(newdatasets) + self.fillList() + return
+ + +
+[docs] + def onDelete(self, event): # wxGlade: DopingSeriesPanel.<event_handler> + """Delete selected files from the list.""" + idxlist = [] + item = self.listCtrlFiles.GetFirstSelected() + while item != -1: + idxlist.append(item) + item = self.listCtrlFiles.GetNextSelected(item) + + idxlist.reverse() + for item in idxlist: + del self.datasets[item] + self.fillList() + return
+ + +
+[docs] + def onOK(self, event): # wxGlade: DopingSeriesPanel.<event_handler> + """Let's go!""" + dvals = [tp[0] for tp in self.datasets] + paths = [tp[1] for tp in self.datasets] + base = self.textCtrlBaseElement.GetValue() + dopant = self.textCtrlDopant.GetValue() + # Value checks will take place in makeDopingSeries + org = makeDopingSeries(self.mainFrame.control, self.fit, base, dopant, paths, dvals) + self.treeCtrlMain.ExtendProjectTree(org, clear=False) + self.mainFrame.needsSave() + self.onCancel(event) + return
+ + +
+[docs] + def onCancel(self, event): # wxGlade: DopingSeriesPanel.<event_handler> + """Let's go, but not actually do anything.""" + self.mainFrame.setMode("fitting") + self.treeCtrlMain.UnselectAll() + self.mainFrame.switchRightPanel("blank") + return
+ + + # Utility functions +
+[docs] + def checkConfiguration(self): + """Verify that the dopant and base are elements. + + More detailed checking is done in the control method. + """ + from diffpy.pdffit2 import is_element + from diffpy.pdfgui.control.controlerrors import ControlValueError + + base = self.textCtrlBaseElement.GetValue() + dopant = self.textCtrlDopant.GetValue() + # Make sure that the base and dopant are actual elements + base = base.title() + dopant = dopant.title() + if not is_element(base): + raise ControlValueError("'%s' is not an element!" % base) + if not is_element(dopant): + raise ControlValueError("'%s' is not an element!" % dopant) + return
+ + +
+[docs] + def fillList(self): + """Fill the list with the datasets.""" + self.listCtrlFiles.DeleteAllItems() + names = [pair[1] for pair in self.datasets] + cp = os.path.commonprefix(names) + # We want to break at the last path/separator in the common prefix + idx = cp.rfind(os.path.sep) + if idx == -1: + idx = len(cp) + for doping, filename in self.datasets: + shortname = "..." + filename[idx:] + # index = self.listCtrlFiles.InsertItem(sys.maxsize, str(doping)) #doesn't work for windows + index = self.listCtrlFiles.InsertItem(100000, str(doping)) # doesn't work for windows + self.listCtrlFiles.SetItem(index, 1, shortname) + return
+ + + # Needed by mainframe +
+[docs] + def treeSelectionUpdate(self, node): + """Set the current fit when the tree selection changes.""" + nodetype = self.treeCtrlMain.GetNodeType(node) + if nodetype == "fit": + self.fit = self.treeCtrlMain.GetControlData(node) + self.refresh() + return
+ + + # Required by PDFPanel +
+[docs] + def refresh(self): + """Block out OK button if there is no fit. + + This also blocks OK if the fit has no datasets or structures. + """ + # We can't rely on Veto to block unwanted tree selections on windows. + # So, we have to check for errors here. + node = None + nodetype = None + selections = self.treeCtrlMain.GetSelections() + if selections: + node = selections[0] + nodetype = self.treeCtrlMain.GetNodeType(node) + + if node and nodetype == "fit" and self.fit and self.fit.hasDataSets() and self.fit.hasStructures(): + self.goButton.Enable() + else: + self.goButton.Enable(False) + return
+
+ + + +# end of class DopingSeriesPanel +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/errorreportdialog.html b/_modules/diffpy/pdfgui/gui/errorreportdialog.html new file mode 100644 index 00000000..8599bb0f --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/errorreportdialog.html @@ -0,0 +1,376 @@ + + + + + + + + diffpy.pdfgui.gui.errorreportdialog — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.errorreportdialog

+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Dmitriy Bryndin
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+# generated by wxGlade 0.9.3 on Fri Jul 19 16:01:37 2019
+
+import re
+import webbrowser
+
+#
+# "Bug report" Dialog
+#
+import wx
+import wx.html
+
+# Constants ------------------------------------------------------------------
+
+ISSUESTRACKER = "https://github.com/diffpy/diffpy.pdfgui/issues"
+USERSMAILINGLIST = "https://groups.google.com/d/forum/diffpy-users"
+_WEBSEARCHURL = "https://www.google.com/search?q={query}"
+
+_MSG_TRAILER = """
+<p>
+You can view current bug reports and feature requests at
+<a href="{issues}">{issues}</a>.
+</p><p>
+Discuss PDFgui and learn about new developments and features at
+<a href="{mlist}">{mlist}</a>.
+</p>
+""".format(
+    issues=ISSUESTRACKER, mlist=USERSMAILINGLIST
+)
+
+_MSG_FEATURE_REQUEST = (
+    """
+<p>
+Share you thoughts about PDFgui!
+</p>
+"""
+    + _MSG_TRAILER
+)
+
+_MSG_ERROR_REPORT = (
+    """
+<p>
+PDFgui has encountered a problem.  We are sorry for the inconvenience.
+</p><p>
+"""
+    + _MSG_TRAILER
+)
+
+# ----------------------------------------------------------------------------
+
+
+
+[docs] +class ErrorReportDialog(wx.Dialog): + def __init__(self, *args, **kwds): + # begin wxGlade: ErrorReportDialog.__init__ + kwds["style"] = ( + kwds.get("style", 0) | wx.DEFAULT_DIALOG_STYLE | wx.MAXIMIZE_BOX | wx.MINIMIZE_BOX | wx.RESIZE_BORDER + ) + wx.Dialog.__init__(self, *args, **kwds) + self.SetSize((540, 600)) + self.label_header = wx.html.HtmlWindow(self, wx.ID_ANY) + self.label_log = wx.StaticText(self, wx.ID_ANY, "Error Log:") + self.text_ctrl_log = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_MULTILINE | wx.TE_READONLY) + self.static_line_1 = wx.StaticLine(self, wx.ID_ANY) + self.button_google = wx.Button(self, wx.ID_ANY, "Google This Error") + self.button_copyErrorLog = wx.Button(self, wx.ID_ANY, "Copy Error Log") + self.button_close = wx.Button(self, wx.ID_CANCEL, "Close") + + self.__set_properties() + self.__do_layout() + + self.Bind(wx.EVT_BUTTON, self.onGoogle, self.button_google) + self.Bind(wx.EVT_BUTTON, self.onCopyErrorLog, self.button_copyErrorLog) + # end wxGlade + self.__customProperties() + return + + def __set_properties(self): + # begin wxGlade: ErrorReportDialog.__set_properties + self.SetTitle("Problem Report for PDFgui") + self.SetSize((540, 600)) + # end wxGlade + + def __do_layout(self): + # begin wxGlade: ErrorReportDialog.__do_layout + sizer_main = wx.BoxSizer(wx.VERTICAL) + sizer_buttons = wx.BoxSizer(wx.HORIZONTAL) + sizer_log = wx.BoxSizer(wx.VERTICAL) + sizer_label = wx.BoxSizer(wx.HORIZONTAL) + sizer_label.Add(self.label_header, 1, wx.EXPAND, 5) + sizer_main.Add(sizer_label, 1, wx.ALL | wx.EXPAND, 5) + sizer_log.Add(self.label_log, 0, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, 5) + sizer_log.Add(self.text_ctrl_log, 1, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) + sizer_main.Add(sizer_log, 3, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, 10) + sizer_main.Add(self.static_line_1, 0, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, 5) + sizer_buttons.Add((20, 20), 1, 0, 0) + sizer_buttons.Add(self.button_google, 0, wx.ALL, 5) + sizer_buttons.Add(self.button_copyErrorLog, 0, wx.ALL, 5) + sizer_buttons.Add(self.button_close, 0, wx.ALL, 5) + sizer_main.Add(sizer_buttons, 0, wx.EXPAND, 0) + self.SetSizer(sizer_main) + self.Layout() + # end wxGlade + + def __customProperties(self): + """Set custom properties.""" + # Events + self.errorReport = True + self.label_header.Bind(wx.html.EVT_HTML_LINK_CLICKED, self.onURL) + return + +
+[docs] + def ShowModal(self): + # there are 2 modes: error report and feature request + if self.text_ctrl_log.GetValue().strip() == "": + self.SetTitle("Feature Request / Bug Report") + self.label_header.SetPage(_MSG_FEATURE_REQUEST) + self.label_header.SetBackgroundColour("") + self.label_log.Hide() + self.text_ctrl_log.Hide() + self.button_google.Hide() + self.button_copyErrorLog.Hide() + self.SetSize((540, 200)) + self.errorReport = False + else: + self.SetTitle("Problem Report for PDFgui") + self.label_header.SetPage(_MSG_ERROR_REPORT) + self.label_header.SetBackgroundColour("") + self.text_ctrl_log.Show() + self.errorReport = True + + wx.Dialog.ShowModal(self)
+ + +
+[docs] + def onGoogle(self, event): # wxGlade: ErrorReportDialog.<event_handler> + """Handle the "Google This Error" button. + + Search for path-independent module and function names and for + error message extracted from exception traceback. + """ + from urllib.parse import quote_plus + + traceback = self.text_ctrl_log.GetValue() + terms = _extractSearchTerms(traceback) + str_to_search = " ".join(terms) if terms else traceback.strip() + query = quote_plus(str_to_search) + url = _WEBSEARCHURL.format(query=query) + webbrowser.open(url) + event.Skip() + return
+ + +
+[docs] + def onCopyErrorLog(self, event): # wxGlade: ErrorReportDialog.<event_handler> + # copy the traceback enclosed in GitHub block quotations so it is easier to paste into GitHub issue. + traceback = self.text_ctrl_log.GetValue() + clipdata = wx.TextDataObject() + clipdata.SetText("```\n" + traceback.strip() + "\n```\n") + wx.TheClipboard.Open() + wx.TheClipboard.SetData(clipdata) + wx.TheClipboard.Close() + event.Skip() + return
+ + +
+[docs] + def onURL(self, event): # wxGlade: ErrorReportDialog.<event_handler> + # click on the URL link in dialog, it will open the URL in web browser. + link = event.GetLinkInfo() + webbrowser.open(link.GetHref())
+
+ + + +# end of class ErrorReportDialog + +# Helper functions ----------------------------------------------------------- + + +def _extractSearchTerms(tbtext): + """Extract search words from a Python exception traceback. + + Parameters + ---------- + tbtext : str + Python exception traceback converted to a string. + + Returns + ------- + searchterms : list + List of search terms to be used for Google search. + """ + # extract module names and function names from a traceback + modfncpairs = re.findall(r"File.*?([^/\\]*[.]py).*?, line \d+, in (\w+)", tbtext, re.MULTILINE) + modfnc = list(sum(modfncpairs, ())) + # find the last line starting with "SomeError: ...". + lasterr = re.findall(r"^\w+Error:.*", tbtext, re.MULTILINE) + rv = modfnc + lasterr[-1:] + return rv + + +# testing code ############################################################ + +_EXAMPLE_TRACEBACK = r""" +Traceback (most recent call last): + File "C:\DiffPy\Python25\lib\site-packages\diffpy.pdfgui-1.0_r3067_20090410-py2.5.egg\ +diffpy\pdfgui\gui\errorwrapper.py", line 60, in _f + return func(*args, **kwargs) + File "C:\DiffPy\Python25\lib\site-packages\diffpy.pdfgui-1.0_r3067_20090410-py2.5.egg\ +diffpy\pdfgui\gui\mainframe.py", line 2176, in onSave + self.control.save(self.fullpath) + File "C:\DiffPy\Python25\lib\site-packages\diffpy.pdfgui-1.0_r3067_20090410-py2.5.egg\ +diffpy\pdfgui\control\pdfguicontrol.py", line 507, in save + self.projfile = projfile.encode('ascii') +UnicodeDecodeError: 'ascii' codec can't decode byte 0xb0 in position 115: ordinal not in range(128) +""".strip() + + +
+[docs] +class MyApp(wx.App): +
+[docs] + def OnInit(self): + self.dialog = ErrorReportDialog(None, -1, "") + self.SetTopWindow(self.dialog) + self.test() + self.dialog.ShowModal() + self.dialog.Destroy() + return True
+ + +
+[docs] + def test(self): + """Testing code goes here.""" + self.dialog.text_ctrl_log.SetValue(_EXAMPLE_TRACEBACK) + return
+
+ + + +# end of class MyApp + +if __name__ == "__main__": + app = MyApp(0) + app.MainLoop() + +# end of testing code ##################################################### +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/errorreportdialog_control_fix.html b/_modules/diffpy/pdfgui/gui/errorreportdialog_control_fix.html new file mode 100644 index 00000000..7314b88b --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/errorreportdialog_control_fix.html @@ -0,0 +1,304 @@ + + + + + + + + diffpy.pdfgui.gui.errorreportdialog_control_fix — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.errorreportdialog_control_fix

+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Dmitriy Bryndin
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+# generated by wxGlade 0.9.3 on Fri Jul 19 16:01:37 2019
+
+import re
+
+#
+# "Bug report" Dialog
+#
+import wx
+import wx.html
+
+from .errorreportdialog import ErrorReportDialog
+
+# Constants ------------------------------------------------------------------
+
+ISSUESTRACKER = "https://github.com/diffpy/diffpy.pdfgui/issues"
+USERSMAILINGLIST = "https://groups.google.com/d/forum/diffpy-users"
+_WEBSEARCHURL = "https://www.google.com/search?q={query}"
+
+
+_MSG_ERROR_REPORT = """
+<p>
+Currently the control-select is not supported in Python3 PDFgui. We will fix this issue in a future version.
+Please use shift-select for multiple cells instead.
+</p><p>
+"""
+
+# ----------------------------------------------------------------------------
+
+
+
+[docs] +class ErrorReportDialogControlFix(wx.Dialog): + def __init__(self, *args, **kwds): + # begin wxGlade: ErrorReportDialog.__init__ + kwds["style"] = ( + kwds.get("style", 0) | wx.DEFAULT_DIALOG_STYLE | wx.MAXIMIZE_BOX | wx.MINIMIZE_BOX | wx.RESIZE_BORDER + ) + wx.Dialog.__init__(self, *args, **kwds) + self.SetSize((540, 200)) + self.label_header = wx.html.HtmlWindow(self, wx.ID_ANY) + # self.label_log = wx.StaticText(self, wx.ID_ANY, "Error Log:") + # self.text_ctrl_log = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_MULTILINE | wx.TE_READONLY) + # self.static_line_1 = wx.StaticLine(self, wx.ID_ANY) + # self.button_google = wx.Button(self, wx.ID_ANY, "Google This Error") + # self.button_copyErrorLog = wx.Button(self, wx.ID_ANY, "Copy Error Log") + self.button_close = wx.Button(self, wx.ID_CANCEL, "Close") + + self.__set_properties() + self.__do_layout() + + # self.Bind(wx.EVT_BUTTON, self.onGoogle, self.button_google) + # self.Bind(wx.EVT_BUTTON, self.onCopyErrorLog, self.button_copyErrorLog) + # end wxGlade + self.__customProperties() + return + + def __set_properties(self): + # begin wxGlade: ErrorReportDialog.__set_properties + self.SetTitle("Problem Report for PDFgui") + self.SetSize((540, 200)) + # end wxGlade + + def __do_layout(self): + # begin wxGlade: ErrorReportDialog.__do_layout + sizer_main = wx.BoxSizer(wx.VERTICAL) + sizer_buttons = wx.BoxSizer(wx.HORIZONTAL) + # sizer_log = wx.BoxSizer(wx.VERTICAL) + sizer_label = wx.BoxSizer(wx.HORIZONTAL) + sizer_label.Add(self.label_header, 1, wx.EXPAND, 5) + sizer_main.Add(sizer_label, 1, wx.ALL | wx.EXPAND, 5) + # sizer_log.Add(self.label_log, 0, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, 5) + # sizer_log.Add(self.text_ctrl_log, 1, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) + # sizer_main.Add(sizer_log, 3, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, 10) + # sizer_main.Add(self.static_line_1, 0, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, 5) + # sizer_buttons.Add((20, 20), 1, 0, 0) + # sizer_buttons.Add(self.button_google, 0, wx.ALL, 5) + # sizer_buttons.Add(self.button_copyErrorLog, 0, wx.ALL, 5) + sizer_buttons.Add(self.button_close, 0, wx.ALL, 5) + sizer_main.Add(sizer_buttons, 0, wx.EXPAND, 0) + self.SetSizer(sizer_main) + self.Layout() + # end wxGlade + + def __customProperties(self): + """Set custom properties.""" + # Events + self.errorReport = True + # self.label_header.Bind(wx.html.EVT_HTML_LINK_CLICKED, self.onURL) + return + +
+[docs] + def ShowModal(self): + # there are 2 modes: error report and feature request + + self.SetTitle("Problem Report for PDFgui") + self.label_header.SetPage(_MSG_ERROR_REPORT) + self.label_header.SetBackgroundColour("") + # self.text_ctrl_log.Show() + self.errorReport = True + + wx.Dialog.ShowModal(self)
+
+ + + +# end of class ErrorReportDialog + +# Helper functions ----------------------------------------------------------- + + +def _extractSearchTerms(tbtext): + """Extract search words from a Python exception traceback. + + Parameters + ---------- + tbtext : str + Python exception traceback converted to a string. + + Returns + ------- + searchterms : list + List of search terms to be used for Google search. + """ + # extract module names and function names from a traceback + modfncpairs = re.findall(r"File.*?([^/\\]*[.]py).*?, line \d+, in (\w+)", tbtext, re.MULTILINE) + modfnc = list(sum(modfncpairs, ())) + # find the last line starting with "SomeError: ...". + lasterr = re.findall(r"^\w+Error:.*", tbtext, re.MULTILINE) + rv = modfnc + lasterr[-1:] + return rv + + +# testing code ############################################################ + +_EXAMPLE_TRACEBACK = r""" +Traceback (most recent call last): + File "C:\DiffPy\Python25\lib\site-packages\diffpy.pdfgui-1.0_r3067_20090410-py2.5.egg\ +\diffpy\pdfgui\gui\errorwrapper.py", line 60, in _f + return func(*args, **kwargs) + File "C:\DiffPy\Python25\lib\site-packages\diffpy.pdfgui-1.0_r3067_20090410-py2.5.egg\ +\diffpy\pdfgui\gui\mainframe.py", line 2176, in onSave + self.control.save(self.fullpath) + File "C:\DiffPy\Python25\lib\site-packages\diffpy.pdfgui-1.0_r3067_20090410-py2.5.egg\ +\diffpy\pdfgui\control\pdfguicontrol.py", line 507, in save + self.projfile = projfile.encode('ascii') +UnicodeDecodeError: 'ascii' codec can't decode byte 0xb0 in position 115: \ +ordinal not in range(128) +""".strip() + + +
+[docs] +class MyApp(wx.App): +
+[docs] + def OnInit(self): + self.dialog = ErrorReportDialog(None, -1, "") + self.SetTopWindow(self.dialog) + self.test() + self.dialog.ShowModal() + self.dialog.Destroy() + return True
+ + +
+[docs] + def test(self): + """Testing code goes here.""" + # self.dialog.text_ctrl_log.SetValue(_EXAMPLE_TRACEBACK) + return
+
+ + + +# end of class MyApp + +if __name__ == "__main__": + app = MyApp(0) + app.MainLoop() + +# end of testing code ##################################################### +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/errorwrapper.html b/_modules/diffpy/pdfgui/gui/errorwrapper.html new file mode 100644 index 00000000..bfb44115 --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/errorwrapper.html @@ -0,0 +1,244 @@ + + + + + + + + diffpy.pdfgui.gui.errorwrapper — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.errorwrapper

+#!/usr/bin/env python
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2008 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+"""This module contains a function wrapper and an object wrapper that catch
+control errors and shows them in an error report dialog.
+
+This is used by PDFPanel and MainFrame.
+"""
+
+import sys
+import traceback
+
+import wx
+
+from diffpy.pdfgui.control.controlerrors import ControlError, TempControlSelectError
+from diffpy.pdfgui.gui import pdfguiglobals
+from diffpy.pdfgui.gui.errorreportdialog import ErrorReportDialog
+from diffpy.pdfgui.gui.errorreportdialog_control_fix import ErrorReportDialogControlFix
+
+# these methods will not be wrapped in catchFunctionErrors
+_EXCLUDED_METHODS = dict.fromkeys(dir(wx.Panel) + dir(wx.Dialog))
+
+
+
+[docs] +def catchFunctionErrors(obj, funcName): + """Wrap a function so its errors get transferred to a dialog. + + obj -- Object containing the function. It is assumed that the + object has an attribute named 'mainFrame', which is a + reference to the MainFrame instance, which contains + information about how and when to display errors. + funcName -- Name of a function to wrap. + + Returns the wrapped function + """ + func = getattr(obj, funcName) + + # do not catch anything when requested in pdfguigloabals.dbopts + if pdfguiglobals.dbopts.noerrordialog: + return func + + # default return value when exception is skipped: + rvpass = wx.ID_CANCEL + + # otherwise wrap func within exceptions handler + def _f(*args, **kwargs): + + hasmf = hasattr(obj, "mainFrame") and obj.mainFrame is not None + + try: + return func(*args, **kwargs) + + # to be deleted. temporarily used for show the select-control error. + except TempControlSelectError: + dlg = ErrorReportDialogControlFix(obj.mainFrame) + dlg.ShowModal() + dlg.Destroy() + + # Display ControlError error messages in a dialog. + except ControlError as e: + if not hasmf: + raise + message = str(e) + obj.mainFrame.showMessage(message, "Oops!") + return rvpass + + # Everything else + except Exception: + if pdfguiglobals.dbopts.pythondebugger: + import pdb + + tb = sys.exc_info()[2] + pdb.post_mortem(tb) + return rvpass + if not hasmf: + raise + msglines = traceback.format_exception(*sys.exc_info()) + message = "".join(msglines) + if obj.mainFrame.quitting: + sys.stderr.write(message) + sys.stderr.write("\n") + else: + dlg = ErrorReportDialog(obj.mainFrame) + dlg.text_ctrl_log.SetValue(message) + dlg.ShowModal() + dlg.Destroy() + return rvpass + + # we should never get here + pass + + return _f
+ + + +
+[docs] +def catchObjectErrors(obj, exclude=None): + """Wrap all functions of an object so that the exceptions are caught. + + obj -- Object containing the function. It is assumed that the object has an + attribute named 'mainFrame', which is a reference to the MainFrame + instance, which contains information about how and when to display + errors. + exclude -- An iterable of additional function names to exclude. These are + excluded in addition to names in _EXCLUDED_METHODS defined above. + + All functions starting with '_' are excluded. + """ + if exclude: + extra_excludes = dict.fromkeys(exclude) + else: + extra_excludes = {} + + funcNames = [ + item + for item in dir(obj) + if not item.startswith("_") and item not in _EXCLUDED_METHODS and item not in extra_excludes + ] + + for name in funcNames: + if hasattr(getattr(obj, name), "__call__"): + setattr(obj, name, catchFunctionErrors(obj, name)) + + return
+ +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/extendedplotframe.html b/_modules/diffpy/pdfgui/gui/extendedplotframe.html new file mode 100644 index 00000000..891263d1 --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/extendedplotframe.html @@ -0,0 +1,582 @@ + + + + + + + + diffpy.pdfgui.gui.extendedplotframe — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.extendedplotframe

+#!/usr/bin/env python
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Jiwu Liu, Chris Farrow
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+"""The module contains extensions for GUI plot frame."""
+
+import os.path
+
+import matplotlib
+import wx
+from matplotlib.artist import setp
+from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
+from matplotlib.backends.backend_wxagg import NavigationToolbar2WxAgg as NavToolbar
+from matplotlib.figure import Figure
+from matplotlib.font_manager import FontProperties
+
+from diffpy.pdfgui.gui.pdfguiglobals import iconpath
+
+matplotlib.use("WXAgg")
+
+DATA_SAVE_ID = wx.NewIdRef()
+
+
+
+[docs] +class ExtendedToolbar(NavToolbar): + """An extended plotting toolbar with a save and close button.""" + + # override NavToolbar.toolitems to exclude the subplots tool. + toolitems = tuple(el for el in NavToolbar.toolitems if el[0] != "Subplots") + + def __init__(self, canvas): + NavToolbar.__init__(self, canvas) + # Load customized icon image + save_icon_fp = iconpath("exportplotdata.png") + save_icon = wx.Bitmap(save_icon_fp) + # Add new buttons + self.AddTool(DATA_SAVE_ID, "Export data", save_icon, shortHelp="Export plot data to file") + return
+ + + +# End class ExtendedToolbar + + +
+[docs] +class ExtendedPlotFrame(wx.Frame): + """An extended plotting frame with a save and close button. + + The class has a matplotlib.figure.Figure data member named 'figure'. + It also has a matplotlib.axes.Axes data member named 'axes'. The + normal matplotlib plot manipulations can be performed with these two + data members. See the matplotlib API at: + http://matplotlib.sourceforge.net/classdocs.html + """ + + # keyboard shortcut(s) for closing plot window + close_keys = set(matplotlib.rcParamsDefault["keymap.quit"]) + + def __init__(self, parent=None, *args, **kwargs): + """Initialize the CanvasFrame. + + The frame uses ExtendedToolbar as a toolbar, which has a save data + button and a close button on the toolbar in addition to the normal + buttons. + + args -- argument list + kwargs -- keyword argument list + """ + wx.Frame.__init__(self, parent, -1, "ExtendedPlotFrame", size=(550, 350)) + + # figsize in inches + self.figure = Figure(figsize=(0.5, 0.5), dpi=72) + + # we will manage view scale ourselves + self.subplot = self.figure.add_subplot(111, autoscale_on=False) + self.canvas = FigureCanvas(self, -1, self.figure) + + # Introspection data + self.dirname = "" + self.filename = "" + + self.sizer = wx.BoxSizer(wx.VERTICAL) + self.sizer.Add(self.canvas, 1, wx.TOP | wx.LEFT | wx.EXPAND) + self.toolbar = ExtendedToolbar(self.canvas) + self.toolbar.Realize() + + self.coordLabel = wx.StaticText(self, -1, style=wx.ALIGN_RIGHT | wx.NO_BORDER) + # Place coordinates textbox in a horizontal sizer next to the toolbar. + barSizer = wx.BoxSizer(wx.HORIZONTAL) + self.sizer.Add(barSizer, 0, wx.EXPAND | wx.CENTER) + barSizer.Add(self.toolbar, 0, wx.CENTER) + barSizer.Add((20, 10), 0) + barSizer.Add(self.coordLabel, 0, wx.CENTER) + + # update the axes menu on the toolbar + self.toolbar.update() + self.SetSizer(self.sizer) + self.Fit() + self.SetSize((600, 400)) + # Use toolbar's color for coordinates label background. + self.SetBackgroundColour(self.toolbar.GetBackgroundColour()) + # FIXME -- toolbar background color does not match on Mac OS X. + # Use GIMP - picked color until a proper way is found. + if wx.Platform == "__WXMAC__": + self.SetBackgroundColour((200, 200, 200, 255)) + self.canvas.mpl_connect("motion_notify_event", self.UpdateStatusBar) + self.canvas.mpl_connect("key_press_event", self.mplKeyPress) + self.Bind(wx.EVT_PAINT, self.OnPaint) + self.Bind(wx.EVT_TOOL, self.savePlotData, id=DATA_SAVE_ID) + self.Bind(wx.EVT_CLOSE, self.onClose) + + self.datalims = {} + + # CUSTOM METHODS ######################################################## + + # EVENT CODE ############################################################# +
+[docs] + def onClose(self, evt): + """Close the frame.""" + if hasattr(self, "plotter"): + self.plotter.onWindowClose() + self.Destroy() + return
+ + +
+[docs] + def OnPaint(self, event): + self.canvas.draw() + event.Skip()
+ + +
+[docs] + def savePlotData(self, evt): + """Save the data in the plot in columns.""" + d = wx.FileDialog( + None, + "Save as...", + self.dirname, + self.filename, + "(*.dat)|*.dat|(*.txt)|*.txt|(*)|*", + wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT, + ) + if d.ShowModal() == wx.ID_OK: + fullname = d.GetPath() + self.dirname = os.path.dirname(fullname) + self.filename = os.path.basename(fullname) + self.plotter.export(fullname) + + d.Destroy() + return
+ + +
+[docs] + def UpdateStatusBar(self, event): + if event.inaxes: + x, y = event.xdata, event.ydata + xystr = "x = %g, y = %g" % (x, y) + self.coordLabel.SetLabel(xystr)
+ + +
+[docs] + def mplKeyPress(self, event): + """Process keyboard input in matplotlib plot window. + + This implements a standard close-window shortcut key. + """ + if event.key in self.close_keys: + self.Close() + return
+ + +
+[docs] + def replot(self): + """Officially call function in matplotlib to do drawing.""" + self.canvas.draw()
+ + +
+[docs] + def insertCurve(self, xData, yData, style): + """Insert a new curve to the plot. + + xData, yData -- x, y data to used for the curve + style -- the way curve should be plotted + return: internal reference to the newly added curve + """ + _, properties = self.__translateStyles(style) + curveRef = self.subplot.plot(xData, yData, **properties)[0] + if "legend" in style: + self.subplot.legend(**legendBoxProperties()) + try: + self.datalims[curveRef] = (min(xData), max(xData), min(yData), max(yData)) + except ValueError: + self.datalims[curveRef] = (0, 0, 0, 0) + self.__updateViewLimits() + return curveRef
+ + +
+[docs] + def updateData(self, curveRef, xData, yData): + """Update data for a existing curve. + + curveRef -- internal reference to a curve + xData, yData -- x, y data to used for the curve + """ + curveRef.set_data(xData, yData) + try: + self.datalims[curveRef] = (min(xData), max(xData), min(yData), max(yData)) + except ValueError: + self.datalims[curveRef] = (0, 0, 0, 0) + self.__updateViewLimits()
+ + +
+[docs] + def changeStyle(self, curveRef, style): + """Change curve style. + + curveRef -- internal reference to curves + style -- style dictionary + """ + stylestr, properties = self.__translateStyles(style) + # FIXME: we discard stylestr because it seems there's no way + # it can be changed afterwards. + setp((curveRef,), **properties) + self.subplot.legend(**legendBoxProperties())
+ + +
+[docs] + def removeCurve(self, curveRef): + """Remove curve from plot. + + curveRef -- internal reference to curves + """ + del self.datalims[curveRef] + self.figure.gca().lines.remove(curveRef) + self.subplot.legend(**legendBoxProperties()) + self.__updateViewLimits()
+ + + def __updateViewLimits(self): + """Adjust the subplot range in order to show all curves correctly.""" + # NOTE: + # we need to adjust view limits by ourselves because Matplotlib can't + # set the legend nicely when there are multiple curves in the plot. + # Beside, autoscale can not automatically respond to data change. + if len(self.datalims) == 0: + return + # ignore previous range + self.subplot.dataLim.ignore(True) + bounds = list(self.datalims.values()) + xmin = min([b[0] for b in bounds]) + xmax = max([b[1] for b in bounds]) + ymin = min([b[2] for b in bounds]) + ymax = max([b[3] for b in bounds]) + + # If multiple curve, we need calculate new x limits because legend box + # take up some space + # NOTE: 3 and 0.33 is our best estimation for a good view + # 2007-10-25 PJ: it is better to use full plot area + # if len(self.datalims) > 3: + # # leave extra room for legend by shift the upper bound for x axis + # xmax += (xmax-xmin)*0.33 + if xmax > xmin: + self.subplot.set_xlim(xmin, xmax) + if ymax > ymin: + self.subplot.set_ylim(ymin, ymax) + + def __translateStyles(self, style): + """Private function to translate general probabilities to Matplotlib + specific ones. + + style -- general curve style dictionary (defined in demoplot) + """ + # Translation dictionary + lineStyleDict = {"solid": "-", "dash": "--", "dot": ":", "dashDot": "-."} + symbolDict = { + "diamond": "d", + "square": "s", + "circle": "o", + "cross": "+", + "xCross": "x", + "triangle": "^", + } + colorDict = { + "blue": "#0B3C5D", + "green": "#1C6B0A", + "red": "#B82601", + "cyan": "c", + "magenta": "m", + "yellow": "y", + "black": "k", + "white": "w", + "darkRed": "#8B0000", + "darkGreen": "#006400", + "darkCyan": "#008B8B", + "darkYellow": "#FFD700", + "darkBlue": "#00008B", + "darkMagenta": "#8B008B", + } + + properties = {} + + # NOTE: matplotlib takes additional string for plotting. It's + # purpose is like 'with' in Gnuplot + stylestr = "" + # color is universal for either lines, points or linepoints + color = colorDict.get(style["color"], "k") + + if style["with"] in ("points", "linespoints"): + # require symbol properties + stylestr = "." + symbol = symbolDict.get(style["symbol"], "s") # prefer square + symbolSize = style["symbolSize"] + symbolColor = colorDict.get(style["symbolColor"], "k") + properties.update( + { # 'linewidth':0.0, # doesn't affect any + "markerfacecolor": symbolColor, + "markeredgecolor": color, + "marker": symbol, + "markersize": symbolSize, + } + ) + if style["with"] != "points": + # not 'points', so line properties are required as well + lineStyle = lineStyleDict.get(style["line"], "-") # prefer solid + lineWidth = style["width"] + stylestr += lineStyle + properties.update({"color": color, "linestyle": lineStyle, "linewidth": lineWidth}) + + if "legend" in style: + properties["label"] = style["legend"] + return stylestr, properties + +
+[docs] + def setTitle(self, wt, gt): + """Set graph labels. + + wt -- window title + gt -- graph title + """ + self.SetTitle(wt) + self.figure.gca().set_title(gt)
+ + +
+[docs] + def setXLabel(self, x): + """Set label for x axis. + + x -- x label + """ + self.figure.gca().set_xlabel(x)
+ + +
+[docs] + def setYLabel(self, y): + """Set label for y axis. + + y -- y label + """ + self.figure.gca().set_ylabel(y)
+ + +
+[docs] + def clear(self): + """Erase all curves.""" + self.subplot.clear() + self.curverefs = [] + self.replot()
+
+ + + +# End class ExtendedPlotFrame + + +
+[docs] +def legendBoxProperties(): + """Legend properties dictionary with keys consistent with MPL version. + + The argument names have changed in matplotlib 0.98.5. Old arguments + do not work with later versions of matplotlib. + + Return dictionary of legend properties. + """ + global _lbp + # return immediately if properties have already been cached + if len(_lbp) > 0: + return _lbp + # figure out matplotlib version and appropriate names + from matplotlib import __version__ as mplver + from packaging.version import parse + + if parse(mplver) >= parse("0.98.5"): + _lbp = { + "loc": "upper right", + "numpoints": 3, # number of points in the legend line + "borderpad": 0.25, # whitespace in the legend border + "labelspacing": 0, # space between legend entries + "handlelength": 1.5, # the length of the legend lines + "handletextpad": 0.5, # separation between line and text + "prop": FontProperties(size="medium"), + } + else: + _lbp = { + "loc": "upper right", + "numpoints": 3, # number of points in the legend line + "pad": 0.20, # whitespace in the legend border + "labelsep": 0.005, # space between legend entries + "handlelen": 0.03, # the length of the legend lines + "handletextsep": 0.02, # separation between line and text + "prop": FontProperties(size="medium"), + } + return _lbp
+ + + +_lbp = {} + +# End of legendBoxProperties + + +if __name__ == "__main__": + + class MyApp(wx.App): + def OnInit(self): + from numpy import arange, cos, pi, sin + + "Create the main window and insert the custom frame" + x = arange(0.0, 3.0, 0.01) + s = sin(2 * pi * x) + c = cos(2 * pi * x) + t = sin(2 * pi * x) + cos(2 * pi * x) + frame = ExtendedPlotFrame(None) + style = {"with": "lines", "color": "blue", "line": "solid", "width": 2} + style["legend"] = "sin(x)" + frame.insertCurve(x, s, style) + style = {"with": "lines", "color": "red", "line": "solid", "width": 2} + style["legend"] = "cos(x)" + frame.insertCurve(x, c, style) + style = {"with": "lines", "color": "black", "line": "solid", "width": 2} + # style['legend'] = 'sin(x)+cos(x)' + frame.insertCurve(x, t, style) + frame.Show(True) + return True + + app = MyApp(0) + app.MainLoop() + + +# End of file +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/fitnotebookpanel.html b/_modules/diffpy/pdfgui/gui/fitnotebookpanel.html new file mode 100644 index 00000000..aafa4b13 --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/fitnotebookpanel.html @@ -0,0 +1,216 @@ + + + + + + + + diffpy.pdfgui.gui.fitnotebookpanel — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.fitnotebookpanel

+#!/usr/bin/env python
+# -*- coding: ISO-8859-1 -*-
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+# generated by wxGlade 0.9.3 on Fri Jul 19 17:16:20 2019
+
+import wx
+
+from diffpy.pdfgui.gui.parameterspanel import ParametersPanel
+from diffpy.pdfgui.gui.pdfpanel import PDFPanel
+from diffpy.pdfgui.gui.resultspanel import ResultsPanel
+
+
+
+[docs] +class FitNotebookPanel(wx.Panel, PDFPanel): + def __init__(self, *args, **kwds): + # begin wxGlade: FitNotebookPanel.__init__ + kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL + wx.Panel.__init__(self, *args, **kwds) + self.fitnotebook = wx.Notebook(self, wx.ID_ANY, style=0) + self.parametersPanel = ParametersPanel(self.fitnotebook, wx.ID_ANY) + self.resultsPanel = ResultsPanel(self.fitnotebook, wx.ID_ANY) + + self.__set_properties() + self.__do_layout() + + self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.onPageChanged, self.fitnotebook) + self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGING, self.onPageChanging, self.fitnotebook) + # end wxGlade + self.__customProperties() + + def __set_properties(self): + # begin wxGlade: FitNotebookPanel.__set_properties + pass + # end wxGlade + + def __do_layout(self): + # begin wxGlade: FitNotebookPanel.__do_layout + sizer_1 = wx.BoxSizer(wx.HORIZONTAL) + self.fitnotebook.AddPage(self.parametersPanel, "Parameters") + self.fitnotebook.AddPage(self.resultsPanel, "Results") + sizer_1.Add(self.fitnotebook, 1, wx.EXPAND, 0) + self.SetSizer(sizer_1) + sizer_1.Fit(self) + self.Layout() + # end wxGlade + + def __customProperties(self): + """Set the custom properties.""" + self.fit = None + self.mainFrame = None + return + +
+[docs] + def onPageChanged(self, event): # wxGlade: FitNotebookPanel.<event_handler> + """Refresh the panel visible panel.""" + self.refresh() + return
+ + +
+[docs] + def onPageChanging(self, event): # wxGlade: FitNotebookPanel.<event_handler> + event.Skip()
+ + +
+[docs] + def refresh(self): + """Refresh the panels.""" + if not self.fit: + return + panel = self.fitnotebook.GetCurrentPage() + panel.mainFrame = self.mainFrame + panel.refresh() + panel.fit = self.fit + panel.parameters = self.fit.parameters + panel.refresh()
+ + + # Overloaded from Panel. +
+[docs] + def Enable(self, enable=True): + """Keep the notebook enabled, just not the panels. + + outputPanel is immune from this, since it needs to be interacted + with. + """ + self.parametersPanel.Enable(enable) + return
+
+ + + +# end of class FitNotebookPanel +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/fittree.html b/_modules/diffpy/pdfgui/gui/fittree.html new file mode 100644 index 00000000..6b07df6f --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/fittree.html @@ -0,0 +1,1132 @@ + + + + + + + + diffpy.pdfgui.gui.fittree — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for diffpy.pdfgui.gui.fittree

+#!/usr/bin/env python
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+"""This module contains the FitTree object designed for use in PDFgui.
+
+Classes:
+    FitTree         --  A tree specific to orgainizing data for pdffit
+
+Exceptions:
+    FitTreeError    --  Exception for errors with FitTree operations.
+"""
+
+import base64
+import pickle
+import re
+
+import wx
+
+from diffpy.pdfgui.control.controlerrors import ControlError
+from diffpy.pdfgui.control.fitting import Fitting
+from diffpy.pdfgui.gui.pdfguiglobals import iconpath
+from diffpy.pdfgui.utils import safeCPickleDumps
+
+
+
+[docs] +class FitTree(wx.TreeCtrl): + """TreeCtrl designed to organize pdffit fits. + + The root of the tree is hidden. Below that there are several levels + which are diagrammed below. + + _ fit (*) + | + |____ phase (5) + |____ dataset (*) + |____ calculation (*) + + Fits are at the top level. Under fits there are phases, datasets, and + calculations (in that order). + + It is required that the data for each node is a dictionary. In the 'type' + entry of this dictionary is the node type (fit, phase, dataset, + calculation). Fit items also have a 'cdata' entry in their tree item + dictionary. This is the control center data associated with this node's + branch. + + Data members: + control -- The pdfguicontrol object that interfaces between the tree + and the pdffit2 engine. The tree is a mirror of the internal + structure of the control. + """ + + def __init__( + self, + parent, + id=-1, + pos=wx.DefaultPosition, + size=wx.DefaultSize, + style=wx.TR_HAS_BUTTONS | wx.TR_HIDE_ROOT | wx.TR_MULTIPLE, + validator=wx.DefaultValidator, + name="FitTree", + ): + wx.TreeCtrl.__init__(self, parent, id, pos, size, style) + + # Define the control + # This is set by the mainFrame + # self.control = pdfguicontrol() + + # Define bitmaps + datasetbmp = wx.Bitmap(iconpath("datasetitem.png")) + phasebmp = wx.Bitmap(iconpath("phaseitem.png")) + fitbmp = wx.Bitmap(iconpath("fititem.png")) + calcbmp = wx.Bitmap(iconpath("calculationitem.png")) + isz = (16, 16) + il = wx.ImageList(isz[0], isz[1]) + self.fitbmid = il.Add(fitbmp) + self.dtsbmid = il.Add(datasetbmp) + self.phabmid = il.Add(phasebmp) + self.clcbmid = il.Add(calcbmp) + self.SetImageList(il) + self.treeImageList = il + + return + +
+[docs] + def InitializeTree(self): + """This initializes the tree by adding a root node.""" + self.root = self.AddRoot("The Root Item") + self.SetNodeType(self.root, "root") + # Testing code + # fit1 = self.AddFit() + # self.AddPhase(fit1, "Phase 1") + # self.AddPhase(fit1, "Phase 2") + # self.AddDataSet(fit1, "Data 1") + # self.AddCalc(fit1, "Calc 1") + # self.Expand(fit1) + return
+ + +
+[docs] + def GetTreeItemDict(self, node): + """Get the data dictionary of the node.""" + return self.GetItemData(node)
+ + +
+[docs] + def GetFitRoot(self, node): + """Return the id of the fit in which the passed node resides.""" + if not node: + return + fitId = node + nextId = self.GetItemParent(node) + while nextId != self.root: + fitId = nextId + nextId = self.GetItemParent(nextId) + return fitId
+ + +
+[docs] + def GetChildren(self, node): + """Get the ids of the children of a given node.""" + cookie = 0 + ids = [] + (child, cookie) = self.GetFirstChild(node) + while child.IsOk(): + ids.append(child) + (child, cookie) = self.GetNextChild(node, cookie) + + return ids
+ + +
+[docs] + def GetSiblings(self, node): + """Get the ids of the siblings of a given node.""" + parent = self.GetItemParent(node) + ids = self.GetChildren(parent) + ids.remove(node) + return ids
+ + +
+[docs] + def GetAllType(self, node): + """Get the id of each item in the tree of the same type as node.""" + nodetype = self.GetNodeType(node) + fits = self.GetChildren(self.root) + if nodetype == "fit": + return fits + else: + sametype = [] + for fit in fits: + children = self.GetChildren(fit) + sametype.extend([child for child in children if self.GetNodeType(child) == nodetype]) + return sametype
+ + +
+[docs] + def GetPhases(self, node): + """Get a list of phase in branch. + + node is either the fit-root or a node in the fit-branch of + interest. + """ + nodes = self.GetChildren(self.GetFitRoot(node)) + ids = [id for id in nodes if self.GetNodeType(id) == "phase"] + return ids
+ + +
+[docs] + def GetDataSets(self, node): + """Get a list of datasets in branch. + + node is either the fit-root or a node in the fit-branch of + interest. + """ + nodes = self.GetChildren(self.GetFitRoot(node)) + ids = [id for id in nodes if self.GetNodeType(id) == "dataset"] + return ids
+ + +
+[docs] + def GetCalculations(self, node): + """Get a list of calculations in branch. + + node is either the fit-root or a node in the fit-branch of + interest. + """ + nodes = self.GetChildren(self.GetFitRoot(node)) + ids = [id for id in nodes if self.GetNodeType(id) == "calculation"] + return ids
+ + +
+[docs] + def GetNodeType(self, node): + """Get the node type. + + This is the "type" entry in the data dictionary of the node. + """ + if not node: + return None + datadict = self.GetTreeItemDict(node) + if datadict is None: + return None + return datadict["type"]
+ + +
+[docs] + def SetNodeType(self, node, tp): + """Set the node type of a node.""" + if not node: + return + datadict = self.GetTreeItemDict(node) + if datadict is None: + datadict = {} + self.SetItemData(node, datadict) + datadict["type"] = tp + return
+ + +
+[docs] + def GetBranchName(self, node): + """Get the name of the branch in which node resides.""" + fp = self.GetFitRoot(node) + return self.GetItemText(fp)
+ + +
+[docs] + def GetLastPhase(self, node): + """Get the last phase child of the parent node. + + This method is helpful in placing datasets and phases into the + fit tree. This method depends on the fact that phases are placed + before datasets in the fit tree. + """ + siblings = self.GetChildren(node) + lastphase = None + for sib in siblings: + if self.GetNodeType(sib) == "dataset": + break + elif self.GetNodeType(sib) == "calculation": + break + else: + lastphase = sib + return lastphase
+ + +
+[docs] + def GetLastDataSet(self, node): + """Get the last dataset child of the fit node. + + If there is no last dataset node, this may return the last phase + node. The purpose of getting this node is to know where to place + another node, so the actual node type is not important. + """ + siblings = self.GetChildren(node) + lastdata = None + for sib in siblings: + if self.GetNodeType(sib) == "calculation": + break + else: + lastdata = sib + return lastdata
+ + +
+[docs] + def GetNumPhases(self, node): + """Get the number of phases in a branch. + + node -- A node in the branch, or the root of the branch. + """ + parent = self.GetFitRoot(node) + family = self.GetChildren(parent) + phases = [item for item in family if self.GetNodeType(item) == "phase"] + return len(phases)
+ + +
+[docs] + def GetNumDataSets(self, node): + """Get the number of datasets in a branch. + + node -- A node in the branch, or the root of the branch. + """ + parent = self.GetFitRoot(node) + family = self.GetChildren(parent) + phases = [item for item in family if self.GetNodeType(item) == "dataset"] + return len(phases)
+ + +
+[docs] + def GetPositionInSubtree(self, node): + """Get the index if the node in its subtree. + + For fits the position is absolute within the tree. For phases, + datasets, and calculations, the location is taken to be in + reference to the other nodes of its type. This is designed to be + compatible with the control center. + """ + parent = self.GetItemParent(node) + brood = self.GetChildren(parent) + pos = 0 + for sib in brood: + if sib == node: + break + else: + pos += 1 + nodetype = self.GetNodeType(node) + if nodetype == "dataset": + pos -= self.GetNumPhases(node) + if nodetype == "calculation": + pos -= self.GetNumPhases(node) + self.GetNumDataSets(node) + return pos
+ + +
+[docs] + def SetControlData(self, node, data): + """Set the control center data associated with the node. + + This need only be called for 'fit' nodes. This is the "cdata" + entry in the data dictionary of the node. It holds the object + with which the right panel interfaces. For example, for a + 'phase' node, it contains a Structure object. + """ + nodetype = self.GetNodeType(node) + if nodetype != "fit": + message = "Node type %s does not hold its own data" % nodetype + raise FitTreeError(message) + + self.GetTreeItemDict(node)["cdata"] = data + return
+ + +
+[docs] + def GetControlData(self, node): + """Get the control center data associated with a node. + + NOTE: The fit-root of a node holds this data. This method makes it + convenient to retrieve it. + """ + nodetype = self.GetNodeType(node) + parent = self.GetFitRoot(node) + pdata = self.GetTreeItemDict(parent)["cdata"] + if nodetype == "fit": + return pdata + elif nodetype == "phase": + pos = self.GetPositionInSubtree(node) + return pdata.getStructure(pos) + elif nodetype == "dataset": + pos = self.GetPositionInSubtree(node) + return pdata.getDataSet(pos) + elif nodetype == "calculation": + pos = self.GetPositionInSubtree(node) + return pdata.getCalculation(pos) + else: + message = "Node of type %s does not exist" % nodetype + raise FitTreeError(message) + return
+ + +
+[docs] + def AddFit(self, fitname="Fit 1", cdata=None, paste=False): + """Append a new fit tree to the end of the current fits. + + fitname -- The name of the fit. This is incremented if it already + exists. + cdata -- Control data for the node. If cdata is None (default), + then the control is asked to create new data. + paste -- Whether or not the cdata is being pasted from another + node (default False). + + Returns the id of the new node. + """ + # Name the fit, but check to not duplicate names. + fits = self.GetChildren(self.root) + names = [self.GetItemText(f) for f in fits] + fitname = incrementName(fitname, names) + + newfit = self.AppendItem(self.root, fitname) + self.SetNodeType(newfit, "fit") + self.SetItemImage(newfit, self.fitbmid, wx.TreeItemIcon_Normal) + pos = self.GetPositionInSubtree(newfit) + + try: + # Set the node data for the new node + if cdata is None: + cdata = self.control.newFitting(fitname, pos) + elif paste: + cdata = self.control.paste(cdata, None, fitname, pos) + self.SetControlData(newfit, cdata) + return newfit + except Exception: + self.Delete(newfit) + raise + return
+ + +
+[docs] + def AddPhase(self, node, label, insertafter=None, filename=None, makedata=True, cdata=None): + """Add a new blank Phase to the tree as a child of node. + + node -- The parent 'fit' node. + label -- The name of the new node. + insertafter -- The node after which to insert the new phase. If + insertafter is None (default) the new phase is + appended to the end of the phases in the subtree of + the parent node. + filename -- The file from which to load the structure. If this is + None (default), a new structure is created. + makedata -- Tells whether the control needs to make data for the + node (default True). + cdata -- Control data for the node. If cdata is None (default), + then it is assumed that the node already has data in the + control. See ExtendProjectTree and __InsertBranch for + examples of how this is used. + + Phases are always placed before DataSets. + + Raises: + FitTreeError if node is not a "fit" node. + FitTreeError if insertafter is not a "phase" node. + + Returns the id of the new node. + """ + # Check to make sure the new phase is a child of a fit or calculation + nodetype = self.GetNodeType(node) + if nodetype != "fit": + message = "Can only add a phase as a child of a fit." + raise FitTreeError(message) + + if insertafter is not None: + afttype = self.GetNodeType(insertafter) + if afttype != "phase": + insertafter = None + + if insertafter: + newphase = self.InsertItem(node, insertafter, label) + else: + lastphase = self.GetLastPhase(node) + if lastphase: + # Put the new phase after the last + newphase = self.InsertItem(node, lastphase, label) + else: + newphase = self.PrependItem(node, label) + + self.SetNodeType(newphase, "phase") + self.SetItemImage(newphase, self.phabmid, wx.TreeItemIcon_Normal) + + # Set the control data to the new phase + pdata = self.GetControlData(node) + pos = self.GetPositionInSubtree(newphase) + + # Try to get/make the node data from the control. If it doesn't work, + # then delete the new node. + try: + if makedata: + if filename is None: + self.control.newStructure(pdata, label, pos) + else: + self.control.loadStructure(pdata, filename, label, pos) + + elif cdata is not None: + self.control.paste(cdata, pdata, label, pos) + return newphase + except Exception: + self.Delete(newphase) + raise + return
+ + +
+[docs] + def AddDataSet(self, node, label, insertafter=None, filename=None, makedata=True, cdata=None): + """Add a new DataSet to the tree as a child of fit. + + node -- The parent node of the dataset. Must be 'fit' type. + label -- The label of the new node. + insertafter -- The node after which to insert the new dataset. If + insertafter is None (default) the new dataset is + appended to the end of the datasets in the subtree of + the parent node. + filename -- The name of the file from which to load the data. + makedata -- Tells whether the control needs to make data for the + node (default True). If True, cdata is ignored. + cdata -- Control data for the node. If False cdata is None + (default), then it is assumed that the node already has + data in the control. See ExtendProjectTree and + __InsertBranch for examples of how this is used. + + DataSets are always placed after Phases. + + Raises: + FitTreeError if node is not a "fit" node. + FitTreeError if insertafter is not a "dataset" node. + + Returns the id of the new node. + """ + # Check to make sure the new dataset is a child of a fit + nodetype = self.GetNodeType(node) + if nodetype != "fit": + message = "Can only add a data set as a child of a fit." + raise FitTreeError(message) + + if insertafter is not None: + afttype = self.GetNodeType(node) + if afttype != "dataset": + insertafter = None + + if insertafter: + newset = self.InsertItem(node, insertafter, label) + else: + lastset = self.GetLastDataSet(node) + if lastset: + newset = self.InsertItem(node, lastset, label) + else: + newset = self.PrependItem(node, label) + + self.SetNodeType(newset, "dataset") + self.SetItemImage(newset, self.dtsbmid, wx.TreeItemIcon_Normal) + # Attach the control center data to the new dataset + pos = self.GetPositionInSubtree(newset) + pdata = self.GetControlData(node) + + try: + if makedata: + if filename is not None: + self.control.loadDataset(pdata, filename, label, pos) + else: + raise FitTreeError("Cannot load a dataset without a name!") + elif cdata is not None: + self.control.paste(cdata, pdata, label, pos) + return newset + except Exception: + self.Delete(newset) + raise + return
+ + +
+[docs] + def AddCalc(self, node, label, insertafter=None, makedata=True, cdata=None): + """Add a new DataSet to the tree as a child of fit. + + node -- The parent node of the calculation. Must be 'fit' type. + label -- The label of the new node. + insertafter -- The node after which to insert the new calculation. If + insertafter is None (default) the new calculation is + appended to the end of the calculation in the subtree of + the parent node. + makedata -- Tells whether the control needs to make data for the + node (default True). If True, cdata is ignored. + cdata -- Control data for the node. If False cdata is None + (default), then it is assumed that the node already has + data in the control. See ExtendProjectTree and + __InsertBranch for examples of how this is used. + + Calculations are always placed after datasets. + + Raises: + FitTreeError if node is not a "fit" node. + FitTreeError if insertafter is not a "calculation" node. + + Returns the id of the new node. + """ + # Check to make sure the new calculation is a child of a fit + nodetype = self.GetNodeType(node) + if nodetype != "fit": + message = "Can only add a calculation as a child of a fit." + raise FitTreeError(message) + + if insertafter is not None: + afttype = self.GetNodeType(node) + if afttype != "calculation": + insertafter = None + + sibs = self.GetCalculations(node) + names = [self.GetItemText(sb) for sb in sibs] + label = incrementName(label, names) + + if insertafter: + newcalc = self.InsertItem(node, insertafter, label) + else: + newcalc = self.AppendItem(node, label) + + self.SetNodeType(newcalc, "calculation") + self.SetItemImage(newcalc, self.clcbmid, wx.TreeItemIcon_Normal) + # Attach the control center data to the new datacalc + pos = self.GetPositionInSubtree(newcalc) + pdata = self.GetControlData(node) + + try: + if makedata: + self.control.newCalculation(pdata, label, pos) + elif cdata is not None: + self.control.paste(cdata, pdata, label, pos) + return newcalc + except Exception: + self.Delete(newcalc) + raise + return
+ + +
+[docs] + def CopyBranch(self, startnode): + """Make a copy of a tree branch. + + The branch is held in the system clipboard so it can be used in + another instance of the fittree. + """ + nodetype = self.GetNodeType(startnode) + cdata = self.control.copy(self.GetControlData(startnode)) + if isinstance(cdata, Fitting): + cdata = cdata.stripped() + cdata.type = nodetype + cdatabytes = safeCPickleDumps(cdata) + cdatabytes = "pdfgui_cliboard=".encode() + cdatabytes + # wxpython only accepts str, use base64 to convert bytes to str + cdatastring = base64.b64encode(cdatabytes) + textdata = wx.TextDataObject(cdatastring) + if not wx.TheClipboard.IsOpened(): + opened = wx.TheClipboard.Open() + if not opened: + raise FitTreeError("Cannot open the clipboard.") + wx.TheClipboard.SetData(textdata) + wx.TheClipboard.Close() + return
+ + +
+[docs] + def GetClipboard(self): + """Get the clipboard data. + + Returns the controldata in the clipboard, or None if the + clipboard is empty or contains the wrong type of data. + """ + # Check to see if data is present + if not wx.TheClipboard.IsSupported(wx.DataFormat(wx.DF_TEXT)): + return None + + textdata = wx.TextDataObject() + if not wx.TheClipboard.IsOpened(): + opened = wx.TheClipboard.Open() + if not opened: + return None + success = wx.TheClipboard.GetData(textdata) + wx.TheClipboard.Close() + if not success: + return None + cdatastring = textdata.GetText() + + cdata = None + # use base64 to convert str back to bytes + try: + cdatabytes = base64.b64decode(cdatastring.encode()) + + if cdatabytes[:16] == "pdfgui_cliboard=".encode(): + cdatabytes = cdatabytes[16:] + cdata = pickle.loads(cdatabytes, encoding="latin1") + except Exception: + pass + return cdata
+ + +
+[docs] + def PasteBranch(self, entrypoint=None): + """Paste the branch from the clipboard into tree at the given node. + + A certain type of branch can only be copied to specific places. + + fit - A fit can be pasted to anywhere. This does not overwrite + an existing node, but simply inserts the fit into the + last available slot. + phase - A phase can be pasted from anywhere. If pasted from a + fit, it is placed at the end of the phase section of + that node. If inserted from a dataset or a calculation, + it is placed at the end of the phase section. + dataset - A dataset can be pasted from anywhere. If pasted from a + fit, the dataset is appended at the end of the other + datasets. If pasted from a dataset, the pasted set is + inserted right after that one. If pasted from a phase, + it is placed at the beginning of the dataset section. If + pasted from a calculation, it is placed at the end of + the dataset section. + calculation - A calculation can be pasted to anywhere, but it appears + at the end of the calculation section of the tree. If + pasted from a calculation node, it is inserted after + that node. + + Raises: + FitTreeError if the entrypoint and branch type are incompatible. + """ + cdata = self.GetClipboard() + if cdata is None: + message = "There is no branch to paste!" + raise FitTreeError(message) + + # Now we have the cdata, we must put it into the tree + branchtype = cdata.type + insertafter = None + prepend = False + entrytype = None + if entrypoint: + entrytype = self.GetNodeType(entrypoint) + # Check to see what we are trying to paste, and where. + + if branchtype == "fit": + # Paste after the selected fit containing the selection, or + # after the last fit if a calculation is selected. If nothing is + # selected, just paste it! + + entrytype = None + if entrypoint: + entrypoint = self.GetFitRoot(entrypoint) + entrytype = self.GetNodeType(entrypoint) + + if entrytype is None: + entrypoint = self.root + insertafter = None + elif entrytype == "fit": + insertafter = entrypoint + entrypoint = self.root + else: # Just in case + raise FitTreeError("Cannot paste a fit branch here.") + + if branchtype == "phase": + # Paste after selected phase, or append to the end of the phase + # section of a fit. + + if entrytype == "phase": + # The entry is to be a sibling. + insertafter = entrypoint + entrypoint = self.GetItemParent(entrypoint) + elif entrytype in ("dataset", "calculation"): + # Paste to the end of the phases, if they exist. + entrypoint = self.GetItemParent(entrypoint) + insertafter = self.GetLastPhase(entrypoint) + if not insertafter: + # Put the branch at the beginning of the phases + prepend = True + elif entrytype == "fit": + # Get the last phase in the phase section, which may not + # exist. + insertafter = self.GetLastPhase(entrypoint) + if not insertafter: + # Put the branch at the beginning of the phases + prepend = True + else: # Just in case + raise FitTreeError("Cannot paste a phase branch here.") + + if branchtype == "dataset": + # Paste after a selected dataset, or into a selected fit. + + if entrytype == "dataset": + # The entry is to be a sibling. + insertafter = entrypoint + entrypoint = self.GetItemParent(entrypoint) + elif entrytype == "phase": + # The entry goes to the end of the phases, which must exist. + entrypoint = self.GetItemParent(entrypoint) + insertafter = self.GetLastPhase(entrypoint) + elif entrytype == "calculation": + # The entry goes to the end of the datasets. + entrypoint = self.GetItemParent(entrypoint) + insertafter = self.GetLastDataSet(entrypoint) + elif entrytype == "fit": + insertafter = self.GetLastDataSet(entrypoint) + # The entrypoint is ok. The branch is appended to the end of + # the calculations. + pass + else: + raise FitTreeError("Cannot paste a data set branch here.") + + if branchtype == "calculation": + # Paste after the selected calculation or after the calculations. + + if entrytype == "calculation": + # The entry is to be a sibling. + insertafter = entrypoint + entrypoint = self.GetItemParent(entrypoint) + elif entrytype in ("phase", "dataset"): + entrypoint = self.GetItemParent(entrypoint) + insertafter = self.GetLastDataSet(entrypoint) + elif entrytype == "fit": + insertafter = self.GetLastDataSet(entrypoint) + else: # Just in case + raise FitTreeError("Cannot paste a calculation branch here.") + + # Now set the name of the item to be inserted. + label = self.__copyLabel(cdata.name, entrypoint) + + # Now we have a label. We must insert the item into the tree. + newnode = self.__InsertBranch(cdata, entrypoint, label, insertafter, prepend) + + return newnode
+ + + def __copyLabel(self, oldlabel, entrypoint): + """Make a new label that is appropriate for a new node.""" + # Append "_copy" to the end of the label, unless it already has that. + # In that case, just add a number to indicate which copy it is. + siblings = self.GetChildren(entrypoint) + labels = [self.GetItemText(sb) for sb in siblings] + match = r"_copy\d*$" + label = re.sub(match, "", oldlabel) + label += "_copy" + label = incrementName(label, labels) + return label + + def __InsertBranch(self, cdata, entrypoint, label, insertafter=None, prepend=False): + """Insert control data into the tree. + + cdata -- The control data that goes with the branch + entrypoint -- The subbranch (fit root) to paste into + label -- The label of the new node + insertafter -- A node after which to insert. If insertafter is None + (default), then the new node will be pasted after the + last node of the same type. + prepend -- Prepend to the beginning of the node group (default + False). insertafter takes prescedent over prepend. + + Returns the newly inserted node. + """ + if cdata is None: + message = "There is no branch to paste!" + raise FitTreeError(message) + + branchtype = cdata.type + # cdata.name = label + if branchtype == "fit": + cdata.name = label + newnode = self.ExtendProjectTree([cdata.organization()], clear=False, paste=True) + elif branchtype == "phase": + newnode = self.AddPhase(entrypoint, label, insertafter=insertafter, makedata=False, cdata=cdata) + elif branchtype == "dataset": + newnode = self.AddDataSet(entrypoint, label, insertafter=insertafter, makedata=False, cdata=cdata) + elif branchtype == "calculation": + newnode = self.AddCalc(entrypoint, label, insertafter=insertafter, makedata=False, cdata=cdata) + else: + raise FitTreeError("Unrecognized node type: %s" % branchtype) + + return newnode + +
+[docs] + def DeleteBranches(self, selections): + """Remove the subtree starting from the selected node(s).""" + # Get a list of branch heads + branchset = [node for node in selections if self.GetNodeType(node) == "fit"] + + # Get their children + childset = [] + for node in branchset: + childset.extend(self.GetChildren(node)) + + # Collect all nodes, removing any children of branch nodes. + nodeset = [node for node in selections if node not in childset] + + for node in nodeset: + cdata = self.GetControlData(node) + self.control.remove(cdata) + self.Delete(node) + return nodeset
+ + +
+[docs] + def SelectAll(self): + """Select all nodes.""" + self.UnselectAll() + fits = self.GetChildren(self.root) + for fit in fits: + children = self.GetChildren(fit) + self.SelectItem(fit) + for child in children: + self.SelectItem(child) + return
+ + +
+[docs] + def SelectAllType(self, node=None): + """Select all nodes of same type as passed node. + + node -- Node whose type to select. If node is None (default), then + all fit nodes will be selected. + """ + self.UnselectAll() + if node is None: + # Get the first fit node + fits = self.GetChildren(self.root) + if not fits: + return + node = fits[0] + typelist = self.GetAllType(node) + for item in typelist: + self.SelectItem(item) + return
+ + +
+[docs] + def ExtendProjectTree(self, treelist, clear=True, paste=False): + """Extend the project tree from the treelist. + + treelist -- A list of control data returned by + Oraganizer.organization() + clear -- Clear the tree before adding new nodes (default True) + paste -- Whether or not the cdata is being pasted from another + node (default False). + + The treelist here is of the type returned from pdfguicontrol.load. + It is a list of fit lists with the following format. + node[0] -- fit object + node[1] -- list of (name, dataset) tuples + node[2] -- list of (name, phase) tuples + node[3] -- list of (name, calculation) tuples + + Note that node[1] should be empty if the node is a calculation. + + Returns the last inserted fit or calculation node + """ + # Clean slate + if clear: + self.DeleteAllItems() + self.InitializeTree() + roots = [] + + # Return if the treelist is empty + if not treelist: + return + + # Build the tree + for item in treelist: + broot = item[0] + name = broot.name + node = self.AddFit(name, cdata=broot, paste=paste) + + if node is None: + message = "Cannot insert data. Malformed tree list." + raise FitTreeError(message) + + roots.append(node) + # Build the rest of the tree. Note that we don't want to create new + # data, but we don't pass the cdata since it is already included in + # the fit root. + phases = item[2] + for name, phase in phases: + self.AddPhase(node, name, makedata=False) + dsets = item[1] + for name, set in dsets: + self.AddDataSet(node, name, makedata=False) + calcs = item[3] + for name, calc in calcs: + self.AddCalc(node, name, makedata=False) + + for item in roots: + self.Expand(item) + return node
+
+ + + +# End class FitTree + + +# Exceptions +
+[docs] +class FitTreeError(ControlError): + def __init__(self, *args): + ControlError.__init__(self, *args) + return
+ + + +# End class FitTreeError + + +# Utility functions +
+[docs] +def incrementName(name, namelist, start=1): + """Increment the name by assigning the lowest number to the end such that + the name does not appear in the namelist.""" + newname = name + match = r"\d+$" + counter = start + while newname in namelist: + newname = re.sub(match, "", name) + counter += 1 + newname = "%s%i" % (newname, counter) + return newname
+ +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/insertrowsdialog.html b/_modules/diffpy/pdfgui/gui/insertrowsdialog.html new file mode 100644 index 00000000..622b841a --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/insertrowsdialog.html @@ -0,0 +1,179 @@ + + + + + + + + diffpy.pdfgui.gui.insertrowsdialog — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.insertrowsdialog

+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Dmitriy Bryndin
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+# generated by wxGlade 0.9.3 on Fri Jul 19 16:08:52 2019
+
+import wx
+
+
+
+[docs] +class InsertRowsDialog(wx.Dialog): + def __init__(self, *args, **kwds): + # begin wxGlade: InsertRowsDialog.__init__ + kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_DIALOG_STYLE + wx.Dialog.__init__(self, *args, **kwds) + self.Rows = wx.StaticText(self, wx.ID_ANY, "Rows:") + self.spin_ctrl_Rows = wx.SpinCtrl(self, wx.ID_ANY, "1", min=0, max=100, style=0) + self.radio_box_where = wx.RadioBox( + self, + wx.ID_ANY, + "", + choices=["Above", "Below"], + majorDimension=2, + style=wx.RA_SPECIFY_ROWS, + ) + self.button_OK = wx.Button(self, wx.ID_OK, "OK") + self.button_Cancel = wx.Button(self, wx.ID_CANCEL, "Cancel") + + self.__set_properties() + self.__do_layout() + # end wxGlade + + def __set_properties(self): + # begin wxGlade: InsertRowsDialog.__set_properties + self.SetTitle("InsertRows") + self.radio_box_where.SetSelection(1) + # end wxGlade + + def __do_layout(self): + # begin wxGlade: InsertRowsDialog.__do_layout + sizer_horiz = wx.BoxSizer(wx.HORIZONTAL) + sizer_right_vert = wx.BoxSizer(wx.VERTICAL) + sizer_left_vert = wx.BoxSizer(wx.VERTICAL) + sizer_4 = wx.BoxSizer(wx.HORIZONTAL) + sizer_4.Add(self.Rows, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) + sizer_4.Add(self.spin_ctrl_Rows, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) + sizer_left_vert.Add(sizer_4, 0, wx.EXPAND, 0) + sizer_left_vert.Add(self.radio_box_where, 0, wx.ALL | wx.EXPAND, 5) + sizer_horiz.Add(sizer_left_vert, 0, wx.EXPAND, 0) + sizer_right_vert.Add(self.button_OK, 0, wx.ALL, 5) + sizer_right_vert.Add(self.button_Cancel, 0, wx.ALL, 5) + sizer_horiz.Add(sizer_right_vert, 0, wx.EXPAND, 0) + self.SetSizer(sizer_horiz) + sizer_horiz.Fit(self) + self.Layout()
+ + # end wxGlade + + +# end of class InsertRowsDialog +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/journalpanel.html b/_modules/diffpy/pdfgui/gui/journalpanel.html new file mode 100644 index 00000000..16c6d0a7 --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/journalpanel.html @@ -0,0 +1,258 @@ + + + + + + + + diffpy.pdfgui.gui.journalpanel — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.journalpanel

+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+# generated by wxGlade 0.9.3 on Fri Jul 19 16:03:01 2019
+
+import os.path
+
+import wx
+
+from diffpy.pdfgui.gui.pdfpanel import PDFPanel
+
+
+
+[docs] +class JournalPanel(wx.Panel, PDFPanel): + def __init__(self, *args, **kwds): + PDFPanel.__init__(self) + # begin wxGlade: JournalPanel.__init__ + kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL + wx.Panel.__init__(self, *args, **kwds) + self.textCtrlJournal = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_MULTILINE) + self.exportButton = wx.Button(self, wx.ID_ANY, "Export") + self.closeButton = wx.Button(self, wx.ID_CLOSE, "") + + self.__set_properties() + self.__do_layout() + + self.Bind(wx.EVT_TEXT, self.onText, self.textCtrlJournal) + self.Bind(wx.EVT_BUTTON, self.onExport, self.exportButton) + self.Bind(wx.EVT_BUTTON, self.onClose, self.closeButton) + # end wxGlade + self.__customProperties() + + def __set_properties(self): + # begin wxGlade: JournalPanel.__set_properties + pass + # end wxGlade + + def __do_layout(self): + # begin wxGlade: JournalPanel.__do_layout + sizer_1 = wx.BoxSizer(wx.VERTICAL) + sizer_2 = wx.BoxSizer(wx.HORIZONTAL) + sizer_1.Add(self.textCtrlJournal, 1, wx.EXPAND, 0) + sizer_2.Add((1, 1), 1, 0, 0) + sizer_2.Add(self.exportButton, 0, wx.ALL, 5) + sizer_2.Add(self.closeButton, 0, wx.ALL, 5) + sizer_1.Add(sizer_2, 0, wx.EXPAND, 0) + self.SetSizer(sizer_1) + sizer_1.Fit(self) + self.Layout() + # end wxGlade + + def __customProperties(self): + """Custom Properties go here.""" + self.fullpath = "" + + # Bind the focus loss of the text control + self.textCtrlJournal.Bind(wx.EVT_KEY_DOWN, self.onKey) + return + +
+[docs] + def onText(self, event): # wxGlade: JournalPanel.<event_handler> + """Record anything that is written into the journal.""" + text = self.textCtrlJournal.GetValue() + if text != self.mainFrame.control.journal: + self.mainFrame.control.journal = text + self.mainFrame.needsSave() + return
+ + +
+[docs] + def onExport(self, event): # wxGlade: JournalPanel.<event_handler> + """Export the journal to an external file.""" + matchstring = "Text files (*.txt)|*.txt|All Files|*" + dir, filename = os.path.split(self.fullpath) + if not dir: + dir = self.mainFrame.workpath + d = wx.FileDialog( + None, + "Export to...", + dir, + filename, + matchstring, + wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT, + ) + + if d.ShowModal() == wx.ID_OK: + self.fullpath = d.GetPath() + self.mainFrame.workpath = os.path.dirname(self.fullpath) + outfile = open(self.fullpath, "w") + outfile.write(self.mainFrame.control.journal) + outfile.close() + d.Destroy() + return
+ + +
+[docs] + def onClose(self, event): # wxGlade: JournalPanel.<event_handler> + self._close() + return
+ + + def _close(self): + self.mainFrame.onShowJournal(None) + return + +
+[docs] + def onKey(self, event): + """Catch Ctrl+J to close the journal.""" + # Ctrl J + key = event.GetKeyCode() + if event.ControlDown() and key == 74: + self._close() + event.Skip() + return
+ + + # Methods overloaded from PDFPanel +
+[docs] + def refresh(self): + """Fill the jounalTextCtrl with the journal.""" + # This will make sure that the scroll position does not change. + text = self.textCtrlJournal.GetValue() + if text != self.mainFrame.control.journal: + self.textCtrlJournal.ChangeValue(self.mainFrame.control.journal) + self.textCtrlJournal.SetInsertionPointEnd() + pos = self.textCtrlJournal.GetInsertionPoint() + self.textCtrlJournal.ShowPosition(pos) + return
+
+ + + +# end of class JournalPanel +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/main.html b/_modules/diffpy/pdfgui/gui/main.html new file mode 100644 index 00000000..fb10b4fd --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/main.html @@ -0,0 +1,164 @@ + + + + + + + + diffpy.pdfgui.gui.main — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for diffpy.pdfgui.gui.main

+#!/usr/bin/env python
+# -*- coding: ISO-8859-1 -*-
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+# generated by wxGlade 0.4 on Tue Feb 21 12:00:30 2006
+
+import wx
+
+
+
+[docs] +class PDFGuiApp(wx.App): +
+[docs] + def OnInit(self): + from diffpy.pdfgui.gui.mainframe import MainFrame + + self.frame = MainFrame(None, -1, "") + self.SetTopWindow(self.frame) + self.frame.Show() + return True
+
+ + + +# end of class PDFGuiApp + + +
+[docs] +def main(): + """Kick starter for the PDFgui graphical user interface. + + This function is normally called from a light-weight console starter + diffpy.pdfgui.applications.pdfgui. Command line options and + arguments can be passed via cmdopts and cmdargs variables of the + pdfguiglobals module. + """ + app = PDFGuiApp(0) + app.MainLoop() + return
+ + + +if __name__ == "__main__": + main() +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/mainframe.html b/_modules/diffpy/pdfgui/gui/mainframe.html new file mode 100644 index 00000000..263c5c90 --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/mainframe.html @@ -0,0 +1,2960 @@ + + + + + + + + diffpy.pdfgui.gui.mainframe — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for diffpy.pdfgui.gui.mainframe

+#!/usr/bin/env python
+# -*- coding: ISO-8859-1 -*-
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+# generated by wxGlade 0.4 on Thu Feb 23 15:06:06 2006
+"""This module contains the main window of PDFgui."""
+
+import os.path
+from configparser import ConfigParser
+
+import wx
+import wx.aui
+import wx.lib.newevent
+
+from diffpy.pdfgui.control import structureviewer
+from diffpy.pdfgui.control.controlerrors import ControlError, ControlFileError
+from diffpy.pdfgui.control.pdfguicontrol import pdfguicontrol
+from diffpy.pdfgui.gui import pdfguiglobals
+from diffpy.pdfgui.gui.aboutdialog import DialogAbout
+from diffpy.pdfgui.gui.adddatapanel import AddDataPanel
+from diffpy.pdfgui.gui.addphasepanel import AddPhasePanel
+from diffpy.pdfgui.gui.blankpanel import BlankPanel
+from diffpy.pdfgui.gui.calculationpanel import CalculationPanel
+from diffpy.pdfgui.gui.datasetpanel import DataSetPanel
+from diffpy.pdfgui.gui.dopingseriespanel import DopingSeriesPanel
+from diffpy.pdfgui.gui.errorreportdialog import USERSMAILINGLIST, ErrorReportDialog
+from diffpy.pdfgui.gui.errorwrapper import catchObjectErrors
+from diffpy.pdfgui.gui.fitnotebookpanel import FitNotebookPanel
+from diffpy.pdfgui.gui.fittree import FitTree, FitTreeError
+from diffpy.pdfgui.gui.journalpanel import JournalPanel
+from diffpy.pdfgui.gui.outputpanel import OutputPanel
+from diffpy.pdfgui.gui.pdfguiglobals import docMainFile, iconpath
+from diffpy.pdfgui.gui.phasenotebookpanel import PhaseNotebookPanel
+from diffpy.pdfgui.gui.plotpanel import PlotPanel
+from diffpy.pdfgui.gui.preferencespanel import PreferencesPanel
+from diffpy.pdfgui.gui.rseriespanel import RSeriesPanel
+from diffpy.pdfgui.gui.temperatureseriespanel import TemperatureSeriesPanel
+from diffpy.pdfgui.gui.welcomepanel import WelcomePanel
+
+(PDFCustomEvent, EVT_PDFCUSTOM) = wx.lib.newevent.NewEvent()
+
+# WARNING - This file cannot be maintained with wxglade any longer. Do not make
+# modifications with wxglade!!!
+
+# README - Note that wx.TreeCtrl.GetSelections works differently in MSW than it
+# does in GTK. In GTK, it returns a list of nodes as they appear in the tree.
+# In MSW, it returns the list of nodes in some other order.  This can lead to
+# trouble if the order of selected nodes is important to a method.
+# wx.TreeControl does not create an event in windows.  Node deselection does
+# not create an event on windows. There is no workaround for this.  Node
+# selection vetoing does not work on windows.  Finally, changing the tree
+# selection sends two selection events on windows. One for an empty selection
+# and one with the new selections.
+
+
+
+[docs] +class MainFrame(wx.Frame): + """The left pane is a FitTree (from fittree.py), the right is a dynamic + panel, accessed via the data member rightPanel, which can hold one of any + number of panels. The panels that can appear in the right pane must be + derived from PDFPanel (in pdfpanel.py) and are defined in the dynamicPanels + dictionary, which is defined in __customProperties. A panel is placed in + the right pane by passing its dynamicPanels dictionary key to the + switchRightPanel method. This method takes care of displaying the panel, + giving the data it needs, and calling its refresh() method. + + ** NODE TYPES ** + The FitTree is essential to the functionality of the Gui. + The tree contains one of five types of items: + "fit" -- This represents a fit that is to be run by pdffit. + "dataset" -- This represents a data for a fit. + "phase" -- This represents the theoretical phases needed for a + dataset or a calculation. + "calculation" -- This represents a calculation which is to be made from + using a configured fit. + + Depending upon what type of item is selected in the tree, the right pane + will display the properties and configuration of that item (if in "fitting + mode", see below.) More on these item types is given in the documentation + for the FitTree in fittree.py. See r + + ** MODES ** + The program has various modes of operation. + "fitting" -- In this mode the right pane changes depending upon what + type of item is selected in the FitTree. When the + fitting button is pressed, the program is in "fitting" + mode. + "addingdata" -- This mode is for adding data. + "addingphase" -- This mode is for adding the phase + "config" -- This mode is used for preferences and structure viewer + configuration. + "rseries" -- The mode used when configuring an r-series macro. + "tseries" -- The mode used when configuring a temperature series + macro. + "dseries" -- The mode used when configuring a doping series macro. + + The mode determines how the tree and other widgets react to user + interaction. The mode of the program is changed with the method setMode. + This method outright enables or disables certain widgets that should not be + used when in certain modes. + + ** DATA MEMBERS ** + dynamicPanels -- The dictionary of right panels. This is used to change the + right panel in the method switchRightPanel. The panels held + by the dynamicPanels dictionary are listed below by their + dictionary keys: + + * Miscellaneous panels: + "blank" -- A blank panel + "rseries" -- The r-series macro panel + "tseries" -- The temperature series macro panel + "dseries" -- The doping series macro panel + "welcome" -- A welcome panel + + * 'fitting' mode panels + "fit" -- The panel for 'fit' nodes + "phase" -- The panel for 'phase' nodes + "dataset" -- The panel for 'dataset' nodes + "calculation" -- The panel for 'calculation' nodes + + * Panels specific to other program modes + "adddata" -- The panel used in 'addingdata' mode + "addphase" -- The panel used in 'addingphase' mode + + * Panels for future implementation + "configuration" -- Another 'config' mode panel + + rightPanel -- The current right panel. + fullpath -- The full path to the most recently accessed project file. + workpath -- The full path to the working directory. This is modified + whenever something is loaded or saved to file. It is + preserved in the current session and across new projects. + cP -- A python SafeConfigurationParser object. This is in charge + of storing configuration information about the most recently + used files list. It is also used by addphasepanel and + adddatapanel to store their respective fullpath variables. + The code that handles the MRU files interacts directly + with cP. + mode -- The current mode of the program. This is modified using the + setMode method. See the MODES section above. + name -- The name of the program as defined in pdfguiglobals. + control -- The pdfguicontrol object needed for interfacing with the + engine pdffit2 code. + isAltered -- A Boolean flag that indicates when the program has been + altered. This should be changed with the method needsSave so + that the save menu item and toolbar button can be updated + accordingly. + runningDict -- A dictionary of running fits and calculations indexed by + name. This dictionary is used to change the status colors of + running fits and to keep the user from editing a running + fit. + quitting -- A boolean that is set when the program is quitting. This + flag tells the error handlers to ignore any errors that take + place during shutdown. + """ + + def __init__(self, *args, **kwds): + kwds["style"] = wx.DEFAULT_FRAME_STYLE + + wx.Frame.__init__(self, *args, **kwds) + + self.SetMinSize((700, 500)) + self.auiManager = wx.aui.AuiManager(self) + + self.treeCtrlMain = FitTree( + self, + -1, + style=wx.TR_HAS_BUTTONS + | wx.TR_NO_LINES + | wx.TR_EDIT_LABELS + | wx.TR_MULTIPLE + | wx.TR_HIDE_ROOT + | wx.TR_MULTIPLE + | wx.TR_DEFAULT_STYLE + | wx.SUNKEN_BORDER, + ) + self.plotPanel = PlotPanel(self, -1) + self.outputPanel = OutputPanel(self, -1) + self.journalPanel = JournalPanel(self, -1) + self.panelDynamic = BlankPanel(self, -1) + + self.__customProperties() + + self.Bind(wx.EVT_TREE_SEL_CHANGING, self.onTreeSelChanging, self.treeCtrlMain) + self.Bind(wx.EVT_TREE_SEL_CHANGED, self.onTreeSelChanged, self.treeCtrlMain) + self.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.onEndLabelEdit, self.treeCtrlMain) + self.Bind(wx.EVT_TREE_BEGIN_LABEL_EDIT, self.onBeginLabelEdit, self.treeCtrlMain) + self.__customBindings() + self.__cmdLineLoad() + self.updateTitle() + + self.auiManager.Update() + self.switchRightPanel("welcome") + return + + # USER CONFIGURATION CODE ################################################# + + def __cmdLineLoad(self): + """Open file loaded from the command line. + + This opens a file without any checking for existing projects. + This should only be called after all initializations. It will + open a file whose name is specified in pdfguiglobals.cmdargs. + """ + if pdfguiglobals.cmdargs: + filename = pdfguiglobals.cmdargs[0] + fullpath = os.path.abspath(filename) + treelist = self.control.load(fullpath) + self.treeCtrlMain.ExtendProjectTree(treelist) + self.fullpath = fullpath + self.workpath = os.path.dirname(fullpath) + self.fileHistory.AddFileToHistory(fullpath) + self.plotPanel.refresh() + return + + def __defineLocalIds(self): + """Several user functions are duplicated many times throughout the gui. + + This occurs mostly between the main menu, the right-click menu, + and the many buttons in the gui. This method defines local Ids + that can be used for all of these. + """ + # Functions that modify the tree. + # These are used in the fitting right-click menu and the main menu. + self.newFitId = wx.NewIdRef() # New Fit + self.newCalcId = wx.NewIdRef() # New Calculation + self.newPhaseId = wx.NewIdRef() # New Phase + self.newDataId = wx.NewIdRef() # New Data Set + self.deleteId = wx.ID_DELETE # Delete tree item + self.copyId = wx.ID_COPY # Copy a tree item + self.pasteId = wx.ID_PASTE # Paste a tree item into tree + self.pasteLinkId = wx.NewIdRef() # Paste and link a fit node + + # Misc. functions, these are exclusive to the main menu. + self.newId = wx.ID_NEW # Start a new Project + self.openId = wx.ID_OPEN # Open a project + self.recentId = None # Open a recent project (set later) + self.saveId = wx.ID_SAVE # Save the project + self.saveAsId = wx.ID_SAVEAS # Save the project as... + self.quitId = wx.ID_CLOSE # Quit the program + self.runFitId = wx.NewIdRef() # Run a fit + self.stopFitId = wx.NewIdRef() # Stop a fit + self.quickPlotId = wx.NewIdRef() # Quick plot a fit + self.exportFitPDFId = wx.NewIdRef() # Save a fit PDF + self.exportFitStruId = wx.NewIdRef() # Save a fit structure + self.exportNewStruId = wx.NewIdRef() # Export a 'new' structure + self.plotIStructId = wx.NewIdRef() # Plot initial structure + self.plotFStructId = wx.NewIdRef() # Plot final structure + self.printBLId = wx.NewIdRef() # Print the bond lengths of a structure + self.printBAId = wx.NewIdRef() # Print the bond angles of a structure + self.exportResId = wx.NewIdRef() # Save the results file + self.runCalcId = wx.NewIdRef() # Run a calculation + self.exportCalcPDFId = wx.NewIdRef() # Save a calculated PDF + return + + def __customProperties(self): + """Custom Properties go here.""" + # Set some visual stuff + icon = wx.Icon(iconpath("pdfgui.ico"), wx.BITMAP_TYPE_ANY) + self.SetIcon(icon) + + # The panel should know its name + self.name = pdfguiglobals.name + + # The fit tree needs a copy of the control, as + # most interactions with the control happen there. + self.control = pdfguicontrol(self) + self.control.startQueue() + self.treeCtrlMain.control = self.control + + # Constants needed for communication with the control + self.ERROR = 1 + self.UPDATE = 1 << 1 + self.OUTPUT = 1 << 2 + self.PLOTNOW = 1 << 3 + + # Needed for the error checker so it doesn't throw errors at quit time + self.quitting = False + + # Wrap the events to use an event handler + self.mainFrame = self # needed by error wrapper + catchObjectErrors(self) + + # Needed for loading and saving + self.fullpath = "" + self.workpath = os.path.abspath(".") + + # The dictionary of running fits/calculations + self.runningDict = {} + + # The configuration parser for getting configuration data. + # self.cP = Configparser() + # Long try this to avoid DuplicateSectionError and ParsingError + self.cP = ConfigParser(strict=False, allow_no_value=True, interpolation=None) + + # Set the program mode + self.mode = "fitting" + + # This is the dictionary of right panels. For simplicity the five panels + # corresponding to the five tree item types are given the name of the + # data type (fit, dataset, phase, calculation). This allows for + # automatic switching of panels. + self.dynamicPanels = { + "blank": self.panelDynamic, + "welcome": WelcomePanel(self, -1), + "fit": FitNotebookPanel(self, -1), + "phase": PhaseNotebookPanel(self, -1), + "dataset": DataSetPanel(self, -1), + "calculation": CalculationPanel(self, -1), + "adddata": AddDataPanel(self, -1), + "addphase": AddPhasePanel(self, -1), + "preferences": PreferencesPanel(self, -1), + "rseries": RSeriesPanel(self, -1), + "tseries": TemperatureSeriesPanel(self, -1), + "dseries": DopingSeriesPanel(self, -1), + } + + # Prepare the right pane. Display the welcome screen. + self.rightPanel = self.panelDynamic + for key in self.dynamicPanels: + self.auiManager.AddPane( + self.dynamicPanels[key], + wx.aui.AuiPaneInfo() + .Name(key) + .CenterPane() + .BestSize(wx.Size(400, 380)) + .MinSize(wx.Size(190, 200)) + .Hide(), + ) + self.dynamicPanels[key].mainFrame = self + self.dynamicPanels[key].treeCtrlMain = self.treeCtrlMain + self.dynamicPanels[key].cP = self.cP + self.dynamicPanels[key].key = key + self.dynamicPanels[key].Enable(False) + + # Do the same for the plotPanel and journalPanel + self.plotPanel.mainFrame = self + self.plotPanel.treeCtrlMain = self.treeCtrlMain + self.plotPanel.cP = self.cP + self.plotPanel.Enable(False) + + self.journalPanel.mainFrame = self + self.journalPanel.treeCtrlMain = self.treeCtrlMain + self.journalPanel.cP = self.cP + + # Position other panels. Note that currently MinimizeButton does not do + # anything. It is to be implemented in future versions of wx.aui + self.auiManager.AddPane( + self.outputPanel, + wx.aui.AuiPaneInfo() + .Name("outputPanel") + .Caption("PDFfit2 Output") + .Bottom() + .TopDockable() + .BottomDockable() + .LeftDockable() + .RightDockable() + .MinimizeButton() + .BestSize(wx.Size(400, 40)) + .MinSize(wx.Size(200, 40)), + ) + self.auiManager.AddPane( + self.treeCtrlMain, + wx.aui.AuiPaneInfo() + .Name("treeCtrlMain") + .Caption("Fit Tree") + .Left() + .TopDockable() + .BottomDockable() + .LeftDockable() + .RightDockable() + .MinimizeButton() + .BestSize(wx.Size(200, 100)) + .MinSize(wx.Size(200, 40)), + ) + self.auiManager.AddPane( + self.plotPanel, + wx.aui.AuiPaneInfo() + .Name("plotPanel") + .Caption("Plot Control") + .Left() + .TopDockable() + .BottomDockable() + .LeftDockable() + .RightDockable() + .MinimizeButton() + .BestSize(wx.Size(200, 250)) + .MinSize(wx.Size(200, 150)), + ) + self.auiManager.AddPane( + self.journalPanel, + wx.aui.AuiPaneInfo() + .Name("journalPanel") + .Caption("Project Journal") + .TopDockable() + .BottomDockable() + .LeftDockable() + .RightDockable() + .MinimizeButton() + .Hide() + .BestSize(wx.Size(450, 450)) + .MinSize(wx.Size(200, 200)) + .FloatingSize(wx.Size(450, 450)) + .Float(), + ) + + # Continue with initialization + self.__defineLocalIds() # Ids for menu items + self.__setupMainMenu() # Make the main menu + self.__setupToolBar() # Make the toolbar + self.treeCtrlMain.InitializeTree() # Initialize the tree + + # Load the configuration + self.loadConfiguration() + + # Set the state of the program + self.needsSave(False) + + return + + def __setupMainMenu(self): + """This sets up the menu in the main frame.""" + self.menulength = 8 + + self.menuBar = wx.MenuBar() + self.SetMenuBar(self.menuBar) + + # File Menu + self.fileMenu = wx.Menu() + self.newItem = wx.MenuItem(self.fileMenu, self.newId, "&New Project\tCtrl+n", "", wx.ITEM_NORMAL) + self.fileMenu.Append(self.newItem) + self.openItem = wx.MenuItem(self.fileMenu, self.openId, "&Open Project\tCtrl+o", "", wx.ITEM_NORMAL) + self.fileMenu.Append(self.openItem) + self.recentMenu = wx.Menu() + msub = self.fileMenu.AppendSubMenu(self.recentMenu, "&Recent Files") + self.recentId = msub.Id + self.fileMenu.AppendSeparator() + self.saveItem = wx.MenuItem(self.fileMenu, self.saveId, "&Save Project\tCtrl+s", "", wx.ITEM_NORMAL) + self.fileMenu.Append(self.saveItem) + self.saveAsItem = wx.MenuItem( + self.fileMenu, + self.saveAsId, + "Save Project &as\tCtrl+Shift+s", + "", + wx.ITEM_NORMAL, + ) + self.fileMenu.Append(self.saveAsItem) + self.fileMenu.AppendSeparator() + self.quitItem = wx.MenuItem(self.fileMenu, self.quitId, "&Quit\tCtrl+q", "", wx.ITEM_NORMAL) + self.fileMenu.Append(self.quitItem) + self.menuBar.Append(self.fileMenu, "&File") + # End File Menu + + # Edit Menu + self.editMenu = wx.Menu() + self.delItem = wx.MenuItem(self.editMenu, self.deleteId, "&Delete Item(s)\tCtrl+X", "", wx.ITEM_NORMAL) + self.editMenu.Append(self.delItem) + self.copyItem = wx.MenuItem(self.editMenu, self.copyId, "&Copy Item\tCtrl+C", "", wx.ITEM_NORMAL) + self.editMenu.Append(self.copyItem) + self.pasteItem = wx.MenuItem(self.editMenu, self.pasteId, "&Paste Item\tCtrl+V", "", wx.ITEM_NORMAL) + self.editMenu.Append(self.pasteItem) + self.pasteLinkItem = wx.MenuItem(self.editMenu, self.pasteLinkId, "Paste &Linked Fit", "", wx.ITEM_NORMAL) + self.editMenu.Append(self.pasteLinkItem) + self.editMenu.AppendSeparator() + self.prefItem = wx.MenuItem(self.editMenu, wx.NewIdRef(), "&Preferences", "", wx.ITEM_NORMAL) + self.editMenu.Append(self.prefItem) + self.menuBar.Append(self.editMenu, "&Edit") + # End Edit Menu + + # View Menu + self.viewMenu = wx.Menu() + self.defaultLayoutItem = wx.MenuItem( + self.editMenu, wx.NewIdRef(), "Default Window Layout", "", wx.ITEM_NORMAL + ) + self.viewMenu.Append(self.defaultLayoutItem) + self.viewMenu.AppendSeparator() + # These items are context sensitive. + self.showFitItem = wx.MenuItem(self.viewMenu, wx.NewIdRef(), "Show Fit Tree", "", wx.ITEM_NORMAL) + self.viewMenu.Append(self.showFitItem) + self.showPlotItem = wx.MenuItem(self.viewMenu, wx.NewIdRef(), "Show Plot Control", "", wx.ITEM_NORMAL) + self.viewMenu.Append(self.showPlotItem) + self.showOutputItem = wx.MenuItem(self.viewMenu, wx.NewIdRef(), "Show Output", "", wx.ITEM_NORMAL) + self.viewMenu.Append(self.showOutputItem) + self.showJournalItem = wx.MenuItem( + self.viewMenu, wx.NewIdRef(), "Show Journal\tCtrl+j", "", wx.ITEM_NORMAL + ) + self.viewMenu.Append(self.showJournalItem) + self.menuBar.Append(self.viewMenu, "&View") + + # Fits Menu + self.fitsMenu = wx.Menu() + self.newFitItem = wx.MenuItem(self.fitsMenu, self.newFitId, "&New Fit\tCtrl+t", "", wx.ITEM_NORMAL) + self.fitsMenu.Append(self.newFitItem) + self.fitsMenu.AppendSeparator() + self.runFitItem = wx.MenuItem(self.fitsMenu, self.runFitId, "&Run Selected Fits", "", wx.ITEM_NORMAL) + self.fitsMenu.Append(self.runFitItem) + self.stopFitItem = wx.MenuItem(self.fitsMenu, self.stopFitId, "&Stop Fitting", "", wx.ITEM_NORMAL) + self.fitsMenu.Append(self.stopFitItem) + self.fitsMenu.AppendSeparator() + self.expResItem = wx.MenuItem(self.fitsMenu, self.exportResId, "Export Resu&lts File", "", wx.ITEM_NORMAL) + self.fitsMenu.Append(self.expResItem) + self.fitsMenu.AppendSeparator() + # Macros sub-menu + self.macrosMenu = wx.Menu() + self.rseriesItem = wx.MenuItem(self.macrosMenu, wx.NewIdRef(), "r-Series", "", wx.ITEM_NORMAL) + self.macrosMenu.Append(self.rseriesItem) + self.tseriesItem = wx.MenuItem(self.macrosMenu, wx.NewIdRef(), "Temperature Series", "", wx.ITEM_NORMAL) + self.macrosMenu.Append(self.tseriesItem) + self.dseriesItem = wx.MenuItem(self.macrosMenu, wx.NewIdRef(), "Doping Series", "", wx.ITEM_NORMAL) + self.macrosMenu.Append(self.dseriesItem) + self.fitsMenu.AppendSubMenu(self.macrosMenu, "Macros") + self.menuBar.Append(self.fitsMenu, "Fi&ts") + # End Fits Menu + + # Phases Menu + self.phasesMenu = wx.Menu() + self.newPhaseItem = wx.MenuItem(self.phasesMenu, self.newPhaseId, "&New Phase\tCtrl+p", "", wx.ITEM_NORMAL) + self.phasesMenu.Append(self.newPhaseItem) + self.phasesMenu.AppendSeparator() + self.printBLItem = wx.MenuItem( + self.phasesMenu, + self.printBLId, + "Calculate bond lengths", + "", + wx.ITEM_NORMAL, + ) + self.phasesMenu.Append(self.printBLItem) + self.printBAItem = wx.MenuItem( + self.phasesMenu, self.printBAId, "Calculate bond angles", "", wx.ITEM_NORMAL + ) + self.phasesMenu.Append(self.printBAItem) + self.phasesMenu.AppendSeparator() + self.expNewPhaseItem = wx.MenuItem( + self.phasesMenu, + self.exportNewStruId, + "Export &Selected Phase", + "", + wx.ITEM_NORMAL, + ) + self.phasesMenu.Append(self.expNewPhaseItem) + self.expStruItem = wx.MenuItem( + self.fitsMenu, + self.exportFitStruId, + "&Export Fit Structure", + "", + wx.ITEM_NORMAL, + ) + self.phasesMenu.Append(self.expStruItem) + self.phasesMenu.AppendSeparator() + self.plotIStructItem = wx.MenuItem( + self.phasesMenu, + self.plotIStructId, + "&Plot Initial Structure", + "", + wx.ITEM_NORMAL, + ) + self.phasesMenu.Append(self.plotIStructItem) + self.plotFStructItem = wx.MenuItem( + self.phasesMenu, + self.plotFStructId, + "&Plot Final Structure", + "", + wx.ITEM_NORMAL, + ) + self.phasesMenu.Append(self.plotFStructItem) + + self.menuBar.Append(self.phasesMenu, "&Phases") + # End Phases Menu + + # Data Menu + self.dataMenu = wx.Menu() + self.newDataItem = wx.MenuItem(self.dataMenu, self.newDataId, "&New Data Set\tCtrl+d", "", wx.ITEM_NORMAL) + self.dataMenu.Append(self.newDataItem) + self.dataMenu.AppendSeparator() + self.expFitPDFItem = wx.MenuItem(self.fitsMenu, self.exportFitPDFId, "&Export Fit PDF", "", wx.ITEM_NORMAL) + self.dataMenu.Append(self.expFitPDFItem) + self.menuBar.Append(self.dataMenu, "&Data") + # End Data Menu + + # Calculations Menu + self.calcMenu = wx.Menu() + self.newCalcItem = wx.MenuItem( + self.calcMenu, + self.newCalcId, + "&New Calculation\tCtrl+l", + "", + wx.ITEM_NORMAL, + ) + self.calcMenu.Append(self.newCalcItem) + self.calcMenu.AppendSeparator() + self.runCalcItem = wx.MenuItem( + self.calcMenu, + self.runCalcId, + "&Run Selected Calculation", + "", + wx.ITEM_NORMAL, + ) + self.calcMenu.Append(self.runCalcItem) + self.calcMenu.AppendSeparator() + self.expCalcPDFItem = wx.MenuItem( + self.calcMenu, + self.exportCalcPDFId, + "&Export Selected Calculation", + "", + wx.ITEM_NORMAL, + ) + self.calcMenu.Append(self.expCalcPDFItem) + self.menuBar.Append(self.calcMenu, "Ca&lculations") + # End Calculations Menu + + # Help Menu + self.helpMenu = wx.Menu() + self.docItem = wx.MenuItem(self.helpMenu, wx.NewIdRef(), "&Documentation\tF1", "", wx.ITEM_NORMAL) + self.helpMenu.Append(self.docItem) + self.requestItem = wx.MenuItem( + self.helpMenu, + wx.NewIdRef(), + "Request a Feature / Report a Bug", + "", + wx.ITEM_NORMAL, + ) + self.helpMenu.Append(self.requestItem) + self.communityItem = wx.MenuItem(self.helpMenu, wx.NewIdRef(), "PDFgui Community", "", wx.ITEM_NORMAL) + self.helpMenu.Append(self.communityItem) + self.aboutItem = wx.MenuItem(self.helpMenu, wx.NewIdRef(), "&About", "", wx.ITEM_NORMAL) + self.helpMenu.Append(self.aboutItem) + self.menuBar.Append(self.helpMenu, "&Help") + # End Help Menu + + # For managing MRUs + self.fileHistory = wx.FileHistory(pdfguiglobals.MAXMRU) + self.fileHistory.UseMenu(self.recentMenu) + + return + + def __setupToolBar(self): + """This sets up the tool bar in the parent window.""" + self.toolBar = self.CreateToolBar() + size = (16, 16) + bitmap = wx.ArtProvider.GetBitmap(wx.ART_NEW, wx.ART_TOOLBAR, size) + self.toolBar.AddTool( + self.newId, + "New Project", + bitmap, + wx.NullBitmap, + wx.ITEM_NORMAL, + "Start a new project", + ) + bitmap = wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN, wx.ART_TOOLBAR, size) + self.toolBar.AddTool( + self.openId, + "Open Project", + bitmap, + wx.NullBitmap, + wx.ITEM_NORMAL, + "Open an existing project", + ) + bitmap = wx.ArtProvider.GetBitmap(wx.ART_FILE_SAVE, wx.ART_TOOLBAR, size) + self.toolBar.AddTool( + self.saveId, + "Save Project", + bitmap, + wx.NullBitmap, + wx.ITEM_NORMAL, + "Save this project", + ) + self.toolBar.AddSeparator() + # This fixes the shadowing problem on Windows. + # The bitmap has a white transparency color (mask) + maskcolor = wx.Colour(red=255, green=255, blue=255) + bitmap = wx.Bitmap(iconpath("run.png")) + bitmap.SetSize(size) + mask = wx.Mask(bitmap, maskcolor) + bitmap.SetMask(mask) + self.toolBar.AddTool( + self.runFitId, + "Start", + bitmap, + wx.NullBitmap, + wx.ITEM_NORMAL, + "Start a fit or calculation", + ) + bitmap = wx.Bitmap(iconpath("stop.png")) + bitmap.SetSize(size) + mask = wx.Mask(bitmap, maskcolor) + bitmap.SetMask(mask) + self.toolBar.AddTool( + self.stopFitId, + "Stop", + bitmap, + wx.NullBitmap, + wx.ITEM_NORMAL, + "Stop running fits or calculations", + ) + self.toolBar.AddSeparator() + bitmap = wx.Bitmap(iconpath("datasetitem.png")) + bitmap.SetSize(size) + self.toolBar.AddTool( + self.quickPlotId, + "Quick plot", + bitmap, + wx.NullBitmap, + wx.ITEM_NORMAL, + "Plot PDF or structure", + ) + self.toolBar.Realize() + return + + def __customBindings(self): + """Custom user bindings go here. + + These bindings are not present in wxglade. + """ + # Allow a general right-click to work on the tree + self.treeCtrlMain.Bind(wx.EVT_RIGHT_DOWN, self.onRightClick) + # Double-click select all type on tree + # FIXME - this doesn't work, I suspect the problem is with the tree + # selection code. + # self.treeCtrlMain.Bind(wx.EVT_LEFT_DCLICK, self.onDoubleClick2) + # self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.onDoubleClick, self.treeCtrlMain) + # Middle-click quickplot + self.Bind(wx.EVT_TREE_ITEM_MIDDLE_CLICK, self.onMiddleClick, self.treeCtrlMain) + # Catch key events for the tree + self.treeCtrlMain.Bind(wx.EVT_KEY_DOWN, self.onKey) + # Catch the close event + self.Bind(wx.EVT_CLOSE, self.onQuit) + # Use the custom event to pop up error messages + self.Bind(EVT_PDFCUSTOM, self.onCustom) + # Do bindings for menu items + self.__menuBindings() + self.__fittingRightMenuBindings() + return + + def __menuBindings(self): + """Setup bindings for the main menu and toolbar. + + Since all toolbar functions use the same Ids as main menu items, + the toolbar events do not need their own bindings. + """ + # File Menu + self.Bind(wx.EVT_MENU, self.onNew, id=self.newId) + self.Bind(wx.EVT_MENU, self.onOpen, id=self.openId) + self.Bind(wx.EVT_MENU, self.onSave, id=self.saveId) + self.Bind(wx.EVT_MENU, self.onSaveAs, id=self.saveAsId) + self.Bind(wx.EVT_MENU, self.onQuit, id=self.quitId) + # For recent items + self.Bind(wx.EVT_MENU_RANGE, self.onMRUFile, id=wx.ID_FILE1, id2=wx.ID_FILE5) + + # Edit Menu + self.Bind(wx.EVT_MENU, self.onDelete, id=self.deleteId) + self.Bind(wx.EVT_MENU, self.onCopy, id=self.copyId) + self.Bind(wx.EVT_MENU, self.onPaste, id=self.pasteId) + self.Bind(wx.EVT_MENU, self.onPasteLink, id=self.pasteLinkId) + self.Bind(wx.EVT_MENU, self.onPreferences, self.prefItem) + + # View menu + self.Bind(wx.EVT_MENU, self.onDefaultLayout, self.defaultLayoutItem) + self.Bind(wx.EVT_MENU, self.onShowFit, self.showFitItem) + self.Bind(wx.EVT_MENU, self.onShowPlot, self.showPlotItem) + self.Bind(wx.EVT_MENU, self.onShowOutput, self.showOutputItem) + self.Bind(wx.EVT_MENU, self.onShowJournal, self.showJournalItem) + + # Fits Menu + self.Bind(wx.EVT_MENU, self.onNewFit, id=self.newFitId) + self.Bind(wx.EVT_MENU, self.onRun, id=self.runFitId) + self.Bind(wx.EVT_MENU, self.onStop, id=self.stopFitId) + self.Bind(wx.EVT_MENU, self.onExportRes, id=self.exportResId) + self.Bind(wx.EVT_MENU, self.onRSeries, self.rseriesItem) + self.Bind(wx.EVT_MENU, self.onTSeries, self.tseriesItem) + self.Bind(wx.EVT_MENU, self.onDSeries, self.dseriesItem) + # Macros are inserted individually + + # Phases Menu + self.Bind(wx.EVT_MENU, self.onInsPhase, id=self.newPhaseId) + self.Bind(wx.EVT_MENU, self.onPrintBL, id=self.printBLId) + self.Bind(wx.EVT_MENU, self.onPrintBA, id=self.printBAId) + self.Bind(wx.EVT_MENU, self.onExportNewStruct, id=self.exportNewStruId) + self.Bind(wx.EVT_MENU, self.onExportStruct, id=self.exportFitStruId) + self.Bind(wx.EVT_MENU, self.onPlotIStruct, id=self.plotIStructId) + self.Bind(wx.EVT_MENU, self.onPlotFStruct, id=self.plotFStructId) + + # Data Menu + self.Bind(wx.EVT_MENU, self.onInsData, id=self.newDataId) + self.Bind(wx.EVT_MENU, self.onExportPDF, id=self.exportFitPDFId) + + # Calculations Menu + self.Bind(wx.EVT_MENU, self.onInsCalc, id=self.newCalcId) + self.Bind(wx.EVT_MENU, self.onRun, id=self.runCalcId) + self.Bind(wx.EVT_MENU, self.onSaveCalc, id=self.exportCalcPDFId) + + # Help Menu + self.Bind(wx.EVT_MENU, self.onDocumentation, self.docItem) + self.Bind(wx.EVT_MENU, self.onAbout, self.aboutItem) + self.Bind(wx.EVT_MENU, self.onRequest, self.requestItem) + self.Bind(wx.EVT_MENU, self.onCommunity, self.communityItem) + + # The generic menu-check. + self.Bind(wx.EVT_MENU_OPEN, self.onMainMenu) + + # Toolbar events that have no menu item + self.Bind(wx.EVT_MENU, self.onQuickPlot, id=self.quickPlotId) + return + + def __fittingRightMenuBindings(self): + """Bindings for the fitting-mode right-click menu.""" + self.Bind(wx.EVT_MENU, self.onNewFit, id=self.newFitId) + self.Bind(wx.EVT_MENU, self.onCopy, id=self.copyId) + self.Bind(wx.EVT_MENU, self.onPaste, id=self.pasteId) + self.Bind(wx.EVT_MENU, self.onPasteLink, id=self.pasteLinkId) + self.Bind(wx.EVT_MENU, self.onInsPhase, id=self.newPhaseId) + self.Bind(wx.EVT_MENU, self.onInsData, id=self.newDataId) + self.Bind(wx.EVT_MENU, self.onInsCalc, id=self.newCalcId) + self.Bind(wx.EVT_MENU, self.onDelete, id=self.deleteId) + return + + # UTILITY FUNCTIONS ###################################################### + +
+[docs] + def switchRightPanel(self, paneltype): + """Switch the panel which is visible in the right hand side. + + This sets any panel-specific data and calls the refresh() method of the + new rightPanel. All right panels must be derived from wxPanel and + PDFPanel (in pdfpanel module). + + Inputs: + paneltype -- The code used in self.dynamicPanels that indicates the + panel to be displayed. If paneltype is None, the blank + panel is displayed. + """ + self.rightPanel.Enable(False) + self.plotPanel.Enable(False) + for key in self.dynamicPanels: + self.auiManager.GetPane(key).Hide() + + # Why doesn't this work? + # key = self.rightPanel.key + # self.auiManager.GetPane(key).Hide() + + if paneltype is None: + paneltype = "blank" + + self.rightPanel = self.dynamicPanels[paneltype] + self.rightPanel.Enable(True) + self.setPanelSpecificData(paneltype) + self.rightPanel.refresh() + paneinfo = self.auiManager.GetPane(paneltype) + paneinfo.Show() + self.auiManager.Update() + + selections = self.treeCtrlMain.GetSelections() + if len(selections) == 1: + self.plotPanel.Enable(True) + + return
+ + +
+[docs] + def setPanelSpecificData(self, paneltype): + """This method sets the panel specific data for the right panel. + + This method gets panel-specific data and sends it to the rightPanel. The + different types of data assignment are listed below. + + "fit" type: + * Give the fit object to the panel + + "phase" type: + * initialize constraints dictionary and configuration and results + * Structure objects. + + "dataset" type: + * initialize configuration, constraints, and results objects + + "calculation" type: + * Give the calculation object to the panel + + "rseries" type: + * Give the fit object to the panel + + "tseries" type: + * Give the fit object to the panel + + "dseries" type: + * Give the fit object to the panel + """ + selections = self.treeCtrlMain.GetSelections() + if len(selections) == 1: + node = selections[0] + dataobject = self.treeCtrlMain.GetControlData(node) + + if paneltype == "phase": + self.rightPanel.configuration = dataobject.initial + self.rightPanel.constraints = dataobject.constraints + self.rightPanel.results = dataobject.refined + elif paneltype == "dataset": + self.rightPanel.configuration = dataobject + self.rightPanel.constraints = dataobject.constraints + self.rightPanel.results = dataobject.refined + elif paneltype == "fit": + dataobject.updateParameters() + self.rightPanel.fit = dataobject + elif paneltype == "calculation": + self.rightPanel.calculation = dataobject + elif paneltype == "rseries": + self.rightPanel.fit = dataobject + elif paneltype == "tseries": + self.rightPanel.fit = dataobject + elif paneltype == "dseries": + self.rightPanel.fit = dataobject + + return
+ + +
+[docs] + def setMode(self, mode): + """Set the mode of the program. + + This method takes care of any widget properties that must change when + the mode is changed. If the mode is changing due to the change in the + right panel, always call setMode before switchRightPanel. + + "fitting" mode: + * treeCtrlMain is enabled + * plotPanel panel is enabled + * toolBar is enabled + * menuBar is enabled + + "addingdata" mode: + "addingphase" mode: + "config" mode: + * treeCtrlMain is disabled + * plotPanel panel is disabled + * toolBar is disabled + * menuBar is disabled + + "rseries" mode: + "tseries" mode: + "dseries" mode: + * treeCtrlMain is enabled + * plotPanel panel is disabled + * toolBar is disabled + * menuBar is disabled + """ + self.mode = mode + if mode == "fitting": + self.treeCtrlMain.Enable(True) + self.plotPanel.Enable(True) + self.toolBar.Enable(True) + for i in range(self.menulength): + self.menuBar.EnableTop(i, True) + elif mode in ["addingdata", "addingphase", "config"]: + self.treeCtrlMain.Enable(False) + self.plotPanel.Enable(False) + self.toolBar.Enable(False) + for i in range(self.menulength): + self.menuBar.EnableTop(i, False) + elif mode in ["rseries", "tseries", "dseries"]: + self.treeCtrlMain.Enable(True) + self.plotPanel.Enable(False) + self.toolBar.Enable(False) + for i in range(self.menulength): + self.menuBar.EnableTop(i, False) + return
+ + +
+[docs] + def loadConfiguration(self): + """Load the configuration from file. + + The MRU list is handled by the local member fileHistory, which + is a wxFileHistory object. + """ + + # Get MRU information + localpath = os.path.expanduser(pdfguiglobals.configfilename) + if os.path.exists(localpath): + self.cP.read(localpath) + for i in range(pdfguiglobals.MAXMRU, 0, -1): + if self.cP.has_option("MRU", str(i)): + filename = self.cP.get("MRU", str(i)) + if filename: + self.fileHistory.AddFileToHistory(filename) + + # Import perspective from last session + if self.cP.has_section("PERSPECTIVE"): + if self.cP.has_option("PERSPECTIVE", "last"): + perspective = self.cP.get("PERSPECTIVE", "last") + self.auiManager.LoadPerspective(perspective) + else: + from diffpy.pdfgui.gui.windowperspective import default + + self.auiManager.LoadPerspective(default) + + # Load the window dimensions + w = 800 + h = 600 + if self.cP.has_option("SIZE", "width"): + w = self.cP.get("SIZE", "width") + w = int(w) + if self.cP.has_option("SIZE", "height"): + h = self.cP.get("SIZE", "height") + h = int(h) + self.SetSize((w, h)) + + # Load structure viewer information and put this in the configure panel + viewerconfig = {} + if self.cP.has_section("STRUCTUREVIEWER"): + viewerconfig = dict(self.cP.items("STRUCTUREVIEWER")) + viewer = structureviewer.getStructureViewer() + viewer.setConfig(viewerconfig) + + return
+ + +
+[docs] + def updateConfiguration(self): + """Update the configuration information. + + This updates the 'MRU' section of the configuration. + """ + # Most recently used list + if not self.cP.has_section("MRU"): + self.cP.add_section("MRU") + + for i in range(self.fileHistory.GetCount()): + item = self.fileHistory.GetHistoryFile(i) + self.cP.set("MRU", str(i + 1), item) + + # Window size + if not self.cP.has_section("SIZE"): + self.cP.add_section("SIZE") + + w, h = self.GetSize() + self.cP.set("SIZE", "width", str(w)) + self.cP.set("SIZE", "height", str(h)) + + # Frame layout + if not self.cP.has_section("PERSPECTIVE"): + self.cP.add_section("PERSPECTIVE") + + perspective = self.auiManager.SavePerspective() + self.cP.set("PERSPECTIVE", "last", perspective) + + # Set the structure viewer information + if not self.cP.has_section("STRUCTUREVIEWER"): + self.cP.add_section("STRUCTUREVIEWER") + viewer = structureviewer.getStructureViewer() + viewerconfig = viewer.getConfig() + for key, value in viewerconfig.items(): + self.cP.set("STRUCTUREVIEWER", key, value) + + return
+ + +
+[docs] + def writeConfiguration(self): + """Write the program configuration to file.""" + filename = os.path.expanduser(pdfguiglobals.configfilename) + oflags = os.O_CREAT | os.O_WRONLY + try: + with os.fdopen(os.open(filename, oflags, 0o600), "w") as outfile: + self.cP.write(outfile) + except IOError: + emsg = "Cannot write configuration file %r" % filename + raise ControlFileError(emsg) + return
+ + +
+[docs] + def checkForSave(self): + """Pop up a dialog if the project needs to be saved. + + returns: + wx.ID_YES if the user chose to save the project. + wx.ID_NO if the user chose not to save the project. + wx.ID_CANCEL if they changed their mind about their action. + """ + code = wx.ID_NO + # disable when requested in dbopts + if pdfguiglobals.dbopts.noconfirm: + return code + if pdfguiglobals.isAltered: + d = wx.MessageDialog( + self, + "Would you like to save this session?", + "Save?", + wx.YES_NO | wx.CANCEL, + ) + code = d.ShowModal() + if code == wx.ID_YES: + code = self.onSave(None) + d.Destroy() + return code
+ + +
+[docs] + def updateTitle(self): + """Update the title according to the name of the current file.""" + shorttitle = os.path.basename(self.fullpath) + udirnamed = "~" + os.path.sep + udir = os.path.expanduser(udirnamed) + if shorttitle: + namedpath = self.fullpath + if namedpath.startswith(udir): + namedpath = namedpath.replace(udir, udirnamed) + fulltitle = "%s (%s) - %s" % (shorttitle, namedpath, self.name) + else: + fulltitle = self.name + self.SetTitle(fulltitle) + return
+ + + # MAIN PANEL EVENT CODE ####################################################### + +
+[docs] + def onMainMenu(self, event): + """Prepare the main menu whenever it is activated.""" + self.disableMainMenuItems() + return
+ + +
+[docs] + def makeTreeSelection(self, node): + """Manually select a node of the tree and update according to + selection. + + This makes sure that the node is visible after selection. + + If node is None, this does nothing. + """ + if node is None: + return + + self.treeCtrlMain.SelectItem(node) + + # Make sure that the node is visible. + self.treeCtrlMain.SetFocus() + self.treeCtrlMain.EnsureVisible(node) + self.treeCtrlMain.ScrollTo(node) + + self.treeSelectionUpdate(node) + + # The right-panel probably stole focus, but we want it back. + self.treeCtrlMain.SetFocus() + return
+ + +
+[docs] + def treeSelectionUpdate(self, node): + """Update the widgets based on a tree selection. + + "fitting" mode: + * Right panel changes depending upon the type of item selected from the + tree. + + "rseries", "tseries", "dseries" mode: + * The behavior is defined in the associated panel + """ + selections = self.treeCtrlMain.GetSelections() + + # "fitting" mode + if self.mode == "fitting": + # This doesn't work on Windows. + self.plotPanel.Enable(True) + if len(selections) == 0: + self.switchRightPanel("blank") + self.plotPanel.Enable(False) + # return + elif len(selections) == 1: + self.rightPanel.Enable() + selectiontype = self.treeCtrlMain.GetNodeType(selections[0]) + self.switchRightPanel(selectiontype) + else: + self.rightPanel.Enable(False) + self.plotPanel.Enable(True) + + # Don't let the user edit the right panel of a running fit. + fp = self.treeCtrlMain.GetFitRoot(node) + if fp: + name = self.treeCtrlMain.GetItemText(fp) + if name in self.runningDict: + self.rightPanel.Enable(False) + + elif self.mode in ["rseries", "tseries", "dseries"]: + self.rightPanel.treeSelectionUpdate(node) + + # Update the plotPanel + self.plotPanel.refresh() + + # update the toolbar and menu + self.updateToolbar() + if self.runningDict: + self.disableMainMenuItems() + return
+ + +
+[docs] + def onTreeSelChanged(self, event): + """Set the click behavior for each mode.""" + node = event.GetItem() + self.treeSelectionUpdate(node) + return
+ + +
+[docs] + def onTreeSelChanging(self, event): # wxGlade: MainPanel.<event_handler> + """Set the click behavior for each mode. + + Note that this doesn't work on Windows. Be sure to build in redundancy + so that the program behaves as if this does not even get called. If the + Windows bug does not get fixed, this method will probably be + eliminated. + + "addingdata" mode: + * can select nothing + + "addingphase" mode: + * can select nothing + + "config" mode: + * can select nothing + + "rseries" mode: + * can only select fit items + + "tseries" mode: + * can only select fit items + + "dseries" mode: + * can only select fit items + """ + # THIS DOESN'T WORK ON WINDOWS! + node = event.GetItem() + if not node: + return + if self.mode in ["addingdata", "addingphase", "config"]: + event.Veto() + elif self.mode in ["rseries", "tseries", "dseries"]: + nodetype = self.treeCtrlMain.GetNodeType(node) + if nodetype != "fit": + event.Veto() + + return
+ + +
+[docs] + def onBeginLabelEdit(self, event): # wxGlade: MainPanel.<event_handler> + """Veto editing of some items and in some modes. + + The following editing attempts are Veto()'d + * Editing any item in "addingdata", "addingphase", or "config" mode. + """ + nodetype = self.treeCtrlMain.GetNodeType(event.GetItem()) + # silence the pyflakes syntax checker + assert nodetype or True + if self.mode != "fitting": + event.Veto() + return
+ + +
+[docs] + def onEndLabelEdit(self, event): # wxGlade: MainPanel.<event_handler> + """Allow only certain types of renaming. + + The following rename attempts are Veto()'d + * Giving a node the same name as a sibling. Cousins can share names. + * Giving a node the name ''. Everything needs a name. + """ + label = event.GetLabel() + + # No '' + if label.strip() == "": + event.Veto() + return + + # No sibling's sharing the same name. (Sorry, George Foreman.) + node = event.GetItem() + siblings = [self.treeCtrlMain.GetItemText(id) for id in self.treeCtrlMain.GetSiblings(node)] + if label in siblings: + event.Veto() + return + + # Notify the control of the rename + cdata = self.treeCtrlMain.GetControlData(node) + self.control.rename(cdata, label) + self.needsSave() + return
+ + +
+[docs] + def onRightClick(self, event): # wxGlade: MainPanel.<event_handler> + """Bring up the right-click menu. + + This menu can give a different menu depending upon which mode the + program is in. It can even give a different menu depending upon what + part of the tree is selected. + + "fitting" mode + The menu appears for right-clicks both on and off of tree items. + The menu has the following items: + "New Fit" -- Append a new fit from anywhere on the tree. + "Copy" -- Copy a fit, phase, dataset, or calc branch + "Paste" -- Paste a copied branch into the tree. Branches + of a given type can only be pasted in certain + places. + "Delete" -- Delete a branch from the tree. + "Insert Phase" -- Insert a phase in the phase section of a fit or + calculation branch. + "Insert Data Set" -- Insert a dataset in the dataset section of a fit + branch. + "Insert Calculation"-- Insert a calculation in the calculation section + of a fit. + + The menu appears for right-clicks both on and off of tree items. + The menu has the following items: + "Select All" -- The tree automatically selects all items of the + type the user clicked on. + """ + # This menu is disabled the if item is part of a running fit. + selections = self.treeCtrlMain.GetSelections() + if selections: + node = self.treeCtrlMain.GetFitRoot(selections[0]) + nodetype = self.treeCtrlMain.GetNodeType(node) + # silence the pyflakes syntax checker + assert nodetype or True + if node in self.runningDict.values(): + return + + if self.mode == "fitting": + + # The menu Ids are defined in __defineLocalIds. + menu = wx.Menu() + menu.Append(self.newFitId, "New Fit") + menu.AppendSeparator() + menu.Append(self.copyId, "Copy") + menu.Append(self.pasteId, "Paste") + menu.Append(self.pasteLinkId, "Paste Linked Fit") + menu.Append(self.deleteId, "Delete") + menu.AppendSeparator() + menu.Append(self.newPhaseId, "Insert Phase") + menu.Append(self.newDataId, "Insert Data Set") + menu.Append(self.newCalcId, "Insert Calculation") + + # Get the item we've right clicked on + itemtype = None + x = event.GetX() + y = event.GetY() + node, flags = self.treeCtrlMain.HitTest((x, y)) + + if flags in [ + wx.TREE_HITTEST_ABOVE, + wx.TREE_HITTEST_BELOW, + wx.TREE_HITTEST_NOWHERE, + ]: + # The hit is not on an item. + self.treeCtrlMain.UnselectAll() + self.switchRightPanel("blank") + selections = [] + # Select the item with a right click, but don't add it to an + # existing selection. + elif node not in selections: + self.treeCtrlMain.UnselectAll() + self.treeCtrlMain.SelectItem(node) + selections = [node] + itemtype = self.treeCtrlMain.GetNodeType(node) + # silence the pyflakes syntax checker + assert itemtype or True + # Enable/Disable certain entries based upon where we clicked. + self.disableSharedMenuItems(menu) + + else: + return + + # Bring up the popup menu. Must have the coordinates of the right-click + # event that summoned the menu. + + # This is to position the menu correctly on a floating frame. + # wx.treeCtrlMain.GetPosition() will return (0,0) if the frame is + # not docked. This is a bit of a hack, since pane.floating_pos is not + # designed to be a public attribute. + pane = self.auiManager.GetPane("treeCtrlMain") + (x0, y0) = self.treeCtrlMain.GetPosition() + if pane.IsFloating(): + (x0, y0) = self.ScreenToClient(pane.floating_pos) + self.PopupMenu(menu, (x0 + x, y0 + y)) + menu.Destroy() + return
+ + +
+[docs] + def onMiddleClick(self, event): + """Quickplot on item middle click.""" + node = event.GetItem() + self.treeCtrlMain.UnselectAll() + self.treeCtrlMain.SelectItem(node) + self.onQuickPlot(None) + return
+ + +
+[docs] + def onDoubleClick2(self, event): + """Select-all type on item double click.""" + x = event.GetX() + y = event.GetY() + node, flags = self.treeCtrlMain.HitTest((x, y)) + + if flags not in [ + wx.TREE_HITTEST_ABOVE, + wx.TREE_HITTEST_BELOW, + wx.TREE_HITTEST_NOWHERE, + ]: + if self.mode == "fitting": + wx.CallAfter(self.treeCtrlMain.SelectAllType, node) + wx.CallAfter(self.treeSelectionUpdate, node) + return
+ + +
+[docs] + def onDoubleClick(self, event): + """Select-all type on item double click.""" + node = event.GetItem() + if self.mode == "fitting": + wx.CallAfter(self.treeCtrlMain.SelectAllType, node) + wx.CallAfter(self.treeSelectionUpdate, node) + return
+ + +
+[docs] + def onKey(self, event): + """Catch key events in the panel.""" + # See if the tree is in focus. If not, pass the event on + key = event.GetKeyCode() + + selections = self.treeCtrlMain.GetSelections() + node = None + if selections: + node = selections[0] + + # Shift+Ctrl+A + # "fitting" mode -- Select all nodes of a given type + if event.ShiftDown() and event.ControlDown() and key == 65: + if self.mode == "fitting": + self.treeCtrlMain.SelectAllType(node) + self.treeSelectionUpdate(node) + + # Ctrl+A + # "fitting" mode -- Select all nodes + elif event.ControlDown() and key == 65: + if self.mode == "fitting": + self.treeCtrlMain.SelectAll() + self.treeSelectionUpdate(node) + + # XXX - removed - Without undo functionality, this is too dangerous. + # Delete + # "fitting" mode -- Delete selected noded + # elif key == 127: + # if self.mode == "fitting": + # self.onDelete(None) + + # Tab + # Move to the right panel + elif key == 9: + self.rightPanel.SetFocus() + + else: + event.Skip() + + return
+ + + # MENU RELATED FUNCTIONS ################################################## + +
+[docs] + def updateToolbar(self): + """Update the toolbar based upon the status of the program.""" + self.toolBar.EnableTool(self.saveId, (pdfguiglobals.isAltered and self.runningDict == {})) + + itemtype = None + selections = self.treeCtrlMain.GetSelections() + if selections: + itemtype = self.treeCtrlMain.GetNodeType(selections[0]) + + # This is redundant, but easy to maintain + if self.mode == "fitting": + + # Quickplot + if len(selections) == 1 and itemtype and itemtype != "fit": + self.toolBar.EnableTool(self.quickPlotId, True) + else: + self.toolBar.EnableTool(self.quickPlotId, False) + + # Fit run/stop + if not self.runningDict: + # No fit is running + self.toolBar.EnableTool(self.stopFitId, False) + # We can run a fit if there are any selections + if selections: + self.toolBar.EnableTool(self.runFitId, True) + else: + self.toolBar.EnableTool(self.runFitId, False) + + else: + self.toolBar.EnableTool(self.stopFitId, True) + self.toolBar.EnableTool(self.runFitId, False) + + else: + # Quickplot + self.toolBar.EnableTool(self.quickPlotId, False) + + # Fit run/stop + self.toolBar.EnableTool(self.stopFitId, False) + self.toolBar.EnableTool(self.runFitId, False) + + return
+ + +
+[docs] + def needsSave(self, altered=True): + """Tell the gui that the program needs to be saved. + + This changes the state of the save menu and tool bar items. + + altered -- Whether or not the program needs saving (default True). + """ + if not self.quitting: + pdfguiglobals.isAltered = altered + self.updateToolbar() + return
+ + +
+[docs] + def disableSharedMenuItems(self, menu): + """Disable some menu items based upon what is selected in the tree. + + menu -- The menu which to apply the changes. + + Note that this method is meant to disable only the shared menu items, + that is, those that use the same menu item Ids. These are defined in the + top part of __defineLocalIds(). Putting this logic into a single method + makes it easier to make changes with the menus. If a specific menu needs + additional logic, put that in a separate method. + """ + # Start by refreshing the shared items. We don't need things to become + # perpetually disabled. All things are enabled by default. It is up to + # the logic below to disable them. + menu.Enable(self.newFitId, True) + menu.Enable(self.newPhaseId, True) + menu.Enable(self.newDataId, True) + menu.Enable(self.newCalcId, True) + menu.Enable(self.deleteId, True) + menu.Enable(self.copyId, True) + menu.Enable(self.pasteId, True) + menu.Enable(self.pasteLinkId, True) + + # Get the selections off the tree + selections = self.treeCtrlMain.GetSelections() + node = None + if selections: + node = selections[0] + + noPhases = False + if node: + phases = self.treeCtrlMain.GetPhases(node) + # No insert calculation if there are no phases + if len(phases) == 0: + noPhases = True + + # No insert calculation if there are no phases + if noPhases: + menu.Enable(self.newCalcId, False) + + # Change the paste text and enable or disable the paste function + # based upon where we are in the tree or whether or not we have + # something in the clipboard + pastename = "" + clipbranchtype = None + cdata = self.treeCtrlMain.GetClipboard() + + # No paste if nothing in the clipboard + if cdata is None: + menu.Enable(self.pasteId, False) + menu.Enable(self.pasteLinkId, False) + else: + clipbranchtype = cdata.type + if clipbranchtype == "fit": + pastename = "Fit" + # Check to see if the linking fit is still in the tree. If it is + # not, we disable pasteLink + fitname = cdata.name + fits = self.treeCtrlMain.GetChildren(self.treeCtrlMain.root) + fitnames = set(map(self.treeCtrlMain.GetItemText, fits)) + if fitname not in fitnames: + menu.Enable(self.pasteLinkId, False) + # pasteLink only if there's a fit in the clipboard + elif clipbranchtype == "phase": + pastename = "Phase" + menu.Enable(self.pasteLinkId, False) + elif clipbranchtype == "dataset": + pastename = "Data Set" + menu.Enable(self.pasteLinkId, False) + elif clipbranchtype == "calculation": + pastename = "Calculation" + menu.Enable(self.pasteLinkId, False) + pastetext = "&Paste %s\tCtrl+V" % pastename + menu.SetLabel(self.pasteId, pastetext) + + # Disable certain entries based upon where we clicked. + # No copy, paste, or insert on multiple items. + if len(selections) > 1: + menu.Enable(self.copyId, False) + menu.Enable(self.pasteId, False) + menu.Enable(self.pasteLinkId, False) + menu.Enable(self.newDataId, False) + menu.Enable(self.newPhaseId, False) + menu.Enable(self.newCalcId, False) + # Disallow paste of fit if no items selected + elif not selections: + menu.Enable(self.copyId, False) + menu.Enable(self.deleteId, False) + menu.Enable(self.newDataId, False) + menu.Enable(self.newPhaseId, False) + menu.Enable(self.newCalcId, False) + if clipbranchtype != "fit": + menu.Enable(self.pasteId, False) + menu.Enable(self.pasteLinkId, False) + + return
+ + +
+[docs] + def disableMainMenuItems(self): + """Disable main menu items.""" + + menu = self.menuBar + # First disable the shared items + + self.disableSharedMenuItems(menu) + + # Enable everything that can be disabled + # Menus + menu.EnableTop(1, True) + menu.EnableTop(2, True) + menu.EnableTop(3, True) + menu.EnableTop(4, True) + menu.EnableTop(5, True) + menu.EnableTop(6, True) + menu.EnableTop(7, True) + # Menu Items + menu.Enable(self.runFitId, True) + menu.Enable(self.stopFitId, True) + menu.Enable(self.exportFitPDFId, True) + menu.Enable(self.exportFitStruId, True) + menu.Enable(self.exportResId, True) + menu.Enable(self.runCalcId, True) + menu.Enable(self.exportCalcPDFId, True) + menu.Enable(self.printBLId, True) + menu.Enable(self.printBAId, True) + menu.Enable(self.exportNewStruId, True) + menu.Enable(self.plotIStructId, True) + menu.Enable(self.plotFStructId, True) + menu.Enable(self.aboutItem.GetId(), True) + + # Reset the save menus so that they can be disabled if a fit is running. + menu.Enable(self.saveId, pdfguiglobals.isAltered) + menu.Enable(self.saveAsId, True) + menu.Enable(self.openId, True) + menu.Enable(self.recentId, True) + + # Now disable the non-shared menu items + selections = self.treeCtrlMain.GetSelections() + numsel = len(selections) + node = None + if selections: + node = selections[0] + itemtype = self.treeCtrlMain.GetNodeType(node) + else: + itemtype = None + + # MODE + if self.mode != "fitting": + menu.Enable(self.deleteId, False) + menu.Enable(self.copyId, False) + menu.Enable(self.pasteId, False) + menu.Enable(self.runFitId, False) + menu.Enable(self.runCalcId, False) + menu.Enable(self.newFitId, False) + menu.Enable(self.newCalcId, False) + menu.Enable(self.newPhaseId, False) + menu.Enable(self.newDataId, False) + + # FIT + if itemtype != "fit": + menu.Enable(self.runFitId, False) + menu.Enable(self.exportResId, False) + elif numsel > 1: + menu.Enable(self.exportResId, False) + else: + cdata = self.treeCtrlMain.GetControlData(node) + if not cdata.res: + menu.Enable(self.exportResId, False) + + # CALCULATION + if itemtype != "calculation": + menu.Enable(self.runCalcId, False) + menu.Enable(self.exportCalcPDFId, False) + elif numsel > 1: + menu.Enable(self.exportCalcPDFId, False) + else: + cdata = self.treeCtrlMain.GetControlData(node) + if not cdata.Gcalc: + menu.Enable(self.exportCalcPDFId, False) + + # PHASE + if itemtype != "phase": + menu.Enable(self.exportNewStruId, False) + menu.Enable(self.exportFitStruId, False) + menu.Enable(self.printBLId, False) + menu.Enable(self.printBAId, False) + menu.Enable(self.plotIStructId, False) + menu.Enable(self.plotFStructId, False) + elif numsel > 1: + menu.Enable(self.plotIStructId, False) + menu.Enable(self.plotFStructId, False) + menu.Enable(self.printBLId, False) + menu.Enable(self.printBAId, False) + menu.Enable(self.exportFitStruId, False) + menu.Enable(self.exportNewStruId, False) + else: + menu.Enable(self.plotIStructId, True) + cdata = self.treeCtrlMain.GetControlData(node) + if not cdata.refined: + menu.Enable(self.exportFitStruId, False) + menu.Enable(self.plotFStructId, False) + + # DATASET + if itemtype != "dataset": + menu.Enable(self.exportFitPDFId, False) + elif numsel > 1: + menu.Enable(self.exportFitPDFId, False) + else: + cdata = self.treeCtrlMain.GetControlData(node) + if not cdata.Gcalc: + menu.Enable(self.exportFitPDFId, False) + + # Check the run/stop status. + if self.runningDict: + menu.Enable(self.newId, False) + menu.Enable(self.runCalcId, False) + menu.Enable(self.runFitId, False) + menu.Enable(self.saveAsId, False) + menu.Enable(self.saveId, False) + menu.Enable(self.openId, False) + menu.Enable(self.recentId, False) + + # Disallow certain things during a running fit + pnode = self.treeCtrlMain.GetFitRoot(node) + if pnode in self.runningDict.values(): + menu.EnableTop(1, False) + menu.EnableTop(3, False) + menu.EnableTop(4, False) + menu.EnableTop(5, False) + menu.EnableTop(6, False) + else: + menu.Enable(self.stopFitId, False) + + # Show/Hide fitTree + if self.auiManager.GetPane("treeCtrlMain").IsShown(): + self.showFitItem.SetItemLabel("Hide Fit Tree") + else: + self.showFitItem.SetItemLabel("Show Fit Tree") + + # Show/Hide plotPanel + if self.auiManager.GetPane("plotPanel").IsShown(): + self.showPlotItem.SetItemLabel("Hide Plot Control") + else: + self.showPlotItem.SetItemLabel("Show Plot Control") + + # Show/Hide outputPanel + if self.auiManager.GetPane("outputPanel").IsShown(): + self.showOutputItem.SetItemLabel("Hide Output") + else: + self.showOutputItem.SetItemLabel("Show Output") + + # Show/Hide journalPanel + if self.auiManager.GetPane("journalPanel").IsShown(): + self.showJournalItem.SetItemLabel("Hide Journal\tCtrl+j") + else: + self.showJournalItem.SetItemLabel("Show Journal\tCtrl+j") + + return
+ + + # Shared menu items + # The bulk of the code for these methods is in the FitTree class. +
+[docs] + def onNewFit(self, event): + """Start a new fit tree. + + A fit is given the name "Fit n", where n is the smallest + positive integer such that the name is not already taken. + """ + newfit = self.treeCtrlMain.AddFit() + # Select the fit item so that the name can be edited + self.treeCtrlMain.Expand(newfit) + self.treeCtrlMain.EditLabel(newfit) + self.treeCtrlMain.SelectItem(newfit) + self.treeCtrlMain.EnsureVisible(newfit) + self.needsSave() + return
+ + +
+[docs] + def onCopy(self, event): + """Copy the subtree of the current selected item into the clipboard.""" + selections = self.treeCtrlMain.GetSelections() + if len(selections) == 1: + self.treeCtrlMain.CopyBranch(selections[0]) + return
+ + +
+[docs] + def onPaste(self, event): + """Paste the subtree from the clipboard into the tree.""" + selections = self.treeCtrlMain.GetSelections() + ep = None + if selections: + ep = selections[0] + try: + newnode = self.treeCtrlMain.PasteBranch(ep) + except FitTreeError: + return + self.treeCtrlMain.Expand(newnode) + self.treeCtrlMain.EditLabel(newnode) + self.treeCtrlMain.SelectItem(newnode) + self.treeCtrlMain.EnsureVisible(newnode) + self.needsSave() + return
+ + + + + +
+[docs] + def onInsData(self, event): + """Insert a new dataset item. + + This opens up the new data set panel from adddatapanel.py. That + panel is in charge of inserting a new phase. See the module for + details. + """ + selections = self.treeCtrlMain.GetSelections() + if len(selections) == 1: + self.setMode("addingdata") + self.switchRightPanel("adddata") + self.needsSave() + return
+ + +
+[docs] + def onInsPhase(self, event): + """Insert a new phase item. + + This opens up the new phase panel from addphasepanel.py. That + panel is in charge of inserting a new phase. See the module for + details. + """ + selections = self.treeCtrlMain.GetSelections() + if len(selections) == 1: + self.setMode("addingphase") + self.switchRightPanel("addphase") + self.needsSave() + return
+ + +
+[docs] + def onInsCalc(self, event): + """Insert a new calculation item. + + A calculation is given the name "Calculation n", where n is the + smallest positive integer such that the name is not already + taken. + """ + selections = self.treeCtrlMain.GetSelections() + if len(selections) == 1: + node = selections[0] + fitroot = self.treeCtrlMain.GetFitRoot(node) + newcalc = self.treeCtrlMain.AddCalc(fitroot, "Calculation 1", insertafter=node) + # Select the calculation item so that the name can be edited + self.treeCtrlMain.UnselectAll() + self.treeCtrlMain.EditLabel(newcalc) + self.treeCtrlMain.SelectItem(newcalc) + self.treeCtrlMain.EnsureVisible(newcalc) + self.needsSave() + return
+ + +
+[docs] + def onDelete(self, event): + """Remove the subtrees starting from the selected nodes.""" + selections = self.treeCtrlMain.GetSelections() + + # find a node to choose after deletion + fitroot = None + roots = self.treeCtrlMain.GetChildren(self.treeCtrlMain.root) + delroots = list(map(self.treeCtrlMain.GetFitRoot, selections)) + # Find the fit node above the first removed node. + for root in roots: + if root in selections: + break + + fitroot = root + if root in delroots: + break + + # Delete! + if selections: + self.treeCtrlMain.DeleteBranches(selections) + self.needsSave() + + # Select the fit root it it exists. If not, select the first fit node. + # If that does not exist, then go blank. + if fitroot: + self.treeCtrlMain.SelectItem(fitroot) + else: + fits = self.treeCtrlMain.GetChildren(self.treeCtrlMain.root) + if fits: + self.treeCtrlMain.SelectItem(fits[0]) + else: + self.switchRightPanel("blank") + return
+ + + # Main menu items + +
+[docs] + def onRun(self, event): + """Run the selected fits/calculations and disable their tree entries. + + This also runs calculations that are children of a running fit. + """ + # Make sure that the tree is focused. This will trigger the KILL_FOCUS + # events of the other panels. + self.treeCtrlMain.SetFocus() + + selections = self.treeCtrlMain.GetSelections() + # Get the calculation nodes and fit parent nodes from the selections. + nodes = [ + self.treeCtrlMain.GetFitRoot(sel) + for sel in selections + if self.treeCtrlMain.GetNodeType(sel) != "calculation" + ] + nodes.extend([sel for sel in selections if self.treeCtrlMain.GetNodeType(sel) == "calculation"]) + + # Add calculation nodes that are children of fit nodes, and order them + # as if walking down the fit tree + allnodes = [] + for node in nodes: + if node not in allnodes: + allnodes.append(node) + if self.treeCtrlMain.GetNodeType(node) == "fit": + allnodes.extend(self.treeCtrlMain.GetChildren(node)) + + # Disable the current panel + if self.rightPanel.key != "calculation": + self.rightPanel.Enable(False) + + # Change the color of the fitting nodes depending upon their status. See + # updateFittingStatus for the color scheme. Create a dictionary of fits + # for ease of use. + for sel in allnodes: + if self.treeCtrlMain.GetNodeType(sel) == "fit": + self.treeCtrlMain.SetItemBackgroundColour(sel, wx.LIGHT_GREY) + name = self.treeCtrlMain.GetItemText(sel) + self.runningDict[name] = sel + self.needsSave() + + IDlist = list(map(self.treeCtrlMain.GetControlData, allnodes)) + self.control.start(IDlist) + return
+ + +
+[docs] + def onStop(self, event): + """Stop all fits. + + This removes all items from the runningDict and changes the + status colors back to wxWHITE. + """ + self.control.stop() + self.needsSave() + return
+ + +
+[docs] + def onPreferences(self, event): + """Switch the right panel to the 'preferences' panel. + + The 'preferences' panel uses the 'config' mode. + """ + self.setMode("config") + self.switchRightPanel("preferences") + return
+ + +
+[docs] + def onDefaultLayout(self, event): + """Place the fit tree and plot panel in default locations.""" + from diffpy.pdfgui.gui.windowperspective import default + + self.auiManager.LoadPerspective(default) + self.auiManager.Update() + return
+ + +
+[docs] + def onShowFit(self, event): + """Make sure the fit tree is visible.""" + if self.auiManager.GetPane("treeCtrlMain").IsShown(): + self.auiManager.GetPane("treeCtrlMain").Hide() + else: + self.auiManager.GetPane("treeCtrlMain").Show() + self.auiManager.Update() + return
+ + +
+[docs] + def onShowPlot(self, event): + """Make sure the plot panel is visible.""" + if self.auiManager.GetPane("plotPanel").IsShown(): + self.auiManager.GetPane("plotPanel").Hide() + else: + self.auiManager.GetPane("plotPanel").Show() + self.auiManager.Update() + return
+ + +
+[docs] + def onShowOutput(self, event): + """Make sure the output panel is visible.""" + if self.auiManager.GetPane("outputPanel").IsShown(): + self.auiManager.GetPane("outputPanel").Hide() + else: + self.auiManager.GetPane("outputPanel").Show() + self.auiManager.Update() + return
+ + +
+[docs] + def onShowJournal(self, event): + """Bring up or hide the journal window.""" + if self.auiManager.GetPane("journalPanel").IsShown(): + self.auiManager.GetPane("journalPanel").Hide() + else: + self.auiManager.GetPane("journalPanel").Show() + self.journalPanel.refresh() + self.journalPanel.SetFocus() + self.auiManager.Update() + return
+ + +
+[docs] + def onPlotIStruct(self, event): + """Plots the phase structure. + + Opens Atomeye and plots the structure. + """ + return self._plotStruct("initial")
+ + +
+[docs] + def onPlotFStruct(self, event): + """Plots the phase structure. + + Opens Atomeye and plots the structure. + """ + return self._plotStruct("refined")
+ + + def _plotStruct(self, stype): + """Helper for onPlotFStruct and onPlotIStruct.""" + selections = self.treeCtrlMain.GetSelections() + if selections: + node = selections[0] + itemtype = self.treeCtrlMain.GetNodeType(node) + if itemtype == "phase": + # panel = self.dynamicPanels['phase'] + cdata = self.treeCtrlMain.GetControlData(node) + stru = getattr(cdata, stype) + viewer = structureviewer.getStructureViewer() + viewer.plot(stru) + return + +
+[docs] + def onPrintBL(self, event): + """Print the bond lengths of a selected structure to the output + panel.""" + from diffpy.pdfgui.gui.bondlengthdialog import BondLengthDialog + + selections = self.treeCtrlMain.GetSelections() + if selections: + node = selections[0] + itemtype = self.treeCtrlMain.GetNodeType(node) + if itemtype == "phase": + # panel = self.dynamicPanels['phase'] + cdata = self.treeCtrlMain.GetControlData(node) + S = cdata.refined + if not S: + S = cdata.initial + + dlg = BondLengthDialog(self) + dlg.setStructure(S) + + if dlg.ShowModal() == wx.ID_OK: + fitroot = self.treeCtrlMain.GetFitRoot(node) + fitting = self.treeCtrlMain.GetControlData(fitroot) + + self.control.redirectStdout() + + # Figure out what to calculate. If the upper and lower bound + # is too small, it is assumed that a single distance is + # intended to be calculated. + a = dlg.a + b = dlg.b + ea = dlg.ea + eb = dlg.eb + lb = min(dlg.lb, dlg.ub) + ub = max(dlg.lb, dlg.ub) + + if lb == ub == 0: + fitting.outputBondLengthAtoms(S, a, b) + else: + fitting.outputBondLengthTypes(S, ea, eb, lb, ub) + + self.updateOutput() + dlg.Destroy() + return
+ + +
+[docs] + def onPrintBA(self, event): + """Print the bond angles of a selected structure to the output + panel.""" + from diffpy.pdfgui.gui.bondangledialog import BondAngleDialog + + selections = self.treeCtrlMain.GetSelections() + if selections: + node = selections[0] + itemtype = self.treeCtrlMain.GetNodeType(node) + if itemtype == "phase": + # panel = self.dynamicPanels['phase'] + cdata = self.treeCtrlMain.GetControlData(node) + S = cdata.refined + if not S: + S = cdata.initial + + dlg = BondAngleDialog(self) + dlg.setStructure(S) + + if dlg.ShowModal() == wx.ID_OK: + fitroot = self.treeCtrlMain.GetFitRoot(node) + fitting = self.treeCtrlMain.GetControlData(fitroot) + self.control.redirectStdout() + fitting.outputBondAngle(S, dlg.a, dlg.b, dlg.c) + self.updateOutput() + dlg.Destroy()
+ + +
+[docs] + def onQuickPlot(self, event): + """Quickly plot information for the selected node.""" + selections = self.treeCtrlMain.GetSelections() + if len(selections) != 1: + return + node = selections[0] + refs = [self.treeCtrlMain.GetControlData(node)] + nodetype = self.treeCtrlMain.GetNodeType(selections[0]) + if nodetype == "dataset": + xval = "r" + # For quick plotting, keep this order. Gdiff must be the last. + yvals = ["Gtrunc", "Gcalc", "Gdiff"] + soffset = self.plotPanel.offsetTextCtrl.GetValue() + offset = 0 + if soffset: + offset = float(self.plotPanel.offsetTextCtrl.GetValue()) + self.control.plot(xval, yvals, refs, shift=offset) + elif nodetype == "calculation": + xval = "r" + yvals = ["Gcalc"] + self.control.plot(xval, yvals, refs, shift=0) + elif nodetype == "phase": + cdata = self.treeCtrlMain.GetControlData(node) + if cdata.refined: + self.onPlotFStruct(event) + else: + self.onPlotIStruct(event) + return
+ + +
+[docs] + def onAbout(self, event): + dlg = DialogAbout(self) + # dlg.CenterOnScreen() + dlg.ShowModal() + dlg.Destroy() + return
+ + +
+[docs] + def onRequest(self, event): + dlg = ErrorReportDialog(self) + # dlg.errorReport = True + dlg.ShowModal() + dlg.Destroy() + return
+ + +
+[docs] + def onCommunity(self, event): + """Open the browser and go to the diffpy-users Google Group.""" + import webbrowser + + try: + webbrowser.open(USERSMAILINGLIST) + except Exception as e: + errorinfo = 'Failed to open "%s"' % e + raise ControlError(errorinfo) + return
+ + +
+[docs] + def onNew(self, event): + """Create a new project.""" + retval = self.checkForSave() + if retval != wx.ID_CANCEL: + self.control.stop() + self.control.close() + self.treeCtrlMain.DeleteAllItems() + self.treeCtrlMain.InitializeTree() + self.switchRightPanel("welcome") + self.plotPanel.refresh() + self.needsSave(False) + self.fullpath = "" + self.outputPanel.clearText() + self.journalPanel.refresh() + self.updateTitle() + return
+ + +
+[docs] + def onOpen(self, event): + """Open a file dialog so an existing project can be opened.""" + retval = self.checkForSave() + if retval != wx.ID_CANCEL: + dir, filename = os.path.split(self.fullpath) + if not dir: + dir = self.workpath + matchstring = "PDFgui project files (*.ddp)|*.ddp;*.ddp3" + d = wx.FileDialog(None, "Choose a file", dir, "", matchstring) + if d.ShowModal() == wx.ID_OK: + fullpath = d.GetPath() + # Load this file into the control center. + self.control.stop() + self.control.close() + treelist = self.control.load(fullpath) + self.treeCtrlMain.ExtendProjectTree(treelist) + self.setMode("fitting") + self.switchRightPanel("welcome") + + self.fullpath = fullpath + self.workpath = os.path.dirname(fullpath) + self.fileHistory.AddFileToHistory(fullpath) + self.needsSave(False) + + self.outputPanel.clearText() + self.journalPanel.refresh() + self.updateTitle() + d.Destroy() + return
+ + +
+[docs] + def onSave(self, event): + """Save the project to a predetermined location.""" + # Make sure that the tree is focused. This will trigger the KILL_FOCUS + # events of the other panels. + self.treeCtrlMain.SetFocus() + + code = wx.ID_OK + if self.fullpath: + self.control.save(self.fullpath) + self.fileHistory.AddFileToHistory(self.fullpath) + self.needsSave(False) + pass + else: + code = self.onSaveAs(event) + return code
+ + +
+[docs] + def onSaveAs(self, event): + """Open a save dialog so the current project can be saved.""" + # Make sure that the tree is focused. This will trigger the KILL_FOCUS + # events of the other panels. + self.treeCtrlMain.SetFocus() + + matchstring = "PDFgui project files (*.ddp3)|*.ddp3|All Files|*" + dir, filename = os.path.split(self.fullpath) + if not dir: + dir = self.workpath + d = wx.FileDialog( + None, + "Save as...", + dir, + filename or "project.ddp3", + matchstring, + wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT, + ) + code = d.ShowModal() + if code == wx.ID_OK: + self.fullpath = d.GetPath() + if len(self.fullpath) < 5 or self.fullpath[-5:] != ".ddp3": + self.fullpath += ".ddp3" + self.workpath = os.path.dirname(self.fullpath) + self.fileHistory.AddFileToHistory(self.fullpath) + # Save the file + self.control.save(self.fullpath) + self.needsSave(False) + self.updateTitle() + d.Destroy() + return code
+ + +
+[docs] + def onQuit(self, event): + """Shut down gracefully.""" + # Make sure that we have focus. + self.SetFocus() + retval = self.checkForSave() + if retval != wx.ID_CANCEL: + self.quitting = True + self.updateConfiguration() + self.writeConfiguration() + self.control.exit() + self.auiManager.UnInit() + self.Destroy() + return
+ + +
+[docs] + def onMRUFile(self, event): + """Open a recently used file.""" + index = event.GetId() - wx.ID_FILE1 + filename = self.fileHistory.GetHistoryFile(index) + retval = self.checkForSave() + if retval != wx.ID_CANCEL: + self.control.stop() + self.control.close() + try: + treelist = self.control.load(filename) + self.treeCtrlMain.ExtendProjectTree(treelist) + self.setMode("fitting") + self.switchRightPanel("welcome") + self.needsSave(False) + self.outputPanel.clearText() + self.journalPanel.refresh() + self.fullpath = filename + self.workpath = os.path.dirname(self.fullpath) + self.fileHistory.AddFileToHistory(self.fullpath) + self.updateTitle() + except ControlError as e: + self.fileHistory.RemoveFileFromHistory(index) + self.updateConfiguration() + self.writeConfiguration() + raise e + return
+ + +
+[docs] + def onExportRes(self, event): + """Export the results file for the selected calculation.""" + selections = self.treeCtrlMain.GetSelections() + if not selections: + return + node = selections[0] + nodetype = self.treeCtrlMain.GetNodeType(node) + if nodetype != "fit": + return + cdata = self.treeCtrlMain.GetControlData(node) + name = self.treeCtrlMain.GetItemText(node) + basename = ".".join(name.split(".")[:-1]) or name + matchstring = "PDFgui results files (*.res)|*.res|All Files|*" + d = wx.FileDialog( + None, + "Save as...", + self.workpath, + basename, + matchstring, + wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT, + ) + if d.ShowModal() == wx.ID_OK: + path = d.GetPath() + self.workpath, savename = os.path.split(path) + # Add the right extension if it doesn't already have it. + if len(savename) < 3 or savename[-3:] != "res": + savename += ".res" + path = os.path.join(self.workpath, savename) + outfile = open(path, "w") + outfile.write(cdata.res) + outfile.close() + d.Destroy() + return
+ + +
+[docs] + def onRSeries(self, event): + """Open up the r-series panel.""" + self.setMode("rseries") + self.switchRightPanel("rseries") + return
+ + +
+[docs] + def onTSeries(self, event): + """Open up the temperature series panel.""" + self.setMode("tseries") + self.switchRightPanel("tseries") + return
+ + +
+[docs] + def onDSeries(self, event): + """Open up the doping series panel.""" + self.setMode("dseries") + self.switchRightPanel("dseries") + return
+ + +
+[docs] + def onExportNewStruct(self, event): + """Export a structure that was created from scratch.""" + extlist = ["stru", "cif", "pdb", "xyz", "xyz", ""] + fmtlist = ["pdffit", "cif", "pdb", "xyz", "rawxyz", "xcfg"] + selections = self.treeCtrlMain.GetSelections() + if not selections: + return + node = selections[0] + nodetype = self.treeCtrlMain.GetNodeType(node) + if nodetype != "phase": + return + cdata = self.treeCtrlMain.GetControlData(node) + # branchname = self.treeCtrlMain.GetBranchName(node) + name = self.treeCtrlMain.GetItemText(node) + basename = ".".join(name.split(".")[:-1]) or name + matchstring = ( + "PDFfit structure file (*.stru)|*.stru|" + "Crystallographic Information File (*.cif)|*.cif|" + "Protein Data Bank file (*.pdb)|*.pdb|" + "Labeled coordinate file (*.xyz)|*.xyz|" + "Raw coordinate file (*.xyz)|*.xyz|" + "AtomEye configuration file|*" + ) + d = wx.FileDialog( + None, + "Save as...", + self.workpath, + basename, + matchstring, + wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT, + ) + if d.ShowModal() == wx.ID_OK: + i = d.GetFilterIndex() + path = d.GetPath() + self.workpath, savename = os.path.split(path) + # Add the right extension if the file needs it. + if len(savename) < 3 or (extlist[i] and savename[-3:] != extlist[i][-3:]): + savename += ".%s" % extlist[i] + path = os.path.join(self.workpath, savename) + text = cdata.initial.writeStr(fmtlist[i]) + outfile = open(path, "w") + outfile.write(text) + outfile.close() + d.Destroy() + return
+ + +
+[docs] + def onExportStruct(self, event): + """Export a fit structure.""" + extlist = ["stru", "cif", "pdb", "xyz", "xyz", ""] + fmtlist = ["pdffit", "cif", "pdb", "xyz", "rawxyz", "xcfg"] + selections = self.treeCtrlMain.GetSelections() + if not selections: + return + node = selections[0] + nodetype = self.treeCtrlMain.GetNodeType(node) + if nodetype != "phase": + return + cdata = self.treeCtrlMain.GetControlData(node) + # branchname = self.treeCtrlMain.GetBranchName(node) + name = self.treeCtrlMain.GetItemText(node) + basename = ".".join(name.split(".")[:-1]) or name + matchstring = ( + "PDFfit structure file (*.stru)|*.stru|" + "Crystallographic Information File (*.cif)|*.cif|" + "Protein Data Bank file (*.pdb)|*.pdb|" + "Labeled coordinate file (*.xyz)|*.xyz|" + "Raw coordinate file (*.xyz)|*.xyz|" + "AtomEye configuration file|*" + ) + d = wx.FileDialog( + None, + "Save as...", + self.workpath, + basename, + matchstring, + wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT, + ) + if d.ShowModal() == wx.ID_OK: + i = d.GetFilterIndex() + path = d.GetPath() + self.workpath, savename = os.path.split(path) + # Add the right extension if the file needs it. + if len(savename) < 3 or (extlist[i] and savename[-3:] != extlist[i][-3:]): + savename += ".%s" % extlist[i] + path = os.path.join(self.workpath, savename) + text = cdata.refined.writeStr(fmtlist[i]) + outfile = open(path, "w") + outfile.write(text) + outfile.close() + d.Destroy() + return
+ + +
+[docs] + def onExportPDF(self, event): + """Export a fit PDF.""" + selections = self.treeCtrlMain.GetSelections() + if not selections: + return + node = selections[0] + nodetype = self.treeCtrlMain.GetNodeType(node) + if nodetype != "dataset": + return + cdata = self.treeCtrlMain.GetControlData(node) + # branchname = self.treeCtrlMain.GetBranchName(node) + name = self.treeCtrlMain.GetItemText(node) + basename = ".".join(name.split(".")[:-1]) or name + matchstring = "PDF fit data file (*.fgr)|*.fgr|All Files|*" + d = wx.FileDialog( + None, + "Save as...", + self.workpath, + basename, + matchstring, + wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT, + ) + if d.ShowModal() == wx.ID_OK: + path = d.GetPath() + self.workpath, savename = os.path.split(path) + # Add the right extension if it doesn't already have it. + if len(savename) < 3 or savename[-3:] != "fgr": + savename += ".fgr" + path = os.path.join(self.workpath, savename) + cdata.writeCalc(path) + d.Destroy() + return
+ + +
+[docs] + def onSaveCalc(self, event): + """Export a calculated PDF.""" + selections = self.treeCtrlMain.GetSelections() + if not selections: + return + node = selections[0] + nodetype = self.treeCtrlMain.GetNodeType(node) + if nodetype != "calculation": + return + cdata = self.treeCtrlMain.GetControlData(node) + name = self.treeCtrlMain.GetItemText(node) + basename = ".".join(name.split(".")[:-1]) or name + matchstring = "PDF calculated data file (*.cgr)|*.cgr|All Files|*" + d = wx.FileDialog( + None, + "Save as...", + self.workpath, + basename, + matchstring, + wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT, + ) + if d.ShowModal() == wx.ID_OK: + path = d.GetPath() + self.workpath, savename = os.path.split(path) + # Add the right extension if it doesn't already have it. + if len(savename) < 3 or savename[-3:] != "cgr": + savename += ".cgr" + path = os.path.join(self.workpath, savename) + cdata.write(path) + d.Destroy() + return
+ + +
+[docs] + def onDocumentation(self, event): + """Show information about the documentation.""" + import webbrowser + + webbrowser.open(docMainFile) + return
+ + + # MISC INTERACTION ITEMS +
+[docs] + def showMessage(self, info, title="PDF Control Error"): + """ShowMessage(self, info) --> tell user about an exception and so on. + + title -- window title + info -- message + """ + dlg = wx.MessageDialog(self, info, title, wx.OK | wx.ICON_ERROR) + dlg.ShowModal() + dlg.Destroy() + return
+ + + # control items +
+[docs] + def lock(self): + if not wx.IsMainThread(): + wx.MutexGuiEnter()
+ + +
+[docs] + def unlock(self): + if not wx.IsMainThread(): + wx.MutexGuiLeave()
+ + +
+[docs] + def postEvent(self, type, info): + """This method is called by the control. + + Whenever the control needs to communicate directly with the gui + it can call this method. The event is processed by onCustom and + then handled by the gui on its own terms. + """ + event = PDFCustomEvent() + event.type = type + event.info = info + wx.PostEvent(self, event) + return
+ + +
+[docs] + def onCustom(self, event): + """This handles the custom events sent by the control.""" + if event.type == self.ERROR: + self.showMessage(event.info) + elif event.type == self.UPDATE: + # job is a fitting or a calculation + job = event.info + self.updateFittingStatus(job) + elif event.type == self.OUTPUT: + self.updateOutput() + elif event.type == self.PLOTNOW: + # job is a fitting or a calculation with a new data to plot. + job = event.info + for plot in self.control.plots: + plot.notify(job) + return
+ + +
+[docs] + def updateFittingStatus(self, job): + """Update the fitting status. + + This will alter the local member runningDict so that the running items + cannot be altered. The following status ids are defined in the fitting + module. Some are given a color which gives the user an indication of the + fit status. job is actually a fitting or a calculation object. + + Fit status + INITIALIZED -- 'LIGHT GRAY' + CONNECTED -- 'GREEN' + CONFIGURED -- 'GREEN' + DONE -- 'WHITE' + + JOB Status + VOID + QUEUED + RUNNING + PAUSED + """ + from diffpy.pdfgui.control.fitting import Fitting + + if isinstance(job, Fitting): + name = job.name + fitStatus = job.fitStatus + jobStatus = job.jobStatus + try: + node = self.runningDict[name] + except KeyError: + return + if jobStatus == Fitting.RUNNING: + if fitStatus == Fitting.INITIALIZED: + self.treeCtrlMain.SetItemBackgroundColour(node, wx.LIGHT_GREY) + elif fitStatus in (Fitting.CONNECTED, Fitting.CONFIGURED): + self.treeCtrlMain.SetItemBackgroundColour(node, wx.GREEN) + elif jobStatus == Fitting.VOID: + self.treeCtrlMain.SetItemBackgroundColour(node, wx.WHITE) + selections = self.treeCtrlMain.GetSelections() + if len(selections) == 1: + # Enable whatever panel is currently being viewed. + self.rightPanel.Enable() + if node == selections[0]: + self.rightPanel.refresh() + self.runningDict.pop(name, None) + self.needsSave() + + # Update the menus and toolbars whenever an event is posted. + self.disableMainMenuItems() + self.updateToolbar() + return
+ + +
+[docs] + def updateOutput(self): + """Update text in outputPanel with text in stdout.""" + self.outputPanel.updateText(self.control.getEngineOutput()) + return
+
+ + + +# end of class MainPanel +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/outputpanel.html b/_modules/diffpy/pdfgui/gui/outputpanel.html new file mode 100644 index 00000000..aca048c3 --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/outputpanel.html @@ -0,0 +1,196 @@ + + + + + + + + diffpy.pdfgui.gui.outputpanel — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.outputpanel

+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2007 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Jiwu Liu, Chris Farrow
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+# generated by wxGlade 0.9.3 on Fri Jul 19 16:04:33 2019
+
+import wx
+
+from diffpy.pdfgui.gui.pdfpanel import PDFPanel
+
+
+
+[docs] +class OutputPanel(wx.Panel, PDFPanel): + def __init__(self, *args, **kwds): + # begin wxGlade: OutputPanel.__init__ + kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL + wx.Panel.__init__(self, *args, **kwds) + self.outputTextCtrl = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.HSCROLL | wx.TE_MULTILINE | wx.TE_READONLY) + + self.__set_properties() + self.__do_layout() + # end wxGlade + self.__customProperties() + + def __set_properties(self): + # begin wxGlade: OutputPanel.__set_properties + pass + # end wxGlade + return + + def __do_layout(self): + # begin wxGlade: OutputPanel.__do_layout + sizer_1 = wx.BoxSizer(wx.VERTICAL) + sizer_1.Add(self.outputTextCtrl, 1, wx.ALL | wx.EXPAND, 0) + self.SetSizer(sizer_1) + sizer_1.Fit(self) + self.Layout() + # end wxGlade + + def __customProperties(self): + """Set the custom properties.""" + # Set the font to monospace + ftxt = self.outputTextCtrl.GetFont() + font = wx.Font( + ftxt.GetPointSize(), + wx.FONTFAMILY_TELETYPE, + ftxt.GetStyle(), + ftxt.GetWeight(), + ) + self.outputTextCtrl.SetFont(font) + return + +
+[docs] + def clearText(self): + """Clear the text from the output control.""" + self.outputTextCtrl.Clear() + return
+ + +
+[docs] + def updateText(self, text): + """Update the text in the window.""" + self.outputTextCtrl.AppendText(text) + return
+ + +
+[docs] + def refresh(self): + pass
+
+ + + +# end of class OutputPanel +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/paneltest.html b/_modules/diffpy/pdfgui/gui/paneltest.html new file mode 100644 index 00000000..91675c4a --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/paneltest.html @@ -0,0 +1,193 @@ + + + + + + + + diffpy.pdfgui.gui.paneltest — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for diffpy.pdfgui.gui.paneltest

+#!/usr/bin/env python
+# -*- coding: ISO-8859-1 -*-
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+# generated by wxGlade 0.4 on Tue Feb 21 12:00:30 2006
+
+import wx
+
+# from diffpy.pdfgui.gui.mainframe import MainPanel
+# from diffpy.pdfgui.gui.journalpanel import JournalPanel
+# from diffpy.pdfgui.gui.datasetconfigurepanel import DataSetConfigurePanel
+# from diffpy.pdfgui.gui.fitnotebookpanel import FitNotebookPanel
+# from diffpy.pdfgui.gui.rseriespanel import RSeriesPanel
+from diffpy.pdfgui.gui.temperatureseriespanel import TemperatureSeriesPanel
+
+
+
+[docs] +class MyFrame(wx.Frame): + def __init__(self, *args, **kwds): + # begin wxGlade: MyFrame.__init__ + kwds["style"] = wx.DEFAULT_FRAME_STYLE + wx.Frame.__init__(self, *args, **kwds) + # self.window_1 = MainPanel(self, -1) + # self.window_1 = JournalPanel(self, -1) + # self.window_1 = DataSetConfigurePanel(self, -1) + # self.window_1 = FitNotebookPanel(self, -1) + # self.window_1 = RSeriesPanel(self, -1) + self.window_1 = TemperatureSeriesPanel(self, -1) + + self.__set_properties() + self.__do_layout() + # end wxGlade + + def __set_properties(self): + # begin wxGlade: MyFrame.__set_properties + self.SetTitle("panel test") + # end wxGlade + + def __do_layout(self): + # begin wxGlade: MyFrame.__do_layout + sizer_3 = wx.BoxSizer(wx.VERTICAL) + sizer_3.Add(self.window_1, 1, wx.EXPAND, 0) + self.SetAutoLayout(True) + self.SetSizer(sizer_3) + sizer_3.Fit(self) + sizer_3.SetSizeHints(self) + self.Layout() + # end wxGlade + self.SetSize((700, 120))
+ + + +# end of class MyFrame + + +
+[docs] +class MyApp(wx.App): +
+[docs] + def OnInit(self): + frame_1 = MyFrame(None, -1, "") + self.SetTopWindow(frame_1) + frame_1.Show() + return True
+
+ + + +# end of class MyApp + +if __name__ == "__main__": + app = MyApp(0) + app.MainLoop() +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/parameterspanel.html b/_modules/diffpy/pdfgui/gui/parameterspanel.html new file mode 100644 index 00000000..611fbebb --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/parameterspanel.html @@ -0,0 +1,636 @@ + + + + + + + + diffpy.pdfgui.gui.parameterspanel — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.parameterspanel

+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Dmitriy Bryndin, Chris Farrow
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+
+# Parameters panel
+# Dmitriy Bryndin
+
+
+# generated by wxGlade 0.9.3 on Fri Jul 19 16:04:38 2019
+
+import wx.grid
+
+from diffpy.pdfgui.gui.pdfpanel import PDFPanel
+from diffpy.pdfgui.gui.wxextensions.autowidthlabelsgrid import AutoWidthLabelsGrid
+from diffpy.utils.wx import gridutils
+
+
+
+[docs] +class ParametersPanel(wx.Panel, PDFPanel): + """GUI Panel, parameters viewer/editor. + + Data members: + parameters -- parameters dictionary + _focusedText -- value of a cell before it changes + """ + + def __init__(self, *args, **kwds): + PDFPanel.__init__(self) + # begin wxGlade: ParametersPanel.__init__ + kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL + wx.Panel.__init__(self, *args, **kwds) + self.grid_parameters = AutoWidthLabelsGrid(self, wx.ID_ANY, size=(1, 1)) + self.button_applyparameters = wx.Button(self, wx.ID_ANY, "Apply parameters") + + self.__set_properties() + self.__do_layout() + + self.Bind(wx.grid.EVT_GRID_CMD_CELL_CHANGED, self.onCellChange, self.grid_parameters) + self.Bind( + wx.grid.EVT_GRID_CMD_CELL_LEFT_CLICK, + self.onCellLeftClick, + self.grid_parameters, + ) + self.Bind( + wx.grid.EVT_GRID_CMD_CELL_RIGHT_CLICK, + self.onCellRightClick, + self.grid_parameters, + ) + self.Bind(wx.grid.EVT_GRID_CMD_EDITOR_SHOWN, self.onEditorShown, self.grid_parameters) + self.Bind( + wx.grid.EVT_GRID_CMD_RANGE_SELECT, + self.onGridRangeSelect, + self.grid_parameters, + ) + self.Bind(wx.EVT_BUTTON, self.onApplyParameters, self.button_applyparameters) + # end wxGlade + self.__customProperties() + return + + def __set_properties(self): + # begin wxGlade: ParametersPanel.__set_properties + self.grid_parameters.CreateGrid(0, 3) + self.grid_parameters.EnableDragRowSize(0) + self.grid_parameters.SetColLabelValue(0, "Initial") + self.grid_parameters.SetColLabelValue(1, "Fixed") + self.grid_parameters.SetColLabelValue(2, "Refined") + # end wxGlade + + # set the second column to display boolean values + attr = wx.grid.GridCellAttr() + attr.SetEditor(wx.grid.GridCellBoolEditor()) + attr.SetRenderer(wx.grid.GridCellBoolRenderer()) + self.grid_parameters.SetColAttr(1, attr) + + def __do_layout(self): + # begin wxGlade: ParametersPanel.__do_layout + sizer_1 = wx.BoxSizer(wx.VERTICAL) + sizer_buttons = wx.BoxSizer(wx.HORIZONTAL) + sizer_1.Add(self.grid_parameters, 1, wx.EXPAND, 0) + sizer_buttons.Add((20, 20), 1, 0, 0) + sizer_buttons.Add(self.button_applyparameters, 0, wx.ALL, 5) + sizer_1.Add(sizer_buttons, 0, wx.EXPAND, 0) + self.SetSizer(sizer_1) + sizer_1.Fit(self) + self.Layout() + # end wxGlade + + # ######################################################################## + # Misc Methods + + def __customProperties(self): + """Custom properties for the panel.""" + self._focusedText = None + self._selectedCells = [] + self.parameters = {} + self.fit = None + return + +
+[docs] + def refresh(self): + """Refreshes wigets on the panel.""" + # # Update the parameters dictionary + # self.fitting.updateParameters() + + nRows = len(self.parameters) + + # update the grid + # remove all rows and create new ones + self.grid_parameters.BeginBatch() + gridrows = self.grid_parameters.GetNumberRows() + if gridrows != 0: + self.grid_parameters.DeleteRows(numRows=gridrows) + self.grid_parameters.InsertRows(numRows=nRows) + # self.grid_parameters.SetColFormatBool(1) + + i = 0 + keys = sorted(self.parameters.keys()) + for key in keys: + # parameter index + self.grid_parameters.SetRowLabelValue(i, str(self.parameters[key].idx)) + # initial value + self.grid_parameters.SetCellValue(i, 0, str(self.parameters[key].initialStr())) + # flag "fixed" + # NOTE: for bool type of cells use '0' or '1' as False and True + self.grid_parameters.SetCellValue(i, 1, str(int(self.parameters[key].fixed))) + # refined value + self.grid_parameters.SetReadOnly(i, 2) + if self.parameters[key].refined is None: + self.grid_parameters.SetCellValue(i, 2, "") + else: + self.grid_parameters.SetCellValue(i, 2, str(self.parameters[key].refined)) + i += 1 + + self.grid_parameters.AutosizeLabels() + self.grid_parameters.AutoSizeColumns() + self.grid_parameters.EndBatch()
+ + +
+[docs] + def onCellLeftClick(self, event): # wxGlade: ParametersPanel.<event_handler> + """Toggle a fix/free cell when clicked.""" + r = event.GetRow() + c = event.GetCol() + # Only proceed if there is no selection and + # this click has no keyboard modifiers. + ignorethis = c != 1 or self.grid_parameters.IsSelection() or event.ShiftDown() or event.ControlDown() + if ignorethis: + # do standard click event handling + event.Skip() + return + # We consume the event here. This prevents focusing the clicked + # cell after a click, but that is not necessary for a checkbox. + state = int(self.grid_parameters.GetCellValue(r, c) or 0) + self.applyCellChange(r, c, not state) + return
+ + +
+[docs] + def onGridRangeSelect(self, event): # wxGlade: ParametersPanel.<event_handler> + """Handle range selections. + + This is needed to properly handle simple left-clicking of + fix/free cells. It serves no other purpose. + """ + event.Skip() + return
+ + +
+[docs] + def onCellRightClick(self, event): # wxGlade: ParametersPanel.<event_handler> + # Popup the menu. If an item is selected then its handler + # will be called before PopupMenu returns. + r = event.GetRow() + c = event.GetCol() + # If the right-clicked node is not part of a group, then make sure that + # it is the only selected cell. + append = False + if self.grid_parameters.IsInSelection(r, c): + append = True + self.grid_parameters.SelectBlock(r, c, r, c, append) + self.popupMenu(self.grid_parameters, event.GetPosition().x, event.GetPosition().y) + event.Skip() + return
+ + +
+[docs] + def onEditorShown(self, event): # wxGlade: ParametersPanel.<event_handler> + i = event.GetRow() + j = event.GetCol() + self._focusedText = self.grid_parameters.GetCellValue(i, j) + self._selectedCells = gridutils.getSelectedCells(self.grid_parameters) + event.Skip() + return
+ + +
+[docs] + def onCellChange(self, event): # wxGlade: ParametersPanel.<event_handler> + # NOTE: be careful with refresh() => recursion! operations on grid will + # call onCellChange + # Note that this method does not get called when a fix/free cell is + # selected. + i = event.GetRow() + j = event.GetCol() + + if self._focusedText is None: + return + self._focusedText = None + + value = self.grid_parameters.GetCellValue(i, j) + # Verify the value. This is done here since if it is allowed to be done + # in fillCells, then an error dialog will be thrown for each point + # in the loop. + try: + # Check that the value is valid + if j == 0: + converted = value + try: + converted = int(value) + except ValueError: + pass + key = int(self.grid_parameters.GetRowLabelValue(i)) + temp = self.parameters[key].initialValue() + if temp != converted: + self.parameters[key].setInitial(converted) + self.mainFrame.needsSave() + + # If we made it this far, then we can continue. + self.fillCells(self._selectedCells, value) + self.grid_parameters.AutoSizeColumns(0) + finally: + # self.refresh() + event.Skip() + + return
+ + +
+[docs] + def applyCellChange(self, row, col, value): + """Update parameters dictionary according to a change in a cell. + + This also updates the cell, if possible, but not the grid. Changes to + the cell that may affect the grid, such as inserting text that is wider + than the column width, must be handled elsewhere. + + row -- row + col -- column + value -- new value + """ + key = int(self.grid_parameters.GetRowLabelValue(row)) + if col == 0: # initial value + temp = self.parameters[key].initialValue() + if temp != value: + self.parameters[key].setInitial(value) + self.grid_parameters.SetCellValue(row, 0, str(float(value))) + self.mainFrame.needsSave() + + elif col == 1: # flag "fixed" + temp = bool(self.parameters[key].fixed) + value = bool(int(value)) + if temp is not value: + self.parameters[key].fixed = value + self.grid_parameters.SetCellValue(row, 1, str(int(value))) + self.mainFrame.needsSave() + + return
+ + +
+[docs] + def popupMenu(self, window, x, y): + """Opens a popup menu. + + window -- window, where to popup a menu + x -- x coordinate + y -- y coordinate + """ + # only do this part the first time so the events are only bound once + if not hasattr(self, "did_popupIDs"): + self.did_popupIDs = True + self.popupID1 = wx.NewIdRef() + self.popupID2 = wx.NewIdRef() + self.popupID3 = wx.NewIdRef() + + self.Bind(wx.EVT_MENU, self.onPopupFixFree, id=self.popupID1) + self.Bind(wx.EVT_MENU, self.onPopupCopyRefinedToInitial, id=self.popupID2) + self.Bind(wx.EVT_MENU, self.onPopupRenameParameters, id=self.popupID3) + + # make a menu + menu = wx.Menu() + + # add some other items + menu.Append(self.popupID1, "Fix / Free") + menu.Append(self.popupID2, "Copy Refined To Initial") + menu.Append(self.popupID3, "Rename Parameters") + + # Popup the menu. If an item is selected then its handler + # will be called before PopupMenu returns. + window.PopupMenu(menu, wx.Point(x, y)) + menu.Destroy() + return
+ + + # Popup menu events ################################################## +
+[docs] + def onPopupFill(self, event): + """Fills cells selected in the grid with a new value.""" + + # NOTE: GetSelectedCells returns only SINGLE selected cells, not blocks or row/columns ! + if self.grid_parameters.IsSelection(): + dlg = wx.TextEntryDialog(self, "New value:", "Fill Selected Cells", "") + + if dlg.ShowModal() == wx.ID_OK: + value = dlg.GetValue() + + rows = self.grid_parameters.GetNumberRows() + cols = self.grid_parameters.GetNumberCols() + + for i in range(rows): + for j in range(cols): + inSelection = self.grid_parameters.IsInSelection(i, j) + valueChanged = value != self.grid_parameters.GetCellValue(i, j) + if inSelection and valueChanged: + self.applyCellChange(i, j, value) + + # self.refresh() + + dlg.Destroy() + event.Skip()
+ + +
+[docs] + def onPopupFixFree(self, event): + """Fixes parameters with selected cells.""" + # NOTE: GetSelectedCells returns only SINGLE selected cells, not blocks + # or row/columns ! + seldict = {} + if self.grid_parameters.IsSelection(): + + indices = self.getSelectedParameters() + for row in indices: + state = self.grid_parameters.GetCellValue(row, 1) + state = bool(int(state.strip() or "0")) + seldict[row] = state + + # Find the majority state + nfixed = sum(1 for st in seldict.values() if st) + nfree = len(seldict) - nfixed + newstate = True # fixed + if nfree < nfixed: + # free all parameters + newstate = False + + for row in seldict: + self.applyCellChange(row, 1, newstate) + event.Skip() + return
+ + +
+[docs] + def onPopupCopyRefinedToInitial(self, event): + """Copy refined parameter to initial value.""" + if not self.grid_parameters.IsSelection(): + event.Skip() + return + for row in self.getSelectedParameters(): + refined = self.grid_parameters.GetCellValue(row, 2) + if refined == "": + continue + self.applyCellChange(row, 0, refined) + # Resize the first column + self.grid_parameters.AutoSizeColumn(0) + event.Skip() + return
+ + +
+[docs] + def onPopupRenameParameters(self, event): + """Rename parameters.""" + + if self.grid_parameters.IsSelection(): + dlg = wx.TextEntryDialog(self, "New index:", "Rename Selected Parameters", "") + + value = None + if dlg.ShowModal() == wx.ID_OK: + value = dlg.GetValue() + dlg.Destroy() + try: + value = int(value) + except (ValueError, TypeError): + return + + rows = self.grid_parameters.GetNumberRows() + cols = self.grid_parameters.GetNumberCols() + + selpars = [] + # Get the selected parameters + for i in range(rows): + key = int(self.grid_parameters.GetRowLabelValue(i)) + for j in range(cols): + if self.grid_parameters.IsInSelection(i, j): + selpars.append(key) + break + + for key in selpars: + if key != value: + self.fit.changeParameterIndex(key, value) + self.mainFrame.needsSave() + + self.fit.updateParameters() + self.refresh() + + event.Skip() + return
+ + + # end of Popup menu events ########################################### + +
+[docs] + def onApplyParameters(self, event): # wxGlade: ParametersPanel.<event_handler> + self.fit.applyParameters() + self.mainFrame.needsSave() + event.Skip()
+ + + # Required by event handlers + +
+[docs] + def getSelectedParameters(self): + """Get list of row values of selected cells.""" + rows = self.grid_parameters.GetNumberRows() + cols = self.grid_parameters.GetNumberCols() + selection = [] + + for i in range(rows): + for j in range(cols): + if self.grid_parameters.IsInSelection(i, j): + selection.append(i) + break + + return selection
+ + +
+[docs] + def fillCells(self, indices, value): + """Fill cells with a given value. + + indices -- list of (i,j) tuples representing cell coordinates + value -- string value to place into cells + """ + for i, j in indices: + if j != 1 and not self.grid_parameters.IsReadOnly(i, j): + self.applyCellChange(i, j, value) + return
+
+ + + +# end of class ParametersPanel + +# testing code ############################################################ +if __name__ == "__main__": + + class MyFrame(wx.Frame): + def __init__(self, *args, **kwds): + kwds["style"] = wx.DEFAULT_FRAME_STYLE + wx.Frame.__init__(self, *args, **kwds) + self.window = ParametersPanel(self, -1) + self.SetTitle("testing") + # choke, mainframe.needsSave() emulation + self.window.mainFrame = self.window + self.window.mainFrame.needsSave = self.dummy + + self.test() + + def dummy(self): + pass + + def test(self): + """Testing code goes here.""" + from diffpy.pdfgui.control.parameter import Parameter + + self.window.parameters = { + 3: Parameter(3), + 17: Parameter(17), + 11: Parameter(11), + } + self.window.parameters[3].setInitial(1) + self.window.parameters[17].setInitial(0.55) + self.window.parameters[11].setInitial(5.532) + + self.window.refresh() + + class MyApp(wx.App): + def onInit(self): + frame_1 = MyFrame(None, -1, "") + self.SetTopWindow(frame_1) + frame_1.Show() + return 1 + + app = MyApp(0) + app.MainLoop() +# end of testing code ##################################################### +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/pdfguiglobals.html b/_modules/diffpy/pdfgui/gui/pdfguiglobals.html new file mode 100644 index 00000000..dad89d02 --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/pdfguiglobals.html @@ -0,0 +1,194 @@ + + + + + + + + diffpy.pdfgui.gui.pdfguiglobals — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.pdfguiglobals

+#!/usr/bin/env python
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Pavol Juhas
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+"""This module contains global parameters needed by PDFgui."""
+
+import os.path
+from importlib.resources import files
+
+from diffpy.pdfgui.gui import debugoptions
+
+# Name of the program
+name = "PDFgui"
+# Maximum number of files to be remembered
+MAXMRU = 5
+# The location of the configuration file
+configfilename = os.path.expanduser("~/.pdfgui_py3.cfg")
+# Project modification flag
+isAltered = False
+
+# Resolve APPDATADIR base path to application data files.
+try:
+    _mydir = os.path.abspath(str(files(__name__)))
+except TypeError:  # For Python < 3.12
+    _mydir = os.path.abspath(os.path.dirname(__file__))
+
+_upbasedir = os.path.normpath(_mydir + "/../../..")
+_development_mode = os.path.basename(_upbasedir) == "src" and os.path.isfile(
+    os.path.join(_upbasedir, "../pyproject.toml")
+)
+
+# Requirement must have egg-info.  Do not use in _development_mode.
+_req = "diffpy.pdfgui"
+
+# pavol
+# APPDATADIR = (os.path.dirname(_upbasedir) if _development_mode
+#               else str(files(_req)))
+# long
+if _development_mode:
+    APPDATADIR = os.path.dirname(_mydir)
+else:
+    APPDATADIR = str(files(_req))
+
+APPDATADIR = os.path.abspath(APPDATADIR)
+
+# Location of the HTML manual
+docMainFile = "https://diffpy.github.io/diffpy.pdfgui/manual.html"
+
+del _upbasedir
+del _development_mode
+del _req
+
+
+
+[docs] +def iconpath(iconfilename): + """Full path to the icon file in pdfgui installation. This function should + be used whenever GUI needs access to custom icons. + + iconfilename -- icon file name without any path + + Return string. + """ + rv = os.path.join(APPDATADIR, "icons", iconfilename) + assert os.path.isfile(rv), "icon file does not exist" + return rv
+ + + +# options and arguments passed on command line +cmdopts = [] +cmdargs = [] + +# debugging options: + +dbopts = debugoptions.DebugOptions() + +# End of file +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/pdfpanel.html b/_modules/diffpy/pdfgui/gui/pdfpanel.html new file mode 100644 index 00000000..37bbc4aa --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/pdfpanel.html @@ -0,0 +1,176 @@ + + + + + + + + diffpy.pdfgui.gui.pdfpanel — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for diffpy.pdfgui.gui.pdfpanel

+#!/usr/bin/env python
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow, Dmitriy Bryndin
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+import wx
+
+from diffpy.pdfgui.gui.errorwrapper import catchObjectErrors
+
+
+
+[docs] +class PDFPanel(object): + """Mix-in class for all PDF gui panels. + + This method is meant to be a secondary parent class for classed + derived from wx.Panel. It defines methods and member variables + necessary to all panels in the PDFgui. + """ + + def __init__(self, *args, **kwds): + self.mainFrame = None + self.treeCtrlMain = None + # The configuration parser for reading and writing to the + # configuration file + self.cP = None + # key is used to determine the node type associated with the given panel. + self.key = "" + # Wrap all events so that the exceptions get handled. + catchObjectErrors(self) + return + +
+[docs] + def refresh(self): + """Refreshes wigets of the panel. + + This method must be overloaded in the derived class or else a + NotImplementedError will be raised when this method is called. + """ + raise NotImplementedError("refresh() must be implemented in subclass")
+ + +
+[docs] + def setToolTips(self, toolTips): + """Sets tooltips for controls. + + @param toolTips: dictionary of the form {'controlname' : + 'tooltip'} + """ + for controlName, tooltip in toolTips.items(): + control = getattr(self, controlName) + if control.GetToolTip() is None: + control.SetToolTip(wx.ToolTip("")) + tt = control.GetToolTip() + tt.SetTip(tooltip) + return
+
+ +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/phaseconfigurepanel.html b/_modules/diffpy/pdfgui/gui/phaseconfigurepanel.html new file mode 100644 index 00000000..cd533b99 --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/phaseconfigurepanel.html @@ -0,0 +1,965 @@ + + + + + + + + diffpy.pdfgui.gui.phaseconfigurepanel — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.phaseconfigurepanel

+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow, Dmitriy Bryndin
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+# generated by wxGlade 0.9.3 on Fri Jul 19 16:04:47 2019
+
+import wx
+import wx.grid
+
+from diffpy.pdffit2 import is_element
+from diffpy.pdfgui.control.controlerrors import TempControlSelectError
+from diffpy.pdfgui.gui import phasepanelutils, tooltips
+from diffpy.pdfgui.gui.insertrowsdialog import InsertRowsDialog
+from diffpy.pdfgui.gui.pdfpanel import PDFPanel
+from diffpy.pdfgui.gui.wxextensions.autowidthlabelsgrid import AutoWidthLabelsGrid
+from diffpy.pdfgui.gui.wxextensions.textctrlutils import textCtrlAsGridCell
+from diffpy.pdfgui.gui.wxextensions.validators import FLOAT_ONLY, TextValidator
+from diffpy.structure import Atom
+from diffpy.utils.wx import gridutils
+
+
+
+[docs] +class PhaseConfigurePanel(wx.Panel, PDFPanel): + """Panel for configuring a phase. + + Data members: + structure -- reference to PDFStructure + _focusedText -- value of a cell or textctrl before it changes + lConstraintsMap -- map of TextCtrl name to parameter name + _row -- row, where rightclick occurred + _col -- column, where rightclick occurred + """ + + def __init__(self, *args, **kwds): + PDFPanel.__init__(self) + # begin wxGlade: PhaseConfigurePanel.__init__ + kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL + wx.Panel.__init__(self, *args, **kwds) + self.SetFocus() + + sizerMain = wx.BoxSizer(wx.VERTICAL) + + sizerPanelName = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.HORIZONTAL) + sizerMain.Add(sizerPanelName, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) + + self.labelPanelName = wx.StaticText(self, wx.ID_ANY, "Phase Configuration") + self.labelPanelName.SetFont( + wx.Font( + 18, + wx.FONTFAMILY_DEFAULT, + wx.FONTSTYLE_NORMAL, + wx.FONTWEIGHT_BOLD, + 0, + "", + ) + ) + sizerPanelName.Add(self.labelPanelName, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT, 5) + + sizerLatticeParameters = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.HORIZONTAL) + sizerMain.Add(sizerLatticeParameters, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) + + grid_sizer_3 = wx.FlexGridSizer(2, 6, 0, 0) + sizerLatticeParameters.Add(grid_sizer_3, 1, wx.EXPAND, 0) + + self.labelA = wx.StaticText(self, wx.ID_ANY, "a") + grid_sizer_3.Add(self.labelA, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) + + self.textCtrlA = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) + grid_sizer_3.Add(self.textCtrlA, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + self.labelB = wx.StaticText(self, wx.ID_ANY, "b") + grid_sizer_3.Add(self.labelB, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) + + self.textCtrlB = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) + grid_sizer_3.Add(self.textCtrlB, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + self.labelC = wx.StaticText(self, wx.ID_ANY, "c") + grid_sizer_3.Add(self.labelC, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) + + self.textCtrlC = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) + grid_sizer_3.Add(self.textCtrlC, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + self.labelAlpha = wx.StaticText(self, wx.ID_ANY, "alpha") + grid_sizer_3.Add(self.labelAlpha, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) + + self.textCtrlAlpha = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) + grid_sizer_3.Add(self.textCtrlAlpha, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + self.labelBeta = wx.StaticText(self, wx.ID_ANY, "beta") + grid_sizer_3.Add(self.labelBeta, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) + + self.textCtrlBeta = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) + grid_sizer_3.Add(self.textCtrlBeta, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + self.labelGamma = wx.StaticText(self, wx.ID_ANY, "gamma") + grid_sizer_3.Add(self.labelGamma, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) + + self.textCtrlGamma = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) + grid_sizer_3.Add(self.textCtrlGamma, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + sizerAdditionalParameters = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.HORIZONTAL) + sizerMain.Add(sizerAdditionalParameters, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) + + grid_sizer_4 = wx.FlexGridSizer(3, 6, 0, 0) + sizerAdditionalParameters.Add(grid_sizer_4, 1, wx.EXPAND, 0) + + self.labelScaleFactor = wx.StaticText(self, wx.ID_ANY, "Scale Factor") + grid_sizer_4.Add( + self.labelScaleFactor, + 0, + wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, + 5, + ) + + self.textCtrlScaleFactor = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) + grid_sizer_4.Add(self.textCtrlScaleFactor, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + grid_sizer_4.Add((20, 10), 0, 0, 0) + + grid_sizer_4.Add((20, 10), 0, 0, 0) + + grid_sizer_4.Add((20, 10), 0, 0, 0) + + grid_sizer_4.Add((20, 10), 0, 0, 0) + + self.labelDelta1 = wx.StaticText(self, wx.ID_ANY, "delta1") + grid_sizer_4.Add(self.labelDelta1, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) + + self.textCtrlDelta1 = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) + grid_sizer_4.Add(self.textCtrlDelta1, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + self.labelDelta2 = wx.StaticText(self, wx.ID_ANY, "delta2") + grid_sizer_4.Add(self.labelDelta2, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) + + self.textCtrlDelta2 = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) + grid_sizer_4.Add(self.textCtrlDelta2, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + self.labelSpdiameter = wx.StaticText(self, wx.ID_ANY, "spdiameter") + grid_sizer_4.Add( + self.labelSpdiameter, + 0, + wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, + 5, + ) + + self.textCtrlSpdiameter = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) + grid_sizer_4.Add(self.textCtrlSpdiameter, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + self.labelSratio = wx.StaticText(self, wx.ID_ANY, "sratio") + grid_sizer_4.Add(self.labelSratio, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) + + self.textCtrlSratio = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) + grid_sizer_4.Add(self.textCtrlSratio, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + self.labelRcut = wx.StaticText(self, wx.ID_ANY, "rcut") + grid_sizer_4.Add(self.labelRcut, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) + + self.textCtrlRcut = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) + grid_sizer_4.Add(self.textCtrlRcut, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + self.labelStepcut = wx.StaticText(self, wx.ID_ANY, "stepcut") + grid_sizer_4.Add(self.labelStepcut, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) + + self.textCtrlStepcut = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) + grid_sizer_4.Add(self.textCtrlStepcut, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + sizerAtoms = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.VERTICAL) + sizerMain.Add(sizerAtoms, 1, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) + + sizer_1 = wx.BoxSizer(wx.HORIZONTAL) + sizerAtoms.Add(sizer_1, 0, wx.EXPAND, 0) + + self.labelIncludedPairs = wx.StaticText(self, wx.ID_ANY, "Included Pairs") + sizer_1.Add(self.labelIncludedPairs, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) + + self.textCtrlIncludedPairs = wx.TextCtrl(self, wx.ID_ANY, "all-all") + self.textCtrlIncludedPairs.SetMinSize((240, 25)) + sizer_1.Add(self.textCtrlIncludedPairs, 0, wx.ALL, 5) + + self.gridAtoms = AutoWidthLabelsGrid(self, wx.ID_ANY, size=(1, 1)) + self.gridAtoms.CreateGrid(0, 11) + self.gridAtoms.EnableDragRowSize(0) + self.gridAtoms.SetColLabelValue(0, "elem") + self.gridAtoms.SetColLabelValue(1, "x") + self.gridAtoms.SetColLabelValue(2, "y") + self.gridAtoms.SetColLabelValue(3, "z") + self.gridAtoms.SetColLabelValue(4, "u11") + self.gridAtoms.SetColLabelValue(5, "u22") + self.gridAtoms.SetColLabelValue(6, "u33") + self.gridAtoms.SetColLabelValue(7, "u12") + self.gridAtoms.SetColLabelValue(8, "u13") + self.gridAtoms.SetColLabelValue(9, "u23") + self.gridAtoms.SetColLabelValue(10, "occ") + sizerAtoms.Add(self.gridAtoms, 1, wx.EXPAND, 0) + + self.SetSizer(sizerMain) + sizerMain.Fit(self) + + self.Layout() + + self.Bind(wx.grid.EVT_GRID_CMD_CELL_CHANGED, self.onCellChange, self.gridAtoms) + self.Bind(wx.grid.EVT_GRID_CMD_CELL_RIGHT_CLICK, self.onCellRightClick, self.gridAtoms) + self.Bind(wx.grid.EVT_GRID_CMD_EDITOR_SHOWN, self.onEditorShown, self.gridAtoms) + self.Bind( + wx.grid.EVT_GRID_CMD_LABEL_RIGHT_CLICK, + self.onLabelRightClick, + self.gridAtoms, + ) + # end wxGlade + self.__customProperties() + + # ######################################################################## + # Misc Methods + + def __customProperties(self): + """Custom properties for the panel.""" + self.structure = None + self.constraints = {} + self.results = None + self._row = 0 + self._col = 0 + self._focusedText = None + self._selectedCells = [] + + self.lAtomConstraints = [ + "x", + "y", + "z", + "u11", + "u22", + "u33", + "u12", + "u13", + "u23", + "occ", + ] + # pdffit internal naming + self.lConstraintsMap = { + "textCtrlA": "lat(1)", + "textCtrlB": "lat(2)", + "textCtrlC": "lat(3)", + "textCtrlAlpha": "lat(4)", + "textCtrlBeta": "lat(5)", + "textCtrlGamma": "lat(6)", + "textCtrlScaleFactor": "pscale", + "textCtrlDelta1": "delta1", + "textCtrlDelta2": "delta2", + "textCtrlSratio": "sratio", + "textCtrlRcut": "rcut", + "textCtrlStepcut": "stepcut", + "textCtrlSpdiameter": "spdiameter", + } + + # bind onSetFocus onKillFocus events to text controls + for tname in self.lConstraintsMap: + self.__dict__[tname].Bind(wx.EVT_SET_FOCUS, self.onSetFocus) + self.__dict__[tname].Bind(wx.EVT_KILL_FOCUS, self.onKillFocus) + self.__dict__[tname].SetValidator(TextValidator(FLOAT_ONLY)) + self.__dict__[tname].Bind(wx.EVT_KEY_DOWN, self.onTextCtrlKey) + + self.textCtrlIncludedPairs.Bind(wx.EVT_SET_FOCUS, self.onSetFocus) + self.textCtrlIncludedPairs.Bind(wx.EVT_KILL_FOCUS, self.onSelectedPairs) + self.textCtrlIncludedPairs.Bind(wx.EVT_KEY_DOWN, self.onTextCtrlKey) + + # define tooltips + self.setToolTips(tooltips.phasepanel) + # make sure tooltips exist for all lConstraintsMap controls as + # this is later assumed in restrictConstrainedParameters code + for tname in self.lConstraintsMap: + assert getattr(self, tname).GetToolTip() is not None + + # catch key events and apply them to the grid + self.Bind(wx.EVT_KEY_DOWN, self.onKey) + return + + # Create the onTextCtrlKey event handler from textCtrlAsGridCell from + # wxextensions.textctrlutils + onTextCtrlKey = textCtrlAsGridCell + + def _cache(self): + """Cache the current structure and constraints for future + comparison.""" + pass + + __this_is_first_refresh = True + +
+[docs] + def refresh(self): + """Refreshes widgets on the panel.""" + phasepanelutils.refreshTextCtrls(self) + pairs = self.structure.getSelectedPairs() + self.textCtrlIncludedPairs.SetValue(pairs) + phasepanelutils.refreshGrid(self) + self.restrictConstrainedParameters() + # wxpython 3.0 on Windows 7 prevents textCtrlA from receiving + # left-click input focus and can be only focused with a Tab key. + # This only happens for the first input, the text control behaves + # normally after receiving focus once. + # Workaround: do explicit focus here for the first rendering. + if self.__this_is_first_refresh: + self.__this_is_first_refresh = False + focusowner = self.textCtrlA.FindFocus() + wx.CallAfter(self.textCtrlA.SetFocus) + if focusowner is not None: + wx.CallAfter(focusowner.SetFocus) + return
+ + +
+[docs] + def restrictConstrainedParameters(self): + """Set 'read-only' boxes that correspond to constrained parameters.""" + + self.setToolTips(tooltips.phasepanel) + self.textCtrlA.DefaultStyle.BackgroundColour + txtbg = self.textCtrlScaleFactor.DefaultStyle.BackgroundColour + + # First the TextCtrls + for key, var in self.lConstraintsMap.items(): + textCtrl = getattr(self, key) + if var in self.constraints: + textCtrl.SetEditable(False) + textCtrl.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT)) + tt = textCtrl.GetToolTip() + tt.SetTip(self.constraints[var].formula) + else: + textCtrl.SetEditable(True) + textCtrl.SetBackgroundColour(txtbg) + + # Now the grid + rows = self.gridAtoms.GetNumberRows() + cols = self.gridAtoms.GetNumberCols() + + for i in range(rows): + for j in range(1, cols): + var = self.lAtomConstraints[j - 1] + var += "(%i)" % (i + 1) + if var in self.constraints: + self.gridAtoms.SetReadOnly(i, j, True) + self.gridAtoms.SetCellBackgroundColour( + i, j, wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT) + ) + else: + self.gridAtoms.SetReadOnly(i, j, False) + self.gridAtoms.SetCellBackgroundColour(i, j, wx.NullColour) + + return
+ + +
+[docs] + def applyTextCtrlChange(self, id, value): + """Update a structure according to a change in a TextCtrl. + + id -- textctrl id + value -- new value + """ + if self.structure is None: + return + + try: + value = float(value) + if id == self.textCtrlA.GetId(): + self.structure.lattice.setLatPar(a=value) + elif id == self.textCtrlB.GetId(): + self.structure.lattice.setLatPar(b=value) + elif id == self.textCtrlC.GetId(): + self.structure.lattice.setLatPar(c=value) + elif id == self.textCtrlAlpha.GetId(): + self.structure.lattice.setLatPar(alpha=value) + elif id == self.textCtrlBeta.GetId(): + self.structure.lattice.setLatPar(beta=value) + elif id == self.textCtrlGamma.GetId(): + self.structure.lattice.setLatPar(gamma=value) + elif id == self.textCtrlScaleFactor.GetId(): + self.structure.pdffit["scale"] = value + elif id == self.textCtrlDelta1.GetId(): + self.structure.pdffit["delta1"] = value + elif id == self.textCtrlDelta2.GetId(): + self.structure.pdffit["delta2"] = value + elif id == self.textCtrlSratio.GetId(): + self.structure.pdffit["sratio"] = value + elif id == self.textCtrlRcut.GetId(): + self.structure.pdffit["rcut"] = value + elif id == self.textCtrlStepcut.GetId(): + self.structure.pdffit["stepcut"] = value + elif id == self.textCtrlSpdiameter.GetId(): + self.structure.pdffit["spdiameter"] = value + + return value + + except Exception: + return None
+ + +
+[docs] + def applyCellChange(self, i, j, value): + """Update an atom according to a change in a cell. + + i -- cell position + j -- cell position + value -- new value + """ + if not self.mainFrame or self.structure is None: + return + + # The element name + if j == 0: + value = value.title() + if not is_element(value): + return + self.structure[i].element = value # element + return value + + # Other entries + # ignore the change if the value is not valid + try: + value = float(value) + if value == "": + value = 0.0 + if j == 1: + self.structure[i].xyz[0] = value # x + elif j == 2: + self.structure[i].xyz[1] = value # y + elif j == 3: + self.structure[i].xyz[2] = value # z + elif j == 4: + self.structure[i].U[0, 0] = value # U(1,1) + elif j == 5: + self.structure[i].U[1, 1] = value # U(2,2) + elif j == 6: + self.structure[i].U[2, 2] = value # U(3,3) + elif j == 7: + self.structure[i].U[0, 1] = self.structure[i].U[1, 0] = value # U(1,2) + elif j == 8: + self.structure[i].U[0, 2] = self.structure[i].U[2, 0] = value # U(1,3) + elif j == 9: + self.structure[i].U[1, 2] = self.structure[i].U[2, 1] = value # U(2,3) + elif j == 10: + self.structure[i].occupancy = value # occupancy + + self.mainFrame.needsSave() + return value + + except ValueError: + return
+ + + # ######################################################################## + # Event Handlers + + # TextCtrl Events +
+[docs] + def onSetFocus(self, event): + """Saves a TextCtrl value, to be compared in onKillFocus later.""" + self._focusedText = event.GetEventObject().GetValue() + event.Skip() + return
+ + +
+[docs] + def onKillFocus(self, event): + """Check value of TextCtrl and update structure if necessary.""" + if not self.mainFrame: + return + textctrl = event.GetEventObject() + value = textctrl.GetValue() + if value != self._focusedText: + self.applyTextCtrlChange(textctrl.GetId(), value) + phasepanelutils.refreshTextCtrls(self) + self.mainFrame.needsSave() + self._focusedText = None + event.Skip() + return
+ + +
+[docs] + def onSelectedPairs(self, event): + """Check to see if the value of the selected pairs is valid.""" + if not self.mainFrame: + return + value = self.textCtrlIncludedPairs.GetValue() + self.structure.setSelectedPairs(value) + value = self.structure.getSelectedPairs() + self.textCtrlIncludedPairs.SetValue(value) + event.Skip() + return
+ + + # Grid Events +
+[docs] + def onLabelRightClick(self, event): # wxGlade: PhaseConfigurePanel.<event_handler> + """Bring up right-click menu.""" + if self.structure is not None: + dx = dy = 0 + if event.GetRow() == -1: + dy = self.gridAtoms.GetGridCornerLabelWindow().GetSize().y + if event.GetCol() == -1: + dx = self.gridAtoms.GetGridCornerLabelWindow().GetSize().x + + # do not popup menu if the whole grid is set to read only + if len(self.structure) == 0: + self.popupMenu( + self.gridAtoms, + event.GetPosition().x - dx, + event.GetPosition().y - dy, + ) + event.Skip() + return
+ + +
+[docs] + def onCellRightClick(self, event): # wxGlade: PhaseConfigurePanel.<event_handler> + """Bring up right-click menu.""" + self._row = event.GetRow() + self._col = event.GetCol() + + # If the right-clicked node is not part of a group, then make sure that + # it is the only selected cell. + append = False + r = self._row + c = self._col + if self.gridAtoms.IsInSelection(r, c): + append = True + self.gridAtoms.SelectBlock(r, c, r, c, append) + + self.popupMenu(self.gridAtoms, event.GetPosition().x, event.GetPosition().y) + event.Skip() + return
+ + +
+[docs] + def onEditorShown(self, event): # wxGlade: PhaseConfigurePanel.<event_handler> + """Capture the focused text when the grid editor is shown.""" + i = event.GetRow() + j = event.GetCol() + self._focusedText = self.gridAtoms.GetCellValue(i, j) + # self._selectedCells = gridutils.getSelectedCells(self.gridAtoms) + # TODO: temporary show the error message for control-select. + try: + self._selectedCells = gridutils.getSelectedCells(self.gridAtoms) + except TypeError: + raise TempControlSelectError("controlselecterror") + return
+ + +
+[docs] + def onCellChange(self, event): # wxGlade: PhaseConfigurePanel.<event_handler> + """Update focused and selected text when a cell changes.""" + # NOTE: be careful with refresh(). It calls Grid.AutoSizeColumns, which + # creates a EVT_GRID_CMD_CELL_CHANGED event, which causes a recursion + # loop. + i = event.GetRow() + j = event.GetCol() + + value = self.gridAtoms.GetCellValue(i, j) + while (i, j) in self._selectedCells: + self._selectedCells.remove((i, j)) + # We need the edited cell to be at the front of the list + self._selectedCells.insert(0, (i, j)) + self.fillCells(value) + self._focusedText = None + return
+ + +
+[docs] + def fillCells(self, value): + """Fill cells with a given value. + + value -- string value to place into cells + + This uses the member variable _selectedCells, a list of (i,j) tuples for + the selected cells. + """ + for i, j in self._selectedCells: + if not self.gridAtoms.IsReadOnly(i, j): + # Get the last valid text from the cell. For the cell that triggered + # this method, that is the _focusedText, for other cells it is the + # value returned by GetCellValue + oldvalue = self._focusedText or self.gridAtoms.GetCellValue(i, j) + self._focusedText = None + newvalue = self.applyCellChange(i, j, value) + # print i, j, value, oldvalue, newvalue + if newvalue is None: + newvalue = oldvalue + self.gridAtoms.SetCellValue(i, j, str(newvalue)) + + gridutils.quickResizeColumns(self.gridAtoms, self._selectedCells) + return
+ + +
+[docs] + def onKey(self, event): + """Catch key events in the panel.""" + key = event.GetKeyCode() + + # Select All + # Ctrl A + if event.ControlDown() and key == 65: + rows = self.gridAtoms.GetNumberRows() + cols = self.gridAtoms.GetNumberCols() + self.gridAtoms.SelectBlock(0, 0, rows, cols) + + # context menu key + elif key == wx.WXK_MENU: + self.popupMenu(self.gridAtoms, event.GetPosition().x, event.GetPosition().y) + + # Vim-like search for atom selection + elif key == 47: + self.onPopupSelect(event) + + # Delete an atom + # Delete + elif key == 127: + selected = self.gridAtoms.GetSelectedRows() + if selected: + self.structure.deleteAtoms(selected) + self.refresh() + self.mainFrame.needsSave() + + # Ctrl - + elif event.ControlDown() and key == 45: + indices = gridutils.getSelectionRows(self.gridAtoms) + self.structure.deleteAtoms(indices) + self.refresh() + self.mainFrame.needsSave() + + # Append an atom + # Ctrl + or Ctrl = + elif event.ControlDown() and (key == 61 or key == 43): + indices = gridutils.getSelectionRows(self.gridAtoms) + pos = 0 + if indices: + pos = 1 + indices[-1] + elif self.structure: + pos = len(self.structure) + # insert "rows" atoms into the structure + atoms = [_defaultNewAtom()] + self.structure.insertAtoms(pos, atoms) + self.refresh() + self.mainFrame.needsSave() + + else: + event.Skip() + + return
+ + + # ######################################################################## + # Grid popup menu and handlers + +
+[docs] + def popupMenu(self, window, x, y): + """Creates the popup menu. + + window -- window, where to popup a menu + x -- x coordinate + y -- y coordinate + """ + # only do this part the first time so the events are only bound once + if not hasattr(self, "insertID"): + self.insertID = wx.NewIdRef() + self.deleteID = wx.NewIdRef() + self.selectID = wx.NewIdRef() + self.copyID = wx.NewIdRef() + self.pasteID = wx.NewIdRef() + self.supercellID = wx.NewIdRef() + self.spaceGroupID = wx.NewIdRef() + + self.Bind(wx.EVT_MENU, self.onPopupInsert, id=self.insertID) + self.Bind(wx.EVT_MENU, self.onPopupDelete, id=self.deleteID) + self.Bind(wx.EVT_MENU, self.onPopupSelect, id=self.selectID) + self.Bind(wx.EVT_MENU, self.onPopupCopy, id=self.copyID) + self.Bind(wx.EVT_MENU, self.onPopupPaste, id=self.pasteID) + self.Bind(wx.EVT_MENU, self.onPopupSupercell, id=self.supercellID) + self.Bind(wx.EVT_MENU, self.onPopupSpaceGroup, id=self.spaceGroupID) + + # make a menu + menu = wx.Menu() + + # add some other items + menu.Append(self.insertID, "&Insert atoms...") + menu.Append(self.deleteID, "&Delete atoms") + menu.AppendSeparator() + menu.Append(self.selectID, "Select &atoms...") + menu.Append(self.copyID, "&Copy") + menu.Append(self.pasteID, "&Paste") + menu.AppendSeparator() + menu.Append(self.supercellID, "Create supercell...") + menu.Append(self.spaceGroupID, "Expand space group...") + + # Disable some items if there are no atoms selected + indices = gridutils.getSelectionRows(self.gridAtoms) + if not indices: + menu.Enable(self.deleteID, False) + menu.Enable(self.spaceGroupID, False) + + # Disable some items if there is no structure + if self.structure is None or len(self.structure) == 0: + menu.Enable(self.deleteID, False) + menu.Enable(self.supercellID, False) + menu.Enable(self.spaceGroupID, False) + + # Check for copy/paste + if not phasepanelutils.canCopySelectedCells(self): + menu.Enable(self.copyID, False) + if not phasepanelutils.canPasteIntoCells(self): + menu.Enable(self.pasteID, False) + + # Popup the menu. If an item is selected then its handler + # will be called before PopupMenu returns. + window.PopupMenu(menu, wx.Point(x, y)) + menu.Destroy() + return
+ + +
+[docs] + def onPopupInsert(self, event): + """Adds rows to the grid.""" + if self.structure is not None: + dlg = InsertRowsDialog(self) + if dlg.ShowModal() == wx.ID_OK: + rows = dlg.spin_ctrl_Rows.GetValue() + + if len(self.structure) == 0: + self._row = 0 + elif dlg.radio_box_where.GetSelection() == 1: # if selected "below" + self._row += 1 + + # insert "rows" atoms into the structure + atoms = [_defaultNewAtom() for i in range(rows)] + self.structure.insertAtoms(self._row, atoms) + self.refresh() + self.mainFrame.needsSave() + + # Highlight the elements of the new rows so that they can be + # changed by the user. + self.gridAtoms.SetFocus() + self.gridAtoms.SelectBlock(self._row, 0, self._row + len(atoms) - 1, 0) + self.gridAtoms.SetGridCursor(self._row, 0) + + dlg.Destroy() + return
+ + +
+[docs] + def onPopupDelete(self, event): + """Deletes the row under mouse pointer from the grid.""" + if self.structure is not None: + indices = gridutils.getSelectionRows(self.gridAtoms) + self.structure.deleteAtoms(indices) + self.refresh() + self.mainFrame.needsSave() + return
+ + +
+[docs] + def onPopupSelect(self, event): + """Limit cell selection to specified atom selection string.""" + phasepanelutils.showSelectAtomsDialog(self) + return
+ + +
+[docs] + def onPopupCopy(self, event): + """Copy selected cells.""" + phasepanelutils.copySelectedCells(self) + return
+ + +
+[docs] + def onPopupPaste(self, event): + """Paste previously copied cells.""" + phasepanelutils.pasteIntoCells(self) + return
+ + +
+[docs] + def onPopupSupercell(self, event): + """Create a supercell with the supercell dialog.""" + from diffpy.pdfgui.gui.supercelldialog import SupercellDialog + + if self.structure is not None: + dlg = SupercellDialog(self) + if dlg.ShowModal() == wx.ID_OK: + mno = dlg.getMNO() + self.structure.expandSuperCell(mno) + self.refresh() + self.mainFrame.needsSave() + dlg.Destroy() + return
+ + +
+[docs] + def onPopupSpaceGroup(self, event): + """Create a supercell with the supercell dialog.""" + from diffpy.pdfgui.gui.sgstructuredialog import SGStructureDialog + + if self.structure is not None: + + indices = gridutils.getSelectionRows(self.gridAtoms) + dlg = SGStructureDialog(self) + dlg.mainFrame = self.mainFrame + dlg.indices = indices + dlg.setStructure(self.structure) + if dlg.ShowModal() == wx.ID_OK: + spcgrp = dlg.getSpaceGroup() + offset = dlg.getOffset() + self.structure.expandAsymmetricUnit(spcgrp, indices, offset) + self.refresh() + self.mainFrame.needsSave() + dlg.Destroy() + return
+
+ + + +# end of class PhaseConfigurePanel + +# Local helpers -------------------------------------------------------------- + + +def _defaultNewAtom(): + """Create new atom instance with non-zero initial U.""" + uii = 0.003 + rv = Atom("C", [0.0, 0.0, 0.0], U=[[uii, 0, 0], [0, uii, 0], [0, 0, uii]]) + return rv +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/phaseconstraintspanel.html b/_modules/diffpy/pdfgui/gui/phaseconstraintspanel.html new file mode 100644 index 00000000..6571ec16 --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/phaseconstraintspanel.html @@ -0,0 +1,818 @@ + + + + + + + + diffpy.pdfgui.gui.phaseconstraintspanel — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.phaseconstraintspanel

+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow, Dmitriy Bryndin
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+# generated by wxGlade 0.9.3 on Fri Jul 19 16:05:04 2019
+
+import re
+
+import wx
+import wx.grid
+
+from diffpy.pdfgui.control.constraint import Constraint
+from diffpy.pdfgui.control.controlerrors import ControlValueError
+from diffpy.pdfgui.gui import phasepanelutils, tooltips
+from diffpy.pdfgui.gui.pdfpanel import PDFPanel
+from diffpy.pdfgui.gui.sgconstraindialog import SGConstrainDialog
+from diffpy.pdfgui.gui.wxextensions.autowidthlabelsgrid import AutoWidthLabelsGrid
+from diffpy.pdfgui.gui.wxextensions.textctrlutils import textCtrlAsGridCell
+from diffpy.utils.wx import gridutils
+
+
+
+[docs] +class PhaseConstraintsPanel(wx.Panel, PDFPanel): + def __init__(self, *args, **kwds): + PDFPanel.__init__(self) + # begin wxGlade: PhaseConstraintsPanel.__init__ + kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL + wx.Panel.__init__(self, *args, **kwds) + + sizerMain = wx.BoxSizer(wx.VERTICAL) + + sizerPanelName = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.HORIZONTAL) + sizerMain.Add(sizerPanelName, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) + + self.labelPanelName = wx.StaticText(self, wx.ID_ANY, "Phase Constraints") + self.labelPanelName.SetFont( + wx.Font( + 18, + wx.FONTFAMILY_DEFAULT, + wx.FONTSTYLE_NORMAL, + wx.FONTWEIGHT_BOLD, + 0, + "", + ) + ) + sizerPanelName.Add(self.labelPanelName, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT, 5) + + sizerLatticeParameters = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.HORIZONTAL) + sizerMain.Add(sizerLatticeParameters, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) + + grid_sizer_3 = wx.FlexGridSizer(2, 6, 0, 0) + sizerLatticeParameters.Add(grid_sizer_3, 1, wx.EXPAND, 0) + + self.labelA = wx.StaticText(self, wx.ID_ANY, "a") + grid_sizer_3.Add(self.labelA, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) + + self.textCtrlA = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) + grid_sizer_3.Add(self.textCtrlA, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + self.labelB = wx.StaticText(self, wx.ID_ANY, "b") + grid_sizer_3.Add(self.labelB, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) + + self.textCtrlB = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) + grid_sizer_3.Add(self.textCtrlB, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + self.labelC = wx.StaticText(self, wx.ID_ANY, "c") + grid_sizer_3.Add(self.labelC, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) + + self.textCtrlC = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) + grid_sizer_3.Add(self.textCtrlC, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + self.labelAlpha = wx.StaticText(self, wx.ID_ANY, "alpha") + grid_sizer_3.Add(self.labelAlpha, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) + + self.textCtrlAlpha = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) + grid_sizer_3.Add(self.textCtrlAlpha, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + self.labelBeta = wx.StaticText(self, wx.ID_ANY, "beta") + grid_sizer_3.Add(self.labelBeta, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) + + self.textCtrlBeta = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) + grid_sizer_3.Add(self.textCtrlBeta, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + self.labelGamma = wx.StaticText(self, wx.ID_ANY, "gamma") + grid_sizer_3.Add(self.labelGamma, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) + + self.textCtrlGamma = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) + grid_sizer_3.Add(self.textCtrlGamma, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + sizerAdditionalParameters = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.HORIZONTAL) + sizerMain.Add(sizerAdditionalParameters, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) + + grid_sizer_4 = wx.FlexGridSizer(3, 6, 0, 0) + sizerAdditionalParameters.Add(grid_sizer_4, 1, wx.EXPAND, 0) + + self.labelScaleFactor = wx.StaticText(self, wx.ID_ANY, "Scale Factor") + grid_sizer_4.Add( + self.labelScaleFactor, + 0, + wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, + 5, + ) + + self.textCtrlScaleFactor = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) + grid_sizer_4.Add(self.textCtrlScaleFactor, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + grid_sizer_4.Add((20, 10), 0, 0, 0) + + grid_sizer_4.Add((20, 10), 0, 0, 0) + + grid_sizer_4.Add((20, 10), 0, 0, 0) + + grid_sizer_4.Add((20, 10), 0, 0, 0) + + self.labelDelta1 = wx.StaticText(self, wx.ID_ANY, "delta1") + grid_sizer_4.Add(self.labelDelta1, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) + + self.textCtrlDelta1 = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) + grid_sizer_4.Add(self.textCtrlDelta1, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + self.labelDelta2 = wx.StaticText(self, wx.ID_ANY, "delta2") + grid_sizer_4.Add(self.labelDelta2, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) + + self.textCtrlDelta2 = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) + grid_sizer_4.Add(self.textCtrlDelta2, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + self.labelSpdiameter = wx.StaticText(self, wx.ID_ANY, "spdiameter") + grid_sizer_4.Add( + self.labelSpdiameter, + 0, + wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, + 5, + ) + + self.textCtrlSpdiameter = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) + grid_sizer_4.Add(self.textCtrlSpdiameter, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + self.labelSratio = wx.StaticText(self, wx.ID_ANY, "sratio") + grid_sizer_4.Add(self.labelSratio, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) + + self.textCtrlSratio = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) + grid_sizer_4.Add(self.textCtrlSratio, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + self.labelRcut = wx.StaticText(self, wx.ID_ANY, "rcut") + grid_sizer_4.Add(self.labelRcut, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) + + self.textCtrlRcut = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER | wx.TE_READONLY) + grid_sizer_4.Add(self.textCtrlRcut, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + self.labelStepcut = wx.StaticText(self, wx.ID_ANY, "stepcut") + grid_sizer_4.Add(self.labelStepcut, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) + + self.textCtrlStepcut = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER | wx.TE_READONLY) + grid_sizer_4.Add(self.textCtrlStepcut, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + sizerAtoms = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.VERTICAL) + sizerMain.Add(sizerAtoms, 1, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) + + sizer_1 = wx.BoxSizer(wx.HORIZONTAL) + sizerAtoms.Add(sizer_1, 0, wx.EXPAND, 0) + + self.labelIncludedPairs = wx.StaticText(self, wx.ID_ANY, "Included Pairs") + sizer_1.Add(self.labelIncludedPairs, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) + + self.textCtrlIncludedPairs = wx.TextCtrl(self, wx.ID_ANY, "all-all", style=wx.TE_READONLY) + self.textCtrlIncludedPairs.SetMinSize((240, 25)) + sizer_1.Add(self.textCtrlIncludedPairs, 0, wx.ALL, 5) + + self.gridAtoms = AutoWidthLabelsGrid(self, wx.ID_ANY, size=(1, 1)) + self.gridAtoms.CreateGrid(0, 11) + self.gridAtoms.EnableDragRowSize(0) + self.gridAtoms.SetColLabelValue(0, "elem") + self.gridAtoms.SetColLabelValue(1, "x") + self.gridAtoms.SetColLabelValue(2, "y") + self.gridAtoms.SetColLabelValue(3, "z") + self.gridAtoms.SetColLabelValue(4, "u11") + self.gridAtoms.SetColLabelValue(5, "u22") + self.gridAtoms.SetColLabelValue(6, "u33") + self.gridAtoms.SetColLabelValue(7, "u12") + self.gridAtoms.SetColLabelValue(8, "u13") + self.gridAtoms.SetColLabelValue(9, "u23") + self.gridAtoms.SetColLabelValue(10, "occ") + sizerAtoms.Add(self.gridAtoms, 1, wx.EXPAND, 0) + + self.SetSizer(sizerMain) + sizerMain.Fit(self) + + self.Layout() + + self.Bind(wx.grid.EVT_GRID_CMD_CELL_CHANGED, self.onCellChange, self.gridAtoms) + self.Bind(wx.grid.EVT_GRID_CMD_CELL_RIGHT_CLICK, self.onCellRightClick, self.gridAtoms) + self.Bind(wx.grid.EVT_GRID_CMD_EDITOR_SHOWN, self.onEditorShown, self.gridAtoms) + self.Bind( + wx.grid.EVT_GRID_CMD_LABEL_RIGHT_CLICK, + self.onLabelRightClick, + self.gridAtoms, + ) + # end wxGlade + self.__customProperties() + + # ######################################################################## + # Misc Methods + + def __customProperties(self): + """Custom properties for the panel.""" + self.structure = None + self.constraints = {} + self.results = None + self._textctrls = [ + "textCtrlA", + "textCtrlB", + "textCtrlC", + "textCtrlAlpha", + "textCtrlBeta", + "textCtrlGamma", + "textCtrlScaleFactor", + "textCtrlDelta1", + "textCtrlDelta2", + "textCtrlSratio", + "textCtrlSpdiameter", + ] + self._row = 0 + self._col = 0 + self._focusedText = None + self._selectedCells = [] + # bind onSetFocus onKillFocus events to text controls + for widget in self._textctrls: + self.__dict__[widget].Bind(wx.EVT_SET_FOCUS, self.onSetFocus) + self.__dict__[widget].Bind(wx.EVT_KILL_FOCUS, self.onKillFocus) + self.__dict__[widget].Bind(wx.EVT_KEY_DOWN, self.onTextCtrlKey) + + # set up grid + self.lAtomConstraints = [ + "x", + "y", + "z", + "u11", + "u22", + "u33", + "u12", + "u13", + "u23", + "occ", + ] + # pdffit internal naming + self.lConstraints = [ + "lat(1)", + "lat(2)", + "lat(3)", + "lat(4)", + "lat(5)", + "lat(6)", + "pscale", + "delta1", + "delta2", + "sratio", + "spdiameter", + ] + textCtrlIds = [getattr(self, n).GetId() for n in self._textctrls] + self._id2varname = dict(zip(textCtrlIds, self.lConstraints)) + + # Define tooltips. + self.setToolTips(tooltips.phasepanel) + + # NOTE: GridCellAttr is reference counted. + # Each call of SetX(attr) decreases its reference count. + # We need to call attr.IncRef before each SetX(attr) + # https://github.com/wxWidgets/Phoenix/issues/627#issuecomment-354219493 + + # set 'elem' abd 'name' columns to read-only + attr = wx.grid.GridCellAttr() + attr.SetReadOnly(True) + attr.IncRef() + self.gridAtoms.SetColAttr(0, attr) + attr.IncRef() + self.gridAtoms.SetColAttr(11, attr) + # drop local reference to `attr` as it was constructed here. + attr.DecRef() + + # catch key events and apply them to the grid + self.Bind(wx.EVT_KEY_DOWN, self.onKey) + + # Hide some stuff + self.labelRcut.Hide() + self.textCtrlRcut.Hide() + self.labelStepcut.Hide() + self.textCtrlStepcut.Hide() + return + + # Create the onTextCtrlKey event handler from textCtrlAsGridCell from + # wxextensions.textctrlutils + onTextCtrlKey = textCtrlAsGridCell + + def _cache(self): + """Cache the current structure and constraints for future + comparison.""" + pass + +
+[docs] + def refresh(self): + """Refresh wigets on the panel.""" + if self.structure is None: + raise ValueError("structure is not defined.") + + self.refreshTextCtrls() + + # # update the grid ### + natoms = len(self.structure) + nrows = self.gridAtoms.GetNumberRows() + self.gridAtoms.BeginBatch() + # make sure grid has correct number of rows + if natoms > nrows: + self.gridAtoms.InsertRows(numRows=natoms - nrows) + elif natoms < nrows: + self.gridAtoms.DeleteRows(numRows=nrows - natoms) + + # start with clean grid + self.gridAtoms.ClearGrid() + + # fill the first 'elem' column with element symbols + for row, atom in zip(range(natoms), self.structure): + self.gridAtoms.SetCellValue(row, 0, atom.element) + + # update constraints + bareAtomVarColumn = dict(zip(self.lAtomConstraints, range(1, 1 + len(self.lAtomConstraints)))) + avpat = re.compile(r"(\w+)\((\d+)\)$") + for var, con in self.constraints.items(): + m = avpat.match(var) + if not m: + continue + barevar = m.group(1) + if barevar not in bareAtomVarColumn: + continue + column = bareAtomVarColumn[barevar] + row = int(m.group(2)) - 1 + if not 0 <= row < natoms: + emsg = "Invalid variable index for %r" % var + raise ControlValueError(emsg) + self.gridAtoms.SetCellValue(row, column, con.formula) + barevar = re.sub(r"\(\d+\)$", "", var) + if barevar not in bareAtomVarColumn: + continue + + self.gridAtoms.AutosizeLabels() + self.gridAtoms.AutoSizeColumns() + self.gridAtoms.EndBatch() + + self.gridAtoms.AdjustScrollbars() + self.gridAtoms.ForceRefresh() + return
+ + +
+[docs] + def refreshTextCtrls(self): + """Refreshes the TextCtrls.""" + + for widget, var in zip(self._textctrls, self.lConstraints): + wobj = getattr(self, widget) + if var in self.constraints: + s = self.constraints[var].formula + else: + s = "" + wobj.SetValue(s) + + pairs = self.structure.getSelectedPairs() + self.textCtrlIncludedPairs.SetValue(pairs) + return
+ + +
+[docs] + def applyTextCtrlChange(self, id, value): + """Update a structure according to a change in a TextCtrl. + + id -- textctrl id + value -- new value + """ + self.mainFrame.needsSave() + var = self._id2varname[id] + formula = value.strip() + if formula != "": + self.constraints[var] = Constraint(formula) + return self.constraints[var].formula + else: + self.constraints.pop(var, None) + return ""
+ + +
+[docs] + def applyCellChange(self, i, j, value): + """Update an atom according to a change in a cell. + + i -- cell position + j -- cell position + value -- new value + + returns the new value stored in the data object, or None if value is + somehow invalid. + """ + self.mainFrame.needsSave() + key = self.lAtomConstraints[j - 1] + "({})".format(i + 1) + formula = value.strip() + if formula != "": + self.constraints[key] = Constraint(formula) + return self.constraints[key].formula + else: + self.constraints.pop(key, None) + return "" + return
+ + + # ######################################################################## + # Event Handlers + + # TextCtrl Events +
+[docs] + def onSetFocus(self, event): + """Saves a TextCtrl value, to be compared in onKillFocuse later.""" + self._focusedText = event.GetEventObject().GetValue() + event.Skip() + return
+ + +
+[docs] + def onKillFocus(self, event): + """Check value of TextCtrl and update structure if necessary.""" + event.Skip() + if not self.mainFrame: + return + textctrl = event.GetEventObject() + value = textctrl.GetValue() + if value != self._focusedText: + self.applyTextCtrlChange(textctrl.GetId(), value) + self.refreshTextCtrls() + self.mainFrame.needsSave() + self._focusedText = None + return
+ + + # Grid Events +
+[docs] + def onLabelRightClick(self, event): # wxGlade: PhaseConstraintsPanel.<event_handler> + """Bring up right-click menu.""" + if self.structure is not None: + dx = dy = 0 + if event.GetRow() == -1: + dy = self.gridAtoms.GetGridCornerLabelWindow().GetSize().y + if event.GetCol() == -1: + dx = self.gridAtoms.GetGridCornerLabelWindow().GetSize().x + + # do not popup menu if the whole grid is set to read only + if len(self.structure) == 0: + self.popupMenu( + self.gridAtoms, + event.GetPosition().x - dx, + event.GetPosition().y - dy, + ) + event.Skip() + return
+ + +
+[docs] + def onCellRightClick(self, event): # wxGlade: PhaseConstraintsPanel.<event_handler> + """Bring up right-click menu.""" + self._row = event.GetRow() + self._col = event.GetCol() + + # If the right-clicked node is not part of a group, then make sure that + # it is the only selected cell. + append = False + r = self._row + c = self._col + if self.gridAtoms.IsInSelection(r, c): + append = True + self.gridAtoms.SelectBlock(r, c, r, c, append) + + self.popupMenu(self.gridAtoms, event.GetPosition().x, event.GetPosition().y) + event.Skip() + return
+ + +
+[docs] + def onEditorShown(self, event): # wxGlade: PhaseConstraintsPanel.<event_handler> + """Capture the focused text when the grid editor is shown.""" + i = event.GetRow() + j = event.GetCol() + self._focusedText = self.gridAtoms.GetCellValue(i, j) + self._selectedCells = gridutils.getSelectedCells(self.gridAtoms) + return
+ + +
+[docs] + def onCellChange(self, event): # wxGlade: PhaseConstraintsPanel.<event_handler> + """Update focused and selected text when a cell changes.""" + # NOTE: be careful with refresh(). It calls Grid.AutoSizeColumns, which + # creates a EVT_GRID_CMD_CELL_CHANGED event, which causes a recursion + # loop. + i = event.GetRow() + j = event.GetCol() + + value = self.gridAtoms.GetCellValue(i, j) + while (i, j) in self._selectedCells: + self._selectedCells.remove((i, j)) + # We need the edited cell to be at the front of the list + self._selectedCells.insert(0, (i, j)) + self.fillCells(value) + self._focusedText = None + return
+ + +
+[docs] + def fillCells(self, value): + """Fill cells with a given value. + + value -- string value to place into cells + + This uses the member variable _selectedCells, a list of (i,j) tuples for + the selected cells. + """ + for i, j in self._selectedCells: + if not self.gridAtoms.IsReadOnly(i, j): + # Get the last valid text from the cell. For the cell that triggered + # this method, that is the _focusedText, for other cells it is the + # value returned by GetCellValue + oldvalue = self._focusedText + if oldvalue is None: + oldvalue = self.gridAtoms.GetCellValue(i, j) + self._focusedText = None + newvalue = self.applyCellChange(i, j, value) + # print i, j, value, oldvalue, newvalue + if newvalue is None: + # Get out of here. If the value is invalid, it won't be valid + # for any cells. + newvalue = oldvalue + self.gridAtoms.SetCellValue(i, j, str(newvalue)) + break + else: + self.gridAtoms.SetCellValue(i, j, str(newvalue)) + + gridutils.quickResizeColumns(self.gridAtoms, self._selectedCells) + return
+ + +
+[docs] + def onKey(self, event): + """Catch key events in the panel.""" + key = event.GetKeyCode() + + # Select All - Ctrl+A + if event.ControlDown() and key == 65: + rows = self.gridAtoms.GetNumberRows() + cols = self.gridAtoms.GetNumberCols() + self.gridAtoms.SelectBlock(0, 0, rows, cols) + + # context menu key + elif key == wx.WXK_MENU: + self.popupMenu(self.gridAtoms, event.GetPosition().x, event.GetPosition().y) + + # Vim-like search for atom selection + elif key == 47: + self.onPopupSelect(event) + + # Delete + elif key == 127: + self._selectedCells = gridutils.getSelectedCells(self.gridAtoms) + self.fillCells("") + self.mainFrame.needsSave() + + # Can't get these to work. Maybe later. + # Copy - Ctrl+C / Ctrl+Insert + # if event.ControlDown() and (key == 67 or key == wx.WXK_INSERT): + # if phasepanelutils.canCopySelectedCells(self): + # phasepanelutils.copySelectedCells(self) + + # Paste - Ctrl+V / Shift+Insert + # if (event.ControlDown() and key == 86) or\ + # (event.ShiftDown() and key == wx.WXK_INSERT): + # if phasepanelutils.canPasteIntoCells(self): + # phasepanelutils.pasteIntoCells(self) + + else: + event.Skip() + return
+ + + # ######################################################################## + # Grid popup menu and handlers + +
+[docs] + def popupMenu(self, window, x, y): + """Creates the popup menu. + + window -- window, where to popup a menu + x -- x coordinate + y -- y coordinate + """ + # only do this part the first time so the events are only bound once + if not hasattr(self, "spaceGroupID"): + self.spaceGroupID = wx.NewIdRef() + self.selectID = wx.NewIdRef() + self.copyID = wx.NewIdRef() + self.pasteID = wx.NewIdRef() + + self.Bind(wx.EVT_MENU, self.onPopupSpaceGroup, id=self.spaceGroupID) + self.Bind(wx.EVT_MENU, self.onPopupSelect, id=self.selectID) + self.Bind(wx.EVT_MENU, self.onPopupCopy, id=self.copyID) + self.Bind(wx.EVT_MENU, self.onPopupPaste, id=self.pasteID) + + # make a menu + menu = wx.Menu() + + # add some other items + menu.Append(self.spaceGroupID, "&Symmetry constraints...") + menu.AppendSeparator() + menu.Append(self.selectID, "Select &atoms...") + menu.Append(self.copyID, "&Copy") + menu.Append(self.pasteID, "&Paste") + + # Disable some items if there are no atoms selected + indices = gridutils.getSelectionRows(self.gridAtoms) + if not indices: + menu.Enable(self.spaceGroupID, False) + + # Check for copy/paste + if not phasepanelutils.canCopySelectedCells(self): + menu.Enable(self.copyID, False) + if not phasepanelutils.canPasteIntoCells(self): + menu.Enable(self.pasteID, False) + + # Popup the menu. If an item is selected then its handler + # will be called before PopupMenu returns. + window.PopupMenu(menu, wx.Point(x, y)) + menu.Destroy() + return
+ + +
+[docs] + def onPopupSpaceGroup(self, event): + """Create a supercell with the supercell dialog.""" + if self.structure is not None: + + indices = gridutils.getSelectionRows(self.gridAtoms) + dlg = SGConstrainDialog(self) + dlg.mainFrame = self.mainFrame + dlg.indices = indices + dlg.setStructure(self.structure) + dlg.updateWidgets() + if dlg.ShowModal() == wx.ID_OK: + spcgrp = dlg.getSpaceGroup() + offset = dlg.getOffset() + posflag = dlg.getPosFlag() + tempflag = dlg.getTempFlag() + self.structure.applySymmetryConstraints(spcgrp, indices, posflag, tempflag, offset) + self.refresh() + dlg.Destroy() + self.mainFrame.needsSave() + return
+ + +
+[docs] + def onPopupSelect(self, event): + """Limit cell selection to specified atom selection string.""" + phasepanelutils.showSelectAtomsDialog(self) + return
+ + +
+[docs] + def onPopupCopy(self, event): + """Copy selected cells.""" + phasepanelutils.copySelectedCells(self) + return
+ + +
+[docs] + def onPopupPaste(self, event): + """Paste previously copied cells.""" + phasepanelutils.pasteIntoCells(self) + return
+
+ + + +# end of class PhaseConstraintsPanel +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/phasenotebookpanel.html b/_modules/diffpy/pdfgui/gui/phasenotebookpanel.html new file mode 100644 index 00000000..f00ccf39 --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/phasenotebookpanel.html @@ -0,0 +1,233 @@ + + + + + + + + diffpy.pdfgui.gui.phasenotebookpanel — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.phasenotebookpanel

+#!/usr/bin/env python
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Dmitriy Bryndin
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+#
+# Phase notebook panel
+#
+# Just a notebook, holds three panels:  "Configure", "Constraints", "Results"
+#
+# Dmitriy Bryndin
+
+
+import wx
+
+from diffpy.pdfgui.gui.pdfpanel import PDFPanel
+from diffpy.pdfgui.gui.phaseconfigurepanel import PhaseConfigurePanel
+from diffpy.pdfgui.gui.phaseconstraintspanel import PhaseConstraintsPanel
+from diffpy.pdfgui.gui.phaseresultspanel import PhaseResultsPanel
+
+
+
+[docs] +class PhaseNotebookPanel(wx.Panel, PDFPanel): + def __init__(self, *args, **kwds): + PDFPanel.__init__(self) + kwds["style"] = wx.TAB_TRAVERSAL + wx.Panel.__init__(self, *args, **kwds) + self.notebook_phase = wx.Notebook(self, -1, style=0) + self.notebook_phase_pane_Configure = PhaseConfigurePanel(self.notebook_phase, -1) + self.notebook_phase_pane_Constraints = PhaseConstraintsPanel(self.notebook_phase, -1) + self.notebook_phase_pane_Results = PhaseResultsPanel(self.notebook_phase, -1) + + self.__set_properties() + self.__do_layout() + + self.notebook_phase.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.onNotebookPageChanged) + self.notebook_phase.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGING, self.onNotebookPageChanging) + + self.configuration = None + self.constraints = {} + self.results = None + self.mainFrame = None + self.focusedId = 0 + + def __set_properties(self): + pass + + def __do_layout(self): + sizer_1 = wx.BoxSizer(wx.HORIZONTAL) + self.notebook_phase.AddPage(self.notebook_phase_pane_Configure, "Configure") + self.notebook_phase.AddPage(self.notebook_phase_pane_Constraints, "Constraints") + self.notebook_phase.AddPage(self.notebook_phase_pane_Results, "Results") + sizer_1.Add(self.notebook_phase, 1, wx.EXPAND, 0) + self.SetAutoLayout(True) + self.SetSizer(sizer_1) + sizer_1.Fit(self) + sizer_1.SetSizeHints(self) + +
+[docs] + def refresh(self): + """Refreshes the currently shown panel.""" + if self.mainFrame.quitting: + return + if self.focusedId == -1: + return + + panel = self.notebook_phase.GetPage(self.focusedId) + + panel.structure = self.configuration + panel.constraints = self.constraints + panel.results = self.results + + # This has to be done here, because this panel does not know who it + # belongs to until after it is instantiated. + panel.mainFrame = self.mainFrame + panel.refresh() + return
+ + +
+[docs] + def onNotebookPageChanging(self, event): + """Called during the page selection change.""" + # focusedId = event.GetOldSelection() + panel = self.notebook_phase.GetPage(self.focusedId) + panel._cache() + return
+ + +
+[docs] + def onNotebookPageChanged(self, event): + """Called after the page selection is changed.""" + self.focusedId = event.GetSelection() + self.refresh() + event.Skip() + return
+ + + # Overloaded from Panel. +
+[docs] + def Enable(self, enable=True): + """Keep the notebook enabled, just not the panels.""" + self.notebook_phase_pane_Configure.Enable(enable) + self.notebook_phase_pane_Constraints.Enable(enable) + self.notebook_phase_pane_Results.Enable(enable) + return
+
+ + + +# end of class PhaseNotebookPanel + +# End of file +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/phasepanelutils.html b/_modules/diffpy/pdfgui/gui/phasepanelutils.html new file mode 100644 index 00000000..89e317b5 --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/phasepanelutils.html @@ -0,0 +1,470 @@ + + + + + + + + diffpy.pdfgui.gui.phasepanelutils — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.phasepanelutils

+#!/usr/bin/env python
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+"""Common methods used in the phase panels."""
+
+import wx
+
+from diffpy.utils.wx import gridutils
+
+# List of row entries taken from the clipboard
+clipcells = []
+
+# String describing what atoms should be selected.
+selected_atoms = ""
+
+
+
+[docs] +def float2str(x): + """Compact string representation of float.""" + s = "%g" % x + if s.find(".") == -1 and s.find("e") == -1: + s = s + ".0" + return s
+ + + +
+[docs] +def refreshTextCtrls(panel): + """Refreshes the TextCtrls on the panel. + + This is used by phaseconfigurepanel and phaseresultspanel. + + This method updates the following TextCtrls with with contents of + the structure member variable of the panel. textCtrlA textCtrlB + textCtrlC textCtrlAlpha textCtrlBeta textCtrlGamma + textCtrlScaleFactor textCtrlDelta1 textCtrlDelta2 textCtrlSratio + textCtrlRcut textCtrlStepcut textCtrlSpdiameter + """ + if panel.structure is None: + # clear textcontrols + panel.textCtrlA.SetValue("") + panel.textCtrlB.SetValue("") + panel.textCtrlC.SetValue("") + panel.textCtrlAlpha.SetValue("") + panel.textCtrlBeta.SetValue("") + panel.textCtrlGamma.SetValue("") + panel.textCtrlScaleFactor.SetValue("") + panel.textCtrlDelta1.SetValue("") + panel.textCtrlDelta2.SetValue("") + panel.textCtrlSratio.SetValue("") + panel.textCtrlRcut.SetValue("") + panel.textCtrlStepcut.SetValue("") + panel.textCtrlSpdiameter.SetValue("") + + else: + # update panel with values from panel.structure + # update textctrls + panel.textCtrlA.SetValue(float2str(panel.structure.lattice.a)) + panel.textCtrlB.SetValue(float2str(panel.structure.lattice.b)) + panel.textCtrlC.SetValue(float2str(panel.structure.lattice.c)) + panel.textCtrlAlpha.SetValue(float2str(panel.structure.lattice.alpha)) + panel.textCtrlBeta.SetValue(float2str(panel.structure.lattice.beta)) + panel.textCtrlGamma.SetValue(float2str(panel.structure.lattice.gamma)) + panel.textCtrlScaleFactor.SetValue(float2str(panel.structure.pdffit["scale"])) + panel.textCtrlDelta1.SetValue(float2str(panel.structure.pdffit["delta1"])) + panel.textCtrlDelta2.SetValue(float2str(panel.structure.pdffit["delta2"])) + panel.textCtrlSratio.SetValue(float2str(panel.structure.pdffit["sratio"])) + panel.textCtrlRcut.SetValue(float2str(panel.structure.pdffit["rcut"])) + panel.textCtrlStepcut.SetValue(float2str(panel.structure.pdffit["stepcut"])) + panel.textCtrlSpdiameter.SetValue(float2str(panel.structure.pdffit["spdiameter"])) + return
+ + + +
+[docs] +def refreshGrid(panel): + """Refreshes grid on the panel. + + This is used by phaseconfigurepanel and phaseresultspanel. + + This method fills the grid with the contents of the structure member + variable of the panel. It is expected that the grid is named + 'gridAtoms'. + """ + if panel.structure is None: + # remove all rows from grid + panel.gridAtoms.BeginBatch() + if panel.gridAtoms.GetNumberRows() != 0: + panel.gridAtoms.DeleteRows(numRows=panel.gridAtoms.GetNumberRows()) + panel.gridAtoms.EndBatch() + + else: + # update the grid with atoms + panel.gridAtoms.BeginBatch() + + # set column labels + panel.gridAtoms.SetColLabelValue(0, "elem") + panel.gridAtoms.SetColLabelValue(1, "x") + panel.gridAtoms.SetColLabelValue(2, "y") + panel.gridAtoms.SetColLabelValue(3, "z") + panel.gridAtoms.SetColLabelValue(4, "u11") + panel.gridAtoms.SetColLabelValue(5, "u22") + panel.gridAtoms.SetColLabelValue(6, "u33") + panel.gridAtoms.SetColLabelValue(7, "u12") + panel.gridAtoms.SetColLabelValue(8, "u13") + panel.gridAtoms.SetColLabelValue(9, "u23") + panel.gridAtoms.SetColLabelValue(10, "occ") + + # make sure grid has correct number of rows and blank it + natoms = len(panel.structure) + nrows = panel.gridAtoms.GetNumberRows() + if natoms > nrows: + panel.gridAtoms.InsertRows(numRows=natoms - nrows) + elif natoms < nrows: + panel.gridAtoms.DeleteRows(numRows=nrows - natoms) + panel.gridAtoms.ClearGrid() + for i, atom in enumerate(panel.structure): + panel.gridAtoms.SetCellValue(i, 0, str(atom.element)) # element + panel.gridAtoms.SetCellValue(i, 1, float2str(atom.xyz[0])) # x + panel.gridAtoms.SetCellValue(i, 2, float2str(atom.xyz[1])) # y + panel.gridAtoms.SetCellValue(i, 3, float2str(atom.xyz[2])) # z + panel.gridAtoms.SetCellValue(i, 4, float2str(atom.U[0, 0])) # U(1,1) + panel.gridAtoms.SetCellValue(i, 5, float2str(atom.U[1, 1])) # U(2,2) + panel.gridAtoms.SetCellValue(i, 6, float2str(atom.U[2, 2])) # U(3,3) + panel.gridAtoms.SetCellValue(i, 7, float2str(atom.U[0, 1])) # U(1,2) + panel.gridAtoms.SetCellValue(i, 8, float2str(atom.U[0, 2])) # U(1,3) + panel.gridAtoms.SetCellValue(i, 9, float2str(atom.U[1, 2])) # U(2,3) + panel.gridAtoms.SetCellValue(i, 10, float2str(atom.occupancy)) # occupancy + + panel.gridAtoms.AutosizeLabels() + panel.gridAtoms.AutoSizeColumns() + panel.gridAtoms.EndBatch() + + panel.gridAtoms.AdjustScrollbars() + return
+ + + +# Utility functions + + +
+[docs] +def showSelectAtomsDialog(panel): + """Extend or limit selection to a string atom selection. + + panel -- instance of PhaseConfigurePanel or PhaseConstraintsPanel + + No return value. + """ + # do nothing for non-existent or empty structure + if not panel.structure: + return + msg = "\n".join( + [ + 'Specify index, symbol or "all", use "!" to subtract selection.', + 'Examples: "Na", "1:4, 6, 9:10", "all, !Na".', + ] + ) + global selected_atoms + dlg = wx.TextEntryDialog(panel, msg, "Select Atoms", selected_atoms) + if dlg.ShowModal() == wx.ID_OK: + s1 = dlg.GetValue().strip() + rows = panel.structure.getSelectedIndices(s1) + selected_atoms = s1 + if s1: + gridutils.limitSelectionToRows(panel.gridAtoms, rows) + dlg.Destroy() + return
+ + + +
+[docs] +def canCopySelectedCells(panel): + """Check to see if we can copy selected cells. + + To be copyable, the cells must exist in a single block or there must + be a single cell selected. Note that a block that is selected by + individual cells is considered a collection of individual atoms, not + a block. This is default wxPython behavior. + """ + grid = panel.gridAtoms + + topleft = grid.GetSelectionBlockTopLeft() + individuals = grid.GetSelectedCells() + numsel = len(topleft) + len(individuals) + return numsel == 1
+ + + +
+[docs] +def canPasteIntoCells(panel): + """Check if clipboard contents are formatted for grid insertion. + + This also checks to see if the cell selection is appropriate for + pasting. + """ + grid = panel.gridAtoms + + individuals = grid.GetSelectedCells() + topleft = grid.GetSelectionBlockTopLeft() + if len(individuals) + len(topleft) != 1: + return False + + # Get the text + if not wx.TheClipboard.IsSupported(wx.DataFormat(wx.DF_TEXT)): + return False + + textdata = wx.TextDataObject() + if not wx.TheClipboard.IsOpened(): + opened = wx.TheClipboard.Open() + if not opened: + return False + success = wx.TheClipboard.GetData(textdata) + wx.TheClipboard.Close() + if not success: + return False + copytext = textdata.GetText() + + # Remove any trailing newline + copytext = copytext.rstrip("\n") + + # Make sure it is of the appropriate format + try: + rowlist = copytext.split("\n") + # Strip any trailing tabs + rowlist = [r.rstrip("\t") for r in rowlist] + celllist = [r.split("\t") for r in rowlist] + except wx.PyDeadObjectError: + return False + + if len(celllist) == 0: + return False + ncol = len(celllist[0]) + for row in celllist: + if len(row) != ncol: + return False + if ncol == 0: + return False + + global clipcells + clipcells = celllist + return True
+ + + +
+[docs] +def copySelectedCells(panel): + """Copy block of selected cells or individual cell into clipboard. + + This stores the cells as a plain text grid so that it can be copied + to and from other applications. Columns are delimited by tabs '\t'. + Rows are delimited by newlines '\n'. + """ + grid = panel.gridAtoms + copytext = "" + + # Get the cells + individuals = grid.GetSelectedCells() + topleft = grid.GetSelectionBlockTopLeft() + bottomright = grid.GetSelectionBlockBottomRight() + + if len(individuals) == 1: + copytext = str(grid.GetCellValue(individuals[0])) + + elif len(topleft) == 1: + # Format the block of cells + rtl = topleft[0][0] + ctl = topleft[0][1] + rbr = bottomright[0][0] + cbr = bottomright[0][1] + + for row in range(rtl, rbr + 1): + for col in range(ctl, cbr + 1): + copytext += str(grid.GetCellValue(row, col)) + copytext += "\t" + copytext += "\n" + + # Place the copytext into the clipboard + if not wx.TheClipboard.IsOpened(): + opened = wx.TheClipboard.Open() + if not opened: + raise IOError("Cannot open the clipboard.") + textdata = wx.TextDataObject(copytext) + wx.TheClipboard.SetData(textdata) + wx.TheClipboard.Close() + return
+ + + +
+[docs] +def pasteIntoCells(panel): + """Paste clipboard contents into cells. + + canPasteIntoCells must be called before this method in order to + format clipboard text for pasting. + """ + # Double check the clipcells + if len(clipcells) == 0: + return + if len(clipcells[0]) == 0: + return + + grid = panel.gridAtoms + individuals = grid.GetSelectedCells() + topleft = grid.GetSelectionBlockTopLeft() + if len(individuals) > 0: + tl = individuals[0] + elif len(topleft) > 0: + tl = topleft[0] + else: + return + rtl = tl[0] + ctl = tl[1] + + nrows = grid.GetNumberRows() + ncols = grid.GetNumberCols() + + rbr = min(nrows, rtl + len(clipcells)) - 1 + cbr = min(ncols, ctl + len(clipcells[0])) - 1 + + selections = [] + for row in range(rtl, rbr + 1): + for col in range(ctl, cbr + 1): + if not grid.IsReadOnly(row, col): + oldvalue = panel.gridAtoms.GetCellValue(row, col) + newvalue = panel.applyCellChange(row, col, clipcells[row - rtl][col - ctl]) + if newvalue is None: + newvalue = oldvalue + panel.gridAtoms.SetCellValue(row, col, str(newvalue)) + selections.append((row, col)) + + gridutils.quickResizeColumns(panel.gridAtoms, selections) + + # Clear the grid and select the inserted entries + grid.ClearSelection() + # panel.refresh() + for row in range(rtl, rbr + 1): + for col in range(ctl, cbr + 1): + if not grid.IsReadOnly(row, col): + grid.SelectBlock(row, col, row, col, True) + return
+ + + +# End of file +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/phaseresultspanel.html b/_modules/diffpy/pdfgui/gui/phaseresultspanel.html new file mode 100644 index 00000000..2a52abde --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/phaseresultspanel.html @@ -0,0 +1,343 @@ + + + + + + + + diffpy.pdfgui.gui.phaseresultspanel — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.phaseresultspanel

+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow, Dmitriy Bryndin
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+# generated by wxGlade 0.9.3 on Fri Jul 19 16:05:14 2019
+
+
+import wx
+import wx.grid
+
+from diffpy.pdfgui.gui import phasepanelutils, tooltips
+from diffpy.pdfgui.gui.pdfpanel import PDFPanel
+from diffpy.pdfgui.gui.wxextensions.autowidthlabelsgrid import AutoWidthLabelsGrid
+
+
+
+[docs] +class PhaseResultsPanel(wx.Panel, PDFPanel): + """GUI Panel, holds phase (structure) related constraints.""" + + def __init__(self, *args, **kwds): + PDFPanel.__init__(self) + # begin wxGlade: PhaseResultsPanel.__init__ + kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL + wx.Panel.__init__(self, *args, **kwds) + + sizerMain = wx.BoxSizer(wx.VERTICAL) + + sizerPanelName = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.HORIZONTAL) + sizerMain.Add(sizerPanelName, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) + + self.labelPanelName = wx.StaticText(self, wx.ID_ANY, "Phase Results") + self.labelPanelName.SetFont( + wx.Font( + 18, + wx.FONTFAMILY_DEFAULT, + wx.FONTSTYLE_NORMAL, + wx.FONTWEIGHT_BOLD, + 0, + "", + ) + ) + sizerPanelName.Add(self.labelPanelName, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT, 5) + + sizerLatticeParameters = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.HORIZONTAL) + sizerMain.Add(sizerLatticeParameters, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) + + grid_sizer_3 = wx.FlexGridSizer(2, 6, 0, 0) + sizerLatticeParameters.Add(grid_sizer_3, 1, wx.EXPAND, 0) + + self.labelA = wx.StaticText(self, wx.ID_ANY, "a") + grid_sizer_3.Add(self.labelA, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) + + self.textCtrlA = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) + grid_sizer_3.Add(self.textCtrlA, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + self.labelB = wx.StaticText(self, wx.ID_ANY, "b") + grid_sizer_3.Add(self.labelB, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) + + self.textCtrlB = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) + grid_sizer_3.Add(self.textCtrlB, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + self.labelC = wx.StaticText(self, wx.ID_ANY, "c") + grid_sizer_3.Add(self.labelC, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) + + self.textCtrlC = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) + grid_sizer_3.Add(self.textCtrlC, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + self.labelAlpha = wx.StaticText(self, wx.ID_ANY, "alpha") + grid_sizer_3.Add(self.labelAlpha, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) + + self.textCtrlAlpha = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) + grid_sizer_3.Add(self.textCtrlAlpha, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + self.labelBeta = wx.StaticText(self, wx.ID_ANY, "beta") + grid_sizer_3.Add(self.labelBeta, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) + + self.textCtrlBeta = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) + grid_sizer_3.Add(self.textCtrlBeta, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + self.labelGamma = wx.StaticText(self, wx.ID_ANY, "gamma") + grid_sizer_3.Add(self.labelGamma, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) + + self.textCtrlGamma = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) + grid_sizer_3.Add(self.textCtrlGamma, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + sizerAdditionalParameters = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.HORIZONTAL) + sizerMain.Add(sizerAdditionalParameters, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) + + grid_sizer_4 = wx.FlexGridSizer(3, 6, 0, 0) + sizerAdditionalParameters.Add(grid_sizer_4, 1, wx.EXPAND, 0) + + self.labelScaleFactor = wx.StaticText(self, wx.ID_ANY, "Scale Factor") + grid_sizer_4.Add( + self.labelScaleFactor, + 0, + wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, + 5, + ) + + self.textCtrlScaleFactor = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) + grid_sizer_4.Add(self.textCtrlScaleFactor, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + grid_sizer_4.Add((20, 10), 0, 0, 0) + + grid_sizer_4.Add((20, 10), 0, 0, 0) + + grid_sizer_4.Add((20, 10), 0, 0, 0) + + grid_sizer_4.Add((20, 10), 0, 0, 0) + + self.labelDelta1 = wx.StaticText(self, wx.ID_ANY, "delta1") + grid_sizer_4.Add(self.labelDelta1, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) + + self.textCtrlDelta1 = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) + grid_sizer_4.Add(self.textCtrlDelta1, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + self.labelDelta2 = wx.StaticText(self, wx.ID_ANY, "delta2") + grid_sizer_4.Add(self.labelDelta2, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) + + self.textCtrlDelta2 = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) + grid_sizer_4.Add(self.textCtrlDelta2, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + self.labelSpdiameter = wx.StaticText(self, wx.ID_ANY, "spdiameter") + grid_sizer_4.Add( + self.labelSpdiameter, + 0, + wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, + 5, + ) + + self.textCtrlSpdiameter = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) + grid_sizer_4.Add(self.textCtrlSpdiameter, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + self.labelSratio = wx.StaticText(self, wx.ID_ANY, "sratio") + grid_sizer_4.Add(self.labelSratio, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) + + self.textCtrlSratio = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) + grid_sizer_4.Add(self.textCtrlSratio, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + self.labelRcut = wx.StaticText(self, wx.ID_ANY, "rcut") + grid_sizer_4.Add(self.labelRcut, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) + + self.textCtrlRcut = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) + grid_sizer_4.Add(self.textCtrlRcut, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + self.labelStepcut = wx.StaticText(self, wx.ID_ANY, "stepcut") + grid_sizer_4.Add(self.labelStepcut, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) + + self.textCtrlStepcut = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) + grid_sizer_4.Add(self.textCtrlStepcut, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) + + sizerAtoms = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.VERTICAL) + sizerMain.Add(sizerAtoms, 1, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) + + sizer_1 = wx.BoxSizer(wx.HORIZONTAL) + sizerAtoms.Add(sizer_1, 0, wx.EXPAND, 0) + + self.labelIncludedPairs = wx.StaticText(self, wx.ID_ANY, "Included Pairs") + sizer_1.Add(self.labelIncludedPairs, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) + + self.textCtrlIncludedPairs = wx.TextCtrl(self, wx.ID_ANY, "all-all", style=wx.TE_READONLY) + self.textCtrlIncludedPairs.SetMinSize((240, 25)) + sizer_1.Add(self.textCtrlIncludedPairs, 0, wx.ALL, 5) + + self.gridAtoms = AutoWidthLabelsGrid(self, wx.ID_ANY, size=(1, 1)) + self.gridAtoms.CreateGrid(0, 11) + self.gridAtoms.EnableEditing(0) + self.gridAtoms.EnableDragRowSize(0) + self.gridAtoms.SetColLabelValue(0, "elem") + self.gridAtoms.SetColLabelValue(1, "x") + self.gridAtoms.SetColLabelValue(2, "y") + self.gridAtoms.SetColLabelValue(3, "z") + self.gridAtoms.SetColLabelValue(4, "u11") + self.gridAtoms.SetColLabelValue(5, "u22") + self.gridAtoms.SetColLabelValue(6, "u33") + self.gridAtoms.SetColLabelValue(7, "u12") + self.gridAtoms.SetColLabelValue(8, "u13") + self.gridAtoms.SetColLabelValue(9, "u23") + self.gridAtoms.SetColLabelValue(10, "occ") + sizerAtoms.Add(self.gridAtoms, 1, wx.EXPAND, 0) + + self.SetSizer(sizerMain) + sizerMain.Fit(self) + + self.Layout() + # end wxGlade + self.__customProperties() + return + + # ######################################################################## + # Misc Methods + + def __customProperties(self): + """Custom properties for the panel.""" + # The resulting structure + self.structure = None + self.constraints = {} + self.results = None + # Define tooltips. + self.setToolTips(tooltips.phasepanel) + return + + def _cache(self): + """Cache the current structure and constraints for future + comparison.""" + pass + +
+[docs] + def refresh(self): + """Refreshes wigets on the panel.""" + # This makes the right thing happen in phasepanelutils. It saves a lot + # of coding. + pairs = self.structure.getSelectedPairs() + self.textCtrlIncludedPairs.SetValue(pairs) + self.structure = self.results + phasepanelutils.refreshTextCtrls(self) + phasepanelutils.refreshGrid(self) + return
+
+ + + +# end of class PhaseResultsPanel +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/plotpanel.html b/_modules/diffpy/pdfgui/gui/plotpanel.html new file mode 100644 index 00000000..e10944b6 --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/plotpanel.html @@ -0,0 +1,406 @@ + + + + + + + + diffpy.pdfgui.gui.plotpanel — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for diffpy.pdfgui.gui.plotpanel

+#!/usr/bin/env python
+# -*- coding: ISO-8859-1 -*-
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+# generated by wxGlade 0.9.3 on Fri Jul 19 16:05:24 2019
+
+
+import wx
+
+from diffpy.pdfgui.control.controlerrors import ControlConfigError
+from diffpy.pdfgui.gui import tooltips
+from diffpy.pdfgui.gui.pdfpanel import PDFPanel
+from diffpy.pdfgui.gui.wxextensions.listctrls import KeyEventsListCtrl
+from diffpy.pdfgui.gui.wxextensions.validators import FLOAT_ONLY, TextValidator
+from diffpy.pdfgui.utils import numericStringSort
+
+
+
+[docs] +class PlotPanel(wx.Panel, PDFPanel): + def __init__(self, *args, **kwds): + PDFPanel.__init__(self) + # begin wxGlade: PlotPanel.__init__ + kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL + wx.Panel.__init__(self, *args, **kwds) + self.SetSize((456, 659)) + + sizer_1 = wx.BoxSizer(wx.VERTICAL) + + sizer_3 = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, "X"), wx.HORIZONTAL) + sizer_1.Add(sizer_3, 0, wx.EXPAND, 0) + + self.xDataCombo = wx.ComboBox(self, wx.ID_ANY, choices=[], style=wx.CB_READONLY) + sizer_3.Add(self.xDataCombo, 1, wx.ALL, 5) + + sizer_4 = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, "Y"), wx.HORIZONTAL) + sizer_1.Add(sizer_4, 1, wx.EXPAND, 0) + + self.yDataList = KeyEventsListCtrl( + self, wx.ID_ANY, style=wx.BORDER_SUNKEN | wx.LC_NO_HEADER | wx.LC_REPORT + ) + sizer_4.Add(self.yDataList, 1, wx.ALL | wx.EXPAND, 5) + + sizer_6 = wx.BoxSizer(wx.HORIZONTAL) + sizer_1.Add(sizer_6, 0, wx.EXPAND, 0) + + self.offsetLabel = wx.StaticText(self, wx.ID_ANY, "offset", style=wx.ALIGN_RIGHT) + sizer_6.Add(self.offsetLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) + + self.offsetTextCtrl = wx.TextCtrl(self, wx.ID_ANY, "-5", style=wx.TE_PROCESS_ENTER) + sizer_6.Add(self.offsetTextCtrl, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) + + self.static_line_1 = wx.StaticLine(self, wx.ID_ANY) + sizer_1.Add(self.static_line_1, 0, wx.BOTTOM | wx.EXPAND | wx.TOP, 5) + + sizer_2 = wx.BoxSizer(wx.HORIZONTAL) + sizer_1.Add(sizer_2, 0, wx.EXPAND, 0) + + self.plotButton = wx.Button(self, wx.ID_ANY, "Plot") + sizer_2.Add(self.plotButton, 0, wx.ALL, 5) + + self.resetButton = wx.Button(self, wx.ID_ANY, "Reset") + sizer_2.Add(self.resetButton, 0, wx.ALL, 5) + + self.SetSizer(sizer_1) + + self.Layout() + + self.Bind(wx.EVT_TEXT_ENTER, self.onEnter, self.offsetTextCtrl) + self.Bind(wx.EVT_BUTTON, self.onPlot, self.plotButton) + self.Bind(wx.EVT_BUTTON, self.onReset, self.resetButton) + # end wxGlade + self.Bind(wx.EVT_COMBOBOX, self._check, self.xDataCombo) + self.Bind(wx.EVT_LIST_ITEM_SELECTED, self._check, self.yDataList) + self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self._check, self.yDataList) + self.__customProperties() + + # USER CONFIGURATION CODE ################################################# + def __customProperties(self): + """Custom Properties go here.""" + self.yDataList.InsertColumn(0, "Y data") + self.offsetTextCtrl.SetValidator(TextValidator(FLOAT_ONLY, allowNeg=True)) + + # Define tooltips. + self.setToolTips(tooltips.plotpanel) + + # Testing Code. Comment or delete this block when finished. + # self.yDataList.InsertStringItem(sys.maxint, "y1") + # self.yDataList.InsertStringItem(sys.maxint, "y2") + # self.yDataList.InsertStringItem(sys.maxint, "y3") + # self.yDataList.InsertStringItem(sys.maxint, "y4") + # self.yDataList.InsertStringItem(sys.maxint, "y5") + # Initialize the sorter. + # self.yDataList.makeIDM() + # self.yDataList.initializeSorter() + + return + +
+[docs] + def enableWidgets(self, on=True): + """Enable or disable the widgets.""" + self.xDataCombo.Enable(on) + self.yDataList.Enable(on) + self.offsetTextCtrl.Enable(on) + self.resetButton.Enable(on) + self.plotButton.Enable(on) + return
+ + +
+[docs] + def updateWidgets(self): + """Enable or disable certain widgets depending upon what is selected in + the tree and in the plotting widgets.""" + # selections: selected nodes in treeCtrl + # fits: only different fittings + # refs: data item ids ( can be calculation, fit, structure and dataset + selections = self.treeCtrlMain.GetSelections() + # Only proceed if we have compatible items selected from the tree. + if not selections: + self.enableWidgets(False) + return + self.enableWidgets(True) + fits = dict.fromkeys( + [self.treeCtrlMain.GetControlData(self.treeCtrlMain.GetFitRoot(sel)) for sel in selections] + ) + refs = [self.treeCtrlMain.GetControlData(sel) for sel in selections] + + xdata = [] + # step is added if selections include type other than calculation + for type in [self.treeCtrlMain.GetNodeType(sel) for sel in selections]: + if type != "calculation": + xdata.append("step") + break + + # index is added if multiple selections are chosen from different fits + if len(fits) > 1: + xdata.append("index") + + for ref in refs: + xdata.extend(ref.getXNames()) + + for fit in fits: + xdata.extend(fit.getMetaDataNames()) + # also can plot y against y so add yNames as well + xdata.extend(fit.getYNames()) + + # reduce + xdata = list(set(xdata)) + + # Make the parameter entries a bit more presentable. + def _represent(mixedNames): + vals = ["@%i" % item for item in mixedNames if isinstance(item, int)] + others = [item for item in mixedNames if not isinstance(item, int)] + vals.extend(others) + numericStringSort(vals) + return vals + + xvals = _represent(xdata) + try: + xvals.remove("rw") + except ValueError: + pass + numericStringSort(xvals) + + # Fill the xDataCombo + if self.xDataCombo.GetCount(): + current = self.xDataCombo.GetValue() + else: + current = None + self.xDataCombo.Clear() + for item in xvals: + self.xDataCombo.Append(item) + + # Set default value for xDataCombo + # Either keep the current plot value selected, select 'r', or the + # first in the list. + defaultOrders = ["r", "step", "index"] + if current: + defaultOrders.insert(0, current) + for item in defaultOrders: + if item in xvals: + self.xDataCombo.SetValue(item) + break + else: + self.xDataCombo.SetSelection(0) + + # Y-DATA is the common subset of all data id + ydata = refs[0].getYNames() + for ref in refs[1:]: + for name in ydata[:]: + if name not in ref.getYNames(): + ydata.remove(name) + + yvals = _represent(ydata) + + # Fill the List + self.yDataList.DeleteAllItems() + for val in yvals: + # self.yDataList.InsertItem(sys.maxsize, str(val)) #doesn't work for windows + self.yDataList.InsertItem(100000, str(val)) + self.yDataList.makeIDM() + self.yDataList.initializeSorter() + if yvals: + self.yDataList.Select(0) + + # self.prevSelectionType = selectiontype + self._check(None) + + return
+ + +
+[docs] + def getSelectedYVals(self): + """Get the y-values selected in the y-value ListCtrl.""" + yvals = [] + item = self.yDataList.GetFirstSelected() + while item != -1: + name = self.yDataList.GetItemText(item) + yvals.append(name) + item = self.yDataList.GetNextSelected(item) + return yvals
+ + + # EVENT CODE ############################################################# +
+[docs] + def onPlot(self, event): # wxGlade: PlotPanel.<event_handler> + """Plot some stuff.""" + self._plot(event) + return
+ + + def _plot(self, event): + """This function is not wrapped.""" + selections = self.treeCtrlMain.GetSelections() + refs = [self.treeCtrlMain.GetControlData(node) for node in selections] + xval = self.xDataCombo.GetValue() + if xval[0] == "@": + xval = int(xval[1:]) + temp = self.getSelectedYVals() + # Clean up some formatting so the control can understand this. + yvals = [int(par[1:]) for par in temp if par[0] == "@"] + yvals.extend([val for val in temp if val[0] != "@"]) + offset = self.offsetTextCtrl.GetValue() + try: + offset = float(offset) + except ValueError: # offset can be empty string + offset = 0.0 + + self.mainFrame.control.plot(xval, yvals, refs, shift=offset, dry=(event is None)) + return + +
+[docs] + def onEnter(self, event): + """Reset plot.""" + self.onPlot(event) + return
+ + +
+[docs] + def onReset(self, event): # wxGlade: PlotPanel.<event_handler> + """Reset everything.""" + self.offsetTextCtrl.SetValue("-5") + self.refresh() + return
+ + + # Methods overloaded from PDFPanel +
+[docs] + def refresh(self): + """Refresh this panel.""" + self.updateWidgets() + return
+ + + def _check(self, event): + try: + self._plot(None) + self.plotButton.Enable() + except ControlConfigError: + self.plotButton.Disable()
+ +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/preferencespanel.html b/_modules/diffpy/pdfgui/gui/preferencespanel.html new file mode 100644 index 00000000..9a5e8e5e --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/preferencespanel.html @@ -0,0 +1,330 @@ + + + + + + + + diffpy.pdfgui.gui.preferencespanel — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.preferencespanel

+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2007 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+# generated by wxGlade 0.9.3 on Fri Jul 19 16:05:32 2019
+
+import wx
+import wx.lib.filebrowsebutton
+
+from diffpy.pdfgui.control import structureviewer
+from diffpy.pdfgui.gui import tooltips
+from diffpy.pdfgui.gui.pdfpanel import PDFPanel
+
+
+
+[docs] +class PreferencesPanel(wx.Panel, PDFPanel): + def __init__(self, *args, **kwds): + PDFPanel.__init__(self) + # begin wxGlade: PreferencesPanel.__init__ + kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL + wx.Panel.__init__(self, *args, **kwds) + + sizer_1 = wx.BoxSizer(wx.VERTICAL) + + sizerPanelName = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.HORIZONTAL) + sizer_1.Add(sizerPanelName, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) + + self.labelPanelName = wx.StaticText(self, wx.ID_ANY, "Preferences") + self.labelPanelName.SetFont( + wx.Font( + 18, + wx.FONTFAMILY_DEFAULT, + wx.FONTSTYLE_NORMAL, + wx.FONTWEIGHT_BOLD, + 0, + "Bitstream Vera Sans", + ) + ) + sizerPanelName.Add(self.labelPanelName, 1, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) + + grid_sizer_1 = wx.GridSizer(3, 3, 10, 10) + sizer_1.Add(grid_sizer_1, 0, wx.ALL, 5) + + self.labelViewer = wx.StaticText(self, wx.ID_ANY, "Structure viewer executable") + grid_sizer_1.Add(self.labelViewer, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT, 0) + + self.textCtrlViewer = wx.TextCtrl(self, wx.ID_ANY, "") + grid_sizer_1.Add(self.textCtrlViewer, 0, wx.EXPAND, 0) + + self.buttonViewerBrowse = wx.Button(self, wx.ID_ANY, "Browse") + grid_sizer_1.Add(self.buttonViewerBrowse, 0, 0, 0) + + self.labelArgStr = wx.StaticText(self, wx.ID_ANY, "Argument string") + grid_sizer_1.Add(self.labelArgStr, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT, 0) + + self.textCtrlArgument = wx.TextCtrl(self, wx.ID_ANY, "") + grid_sizer_1.Add(self.textCtrlArgument, 0, wx.EXPAND, 0) + + grid_sizer_1.Add((20, 20), 0, 0, 0) + + self.labelFormat = wx.StaticText(self, wx.ID_ANY, "Structure format") + grid_sizer_1.Add(self.labelFormat, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT, 0) + + self.choiceFormat = wx.Choice(self, wx.ID_ANY, choices=[]) + grid_sizer_1.Add(self.choiceFormat, 0, wx.EXPAND, 0) + + grid_sizer_1.Add((20, 20), 0, 0, 0) + + self.structureDirCheckBox = wx.CheckBox(self, wx.ID_ANY, "Remember path to structure files") + sizer_1.Add(self.structureDirCheckBox, 0, wx.ALL, 5) + + self.dataDirCheckBox = wx.CheckBox(self, wx.ID_ANY, "Remember path to data sets") + sizer_1.Add(self.dataDirCheckBox, 0, wx.ALL, 5) + + sizer_1.Add((0, 0), 1, wx.EXPAND, 0) + + self.static_line_1 = wx.StaticLine(self, wx.ID_ANY) + sizer_1.Add(self.static_line_1, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) + + sizer_3 = wx.BoxSizer(wx.HORIZONTAL) + sizer_1.Add(sizer_3, 0, wx.EXPAND, 0) + + sizer_3.Add((0, 0), 1, 0, 0) + + self.okButton = wx.Button(self, wx.ID_OK, "OK") + sizer_3.Add(self.okButton, 0, wx.ALL, 5) + + self.cancelButton = wx.Button(self, wx.ID_CANCEL, "Cancel") + sizer_3.Add(self.cancelButton, 0, wx.ALL, 5) + + self.SetSizer(sizer_1) + sizer_1.Fit(self) + + self.Layout() + + self.Bind(wx.EVT_BUTTON, self.onBrowse, self.buttonViewerBrowse) + self.Bind(wx.EVT_BUTTON, self.onOK, self.okButton) + self.Bind(wx.EVT_BUTTON, self.onCancel, self.cancelButton) + # end wxGlade + self.__customProperties() + + def __customProperties(self): + """Set the custom properties.""" + + # Fill the options in the format choice + viewer = structureviewer.getStructureViewer() + formats = viewer.getFileFormats() + formats.sort() + for fmt in formats: + self.choiceFormat.Append(fmt) + + self.setToolTips(tooltips.preferencespanel) + return + +
+[docs] + def onCancel(self, event): # wxGlade: PreferencesPanel.<event_handler> + """Cancel the changes. + + Go back to the last panel. + """ + selections = self.treeCtrlMain.GetSelections() + if selections: + node = selections[0] + entrytype = self.treeCtrlMain.GetNodeType(node) + else: + entrytype = None + self.mainFrame.setMode("fitting") + self.mainFrame.switchRightPanel(entrytype) + return
+ + +
+[docs] + def onOK(self, event): # wxGlade: PreferencesPanel.<event_handler> + """Record all of the preferences and return to fitting mode.""" + + # Record structure viewer stuff + executable = str(self.textCtrlViewer.GetValue()).strip() + argstr = str(self.textCtrlArgument.GetValue()).strip() + fileformat = str(self.choiceFormat.GetStringSelection()) + config = { + "executable": executable, + "argstr": argstr, + "fileformat": fileformat, + } + + viewer = structureviewer.getStructureViewer() + viewer.setConfig(config) + + # Structures path + remember = bool(self.structureDirCheckBox.GetValue()) + if not self.cP.has_section("PHASE"): + self.cP.add_section("PHASE") + self.cP.set("PHASE", "remember", str(remember)) + + # Data set path + remember = bool(self.dataDirCheckBox.GetValue()) + if not self.cP.has_section("DATASET"): + self.cP.add_section("DATASET") + self.cP.set("DATASET", "remember", str(remember)) + + # Get out of here + self.onCancel(event) + return
+ + +
+[docs] + def refresh(self): + """Refresh the panel.""" + + # Structure viewer stuff + viewer = structureviewer.getStructureViewer() + config = viewer.getConfig() + self.textCtrlViewer.SetValue(config["executable"]) + self.textCtrlArgument.SetValue(config["argstr"]) + self.choiceFormat.SetStringSelection(config["fileformat"]) + + remember = False + if self.cP.has_option("DATASET", "remember"): + remember = self.cP.getboolean("DATASET", "remember") + self.dataDirCheckBox.SetValue(remember) + + remember = False + if self.cP.has_option("PHASE", "remember"): + remember = self.cP.getboolean("PHASE", "remember") + self.structureDirCheckBox.SetValue(remember) + return
+ + +
+[docs] + def onBrowse(self, event): # wxGlade: PreferencesPanel.<event_handler> + d = wx.FileDialog( + None, + "Choose structure viewer", + ".", + "", + "All Files|*", + wx.FD_OPEN | wx.FD_FILE_MUST_EXIST, + ) + if d.ShowModal() == wx.ID_OK: + fullpath = d.GetPath() + self.textCtrlViewer.SetValue(fullpath) + return
+
+ + + +# end of class PreferencesPanel +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/resultspanel.html b/_modules/diffpy/pdfgui/gui/resultspanel.html new file mode 100644 index 00000000..94fe960f --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/resultspanel.html @@ -0,0 +1,214 @@ + + + + + + + + diffpy.pdfgui.gui.resultspanel — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.resultspanel

+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+# generated by wxGlade 0.9.3 on Fri Jul 19 16:05:44 2019
+
+import wx
+
+from diffpy.pdfgui.gui.pdfpanel import PDFPanel
+
+
+
+[docs] +class ResultsPanel(wx.Panel, PDFPanel): + def __init__(self, *args, **kwds): + # begin wxGlade: ResultsPanel.__init__ + kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL + wx.Panel.__init__(self, *args, **kwds) + self.fitResLabel = wx.StaticText(self, wx.ID_ANY, "Fit Summary") + self.resultsTextCtrl = wx.TextCtrl( + self, + wx.ID_ANY, + "Fit results will display here once the fit is complete.", + style=wx.HSCROLL | wx.TE_MULTILINE | wx.TE_READONLY, + ) + + self.__set_properties() + self.__do_layout() + # end wxGlade + self.__customProperties() + + def __set_properties(self): + # begin wxGlade: ResultsPanel.__set_properties + self.fitResLabel.SetFont( + wx.Font( + 18, + wx.FONTFAMILY_DEFAULT, + wx.FONTSTYLE_NORMAL, + wx.FONTWEIGHT_BOLD, + 0, + "", + ) + ) + # end wxGlade + + def __do_layout(self): + # begin wxGlade: ResultsPanel.__do_layout + sizer_1 = wx.BoxSizer(wx.VERTICAL) + sizer_2 = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.HORIZONTAL) + sizer_2.Add(self.fitResLabel, 0, wx.ALL, 5) + sizer_1.Add(sizer_2, 0, wx.ALL | wx.EXPAND, 5) + sizer_1.Add(self.resultsTextCtrl, 1, wx.ALL | wx.EXPAND, 5) + self.SetSizer(sizer_1) + sizer_1.Fit(self) + self.Layout() + # end wxGlade + + # UTILITY METHODS ################################# + def __customProperties(self): + """Set the custom properties.""" + self.fit = None + self.defres = "Fit results will display here once the fit is complete." + self.results = self.defres + + # Set the font to monospace + ftxt = self.resultsTextCtrl.GetFont() + font = wx.Font( + ftxt.GetPointSize(), + wx.FONTFAMILY_TELETYPE, + ftxt.GetStyle(), + ftxt.GetWeight(), + ) + self.resultsTextCtrl.SetFont(font) + return + + # Methods overloaded from PDFPanel +
+[docs] + def refresh(self): + """Fill in the resultsTextCtrl with the fit results if they exist.""" + if self.fit: + self.results = self.fit.res + else: + self.results = "" + if not self.results: + self.results = self.defres + displayed = self.resultsTextCtrl.GetValue() + if displayed != self.results: + lastpos = self.resultsTextCtrl.GetLastPosition() + self.resultsTextCtrl.Replace(0, lastpos, self.results) + return
+
+ + + +# end of class ResultsPanel +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/rseriespanel.html b/_modules/diffpy/pdfgui/gui/rseriespanel.html new file mode 100644 index 00000000..6b5015ea --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/rseriespanel.html @@ -0,0 +1,308 @@ + + + + + + + + diffpy.pdfgui.gui.rseriespanel — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.rseriespanel

+#!/usr/bin/env python
+# -*- coding: ISO-8859-1 -*-
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+# generated by wxGlade 0.9.3 on Fri Jul 19 16:05:55 2019
+
+import wx
+
+from diffpy.pdfgui.control.pdfguimacros import makeRSeries
+from diffpy.pdfgui.gui.pdfpanel import PDFPanel
+from diffpy.pdfgui.gui.wxextensions.validators import FLOAT_ONLY, TextValidator
+
+
+
+[docs] +class RSeriesPanel(wx.Panel, PDFPanel): + def __init__(self, *args, **kwds): + PDFPanel.__init__(self) + # begin wxGlade: RSeriesPanel.__init__ + kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL + wx.Panel.__init__(self, *args, **kwds) + self.instructionsLabel = wx.StaticText( + self, + wx.ID_ANY, + "Select a fit from the tree on the left and set the first value, last value, \nand the step size of the maximum and/or minimum of the fit range\nbelow. If you have not set up a fit to be the template for the series, hit\ncancel and rerun this macro once a fit has been created.", # noqa: E501 + ) + self.maxFirstLabel = wx.StaticText(self, wx.ID_ANY, "first") + self.maxFirstTextCtrl = wx.TextCtrl(self, wx.ID_ANY, "") + self.maxLastLabel = wx.StaticText(self, wx.ID_ANY, "last") + self.maxLastTextCtrl = wx.TextCtrl(self, wx.ID_ANY, "") + self.maxStepLabel = wx.StaticText(self, wx.ID_ANY, "step") + self.maxStepTextCtrl = wx.TextCtrl(self, wx.ID_ANY, "") + self.minFirstLabel = wx.StaticText(self, wx.ID_ANY, "first") + self.minFirstTextCtrl = wx.TextCtrl(self, wx.ID_ANY, "") + self.minLastLabel = wx.StaticText(self, wx.ID_ANY, "last") + self.minLastTextCtrl = wx.TextCtrl(self, wx.ID_ANY, "") + self.minStepLabel = wx.StaticText(self, wx.ID_ANY, "step") + self.minStepTextCtrl = wx.TextCtrl(self, wx.ID_ANY, "") + self.goButton = wx.Button(self, wx.ID_OK, "OK") + self.cancelButton = wx.Button(self, wx.ID_CANCEL, "Cancel") + + self.__set_properties() + self.__do_layout() + + self.Bind(wx.EVT_BUTTON, self.onOK, self.goButton) + self.Bind(wx.EVT_BUTTON, self.onCancel, self.cancelButton) + # end wxGlade + self.__customProperties() + + def __set_properties(self): + # begin wxGlade: RSeriesPanel.__set_properties + self.instructionsLabel.SetFont( + wx.Font( + 10, + wx.FONTFAMILY_DEFAULT, + wx.FONTSTYLE_NORMAL, + wx.FONTWEIGHT_NORMAL, + 0, + "Sans", + ) + ) + # end wxGlade + + def __do_layout(self): + # begin wxGlade: RSeriesPanel.__do_layout + sizer_1 = wx.BoxSizer(wx.VERTICAL) + sizer_3 = wx.BoxSizer(wx.HORIZONTAL) + sizer_4_copy = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, "fit minimum"), wx.HORIZONTAL) + sizer_4 = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, "fit maximum"), wx.HORIZONTAL) + sizer_1.Add(self.instructionsLabel, 0, wx.ALL | wx.EXPAND, 5) + sizer_4.Add(self.maxFirstLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) + sizer_4.Add(self.maxFirstTextCtrl, 0, wx.ALL, 5) + sizer_4.Add(self.maxLastLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) + sizer_4.Add(self.maxLastTextCtrl, 0, wx.ALL, 5) + sizer_4.Add(self.maxStepLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) + sizer_4.Add(self.maxStepTextCtrl, 0, wx.ALL, 5) + sizer_1.Add(sizer_4, 0, wx.ALL | wx.EXPAND, 5) + sizer_4_copy.Add(self.minFirstLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) + sizer_4_copy.Add(self.minFirstTextCtrl, 0, wx.ALL, 5) + sizer_4_copy.Add(self.minLastLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) + sizer_4_copy.Add(self.minLastTextCtrl, 0, wx.ALL, 5) + sizer_4_copy.Add(self.minStepLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) + sizer_4_copy.Add(self.minStepTextCtrl, 0, wx.ALL, 5) + sizer_1.Add(sizer_4_copy, 0, wx.ALL | wx.EXPAND, 5) + sizer_3.Add((20, 20), 1, wx.EXPAND, 0) + sizer_3.Add(self.goButton, 0, wx.ALL, 5) + sizer_3.Add(self.cancelButton, 0, wx.ALL, 5) + sizer_1.Add(sizer_3, 0, wx.EXPAND, 0) + self.SetSizer(sizer_1) + sizer_1.Fit(self) + self.Layout() + # end wxGlade + + # ################################################ + def __customProperties(self): + """Set the custom properties of this panel.""" + self.fit = None + self.ctrlMap = { + "maxfirst": "maxFirstTextCtrl", + "maxlast": "maxLastTextCtrl", + "maxstep": "maxStepTextCtrl", + "minfirst": "minFirstTextCtrl", + "minlast": "minLastTextCtrl", + "minstep": "minStepTextCtrl", + } + + for var in self.ctrlMap: + setattr(self, var, None) + + for ctrlname in self.ctrlMap.values(): + textCtrl = getattr(self, ctrlname) + textCtrl.SetValidator(TextValidator(FLOAT_ONLY)) + return + +
+[docs] + def onOK(self, event): # wxGlade: RSeriesPanel.<event_handler> + """Add make a temperature series and add it to the project.""" + for varname, ctrlname in self.ctrlMap.items(): + textCtrl = getattr(self, ctrlname) + value = textCtrl.GetValue() + if value == "": + value = None + else: + value = float(value) + setattr(self, varname, value) + + org = makeRSeries( + self.mainFrame.control, + self.fit, + self.maxfirst, + self.maxlast, + self.maxstep, + self.minfirst, + self.minlast, + self.minstep, + ) + self.treeCtrlMain.ExtendProjectTree(org, clear=False) + self.mainFrame.needsSave() + self.onCancel(event) + return
+ + +
+[docs] + def onCancel(self, event): # wxGlade: RSeriesPanel.<event_handler> + """Return to the main panel.""" + self.mainFrame.setMode("fitting") + self.treeCtrlMain.UnselectAll() + self.mainFrame.switchRightPanel("blank") + return
+ + +
+[docs] + def treeSelectionUpdate(self, node): + """Set the current fit when the tree selection changes.""" + nodetype = self.treeCtrlMain.GetNodeType(node) + if nodetype == "fit": + self.fit = self.treeCtrlMain.GetControlData(node) + self.refresh() + return
+ + +
+[docs] + def refresh(self): + """Block out OK button if there is no fit. + + This also blocks OK if the fit has no datasets or phases. + """ + # We can't rely on Veto to block unwanted tree selections on windows. + # So, we have to check for errors here. + node = None + nodetype = None + selections = self.treeCtrlMain.GetSelections() + if selections: + node = selections[0] + nodetype = self.treeCtrlMain.GetNodeType(node) + + if node and nodetype == "fit" and self.fit and self.fit.hasDataSets() and self.fit.hasStructures(): + self.goButton.Enable() + else: + self.goButton.Enable(False) + return
+
+ + + +# end of class RSeriesPanel +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/sgconstraindialog.html b/_modules/diffpy/pdfgui/gui/sgconstraindialog.html new file mode 100644 index 00000000..714b9134 --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/sgconstraindialog.html @@ -0,0 +1,423 @@ + + + + + + + + diffpy.pdfgui.gui.sgconstraindialog — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.sgconstraindialog

+#!/usr/bin/env python
+# -*- coding: ISO-8859-1 -*-
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+# generated by wxGlade 0.9.3 on Fri Jul 19 16:06:06 2019
+
+import math
+
+import wx
+
+from diffpy.pdfgui.control.controlerrors import ControlValueError
+from diffpy.pdfgui.gui.pdfpanel import PDFPanel
+
+
+
+[docs] +class SGConstrainDialog(wx.Dialog, PDFPanel): + def __init__(self, *args, **kwds): + PDFPanel.__init__(self) + # begin wxGlade: SGConstrainDialog.__init__ + kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_DIALOG_STYLE + wx.Dialog.__init__(self, *args, **kwds) + self.SetTitle("Space Group Constraints") + + sizer_2 = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, "Space Group Constraints"), wx.VERTICAL) + + self.numConstrainedLabel = wx.StaticText(self, wx.ID_ANY, "") + sizer_2.Add(self.numConstrainedLabel, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 5) + + sizer_3 = wx.BoxSizer(wx.HORIZONTAL) + sizer_2.Add(sizer_3, 0, wx.EXPAND, 0) + + self.sgLabel = wx.StaticText(self, wx.ID_ANY, "Space Group") + sizer_3.Add(self.sgLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) + + self.sgComboBox = wx.ComboBox(self, wx.ID_ANY, choices=["P1"], style=0) + self.sgComboBox.SetSelection(0) + sizer_3.Add(self.sgComboBox, 0, wx.ALL, 5) + + sizer_4 = wx.BoxSizer(wx.HORIZONTAL) + sizer_2.Add(sizer_4, 0, wx.EXPAND, 0) + + self.offsetLabel = wx.StaticText(self, wx.ID_ANY, "Origin Offset") + sizer_4.Add(self.offsetLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) + + self.offsetTextCtrlX = wx.TextCtrl(self, wx.ID_ANY, "0") + sizer_4.Add(self.offsetTextCtrlX, 0, wx.ALL, 5) + + self.offsetTextCtrlY = wx.TextCtrl(self, wx.ID_ANY, "0") + sizer_4.Add(self.offsetTextCtrlY, 0, wx.ALL, 5) + + self.offsetTextCtrlZ = wx.TextCtrl(self, wx.ID_ANY, "0") + sizer_4.Add(self.offsetTextCtrlZ, 0, wx.ALL, 5) + + self.positionCheckBox = wx.CheckBox(self, wx.ID_ANY, "constrain positions") + self.positionCheckBox.SetValue(1) + sizer_2.Add(self.positionCheckBox, 0, wx.ALL, 5) + + self.tfCheckBox = wx.CheckBox(self, wx.ID_ANY, "constrain temperature factors") + self.tfCheckBox.SetValue(1) + sizer_2.Add(self.tfCheckBox, 0, wx.ALL, 5) + + self.static_line_1 = wx.StaticLine(self, wx.ID_ANY) + sizer_2.Add(self.static_line_1, 0, wx.EXPAND, 0) + + sizer_4_copy = wx.BoxSizer(wx.HORIZONTAL) + sizer_2.Add(sizer_4_copy, 0, wx.EXPAND, 0) + + sizer_4_copy.Add((0, 0), 1, wx.EXPAND, 0) + + self.cancelButton = wx.Button(self, wx.ID_CANCEL, "Cancel") + sizer_4_copy.Add(self.cancelButton, 0, wx.ALL, 5) + + self.okButton = wx.Button(self, wx.ID_OK, "OK") + sizer_4_copy.Add(self.okButton, 0, wx.ALL, 5) + + self.SetSizer(sizer_2) + sizer_2.Fit(self) + + self.Layout() + + self.Bind(wx.EVT_COMBOBOX, self.onSGSelect, self.sgComboBox) + self.Bind(wx.EVT_TEXT_ENTER, self.onSGTextEnter, self.sgComboBox) + self.Bind(wx.EVT_TEXT_ENTER, self.onOXTextEnter, self.offsetTextCtrlX) + self.Bind(wx.EVT_TEXT_ENTER, self.onOYTextEnter, self.offsetTextCtrlY) + self.Bind(wx.EVT_TEXT_ENTER, self.onOZTextEnter, self.offsetTextCtrlZ) + self.Bind(wx.EVT_CHECKBOX, self.onPosFlag, self.positionCheckBox) + self.Bind(wx.EVT_CHECKBOX, self.onTempFlag, self.tfCheckBox) + self.Bind(wx.EVT_BUTTON, self.onCancel, self.cancelButton) + self.Bind(wx.EVT_BUTTON, self.onOk, self.okButton) + # end wxGlade + self.__customProperties() + + # ######################################################################### + + def __customProperties(self): + """Set the custom properties.""" + # setting of combo box items was deferred to updateSpaceGroupList() + self.spacegroup = None + self.offset = [0.0, 0.0, 0.0] + self.posflag = True + self.tempflag = True + self.structure = None + self.indices = [] + + self.textCtrls = [ + self.offsetTextCtrlX, + self.offsetTextCtrlY, + self.offsetTextCtrlZ, + ] + + # Set the focus events. + for textctrl in self.textCtrls: + textctrl.Bind(wx.EVT_KILL_FOCUS, self.onKillFocus) + self.sgComboBox.Bind(wx.EVT_KILL_FOCUS, self.onKillFocus) + return + +
+[docs] + def updateSpaceGroupList(self): + """Update space group choices in combobox according to + self.structure.getSpaceGroupList(). + + Requires that structure attribute is defined. + """ + self.sgComboBox.Clear() + sglist = self.structure.getSpaceGroupList() + self.spacegroup = self.structure.getSpaceGroup("P1") + for sg in sglist: + self.sgComboBox.Append(sg.short_name) + return
+ + +
+[docs] + def setStructure(self, structure): + """Set the structure and update the widgets.""" + self.structure = structure + self.updateSpaceGroupList() + sgname = self.structure.pdffit.get("spcgr") + offset = self.structure.pdffit.get("sgoffset") + if sgname: + self.sgComboBox.SetValue(sgname) + if offset: + self.offsetTextCtrlX.SetValue(str(offset[0])) + self.offsetTextCtrlY.SetValue(str(offset[1])) + self.offsetTextCtrlZ.SetValue(str(offset[2])) + self.updateWidgets() + return
+ + +
+[docs] + def getSpaceGroup(self): + """Get the current space group.""" + return self.spacegroup
+ + +
+[docs] + def getOffset(self): + """Get the offset.""" + return self.offset
+ + +
+[docs] + def getPosFlag(self): + """Get whether the positions should be constrained.""" + return self.posflag
+ + +
+[docs] + def getTempFlag(self): + """Get whether the positions should be constrained.""" + return self.tempflag
+ + +
+[docs] + def updateWidgets(self): + """Update the widgets.""" + # Update space group + sgname = self.sgComboBox.GetValue() + try: + self.spacegroup = self.structure.getSpaceGroup(sgname) + error = None + except ValueError: + error = "Space group %s does not exist." % sgname + # This changes list box value to the short_name of the new spacegroup + # or to the name of previous spacegroup when getSpaceGroup failed. + self.sgComboBox.SetValue(self.spacegroup.short_name) + # Update offset + for i in range(3): + textctrl = self.textCtrls[i] + val = textctrl.GetValue() + # make sure the value is meaningful + try: + val = float(eval("1.0*" + val, dict(math.__dict__))) + except (NameError, TypeError, SyntaxError): + val = 0 + textctrl.SetValue("%s" % val) + self.offset[i] = val + + # newatoms = len(stemp) - len(self.structure) + s = "" + if len(self.indices) != 1: + s = "s" + message = "%i atom%s selected." % (len(self.indices), s) + self.numConstrainedLabel.SetLabel(message) + + # Raise an error if we had to change the space group + if error: + raise ControlValueError(error) + return
+ + + # # Events + +
+[docs] + def onKillFocus(self, event): + """Check value of widgets and update the dialog message.""" + self.updateWidgets() + event.Skip() + return
+ + +
+[docs] + def onSGTextEnter(self, event): # wxGlade: SGConstrainDialog.<event_handler> + self.updateWidgets() + return
+ + +
+[docs] + def onOXTextEnter(self, event): # wxGlade: SGConstrainDialog.<event_handler> + self.updateWidgets() + return
+ + +
+[docs] + def onOYTextEnter(self, event): # wxGlade: SGConstrainDialog.<event_handler> + self.updateWidgets() + return
+ + +
+[docs] + def onOZTextEnter(self, event): # wxGlade: SGConstrainDialog.<event_handler> + self.updateWidgets() + return
+ + +
+[docs] + def onSGSelect(self, event): # wxGlade: SGConstrainDialog.<event_handler> + self.updateWidgets() + return
+ + +
+[docs] + def onOk(self, event): # wxGlade: SGConstrainDialog.<event_handler> + # check to see if the space group is consistent + if not self.structure.isSpaceGroupPossible(self.spacegroup): + message = "The chosen space group is not consistent\n" + message += "with the lattice parameters.\n" + message += "Would you like to proceed anyways?" + d = wx.MessageDialog(self, message, "Inconsistent space group", wx.YES_NO) + code = d.ShowModal() + if code == wx.ID_YES: + self.EndModal(wx.ID_OK) + else: + self.EndModal(wx.ID_OK) + return
+ + +
+[docs] + def onCancel(self, event): # wxGlade: SGConstrainDialog.<event_handler> + event.Skip() + return
+ + +
+[docs] + def onPosFlag(self, event): # wxGlade: SGConstrainDialog.<event_handler> + self.posflag = self.positionCheckBox.GetValue() + return
+ + +
+[docs] + def onTempFlag(self, event): # wxGlade: SGConstrainDialog.<event_handler> + self.tempflag = self.tfCheckBox.GetValue() + return
+
+ + + +# end of class SGConstrainDialog +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/sgstructuredialog.html b/_modules/diffpy/pdfgui/gui/sgstructuredialog.html new file mode 100644 index 00000000..f1c612a7 --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/sgstructuredialog.html @@ -0,0 +1,397 @@ + + + + + + + + diffpy.pdfgui.gui.sgstructuredialog — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.sgstructuredialog

+#!/usr/bin/env python
+# -*- coding: ISO-8859-1 -*-
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+# generated by wxGlade 0.9.3 on Fri Jul 19 16:06:15 2019
+
+import math
+
+import wx
+
+from diffpy.pdfgui.control.controlerrors import ControlValueError
+from diffpy.pdfgui.gui.pdfpanel import PDFPanel
+
+
+
+[docs] +class SGStructureDialog(wx.Dialog, PDFPanel): + def __init__(self, *args, **kwds): + PDFPanel.__init__(self) + # begin wxGlade: SGStructureDialog.__init__ + kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_DIALOG_STYLE + wx.Dialog.__init__(self, *args, **kwds) + self.SetTitle("Space Group Expansion") + + sizer_2 = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, "Space Group Expansion"), wx.VERTICAL) + + self.numConstrainedLabel = wx.StaticText(self, wx.ID_ANY, "") + sizer_2.Add(self.numConstrainedLabel, 0, wx.ALL, 5) + + sizer_3 = wx.BoxSizer(wx.HORIZONTAL) + sizer_2.Add(sizer_3, 0, wx.EXPAND, 0) + + self.sgLabel = wx.StaticText(self, wx.ID_ANY, "Space Group") + sizer_3.Add(self.sgLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) + + self.sgComboBox = wx.ComboBox(self, wx.ID_ANY, choices=["P1"], style=0) + self.sgComboBox.SetSelection(0) + sizer_3.Add(self.sgComboBox, 0, wx.ALL, 5) + + sizer_4 = wx.BoxSizer(wx.HORIZONTAL) + sizer_2.Add(sizer_4, 0, wx.EXPAND, 0) + + self.offsetLabel = wx.StaticText(self, wx.ID_ANY, "Origin Offset") + sizer_4.Add(self.offsetLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) + + self.offsetTextCtrlX = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_PROCESS_ENTER) + sizer_4.Add(self.offsetTextCtrlX, 0, wx.ALL, 5) + + self.offsetTextCtrlY = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_PROCESS_ENTER) + sizer_4.Add(self.offsetTextCtrlY, 0, wx.ALL, 5) + + self.offsetTextCtrlZ = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_PROCESS_ENTER) + sizer_4.Add(self.offsetTextCtrlZ, 0, wx.ALL, 5) + + self.static_line_1 = wx.StaticLine(self, wx.ID_ANY) + sizer_2.Add(self.static_line_1, 0, wx.EXPAND, 0) + + sizer_4_copy = wx.BoxSizer(wx.HORIZONTAL) + sizer_2.Add(sizer_4_copy, 0, wx.EXPAND, 0) + + sizer_4_copy.Add((0, 0), 1, wx.EXPAND, 0) + + self.cancelButton = wx.Button(self, wx.ID_CANCEL, "Cancel") + sizer_4_copy.Add(self.cancelButton, 0, wx.ALL, 5) + + self.okButton = wx.Button(self, wx.ID_OK, "OK") + sizer_4_copy.Add(self.okButton, 0, wx.ALL, 5) + + self.SetSizer(sizer_2) + sizer_2.Fit(self) + + self.Layout() + + self.Bind(wx.EVT_COMBOBOX, self.onSGSelect, self.sgComboBox) + self.Bind(wx.EVT_TEXT_ENTER, self.onSGTextEnter, self.sgComboBox) + self.Bind(wx.EVT_TEXT_ENTER, self.onOXTextEnter, self.offsetTextCtrlX) + self.Bind(wx.EVT_TEXT_ENTER, self.onOYTextEnter, self.offsetTextCtrlY) + self.Bind(wx.EVT_TEXT_ENTER, self.onOZTextEnter, self.offsetTextCtrlZ) + self.Bind(wx.EVT_BUTTON, self.onCancel, self.cancelButton) + self.Bind(wx.EVT_BUTTON, self.onOk, self.okButton) + # end wxGlade + self.__customProperties() + + # ######################################################################### + + def __customProperties(self): + """Set the custom properties.""" + # setting of combo box items was deferred to updateSpaceGroupList() + self.spacegroup = None + self.offset = [0.0, 0.0, 0.0] + self.structure = None + self.indices = [] + + self.textCtrls = [ + self.offsetTextCtrlX, + self.offsetTextCtrlY, + self.offsetTextCtrlZ, + ] + + # Set the focus events. + for textctrl in self.textCtrls: + textctrl.Bind(wx.EVT_KILL_FOCUS, self.onKillFocus) + self.sgComboBox.Bind(wx.EVT_KILL_FOCUS, self.onKillFocus) + return + +
+[docs] + def updateSpaceGroupList(self): + """Update space group choices in combobox according to + self.structure.getSpaceGroupList(). + + Requires that structure attribute is defined. + """ + self.sgComboBox.Clear() + sglist = self.structure.getSpaceGroupList() + self.spacegroup = self.structure.getSpaceGroup("P1") + for sg in sglist: + self.sgComboBox.Append(sg.short_name) + return
+ + +
+[docs] + def setStructure(self, structure): + """Set the structure and update the dialog.""" + self.structure = structure + self.updateSpaceGroupList() + sgname = self.structure.pdffit.get("spcgr") + offset = self.structure.pdffit.get("sgoffset") + if sgname: + self.sgComboBox.SetValue(sgname) + if offset: + self.offsetTextCtrlX.SetValue(str(offset[0])) + self.offsetTextCtrlY.SetValue(str(offset[1])) + self.offsetTextCtrlZ.SetValue(str(offset[2])) + self.updateWidgets() + return
+ + +
+[docs] + def getSpaceGroup(self): + """Get the current space group.""" + return self.spacegroup
+ + +
+[docs] + def getOffset(self): + """Get the offset.""" + return self.offset
+ + +
+[docs] + def updateWidgets(self): + """Update the widgets.""" + # Update space group + sgname = self.sgComboBox.GetValue() + try: + self.spacegroup = self.structure.getSpaceGroup(sgname) + error = None + except ValueError: + error = "Space group %s does not exist." % sgname + # This changes list box value to the short_name of the new spacegroup + # or to the name of previous spacegroup when getSpaceGroup failed. + self.sgComboBox.SetValue(self.spacegroup.short_name) + + # Update offset + for i in range(3): + textctrl = self.textCtrls[i] + val = textctrl.GetValue() + # make sure the value is meaningful + try: + val = float(eval("1.0*" + val, dict(math.__dict__))) + except (NameError, TypeError, SyntaxError): + val = 0.0 + textctrl.SetValue("%s" % val) + self.offset[i] = val + + # find how many new atoms would be generated + from diffpy.structure.symmetryutilities import ExpandAsymmetricUnit + + corepos = [self.structure[i].xyz for i in self.indices] + symposeps = self.structure.symposeps + eau = ExpandAsymmetricUnit(self.spacegroup, corepos, sgoffset=self.offset, eps=symposeps) + newsize = sum(eau.multiplicity) + s = "" + if len(self.indices) != 1: + s = "s" + message = "%i atom%s selected. Expanding to %i positions." % ( + len(self.indices), + s, + newsize, + ) + self.numConstrainedLabel.SetLabel(message) + + # Raise an error if we had to change the space group + if error: + raise ControlValueError(error) + return
+ + + # # Events +
+[docs] + def onKillFocus(self, event): + """Check value of widgets and update the dialog message.""" + self.updateWidgets() + event.Skip() + return
+ + +
+[docs] + def onSGTextEnter(self, event): # wxGlade: SGStructureDialog.<event_handler> + self.updateWidgets() + self.onOk(None) + return
+ + +
+[docs] + def onSGSelect(self, event): # wxGlade: SGStructureDialog.<event_handler> + self.updateWidgets() + return
+ + +
+[docs] + def onOXTextEnter(self, event): # wxGlade: SGStructureDialog.<event_handler> + self.updateWidgets() + self.onOk(None) + return
+ + +
+[docs] + def onOYTextEnter(self, event): # wxGlade: SGStructureDialog.<event_handler> + self.updateWidgets() + self.onOk(None) + return
+ + +
+[docs] + def onOZTextEnter(self, event): # wxGlade: SGStructureDialog.<event_handler> + self.updateWidgets() + self.onOk(None) + return
+ + +
+[docs] + def onOk(self, event): # wxGlade: SGStructureDialog.<event_handler> + # check to see if the space group is consistent + if not self.structure.isSpaceGroupPossible(self.spacegroup): + message = "The chosen space group is not consistent\n" + message += "with the lattice parameters.\n" + message += "Would you like to proceed anyways?" + d = wx.MessageDialog(self, message, "Inconsistent space group", wx.YES_NO) + code = d.ShowModal() + if code == wx.ID_YES: + self.EndModal(wx.ID_OK) + else: + self.EndModal(wx.ID_OK) + return
+ + +
+[docs] + def onCancel(self, event): # wxGlade: SGStructureDialog.<event_handler> + event.Skip() + return
+
+ + + +# end of class SGStructureDialog +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/supercelldialog.html b/_modules/diffpy/pdfgui/gui/supercelldialog.html new file mode 100644 index 00000000..da93bba6 --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/supercelldialog.html @@ -0,0 +1,223 @@ + + + + + + + + diffpy.pdfgui.gui.supercelldialog — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.supercelldialog

+#!/usr/bin/env python
+# -*- coding: ISO-8859-1 -*-
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+# generated by wxGlade 0.9.3 on Fri Jul 19 16:06:24 2019
+
+import wx
+
+
+
+[docs] +class SupercellDialog(wx.Dialog): + def __init__(self, *args, **kwds): + # begin wxGlade: SupercellDialog.__init__ + kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_DIALOG_STYLE + wx.Dialog.__init__(self, *args, **kwds) + self.aLabel = wx.StaticText(self, wx.ID_ANY, "a multiplier") + self.aSpinCtrl = wx.SpinCtrl(self, wx.ID_ANY, "1", min=1, max=10, style=0) + self.bLabel = wx.StaticText(self, wx.ID_ANY, "b multiplier") + self.bSpinCtrl = wx.SpinCtrl(self, wx.ID_ANY, "1", min=1, max=10, style=0) + self.cLabel = wx.StaticText(self, wx.ID_ANY, "c multiplier") + self.cSpinCtrl = wx.SpinCtrl(self, wx.ID_ANY, "1", min=1, max=10, style=0) + self.static_line_1 = wx.StaticLine(self, wx.ID_ANY) + self.cancelButton = wx.Button(self, wx.ID_CANCEL, "Cancel") + self.okButton = wx.Button(self, wx.ID_OK, "OK") + + self.__set_properties() + self.__do_layout() + + self.Bind(wx.EVT_BUTTON, self.onCancel, self.cancelButton) + self.Bind(wx.EVT_BUTTON, self.onOk, self.okButton) + # end wxGlade + self.__customProperties() + + def __set_properties(self): + # begin wxGlade: SupercellDialog.__set_properties + self.SetTitle("Supercell Expansion") + # end wxGlade + + def __do_layout(self): + # begin wxGlade: SupercellDialog.__do_layout + sizer_1 = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, "Supercell Expansion"), wx.VERTICAL) + sizer_4 = wx.BoxSizer(wx.HORIZONTAL) + sizer_3 = wx.BoxSizer(wx.HORIZONTAL) + sizer_2_copy_1 = wx.BoxSizer(wx.HORIZONTAL) + sizer_2_copy = wx.BoxSizer(wx.HORIZONTAL) + sizer_2 = wx.BoxSizer(wx.HORIZONTAL) + sizer_2.Add(self.aLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) + sizer_2.Add(self.aSpinCtrl, 0, wx.ALL, 5) + sizer_1.Add(sizer_2, 0, wx.EXPAND, 0) + sizer_2_copy.Add(self.bLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) + sizer_2_copy.Add(self.bSpinCtrl, 0, wx.ALL, 5) + sizer_1.Add(sizer_2_copy, 0, wx.EXPAND, 0) + sizer_2_copy_1.Add(self.cLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) + sizer_2_copy_1.Add(self.cSpinCtrl, 0, wx.ALL, 5) + sizer_1.Add(sizer_2_copy_1, 0, wx.EXPAND, 0) + sizer_3.Add(self.static_line_1, 1, wx.BOTTOM | wx.EXPAND | wx.TOP, 5) + sizer_1.Add(sizer_3, 0, wx.EXPAND, 0) + sizer_4.Add(self.cancelButton, 0, wx.ALL, 5) + sizer_4.Add(self.okButton, 0, wx.ALL, 5) + sizer_1.Add(sizer_4, 1, wx.EXPAND, 0) + self.SetSizer(sizer_1) + sizer_1.Fit(self) + self.Layout() + # end wxGlade + + # ########################################################################## + + def __customProperties(self): + """Set custom properties.""" + # Set the text validators + self.m = 1 + self.n = 1 + self.o = 1 + return + +
+[docs] + def getMNO(self): + """Get the [m, n, o] expansion parameters from the dialog.""" + return [self.m, self.n, self.o]
+ + +
+[docs] + def onOk(self, event): # wxGlade: SupercellDialog.<event_handler> + """Accept the expansion.""" + self.m = self.aSpinCtrl.GetValue() + self.n = self.bSpinCtrl.GetValue() + self.o = self.cSpinCtrl.GetValue() + event.Skip() + return
+ + +
+[docs] + def onCancel(self, event): # wxGlade: SupercellDialog.<event_handler> + """Get out of here.""" + event.Skip() + return
+
+ + + +# end of class SupercellDialog +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/temperatureseriespanel.html b/_modules/diffpy/pdfgui/gui/temperatureseriespanel.html new file mode 100644 index 00000000..221ce2c3 --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/temperatureseriespanel.html @@ -0,0 +1,500 @@ + + + + + + + + diffpy.pdfgui.gui.temperatureseriespanel — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.temperatureseriespanel

+#!/usr/bin/env python
+# -*- coding: ISO-8859-1 -*-
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+# generated by wxGlade 0.9.3 on Fri Jul 19 16:06:35 2019
+
+import os.path
+import re
+
+import wx
+
+from diffpy.pdfgui.control.pdfguimacros import makeTemperatureSeries
+from diffpy.pdfgui.gui import tooltips
+from diffpy.pdfgui.gui.pdfpanel import PDFPanel
+from diffpy.pdfgui.gui.wxextensions.listctrls import AutoWidthListCtrl
+from diffpy.pdfgui.utils import numericStringSort
+
+
+
+[docs] +class TemperatureSeriesPanel(wx.Panel, PDFPanel): + def __init__(self, *args, **kwds): + PDFPanel.__init__(self) + # begin wxGlade: TemperatureSeriesPanel.__init__ + kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL + wx.Panel.__init__(self, *args, **kwds) + + sizer_1 = wx.BoxSizer(wx.VERTICAL) + + self.instructionsLabel = wx.StaticText( + self, + wx.ID_ANY, + "Select a fit from the tree on the left then add datasets and assign\ntemperatues below. If you have not set up a fit to be the template\nfor the series, hit cancel and rerun this macro once a fit has been\ncreated.", # noqa: E501 + ) + self.instructionsLabel.SetFont( + wx.Font( + 10, + wx.FONTFAMILY_DEFAULT, + wx.FONTSTYLE_NORMAL, + wx.FONTWEIGHT_NORMAL, + 0, + "Sans", + ) + ) + sizer_1.Add(self.instructionsLabel, 0, wx.ALL | wx.EXPAND, 5) + + sizer_2 = wx.BoxSizer(wx.VERTICAL) + sizer_1.Add(sizer_2, 1, wx.EXPAND, 0) + + sizer_4 = wx.BoxSizer(wx.HORIZONTAL) + sizer_2.Add(sizer_4, 1, wx.EXPAND, 0) + + self.listCtrlFiles = AutoWidthListCtrl( + self, wx.ID_ANY, style=wx.BORDER_SUNKEN | wx.LC_EDIT_LABELS | wx.LC_REPORT + ) + sizer_4.Add(self.listCtrlFiles, 1, wx.ALL | wx.EXPAND, 5) + + sizer_5 = wx.BoxSizer(wx.VERTICAL) + sizer_4.Add(sizer_5, 0, wx.EXPAND, 0) + + sizer_5.Add((0, 0), 1, 0, 0) + + self.buttonUp = wx.BitmapButton(self, wx.ID_ANY, wx.NullBitmap) + self.buttonUp.SetSize(self.buttonUp.GetBestSize()) + sizer_5.Add(self.buttonUp, 0, wx.ALL, 5) + + self.buttonDown = wx.BitmapButton(self, wx.ID_ANY, wx.NullBitmap) + self.buttonDown.SetSize(self.buttonDown.GetBestSize()) + sizer_5.Add(self.buttonDown, 0, wx.ALL, 5) + + sizer_5.Add((0, 0), 1, 0, 0) + + grid_sizer_1 = wx.GridSizer(1, 2, 10, 10) + sizer_1.Add(grid_sizer_1, 0, wx.ALL, 5) + + self.buttonAdd = wx.Button(self, wx.ID_ADD, "Add") + grid_sizer_1.Add(self.buttonAdd, 0, 0, 0) + + self.buttonDelete = wx.Button(self, wx.ID_DELETE, "Delete") + grid_sizer_1.Add(self.buttonDelete, 0, 0, 0) + + self.static_line_1 = wx.StaticLine(self, wx.ID_ANY) + sizer_1.Add(self.static_line_1, 0, wx.EXPAND, 0) + + sizer_3 = wx.BoxSizer(wx.HORIZONTAL) + sizer_1.Add(sizer_3, 0, wx.EXPAND, 0) + + sizer_3.Add((20, 20), 1, wx.EXPAND, 0) + + self.goButton = wx.Button(self, wx.ID_OK, "OK") + sizer_3.Add(self.goButton, 0, wx.ALL, 5) + + self.cancelButton = wx.Button(self, wx.ID_CANCEL, "Cancel") + sizer_3.Add(self.cancelButton, 0, wx.ALL, 5) + + self.SetSizer(sizer_1) + sizer_1.Fit(self) + + self.Layout() + + self.Bind(wx.EVT_LIST_COL_CLICK, self.onColClick, self.listCtrlFiles) + self.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.onEndLabelEdit, self.listCtrlFiles) + self.Bind(wx.EVT_BUTTON, self.onUp, self.buttonUp) + self.Bind(wx.EVT_BUTTON, self.onDown, self.buttonDown) + self.Bind(wx.EVT_BUTTON, self.onAdd, self.buttonAdd) + self.Bind(wx.EVT_BUTTON, self.onDelete, self.buttonDelete) + self.Bind(wx.EVT_BUTTON, self.onOK, self.goButton) + self.Bind(wx.EVT_BUTTON, self.onCancel, self.cancelButton) + # end wxGlade + self.buttonUp.SetBitmapLabel(wx.ArtProvider.GetBitmap(wx.ART_GO_UP)) + self.buttonDown.SetBitmapLabel(wx.ArtProvider.GetBitmap(wx.ART_GO_DOWN)) + self.__customProperties() + + def __customProperties(self): + """Set the custom properties.""" + self.fit = None + self.reverse = False # Reverse the sort? + self.fullpath = "." + self.datasets = [] # Contains (temperature, filename) tuples + # temperature is a float and comes first for easy sorting + + self.listCtrlFiles.InsertColumn(0, "Temperature") + self.listCtrlFiles.InsertColumn(1, "Data Set") + self.listCtrlFiles.SetColumnWidth(0, -2) + + # Define tooltips. + self.setToolTips(tooltips.temperatureseriespanel) + return + +
+[docs] + def onEndLabelEdit(self, event): # wxGlade: TemperatureSeriesPanel.<event_handler> + """Update the temperature in the datasets.""" + index = event.GetIndex() + text = event.GetText() + temperature = 300.0 + try: + temperature = float(text) + except ValueError: + event.Veto() + return + if temperature <= 0: + event.Veto() + return + # update the internal information + self.datasets[index][0] = temperature + self.reverse = False + return
+ + +
+[docs] + def onOK(self, event): # wxGlade: TemperatureSeriesPanel.<event_handler> + """Let's go!""" + paths = [tp[1] for tp in self.datasets] + temperatures = [tp[0] for tp in self.datasets] + org = makeTemperatureSeries(self.mainFrame.control, self.fit, paths, temperatures) + self.treeCtrlMain.ExtendProjectTree(org, clear=False) + self.mainFrame.needsSave() + self.onCancel(event) + return
+ + +
+[docs] + def onCancel(self, event): # wxGlade: TemperatureSeriesPanel.<event_handler> + """Let's go, but not actually do anything.""" + self.mainFrame.setMode("fitting") + self.treeCtrlMain.UnselectAll() + self.mainFrame.switchRightPanel("blank") + return
+ + +
+[docs] + def onUp(self, event): # wxGlade: TemperatureSeriesPanel.<event_handler> + """Move an item in the list up.""" + index = self.listCtrlFiles.GetFirstSelected() + if index > 0: + temp = self.datasets[index] + self.datasets[index] = self.datasets[index - 1] + self.datasets[index - 1] = temp + self.fillList() + self.listCtrlFiles.Select(index - 1) + return
+ + +
+[docs] + def onDown(self, event): # wxGlade: TemperatureSeriesPanel.<event_handler> + """Move an item in the list down.""" + index = self.listCtrlFiles.GetFirstSelected() + if index > -1 and index != len(self.datasets) - 1: + temp = self.datasets[index] + self.datasets[index] = self.datasets[index + 1] + self.datasets[index + 1] = temp + self.fillList() + self.listCtrlFiles.Select(index + 1) + return
+ + +
+[docs] + def onAdd(self, event): # wxGlade: TemperatureSeriesPanel.<event_handler> + """Append files to the list.""" + dir, filename = os.path.split(self.fullpath) + if not dir: + dir = self.mainFrame.workpath + + matchstring = "PDF data files (*.gr)|*.gr|PDF fit files (*.fgr)|*.fgr|PDF fit files (*.fit)|*.fit|PDF calculation files (*.cgr)|*.cgr|PDF calculation files (*.calc)|*.calc|All Files|*" # noqa: E501 + d = wx.FileDialog( + None, + "Choose files", + dir, + "", + matchstring, + wx.FD_OPEN | wx.FD_FILE_MUST_EXIST | wx.FD_MULTIPLE, + ) + paths = [] + if d.ShowModal() == wx.ID_OK: + paths = d.GetPaths() + d.Destroy() + + # Assign the temperatures. Default to 300.0 + newdatasets = [] + for path in paths: + self.fullpath = path + self.mainFrame.workpath = os.path.dirname(path) + + # Look for the temperature in the filename + temperature = 300.0 + rx = {"f": r"(?:\d+(?:\.\d*)?|\d*\.\d+)"} + # Search for T123, t123, Temp123, temp123, 123k, 123K. + # Some filenames fool this, e.g. "test1.dat" will match '1' since it + # is preceded by a 't'. + # Is there a better regexp? Probably... + regexp = ( + r"""(?:[Tt](?:emp(?:erature)?)?(%(f)s))| + (?:(?<![a-zA-Z0-9])(%(f)s)[Kk]) + """ + % rx + ) + res = re.search(regexp, os.path.basename(path), re.VERBOSE) + if res: + groups = res.groups() + if groups[0] is not None: + temperature = float(res.groups()[0]) + else: + temperature = float(res.groups()[1]) + else: + # Look in the file + infile = open(path, "r") + datastring = infile.read() + infile.close() + # Look for it first in the file + res = re.search(r"^#+ start data\s*(?:#.*\s+)*", datastring, re.M) + # start_data is position where the first data line starts + if res: + start_data = res.end() + else: + res = re.search(r"^[^#]", datastring, re.M) + if res: + start_data = res.start() + else: + start_data = 0 + header = datastring[:start_data] + # parse header to get temperature + regexp = r"\b(?:temp|temperature|T)\ *=\ *(%(f)s)\b" % rx + res = re.search(regexp, header) + if res: + temperature = float(res.groups()[0]) + # Add the new path + if temperature <= 0: + temperature = 300.0 + newdatasets.append([temperature, path]) + + # DONT Sort the new paths according to temperature + # newdatasets.sort() + self.datasets.extend(newdatasets) + self.fillList() + return
+ + +
+[docs] + def onDelete(self, event): # wxGlade: TemperatureSeriesPanel.<event_handler> + """Delete selected files from the list.""" + idxlist = [] + item = self.listCtrlFiles.GetFirstSelected() + while item != -1: + idxlist.append(item) + item = self.listCtrlFiles.GetNextSelected(item) + + idxlist.reverse() + for item in idxlist: + del self.datasets[item] + self.fillList() + return
+ + +
+[docs] + def onColClick(self, event): # wxGlade: TemperatureSeriesPanel.<event_handler> + """Sort by temperature.""" + column = event.GetColumn() + # sort by temperature + if column == 0: + sortkey = lambda tf: float(tf[0]) # noqa: E731 + # sort by filename with numerical comparison of digits + elif column == 1: + filenames = [f for t, f in self.datasets] + numericStringSort(filenames) + order = dict(zip(filenames, range(len(filenames)))) + sortkey = lambda tf: order[tf[1]] # noqa: E731 + # ignore unhandled columns + else: + return + self.datasets.sort(key=sortkey, reverse=self.reverse) + self.reverse = not self.reverse + self.fillList() + return
+ + + # Utility functions +
+[docs] + def fillList(self): + """Fill the list with the datasets.""" + self.listCtrlFiles.DeleteAllItems() + names = [pair[1] for pair in self.datasets] + cp = os.path.commonprefix(names) + # We want to break at the last path/separator in the common prefix + idx = cp.rfind(os.path.sep) + if idx == -1: + idx = len(cp) + for temperature, filename in self.datasets: + shortname = "..." + filename[idx:] + # index = self.listCtrlFiles.InsertItem(sys.maxsize, str(temperature)) #doesn't work for windows + index = self.listCtrlFiles.InsertItem(100000, str(temperature)) + self.listCtrlFiles.SetItem(index, 1, shortname) + return
+ + + # Needed by mainframe +
+[docs] + def treeSelectionUpdate(self, node): + """Set the current fit when the tree selection changes.""" + nodetype = self.treeCtrlMain.GetNodeType(node) + if nodetype == "fit": + self.fit = self.treeCtrlMain.GetControlData(node) + self.refresh() + return
+ + + # Required by PDFPanel +
+[docs] + def refresh(self): + """Block out OK button if there is no fit. + + This also blocks OK if the fit has no datasets or structures. + """ + # We can't rely on Veto to block unwanted tree selections on windows. + # So, we have to check for errors here. + node = None + nodetype = None + selections = self.treeCtrlMain.GetSelections() + if selections: + node = selections[0] + nodetype = self.treeCtrlMain.GetNodeType(node) + + if node and nodetype == "fit" and self.fit and self.fit.hasDataSets() and self.fit.hasStructures(): + self.goButton.Enable() + else: + self.goButton.Enable(False) + return
+
+ + + +# end of class TemperatureSeriesPanel +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/tooltips.html b/_modules/diffpy/pdfgui/gui/tooltips.html new file mode 100644 index 00000000..2a1fde7a --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/tooltips.html @@ -0,0 +1,301 @@ + + + + + + + + diffpy.pdfgui.gui.tooltips — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for diffpy.pdfgui.gui.tooltips

+#!/usr/bin/env python
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2007 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Dmitriy Bryndin
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+"""Tooltips for pdfgui panels."""
+
+
+
+[docs] +def isalias(s): + return s[1:-1] and s[:: len(s) - 1] == "{}" and s[1:-1].replace("_", "").isalnum()
+ + + +def _expand_tooltip_aliases(ttps): + "Replace aliased equivalent values {other} in tooltip strings." + for n, t in list(ttps.items()): + if not isalias(t): + continue + t1 = t.format(**ttps) + assert not isalias(t1), "chained tooltip alias is not allowed" + ttps[n] = t1 + return ttps + + +datasetconfigurepanel = { + # 'panelNameLabel' : '', # StaticText "Data Set Configuration" + "radioBoxStype": "Radiation type", # RadioBox "Scatterer Type", choices=["Neutron", "X-ray"] + "radioBoxSampling": "Fit sampling type", # RadioBox "Scatterer Type", choices=["Default", "Nyquist", "Custom"] + # 'labelDataRange' : '', # StaticText "Data Range" + "textCtrlDataFrom": "Data r_min", # TextCtrl + # 'labelDataTo' : '', # StaticText "to" + "textCtrlDataTo": "Data r_max", # TextCtrl + # 'labelFitRange' : '', # StaticText "Fit Range" + "textCtrlDataStep": "Step size in the data", # TextCtrl + "textCtrlFitFrom": "Fit r_min", # TextCtrl + # 'labelFitTo' : '', # StaticText "to" + "textCtrlFitTo": "Fit r_max", # TextCtrl + "textCtrlFitStep": "Step size in the fit", # TextCtrl + # 'labelScaleFactor' : '', # StaticText "Scale Factor" + "textCtrlScaleFactor": "Data scale factor", # TextCtrl + # 'labelQmax' : '', # StaticText "Qmax" + "textCtrlQmax": "Upper limit used for Fourier transform to obtain data PDF", # TextCtrl + # 'labelQdamp' : '', # StaticText "Qdamp" + "textCtrlQdamp": "Resolution dampening factor", # TextCtrl + # 'labelQbroad' : '', # StaticText "Qbroad" + "textCtrlQbroad": "Resolution peak broadening factor", # TextCtrl + # 'labelTemperature' : '', # StaticText "Temperature" + "textCtrlTemperature": "Temperature at which the data were collected", # TextCtrl + # 'labelDoping' : '', # StaticText "Doping" + "textCtrlDoping": "Sample characteristic doping level (if applicable)", # TextCtrl +} + +datasetconstraintpanel = { + "panelNameLabel": "", # StaticText "Data Set Constraints" + "labelScaleFactor": "", # StaticText "Scale Factor" + "textCtrlScaleFactor": "Data scale factor", # TextCtrl + "labelQdamp": "", # StaticText "Qdamp" + "textCtrlQdamp": "Resolution dampening factor", # TextCtrl + "labelQbroad": "", # StaticText "Qbroad" + "textCtrlQbroad": "Resolution peak broadening factor", # TextCtrl +} + +datasetresultspanel = { + "panelNameLabel": "", # StaticText "Data Set Results" + "labelScaleFactor": "", # StaticText "Scale Factor" + "textCtrlScaleFactor": "Data scale factor", # TextCtrl + "labelQdamp": "", # StaticText "Qdamp" + "textCtrlQdamp": "Resolution dampening factor", # TextCtrl + "labelQbroad": "", # StaticText "Qbroad" + "textCtrlQbroad": "Resolution peak broadening factor", # TextCtrl +} + + +dopingseriespanel = { + # 'instructionsLabel' : '', # StaticText "Select a fit from the tree on the left then add + # datasets and assign\ndoping elements and values below. If you + # have not set up a fit to be\nthe template for the series, hit + # cancel and rerun this macro once a\nfit has been created." + # 'labelBaseElement' : '', # StaticText "Base element" + # 'textCtrlBaseElement' : '', # TextCtrl + # 'labelDopant' : '', # StaticText "Dopant" + # 'textCtrlDopant' : '', # TextCtrl + "listCtrlFiles": "Click header to sort by doping", # AutoWidthListCtrl + # 'buttonUp' : '', # BitmapButton + # 'buttonDown' : '', # BitmapButton + # 'buttonAdd' : '', # Button "Add" + # 'buttonDelete' : '', # Button "Delete" + # 'goButton' : '', # Button "OK" + # 'cancelButton' : '', # Button "Cancel" +} + +phasepanel = _expand_tooltip_aliases( + { + # 'sizerLatticeParameters_staticbox' : '', # StaticBox + # 'sizerAdditionalParameters_staticbox' : '', # StaticBox + # 'sizerAtoms_staticbox' : '', # StaticBox + # 'sizerPanelName_staticbox' : '', # StaticBox + # 'labelPanelName' : '', # StaticText "Phase Configuration" + "labelA": "{textCtrlA}", # StaticText "a" + "textCtrlA": "Lattice parameter a", # TextCtrl + "labelB": "{textCtrlB}", # StaticText "b" + "textCtrlB": "Lattice parameter b", # TextCtrl + "labelC": "{textCtrlC}", # StaticText "c" + "textCtrlC": "Lattice parameter c", # TextCtrl + "labelAlpha": "{textCtrlAlpha}", # StaticText "alpha" + "textCtrlAlpha": "Lattice angle alpha", # TextCtrl + "labelBeta": "{textCtrlBeta}", # StaticText "beta" + "textCtrlBeta": "Lattice angle beta", # TextCtrl + "labelGamma": "{textCtrlGamma}", # StaticText "gamma" + "textCtrlGamma": "Lattice angle gamma", # TextCtrl + "labelScaleFactor": "{textCtrlScaleFactor}", # StaticText "Scale Factor" + "textCtrlScaleFactor": "Phase scale factor", # TextCtrl + "labelDelta1": "{textCtrlDelta1}", # StaticText "delta1" + "textCtrlDelta1": "Linear atomic correlation factor", # TextCtrl + "labelDelta2": "{textCtrlDelta2}", # StaticText "delta2" + "textCtrlDelta2": "Quadratic atomic correlation factor", # TextCtrl + "labelSratio": "{textCtrlSratio}", # StaticText "sratio" + "textCtrlSratio": "Low r peak sharpening", # TextCtrl + "labelRcut": "{textCtrlRcut}", # StaticText "rcut" + "textCtrlRcut": "Peak sharpening cutoff", # TextCtrl + "labelStepcut": "{textCtrlStepcut}", # StaticText "stepcut" + "textCtrlStepcut": "Cutoff for profile step-function", # TextCtrl + "labelSpdiameter": "{textCtrlSpdiameter}", # StaticText "Spdiameter" + "textCtrlSpdiameter": "Spherical nanoparticle amplitude correction", + # 'labelIncludedPairs' : '', # StaticText "Included Pairs" + "textCtrlIncludedPairs": """[!]{element|indexOrRange|all}-[!]{element|indexOrRange|all} +Examples: +all-all all possible pairs +Na-Na only Na-Na pairs +all-all, !Na- all pairs except Na-Na +all-all, -!Na same as previous +Na-1:4 pairs of Na and first 4 atoms +all-all, !Cl-!Cl exclude any pairs containing Cl +all-all, !Cl-, -!Cl same as previous +1-all only pairs including the first atom""", # TextCtrl "all-all" + # 'gridAtoms' : '', # AutoWidthLabelsGrid + } +) + + +plotpanel = { + # 'xDataCombo' : '', # ComboBox + # 'yDataList' : '', # KeyEventsListCtrl + "offsetLabel": "The vertical gap between stacked plots", # StaticText "offset" + # 'offsetTextCtrl' : '', # TextCtrl + "plotButton": "Plot the selected data", # Button "Plot" + "resetButton": "Reset the plot configuration", # Button "Reset" +} + + +preferencespanel = { + "structureDirCheckBox": ( + "Remember the structures directory across sessions. " + "If unchecked, the initial structures directory will " + "default to the current path." + ), + "dataDirCheckBox": ( + "Remember the data set directory across sessions. " + "If unchecked, the initial data set directory will " + "default to the current path." + ), + "textCtrlViewer": ("The name of the structure viewer executable, " "e.g., 'atomeye' or 'pymol'."), + "textCtrlArgument": """\ +The command-line arguments to the structure viewer. +'%s' represents the file name that will be passed to the viewer. +Command-line switches placed here will be passed as well. +E. g. '%s' or '-c %s' (for pymol).\ + """, + "choiceFormat": "Choose a file format the structure viewer accepts.", +} + + +temperatureseriespanel = { + # 'instructionsLabel' : '', # StaticText "Select a fit from the tree on the left + # then add datasets and assign\ntemperatues below. If you have not set up a fit to + # be the template\nfor the series, hit cancel and rerun this macro once a fit has been\ncreated." + "listCtrlFiles": "Click header to sort by temperature", # AutoWidthListCtrl + # 'buttonUp' : '', # BitmapButton + # 'buttonDown' : '', # BitmapButton + # 'buttonAdd' : '', # Button "Add" + # 'buttonDelete' : '', # Button "Delete" + # 'goButton' : '', # Button "OK" + # 'cancelButton' : '', # Button "Cancel" +} +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/welcomepanel.html b/_modules/diffpy/pdfgui/gui/welcomepanel.html new file mode 100644 index 00000000..ebf3d674 --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/welcomepanel.html @@ -0,0 +1,166 @@ + + + + + + + + diffpy.pdfgui.gui.welcomepanel — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.welcomepanel

+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+
+# generated by wxGlade 0.6.3 on Wed Mar 11 13:17:19 2009
+
+import wx
+
+from diffpy.pdfgui.gui.pdfguiglobals import iconpath
+from diffpy.pdfgui.gui.pdfpanel import PDFPanel
+
+
+
+[docs] +class WelcomePanel(wx.Panel, PDFPanel): + def __init__(self, *args, **kwds): + PDFPanel.__init__(self) + wx.Panel.__init__(self, *args, **kwds) + kwds["style"] = wx.TAB_TRAVERSAL + bitmap = wx.Bitmap(iconpath("titlepage.png")) + self.bitmap_1 = wx.StaticBitmap(self, -1, bitmap) + + self.__set_properties() + self.__do_layout() + return + + def __set_properties(self): + return + + def __do_layout(self): + sizer_1 = wx.BoxSizer(wx.HORIZONTAL) + sizer_2 = wx.BoxSizer(wx.VERTICAL) + sizer_2.Add(self.bitmap_1, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_CENTER_VERTICAL, 0) + sizer_1.Add(sizer_2, 1, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_CENTER_VERTICAL, 0) + self.SetSizer(sizer_1) + sizer_1.Fit(self) + return + + # Methods overloaded from PDFPanel +
+[docs] + def refresh(self): + return
+
+ + + +# end of class WelcomePanel +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/wxextensions/autowidthlabelsgrid.html b/_modules/diffpy/pdfgui/gui/wxextensions/autowidthlabelsgrid.html new file mode 100644 index 00000000..d25761c4 --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/wxextensions/autowidthlabelsgrid.html @@ -0,0 +1,171 @@ + + + + + + + + diffpy.pdfgui.gui.wxextensions.autowidthlabelsgrid — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.wxextensions.autowidthlabelsgrid

+#!/usr/bin/env python
+##############################################################################
+#
+# wxextensions      by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Dmitriy Bryndin
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+"""This module contains AutoWidthListCtrl, a wxListCtrl object that
+automatically adjusts the width of its columns."""
+
+
+import wx
+import wx.grid
+
+
+
+[docs] +class AutoWidthLabelsGrid(wx.grid.Grid): + """Wx grid which allows labels auto sizing.""" + + # def __init__(self, parent, state, size): + # wx.grid.Grid.__init__(self, parent, state, size) + +
+[docs] + def AutosizeLabels(self, rows=True, cols=False): + # Common setup. + devContext = wx.ScreenDC() + devContext.SetFont(self.GetLabelFont()) + + # First do row labels. + if rows: + maxWidth = 0 + curRow = self.GetNumberRows() - 1 + while curRow >= 0: + curWidth = devContext.GetTextExtent("M%s" % (self.GetRowLabelValue(curRow)))[0] + if curWidth > maxWidth: + maxWidth = curWidth + curRow = curRow - 1 + self.SetRowLabelSize(maxWidth) + + # Then column labels. + if cols: + maxHeight = 0 + curCol = self.GetNumberCols() - 1 + while curCol >= 0: + (w, h, d, l) = devContext.GetFullTextExtent(self.GetColLabelValue(curCol)) + curHeight = h + d + l + 4 + if curHeight > maxHeight: + maxHeight = curHeight + curCol = curCol - 1 + self.SetColLabelSize(maxHeight) + return
+
+ + + +# End of class AutoWidthLabelsGrid +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/wxextensions/listctrls.html b/_modules/diffpy/pdfgui/gui/wxextensions/listctrls.html new file mode 100644 index 00000000..fd1d2c16 --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/wxextensions/listctrls.html @@ -0,0 +1,327 @@ + + + + + + + + diffpy.pdfgui.gui.wxextensions.listctrls — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.wxextensions.listctrls

+#!/usr/bin/env python
+##############################################################################
+#
+# wxextensions      by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+"""This module contains custom wxListCtrl subclasses.
+AutoWidthListCtrl  - A wxListCtrl object that automatically adjusts the width of
+its columns.
+ColumnSortListCtrl - An AutoWidthListCtrl that sorts its entries when the column
+header is clicked.
+KeyEventsListCtrl  - A ColumnSortListCtrl that selects and item as you type its
+name.
+"""
+
+
+import wx
+import wx.lib.mixins.listctrl as listmix
+
+
+
+[docs] +class AutoWidthListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin): + """WxListCtrl subclass that automatically adjusts its column width.""" + + def __init__(self, parent, ID, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, *args, **kwargs): + wx.ListCtrl.__init__(self, parent, ID, pos, size, style, *args, **kwargs) + listmix.ListCtrlAutoWidthMixin.__init__(self) + +
+[docs] + def clearSelections(self): + """Clear all selections in the list.""" + for item in range(self.GetItemCount()): + self.Select(item, on=0) + return
+ + +
+[docs] + def setSelection(self, itemtext=None): + """Convenience function for simple selection of a list item by label. + + itemtext -- The label of the item to select. If itemtext is None + (default) then all items will be deselected. + """ + # Clear all selections + self.clearSelections() + + # Set the selected item + item = 0 + if itemtext: + item = self.FindItem(-1, itemtext) + self.Select(item) + self.Focus(item) + return item
+
+ + + +# end AutoWidthListCtrl + + +
+[docs] +class ColumnSortListCtrl(AutoWidthListCtrl, listmix.ColumnSorterMixin): + """AutoWidthListCtrl subclass that sorts its columns when the column header + is pressed. + + This ListCtrl requires an itemDataMap member dictionary to be + initialized before the sorting capabilities can be realized. This + dictionary simply references the ListCtrl's entries by a unique + number. This number must be stored as the ItemData (with + SetItemData) of the entry. The member data must be in the form of a + tuple, where the tuple has a number of entries as the ListCtrl has + columns. The sorting routine sorts the items in the ListCtrl by the + entries in this tuple. + """ + + def __init__(self, parent, ID, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, *args, **kwargs): + AutoWidthListCtrl.__init__(self, parent, ID, pos, size, style, *args, **kwargs) + listmix.ListCtrlAutoWidthMixin.__init__(self) + +
+[docs] + def GetListCtrl(self): + """This method is required by the sorter mixin.""" + return self
+ + +
+[docs] + def initializeSorter(self): + """Initialize the column sorter mixin after the ListCtrl is filled. + + This method must be called whenever the itemDataMap is altered. + """ + numcol = self.GetColumnCount() + listmix.ColumnSorterMixin.__init__(self, numcol) + return
+ + +
+[docs] + def makeIDM(self): + """This method automatically sets up the itemDataMap. + + The itemDataMap gets filled with the current ListCtrl entries. + The itemDataMap does not update automatically when the list is + changed. To update the itemDataMap this method must be called + again. initializeSorter should be called after a call to this + method. + """ + numcol = self.GetColumnCount() + numrow = self.GetItemCount() + self.itemDataMap = {} + for i in range(numrow): + infolist = [] + for j in range(numcol): + infolist.append(self.GetItem(i, j).GetText()) + self.itemDataMap[i + 1] = tuple(infolist) + self.SetItemData(i, i + 1) + return
+
+ + + +# end ColumnSortListCtrl + + +
+[docs] +class KeyEventsListCtrl(ColumnSortListCtrl): + """ColumnSortListCtrl that catches key events and selects the item that + matches. + + It only searches for items in the first column. + """ + + def __init__(self, parent, id, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, *args, **kwargs): + ColumnSortListCtrl.__init__(self, parent, id, pos, size, style, *args, **kwargs) + self.typedText = "" + self.Bind(wx.EVT_KEY_DOWN, self.OnKey) + +
+[docs] + def findPrefix(self, prefix): + if prefix: + prefix = prefix.lower() + length = len(prefix) + + for x in range(self.GetItemCount()): + text = self.GetItemText(x) + text = text.lower() + + if text[:length] == prefix: + return x + + return -1
+ + +
+[docs] + def OnKey(self, evt): + key = evt.GetKeyCode() + + # Select All - Ctrl+A + if evt.ControlDown() and key == 65: + for item in range(self.GetItemCount()): + self.Select(item) + return + + # Search for name + if key >= 32 and key <= 127: + self.typedText = self.typedText + chr(key) + item = self.findPrefix(self.typedText) + + if item != -1: + itemtext = self.GetItemText(item) + self.setSelection(itemtext) + + elif key == wx.WXK_BACK: + self.typedText = self.typedText[:-1] + + if not self.typedText: + itemtext = self.GetItemText(0) + self.setSelection(itemtext) + else: + item = self.findPrefix(self.typedText) + + if item != -1: + itemtext = self.GetItemText(item) + self.setSelection(itemtext) + + else: + self.typedText = "" + evt.Skip()
+ + +
+[docs] + def OnKeyDown(self, evt): + pass
+
+ + + +# End of class KeyEventsListCtrl + +# verify inheritance of all ListCtrl classes +assert issubclass(AutoWidthListCtrl, wx.ListCtrl) +assert issubclass(ColumnSortListCtrl, wx.ListCtrl) +assert issubclass(KeyEventsListCtrl, wx.ListCtrl) +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/wxextensions/paneldialog.html b/_modules/diffpy/pdfgui/gui/wxextensions/paneldialog.html new file mode 100644 index 00000000..3b0b6232 --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/wxextensions/paneldialog.html @@ -0,0 +1,184 @@ + + + + + + + + diffpy.pdfgui.gui.wxextensions.paneldialog — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.wxextensions.paneldialog

+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+# generated by wxGlade 0.4.1 on Wed Mar 29 15:15:14 2006
+##############################################################################
+#
+# wxextensions      by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Dmitriy Bryndin
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+"""This module contains the PanelDialog class, a simple class that turns any
+panel into a dialog."""
+
+
+import wx
+
+
+
+[docs] +class PanelDialog(wx.Dialog): + """This class will turn any panel into a dialog. + + Using this makes for quicker development and encourages the + developer to design a gui as a collection of panels, instead of a + monolithic mega-panel. + """ + + def __init__(self, *args, **kwds): + """Initialize the PanelDialog. + + This takes the same args and kwds as wxDialog. See the wxDialog + documentation for more information. + + Unless specified, style is automatically set as + wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER + + Creating a PanelDialog requires three steps. 1) Create the + PanelDialog. 2) Create the Panel, with the new PanelDialog as + the parent. 3) Call the setPanel method of the PanelDialog with + the new Panel as the the argument. + """ + if not hasattr(kwds, "style"): + kwds["style"] = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER + wx.Dialog.__init__(self, *args, **kwds) + return + +
+[docs] + def setPanel(self, panel): + """Call this method to add the panel to the dialog.""" + self.panel = panel + self.__set_properties() + self.__do_layout() + return
+ + + def __set_properties(self): + return + + def __do_layout(self): + sizer_1 = wx.BoxSizer(wx.HORIZONTAL) + sizer_1.Add(self.panel, 1, wx.EXPAND, 0) + self.SetAutoLayout(True) + self.SetSizer(sizer_1) + sizer_1.Fit(self) + sizer_1.SetSizeHints(self) + self.Layout() + return
+ + + +# End of class PanelDialog +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/wxextensions/textctrlutils.html b/_modules/diffpy/pdfgui/gui/wxextensions/textctrlutils.html new file mode 100644 index 00000000..e08afa02 --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/wxextensions/textctrlutils.html @@ -0,0 +1,161 @@ + + + + + + + + diffpy.pdfgui.gui.wxextensions.textctrlutils — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.wxextensions.textctrlutils

+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+##############################################################################
+#
+# wxextensions      by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2009-2024 trustees of Columbia University in the City of
+#                   New York.
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+"""This module contains utilities that can be used with wxTextCtrls."""
+
+
+import wx
+
+
+
+[docs] +def textCtrlAsGridCell(panel, event): + """Process a textCtrl key event as if the textCtrl was a grid cell. + + This catches ESC and ENTER events in textCtrls and processes them as if the + textCtrl were a grid cell. This method can be bound to the wx.EVT_KEY_DOWN + event of any textCtrl. See phaseconfigurepanel.py in diffpy.pdfgui.gui for + an example. + + ESC -- Cancel the edit and highlight the text. This requires that + panel has a _focusedText attribute that stores the previous + value. + ENTER -- Confirm the edit and move to the next cell (the default TAB + behavior). + """ + key = event.GetKeyCode() + + textctrl = event.GetEventObject() + + # ESC - cancel the edit + if key == 27: + # Restore the original value + textctrl.ChangeValue(panel._focusedText) + # Now reselect the text + wx.CallAfter(textctrl.SetSelection, -1, -1) + # ENTER - Act like TAB + elif key == 13: + wx.CallAfter(textctrl.Navigate) + else: + event.Skip() + return
+ +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/gui/wxextensions/validators.html b/_modules/diffpy/pdfgui/gui/wxextensions/validators.html new file mode 100644 index 00000000..36120604 --- /dev/null +++ b/_modules/diffpy/pdfgui/gui/wxextensions/validators.html @@ -0,0 +1,258 @@ + + + + + + + + diffpy.pdfgui.gui.wxextensions.validators — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for diffpy.pdfgui.gui.wxextensions.validators

+#!/usr/bin/env python
+##############################################################################
+#
+# wxextensions      by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2006 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Chris Farrow
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+import string
+
+import wx
+
+"""This module contains TextValidator, which is an input validator for the
+wxTextCtrl. See the wxPython documentation for wxTextCtrl for more about text
+validators. Three constants are defined for use in TextValidator: ALPHA_ONLY,
+DIGIT_ONLY, and FLOAT_ONLY. See the TextValidator class for how these are used.
+"""
+
+ALPHA_ONLY = 1
+DIGIT_ONLY = 2
+FLOAT_ONLY = 3
+
+
+
+[docs] +class TextValidator(wx.Validator): + """This validator is designed to check text input for wxTextCtrls. + + (It might have uses in other widgets.) It can validate for letters + only, digits only, floats only, and can allow for a negative at the + beginning of a digit string or a negative float. + """ + + def __init__(self, flag=DIGIT_ONLY, allowNeg=False): + """Initialize the validator. + + flag -- DIGIT_ONLY, allow only digits (default) + ALPHA_ONLY, allow only letters + FLOAT_ONLY, allow only floats + + allowNeg -- Allow a negative sign in front of DIGIT_ONLY, or + FLOAT_ONLY text. (default False) + """ + wx.Validator.__init__(self) + self.flag = flag + self.allowNeg = allowNeg + self.Bind(wx.EVT_CHAR, self.OnChar) + +
+[docs] + def Clone(self): + return TextValidator(self.flag, self.allowNeg)
+ + +
+[docs] + def Validate(self, win): + tc = self.GetWindow() + val = tc.GetValue() + + if self.flag == ALPHA_ONLY: + return val.isalpha() + + elif self.flag == DIGIT_ONLY: + if self.allowNeg: + val1 = val[:1].lstrip("-") + val[1:] + else: + val1 = val + return val1.isdigit() + + elif self.flag == FLOAT_ONLY: + try: + x = float(val) + if x < 0 and not self.allowNeg: + return False + except ValueError: + return False + + return True
+ + +
+[docs] + def OnChar(self, event): + key = event.GetKeyCode() + + if key < wx.WXK_SPACE or key == wx.WXK_DELETE or key > 255: + event.Skip() + return + + if self.flag == ALPHA_ONLY and chr(key) in string.ascii_letters: + event.Skip() + return + + # resolve the new value here + win = self.GetWindow() + val = win.GetValue() + insertion = win.GetInsertionPoint() + first, last = win.GetSelection() + if first != last: + val = val[:first] + val[last:] + insertion = first + newval = val[:insertion] + chr(key) + val[insertion:] + + if self.flag == DIGIT_ONLY: + newval1 = newval + if self.allowNeg: + newval1 = newval[:1].lstrip("-") + newval[1:] + if newval1.isdigit(): + event.Skip() + return + + if self.flag == FLOAT_ONLY: + try: + x = float(newval + "1") # Catches "1e", a float to be + if x >= 0 or self.allowNeg: + event.Skip() + return + + except ValueError: + pass + + if not wx.Validator.IsSilent(): + wx.Bell() + + # Returning without calling even. Skip eats the event before it + # gets to the text control + return
+ + + # These are needed so the validator can work in dialogs. +
+[docs] + def TransferToWindow(self): + return True
+ + +
+[docs] + def TransferFromWindow(self): + return True
+
+ + + +# End of class TextValidator +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/tui.html b/_modules/diffpy/pdfgui/tui.html new file mode 100644 index 00000000..bc86138e --- /dev/null +++ b/_modules/diffpy/pdfgui/tui.html @@ -0,0 +1,286 @@ + + + + + + + + diffpy.pdfgui.tui — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for diffpy.pdfgui.tui

+#!/usr/bin/env python
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2008 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Pavol Juhas
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+"""Text user interface - utilities for extracting data from project files.
+"""
+
+
+
+[docs] +class LoadProject: + """Load and access data in pdfgui project file. + + Protected instance data: + + _project -- instance of PDFGuiControl with loaded project file. + """ + + # public methods + + def __init__(self, filename=None): + """Initialize LoadProject object, by reading existing project file. + + filename -- path to PDFgui project file. + """ + from diffpy.pdfgui.control.pdfguicontrol import PDFGuiControl + + self._project = PDFGuiControl() + # business + if filename is not None: + self.load(filename) + return + +
+[docs] + def load(self, filename): + """Load a project. + + filename -- path to PDFgui project file. + + No return value. + """ + self._project.load(filename) + return
+ + +
+[docs] + def save(self, filename): + """Save the project. + + filename -- path where to write the PDFgui project. + + No return value. + """ + self._project.save(filename) + return
+ + +
+[docs] + def getFits(self): + """Get all fits defined in the project file. + + Return list of Fitting objects. + """ + rv = self._project.fits[:] + return rv
+ + +
+[docs] + def getDataSets(self, fits=None): + """Return a list of all datasets contained in specified fits. + + fits -- optional list of Fitting objects that own datasets. + When not specified, get datasets from all fits defined + in the project. + + Return list of FitDataSet objects. + """ + if fits is None: + fitlist = self.getFits() + else: + fitlist = fits + rv = sum([fit.datasets for fit in fitlist], []) + return rv
+ + +
+[docs] + def getCalculations(self, fits=None): + """Return list of all calculations contained in specified fits. + + fits -- optional list of Fitting objects that own datasets. + When not specified, get datasets from all fits defined + in the project. + + Return list of Calculation objects. + """ + if fits is None: + fitlist = self.getFits() + else: + fitlist = fits + rv = sum([fit.calcs for fit in fitlist], []) + return rv
+ + +
+[docs] + def getPhases(self, fits=None): + """Collect all phases contained in specified fits. + + fits -- optional list of Fitting objects that own datasets. + When not specified, get phases from all fits defined + in the project. + + Return list of FitStructure objects. + """ + if fits is None: + fitlist = self.getFits() + else: + fitlist = fits + rv = sum([fit.strucs for fit in fitlist], []) + return rv
+ + +
+[docs] + def getTemperatures(self, datasets=None): + """Extract temperatures from a list of datasets. + + datasets -- optional list of FitDataSet objects. When not + specified, temperatures are extracted from all + datasets in the project. + + Return list of floating point values. The list may contain + None-s for datasets with undefined temperature. + """ + if datasets is None: + dslist = self.getDataSets() + else: + dslist = datasets + temperatures = [ds.metadata.get("temperature") for ds in dslist] + return temperatures
+ + +
+[docs] + def getDopings(self, datasets=None): + """Extract doping values from a list of datasets. + + datasets -- optional list of FitDataSet objects. When not + specified, doping values are extracted from all + datasets in the project. + + Return list of floating point values. The list may contain + None-s for datasets with undefined doping. + """ + if datasets is None: + dslist = self.getDataSets() + else: + dslist = datasets + dopings = [ds.metadata.get("doping") for ds in dslist] + return dopings
+
+ + + +# End of class LoadProject +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/diffpy/pdfgui/utils.html b/_modules/diffpy/pdfgui/utils.html new file mode 100644 index 00000000..c6967b1c --- /dev/null +++ b/_modules/diffpy/pdfgui/utils.html @@ -0,0 +1,184 @@ + + + + + + + + diffpy.pdfgui.utils — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for diffpy.pdfgui.utils

+#!/usr/bin/env python
+##############################################################################
+#
+# PDFgui            by DANSE Diffraction group
+#                   Simon J. L. Billinge
+#                   (c) 2007 trustees of the Michigan State University.
+#                   All rights reserved.
+#
+# File coded by:    Pavol Juhas
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+##############################################################################
+"""Small shared routines:
+    numericStringSort   -- sort list of strings according to numeric value
+    safeCPickleDumps    -- same as pickle.dumps, but safe for NaN and Inf
+"""
+
+
+
+[docs] +def numericStringSort(lst): + """Sort list of strings inplace according to general numeric value. Each + string gets split to string and integer segments to create keys for + comparison. Signs, decimal points and exponents are ignored. + + lst -- sorted list of strings + + No return value to highlight inplace sorting. + """ + import re + + rx = re.compile(r"(\d+)") + keys = [rx.split(s) for s in lst] + for k in keys: + k[1::2] = [int(i) for i in k[1::2]] + newlst = sorted(zip(keys, lst)) + lst[:] = [kv[1] for kv in newlst] + return
+ + + +
+[docs] +def safeCPickleDumps(obj): + """Get pickle representation of an object possibly containing NaN or Inf. + By default it uses pickle.HIGHEST_PROTOCOL, but falls back to ASCII + protocol 0 if there is SystemError frexp() exception. + + obj -- object to be pickled + + Return pickle string. + """ + + import pickle + + ascii_protocol = 0 + try: + s = pickle.dumps(obj, pickle.HIGHEST_PROTOCOL) + except SystemError: + s = pickle.dumps(obj, ascii_protocol) + return s
+ + + +
+[docs] +def asunicode(s): + """Convert string or bytes object to a text type.""" + rv = s + if not isinstance(s, str): + rv = s.decode("utf-8") + return rv
+ + + +# End of file +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/index.html b/_modules/index.html new file mode 100644 index 00000000..020c2a98 --- /dev/null +++ b/_modules/index.html @@ -0,0 +1,172 @@ + + + + + + + + Overview: module code — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + +
  • +
  • +
+
+
+
+
+ +

All modules for which code is available

+ + +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/doc/source/api/diffpy.pdfgui.applications.rst b/_sources/api/diffpy.pdfgui.applications.rst.txt similarity index 100% rename from doc/source/api/diffpy.pdfgui.applications.rst rename to _sources/api/diffpy.pdfgui.applications.rst.txt diff --git a/doc/source/api/diffpy.pdfgui.control.rst b/_sources/api/diffpy.pdfgui.control.rst.txt similarity index 100% rename from doc/source/api/diffpy.pdfgui.control.rst rename to _sources/api/diffpy.pdfgui.control.rst.txt diff --git a/doc/source/api/diffpy.pdfgui.gui.design.rst b/_sources/api/diffpy.pdfgui.gui.design.rst.txt similarity index 100% rename from doc/source/api/diffpy.pdfgui.gui.design.rst rename to _sources/api/diffpy.pdfgui.gui.design.rst.txt diff --git a/doc/source/api/diffpy.pdfgui.gui.rst b/_sources/api/diffpy.pdfgui.gui.rst.txt similarity index 100% rename from doc/source/api/diffpy.pdfgui.gui.rst rename to _sources/api/diffpy.pdfgui.gui.rst.txt diff --git a/doc/source/api/diffpy.pdfgui.gui.wxextensions.rst b/_sources/api/diffpy.pdfgui.gui.wxextensions.rst.txt similarity index 100% rename from doc/source/api/diffpy.pdfgui.gui.wxextensions.rst rename to _sources/api/diffpy.pdfgui.gui.wxextensions.rst.txt diff --git a/doc/source/api/diffpy.pdfgui.icons.rst b/_sources/api/diffpy.pdfgui.icons.rst.txt similarity index 100% rename from doc/source/api/diffpy.pdfgui.icons.rst rename to _sources/api/diffpy.pdfgui.icons.rst.txt diff --git a/doc/source/api/diffpy.pdfgui.rst b/_sources/api/diffpy.pdfgui.rst.txt similarity index 100% rename from doc/source/api/diffpy.pdfgui.rst rename to _sources/api/diffpy.pdfgui.rst.txt diff --git a/doc/source/index.rst b/_sources/index.rst.txt similarity index 91% rename from doc/source/index.rst rename to _sources/index.rst.txt index ba6a58f3..6d042abe 100644 --- a/doc/source/index.rst +++ b/_sources/index.rst.txt @@ -4,7 +4,7 @@ .. |title| replace:: diffpy.pdfgui documentation -``diffpy.pdfgui`` - Graphical user interface program for structure refinements to the atomic pair distribution function. +diffpy.pdfgui - GUI for PDF simulation and structure refinement. | Software version |release| | Last updated |today| @@ -18,7 +18,7 @@ visualization capabilities. PDFgui is a friendly interface to the PDFfit2 refinement engine, with many powerful extensions. To get started, please open the :ref:`manual` -(:download:`pdf `) from the help menu or follow the :ref:`tutorial`. +(:download:`pdf <../manual/pdfgui.pdf>`) from the help menu or follow the :ref:`tutorial`. ======= Authors @@ -87,10 +87,9 @@ Table of contents .. toctree:: :titlesonly: - examples - extras license release + manual Package API ======= diff --git a/doc/source/license.rst b/_sources/license.rst.txt similarity index 100% rename from doc/source/license.rst rename to _sources/license.rst.txt diff --git a/doc/source/manual.rst b/_sources/manual.rst.txt similarity index 100% rename from doc/source/manual.rst rename to _sources/manual.rst.txt diff --git a/doc/source/release.rst b/_sources/release.rst.txt similarity index 100% rename from doc/source/release.rst rename to _sources/release.rst.txt diff --git a/_sources/tutorial.rst.txt b/_sources/tutorial.rst.txt new file mode 100644 index 00000000..7b88c041 --- /dev/null +++ b/_sources/tutorial.rst.txt @@ -0,0 +1,205 @@ +.. _tutorial: + +Tutorial +######## + +Please, have your co-workers or students try it out and let us know if you +have any comments. We want to make it really easy for the new users to get +started with PDFgui. + +======================================= +Lesson 1: Creating simple fit of Ni PDF +======================================= + +Input files: + +- :download:`Ni data ` containing: + 1. Ni-xray.gr - experimental X-ray PDF data + 2. Ni.stru - Ni f.c.c. structure in PDFfit format + +This manual will help you to get started with ``PDFgui``. We strongly recommend that that you refer to +the book `Atomic pair distribution function analysis: a primer` by Simon J. L. Billinge, Kirsten Jensen +Soham Banerjee, Emil S. Bozin, Benjamin A. Frandsen, Maxwell W. Terban and Robert J. Koch, Oxford: +Oxford University Press, 2024. URL: https://global.oup.com/academic/product/atomicpair-distribution-function-analysis-9780198885801?cc=us&lang=en& +for much more extensive and detailed descriptions of carrying out fits with PDFgui (and the related program diffpy-cmi). + +Procedure: + +1. Open ``pdfgui``. Instructions for doing this depend on your system, but an example would be + to open a terminal, activate your pdfgui conda environment, and type ``pdfgui`` at the prompt, + or to double-click a project file on windows. + +2. Create a new Fit: + 1. In the GUI locate the ``Fit Tree`` panel. In the default layout it is at the top left of the page. + 2. With your mouse on that panel, right-click the mouse and select "New Fit" from the pop-up menu. + 3. By default, your fit will be called ``Fit 1``. To give it a more meaningful name, left + click the ``Fit 1`` name. It should open an editable box and you can type in a name for your + fit such as "Fit of Ni structure to Ni data" + 4. Note, an alternative workflow to create a new fit is to find ``New fit`` under the ``Fits`` dropdown menu. + +3. Load structure model: + 1. Carefully place your cursor on to the title of the Fit and right-click. Select "Insert Phase" from the pop-up menu. + 2. Click the "Open" button and navigate to and load the ``Ni.stru`` file that you downloaded. You could select + valid structure model file, a ``.stru`` or a ``.cif`` file. + 3. Note, an alternative workflow for adding structural models is to select ``New Phase`` from the ``Phases`` dropdown menu. + + If you select the Phase in the ``Fit Tree`` by left clicking on it, you will see in the + right panel 3 tabs, ``Configure`` ``Constraints``, ``Results``. Feel free to click one + these tabs and look inside. The Configure panel has the initial inputs from the loaded str or cif file, + The ``Constraints`` panel will hold the constraints we will set up for our fits, it should be empty now, + and the results tab will contain the results of any fit. + + Note that what you see on the right is "Context Dependent", it depends on what you have selected on the left. + By selecting a phase on the left, the tabs on the right contain information about that phase, and so on. + +4. Load experimental PDF data: + 1. As before, hover over your cursor over the title of your fit and right-click. This time select + ``Insert Data Set`` from the pop-up menu. + 2. Navigate to and load the `Ni-xray.gr` file that you downloaded. + + Again, the right panel shows 3 tabs, now for properties of this dataset. + +5. Define what is refined: + 1. Click on the `Ni-xray.gr` data and select the "Constraints" tab. + 2. Type ``@1`` into the "Scale Factor" edit box. + 3. Select the `Ni.stru` phase and its "Constraints" tab. + 4. Fill "a", "b", "c" boxes with ``@5``. + + Here we are defining "variables" that will be refined and giving them names + variable "@1", "@5", etc. and linking them to model parameters by typing them + in the text-box associated with the parameter. So by typing ``@1`` in the + data "Scale-Factor" text box we are saying that we are logically assigning the constraint + equation ``data.scale_factor = variable("@1")``. + + When we assign the three parameters ``a``, ``b`` and ``c`` to the same variable, + ``@5``, we are implicitly ensuring that the refinement will respect + the cubic symmetry of the nickel structure and that ``a = b = c``, because the + three parameters are assigned to the same variable, so however much ``a`` + is changed in the refinement, ``b`` and ``c`` will be changed by the same amount. + Note that the variable ensures that changes to ``a``, ``b`` and ``c`` are always + the same, so we have to also ensure that the initial values of ``a``, ``b`` and ``c`` + are the same as each other to ensure that the structure is cubic and remains so. + + PDFgui allows us to express more complex constraint equations than + simply assigning a parameter to a variable. + In general, we can type into be Constraints tab text box any math expression: + ``f(@n1, @n2, @n3, ...)`` where + ``@n1`` stands for the fitted parameter, where it is understood that + ``n1, n2, ...`` are arbitrary positive integers. + This allows simple linking of related variables. For example, if we want to allow a + crystallographic site to contain either Ni or Pt, we don't know how much Ni or Pt is + on the site, but we want it to be always fully occupied, we could create two lattice + site entries with the same fractional coordinates, with one assigned Ni as the element and the other + assigned Pt as the element. Then we could assign the Ni occupancy as ``@100``. Then + typing ``1-@100`` into the constraint text box of the Pt occupancy ensures that however + much the occupancy of the Ni site goes down in a refinement, the occupancy of the Pt on that + same site goes up by the same amount. This ensures full occupancy of that site, as long + as the initial occupancies of the Ni and Pt added up to 1. + +6. Start the refinement: + 1. Select the fit to run by left clicking the title of the fit in the ``Fit Tree`` panel. + The ``Parameters`` panel on the right shows a list of variables that you have defined + and their initial values. Each one also has a check-box that allows you to fix them + (prevent them from varying in the subsequent refinement). Unchecked boxes mean the variable + will be refined. + 2. When you are satisfied with the configuration, click the "gear" icon on the toolbar + and watch the fit progress in the terminal window. + +7. Plot the results: + 1. Select the data in the fit (in this case the `Ni-xray.gr` dataset) by left clicking it. + 2. Click the ``plot`` icon in the toolbar. This is the icon that looks a bit like a PDF + to the right of the Gear and the red/grey X. + + A new window pops up with the plots. It will show the data in blue, the best-fit model + curve in red, and offset below, the difference curve in green. The offset of the difference + curve appears at a default value of ``-5.0``. You can make your plot more pretty and meaningful + by typing a different offset into the ``offset`` text box and hitting ``Plot`` again. + + It is possible to configure the plot in the ``Plot Control`` panel in the GUI. + In the default layout it will be at the lower-left of the GUI panel. + + 1. To plot the fit (as was done above) elect "r" as the X plotting variable. + 2. Hold down shift and select "Gcalc" and "Gtrunc" as the Y plotting variables. + 3. Click the "Plot" button. + + This panel allows more plotting options for advanced cases such as plotting the values + of parameters refined across multiple fits to extract temperature dependent information. + + +8. Save your project for later use. + +====================================================== +Lesson 2: Build structure model using crystal symmetry +====================================================== + +In the previous example the initial structure was defined by an existing file. However, PDFgui makes it very easy to build a structure model from scratch and constrain it with arbitrary crystal symmetry. + +1. Create a blank structure: + 1. Click the FITTING tab. + 2. Repeat steps 1-3a from Lesson 1, but choose the "New" button. Rename "New Phase" to "Ni fcc". + +2. Define asymmetric unit: + 1. Right click the header of the empty atoms grid in the "Configure" page. + 2. Insert 1 atom using the popup menu. + 3. Change the elem cell to "Ni". + 4. Select the u11-u33 cells and type "0.004" and press Enter. + +3. Expand to all equivalent positions: + 1. Right click the first Ni atom and select "Expand space group". A "Space Group Expansion" dialog should open. + 2. In the dialog, select Fm-3m or just type 225 in the "Space Group" box and hit "OK". + + You should now have four atoms in the atoms grid. + +4. Generate symmetry constraints: + 1. Select the "Constraints" tab. + 2. Select all atoms. This can be done by dragging the mouse over the atom names or by clicking on the "elem" header. + 3. Right click in a selected cell and select "Symmetry constraints." A "Space Group Constraints" dialog should open. + 4. "Fm-3m" should already appear in the "Space Group" box. If it does not, select it as you did in step 3 and hit "OK". + + The u11-u33 cells should all read the same value. The "x", "y" and "z" cells should be all empty because Ni atoms are at special positions in Fm-3m. You may try to select lower-symmetry space and check what happens with the constraints. The space group constraints may be mixed by selecting different groups of atoms, for example, when only certain species show lowered symmetry. + +5. Continue the fit as in Lesson 1. + +============================= +Lesson 3: Multi-stage fitting +============================= + +Learn how to string together fits. + +1. Create a fit as in Lesson 1. + +2. Copy the fit: + 1. Right click on the fit name "Fit 1" in the right panel (the fit tree). + 2. Select "Copy" from the pop-up menu. + +3. Paste the fit: + 1. Right click in the empty space between the first fit in the fit tree. + 2. Select "Paste Fit." This will create "Fit 1_copy", a copy of "Fit 1" in the fit tree. + +4. Link the fits: + 1. Click on "Fit 1_copy" in the fit tree. + 2. In the "Parameters" panel, select the entire "Initial" column. + 3. Type ``=Fit 1`` and then press Enter. The "Initial" values of the parameters should now read ``=Fit1:n``, where "n" is the index of the parameter. + + This is the linking syntax: ``=name:index``. + "name" is the name of another fit. + "index" is the index of a parameter in that fit. + If you omit "index", it will default to the index of the parameter you are linking from. A linked parameter uses the refined value of the link as its initial value. This is useful when you are running several related fits. + +5. Add more fit parameters: + 1. Select the "Constraints" tab of the `Ni.stru` phase below "Fit 1_copy". + 2. Write ``@9`` in the "delta2" box. + +6. Run the fit and plot the results: + 1. Run the fit as in Lesson 1. + 2. Plot the fit as in Lesson 1, but this time hold down Control and select the data sets from "Fit 1" and "Fit 1_copy". You can change the "offset" in the plotting window to 0 to place the plots on top of each other. + +========== +References +========== + +1. :download:`(pdf) <../manual/Proffen-jac-1999.pdf>`, + Th. Proffen and S. J. L. Billinge, PDFFIT a program for full profile structural refinement of the atomic pair distribution function, J. Appl. Crystallogr. 32, 572-575 (1999) + +2. :download:`(pdf) <../manual/Farrow-jpcm-2007.pdf>`, + C. L. Farrow, P. Juhas, J. W. Liu, D. Bryndin, J. Bloch, Th. Proffen and S. J. L. Billinge, PDFfit2 and PDFgui: Computer programs for studying nanostructure in crystals, J. Phys.: Condens. Matter 19, 335219 (2007) diff --git a/_static/_sphinx_javascript_frameworks_compat.js b/_static/_sphinx_javascript_frameworks_compat.js new file mode 100644 index 00000000..81415803 --- /dev/null +++ b/_static/_sphinx_javascript_frameworks_compat.js @@ -0,0 +1,123 @@ +/* Compatability shim for jQuery and underscores.js. + * + * Copyright Sphinx contributors + * Released under the two clause BSD licence + */ + +/** + * small helper function to urldecode strings + * + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL + */ +jQuery.urldecode = function(x) { + if (!x) { + return x + } + return decodeURIComponent(x.replace(/\+/g, ' ')); +}; + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s === 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node, addItems) { + if (node.nodeType === 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && + !jQuery(node.parentNode).hasClass(className) && + !jQuery(node.parentNode).hasClass("nohighlight")) { + var span; + var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.className = className; + } + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + if (isInSVG) { + var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + var bbox = node.parentElement.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute('class', className); + addItems.push({ + "parent": node.parentNode, + "target": rect}); + } + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this, addItems); + }); + } + } + var addItems = []; + var result = this.each(function() { + highlight(this, addItems); + }); + for (var i = 0; i < addItems.length; ++i) { + jQuery(addItems[i].parent).before(addItems[i].target); + } + return result; +}; + +/* + * backward compatibility for jQuery.browser + * This will be supported until firefox bug is fixed. + */ +if (!jQuery.browser) { + jQuery.uaMatch = function(ua) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + return { + browser: match[ 1 ] || "", + version: match[ 2 ] || "0" + }; + }; + jQuery.browser = {}; + jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; +} diff --git a/_static/basic.css b/_static/basic.css new file mode 100644 index 00000000..7ebbd6d0 --- /dev/null +++ b/_static/basic.css @@ -0,0 +1,914 @@ +/* + * Sphinx stylesheet -- basic theme. + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin-top: 10px; +} + +ul.search li { + padding: 5px 0; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 360px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +a:visited { + color: #551A8B; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +nav.contents, +aside.topic, +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +nav.contents, +aside.topic, +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +nav.contents > :last-child, +aside.topic > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +nav.contents::after, +aside.topic::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +aside.footnote > span, +div.citation > span { + float: left; +} +aside.footnote > span:last-of-type, +div.citation > span:last-of-type { + padding-right: 0.5em; +} +aside.footnote > p { + margin-left: 2em; +} +div.citation > p { + margin-left: 4em; +} +aside.footnote > p:last-of-type, +div.citation > p:last-of-type { + margin-bottom: 0em; +} +aside.footnote > p:last-of-type:after, +div.citation > p:last-of-type:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +.sig dd { + margin-top: 0px; + margin-bottom: 0px; +} + +.sig dl { + margin-top: 0px; + margin-bottom: 0px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +.translated { + background-color: rgba(207, 255, 207, 0.2) +} + +.untranslated { + background-color: rgba(255, 207, 207, 0.2) +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; + white-space: nowrap; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/_static/css/badge_only.css b/_static/css/badge_only.css new file mode 100644 index 00000000..88ba55b9 --- /dev/null +++ b/_static/css/badge_only.css @@ -0,0 +1 @@ +.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-style:normal;font-weight:400;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#FontAwesome) format("svg")}.fa:before{font-family:FontAwesome;font-style:normal;font-weight:400;line-height:1}.fa:before,a .fa{text-decoration:inherit}.fa:before,a .fa,li .fa{display:inline-block}li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-.8em}ul.fas li .fa{width:.8em}ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before,.icon-book:before{content:"\f02d"}.fa-caret-down:before,.icon-caret-down:before{content:"\f0d7"}.fa-caret-up:before,.icon-caret-up:before{content:"\f0d8"}.fa-caret-left:before,.icon-caret-left:before{content:"\f0d9"}.fa-caret-right:before,.icon-caret-right:before{content:"\f0da"}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60}.rst-versions .rst-current-version:after{clear:both;content:"";display:block}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions .rst-other-versions .rtd-current-item{font-weight:700}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}#flyout-search-form{padding:6px} \ No newline at end of file diff --git a/_static/css/fonts/Roboto-Slab-Bold.woff b/_static/css/fonts/Roboto-Slab-Bold.woff new file mode 100644 index 00000000..6cb60000 Binary files /dev/null and b/_static/css/fonts/Roboto-Slab-Bold.woff differ diff --git a/_static/css/fonts/Roboto-Slab-Bold.woff2 b/_static/css/fonts/Roboto-Slab-Bold.woff2 new file mode 100644 index 00000000..7059e231 Binary files /dev/null and b/_static/css/fonts/Roboto-Slab-Bold.woff2 differ diff --git a/_static/css/fonts/Roboto-Slab-Regular.woff b/_static/css/fonts/Roboto-Slab-Regular.woff new file mode 100644 index 00000000..f815f63f Binary files /dev/null and b/_static/css/fonts/Roboto-Slab-Regular.woff differ diff --git a/_static/css/fonts/Roboto-Slab-Regular.woff2 b/_static/css/fonts/Roboto-Slab-Regular.woff2 new file mode 100644 index 00000000..f2c76e5b Binary files /dev/null and b/_static/css/fonts/Roboto-Slab-Regular.woff2 differ diff --git a/_static/css/fonts/fontawesome-webfont.eot b/_static/css/fonts/fontawesome-webfont.eot new file mode 100644 index 00000000..e9f60ca9 Binary files /dev/null and b/_static/css/fonts/fontawesome-webfont.eot differ diff --git a/_static/css/fonts/fontawesome-webfont.svg b/_static/css/fonts/fontawesome-webfont.svg new file mode 100644 index 00000000..855c845e --- /dev/null +++ b/_static/css/fonts/fontawesome-webfont.svg @@ -0,0 +1,2671 @@ + + + + +Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016 + By ,,, +Copyright Dave Gandy 2016. All rights reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_static/css/fonts/fontawesome-webfont.ttf b/_static/css/fonts/fontawesome-webfont.ttf new file mode 100644 index 00000000..35acda2f Binary files /dev/null and b/_static/css/fonts/fontawesome-webfont.ttf differ diff --git a/_static/css/fonts/fontawesome-webfont.woff b/_static/css/fonts/fontawesome-webfont.woff new file mode 100644 index 00000000..400014a4 Binary files /dev/null and b/_static/css/fonts/fontawesome-webfont.woff differ diff --git a/_static/css/fonts/fontawesome-webfont.woff2 b/_static/css/fonts/fontawesome-webfont.woff2 new file mode 100644 index 00000000..4d13fc60 Binary files /dev/null and b/_static/css/fonts/fontawesome-webfont.woff2 differ diff --git a/_static/css/fonts/lato-bold-italic.woff b/_static/css/fonts/lato-bold-italic.woff new file mode 100644 index 00000000..88ad05b9 Binary files /dev/null and b/_static/css/fonts/lato-bold-italic.woff differ diff --git a/_static/css/fonts/lato-bold-italic.woff2 b/_static/css/fonts/lato-bold-italic.woff2 new file mode 100644 index 00000000..c4e3d804 Binary files /dev/null and b/_static/css/fonts/lato-bold-italic.woff2 differ diff --git a/_static/css/fonts/lato-bold.woff b/_static/css/fonts/lato-bold.woff new file mode 100644 index 00000000..c6dff51f Binary files /dev/null and b/_static/css/fonts/lato-bold.woff differ diff --git a/_static/css/fonts/lato-bold.woff2 b/_static/css/fonts/lato-bold.woff2 new file mode 100644 index 00000000..bb195043 Binary files /dev/null and b/_static/css/fonts/lato-bold.woff2 differ diff --git a/_static/css/fonts/lato-normal-italic.woff b/_static/css/fonts/lato-normal-italic.woff new file mode 100644 index 00000000..76114bc0 Binary files /dev/null and b/_static/css/fonts/lato-normal-italic.woff differ diff --git a/_static/css/fonts/lato-normal-italic.woff2 b/_static/css/fonts/lato-normal-italic.woff2 new file mode 100644 index 00000000..3404f37e Binary files /dev/null and b/_static/css/fonts/lato-normal-italic.woff2 differ diff --git a/_static/css/fonts/lato-normal.woff b/_static/css/fonts/lato-normal.woff new file mode 100644 index 00000000..ae1307ff Binary files /dev/null and b/_static/css/fonts/lato-normal.woff differ diff --git a/_static/css/fonts/lato-normal.woff2 b/_static/css/fonts/lato-normal.woff2 new file mode 100644 index 00000000..3bf98433 Binary files /dev/null and b/_static/css/fonts/lato-normal.woff2 differ diff --git a/_static/css/theme.css b/_static/css/theme.css new file mode 100644 index 00000000..0f14f106 --- /dev/null +++ b/_static/css/theme.css @@ -0,0 +1,4 @@ +html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}[hidden],audio:not([controls]){display:none}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}blockquote{margin:0}dfn{font-style:italic}ins{background:#ff9;text-decoration:none}ins,mark{color:#000}mark{background:#ff0;font-style:italic;font-weight:700}.rst-content code,.rst-content tt,code,kbd,pre,samp{font-family:monospace,serif;_font-family:courier new,monospace;font-size:1em}pre{white-space:pre}q{quotes:none}q:after,q:before{content:"";content:none}small{font-size:85%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}dl,ol,ul{margin:0;padding:0;list-style:none;list-style-image:none}li{list-style:none}dd{margin:0}img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;max-width:100%}svg:not(:root){overflow:hidden}figure,form{margin:0}label{cursor:pointer}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type=button],input[type=reset],input[type=submit]{cursor:pointer;-webkit-appearance:button;*overflow:visible}button[disabled],input[disabled]{cursor:default}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}textarea{resize:vertical}table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}.chromeframe{margin:.2em 0;background:#ccc;color:#000;padding:.2em 0}.ir{display:block;border:0;text-indent:-999em;overflow:hidden;background-color:transparent;background-repeat:no-repeat;text-align:left;direction:ltr;*line-height:0}.ir br{display:none}.hidden{display:none!important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.relative{position:relative}big,small{font-size:100%}@media print{body,html,section{background:none!important}*{box-shadow:none!important;text-shadow:none!important;filter:none!important;-ms-filter:none!important}a,a:visited{text-decoration:underline}.ir a:after,a[href^="#"]:after,a[href^="javascript:"]:after{content:""}blockquote,pre{page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}.rst-content .toctree-wrapper>p.caption,h2,h3,p{orphans:3;widows:3}.rst-content .toctree-wrapper>p.caption,h2,h3{page-break-after:avoid}}.btn,.fa:before,.icon:before,.rst-content .admonition,.rst-content .admonition-title:before,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .code-block-caption .headerlink:before,.rst-content .danger,.rst-content .eqno .headerlink:before,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content p .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-alert,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before,.wy-menu-vertical li button.toctree-expand:before,input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week],select,textarea{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}/*! + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:FontAwesome;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713);src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix&v=4.7.0) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#fontawesomeregular) format("svg");font-weight:400;font-style:normal}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li button.toctree-expand{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14286em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14286em;width:2.14286em;top:.14286em;text-align:center}.fa-li.fa-lg{left:-1.85714em}.fa-border{padding:.2em .25em .15em;border:.08em solid #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa-pull-left.icon,.fa.fa-pull-left,.rst-content .code-block-caption .fa-pull-left.headerlink,.rst-content .eqno .fa-pull-left.headerlink,.rst-content .fa-pull-left.admonition-title,.rst-content code.download span.fa-pull-left:first-child,.rst-content dl dt .fa-pull-left.headerlink,.rst-content h1 .fa-pull-left.headerlink,.rst-content h2 .fa-pull-left.headerlink,.rst-content h3 .fa-pull-left.headerlink,.rst-content h4 .fa-pull-left.headerlink,.rst-content h5 .fa-pull-left.headerlink,.rst-content h6 .fa-pull-left.headerlink,.rst-content p .fa-pull-left.headerlink,.rst-content table>caption .fa-pull-left.headerlink,.rst-content tt.download span.fa-pull-left:first-child,.wy-menu-vertical li.current>a button.fa-pull-left.toctree-expand,.wy-menu-vertical li.on a button.fa-pull-left.toctree-expand,.wy-menu-vertical li button.fa-pull-left.toctree-expand{margin-right:.3em}.fa-pull-right.icon,.fa.fa-pull-right,.rst-content .code-block-caption .fa-pull-right.headerlink,.rst-content .eqno .fa-pull-right.headerlink,.rst-content .fa-pull-right.admonition-title,.rst-content code.download span.fa-pull-right:first-child,.rst-content dl dt .fa-pull-right.headerlink,.rst-content h1 .fa-pull-right.headerlink,.rst-content h2 .fa-pull-right.headerlink,.rst-content h3 .fa-pull-right.headerlink,.rst-content h4 .fa-pull-right.headerlink,.rst-content h5 .fa-pull-right.headerlink,.rst-content h6 .fa-pull-right.headerlink,.rst-content p .fa-pull-right.headerlink,.rst-content table>caption .fa-pull-right.headerlink,.rst-content tt.download span.fa-pull-right:first-child,.wy-menu-vertical li.current>a button.fa-pull-right.toctree-expand,.wy-menu-vertical li.on a button.fa-pull-right.toctree-expand,.wy-menu-vertical li button.fa-pull-right.toctree-expand{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left,.pull-left.icon,.rst-content .code-block-caption .pull-left.headerlink,.rst-content .eqno .pull-left.headerlink,.rst-content .pull-left.admonition-title,.rst-content code.download span.pull-left:first-child,.rst-content dl dt .pull-left.headerlink,.rst-content h1 .pull-left.headerlink,.rst-content h2 .pull-left.headerlink,.rst-content h3 .pull-left.headerlink,.rst-content h4 .pull-left.headerlink,.rst-content h5 .pull-left.headerlink,.rst-content h6 .pull-left.headerlink,.rst-content p .pull-left.headerlink,.rst-content table>caption .pull-left.headerlink,.rst-content tt.download span.pull-left:first-child,.wy-menu-vertical li.current>a button.pull-left.toctree-expand,.wy-menu-vertical li.on a button.pull-left.toctree-expand,.wy-menu-vertical li button.pull-left.toctree-expand{margin-right:.3em}.fa.pull-right,.pull-right.icon,.rst-content .code-block-caption .pull-right.headerlink,.rst-content .eqno .pull-right.headerlink,.rst-content .pull-right.admonition-title,.rst-content code.download span.pull-right:first-child,.rst-content dl dt .pull-right.headerlink,.rst-content h1 .pull-right.headerlink,.rst-content h2 .pull-right.headerlink,.rst-content h3 .pull-right.headerlink,.rst-content h4 .pull-right.headerlink,.rst-content h5 .pull-right.headerlink,.rst-content h6 .pull-right.headerlink,.rst-content p .pull-right.headerlink,.rst-content table>caption .pull-right.headerlink,.rst-content tt.download span.pull-right:first-child,.wy-menu-vertical li.current>a button.pull-right.toctree-expand,.wy-menu-vertical li.on a button.pull-right.toctree-expand,.wy-menu-vertical li button.pull-right.toctree-expand{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s linear infinite;animation:fa-spin 2s linear infinite}.fa-pulse{-webkit-animation:fa-spin 1s steps(8) infinite;animation:fa-spin 1s steps(8) infinite}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);-ms-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:""}.fa-music:before{content:""}.fa-search:before,.icon-search:before{content:""}.fa-envelope-o:before{content:""}.fa-heart:before{content:""}.fa-star:before{content:""}.fa-star-o:before{content:""}.fa-user:before{content:""}.fa-film:before{content:""}.fa-th-large:before{content:""}.fa-th:before{content:""}.fa-th-list:before{content:""}.fa-check:before{content:""}.fa-close:before,.fa-remove:before,.fa-times:before{content:""}.fa-search-plus:before{content:""}.fa-search-minus:before{content:""}.fa-power-off:before{content:""}.fa-signal:before{content:""}.fa-cog:before,.fa-gear:before{content:""}.fa-trash-o:before{content:""}.fa-home:before,.icon-home:before{content:""}.fa-file-o:before{content:""}.fa-clock-o:before{content:""}.fa-road:before{content:""}.fa-download:before,.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{content:""}.fa-arrow-circle-o-down:before{content:""}.fa-arrow-circle-o-up:before{content:""}.fa-inbox:before{content:""}.fa-play-circle-o:before{content:""}.fa-repeat:before,.fa-rotate-right:before{content:""}.fa-refresh:before{content:""}.fa-list-alt:before{content:""}.fa-lock:before{content:""}.fa-flag:before{content:""}.fa-headphones:before{content:""}.fa-volume-off:before{content:""}.fa-volume-down:before{content:""}.fa-volume-up:before{content:""}.fa-qrcode:before{content:""}.fa-barcode:before{content:""}.fa-tag:before{content:""}.fa-tags:before{content:""}.fa-book:before,.icon-book:before{content:""}.fa-bookmark:before{content:""}.fa-print:before{content:""}.fa-camera:before{content:""}.fa-font:before{content:""}.fa-bold:before{content:""}.fa-italic:before{content:""}.fa-text-height:before{content:""}.fa-text-width:before{content:""}.fa-align-left:before{content:""}.fa-align-center:before{content:""}.fa-align-right:before{content:""}.fa-align-justify:before{content:""}.fa-list:before{content:""}.fa-dedent:before,.fa-outdent:before{content:""}.fa-indent:before{content:""}.fa-video-camera:before{content:""}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:""}.fa-pencil:before{content:""}.fa-map-marker:before{content:""}.fa-adjust:before{content:""}.fa-tint:before{content:""}.fa-edit:before,.fa-pencil-square-o:before{content:""}.fa-share-square-o:before{content:""}.fa-check-square-o:before{content:""}.fa-arrows:before{content:""}.fa-step-backward:before{content:""}.fa-fast-backward:before{content:""}.fa-backward:before{content:""}.fa-play:before{content:""}.fa-pause:before{content:""}.fa-stop:before{content:""}.fa-forward:before{content:""}.fa-fast-forward:before{content:""}.fa-step-forward:before{content:""}.fa-eject:before{content:""}.fa-chevron-left:before{content:""}.fa-chevron-right:before{content:""}.fa-plus-circle:before{content:""}.fa-minus-circle:before{content:""}.fa-times-circle:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before{content:""}.fa-check-circle:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before{content:""}.fa-question-circle:before{content:""}.fa-info-circle:before{content:""}.fa-crosshairs:before{content:""}.fa-times-circle-o:before{content:""}.fa-check-circle-o:before{content:""}.fa-ban:before{content:""}.fa-arrow-left:before{content:""}.fa-arrow-right:before{content:""}.fa-arrow-up:before{content:""}.fa-arrow-down:before{content:""}.fa-mail-forward:before,.fa-share:before{content:""}.fa-expand:before{content:""}.fa-compress:before{content:""}.fa-plus:before{content:""}.fa-minus:before{content:""}.fa-asterisk:before{content:""}.fa-exclamation-circle:before,.rst-content .admonition-title:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before{content:""}.fa-gift:before{content:""}.fa-leaf:before{content:""}.fa-fire:before,.icon-fire:before{content:""}.fa-eye:before{content:""}.fa-eye-slash:before{content:""}.fa-exclamation-triangle:before,.fa-warning:before{content:""}.fa-plane:before{content:""}.fa-calendar:before{content:""}.fa-random:before{content:""}.fa-comment:before{content:""}.fa-magnet:before{content:""}.fa-chevron-up:before{content:""}.fa-chevron-down:before{content:""}.fa-retweet:before{content:""}.fa-shopping-cart:before{content:""}.fa-folder:before{content:""}.fa-folder-open:before{content:""}.fa-arrows-v:before{content:""}.fa-arrows-h:before{content:""}.fa-bar-chart-o:before,.fa-bar-chart:before{content:""}.fa-twitter-square:before{content:""}.fa-facebook-square:before{content:""}.fa-camera-retro:before{content:""}.fa-key:before{content:""}.fa-cogs:before,.fa-gears:before{content:""}.fa-comments:before{content:""}.fa-thumbs-o-up:before{content:""}.fa-thumbs-o-down:before{content:""}.fa-star-half:before{content:""}.fa-heart-o:before{content:""}.fa-sign-out:before{content:""}.fa-linkedin-square:before{content:""}.fa-thumb-tack:before{content:""}.fa-external-link:before{content:""}.fa-sign-in:before{content:""}.fa-trophy:before{content:""}.fa-github-square:before{content:""}.fa-upload:before{content:""}.fa-lemon-o:before{content:""}.fa-phone:before{content:""}.fa-square-o:before{content:""}.fa-bookmark-o:before{content:""}.fa-phone-square:before{content:""}.fa-twitter:before{content:""}.fa-facebook-f:before,.fa-facebook:before{content:""}.fa-github:before,.icon-github:before{content:""}.fa-unlock:before{content:""}.fa-credit-card:before{content:""}.fa-feed:before,.fa-rss:before{content:""}.fa-hdd-o:before{content:""}.fa-bullhorn:before{content:""}.fa-bell:before{content:""}.fa-certificate:before{content:""}.fa-hand-o-right:before{content:""}.fa-hand-o-left:before{content:""}.fa-hand-o-up:before{content:""}.fa-hand-o-down:before{content:""}.fa-arrow-circle-left:before,.icon-circle-arrow-left:before{content:""}.fa-arrow-circle-right:before,.icon-circle-arrow-right:before{content:""}.fa-arrow-circle-up:before{content:""}.fa-arrow-circle-down:before{content:""}.fa-globe:before{content:""}.fa-wrench:before{content:""}.fa-tasks:before{content:""}.fa-filter:before{content:""}.fa-briefcase:before{content:""}.fa-arrows-alt:before{content:""}.fa-group:before,.fa-users:before{content:""}.fa-chain:before,.fa-link:before,.icon-link:before{content:""}.fa-cloud:before{content:""}.fa-flask:before{content:""}.fa-cut:before,.fa-scissors:before{content:""}.fa-copy:before,.fa-files-o:before{content:""}.fa-paperclip:before{content:""}.fa-floppy-o:before,.fa-save:before{content:""}.fa-square:before{content:""}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:""}.fa-list-ul:before{content:""}.fa-list-ol:before{content:""}.fa-strikethrough:before{content:""}.fa-underline:before{content:""}.fa-table:before{content:""}.fa-magic:before{content:""}.fa-truck:before{content:""}.fa-pinterest:before{content:""}.fa-pinterest-square:before{content:""}.fa-google-plus-square:before{content:""}.fa-google-plus:before{content:""}.fa-money:before{content:""}.fa-caret-down:before,.icon-caret-down:before,.wy-dropdown .caret:before{content:""}.fa-caret-up:before{content:""}.fa-caret-left:before{content:""}.fa-caret-right:before{content:""}.fa-columns:before{content:""}.fa-sort:before,.fa-unsorted:before{content:""}.fa-sort-desc:before,.fa-sort-down:before{content:""}.fa-sort-asc:before,.fa-sort-up:before{content:""}.fa-envelope:before{content:""}.fa-linkedin:before{content:""}.fa-rotate-left:before,.fa-undo:before{content:""}.fa-gavel:before,.fa-legal:before{content:""}.fa-dashboard:before,.fa-tachometer:before{content:""}.fa-comment-o:before{content:""}.fa-comments-o:before{content:""}.fa-bolt:before,.fa-flash:before{content:""}.fa-sitemap:before{content:""}.fa-umbrella:before{content:""}.fa-clipboard:before,.fa-paste:before{content:""}.fa-lightbulb-o:before{content:""}.fa-exchange:before{content:""}.fa-cloud-download:before{content:""}.fa-cloud-upload:before{content:""}.fa-user-md:before{content:""}.fa-stethoscope:before{content:""}.fa-suitcase:before{content:""}.fa-bell-o:before{content:""}.fa-coffee:before{content:""}.fa-cutlery:before{content:""}.fa-file-text-o:before{content:""}.fa-building-o:before{content:""}.fa-hospital-o:before{content:""}.fa-ambulance:before{content:""}.fa-medkit:before{content:""}.fa-fighter-jet:before{content:""}.fa-beer:before{content:""}.fa-h-square:before{content:""}.fa-plus-square:before{content:""}.fa-angle-double-left:before{content:""}.fa-angle-double-right:before{content:""}.fa-angle-double-up:before{content:""}.fa-angle-double-down:before{content:""}.fa-angle-left:before{content:""}.fa-angle-right:before{content:""}.fa-angle-up:before{content:""}.fa-angle-down:before{content:""}.fa-desktop:before{content:""}.fa-laptop:before{content:""}.fa-tablet:before{content:""}.fa-mobile-phone:before,.fa-mobile:before{content:""}.fa-circle-o:before{content:""}.fa-quote-left:before{content:""}.fa-quote-right:before{content:""}.fa-spinner:before{content:""}.fa-circle:before{content:""}.fa-mail-reply:before,.fa-reply:before{content:""}.fa-github-alt:before{content:""}.fa-folder-o:before{content:""}.fa-folder-open-o:before{content:""}.fa-smile-o:before{content:""}.fa-frown-o:before{content:""}.fa-meh-o:before{content:""}.fa-gamepad:before{content:""}.fa-keyboard-o:before{content:""}.fa-flag-o:before{content:""}.fa-flag-checkered:before{content:""}.fa-terminal:before{content:""}.fa-code:before{content:""}.fa-mail-reply-all:before,.fa-reply-all:before{content:""}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:""}.fa-location-arrow:before{content:""}.fa-crop:before{content:""}.fa-code-fork:before{content:""}.fa-chain-broken:before,.fa-unlink:before{content:""}.fa-question:before{content:""}.fa-info:before{content:""}.fa-exclamation:before{content:""}.fa-superscript:before{content:""}.fa-subscript:before{content:""}.fa-eraser:before{content:""}.fa-puzzle-piece:before{content:""}.fa-microphone:before{content:""}.fa-microphone-slash:before{content:""}.fa-shield:before{content:""}.fa-calendar-o:before{content:""}.fa-fire-extinguisher:before{content:""}.fa-rocket:before{content:""}.fa-maxcdn:before{content:""}.fa-chevron-circle-left:before{content:""}.fa-chevron-circle-right:before{content:""}.fa-chevron-circle-up:before{content:""}.fa-chevron-circle-down:before{content:""}.fa-html5:before{content:""}.fa-css3:before{content:""}.fa-anchor:before{content:""}.fa-unlock-alt:before{content:""}.fa-bullseye:before{content:""}.fa-ellipsis-h:before{content:""}.fa-ellipsis-v:before{content:""}.fa-rss-square:before{content:""}.fa-play-circle:before{content:""}.fa-ticket:before{content:""}.fa-minus-square:before{content:""}.fa-minus-square-o:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before{content:""}.fa-level-up:before{content:""}.fa-level-down:before{content:""}.fa-check-square:before{content:""}.fa-pencil-square:before{content:""}.fa-external-link-square:before{content:""}.fa-share-square:before{content:""}.fa-compass:before{content:""}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:""}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:""}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:""}.fa-eur:before,.fa-euro:before{content:""}.fa-gbp:before{content:""}.fa-dollar:before,.fa-usd:before{content:""}.fa-inr:before,.fa-rupee:before{content:""}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:""}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:""}.fa-krw:before,.fa-won:before{content:""}.fa-bitcoin:before,.fa-btc:before{content:""}.fa-file:before{content:""}.fa-file-text:before{content:""}.fa-sort-alpha-asc:before{content:""}.fa-sort-alpha-desc:before{content:""}.fa-sort-amount-asc:before{content:""}.fa-sort-amount-desc:before{content:""}.fa-sort-numeric-asc:before{content:""}.fa-sort-numeric-desc:before{content:""}.fa-thumbs-up:before{content:""}.fa-thumbs-down:before{content:""}.fa-youtube-square:before{content:""}.fa-youtube:before{content:""}.fa-xing:before{content:""}.fa-xing-square:before{content:""}.fa-youtube-play:before{content:""}.fa-dropbox:before{content:""}.fa-stack-overflow:before{content:""}.fa-instagram:before{content:""}.fa-flickr:before{content:""}.fa-adn:before{content:""}.fa-bitbucket:before,.icon-bitbucket:before{content:""}.fa-bitbucket-square:before{content:""}.fa-tumblr:before{content:""}.fa-tumblr-square:before{content:""}.fa-long-arrow-down:before{content:""}.fa-long-arrow-up:before{content:""}.fa-long-arrow-left:before{content:""}.fa-long-arrow-right:before{content:""}.fa-apple:before{content:""}.fa-windows:before{content:""}.fa-android:before{content:""}.fa-linux:before{content:""}.fa-dribbble:before{content:""}.fa-skype:before{content:""}.fa-foursquare:before{content:""}.fa-trello:before{content:""}.fa-female:before{content:""}.fa-male:before{content:""}.fa-gittip:before,.fa-gratipay:before{content:""}.fa-sun-o:before{content:""}.fa-moon-o:before{content:""}.fa-archive:before{content:""}.fa-bug:before{content:""}.fa-vk:before{content:""}.fa-weibo:before{content:""}.fa-renren:before{content:""}.fa-pagelines:before{content:""}.fa-stack-exchange:before{content:""}.fa-arrow-circle-o-right:before{content:""}.fa-arrow-circle-o-left:before{content:""}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:""}.fa-dot-circle-o:before{content:""}.fa-wheelchair:before{content:""}.fa-vimeo-square:before{content:""}.fa-try:before,.fa-turkish-lira:before{content:""}.fa-plus-square-o:before,.wy-menu-vertical li button.toctree-expand:before{content:""}.fa-space-shuttle:before{content:""}.fa-slack:before{content:""}.fa-envelope-square:before{content:""}.fa-wordpress:before{content:""}.fa-openid:before{content:""}.fa-bank:before,.fa-institution:before,.fa-university:before{content:""}.fa-graduation-cap:before,.fa-mortar-board:before{content:""}.fa-yahoo:before{content:""}.fa-google:before{content:""}.fa-reddit:before{content:""}.fa-reddit-square:before{content:""}.fa-stumbleupon-circle:before{content:""}.fa-stumbleupon:before{content:""}.fa-delicious:before{content:""}.fa-digg:before{content:""}.fa-pied-piper-pp:before{content:""}.fa-pied-piper-alt:before{content:""}.fa-drupal:before{content:""}.fa-joomla:before{content:""}.fa-language:before{content:""}.fa-fax:before{content:""}.fa-building:before{content:""}.fa-child:before{content:""}.fa-paw:before{content:""}.fa-spoon:before{content:""}.fa-cube:before{content:""}.fa-cubes:before{content:""}.fa-behance:before{content:""}.fa-behance-square:before{content:""}.fa-steam:before{content:""}.fa-steam-square:before{content:""}.fa-recycle:before{content:""}.fa-automobile:before,.fa-car:before{content:""}.fa-cab:before,.fa-taxi:before{content:""}.fa-tree:before{content:""}.fa-spotify:before{content:""}.fa-deviantart:before{content:""}.fa-soundcloud:before{content:""}.fa-database:before{content:""}.fa-file-pdf-o:before{content:""}.fa-file-word-o:before{content:""}.fa-file-excel-o:before{content:""}.fa-file-powerpoint-o:before{content:""}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:""}.fa-file-archive-o:before,.fa-file-zip-o:before{content:""}.fa-file-audio-o:before,.fa-file-sound-o:before{content:""}.fa-file-movie-o:before,.fa-file-video-o:before{content:""}.fa-file-code-o:before{content:""}.fa-vine:before{content:""}.fa-codepen:before{content:""}.fa-jsfiddle:before{content:""}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:""}.fa-circle-o-notch:before{content:""}.fa-ra:before,.fa-rebel:before,.fa-resistance:before{content:""}.fa-empire:before,.fa-ge:before{content:""}.fa-git-square:before{content:""}.fa-git:before{content:""}.fa-hacker-news:before,.fa-y-combinator-square:before,.fa-yc-square:before{content:""}.fa-tencent-weibo:before{content:""}.fa-qq:before{content:""}.fa-wechat:before,.fa-weixin:before{content:""}.fa-paper-plane:before,.fa-send:before{content:""}.fa-paper-plane-o:before,.fa-send-o:before{content:""}.fa-history:before{content:""}.fa-circle-thin:before{content:""}.fa-header:before{content:""}.fa-paragraph:before{content:""}.fa-sliders:before{content:""}.fa-share-alt:before{content:""}.fa-share-alt-square:before{content:""}.fa-bomb:before{content:""}.fa-futbol-o:before,.fa-soccer-ball-o:before{content:""}.fa-tty:before{content:""}.fa-binoculars:before{content:""}.fa-plug:before{content:""}.fa-slideshare:before{content:""}.fa-twitch:before{content:""}.fa-yelp:before{content:""}.fa-newspaper-o:before{content:""}.fa-wifi:before{content:""}.fa-calculator:before{content:""}.fa-paypal:before{content:""}.fa-google-wallet:before{content:""}.fa-cc-visa:before{content:""}.fa-cc-mastercard:before{content:""}.fa-cc-discover:before{content:""}.fa-cc-amex:before{content:""}.fa-cc-paypal:before{content:""}.fa-cc-stripe:before{content:""}.fa-bell-slash:before{content:""}.fa-bell-slash-o:before{content:""}.fa-trash:before{content:""}.fa-copyright:before{content:""}.fa-at:before{content:""}.fa-eyedropper:before{content:""}.fa-paint-brush:before{content:""}.fa-birthday-cake:before{content:""}.fa-area-chart:before{content:""}.fa-pie-chart:before{content:""}.fa-line-chart:before{content:""}.fa-lastfm:before{content:""}.fa-lastfm-square:before{content:""}.fa-toggle-off:before{content:""}.fa-toggle-on:before{content:""}.fa-bicycle:before{content:""}.fa-bus:before{content:""}.fa-ioxhost:before{content:""}.fa-angellist:before{content:""}.fa-cc:before{content:""}.fa-ils:before,.fa-shekel:before,.fa-sheqel:before{content:""}.fa-meanpath:before{content:""}.fa-buysellads:before{content:""}.fa-connectdevelop:before{content:""}.fa-dashcube:before{content:""}.fa-forumbee:before{content:""}.fa-leanpub:before{content:""}.fa-sellsy:before{content:""}.fa-shirtsinbulk:before{content:""}.fa-simplybuilt:before{content:""}.fa-skyatlas:before{content:""}.fa-cart-plus:before{content:""}.fa-cart-arrow-down:before{content:""}.fa-diamond:before{content:""}.fa-ship:before{content:""}.fa-user-secret:before{content:""}.fa-motorcycle:before{content:""}.fa-street-view:before{content:""}.fa-heartbeat:before{content:""}.fa-venus:before{content:""}.fa-mars:before{content:""}.fa-mercury:before{content:""}.fa-intersex:before,.fa-transgender:before{content:""}.fa-transgender-alt:before{content:""}.fa-venus-double:before{content:""}.fa-mars-double:before{content:""}.fa-venus-mars:before{content:""}.fa-mars-stroke:before{content:""}.fa-mars-stroke-v:before{content:""}.fa-mars-stroke-h:before{content:""}.fa-neuter:before{content:""}.fa-genderless:before{content:""}.fa-facebook-official:before{content:""}.fa-pinterest-p:before{content:""}.fa-whatsapp:before{content:""}.fa-server:before{content:""}.fa-user-plus:before{content:""}.fa-user-times:before{content:""}.fa-bed:before,.fa-hotel:before{content:""}.fa-viacoin:before{content:""}.fa-train:before{content:""}.fa-subway:before{content:""}.fa-medium:before{content:""}.fa-y-combinator:before,.fa-yc:before{content:""}.fa-optin-monster:before{content:""}.fa-opencart:before{content:""}.fa-expeditedssl:before{content:""}.fa-battery-4:before,.fa-battery-full:before,.fa-battery:before{content:""}.fa-battery-3:before,.fa-battery-three-quarters:before{content:""}.fa-battery-2:before,.fa-battery-half:before{content:""}.fa-battery-1:before,.fa-battery-quarter:before{content:""}.fa-battery-0:before,.fa-battery-empty:before{content:""}.fa-mouse-pointer:before{content:""}.fa-i-cursor:before{content:""}.fa-object-group:before{content:""}.fa-object-ungroup:before{content:""}.fa-sticky-note:before{content:""}.fa-sticky-note-o:before{content:""}.fa-cc-jcb:before{content:""}.fa-cc-diners-club:before{content:""}.fa-clone:before{content:""}.fa-balance-scale:before{content:""}.fa-hourglass-o:before{content:""}.fa-hourglass-1:before,.fa-hourglass-start:before{content:""}.fa-hourglass-2:before,.fa-hourglass-half:before{content:""}.fa-hourglass-3:before,.fa-hourglass-end:before{content:""}.fa-hourglass:before{content:""}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:""}.fa-hand-paper-o:before,.fa-hand-stop-o:before{content:""}.fa-hand-scissors-o:before{content:""}.fa-hand-lizard-o:before{content:""}.fa-hand-spock-o:before{content:""}.fa-hand-pointer-o:before{content:""}.fa-hand-peace-o:before{content:""}.fa-trademark:before{content:""}.fa-registered:before{content:""}.fa-creative-commons:before{content:""}.fa-gg:before{content:""}.fa-gg-circle:before{content:""}.fa-tripadvisor:before{content:""}.fa-odnoklassniki:before{content:""}.fa-odnoklassniki-square:before{content:""}.fa-get-pocket:before{content:""}.fa-wikipedia-w:before{content:""}.fa-safari:before{content:""}.fa-chrome:before{content:""}.fa-firefox:before{content:""}.fa-opera:before{content:""}.fa-internet-explorer:before{content:""}.fa-television:before,.fa-tv:before{content:""}.fa-contao:before{content:""}.fa-500px:before{content:""}.fa-amazon:before{content:""}.fa-calendar-plus-o:before{content:""}.fa-calendar-minus-o:before{content:""}.fa-calendar-times-o:before{content:""}.fa-calendar-check-o:before{content:""}.fa-industry:before{content:""}.fa-map-pin:before{content:""}.fa-map-signs:before{content:""}.fa-map-o:before{content:""}.fa-map:before{content:""}.fa-commenting:before{content:""}.fa-commenting-o:before{content:""}.fa-houzz:before{content:""}.fa-vimeo:before{content:""}.fa-black-tie:before{content:""}.fa-fonticons:before{content:""}.fa-reddit-alien:before{content:""}.fa-edge:before{content:""}.fa-credit-card-alt:before{content:""}.fa-codiepie:before{content:""}.fa-modx:before{content:""}.fa-fort-awesome:before{content:""}.fa-usb:before{content:""}.fa-product-hunt:before{content:""}.fa-mixcloud:before{content:""}.fa-scribd:before{content:""}.fa-pause-circle:before{content:""}.fa-pause-circle-o:before{content:""}.fa-stop-circle:before{content:""}.fa-stop-circle-o:before{content:""}.fa-shopping-bag:before{content:""}.fa-shopping-basket:before{content:""}.fa-hashtag:before{content:""}.fa-bluetooth:before{content:""}.fa-bluetooth-b:before{content:""}.fa-percent:before{content:""}.fa-gitlab:before,.icon-gitlab:before{content:""}.fa-wpbeginner:before{content:""}.fa-wpforms:before{content:""}.fa-envira:before{content:""}.fa-universal-access:before{content:""}.fa-wheelchair-alt:before{content:""}.fa-question-circle-o:before{content:""}.fa-blind:before{content:""}.fa-audio-description:before{content:""}.fa-volume-control-phone:before{content:""}.fa-braille:before{content:""}.fa-assistive-listening-systems:before{content:""}.fa-american-sign-language-interpreting:before,.fa-asl-interpreting:before{content:""}.fa-deaf:before,.fa-deafness:before,.fa-hard-of-hearing:before{content:""}.fa-glide:before{content:""}.fa-glide-g:before{content:""}.fa-sign-language:before,.fa-signing:before{content:""}.fa-low-vision:before{content:""}.fa-viadeo:before{content:""}.fa-viadeo-square:before{content:""}.fa-snapchat:before{content:""}.fa-snapchat-ghost:before{content:""}.fa-snapchat-square:before{content:""}.fa-pied-piper:before{content:""}.fa-first-order:before{content:""}.fa-yoast:before{content:""}.fa-themeisle:before{content:""}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:""}.fa-fa:before,.fa-font-awesome:before{content:""}.fa-handshake-o:before{content:""}.fa-envelope-open:before{content:""}.fa-envelope-open-o:before{content:""}.fa-linode:before{content:""}.fa-address-book:before{content:""}.fa-address-book-o:before{content:""}.fa-address-card:before,.fa-vcard:before{content:""}.fa-address-card-o:before,.fa-vcard-o:before{content:""}.fa-user-circle:before{content:""}.fa-user-circle-o:before{content:""}.fa-user-o:before{content:""}.fa-id-badge:before{content:""}.fa-drivers-license:before,.fa-id-card:before{content:""}.fa-drivers-license-o:before,.fa-id-card-o:before{content:""}.fa-quora:before{content:""}.fa-free-code-camp:before{content:""}.fa-telegram:before{content:""}.fa-thermometer-4:before,.fa-thermometer-full:before,.fa-thermometer:before{content:""}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:""}.fa-thermometer-2:before,.fa-thermometer-half:before{content:""}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:""}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:""}.fa-shower:before{content:""}.fa-bath:before,.fa-bathtub:before,.fa-s15:before{content:""}.fa-podcast:before{content:""}.fa-window-maximize:before{content:""}.fa-window-minimize:before{content:""}.fa-window-restore:before{content:""}.fa-times-rectangle:before,.fa-window-close:before{content:""}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:""}.fa-bandcamp:before{content:""}.fa-grav:before{content:""}.fa-etsy:before{content:""}.fa-imdb:before{content:""}.fa-ravelry:before{content:""}.fa-eercast:before{content:""}.fa-microchip:before{content:""}.fa-snowflake-o:before{content:""}.fa-superpowers:before{content:""}.fa-wpexplorer:before{content:""}.fa-meetup:before{content:""}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-dropdown .caret,.wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-info .wy-input-context,.wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li button.toctree-expand{font-family:inherit}.fa:before,.icon:before,.rst-content .admonition-title:before,.rst-content .code-block-caption .headerlink:before,.rst-content .eqno .headerlink:before,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content p .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before,.wy-menu-vertical li button.toctree-expand:before{font-family:FontAwesome;display:inline-block;font-style:normal;font-weight:400;line-height:1;text-decoration:inherit}.rst-content .code-block-caption a .headerlink,.rst-content .eqno a .headerlink,.rst-content a .admonition-title,.rst-content code.download a span:first-child,.rst-content dl dt a .headerlink,.rst-content h1 a .headerlink,.rst-content h2 a .headerlink,.rst-content h3 a .headerlink,.rst-content h4 a .headerlink,.rst-content h5 a .headerlink,.rst-content h6 a .headerlink,.rst-content p.caption a .headerlink,.rst-content p a .headerlink,.rst-content table>caption a .headerlink,.rst-content tt.download a span:first-child,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li a button.toctree-expand,a .fa,a .icon,a .rst-content .admonition-title,a .rst-content .code-block-caption .headerlink,a .rst-content .eqno .headerlink,a .rst-content code.download span:first-child,a .rst-content dl dt .headerlink,a .rst-content h1 .headerlink,a .rst-content h2 .headerlink,a .rst-content h3 .headerlink,a .rst-content h4 .headerlink,a .rst-content h5 .headerlink,a .rst-content h6 .headerlink,a .rst-content p.caption .headerlink,a .rst-content p .headerlink,a .rst-content table>caption .headerlink,a .rst-content tt.download span:first-child,a .wy-menu-vertical li button.toctree-expand{display:inline-block;text-decoration:inherit}.btn .fa,.btn .icon,.btn .rst-content .admonition-title,.btn .rst-content .code-block-caption .headerlink,.btn .rst-content .eqno .headerlink,.btn .rst-content code.download span:first-child,.btn .rst-content dl dt .headerlink,.btn .rst-content h1 .headerlink,.btn .rst-content h2 .headerlink,.btn .rst-content h3 .headerlink,.btn .rst-content h4 .headerlink,.btn .rst-content h5 .headerlink,.btn .rst-content h6 .headerlink,.btn .rst-content p .headerlink,.btn .rst-content table>caption .headerlink,.btn .rst-content tt.download span:first-child,.btn .wy-menu-vertical li.current>a button.toctree-expand,.btn .wy-menu-vertical li.on a button.toctree-expand,.btn .wy-menu-vertical li button.toctree-expand,.nav .fa,.nav .icon,.nav .rst-content .admonition-title,.nav .rst-content .code-block-caption .headerlink,.nav .rst-content .eqno .headerlink,.nav .rst-content code.download span:first-child,.nav .rst-content dl dt .headerlink,.nav .rst-content h1 .headerlink,.nav .rst-content h2 .headerlink,.nav .rst-content h3 .headerlink,.nav .rst-content h4 .headerlink,.nav .rst-content h5 .headerlink,.nav .rst-content h6 .headerlink,.nav .rst-content p .headerlink,.nav .rst-content table>caption .headerlink,.nav .rst-content tt.download span:first-child,.nav .wy-menu-vertical li.current>a button.toctree-expand,.nav .wy-menu-vertical li.on a button.toctree-expand,.nav .wy-menu-vertical li button.toctree-expand,.rst-content .btn .admonition-title,.rst-content .code-block-caption .btn .headerlink,.rst-content .code-block-caption .nav .headerlink,.rst-content .eqno .btn .headerlink,.rst-content .eqno .nav .headerlink,.rst-content .nav .admonition-title,.rst-content code.download .btn span:first-child,.rst-content code.download .nav span:first-child,.rst-content dl dt .btn .headerlink,.rst-content dl dt .nav .headerlink,.rst-content h1 .btn .headerlink,.rst-content h1 .nav .headerlink,.rst-content h2 .btn .headerlink,.rst-content h2 .nav .headerlink,.rst-content h3 .btn .headerlink,.rst-content h3 .nav .headerlink,.rst-content h4 .btn .headerlink,.rst-content h4 .nav .headerlink,.rst-content h5 .btn .headerlink,.rst-content h5 .nav .headerlink,.rst-content h6 .btn .headerlink,.rst-content h6 .nav .headerlink,.rst-content p .btn .headerlink,.rst-content p .nav .headerlink,.rst-content table>caption .btn .headerlink,.rst-content table>caption .nav .headerlink,.rst-content tt.download .btn span:first-child,.rst-content tt.download .nav span:first-child,.wy-menu-vertical li .btn button.toctree-expand,.wy-menu-vertical li.current>a .btn button.toctree-expand,.wy-menu-vertical li.current>a .nav button.toctree-expand,.wy-menu-vertical li .nav button.toctree-expand,.wy-menu-vertical li.on a .btn button.toctree-expand,.wy-menu-vertical li.on a .nav button.toctree-expand{display:inline}.btn .fa-large.icon,.btn .fa.fa-large,.btn .rst-content .code-block-caption .fa-large.headerlink,.btn .rst-content .eqno .fa-large.headerlink,.btn .rst-content .fa-large.admonition-title,.btn .rst-content code.download span.fa-large:first-child,.btn .rst-content dl dt .fa-large.headerlink,.btn .rst-content h1 .fa-large.headerlink,.btn .rst-content h2 .fa-large.headerlink,.btn .rst-content h3 .fa-large.headerlink,.btn .rst-content h4 .fa-large.headerlink,.btn .rst-content h5 .fa-large.headerlink,.btn .rst-content h6 .fa-large.headerlink,.btn .rst-content p .fa-large.headerlink,.btn .rst-content table>caption .fa-large.headerlink,.btn .rst-content tt.download span.fa-large:first-child,.btn .wy-menu-vertical li button.fa-large.toctree-expand,.nav .fa-large.icon,.nav .fa.fa-large,.nav .rst-content .code-block-caption .fa-large.headerlink,.nav .rst-content .eqno .fa-large.headerlink,.nav .rst-content .fa-large.admonition-title,.nav .rst-content code.download span.fa-large:first-child,.nav .rst-content dl dt .fa-large.headerlink,.nav .rst-content h1 .fa-large.headerlink,.nav .rst-content h2 .fa-large.headerlink,.nav .rst-content h3 .fa-large.headerlink,.nav .rst-content h4 .fa-large.headerlink,.nav .rst-content h5 .fa-large.headerlink,.nav .rst-content h6 .fa-large.headerlink,.nav .rst-content p .fa-large.headerlink,.nav .rst-content table>caption .fa-large.headerlink,.nav .rst-content tt.download span.fa-large:first-child,.nav .wy-menu-vertical li button.fa-large.toctree-expand,.rst-content .btn .fa-large.admonition-title,.rst-content .code-block-caption .btn .fa-large.headerlink,.rst-content .code-block-caption .nav .fa-large.headerlink,.rst-content .eqno .btn .fa-large.headerlink,.rst-content .eqno .nav .fa-large.headerlink,.rst-content .nav .fa-large.admonition-title,.rst-content code.download .btn span.fa-large:first-child,.rst-content code.download .nav span.fa-large:first-child,.rst-content dl dt .btn .fa-large.headerlink,.rst-content dl dt .nav .fa-large.headerlink,.rst-content h1 .btn .fa-large.headerlink,.rst-content h1 .nav .fa-large.headerlink,.rst-content h2 .btn .fa-large.headerlink,.rst-content h2 .nav .fa-large.headerlink,.rst-content h3 .btn .fa-large.headerlink,.rst-content h3 .nav .fa-large.headerlink,.rst-content h4 .btn .fa-large.headerlink,.rst-content h4 .nav .fa-large.headerlink,.rst-content h5 .btn .fa-large.headerlink,.rst-content h5 .nav .fa-large.headerlink,.rst-content h6 .btn .fa-large.headerlink,.rst-content h6 .nav .fa-large.headerlink,.rst-content p .btn .fa-large.headerlink,.rst-content p .nav .fa-large.headerlink,.rst-content table>caption .btn .fa-large.headerlink,.rst-content table>caption .nav .fa-large.headerlink,.rst-content tt.download .btn span.fa-large:first-child,.rst-content tt.download .nav span.fa-large:first-child,.wy-menu-vertical li .btn button.fa-large.toctree-expand,.wy-menu-vertical li .nav button.fa-large.toctree-expand{line-height:.9em}.btn .fa-spin.icon,.btn .fa.fa-spin,.btn .rst-content .code-block-caption .fa-spin.headerlink,.btn .rst-content .eqno .fa-spin.headerlink,.btn .rst-content .fa-spin.admonition-title,.btn .rst-content code.download span.fa-spin:first-child,.btn .rst-content dl dt .fa-spin.headerlink,.btn .rst-content h1 .fa-spin.headerlink,.btn .rst-content h2 .fa-spin.headerlink,.btn .rst-content h3 .fa-spin.headerlink,.btn .rst-content h4 .fa-spin.headerlink,.btn .rst-content h5 .fa-spin.headerlink,.btn .rst-content h6 .fa-spin.headerlink,.btn .rst-content p .fa-spin.headerlink,.btn .rst-content table>caption .fa-spin.headerlink,.btn .rst-content tt.download span.fa-spin:first-child,.btn .wy-menu-vertical li button.fa-spin.toctree-expand,.nav .fa-spin.icon,.nav .fa.fa-spin,.nav .rst-content .code-block-caption .fa-spin.headerlink,.nav .rst-content .eqno .fa-spin.headerlink,.nav .rst-content .fa-spin.admonition-title,.nav .rst-content code.download span.fa-spin:first-child,.nav .rst-content dl dt .fa-spin.headerlink,.nav .rst-content h1 .fa-spin.headerlink,.nav .rst-content h2 .fa-spin.headerlink,.nav .rst-content h3 .fa-spin.headerlink,.nav .rst-content h4 .fa-spin.headerlink,.nav .rst-content h5 .fa-spin.headerlink,.nav .rst-content h6 .fa-spin.headerlink,.nav .rst-content p .fa-spin.headerlink,.nav .rst-content table>caption .fa-spin.headerlink,.nav .rst-content tt.download span.fa-spin:first-child,.nav .wy-menu-vertical li button.fa-spin.toctree-expand,.rst-content .btn .fa-spin.admonition-title,.rst-content .code-block-caption .btn .fa-spin.headerlink,.rst-content .code-block-caption .nav .fa-spin.headerlink,.rst-content .eqno .btn .fa-spin.headerlink,.rst-content .eqno .nav .fa-spin.headerlink,.rst-content .nav .fa-spin.admonition-title,.rst-content code.download .btn span.fa-spin:first-child,.rst-content code.download .nav span.fa-spin:first-child,.rst-content dl dt .btn .fa-spin.headerlink,.rst-content dl dt .nav .fa-spin.headerlink,.rst-content h1 .btn .fa-spin.headerlink,.rst-content h1 .nav .fa-spin.headerlink,.rst-content h2 .btn .fa-spin.headerlink,.rst-content h2 .nav .fa-spin.headerlink,.rst-content h3 .btn .fa-spin.headerlink,.rst-content h3 .nav .fa-spin.headerlink,.rst-content h4 .btn .fa-spin.headerlink,.rst-content h4 .nav .fa-spin.headerlink,.rst-content h5 .btn .fa-spin.headerlink,.rst-content h5 .nav .fa-spin.headerlink,.rst-content h6 .btn .fa-spin.headerlink,.rst-content h6 .nav .fa-spin.headerlink,.rst-content p .btn .fa-spin.headerlink,.rst-content p .nav .fa-spin.headerlink,.rst-content table>caption .btn .fa-spin.headerlink,.rst-content table>caption .nav .fa-spin.headerlink,.rst-content tt.download .btn span.fa-spin:first-child,.rst-content tt.download .nav span.fa-spin:first-child,.wy-menu-vertical li .btn button.fa-spin.toctree-expand,.wy-menu-vertical li .nav button.fa-spin.toctree-expand{display:inline-block}.btn.fa:before,.btn.icon:before,.rst-content .btn.admonition-title:before,.rst-content .code-block-caption .btn.headerlink:before,.rst-content .eqno .btn.headerlink:before,.rst-content code.download span.btn:first-child:before,.rst-content dl dt .btn.headerlink:before,.rst-content h1 .btn.headerlink:before,.rst-content h2 .btn.headerlink:before,.rst-content h3 .btn.headerlink:before,.rst-content h4 .btn.headerlink:before,.rst-content h5 .btn.headerlink:before,.rst-content h6 .btn.headerlink:before,.rst-content p .btn.headerlink:before,.rst-content table>caption .btn.headerlink:before,.rst-content tt.download span.btn:first-child:before,.wy-menu-vertical li button.btn.toctree-expand:before{opacity:.5;-webkit-transition:opacity .05s ease-in;-moz-transition:opacity .05s ease-in;transition:opacity .05s ease-in}.btn.fa:hover:before,.btn.icon:hover:before,.rst-content .btn.admonition-title:hover:before,.rst-content .code-block-caption .btn.headerlink:hover:before,.rst-content .eqno .btn.headerlink:hover:before,.rst-content code.download span.btn:first-child:hover:before,.rst-content dl dt .btn.headerlink:hover:before,.rst-content h1 .btn.headerlink:hover:before,.rst-content h2 .btn.headerlink:hover:before,.rst-content h3 .btn.headerlink:hover:before,.rst-content h4 .btn.headerlink:hover:before,.rst-content h5 .btn.headerlink:hover:before,.rst-content h6 .btn.headerlink:hover:before,.rst-content p .btn.headerlink:hover:before,.rst-content table>caption .btn.headerlink:hover:before,.rst-content tt.download span.btn:first-child:hover:before,.wy-menu-vertical li button.btn.toctree-expand:hover:before{opacity:1}.btn-mini .fa:before,.btn-mini .icon:before,.btn-mini .rst-content .admonition-title:before,.btn-mini .rst-content .code-block-caption .headerlink:before,.btn-mini .rst-content .eqno .headerlink:before,.btn-mini .rst-content code.download span:first-child:before,.btn-mini .rst-content dl dt .headerlink:before,.btn-mini .rst-content h1 .headerlink:before,.btn-mini .rst-content h2 .headerlink:before,.btn-mini .rst-content h3 .headerlink:before,.btn-mini .rst-content h4 .headerlink:before,.btn-mini .rst-content h5 .headerlink:before,.btn-mini .rst-content h6 .headerlink:before,.btn-mini .rst-content p .headerlink:before,.btn-mini .rst-content table>caption .headerlink:before,.btn-mini .rst-content tt.download span:first-child:before,.btn-mini .wy-menu-vertical li button.toctree-expand:before,.rst-content .btn-mini .admonition-title:before,.rst-content .code-block-caption .btn-mini .headerlink:before,.rst-content .eqno .btn-mini .headerlink:before,.rst-content code.download .btn-mini span:first-child:before,.rst-content dl dt .btn-mini .headerlink:before,.rst-content h1 .btn-mini .headerlink:before,.rst-content h2 .btn-mini .headerlink:before,.rst-content h3 .btn-mini .headerlink:before,.rst-content h4 .btn-mini .headerlink:before,.rst-content h5 .btn-mini .headerlink:before,.rst-content h6 .btn-mini .headerlink:before,.rst-content p .btn-mini .headerlink:before,.rst-content table>caption .btn-mini .headerlink:before,.rst-content tt.download .btn-mini span:first-child:before,.wy-menu-vertical li .btn-mini button.toctree-expand:before{font-size:14px;vertical-align:-15%}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.wy-alert{padding:12px;line-height:24px;margin-bottom:24px;background:#e7f2fa}.rst-content .admonition-title,.wy-alert-title{font-weight:700;display:block;color:#fff;background:#6ab0de;padding:6px 12px;margin:-12px -12px 12px}.rst-content .danger,.rst-content .error,.rst-content .wy-alert-danger.admonition,.rst-content .wy-alert-danger.admonition-todo,.rst-content .wy-alert-danger.attention,.rst-content .wy-alert-danger.caution,.rst-content .wy-alert-danger.hint,.rst-content .wy-alert-danger.important,.rst-content .wy-alert-danger.note,.rst-content .wy-alert-danger.seealso,.rst-content .wy-alert-danger.tip,.rst-content .wy-alert-danger.warning,.wy-alert.wy-alert-danger{background:#fdf3f2}.rst-content .danger .admonition-title,.rst-content .danger .wy-alert-title,.rst-content .error .admonition-title,.rst-content .error .wy-alert-title,.rst-content .wy-alert-danger.admonition-todo .admonition-title,.rst-content .wy-alert-danger.admonition-todo .wy-alert-title,.rst-content .wy-alert-danger.admonition .admonition-title,.rst-content .wy-alert-danger.admonition .wy-alert-title,.rst-content .wy-alert-danger.attention .admonition-title,.rst-content .wy-alert-danger.attention .wy-alert-title,.rst-content .wy-alert-danger.caution .admonition-title,.rst-content .wy-alert-danger.caution .wy-alert-title,.rst-content .wy-alert-danger.hint .admonition-title,.rst-content .wy-alert-danger.hint .wy-alert-title,.rst-content .wy-alert-danger.important .admonition-title,.rst-content .wy-alert-danger.important .wy-alert-title,.rst-content .wy-alert-danger.note .admonition-title,.rst-content .wy-alert-danger.note .wy-alert-title,.rst-content .wy-alert-danger.seealso .admonition-title,.rst-content .wy-alert-danger.seealso .wy-alert-title,.rst-content .wy-alert-danger.tip .admonition-title,.rst-content .wy-alert-danger.tip .wy-alert-title,.rst-content .wy-alert-danger.warning .admonition-title,.rst-content .wy-alert-danger.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-danger .admonition-title,.wy-alert.wy-alert-danger .rst-content .admonition-title,.wy-alert.wy-alert-danger .wy-alert-title{background:#f29f97}.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .warning,.rst-content .wy-alert-warning.admonition,.rst-content .wy-alert-warning.danger,.rst-content .wy-alert-warning.error,.rst-content .wy-alert-warning.hint,.rst-content .wy-alert-warning.important,.rst-content .wy-alert-warning.note,.rst-content .wy-alert-warning.seealso,.rst-content .wy-alert-warning.tip,.wy-alert.wy-alert-warning{background:#ffedcc}.rst-content .admonition-todo .admonition-title,.rst-content .admonition-todo .wy-alert-title,.rst-content .attention .admonition-title,.rst-content .attention .wy-alert-title,.rst-content .caution .admonition-title,.rst-content .caution .wy-alert-title,.rst-content .warning .admonition-title,.rst-content .warning .wy-alert-title,.rst-content .wy-alert-warning.admonition .admonition-title,.rst-content .wy-alert-warning.admonition .wy-alert-title,.rst-content .wy-alert-warning.danger .admonition-title,.rst-content .wy-alert-warning.danger .wy-alert-title,.rst-content .wy-alert-warning.error .admonition-title,.rst-content .wy-alert-warning.error .wy-alert-title,.rst-content .wy-alert-warning.hint .admonition-title,.rst-content .wy-alert-warning.hint .wy-alert-title,.rst-content .wy-alert-warning.important .admonition-title,.rst-content .wy-alert-warning.important .wy-alert-title,.rst-content .wy-alert-warning.note .admonition-title,.rst-content .wy-alert-warning.note .wy-alert-title,.rst-content .wy-alert-warning.seealso .admonition-title,.rst-content .wy-alert-warning.seealso .wy-alert-title,.rst-content .wy-alert-warning.tip .admonition-title,.rst-content .wy-alert-warning.tip .wy-alert-title,.rst-content .wy-alert.wy-alert-warning .admonition-title,.wy-alert.wy-alert-warning .rst-content .admonition-title,.wy-alert.wy-alert-warning .wy-alert-title{background:#f0b37e}.rst-content .note,.rst-content .seealso,.rst-content .wy-alert-info.admonition,.rst-content .wy-alert-info.admonition-todo,.rst-content .wy-alert-info.attention,.rst-content .wy-alert-info.caution,.rst-content .wy-alert-info.danger,.rst-content .wy-alert-info.error,.rst-content .wy-alert-info.hint,.rst-content .wy-alert-info.important,.rst-content .wy-alert-info.tip,.rst-content .wy-alert-info.warning,.wy-alert.wy-alert-info{background:#e7f2fa}.rst-content .note .admonition-title,.rst-content .note .wy-alert-title,.rst-content .seealso .admonition-title,.rst-content .seealso .wy-alert-title,.rst-content .wy-alert-info.admonition-todo .admonition-title,.rst-content .wy-alert-info.admonition-todo .wy-alert-title,.rst-content .wy-alert-info.admonition .admonition-title,.rst-content .wy-alert-info.admonition .wy-alert-title,.rst-content .wy-alert-info.attention .admonition-title,.rst-content .wy-alert-info.attention .wy-alert-title,.rst-content .wy-alert-info.caution .admonition-title,.rst-content .wy-alert-info.caution .wy-alert-title,.rst-content .wy-alert-info.danger .admonition-title,.rst-content .wy-alert-info.danger .wy-alert-title,.rst-content .wy-alert-info.error .admonition-title,.rst-content .wy-alert-info.error .wy-alert-title,.rst-content .wy-alert-info.hint .admonition-title,.rst-content .wy-alert-info.hint .wy-alert-title,.rst-content .wy-alert-info.important .admonition-title,.rst-content .wy-alert-info.important .wy-alert-title,.rst-content .wy-alert-info.tip .admonition-title,.rst-content .wy-alert-info.tip .wy-alert-title,.rst-content .wy-alert-info.warning .admonition-title,.rst-content .wy-alert-info.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-info .admonition-title,.wy-alert.wy-alert-info .rst-content .admonition-title,.wy-alert.wy-alert-info .wy-alert-title{background:#6ab0de}.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .wy-alert-success.admonition,.rst-content .wy-alert-success.admonition-todo,.rst-content .wy-alert-success.attention,.rst-content .wy-alert-success.caution,.rst-content .wy-alert-success.danger,.rst-content .wy-alert-success.error,.rst-content .wy-alert-success.note,.rst-content .wy-alert-success.seealso,.rst-content .wy-alert-success.warning,.wy-alert.wy-alert-success{background:#dbfaf4}.rst-content .hint .admonition-title,.rst-content .hint .wy-alert-title,.rst-content .important .admonition-title,.rst-content .important .wy-alert-title,.rst-content .tip .admonition-title,.rst-content .tip .wy-alert-title,.rst-content .wy-alert-success.admonition-todo .admonition-title,.rst-content .wy-alert-success.admonition-todo .wy-alert-title,.rst-content .wy-alert-success.admonition .admonition-title,.rst-content .wy-alert-success.admonition .wy-alert-title,.rst-content .wy-alert-success.attention .admonition-title,.rst-content .wy-alert-success.attention .wy-alert-title,.rst-content .wy-alert-success.caution .admonition-title,.rst-content .wy-alert-success.caution .wy-alert-title,.rst-content .wy-alert-success.danger .admonition-title,.rst-content .wy-alert-success.danger .wy-alert-title,.rst-content .wy-alert-success.error .admonition-title,.rst-content .wy-alert-success.error .wy-alert-title,.rst-content .wy-alert-success.note .admonition-title,.rst-content .wy-alert-success.note .wy-alert-title,.rst-content .wy-alert-success.seealso .admonition-title,.rst-content .wy-alert-success.seealso .wy-alert-title,.rst-content .wy-alert-success.warning .admonition-title,.rst-content .wy-alert-success.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-success .admonition-title,.wy-alert.wy-alert-success .rst-content .admonition-title,.wy-alert.wy-alert-success .wy-alert-title{background:#1abc9c}.rst-content .wy-alert-neutral.admonition,.rst-content .wy-alert-neutral.admonition-todo,.rst-content .wy-alert-neutral.attention,.rst-content .wy-alert-neutral.caution,.rst-content .wy-alert-neutral.danger,.rst-content .wy-alert-neutral.error,.rst-content .wy-alert-neutral.hint,.rst-content .wy-alert-neutral.important,.rst-content .wy-alert-neutral.note,.rst-content .wy-alert-neutral.seealso,.rst-content .wy-alert-neutral.tip,.rst-content .wy-alert-neutral.warning,.wy-alert.wy-alert-neutral{background:#f3f6f6}.rst-content .wy-alert-neutral.admonition-todo .admonition-title,.rst-content .wy-alert-neutral.admonition-todo .wy-alert-title,.rst-content .wy-alert-neutral.admonition .admonition-title,.rst-content .wy-alert-neutral.admonition .wy-alert-title,.rst-content .wy-alert-neutral.attention .admonition-title,.rst-content .wy-alert-neutral.attention .wy-alert-title,.rst-content .wy-alert-neutral.caution .admonition-title,.rst-content .wy-alert-neutral.caution .wy-alert-title,.rst-content .wy-alert-neutral.danger .admonition-title,.rst-content .wy-alert-neutral.danger .wy-alert-title,.rst-content .wy-alert-neutral.error .admonition-title,.rst-content .wy-alert-neutral.error .wy-alert-title,.rst-content .wy-alert-neutral.hint .admonition-title,.rst-content .wy-alert-neutral.hint .wy-alert-title,.rst-content .wy-alert-neutral.important .admonition-title,.rst-content .wy-alert-neutral.important .wy-alert-title,.rst-content .wy-alert-neutral.note .admonition-title,.rst-content .wy-alert-neutral.note .wy-alert-title,.rst-content .wy-alert-neutral.seealso .admonition-title,.rst-content .wy-alert-neutral.seealso .wy-alert-title,.rst-content .wy-alert-neutral.tip .admonition-title,.rst-content .wy-alert-neutral.tip .wy-alert-title,.rst-content .wy-alert-neutral.warning .admonition-title,.rst-content .wy-alert-neutral.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-neutral .admonition-title,.wy-alert.wy-alert-neutral .rst-content .admonition-title,.wy-alert.wy-alert-neutral .wy-alert-title{color:#404040;background:#e1e4e5}.rst-content .wy-alert-neutral.admonition-todo a,.rst-content .wy-alert-neutral.admonition a,.rst-content .wy-alert-neutral.attention a,.rst-content .wy-alert-neutral.caution a,.rst-content .wy-alert-neutral.danger a,.rst-content .wy-alert-neutral.error a,.rst-content .wy-alert-neutral.hint a,.rst-content .wy-alert-neutral.important a,.rst-content .wy-alert-neutral.note a,.rst-content .wy-alert-neutral.seealso a,.rst-content .wy-alert-neutral.tip a,.rst-content .wy-alert-neutral.warning a,.wy-alert.wy-alert-neutral a{color:#2980b9}.rst-content .admonition-todo p:last-child,.rst-content .admonition p:last-child,.rst-content .attention p:last-child,.rst-content .caution p:last-child,.rst-content .danger p:last-child,.rst-content .error p:last-child,.rst-content .hint p:last-child,.rst-content .important p:last-child,.rst-content .note p:last-child,.rst-content .seealso p:last-child,.rst-content .tip p:last-child,.rst-content .warning p:last-child,.wy-alert p:last-child{margin-bottom:0}.wy-tray-container{position:fixed;bottom:0;left:0;z-index:600}.wy-tray-container li{display:block;width:300px;background:transparent;color:#fff;text-align:center;box-shadow:0 5px 5px 0 rgba(0,0,0,.1);padding:0 24px;min-width:20%;opacity:0;height:0;line-height:56px;overflow:hidden;-webkit-transition:all .3s ease-in;-moz-transition:all .3s ease-in;transition:all .3s ease-in}.wy-tray-container li.wy-tray-item-success{background:#27ae60}.wy-tray-container li.wy-tray-item-info{background:#2980b9}.wy-tray-container li.wy-tray-item-warning{background:#e67e22}.wy-tray-container li.wy-tray-item-danger{background:#e74c3c}.wy-tray-container li.on{opacity:1;height:56px}@media screen and (max-width:768px){.wy-tray-container{bottom:auto;top:0;width:100%}.wy-tray-container li{width:100%}}button{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;cursor:pointer;line-height:normal;-webkit-appearance:button;*overflow:visible}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}button[disabled]{cursor:default}.btn{display:inline-block;border-radius:2px;line-height:normal;white-space:nowrap;text-align:center;cursor:pointer;font-size:100%;padding:6px 12px 8px;color:#fff;border:1px solid rgba(0,0,0,.1);background-color:#27ae60;text-decoration:none;font-weight:400;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 2px -1px hsla(0,0%,100%,.5),inset 0 -2px 0 0 rgba(0,0,0,.1);outline-none:false;vertical-align:middle;*display:inline;zoom:1;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:all .1s linear;-moz-transition:all .1s linear;transition:all .1s linear}.btn-hover{background:#2e8ece;color:#fff}.btn:hover{background:#2cc36b;color:#fff}.btn:focus{background:#2cc36b;outline:0}.btn:active{box-shadow:inset 0 -1px 0 0 rgba(0,0,0,.05),inset 0 2px 0 0 rgba(0,0,0,.1);padding:8px 12px 6px}.btn:visited{color:#fff}.btn-disabled,.btn-disabled:active,.btn-disabled:focus,.btn-disabled:hover,.btn:disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:.4;cursor:not-allowed;box-shadow:none}.btn::-moz-focus-inner{padding:0;border:0}.btn-small{font-size:80%}.btn-info{background-color:#2980b9!important}.btn-info:hover{background-color:#2e8ece!important}.btn-neutral{background-color:#f3f6f6!important;color:#404040!important}.btn-neutral:hover{background-color:#e5ebeb!important;color:#404040}.btn-neutral:visited{color:#404040!important}.btn-success{background-color:#27ae60!important}.btn-success:hover{background-color:#295!important}.btn-danger{background-color:#e74c3c!important}.btn-danger:hover{background-color:#ea6153!important}.btn-warning{background-color:#e67e22!important}.btn-warning:hover{background-color:#e98b39!important}.btn-invert{background-color:#222}.btn-invert:hover{background-color:#2f2f2f!important}.btn-link{background-color:transparent!important;color:#2980b9;box-shadow:none;border-color:transparent!important}.btn-link:active,.btn-link:hover{background-color:transparent!important;color:#409ad5!important;box-shadow:none}.btn-link:visited{color:#9b59b6}.wy-btn-group .btn,.wy-control .btn{vertical-align:middle}.wy-btn-group{margin-bottom:24px;*zoom:1}.wy-btn-group:after,.wy-btn-group:before{display:table;content:""}.wy-btn-group:after{clear:both}.wy-dropdown{position:relative;display:inline-block}.wy-dropdown-active .wy-dropdown-menu{display:block}.wy-dropdown-menu{position:absolute;left:0;display:none;float:left;top:100%;min-width:100%;background:#fcfcfc;z-index:100;border:1px solid #cfd7dd;box-shadow:0 2px 2px 0 rgba(0,0,0,.1);padding:12px}.wy-dropdown-menu>dd>a{display:block;clear:both;color:#404040;white-space:nowrap;font-size:90%;padding:0 12px;cursor:pointer}.wy-dropdown-menu>dd>a:hover{background:#2980b9;color:#fff}.wy-dropdown-menu>dd.divider{border-top:1px solid #cfd7dd;margin:6px 0}.wy-dropdown-menu>dd.search{padding-bottom:12px}.wy-dropdown-menu>dd.search input[type=search]{width:100%}.wy-dropdown-menu>dd.call-to-action{background:#e3e3e3;text-transform:uppercase;font-weight:500;font-size:80%}.wy-dropdown-menu>dd.call-to-action:hover{background:#e3e3e3}.wy-dropdown-menu>dd.call-to-action .btn{color:#fff}.wy-dropdown.wy-dropdown-up .wy-dropdown-menu{bottom:100%;top:auto;left:auto;right:0}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu{background:#fcfcfc;margin-top:2px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a{padding:6px 12px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover{background:#2980b9;color:#fff}.wy-dropdown.wy-dropdown-left .wy-dropdown-menu{right:0;left:auto;text-align:right}.wy-dropdown-arrow:before{content:" ";border-bottom:5px solid #f5f5f5;border-left:5px solid transparent;border-right:5px solid transparent;position:absolute;display:block;top:-4px;left:50%;margin-left:-3px}.wy-dropdown-arrow.wy-dropdown-arrow-left:before{left:11px}.wy-form-stacked select{display:block}.wy-form-aligned .wy-help-inline,.wy-form-aligned input,.wy-form-aligned label,.wy-form-aligned select,.wy-form-aligned textarea{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-form-aligned .wy-control-group>label{display:inline-block;vertical-align:middle;width:10em;margin:6px 12px 0 0;float:left}.wy-form-aligned .wy-control{float:left}.wy-form-aligned .wy-control label{display:block}.wy-form-aligned .wy-control select{margin-top:6px}fieldset{margin:0}fieldset,legend{border:0;padding:0}legend{width:100%;white-space:normal;margin-bottom:24px;font-size:150%;*margin-left:-7px}label,legend{display:block}label{margin:0 0 .3125em;color:#333;font-size:90%}input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}.wy-control-group{margin-bottom:24px;max-width:1200px;margin-left:auto;margin-right:auto;*zoom:1}.wy-control-group:after,.wy-control-group:before{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group.wy-control-group-required>label:after{content:" *";color:#e74c3c}.wy-control-group .wy-form-full,.wy-control-group .wy-form-halves,.wy-control-group .wy-form-thirds{padding-bottom:12px}.wy-control-group .wy-form-full input[type=color],.wy-control-group .wy-form-full input[type=date],.wy-control-group .wy-form-full input[type=datetime-local],.wy-control-group .wy-form-full input[type=datetime],.wy-control-group .wy-form-full input[type=email],.wy-control-group .wy-form-full input[type=month],.wy-control-group .wy-form-full input[type=number],.wy-control-group .wy-form-full input[type=password],.wy-control-group .wy-form-full input[type=search],.wy-control-group .wy-form-full input[type=tel],.wy-control-group .wy-form-full input[type=text],.wy-control-group .wy-form-full input[type=time],.wy-control-group .wy-form-full input[type=url],.wy-control-group .wy-form-full input[type=week],.wy-control-group .wy-form-full select,.wy-control-group .wy-form-halves input[type=color],.wy-control-group .wy-form-halves input[type=date],.wy-control-group .wy-form-halves input[type=datetime-local],.wy-control-group .wy-form-halves input[type=datetime],.wy-control-group .wy-form-halves input[type=email],.wy-control-group .wy-form-halves input[type=month],.wy-control-group .wy-form-halves input[type=number],.wy-control-group .wy-form-halves input[type=password],.wy-control-group .wy-form-halves input[type=search],.wy-control-group .wy-form-halves input[type=tel],.wy-control-group .wy-form-halves input[type=text],.wy-control-group .wy-form-halves input[type=time],.wy-control-group .wy-form-halves input[type=url],.wy-control-group .wy-form-halves input[type=week],.wy-control-group .wy-form-halves select,.wy-control-group .wy-form-thirds input[type=color],.wy-control-group .wy-form-thirds input[type=date],.wy-control-group .wy-form-thirds input[type=datetime-local],.wy-control-group .wy-form-thirds input[type=datetime],.wy-control-group .wy-form-thirds input[type=email],.wy-control-group .wy-form-thirds input[type=month],.wy-control-group .wy-form-thirds input[type=number],.wy-control-group .wy-form-thirds input[type=password],.wy-control-group .wy-form-thirds input[type=search],.wy-control-group .wy-form-thirds input[type=tel],.wy-control-group .wy-form-thirds input[type=text],.wy-control-group .wy-form-thirds input[type=time],.wy-control-group .wy-form-thirds input[type=url],.wy-control-group .wy-form-thirds input[type=week],.wy-control-group .wy-form-thirds select{width:100%}.wy-control-group .wy-form-full{float:left;display:block;width:100%;margin-right:0}.wy-control-group .wy-form-full:last-child{margin-right:0}.wy-control-group .wy-form-halves{float:left;display:block;margin-right:2.35765%;width:48.82117%}.wy-control-group .wy-form-halves:last-child,.wy-control-group .wy-form-halves:nth-of-type(2n){margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(odd){clear:left}.wy-control-group .wy-form-thirds{float:left;display:block;margin-right:2.35765%;width:31.76157%}.wy-control-group .wy-form-thirds:last-child,.wy-control-group .wy-form-thirds:nth-of-type(3n){margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n+1){clear:left}.wy-control-group.wy-control-group-no-input .wy-control,.wy-control-no-input{margin:6px 0 0;font-size:90%}.wy-control-no-input{display:inline-block}.wy-control-group.fluid-input input[type=color],.wy-control-group.fluid-input input[type=date],.wy-control-group.fluid-input input[type=datetime-local],.wy-control-group.fluid-input input[type=datetime],.wy-control-group.fluid-input input[type=email],.wy-control-group.fluid-input input[type=month],.wy-control-group.fluid-input input[type=number],.wy-control-group.fluid-input input[type=password],.wy-control-group.fluid-input input[type=search],.wy-control-group.fluid-input input[type=tel],.wy-control-group.fluid-input input[type=text],.wy-control-group.fluid-input input[type=time],.wy-control-group.fluid-input input[type=url],.wy-control-group.fluid-input input[type=week]{width:100%}.wy-form-message-inline{padding-left:.3em;color:#666;font-size:90%}.wy-form-message{display:block;color:#999;font-size:70%;margin-top:.3125em;font-style:italic}.wy-form-message p{font-size:inherit;font-style:italic;margin-bottom:6px}.wy-form-message p:last-child{margin-bottom:0}input{line-height:normal}input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;*overflow:visible}input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week]{-webkit-appearance:none;padding:6px;display:inline-block;border:1px solid #ccc;font-size:80%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 3px #ddd;border-radius:0;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}input[type=datetime-local]{padding:.34375em .625em}input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{padding:0;margin-right:.3125em;*height:13px;*width:13px}input[type=checkbox],input[type=radio],input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}input[type=color]:focus,input[type=date]:focus,input[type=datetime-local]:focus,input[type=datetime]:focus,input[type=email]:focus,input[type=month]:focus,input[type=number]:focus,input[type=password]:focus,input[type=search]:focus,input[type=tel]:focus,input[type=text]:focus,input[type=time]:focus,input[type=url]:focus,input[type=week]:focus{outline:0;outline:thin dotted\9;border-color:#333}input.no-focus:focus{border-color:#ccc!important}input[type=checkbox]:focus,input[type=file]:focus,input[type=radio]:focus{outline:thin dotted #333;outline:1px auto #129fea}input[type=color][disabled],input[type=date][disabled],input[type=datetime-local][disabled],input[type=datetime][disabled],input[type=email][disabled],input[type=month][disabled],input[type=number][disabled],input[type=password][disabled],input[type=search][disabled],input[type=tel][disabled],input[type=text][disabled],input[type=time][disabled],input[type=url][disabled],input[type=week][disabled]{cursor:not-allowed;background-color:#fafafa}input:focus:invalid,select:focus:invalid,textarea:focus:invalid{color:#e74c3c;border:1px solid #e74c3c}input:focus:invalid:focus,select:focus:invalid:focus,textarea:focus:invalid:focus{border-color:#e74c3c}input[type=checkbox]:focus:invalid:focus,input[type=file]:focus:invalid:focus,input[type=radio]:focus:invalid:focus{outline-color:#e74c3c}input.wy-input-large{padding:12px;font-size:100%}textarea{overflow:auto;vertical-align:top;width:100%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif}select,textarea{padding:.5em .625em;display:inline-block;border:1px solid #ccc;font-size:80%;box-shadow:inset 0 1px 3px #ddd;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}select{border:1px solid #ccc;background-color:#fff}select[multiple]{height:auto}select:focus,textarea:focus{outline:0}input[readonly],select[disabled],select[readonly],textarea[disabled],textarea[readonly]{cursor:not-allowed;background-color:#fafafa}input[type=checkbox][disabled],input[type=radio][disabled]{cursor:not-allowed}.wy-checkbox,.wy-radio{margin:6px 0;color:#404040;display:block}.wy-checkbox input,.wy-radio input{vertical-align:baseline}.wy-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-input-prefix,.wy-input-suffix{white-space:nowrap;padding:6px}.wy-input-prefix .wy-input-context,.wy-input-suffix .wy-input-context{line-height:27px;padding:0 8px;display:inline-block;font-size:80%;background-color:#f3f6f6;border:1px solid #ccc;color:#999}.wy-input-suffix .wy-input-context{border-left:0}.wy-input-prefix .wy-input-context{border-right:0}.wy-switch{position:relative;display:block;height:24px;margin-top:12px;cursor:pointer}.wy-switch:before{left:0;top:0;width:36px;height:12px;background:#ccc}.wy-switch:after,.wy-switch:before{position:absolute;content:"";display:block;border-radius:4px;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.wy-switch:after{width:18px;height:18px;background:#999;left:-3px;top:-3px}.wy-switch span{position:absolute;left:48px;display:block;font-size:12px;color:#ccc;line-height:1}.wy-switch.active:before{background:#1e8449}.wy-switch.active:after{left:24px;background:#27ae60}.wy-switch.disabled{cursor:not-allowed;opacity:.8}.wy-control-group.wy-control-group-error .wy-form-message,.wy-control-group.wy-control-group-error>label{color:#e74c3c}.wy-control-group.wy-control-group-error input[type=color],.wy-control-group.wy-control-group-error input[type=date],.wy-control-group.wy-control-group-error input[type=datetime-local],.wy-control-group.wy-control-group-error input[type=datetime],.wy-control-group.wy-control-group-error input[type=email],.wy-control-group.wy-control-group-error input[type=month],.wy-control-group.wy-control-group-error input[type=number],.wy-control-group.wy-control-group-error input[type=password],.wy-control-group.wy-control-group-error input[type=search],.wy-control-group.wy-control-group-error input[type=tel],.wy-control-group.wy-control-group-error input[type=text],.wy-control-group.wy-control-group-error input[type=time],.wy-control-group.wy-control-group-error input[type=url],.wy-control-group.wy-control-group-error input[type=week],.wy-control-group.wy-control-group-error textarea{border:1px solid #e74c3c}.wy-inline-validate{white-space:nowrap}.wy-inline-validate .wy-input-context{padding:.5em .625em;display:inline-block;font-size:80%}.wy-inline-validate.wy-inline-validate-success .wy-input-context{color:#27ae60}.wy-inline-validate.wy-inline-validate-danger .wy-input-context{color:#e74c3c}.wy-inline-validate.wy-inline-validate-warning .wy-input-context{color:#e67e22}.wy-inline-validate.wy-inline-validate-info .wy-input-context{color:#2980b9}.rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.mirror{-webkit-transform:scaleX(-1);-moz-transform:scaleX(-1);-ms-transform:scaleX(-1);-o-transform:scaleX(-1);transform:scaleX(-1)}.mirror.rotate-90{-webkit-transform:scaleX(-1) rotate(90deg);-moz-transform:scaleX(-1) rotate(90deg);-ms-transform:scaleX(-1) rotate(90deg);-o-transform:scaleX(-1) rotate(90deg);transform:scaleX(-1) rotate(90deg)}.mirror.rotate-180{-webkit-transform:scaleX(-1) rotate(180deg);-moz-transform:scaleX(-1) rotate(180deg);-ms-transform:scaleX(-1) rotate(180deg);-o-transform:scaleX(-1) rotate(180deg);transform:scaleX(-1) rotate(180deg)}.mirror.rotate-270{-webkit-transform:scaleX(-1) rotate(270deg);-moz-transform:scaleX(-1) rotate(270deg);-ms-transform:scaleX(-1) rotate(270deg);-o-transform:scaleX(-1) rotate(270deg);transform:scaleX(-1) rotate(270deg)}@media only screen and (max-width:480px){.wy-form button[type=submit]{margin:.7em 0 0}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=text],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week],.wy-form label{margin-bottom:.3em;display:block}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week]{margin-bottom:0}.wy-form-aligned .wy-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.wy-form-aligned .wy-control{margin:1.5em 0 0}.wy-form-message,.wy-form-message-inline,.wy-form .wy-help-inline{display:block;font-size:80%;padding:6px 0}}@media screen and (max-width:768px){.tablet-hide{display:none}}@media screen and (max-width:480px){.mobile-hide{display:none}}.float-left{float:left}.float-right{float:right}.full-width{width:100%}.rst-content table.docutils,.rst-content table.field-list,.wy-table{border-collapse:collapse;border-spacing:0;empty-cells:show;margin-bottom:24px}.rst-content table.docutils caption,.rst-content table.field-list caption,.wy-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.rst-content table.docutils td,.rst-content table.docutils th,.rst-content table.field-list td,.rst-content table.field-list th,.wy-table td,.wy-table th{font-size:90%;margin:0;overflow:visible;padding:8px 16px}.rst-content table.docutils td:first-child,.rst-content table.docutils th:first-child,.rst-content table.field-list td:first-child,.rst-content table.field-list th:first-child,.wy-table td:first-child,.wy-table th:first-child{border-left-width:0}.rst-content table.docutils thead,.rst-content table.field-list thead,.wy-table thead{color:#000;text-align:left;vertical-align:bottom;white-space:nowrap}.rst-content table.docutils thead th,.rst-content table.field-list thead th,.wy-table thead th{font-weight:700;border-bottom:2px solid #e1e4e5}.rst-content table.docutils td,.rst-content table.field-list td,.wy-table td{background-color:transparent;vertical-align:middle}.rst-content table.docutils td p,.rst-content table.field-list td p,.wy-table td p{line-height:18px}.rst-content table.docutils td p:last-child,.rst-content table.field-list td p:last-child,.wy-table td p:last-child{margin-bottom:0}.rst-content table.docutils .wy-table-cell-min,.rst-content table.field-list .wy-table-cell-min,.wy-table .wy-table-cell-min{width:1%;padding-right:0}.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox],.wy-table .wy-table-cell-min input[type=checkbox]{margin:0}.wy-table-secondary{color:grey;font-size:90%}.wy-table-tertiary{color:grey;font-size:80%}.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td,.wy-table-backed,.wy-table-odd td,.wy-table-striped tr:nth-child(2n-1) td{background-color:#f3f6f6}.rst-content table.docutils,.wy-table-bordered-all{border:1px solid #e1e4e5}.rst-content table.docutils td,.wy-table-bordered-all td{border-bottom:1px solid #e1e4e5;border-left:1px solid #e1e4e5}.rst-content table.docutils tbody>tr:last-child td,.wy-table-bordered-all tbody>tr:last-child td{border-bottom-width:0}.wy-table-bordered{border:1px solid #e1e4e5}.wy-table-bordered-rows td{border-bottom:1px solid #e1e4e5}.wy-table-bordered-rows tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal td,.wy-table-horizontal th{border-width:0 0 1px;border-bottom:1px solid #e1e4e5}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-responsive{margin-bottom:24px;max-width:100%;overflow:auto}.wy-table-responsive table{margin-bottom:0!important}.wy-table-responsive table td,.wy-table-responsive table th{white-space:nowrap}a{color:#2980b9;text-decoration:none;cursor:pointer}a:hover{color:#3091d1}a:visited{color:#9b59b6}html{height:100%}body,html{overflow-x:hidden}body{font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;font-weight:400;color:#404040;min-height:100%;background:#edf0f2}.wy-text-left{text-align:left}.wy-text-center{text-align:center}.wy-text-right{text-align:right}.wy-text-large{font-size:120%}.wy-text-normal{font-size:100%}.wy-text-small,small{font-size:80%}.wy-text-strike{text-decoration:line-through}.wy-text-warning{color:#e67e22!important}a.wy-text-warning:hover{color:#eb9950!important}.wy-text-info{color:#2980b9!important}a.wy-text-info:hover{color:#409ad5!important}.wy-text-success{color:#27ae60!important}a.wy-text-success:hover{color:#36d278!important}.wy-text-danger{color:#e74c3c!important}a.wy-text-danger:hover{color:#ed7669!important}.wy-text-neutral{color:#404040!important}a.wy-text-neutral:hover{color:#595959!important}.rst-content .toctree-wrapper>p.caption,h1,h2,h3,h4,h5,h6,legend{margin-top:0;font-weight:700;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif}p{line-height:24px;font-size:16px;margin:0 0 24px}h1{font-size:175%}.rst-content .toctree-wrapper>p.caption,h2{font-size:150%}h3{font-size:125%}h4{font-size:115%}h5{font-size:110%}h6{font-size:100%}hr{display:block;height:1px;border:0;border-top:1px solid #e1e4e5;margin:24px 0;padding:0}.rst-content code,.rst-content tt,code{white-space:nowrap;max-width:100%;background:#fff;border:1px solid #e1e4e5;font-size:75%;padding:0 5px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#e74c3c;overflow-x:auto}.rst-content tt.code-large,code.code-large{font-size:90%}.rst-content .section ul,.rst-content .toctree-wrapper ul,.rst-content section ul,.wy-plain-list-disc,article ul{list-style:disc;line-height:24px;margin-bottom:24px}.rst-content .section ul li,.rst-content .toctree-wrapper ul li,.rst-content section ul li,.wy-plain-list-disc li,article ul li{list-style:disc;margin-left:24px}.rst-content .section ul li p:last-child,.rst-content .section ul li ul,.rst-content .toctree-wrapper ul li p:last-child,.rst-content .toctree-wrapper ul li ul,.rst-content section ul li p:last-child,.rst-content section ul li ul,.wy-plain-list-disc li p:last-child,.wy-plain-list-disc li ul,article ul li p:last-child,article ul li ul{margin-bottom:0}.rst-content .section ul li li,.rst-content .toctree-wrapper ul li li,.rst-content section ul li li,.wy-plain-list-disc li li,article ul li li{list-style:circle}.rst-content .section ul li li li,.rst-content .toctree-wrapper ul li li li,.rst-content section ul li li li,.wy-plain-list-disc li li li,article ul li li li{list-style:square}.rst-content .section ul li ol li,.rst-content .toctree-wrapper ul li ol li,.rst-content section ul li ol li,.wy-plain-list-disc li ol li,article ul li ol li{list-style:decimal}.rst-content .section ol,.rst-content .section ol.arabic,.rst-content .toctree-wrapper ol,.rst-content .toctree-wrapper ol.arabic,.rst-content section ol,.rst-content section ol.arabic,.wy-plain-list-decimal,article ol{list-style:decimal;line-height:24px;margin-bottom:24px}.rst-content .section ol.arabic li,.rst-content .section ol li,.rst-content .toctree-wrapper ol.arabic li,.rst-content .toctree-wrapper ol li,.rst-content section ol.arabic li,.rst-content section ol li,.wy-plain-list-decimal li,article ol li{list-style:decimal;margin-left:24px}.rst-content .section ol.arabic li ul,.rst-content .section ol li p:last-child,.rst-content .section ol li ul,.rst-content .toctree-wrapper ol.arabic li ul,.rst-content .toctree-wrapper ol li p:last-child,.rst-content .toctree-wrapper ol li ul,.rst-content section ol.arabic li ul,.rst-content section ol li p:last-child,.rst-content section ol li ul,.wy-plain-list-decimal li p:last-child,.wy-plain-list-decimal li ul,article ol li p:last-child,article ol li ul{margin-bottom:0}.rst-content .section ol.arabic li ul li,.rst-content .section ol li ul li,.rst-content .toctree-wrapper ol.arabic li ul li,.rst-content .toctree-wrapper ol li ul li,.rst-content section ol.arabic li ul li,.rst-content section ol li ul li,.wy-plain-list-decimal li ul li,article ol li ul li{list-style:disc}.wy-breadcrumbs{*zoom:1}.wy-breadcrumbs:after,.wy-breadcrumbs:before{display:table;content:""}.wy-breadcrumbs:after{clear:both}.wy-breadcrumbs>li{display:inline-block;padding-top:5px}.wy-breadcrumbs>li.wy-breadcrumbs-aside{float:right}.rst-content .wy-breadcrumbs>li code,.rst-content .wy-breadcrumbs>li tt,.wy-breadcrumbs>li .rst-content tt,.wy-breadcrumbs>li code{all:inherit;color:inherit}.breadcrumb-item:before{content:"/";color:#bbb;font-size:13px;padding:0 6px 0 3px}.wy-breadcrumbs-extra{margin-bottom:0;color:#b3b3b3;font-size:80%;display:inline-block}@media screen and (max-width:480px){.wy-breadcrumbs-extra,.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}@media print{.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}html{font-size:16px}.wy-affix{position:fixed;top:1.618em}.wy-menu a:hover{text-decoration:none}.wy-menu-horiz{*zoom:1}.wy-menu-horiz:after,.wy-menu-horiz:before{display:table;content:""}.wy-menu-horiz:after{clear:both}.wy-menu-horiz li,.wy-menu-horiz ul{display:inline-block}.wy-menu-horiz li:hover{background:hsla(0,0%,100%,.1)}.wy-menu-horiz li.divide-left{border-left:1px solid #404040}.wy-menu-horiz li.divide-right{border-right:1px solid #404040}.wy-menu-horiz a{height:32px;display:inline-block;line-height:32px;padding:0 16px}.wy-menu-vertical{width:300px}.wy-menu-vertical header,.wy-menu-vertical p.caption{color:#55a5d9;height:32px;line-height:32px;padding:0 1.618em;margin:12px 0 0;display:block;font-weight:700;text-transform:uppercase;font-size:85%;white-space:nowrap}.wy-menu-vertical ul{margin-bottom:0}.wy-menu-vertical li.divide-top{border-top:1px solid #404040}.wy-menu-vertical li.divide-bottom{border-bottom:1px solid #404040}.wy-menu-vertical li.current{background:#e3e3e3}.wy-menu-vertical li.current a{color:grey;border-right:1px solid #c9c9c9;padding:.4045em 2.427em}.wy-menu-vertical li.current a:hover{background:#d6d6d6}.rst-content .wy-menu-vertical li tt,.wy-menu-vertical li .rst-content tt,.wy-menu-vertical li code{border:none;background:inherit;color:inherit;padding-left:0;padding-right:0}.wy-menu-vertical li button.toctree-expand{display:block;float:left;margin-left:-1.2em;line-height:18px;color:#4d4d4d;border:none;background:none;padding:0}.wy-menu-vertical li.current>a,.wy-menu-vertical li.on a{color:#404040;font-weight:700;position:relative;background:#fcfcfc;border:none;padding:.4045em 1.618em}.wy-menu-vertical li.current>a:hover,.wy-menu-vertical li.on a:hover{background:#fcfcfc}.wy-menu-vertical li.current>a:hover button.toctree-expand,.wy-menu-vertical li.on a:hover button.toctree-expand{color:grey}.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand{display:block;line-height:18px;color:#333}.wy-menu-vertical li.toctree-l1.current>a{border-bottom:1px solid #c9c9c9;border-top:1px solid #c9c9c9}.wy-menu-vertical .toctree-l1.current .toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .toctree-l11>ul{display:none}.wy-menu-vertical .toctree-l1.current .current.toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .current.toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .current.toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .current.toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .current.toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .current.toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .current.toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .current.toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .current.toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .current.toctree-l11>ul{display:block}.wy-menu-vertical li.toctree-l3,.wy-menu-vertical li.toctree-l4{font-size:.9em}.wy-menu-vertical li.toctree-l2 a,.wy-menu-vertical li.toctree-l3 a,.wy-menu-vertical li.toctree-l4 a,.wy-menu-vertical li.toctree-l5 a,.wy-menu-vertical li.toctree-l6 a,.wy-menu-vertical li.toctree-l7 a,.wy-menu-vertical li.toctree-l8 a,.wy-menu-vertical li.toctree-l9 a,.wy-menu-vertical li.toctree-l10 a{color:#404040}.wy-menu-vertical li.toctree-l2 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l3 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l4 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l5 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l6 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l7 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l8 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l9 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l10 a:hover button.toctree-expand{color:grey}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a,.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a,.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a,.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a,.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a,.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a,.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a,.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{display:block}.wy-menu-vertical li.toctree-l2.current>a{padding:.4045em 2.427em}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{padding:.4045em 1.618em .4045em 4.045em}.wy-menu-vertical li.toctree-l3.current>a{padding:.4045em 4.045em}.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{padding:.4045em 1.618em .4045em 5.663em}.wy-menu-vertical li.toctree-l4.current>a{padding:.4045em 5.663em}.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a{padding:.4045em 1.618em .4045em 7.281em}.wy-menu-vertical li.toctree-l5.current>a{padding:.4045em 7.281em}.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a{padding:.4045em 1.618em .4045em 8.899em}.wy-menu-vertical li.toctree-l6.current>a{padding:.4045em 8.899em}.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a{padding:.4045em 1.618em .4045em 10.517em}.wy-menu-vertical li.toctree-l7.current>a{padding:.4045em 10.517em}.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a{padding:.4045em 1.618em .4045em 12.135em}.wy-menu-vertical li.toctree-l8.current>a{padding:.4045em 12.135em}.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a{padding:.4045em 1.618em .4045em 13.753em}.wy-menu-vertical li.toctree-l9.current>a{padding:.4045em 13.753em}.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a{padding:.4045em 1.618em .4045em 15.371em}.wy-menu-vertical li.toctree-l10.current>a{padding:.4045em 15.371em}.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{padding:.4045em 1.618em .4045em 16.989em}.wy-menu-vertical li.toctree-l2.current>a,.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{background:#c9c9c9}.wy-menu-vertical li.toctree-l2 button.toctree-expand{color:#a3a3a3}.wy-menu-vertical li.toctree-l3.current>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{background:#bdbdbd}.wy-menu-vertical li.toctree-l3 button.toctree-expand{color:#969696}.wy-menu-vertical li.current ul{display:block}.wy-menu-vertical li ul{margin-bottom:0;display:none}.wy-menu-vertical li ul li a{margin-bottom:0;color:#d9d9d9;font-weight:400}.wy-menu-vertical a{line-height:18px;padding:.4045em 1.618em;display:block;position:relative;font-size:90%;color:#d9d9d9}.wy-menu-vertical a:hover{background-color:#4e4a4a;cursor:pointer}.wy-menu-vertical a:hover button.toctree-expand{color:#d9d9d9}.wy-menu-vertical a:active{background-color:#2980b9;cursor:pointer;color:#fff}.wy-menu-vertical a:active button.toctree-expand{color:#fff}.wy-side-nav-search{display:block;width:300px;padding:.809em;margin-bottom:.809em;z-index:200;background-color:#2980b9;text-align:center;color:#fcfcfc}.wy-side-nav-search input[type=text]{width:100%;border-radius:50px;padding:6px 12px;border-color:#2472a4}.wy-side-nav-search img{display:block;margin:auto auto .809em;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-side-nav-search .wy-dropdown>a,.wy-side-nav-search>a{color:#fcfcfc;font-size:100%;font-weight:700;display:inline-block;padding:4px 6px;margin-bottom:.809em;max-width:100%}.wy-side-nav-search .wy-dropdown>a:hover,.wy-side-nav-search .wy-dropdown>aactive,.wy-side-nav-search .wy-dropdown>afocus,.wy-side-nav-search>a:hover,.wy-side-nav-search>aactive,.wy-side-nav-search>afocus{background:hsla(0,0%,100%,.1)}.wy-side-nav-search .wy-dropdown>a img.logo,.wy-side-nav-search>a img.logo{display:block;margin:0 auto;height:auto;width:auto;border-radius:0;max-width:100%;background:transparent}.wy-side-nav-search .wy-dropdown>a.icon,.wy-side-nav-search>a.icon{display:block}.wy-side-nav-search .wy-dropdown>a.icon img.logo,.wy-side-nav-search>a.icon img.logo{margin-top:.85em}.wy-side-nav-search>div.switch-menus{position:relative;display:block;margin-top:-.4045em;margin-bottom:.809em;font-weight:400;color:hsla(0,0%,100%,.3)}.wy-side-nav-search>div.switch-menus>div.language-switch,.wy-side-nav-search>div.switch-menus>div.version-switch{display:inline-block;padding:.2em}.wy-side-nav-search>div.switch-menus>div.language-switch select,.wy-side-nav-search>div.switch-menus>div.version-switch select{display:inline-block;margin-right:-2rem;padding-right:2rem;max-width:240px;text-align-last:center;background:none;border:none;border-radius:0;box-shadow:none;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;font-size:1em;font-weight:400;color:hsla(0,0%,100%,.3);cursor:pointer;appearance:none;-webkit-appearance:none;-moz-appearance:none}.wy-side-nav-search>div.switch-menus>div.language-switch select:active,.wy-side-nav-search>div.switch-menus>div.language-switch select:focus,.wy-side-nav-search>div.switch-menus>div.language-switch select:hover,.wy-side-nav-search>div.switch-menus>div.version-switch select:active,.wy-side-nav-search>div.switch-menus>div.version-switch select:focus,.wy-side-nav-search>div.switch-menus>div.version-switch select:hover{background:hsla(0,0%,100%,.1);color:hsla(0,0%,100%,.5)}.wy-side-nav-search>div.switch-menus>div.language-switch select option,.wy-side-nav-search>div.switch-menus>div.version-switch select option{color:#000}.wy-side-nav-search>div.switch-menus>div.language-switch:has(>select):after,.wy-side-nav-search>div.switch-menus>div.version-switch:has(>select):after{display:inline-block;width:1.5em;height:100%;padding:.1em;content:"\f0d7";font-size:1em;line-height:1.2em;font-family:FontAwesome;text-align:center;pointer-events:none;box-sizing:border-box}.wy-nav .wy-menu-vertical header{color:#2980b9}.wy-nav .wy-menu-vertical a{color:#b3b3b3}.wy-nav .wy-menu-vertical a:hover{background-color:#2980b9;color:#fff}[data-menu-wrap]{-webkit-transition:all .2s ease-in;-moz-transition:all .2s ease-in;transition:all .2s ease-in;position:absolute;opacity:1;width:100%;opacity:0}[data-menu-wrap].move-center{left:0;right:auto;opacity:1}[data-menu-wrap].move-left{right:auto;left:-100%;opacity:0}[data-menu-wrap].move-right{right:-100%;left:auto;opacity:0}.wy-body-for-nav{background:#fcfcfc}.wy-grid-for-nav{position:absolute;width:100%;height:100%}.wy-nav-side{position:fixed;top:0;bottom:0;left:0;padding-bottom:2em;width:300px;overflow-x:hidden;overflow-y:hidden;min-height:100%;color:#9b9b9b;background:#343131;z-index:200}.wy-side-scroll{width:320px;position:relative;overflow-x:hidden;overflow-y:scroll;height:100%}.wy-nav-top{display:none;background:#2980b9;color:#fff;padding:.4045em .809em;position:relative;line-height:50px;text-align:center;font-size:100%;*zoom:1}.wy-nav-top:after,.wy-nav-top:before{display:table;content:""}.wy-nav-top:after{clear:both}.wy-nav-top a{color:#fff;font-weight:700}.wy-nav-top img{margin-right:12px;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-nav-top i{font-size:30px;float:left;cursor:pointer;padding-top:inherit}.wy-nav-content-wrap{margin-left:300px;background:#fcfcfc;min-height:100%}.wy-nav-content{padding:1.618em 3.236em;height:100%;max-width:800px;margin:auto}.wy-body-mask{position:fixed;width:100%;height:100%;background:rgba(0,0,0,.2);display:none;z-index:499}.wy-body-mask.on{display:block}footer{color:grey}footer p{margin-bottom:12px}.rst-content footer span.commit tt,footer span.commit .rst-content tt,footer span.commit code{padding:0;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:1em;background:none;border:none;color:grey}.rst-footer-buttons{*zoom:1}.rst-footer-buttons:after,.rst-footer-buttons:before{width:100%;display:table;content:""}.rst-footer-buttons:after{clear:both}.rst-breadcrumbs-buttons{margin-top:12px;*zoom:1}.rst-breadcrumbs-buttons:after,.rst-breadcrumbs-buttons:before{display:table;content:""}.rst-breadcrumbs-buttons:after{clear:both}#search-results .search li{margin-bottom:24px;border-bottom:1px solid #e1e4e5;padding-bottom:24px}#search-results .search li:first-child{border-top:1px solid #e1e4e5;padding-top:24px}#search-results .search li a{font-size:120%;margin-bottom:12px;display:inline-block}#search-results .context{color:grey;font-size:90%}.genindextable li>ul{margin-left:24px}@media screen and (max-width:768px){.wy-body-for-nav{background:#fcfcfc}.wy-nav-top{display:block}.wy-nav-side{left:-300px}.wy-nav-side.shift{width:85%;left:0}.wy-menu.wy-menu-vertical,.wy-side-nav-search,.wy-side-scroll{width:auto}.wy-nav-content-wrap{margin-left:0}.wy-nav-content-wrap .wy-nav-content{padding:1.618em}.wy-nav-content-wrap.shift{position:fixed;min-width:100%;left:85%;top:0;height:100%;overflow:hidden}}@media screen and (min-width:1100px){.wy-nav-content-wrap{background:rgba(0,0,0,.05)}.wy-nav-content{margin:0;background:#fcfcfc}}@media print{.rst-versions,.wy-nav-side,footer{display:none}.wy-nav-content-wrap{margin-left:0}}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60;*zoom:1}.rst-versions .rst-current-version:after,.rst-versions .rst-current-version:before{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-content .code-block-caption .rst-versions .rst-current-version .headerlink,.rst-content .eqno .rst-versions .rst-current-version .headerlink,.rst-content .rst-versions .rst-current-version .admonition-title,.rst-content code.download .rst-versions .rst-current-version span:first-child,.rst-content dl dt .rst-versions .rst-current-version .headerlink,.rst-content h1 .rst-versions .rst-current-version .headerlink,.rst-content h2 .rst-versions .rst-current-version .headerlink,.rst-content h3 .rst-versions .rst-current-version .headerlink,.rst-content h4 .rst-versions .rst-current-version .headerlink,.rst-content h5 .rst-versions .rst-current-version .headerlink,.rst-content h6 .rst-versions .rst-current-version .headerlink,.rst-content p .rst-versions .rst-current-version .headerlink,.rst-content table>caption .rst-versions .rst-current-version .headerlink,.rst-content tt.download .rst-versions .rst-current-version span:first-child,.rst-versions .rst-current-version .fa,.rst-versions .rst-current-version .icon,.rst-versions .rst-current-version .rst-content .admonition-title,.rst-versions .rst-current-version .rst-content .code-block-caption .headerlink,.rst-versions .rst-current-version .rst-content .eqno .headerlink,.rst-versions .rst-current-version .rst-content code.download span:first-child,.rst-versions .rst-current-version .rst-content dl dt .headerlink,.rst-versions .rst-current-version .rst-content h1 .headerlink,.rst-versions .rst-current-version .rst-content h2 .headerlink,.rst-versions .rst-current-version .rst-content h3 .headerlink,.rst-versions .rst-current-version .rst-content h4 .headerlink,.rst-versions .rst-current-version .rst-content h5 .headerlink,.rst-versions .rst-current-version .rst-content h6 .headerlink,.rst-versions .rst-current-version .rst-content p .headerlink,.rst-versions .rst-current-version .rst-content table>caption .headerlink,.rst-versions .rst-current-version .rst-content tt.download span:first-child,.rst-versions .rst-current-version .wy-menu-vertical li button.toctree-expand,.wy-menu-vertical li .rst-versions .rst-current-version button.toctree-expand{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions .rst-other-versions .rtd-current-item{font-weight:700}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}#flyout-search-form{padding:6px}.rst-content .toctree-wrapper>p.caption,.rst-content h1,.rst-content h2,.rst-content h3,.rst-content h4,.rst-content h5,.rst-content h6{margin-bottom:24px}.rst-content img{max-width:100%;height:auto}.rst-content div.figure,.rst-content figure{margin-bottom:24px}.rst-content div.figure .caption-text,.rst-content figure .caption-text{font-style:italic}.rst-content div.figure p:last-child.caption,.rst-content figure p:last-child.caption{margin-bottom:0}.rst-content div.figure.align-center,.rst-content figure.align-center{text-align:center}.rst-content .section>a>img,.rst-content .section>img,.rst-content section>a>img,.rst-content section>img{margin-bottom:24px}.rst-content abbr[title]{text-decoration:none}.rst-content.style-external-links a.reference.external:after{font-family:FontAwesome;content:"\f08e";color:#b3b3b3;vertical-align:super;font-size:60%;margin:0 .2em}.rst-content blockquote{margin-left:24px;line-height:24px;margin-bottom:24px}.rst-content pre.literal-block{white-space:pre;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;display:block;overflow:auto}.rst-content div[class^=highlight],.rst-content pre.literal-block{border:1px solid #e1e4e5;overflow-x:auto;margin:1px 0 24px}.rst-content div[class^=highlight] div[class^=highlight],.rst-content pre.literal-block div[class^=highlight]{padding:0;border:none;margin:0}.rst-content div[class^=highlight] td.code{width:100%}.rst-content .linenodiv pre{border-right:1px solid #e6e9ea;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;user-select:none;pointer-events:none}.rst-content div[class^=highlight] pre{white-space:pre;margin:0;padding:12px;display:block;overflow:auto}.rst-content div[class^=highlight] pre .hll{display:block;margin:0 -12px;padding:0 12px}.rst-content .linenodiv pre,.rst-content div[class^=highlight] pre,.rst-content pre.literal-block{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:12px;line-height:1.4}.rst-content div.highlight .gp,.rst-content div.highlight span.linenos{user-select:none;pointer-events:none}.rst-content div.highlight span.linenos{display:inline-block;padding-left:0;padding-right:12px;margin-right:12px;border-right:1px solid #e6e9ea}.rst-content .code-block-caption{font-style:italic;font-size:85%;line-height:1;padding:1em 0;text-align:center}@media print{.rst-content .codeblock,.rst-content div[class^=highlight],.rst-content div[class^=highlight] pre{white-space:pre-wrap}}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning{clear:both}.rst-content .admonition-todo .last,.rst-content .admonition-todo>:last-child,.rst-content .admonition .last,.rst-content .admonition>:last-child,.rst-content .attention .last,.rst-content .attention>:last-child,.rst-content .caution .last,.rst-content .caution>:last-child,.rst-content .danger .last,.rst-content .danger>:last-child,.rst-content .error .last,.rst-content .error>:last-child,.rst-content .hint .last,.rst-content .hint>:last-child,.rst-content .important .last,.rst-content .important>:last-child,.rst-content .note .last,.rst-content .note>:last-child,.rst-content .seealso .last,.rst-content .seealso>:last-child,.rst-content .tip .last,.rst-content .tip>:last-child,.rst-content .warning .last,.rst-content .warning>:last-child{margin-bottom:0}.rst-content .admonition-title:before{margin-right:4px}.rst-content .admonition table{border-color:rgba(0,0,0,.1)}.rst-content .admonition table td,.rst-content .admonition table th{background:transparent!important;border-color:rgba(0,0,0,.1)!important}.rst-content .section ol.loweralpha,.rst-content .section ol.loweralpha>li,.rst-content .toctree-wrapper ol.loweralpha,.rst-content .toctree-wrapper ol.loweralpha>li,.rst-content section ol.loweralpha,.rst-content section ol.loweralpha>li{list-style:lower-alpha}.rst-content .section ol.upperalpha,.rst-content .section ol.upperalpha>li,.rst-content .toctree-wrapper ol.upperalpha,.rst-content .toctree-wrapper ol.upperalpha>li,.rst-content section ol.upperalpha,.rst-content section ol.upperalpha>li{list-style:upper-alpha}.rst-content .section ol li>*,.rst-content .section ul li>*,.rst-content .toctree-wrapper ol li>*,.rst-content .toctree-wrapper ul li>*,.rst-content section ol li>*,.rst-content section ul li>*{margin-top:12px;margin-bottom:12px}.rst-content .section ol li>:first-child,.rst-content .section ul li>:first-child,.rst-content .toctree-wrapper ol li>:first-child,.rst-content .toctree-wrapper ul li>:first-child,.rst-content section ol li>:first-child,.rst-content section ul li>:first-child{margin-top:0}.rst-content .section ol li>p,.rst-content .section ol li>p:last-child,.rst-content .section ul li>p,.rst-content .section ul li>p:last-child,.rst-content .toctree-wrapper ol li>p,.rst-content .toctree-wrapper ol li>p:last-child,.rst-content .toctree-wrapper ul li>p,.rst-content .toctree-wrapper ul li>p:last-child,.rst-content section ol li>p,.rst-content section ol li>p:last-child,.rst-content section ul li>p,.rst-content section ul li>p:last-child{margin-bottom:12px}.rst-content .section ol li>p:only-child,.rst-content .section ol li>p:only-child:last-child,.rst-content .section ul li>p:only-child,.rst-content .section ul li>p:only-child:last-child,.rst-content .toctree-wrapper ol li>p:only-child,.rst-content .toctree-wrapper ol li>p:only-child:last-child,.rst-content .toctree-wrapper ul li>p:only-child,.rst-content .toctree-wrapper ul li>p:only-child:last-child,.rst-content section ol li>p:only-child,.rst-content section ol li>p:only-child:last-child,.rst-content section ul li>p:only-child,.rst-content section ul li>p:only-child:last-child{margin-bottom:0}.rst-content .section ol li>ol,.rst-content .section ol li>ul,.rst-content .section ul li>ol,.rst-content .section ul li>ul,.rst-content .toctree-wrapper ol li>ol,.rst-content .toctree-wrapper ol li>ul,.rst-content .toctree-wrapper ul li>ol,.rst-content .toctree-wrapper ul li>ul,.rst-content section ol li>ol,.rst-content section ol li>ul,.rst-content section ul li>ol,.rst-content section ul li>ul{margin-bottom:12px}.rst-content .section ol.simple li>*,.rst-content .section ol.simple li ol,.rst-content .section ol.simple li ul,.rst-content .section ul.simple li>*,.rst-content .section ul.simple li ol,.rst-content .section ul.simple li ul,.rst-content .toctree-wrapper ol.simple li>*,.rst-content .toctree-wrapper ol.simple li ol,.rst-content .toctree-wrapper ol.simple li ul,.rst-content .toctree-wrapper ul.simple li>*,.rst-content .toctree-wrapper ul.simple li ol,.rst-content .toctree-wrapper ul.simple li ul,.rst-content section ol.simple li>*,.rst-content section ol.simple li ol,.rst-content section ol.simple li ul,.rst-content section ul.simple li>*,.rst-content section ul.simple li ol,.rst-content section ul.simple li ul{margin-top:0;margin-bottom:0}.rst-content .line-block{margin-left:0;margin-bottom:24px;line-height:24px}.rst-content .line-block .line-block{margin-left:24px;margin-bottom:0}.rst-content .topic-title{font-weight:700;margin-bottom:12px}.rst-content .toc-backref{color:#404040}.rst-content .align-right{float:right;margin:0 0 24px 24px}.rst-content .align-left{float:left;margin:0 24px 24px 0}.rst-content .align-center{margin:auto}.rst-content .align-center:not(table){display:block}.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink{opacity:0;font-size:14px;font-family:FontAwesome;margin-left:.5em}.rst-content .code-block-caption .headerlink:focus,.rst-content .code-block-caption:hover .headerlink,.rst-content .eqno .headerlink:focus,.rst-content .eqno:hover .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink:focus,.rst-content .toctree-wrapper>p.caption:hover .headerlink,.rst-content dl dt .headerlink:focus,.rst-content dl dt:hover .headerlink,.rst-content h1 .headerlink:focus,.rst-content h1:hover .headerlink,.rst-content h2 .headerlink:focus,.rst-content h2:hover .headerlink,.rst-content h3 .headerlink:focus,.rst-content h3:hover .headerlink,.rst-content h4 .headerlink:focus,.rst-content h4:hover .headerlink,.rst-content h5 .headerlink:focus,.rst-content h5:hover .headerlink,.rst-content h6 .headerlink:focus,.rst-content h6:hover .headerlink,.rst-content p.caption .headerlink:focus,.rst-content p.caption:hover .headerlink,.rst-content p .headerlink:focus,.rst-content p:hover .headerlink,.rst-content table>caption .headerlink:focus,.rst-content table>caption:hover .headerlink{opacity:1}.rst-content p a{overflow-wrap:anywhere}.rst-content .wy-table td p,.rst-content .wy-table td ul,.rst-content .wy-table th p,.rst-content .wy-table th ul,.rst-content table.docutils td p,.rst-content table.docutils td ul,.rst-content table.docutils th p,.rst-content table.docutils th ul,.rst-content table.field-list td p,.rst-content table.field-list td ul,.rst-content table.field-list th p,.rst-content table.field-list th ul{font-size:inherit}.rst-content .btn:focus{outline:2px solid}.rst-content table>caption .headerlink:after{font-size:12px}.rst-content .centered{text-align:center}.rst-content .sidebar{float:right;width:40%;display:block;margin:0 0 24px 24px;padding:24px;background:#f3f6f6;border:1px solid #e1e4e5}.rst-content .sidebar dl,.rst-content .sidebar p,.rst-content .sidebar ul{font-size:90%}.rst-content .sidebar .last,.rst-content .sidebar>:last-child{margin-bottom:0}.rst-content .sidebar .sidebar-title{display:block;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif;font-weight:700;background:#e1e4e5;padding:6px 12px;margin:-24px -24px 24px;font-size:100%}.rst-content .highlighted{background:#f1c40f;box-shadow:0 0 0 2px #f1c40f;display:inline;font-weight:700}.rst-content .citation-reference,.rst-content .footnote-reference{vertical-align:baseline;position:relative;top:-.4em;line-height:0;font-size:90%}.rst-content .citation-reference>span.fn-bracket,.rst-content .footnote-reference>span.fn-bracket{display:none}.rst-content .hlist{width:100%}.rst-content dl dt span.classifier:before{content:" : "}.rst-content dl dt span.classifier-delimiter{display:none!important}html.writer-html4 .rst-content table.docutils.citation,html.writer-html4 .rst-content table.docutils.footnote{background:none;border:none}html.writer-html4 .rst-content table.docutils.citation td,html.writer-html4 .rst-content table.docutils.citation tr,html.writer-html4 .rst-content table.docutils.footnote td,html.writer-html4 .rst-content table.docutils.footnote tr{border:none;background-color:transparent!important;white-space:normal}html.writer-html4 .rst-content table.docutils.citation td.label,html.writer-html4 .rst-content table.docutils.footnote td.label{padding-left:0;padding-right:0;vertical-align:top}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.field-list,html.writer-html5 .rst-content dl.footnote{display:grid;grid-template-columns:auto minmax(80%,95%)}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dt{display:inline-grid;grid-template-columns:max-content auto}html.writer-html5 .rst-content aside.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content div.citation{display:grid;grid-template-columns:auto auto minmax(.65rem,auto) minmax(40%,95%)}html.writer-html5 .rst-content aside.citation>span.label,html.writer-html5 .rst-content aside.footnote>span.label,html.writer-html5 .rst-content div.citation>span.label{grid-column-start:1;grid-column-end:2}html.writer-html5 .rst-content aside.citation>span.backrefs,html.writer-html5 .rst-content aside.footnote>span.backrefs,html.writer-html5 .rst-content div.citation>span.backrefs{grid-column-start:2;grid-column-end:3;grid-row-start:1;grid-row-end:3}html.writer-html5 .rst-content aside.citation>p,html.writer-html5 .rst-content aside.footnote>p,html.writer-html5 .rst-content div.citation>p{grid-column-start:4;grid-column-end:5}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.field-list,html.writer-html5 .rst-content dl.footnote{margin-bottom:24px}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dt{padding-left:1rem}html.writer-html5 .rst-content dl.citation>dd,html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dd,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dd,html.writer-html5 .rst-content dl.footnote>dt{margin-bottom:0}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.footnote{font-size:.9rem}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.footnote>dt{margin:0 .5rem .5rem 0;line-height:1.2rem;word-break:break-all;font-weight:400}html.writer-html5 .rst-content dl.citation>dt>span.brackets:before,html.writer-html5 .rst-content dl.footnote>dt>span.brackets:before{content:"["}html.writer-html5 .rst-content dl.citation>dt>span.brackets:after,html.writer-html5 .rst-content dl.footnote>dt>span.brackets:after{content:"]"}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref{text-align:left;font-style:italic;margin-left:.65rem;word-break:break-word;word-spacing:-.1rem;max-width:5rem}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref>a,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref>a{word-break:keep-all}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref>a:not(:first-child):before,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref>a:not(:first-child):before{content:" "}html.writer-html5 .rst-content dl.citation>dd,html.writer-html5 .rst-content dl.footnote>dd{margin:0 0 .5rem;line-height:1.2rem}html.writer-html5 .rst-content dl.citation>dd p,html.writer-html5 .rst-content dl.footnote>dd p{font-size:.9rem}html.writer-html5 .rst-content aside.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content div.citation{padding-left:1rem;padding-right:1rem;font-size:.9rem;line-height:1.2rem}html.writer-html5 .rst-content aside.citation p,html.writer-html5 .rst-content aside.footnote p,html.writer-html5 .rst-content div.citation p{font-size:.9rem;line-height:1.2rem;margin-bottom:12px}html.writer-html5 .rst-content aside.citation span.backrefs,html.writer-html5 .rst-content aside.footnote span.backrefs,html.writer-html5 .rst-content div.citation span.backrefs{text-align:left;font-style:italic;margin-left:.65rem;word-break:break-word;word-spacing:-.1rem;max-width:5rem}html.writer-html5 .rst-content aside.citation span.backrefs>a,html.writer-html5 .rst-content aside.footnote span.backrefs>a,html.writer-html5 .rst-content div.citation span.backrefs>a{word-break:keep-all}html.writer-html5 .rst-content aside.citation span.backrefs>a:not(:first-child):before,html.writer-html5 .rst-content aside.footnote span.backrefs>a:not(:first-child):before,html.writer-html5 .rst-content div.citation span.backrefs>a:not(:first-child):before{content:" "}html.writer-html5 .rst-content aside.citation span.label,html.writer-html5 .rst-content aside.footnote span.label,html.writer-html5 .rst-content div.citation span.label{line-height:1.2rem}html.writer-html5 .rst-content aside.citation-list,html.writer-html5 .rst-content aside.footnote-list,html.writer-html5 .rst-content div.citation-list{margin-bottom:24px}html.writer-html5 .rst-content dl.option-list kbd{font-size:.9rem}.rst-content table.docutils.footnote,html.writer-html4 .rst-content table.docutils.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content aside.footnote-list aside.footnote,html.writer-html5 .rst-content div.citation-list>div.citation,html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.footnote{color:grey}.rst-content table.docutils.footnote code,.rst-content table.docutils.footnote tt,html.writer-html4 .rst-content table.docutils.citation code,html.writer-html4 .rst-content table.docutils.citation tt,html.writer-html5 .rst-content aside.footnote-list aside.footnote code,html.writer-html5 .rst-content aside.footnote-list aside.footnote tt,html.writer-html5 .rst-content aside.footnote code,html.writer-html5 .rst-content aside.footnote tt,html.writer-html5 .rst-content div.citation-list>div.citation code,html.writer-html5 .rst-content div.citation-list>div.citation tt,html.writer-html5 .rst-content dl.citation code,html.writer-html5 .rst-content dl.citation tt,html.writer-html5 .rst-content dl.footnote code,html.writer-html5 .rst-content dl.footnote tt{color:#555}.rst-content .wy-table-responsive.citation,.rst-content .wy-table-responsive.footnote{margin-bottom:0}.rst-content .wy-table-responsive.citation+:not(.citation),.rst-content .wy-table-responsive.footnote+:not(.footnote){margin-top:24px}.rst-content .wy-table-responsive.citation:last-child,.rst-content .wy-table-responsive.footnote:last-child{margin-bottom:24px}.rst-content table.docutils th{border-color:#e1e4e5}html.writer-html5 .rst-content table.docutils th{border:1px solid #e1e4e5}html.writer-html5 .rst-content table.docutils td>p,html.writer-html5 .rst-content table.docutils th>p{line-height:1rem;margin-bottom:0;font-size:.9rem}.rst-content table.docutils td .last,.rst-content table.docutils td .last>:last-child{margin-bottom:0}.rst-content table.field-list,.rst-content table.field-list td{border:none}.rst-content table.field-list td p{line-height:inherit}.rst-content table.field-list td>strong{display:inline-block}.rst-content table.field-list .field-name{padding-right:10px;text-align:left;white-space:nowrap}.rst-content table.field-list .field-body{text-align:left}.rst-content code,.rst-content tt{color:#000;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;padding:2px 5px}.rst-content code big,.rst-content code em,.rst-content tt big,.rst-content tt em{font-size:100%!important;line-height:normal}.rst-content code.literal,.rst-content tt.literal{color:#e74c3c;white-space:normal}.rst-content code.xref,.rst-content tt.xref,a .rst-content code,a .rst-content tt{font-weight:700;color:#404040;overflow-wrap:normal}.rst-content kbd,.rst-content pre,.rst-content samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace}.rst-content a code,.rst-content a tt{color:#2980b9}.rst-content dl{margin-bottom:24px}.rst-content dl dt{font-weight:700;margin-bottom:12px}.rst-content dl ol,.rst-content dl p,.rst-content dl table,.rst-content dl ul{margin-bottom:12px}.rst-content dl dd{margin:0 0 12px 24px;line-height:24px}.rst-content dl dd>ol:last-child,.rst-content dl dd>p:last-child,.rst-content dl dd>table:last-child,.rst-content dl dd>ul:last-child{margin-bottom:0}html.writer-html4 .rst-content dl:not(.docutils),html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple){margin-bottom:24px}html.writer-html4 .rst-content dl:not(.docutils)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt{display:table;margin:6px 0;font-size:90%;line-height:normal;background:#e7f2fa;color:#2980b9;border-top:3px solid #6ab0de;padding:6px;position:relative}html.writer-html4 .rst-content dl:not(.docutils)>dt:before,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt:before{color:#6ab0de}html.writer-html4 .rst-content dl:not(.docutils)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt{margin-bottom:6px;border:none;border-left:3px solid #ccc;background:#f0f0f0;color:#555}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils)>dt:first-child,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt:first-child{margin-top:0}html.writer-html4 .rst-content dl:not(.docutils) code.descclassname,html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descclassname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descname{background-color:transparent;border:none;padding:0;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descname{font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .optional,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .optional{display:inline-block;padding:0 4px;color:#000;font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .property,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .property{display:inline-block;padding-right:8px;max-width:100%}html.writer-html4 .rst-content dl:not(.docutils) .k,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .k{font-style:italic}html.writer-html4 .rst-content dl:not(.docutils) .descclassname,html.writer-html4 .rst-content dl:not(.docutils) .descname,html.writer-html4 .rst-content dl:not(.docutils) .sig-name,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .sig-name{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#000}.rst-content .viewcode-back,.rst-content .viewcode-link{display:inline-block;color:#27ae60;font-size:80%;padding-left:24px}.rst-content .viewcode-back{display:block;float:right}.rst-content p.rubric{margin-bottom:12px;font-weight:700}.rst-content code.download,.rst-content tt.download{background:inherit;padding:inherit;font-weight:400;font-family:inherit;font-size:inherit;color:inherit;border:inherit;white-space:inherit}.rst-content code.download span:first-child,.rst-content tt.download span:first-child{-webkit-font-smoothing:subpixel-antialiased}.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{margin-right:4px}.rst-content .guilabel,.rst-content .menuselection{font-size:80%;font-weight:700;border-radius:4px;padding:2.4px 6px;margin:auto 2px}.rst-content .guilabel,.rst-content .menuselection{border:1px solid #7fbbe3;background:#e7f2fa}.rst-content :not(dl.option-list)>:not(dt):not(kbd):not(.kbd)>.kbd,.rst-content :not(dl.option-list)>:not(dt):not(kbd):not(.kbd)>kbd{color:inherit;font-size:80%;background-color:#fff;border:1px solid #a6a6a6;border-radius:4px;box-shadow:0 2px grey;padding:2.4px 6px;margin:auto 0}.rst-content .versionmodified{font-style:italic}@media screen and (max-width:480px){.rst-content .sidebar{width:100%}}span[id*=MathJax-Span]{color:#404040}.math{text-align:center}@font-face{font-family:Lato;src:url(fonts/lato-normal.woff2?bd03a2cc277bbbc338d464e679fe9942) format("woff2"),url(fonts/lato-normal.woff?27bd77b9162d388cb8d4c4217c7c5e2a) format("woff");font-weight:400;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold.woff2?cccb897485813c7c256901dbca54ecf2) format("woff2"),url(fonts/lato-bold.woff?d878b6c29b10beca227e9eef4246111b) format("woff");font-weight:700;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold-italic.woff2?0b6bb6725576b072c5d0b02ecdd1900d) format("woff2"),url(fonts/lato-bold-italic.woff?9c7e4e9eb485b4a121c760e61bc3707c) format("woff");font-weight:700;font-style:italic;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-normal-italic.woff2?4eb103b4d12be57cb1d040ed5e162e9d) format("woff2"),url(fonts/lato-normal-italic.woff?f28f2d6482446544ef1ea1ccc6dd5892) format("woff");font-weight:400;font-style:italic;font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:400;src:url(fonts/Roboto-Slab-Regular.woff2?7abf5b8d04d26a2cafea937019bca958) format("woff2"),url(fonts/Roboto-Slab-Regular.woff?c1be9284088d487c5e3ff0a10a92e58c) format("woff");font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:700;src:url(fonts/Roboto-Slab-Bold.woff2?9984f4a9bda09be08e83f2506954adbe) format("woff2"),url(fonts/Roboto-Slab-Bold.woff?bed5564a116b05148e3b3bea6fb1162a) format("woff");font-display:block} \ No newline at end of file diff --git a/_static/doctools.js b/_static/doctools.js new file mode 100644 index 00000000..0398ebb9 --- /dev/null +++ b/_static/doctools.js @@ -0,0 +1,149 @@ +/* + * Base JavaScript utilities for all Sphinx HTML documentation. + */ +"use strict"; + +const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ + "TEXTAREA", + "INPUT", + "SELECT", + "BUTTON", +]); + +const _ready = (callback) => { + if (document.readyState !== "loading") { + callback(); + } else { + document.addEventListener("DOMContentLoaded", callback); + } +}; + +/** + * Small JavaScript module for the documentation. + */ +const Documentation = { + init: () => { + Documentation.initDomainIndexTable(); + Documentation.initOnKeyListeners(); + }, + + /** + * i18n support + */ + TRANSLATIONS: {}, + PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), + LOCALE: "unknown", + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext: (string) => { + const translated = Documentation.TRANSLATIONS[string]; + switch (typeof translated) { + case "undefined": + return string; // no translation + case "string": + return translated; // translation exists + default: + return translated[0]; // (singular, plural) translation tuple exists + } + }, + + ngettext: (singular, plural, n) => { + const translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated !== "undefined") + return translated[Documentation.PLURAL_EXPR(n)]; + return n === 1 ? singular : plural; + }, + + addTranslations: (catalog) => { + Object.assign(Documentation.TRANSLATIONS, catalog.messages); + Documentation.PLURAL_EXPR = new Function( + "n", + `return (${catalog.plural_expr})` + ); + Documentation.LOCALE = catalog.locale; + }, + + /** + * helper function to focus on search bar + */ + focusSearchBar: () => { + document.querySelectorAll("input[name=q]")[0]?.focus(); + }, + + /** + * Initialise the domain index toggle buttons + */ + initDomainIndexTable: () => { + const toggler = (el) => { + const idNumber = el.id.substr(7); + const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); + if (el.src.substr(-9) === "minus.png") { + el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; + toggledRows.forEach((el) => (el.style.display = "none")); + } else { + el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; + toggledRows.forEach((el) => (el.style.display = "")); + } + }; + + const togglerElements = document.querySelectorAll("img.toggler"); + togglerElements.forEach((el) => + el.addEventListener("click", (event) => toggler(event.currentTarget)) + ); + togglerElements.forEach((el) => (el.style.display = "")); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); + }, + + initOnKeyListeners: () => { + // only install a listener if it is really needed + if ( + !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && + !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS + ) + return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.altKey || event.ctrlKey || event.metaKey) return; + + if (!event.shiftKey) { + switch (event.key) { + case "ArrowLeft": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const prevLink = document.querySelector('link[rel="prev"]'); + if (prevLink && prevLink.href) { + window.location.href = prevLink.href; + event.preventDefault(); + } + break; + case "ArrowRight": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const nextLink = document.querySelector('link[rel="next"]'); + if (nextLink && nextLink.href) { + window.location.href = nextLink.href; + event.preventDefault(); + } + break; + } + } + + // some keyboard layouts may need Shift to get / + switch (event.key) { + case "/": + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; + Documentation.focusSearchBar(); + event.preventDefault(); + } + }); + }, +}; + +// quick alias for translations +const _ = Documentation.gettext; + +_ready(Documentation.init); diff --git a/_static/documentation_options.js b/_static/documentation_options.js new file mode 100644 index 00000000..6b434114 --- /dev/null +++ b/_static/documentation_options.js @@ -0,0 +1,13 @@ +const DOCUMENTATION_OPTIONS = { + VERSION: '3.1.0', + LANGUAGE: 'en', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: true, + SHOW_SEARCH_SUMMARY: true, + ENABLE_SEARCH_SHORTCUTS: true, +}; \ No newline at end of file diff --git a/_static/file.png b/_static/file.png new file mode 100644 index 00000000..a858a410 Binary files /dev/null and b/_static/file.png differ diff --git a/_static/fonts/Lato/lato-bold.eot b/_static/fonts/Lato/lato-bold.eot new file mode 100644 index 00000000..3361183a Binary files /dev/null and b/_static/fonts/Lato/lato-bold.eot differ diff --git a/_static/fonts/Lato/lato-bold.ttf b/_static/fonts/Lato/lato-bold.ttf new file mode 100644 index 00000000..29f691d5 Binary files /dev/null and b/_static/fonts/Lato/lato-bold.ttf differ diff --git a/_static/fonts/Lato/lato-bold.woff b/_static/fonts/Lato/lato-bold.woff new file mode 100644 index 00000000..c6dff51f Binary files /dev/null and b/_static/fonts/Lato/lato-bold.woff differ diff --git a/_static/fonts/Lato/lato-bold.woff2 b/_static/fonts/Lato/lato-bold.woff2 new file mode 100644 index 00000000..bb195043 Binary files /dev/null and b/_static/fonts/Lato/lato-bold.woff2 differ diff --git a/_static/fonts/Lato/lato-bolditalic.eot b/_static/fonts/Lato/lato-bolditalic.eot new file mode 100644 index 00000000..3d415493 Binary files /dev/null and b/_static/fonts/Lato/lato-bolditalic.eot differ diff --git a/_static/fonts/Lato/lato-bolditalic.ttf b/_static/fonts/Lato/lato-bolditalic.ttf new file mode 100644 index 00000000..f402040b Binary files /dev/null and b/_static/fonts/Lato/lato-bolditalic.ttf differ diff --git a/_static/fonts/Lato/lato-bolditalic.woff b/_static/fonts/Lato/lato-bolditalic.woff new file mode 100644 index 00000000..88ad05b9 Binary files /dev/null and b/_static/fonts/Lato/lato-bolditalic.woff differ diff --git a/_static/fonts/Lato/lato-bolditalic.woff2 b/_static/fonts/Lato/lato-bolditalic.woff2 new file mode 100644 index 00000000..c4e3d804 Binary files /dev/null and b/_static/fonts/Lato/lato-bolditalic.woff2 differ diff --git a/_static/fonts/Lato/lato-italic.eot b/_static/fonts/Lato/lato-italic.eot new file mode 100644 index 00000000..3f826421 Binary files /dev/null and b/_static/fonts/Lato/lato-italic.eot differ diff --git a/_static/fonts/Lato/lato-italic.ttf b/_static/fonts/Lato/lato-italic.ttf new file mode 100644 index 00000000..b4bfc9b2 Binary files /dev/null and b/_static/fonts/Lato/lato-italic.ttf differ diff --git a/_static/fonts/Lato/lato-italic.woff b/_static/fonts/Lato/lato-italic.woff new file mode 100644 index 00000000..76114bc0 Binary files /dev/null and b/_static/fonts/Lato/lato-italic.woff differ diff --git a/_static/fonts/Lato/lato-italic.woff2 b/_static/fonts/Lato/lato-italic.woff2 new file mode 100644 index 00000000..3404f37e Binary files /dev/null and b/_static/fonts/Lato/lato-italic.woff2 differ diff --git a/_static/fonts/Lato/lato-regular.eot b/_static/fonts/Lato/lato-regular.eot new file mode 100644 index 00000000..11e3f2a5 Binary files /dev/null and b/_static/fonts/Lato/lato-regular.eot differ diff --git a/_static/fonts/Lato/lato-regular.ttf b/_static/fonts/Lato/lato-regular.ttf new file mode 100644 index 00000000..74decd9e Binary files /dev/null and b/_static/fonts/Lato/lato-regular.ttf differ diff --git a/_static/fonts/Lato/lato-regular.woff b/_static/fonts/Lato/lato-regular.woff new file mode 100644 index 00000000..ae1307ff Binary files /dev/null and b/_static/fonts/Lato/lato-regular.woff differ diff --git a/_static/fonts/Lato/lato-regular.woff2 b/_static/fonts/Lato/lato-regular.woff2 new file mode 100644 index 00000000..3bf98433 Binary files /dev/null and b/_static/fonts/Lato/lato-regular.woff2 differ diff --git a/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot b/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot new file mode 100644 index 00000000..79dc8efe Binary files /dev/null and b/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot differ diff --git a/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf b/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf new file mode 100644 index 00000000..df5d1df2 Binary files /dev/null and b/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf differ diff --git a/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff b/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff new file mode 100644 index 00000000..6cb60000 Binary files /dev/null and b/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff differ diff --git a/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 b/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 new file mode 100644 index 00000000..7059e231 Binary files /dev/null and b/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 differ diff --git a/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot b/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot new file mode 100644 index 00000000..2f7ca78a Binary files /dev/null and b/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot differ diff --git a/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf b/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf new file mode 100644 index 00000000..eb52a790 Binary files /dev/null and b/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf differ diff --git a/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff b/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff new file mode 100644 index 00000000..f815f63f Binary files /dev/null and b/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff differ diff --git a/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 b/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 new file mode 100644 index 00000000..f2c76e5b Binary files /dev/null and b/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 differ diff --git a/_static/jquery.js b/_static/jquery.js new file mode 100644 index 00000000..c4c6022f --- /dev/null +++ b/_static/jquery.js @@ -0,0 +1,2 @@ +/*! jQuery v3.6.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.0",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var _t,zt=[],Ut=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=zt.pop()||S.expando+"_"+wt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Ut.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ut.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Ut,"$1"+r):!1!==e.jsonp&&(e.url+=(Tt.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,zt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((_t=E.implementation.createHTMLDocument("").body).innerHTML="
",2===_t.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=Fe(y.pixelPosition,function(e,t){if(t)return t=We(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0"),n("table.docutils.footnote").wrap("
"),n("table.docutils.citation").wrap("
"),n(".wy-menu-vertical ul").not(".simple").siblings("a").each((function(){var t=n(this);expand=n(''),expand.on("click",(function(n){return e.toggleCurrent(t),n.stopPropagation(),!1})),t.prepend(expand)}))},reset:function(){var n=encodeURI(window.location.hash)||"#";try{var e=$(".wy-menu-vertical"),t=e.find('[href="'+n+'"]');if(0===t.length){var i=$('.document [id="'+n.substring(1)+'"]').closest("div.section");0===(t=e.find('[href="#'+i.attr("id")+'"]')).length&&(t=e.find('[href="#"]'))}if(t.length>0){$(".wy-menu-vertical .current").removeClass("current").attr("aria-expanded","false"),t.addClass("current").attr("aria-expanded","true"),t.closest("li.toctree-l1").parent().addClass("current").attr("aria-expanded","true");for(let n=1;n<=10;n++)t.closest("li.toctree-l"+n).addClass("current").attr("aria-expanded","true");t[0].scrollIntoView()}}catch(n){console.log("Error expanding nav for anchor",n)}},onScroll:function(){this.winScroll=!1;var n=this.win.scrollTop(),e=n+this.winHeight,t=this.navBar.scrollTop()+(n-this.winPosition);n<0||e>this.docHeight||(this.navBar.scrollTop(t),this.winPosition=n)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",(function(){this.linkScroll=!1}))},toggleCurrent:function(n){var e=n.closest("li");e.siblings("li.current").removeClass("current").attr("aria-expanded","false"),e.siblings().find("li.current").removeClass("current").attr("aria-expanded","false");var t=e.find("> ul li");t.length&&(t.removeClass("current").attr("aria-expanded","false"),e.toggleClass("current").attr("aria-expanded",(function(n,e){return"true"==e?"false":"true"})))}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:n.exports.ThemeNav,StickyNav:n.exports.ThemeNav}),function(){for(var n=0,e=["ms","moz","webkit","o"],t=0;t +
Languages
+ ${config.projects.translations + .map( + (translation) => ` +
+ ${translation.language.code} +
+ `, + ) + .join("\n")} + + `; + return languagesHTML; + } + + function renderVersions(config) { + if (!config.versions.active.length) { + return ""; + } + const versionsHTML = ` +
+
Versions
+ ${config.versions.active + .map( + (version) => ` +
+ ${version.slug} +
+ `, + ) + .join("\n")} +
+ `; + return versionsHTML; + } + + function renderDownloads(config) { + if (!Object.keys(config.versions.current.downloads).length) { + return ""; + } + const downloadsNameDisplay = { + pdf: "PDF", + epub: "Epub", + htmlzip: "HTML", + }; + + const downloadsHTML = ` +
+
Downloads
+ ${Object.entries(config.versions.current.downloads) + .map( + ([name, url]) => ` +
+ ${downloadsNameDisplay[name]} +
+ `, + ) + .join("\n")} +
+ `; + return downloadsHTML; + } + + document.addEventListener("readthedocs-addons-data-ready", function (event) { + const config = event.detail.data(); + + const flyout = ` +
+ + Read the Docs + v: ${config.versions.current.slug} + + +
+
+ ${renderLanguages(config)} + ${renderVersions(config)} + ${renderDownloads(config)} +
+
On Read the Docs
+
+ Project Home +
+
+ Builds +
+
+ Downloads +
+
+
+
Search
+
+
+ +
+
+
+
+ + Hosted by Read the Docs + +
+
+ `; + + // Inject the generated flyout into the body HTML element. + document.body.insertAdjacentHTML("beforeend", flyout); + + // Trigger the Read the Docs Addons Search modal when clicking on the "Search docs" input from inside the flyout. + document + .querySelector("#flyout-search-form") + .addEventListener("focusin", () => { + const event = new CustomEvent("readthedocs-search-show"); + document.dispatchEvent(event); + }); + }) +} + +if (themeLanguageSelector || themeVersionSelector) { + function onSelectorSwitch(event) { + const option = event.target.selectedIndex; + const item = event.target.options[option]; + window.location.href = item.dataset.url; + } + + document.addEventListener("readthedocs-addons-data-ready", function (event) { + const config = event.detail.data(); + + const versionSwitch = document.querySelector( + "div.switch-menus > div.version-switch", + ); + if (themeVersionSelector) { + let versions = config.versions.active; + if (config.versions.current.hidden || config.versions.current.type === "external") { + versions.unshift(config.versions.current); + } + const versionSelect = ` + + `; + + versionSwitch.innerHTML = versionSelect; + versionSwitch.firstElementChild.addEventListener("change", onSelectorSwitch); + } + + const languageSwitch = document.querySelector( + "div.switch-menus > div.language-switch", + ); + + if (themeLanguageSelector) { + if (config.projects.translations.length) { + // Add the current language to the options on the selector + let languages = config.projects.translations.concat( + config.projects.current, + ); + languages = languages.sort((a, b) => + a.language.name.localeCompare(b.language.name), + ); + + const languageSelect = ` + + `; + + languageSwitch.innerHTML = languageSelect; + languageSwitch.firstElementChild.addEventListener("change", onSelectorSwitch); + } + else { + languageSwitch.remove(); + } + } + }); +} + +document.addEventListener("readthedocs-addons-data-ready", function (event) { + // Trigger the Read the Docs Addons Search modal when clicking on "Search docs" input from the topnav. + document + .querySelector("[role='search'] input") + .addEventListener("focusin", () => { + const event = new CustomEvent("readthedocs-search-show"); + document.dispatchEvent(event); + }); +}); \ No newline at end of file diff --git a/_static/language_data.js b/_static/language_data.js new file mode 100644 index 00000000..c7fe6c6f --- /dev/null +++ b/_static/language_data.js @@ -0,0 +1,192 @@ +/* + * This script contains the language-specific data used by searchtools.js, + * namely the list of stopwords, stemmer, scorer and splitter. + */ + +var stopwords = ["a", "and", "are", "as", "at", "be", "but", "by", "for", "if", "in", "into", "is", "it", "near", "no", "not", "of", "on", "or", "such", "that", "the", "their", "then", "there", "these", "they", "this", "to", "was", "will", "with"]; + + +/* Non-minified version is copied as a separate JS file, if available */ + +/** + * Porter Stemmer + */ +var Stemmer = function() { + + var step2list = { + ational: 'ate', + tional: 'tion', + enci: 'ence', + anci: 'ance', + izer: 'ize', + bli: 'ble', + alli: 'al', + entli: 'ent', + eli: 'e', + ousli: 'ous', + ization: 'ize', + ation: 'ate', + ator: 'ate', + alism: 'al', + iveness: 'ive', + fulness: 'ful', + ousness: 'ous', + aliti: 'al', + iviti: 'ive', + biliti: 'ble', + logi: 'log' + }; + + var step3list = { + icate: 'ic', + ative: '', + alize: 'al', + iciti: 'ic', + ical: 'ic', + ful: '', + ness: '' + }; + + var c = "[^aeiou]"; // consonant + var v = "[aeiouy]"; // vowel + var C = c + "[^aeiouy]*"; // consonant sequence + var V = v + "[aeiou]*"; // vowel sequence + + var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 + var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 + var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 + var s_v = "^(" + C + ")?" + v; // vowel in stem + + this.stemWord = function (w) { + var stem; + var suffix; + var firstch; + var origword = w; + + if (w.length < 3) + return w; + + var re; + var re2; + var re3; + var re4; + + firstch = w.substr(0,1); + if (firstch == "y") + w = firstch.toUpperCase() + w.substr(1); + + // Step 1a + re = /^(.+?)(ss|i)es$/; + re2 = /^(.+?)([^s])s$/; + + if (re.test(w)) + w = w.replace(re,"$1$2"); + else if (re2.test(w)) + w = w.replace(re2,"$1$2"); + + // Step 1b + re = /^(.+?)eed$/; + re2 = /^(.+?)(ed|ing)$/; + if (re.test(w)) { + var fp = re.exec(w); + re = new RegExp(mgr0); + if (re.test(fp[1])) { + re = /.$/; + w = w.replace(re,""); + } + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1]; + re2 = new RegExp(s_v); + if (re2.test(stem)) { + w = stem; + re2 = /(at|bl|iz)$/; + re3 = new RegExp("([^aeiouylsz])\\1$"); + re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re2.test(w)) + w = w + "e"; + else if (re3.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + else if (re4.test(w)) + w = w + "e"; + } + } + + // Step 1c + re = /^(.+?)y$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(s_v); + if (re.test(stem)) + w = stem + "i"; + } + + // Step 2 + re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step2list[suffix]; + } + + // Step 3 + re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step3list[suffix]; + } + + // Step 4 + re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; + re2 = /^(.+?)(s|t)(ion)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + if (re.test(stem)) + w = stem; + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1] + fp[2]; + re2 = new RegExp(mgr1); + if (re2.test(stem)) + w = stem; + } + + // Step 5 + re = /^(.+?)e$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + re2 = new RegExp(meq1); + re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) + w = stem; + } + re = /ll$/; + re2 = new RegExp(mgr1); + if (re.test(w) && re2.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + + // and turn initial Y back to y + if (firstch == "y") + w = firstch.toLowerCase() + w.substr(1); + return w; + } +} + diff --git a/_static/minus.png b/_static/minus.png new file mode 100644 index 00000000..d96755fd Binary files /dev/null and b/_static/minus.png differ diff --git a/_static/plus.png b/_static/plus.png new file mode 100644 index 00000000..7107cec9 Binary files /dev/null and b/_static/plus.png differ diff --git a/_static/pygments.css b/_static/pygments.css new file mode 100644 index 00000000..5f2b0a25 --- /dev/null +++ b/_static/pygments.css @@ -0,0 +1,75 @@ +pre { line-height: 125%; } +td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +.highlight .hll { background-color: #ffffcc } +.highlight { background: #eeffcc; } +.highlight .c { color: #408090; font-style: italic } /* Comment */ +.highlight .err { border: 1px solid #F00 } /* Error */ +.highlight .k { color: #007020; font-weight: bold } /* Keyword */ +.highlight .o { color: #666 } /* Operator */ +.highlight .ch { color: #408090; font-style: italic } /* Comment.Hashbang */ +.highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #007020 } /* Comment.Preproc */ +.highlight .cpf { color: #408090; font-style: italic } /* Comment.PreprocFile */ +.highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #408090; background-color: #FFF0F0 } /* Comment.Special */ +.highlight .gd { color: #A00000 } /* Generic.Deleted */ +.highlight .ge { font-style: italic } /* Generic.Emph */ +.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */ +.highlight .gr { color: #F00 } /* Generic.Error */ +.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight .gi { color: #00A000 } /* Generic.Inserted */ +.highlight .go { color: #333 } /* Generic.Output */ +.highlight .gp { color: #C65D09; font-weight: bold } /* Generic.Prompt */ +.highlight .gs { font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight .gt { color: #04D } /* Generic.Traceback */ +.highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { color: #007020 } /* Keyword.Pseudo */ +.highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #902000 } /* Keyword.Type */ +.highlight .m { color: #208050 } /* Literal.Number */ +.highlight .s { color: #4070A0 } /* Literal.String */ +.highlight .na { color: #4070A0 } /* Name.Attribute */ +.highlight .nb { color: #007020 } /* Name.Builtin */ +.highlight .nc { color: #0E84B5; font-weight: bold } /* Name.Class */ +.highlight .no { color: #60ADD5 } /* Name.Constant */ +.highlight .nd { color: #555; font-weight: bold } /* Name.Decorator */ +.highlight .ni { color: #D55537; font-weight: bold } /* Name.Entity */ +.highlight .ne { color: #007020 } /* Name.Exception */ +.highlight .nf { color: #06287E } /* Name.Function */ +.highlight .nl { color: #002070; font-weight: bold } /* Name.Label */ +.highlight .nn { color: #0E84B5; font-weight: bold } /* Name.Namespace */ +.highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #BB60D5 } /* Name.Variable */ +.highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */ +.highlight .w { color: #BBB } /* Text.Whitespace */ +.highlight .mb { color: #208050 } /* Literal.Number.Bin */ +.highlight .mf { color: #208050 } /* Literal.Number.Float */ +.highlight .mh { color: #208050 } /* Literal.Number.Hex */ +.highlight .mi { color: #208050 } /* Literal.Number.Integer */ +.highlight .mo { color: #208050 } /* Literal.Number.Oct */ +.highlight .sa { color: #4070A0 } /* Literal.String.Affix */ +.highlight .sb { color: #4070A0 } /* Literal.String.Backtick */ +.highlight .sc { color: #4070A0 } /* Literal.String.Char */ +.highlight .dl { color: #4070A0 } /* Literal.String.Delimiter */ +.highlight .sd { color: #4070A0; font-style: italic } /* Literal.String.Doc */ +.highlight .s2 { color: #4070A0 } /* Literal.String.Double */ +.highlight .se { color: #4070A0; font-weight: bold } /* Literal.String.Escape */ +.highlight .sh { color: #4070A0 } /* Literal.String.Heredoc */ +.highlight .si { color: #70A0D0; font-style: italic } /* Literal.String.Interpol */ +.highlight .sx { color: #C65D09 } /* Literal.String.Other */ +.highlight .sr { color: #235388 } /* Literal.String.Regex */ +.highlight .s1 { color: #4070A0 } /* Literal.String.Single */ +.highlight .ss { color: #517918 } /* Literal.String.Symbol */ +.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */ +.highlight .fm { color: #06287E } /* Name.Function.Magic */ +.highlight .vc { color: #BB60D5 } /* Name.Variable.Class */ +.highlight .vg { color: #BB60D5 } /* Name.Variable.Global */ +.highlight .vi { color: #BB60D5 } /* Name.Variable.Instance */ +.highlight .vm { color: #BB60D5 } /* Name.Variable.Magic */ +.highlight .il { color: #208050 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/_static/searchtools.js b/_static/searchtools.js new file mode 100644 index 00000000..2c774d17 --- /dev/null +++ b/_static/searchtools.js @@ -0,0 +1,632 @@ +/* + * Sphinx JavaScript utilities for the full-text search. + */ +"use strict"; + +/** + * Simple result scoring code. + */ +if (typeof Scorer === "undefined") { + var Scorer = { + // Implement the following function to further tweak the score for each result + // The function takes a result array [docname, title, anchor, descr, score, filename] + // and returns the new score. + /* + score: result => { + const [docname, title, anchor, descr, score, filename, kind] = result + return score + }, + */ + + // query matches the full name of an object + objNameMatch: 11, + // or matches in the last dotted part of the object name + objPartialMatch: 6, + // Additive scores depending on the priority of the object + objPrio: { + 0: 15, // used to be importantResults + 1: 5, // used to be objectResults + 2: -5, // used to be unimportantResults + }, + // Used when the priority is not in the mapping. + objPrioDefault: 0, + + // query found in title + title: 15, + partialTitle: 7, + // query found in terms + term: 5, + partialTerm: 2, + }; +} + +// Global search result kind enum, used by themes to style search results. +class SearchResultKind { + static get index() { return "index"; } + static get object() { return "object"; } + static get text() { return "text"; } + static get title() { return "title"; } +} + +const _removeChildren = (element) => { + while (element && element.lastChild) element.removeChild(element.lastChild); +}; + +/** + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping + */ +const _escapeRegExp = (string) => + string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string + +const _displayItem = (item, searchTerms, highlightTerms) => { + const docBuilder = DOCUMENTATION_OPTIONS.BUILDER; + const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX; + const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX; + const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY; + const contentRoot = document.documentElement.dataset.content_root; + + const [docName, title, anchor, descr, score, _filename, kind] = item; + + let listItem = document.createElement("li"); + // Add a class representing the item's type: + // can be used by a theme's CSS selector for styling + // See SearchResultKind for the class names. + listItem.classList.add(`kind-${kind}`); + let requestUrl; + let linkUrl; + if (docBuilder === "dirhtml") { + // dirhtml builder + let dirname = docName + "/"; + if (dirname.match(/\/index\/$/)) + dirname = dirname.substring(0, dirname.length - 6); + else if (dirname === "index/") dirname = ""; + requestUrl = contentRoot + dirname; + linkUrl = requestUrl; + } else { + // normal html builders + requestUrl = contentRoot + docName + docFileSuffix; + linkUrl = docName + docLinkSuffix; + } + let linkEl = listItem.appendChild(document.createElement("a")); + linkEl.href = linkUrl + anchor; + linkEl.dataset.score = score; + linkEl.innerHTML = title; + if (descr) { + listItem.appendChild(document.createElement("span")).innerHTML = + " (" + descr + ")"; + // highlight search terms in the description + if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js + highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted")); + } + else if (showSearchSummary) + fetch(requestUrl) + .then((responseData) => responseData.text()) + .then((data) => { + if (data) + listItem.appendChild( + Search.makeSearchSummary(data, searchTerms, anchor) + ); + // highlight search terms in the summary + if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js + highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted")); + }); + Search.output.appendChild(listItem); +}; +const _finishSearch = (resultCount) => { + Search.stopPulse(); + Search.title.innerText = _("Search Results"); + if (!resultCount) + Search.status.innerText = Documentation.gettext( + "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories." + ); + else + Search.status.innerText = Documentation.ngettext( + "Search finished, found one page matching the search query.", + "Search finished, found ${resultCount} pages matching the search query.", + resultCount, + ).replace('${resultCount}', resultCount); +}; +const _displayNextItem = ( + results, + resultCount, + searchTerms, + highlightTerms, +) => { + // results left, load the summary and display it + // this is intended to be dynamic (don't sub resultsCount) + if (results.length) { + _displayItem(results.pop(), searchTerms, highlightTerms); + setTimeout( + () => _displayNextItem(results, resultCount, searchTerms, highlightTerms), + 5 + ); + } + // search finished, update title and status message + else _finishSearch(resultCount); +}; +// Helper function used by query() to order search results. +// Each input is an array of [docname, title, anchor, descr, score, filename, kind]. +// Order the results by score (in opposite order of appearance, since the +// `_displayNextItem` function uses pop() to retrieve items) and then alphabetically. +const _orderResultsByScoreThenName = (a, b) => { + const leftScore = a[4]; + const rightScore = b[4]; + if (leftScore === rightScore) { + // same score: sort alphabetically + const leftTitle = a[1].toLowerCase(); + const rightTitle = b[1].toLowerCase(); + if (leftTitle === rightTitle) return 0; + return leftTitle > rightTitle ? -1 : 1; // inverted is intentional + } + return leftScore > rightScore ? 1 : -1; +}; + +/** + * Default splitQuery function. Can be overridden in ``sphinx.search`` with a + * custom function per language. + * + * The regular expression works by splitting the string on consecutive characters + * that are not Unicode letters, numbers, underscores, or emoji characters. + * This is the same as ``\W+`` in Python, preserving the surrogate pair area. + */ +if (typeof splitQuery === "undefined") { + var splitQuery = (query) => query + .split(/[^\p{Letter}\p{Number}_\p{Emoji_Presentation}]+/gu) + .filter(term => term) // remove remaining empty strings +} + +/** + * Search Module + */ +const Search = { + _index: null, + _queued_query: null, + _pulse_status: -1, + + htmlToText: (htmlString, anchor) => { + const htmlElement = new DOMParser().parseFromString(htmlString, 'text/html'); + for (const removalQuery of [".headerlink", "script", "style"]) { + htmlElement.querySelectorAll(removalQuery).forEach((el) => { el.remove() }); + } + if (anchor) { + const anchorContent = htmlElement.querySelector(`[role="main"] ${anchor}`); + if (anchorContent) return anchorContent.textContent; + + console.warn( + `Anchored content block not found. Sphinx search tries to obtain it via DOM query '[role=main] ${anchor}'. Check your theme or template.` + ); + } + + // if anchor not specified or not found, fall back to main content + const docContent = htmlElement.querySelector('[role="main"]'); + if (docContent) return docContent.textContent; + + console.warn( + "Content block not found. Sphinx search tries to obtain it via DOM query '[role=main]'. Check your theme or template." + ); + return ""; + }, + + init: () => { + const query = new URLSearchParams(window.location.search).get("q"); + document + .querySelectorAll('input[name="q"]') + .forEach((el) => (el.value = query)); + if (query) Search.performSearch(query); + }, + + loadIndex: (url) => + (document.body.appendChild(document.createElement("script")).src = url), + + setIndex: (index) => { + Search._index = index; + if (Search._queued_query !== null) { + const query = Search._queued_query; + Search._queued_query = null; + Search.query(query); + } + }, + + hasIndex: () => Search._index !== null, + + deferQuery: (query) => (Search._queued_query = query), + + stopPulse: () => (Search._pulse_status = -1), + + startPulse: () => { + if (Search._pulse_status >= 0) return; + + const pulse = () => { + Search._pulse_status = (Search._pulse_status + 1) % 4; + Search.dots.innerText = ".".repeat(Search._pulse_status); + if (Search._pulse_status >= 0) window.setTimeout(pulse, 500); + }; + pulse(); + }, + + /** + * perform a search for something (or wait until index is loaded) + */ + performSearch: (query) => { + // create the required interface elements + const searchText = document.createElement("h2"); + searchText.textContent = _("Searching"); + const searchSummary = document.createElement("p"); + searchSummary.classList.add("search-summary"); + searchSummary.innerText = ""; + const searchList = document.createElement("ul"); + searchList.setAttribute("role", "list"); + searchList.classList.add("search"); + + const out = document.getElementById("search-results"); + Search.title = out.appendChild(searchText); + Search.dots = Search.title.appendChild(document.createElement("span")); + Search.status = out.appendChild(searchSummary); + Search.output = out.appendChild(searchList); + + const searchProgress = document.getElementById("search-progress"); + // Some themes don't use the search progress node + if (searchProgress) { + searchProgress.innerText = _("Preparing search..."); + } + Search.startPulse(); + + // index already loaded, the browser was quick! + if (Search.hasIndex()) Search.query(query); + else Search.deferQuery(query); + }, + + _parseQuery: (query) => { + // stem the search terms and add them to the correct list + const stemmer = new Stemmer(); + const searchTerms = new Set(); + const excludedTerms = new Set(); + const highlightTerms = new Set(); + const objectTerms = new Set(splitQuery(query.toLowerCase().trim())); + splitQuery(query.trim()).forEach((queryTerm) => { + const queryTermLower = queryTerm.toLowerCase(); + + // maybe skip this "word" + // stopwords array is from language_data.js + if ( + stopwords.indexOf(queryTermLower) !== -1 || + queryTerm.match(/^\d+$/) + ) + return; + + // stem the word + let word = stemmer.stemWord(queryTermLower); + // select the correct list + if (word[0] === "-") excludedTerms.add(word.substr(1)); + else { + searchTerms.add(word); + highlightTerms.add(queryTermLower); + } + }); + + if (SPHINX_HIGHLIGHT_ENABLED) { // set in sphinx_highlight.js + localStorage.setItem("sphinx_highlight_terms", [...highlightTerms].join(" ")) + } + + // console.debug("SEARCH: searching for:"); + // console.info("required: ", [...searchTerms]); + // console.info("excluded: ", [...excludedTerms]); + + return [query, searchTerms, excludedTerms, highlightTerms, objectTerms]; + }, + + /** + * execute search (requires search index to be loaded) + */ + _performSearch: (query, searchTerms, excludedTerms, highlightTerms, objectTerms) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + const allTitles = Search._index.alltitles; + const indexEntries = Search._index.indexentries; + + // Collect multiple result groups to be sorted separately and then ordered. + // Each is an array of [docname, title, anchor, descr, score, filename, kind]. + const normalResults = []; + const nonMainIndexResults = []; + + _removeChildren(document.getElementById("search-progress")); + + const queryLower = query.toLowerCase().trim(); + for (const [title, foundTitles] of Object.entries(allTitles)) { + if (title.toLowerCase().trim().includes(queryLower) && (queryLower.length >= title.length/2)) { + for (const [file, id] of foundTitles) { + const score = Math.round(Scorer.title * queryLower.length / title.length); + const boost = titles[file] === title ? 1 : 0; // add a boost for document titles + normalResults.push([ + docNames[file], + titles[file] !== title ? `${titles[file]} > ${title}` : title, + id !== null ? "#" + id : "", + null, + score + boost, + filenames[file], + SearchResultKind.title, + ]); + } + } + } + + // search for explicit entries in index directives + for (const [entry, foundEntries] of Object.entries(indexEntries)) { + if (entry.includes(queryLower) && (queryLower.length >= entry.length/2)) { + for (const [file, id, isMain] of foundEntries) { + const score = Math.round(100 * queryLower.length / entry.length); + const result = [ + docNames[file], + titles[file], + id ? "#" + id : "", + null, + score, + filenames[file], + SearchResultKind.index, + ]; + if (isMain) { + normalResults.push(result); + } else { + nonMainIndexResults.push(result); + } + } + } + } + + // lookup as object + objectTerms.forEach((term) => + normalResults.push(...Search.performObjectSearch(term, objectTerms)) + ); + + // lookup as search terms in fulltext + normalResults.push(...Search.performTermsSearch(searchTerms, excludedTerms)); + + // let the scorer override scores with a custom scoring function + if (Scorer.score) { + normalResults.forEach((item) => (item[4] = Scorer.score(item))); + nonMainIndexResults.forEach((item) => (item[4] = Scorer.score(item))); + } + + // Sort each group of results by score and then alphabetically by name. + normalResults.sort(_orderResultsByScoreThenName); + nonMainIndexResults.sort(_orderResultsByScoreThenName); + + // Combine the result groups in (reverse) order. + // Non-main index entries are typically arbitrary cross-references, + // so display them after other results. + let results = [...nonMainIndexResults, ...normalResults]; + + // remove duplicate search results + // note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept + let seen = new Set(); + results = results.reverse().reduce((acc, result) => { + let resultStr = result.slice(0, 4).concat([result[5]]).map(v => String(v)).join(','); + if (!seen.has(resultStr)) { + acc.push(result); + seen.add(resultStr); + } + return acc; + }, []); + + return results.reverse(); + }, + + query: (query) => { + const [searchQuery, searchTerms, excludedTerms, highlightTerms, objectTerms] = Search._parseQuery(query); + const results = Search._performSearch(searchQuery, searchTerms, excludedTerms, highlightTerms, objectTerms); + + // for debugging + //Search.lastresults = results.slice(); // a copy + // console.info("search results:", Search.lastresults); + + // print the results + _displayNextItem(results, results.length, searchTerms, highlightTerms); + }, + + /** + * search for object names + */ + performObjectSearch: (object, objectTerms) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const objects = Search._index.objects; + const objNames = Search._index.objnames; + const titles = Search._index.titles; + + const results = []; + + const objectSearchCallback = (prefix, match) => { + const name = match[4] + const fullname = (prefix ? prefix + "." : "") + name; + const fullnameLower = fullname.toLowerCase(); + if (fullnameLower.indexOf(object) < 0) return; + + let score = 0; + const parts = fullnameLower.split("."); + + // check for different match types: exact matches of full name or + // "last name" (i.e. last dotted part) + if (fullnameLower === object || parts.slice(-1)[0] === object) + score += Scorer.objNameMatch; + else if (parts.slice(-1)[0].indexOf(object) > -1) + score += Scorer.objPartialMatch; // matches in last name + + const objName = objNames[match[1]][2]; + const title = titles[match[0]]; + + // If more than one term searched for, we require other words to be + // found in the name/title/description + const otherTerms = new Set(objectTerms); + otherTerms.delete(object); + if (otherTerms.size > 0) { + const haystack = `${prefix} ${name} ${objName} ${title}`.toLowerCase(); + if ( + [...otherTerms].some((otherTerm) => haystack.indexOf(otherTerm) < 0) + ) + return; + } + + let anchor = match[3]; + if (anchor === "") anchor = fullname; + else if (anchor === "-") anchor = objNames[match[1]][1] + "-" + fullname; + + const descr = objName + _(", in ") + title; + + // add custom score for some objects according to scorer + if (Scorer.objPrio.hasOwnProperty(match[2])) + score += Scorer.objPrio[match[2]]; + else score += Scorer.objPrioDefault; + + results.push([ + docNames[match[0]], + fullname, + "#" + anchor, + descr, + score, + filenames[match[0]], + SearchResultKind.object, + ]); + }; + Object.keys(objects).forEach((prefix) => + objects[prefix].forEach((array) => + objectSearchCallback(prefix, array) + ) + ); + return results; + }, + + /** + * search for full-text terms in the index + */ + performTermsSearch: (searchTerms, excludedTerms) => { + // prepare search + const terms = Search._index.terms; + const titleTerms = Search._index.titleterms; + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + + const scoreMap = new Map(); + const fileMap = new Map(); + + // perform the search on the required terms + searchTerms.forEach((word) => { + const files = []; + const arr = [ + { files: terms[word], score: Scorer.term }, + { files: titleTerms[word], score: Scorer.title }, + ]; + // add support for partial matches + if (word.length > 2) { + const escapedWord = _escapeRegExp(word); + if (!terms.hasOwnProperty(word)) { + Object.keys(terms).forEach((term) => { + if (term.match(escapedWord)) + arr.push({ files: terms[term], score: Scorer.partialTerm }); + }); + } + if (!titleTerms.hasOwnProperty(word)) { + Object.keys(titleTerms).forEach((term) => { + if (term.match(escapedWord)) + arr.push({ files: titleTerms[term], score: Scorer.partialTitle }); + }); + } + } + + // no match but word was a required one + if (arr.every((record) => record.files === undefined)) return; + + // found search word in contents + arr.forEach((record) => { + if (record.files === undefined) return; + + let recordFiles = record.files; + if (recordFiles.length === undefined) recordFiles = [recordFiles]; + files.push(...recordFiles); + + // set score for the word in each file + recordFiles.forEach((file) => { + if (!scoreMap.has(file)) scoreMap.set(file, {}); + scoreMap.get(file)[word] = record.score; + }); + }); + + // create the mapping + files.forEach((file) => { + if (!fileMap.has(file)) fileMap.set(file, [word]); + else if (fileMap.get(file).indexOf(word) === -1) fileMap.get(file).push(word); + }); + }); + + // now check if the files don't contain excluded terms + const results = []; + for (const [file, wordList] of fileMap) { + // check if all requirements are matched + + // as search terms with length < 3 are discarded + const filteredTermCount = [...searchTerms].filter( + (term) => term.length > 2 + ).length; + if ( + wordList.length !== searchTerms.size && + wordList.length !== filteredTermCount + ) + continue; + + // ensure that none of the excluded terms is in the search result + if ( + [...excludedTerms].some( + (term) => + terms[term] === file || + titleTerms[term] === file || + (terms[term] || []).includes(file) || + (titleTerms[term] || []).includes(file) + ) + ) + break; + + // select one (max) score for the file. + const score = Math.max(...wordList.map((w) => scoreMap.get(file)[w])); + // add result to the result list + results.push([ + docNames[file], + titles[file], + "", + null, + score, + filenames[file], + SearchResultKind.text, + ]); + } + return results; + }, + + /** + * helper function to return a node containing the + * search summary for a given text. keywords is a list + * of stemmed words. + */ + makeSearchSummary: (htmlText, keywords, anchor) => { + const text = Search.htmlToText(htmlText, anchor); + if (text === "") return null; + + const textLower = text.toLowerCase(); + const actualStartPosition = [...keywords] + .map((k) => textLower.indexOf(k.toLowerCase())) + .filter((i) => i > -1) + .slice(-1)[0]; + const startWithContext = Math.max(actualStartPosition - 120, 0); + + const top = startWithContext === 0 ? "" : "..."; + const tail = startWithContext + 240 < text.length ? "..." : ""; + + let summary = document.createElement("p"); + summary.classList.add("context"); + summary.textContent = top + text.substr(startWithContext, 240).trim() + tail; + + return summary; + }, +}; + +_ready(Search.init); diff --git a/_static/sphinx_highlight.js b/_static/sphinx_highlight.js new file mode 100644 index 00000000..8a96c69a --- /dev/null +++ b/_static/sphinx_highlight.js @@ -0,0 +1,154 @@ +/* Highlighting utilities for Sphinx HTML documentation. */ +"use strict"; + +const SPHINX_HIGHLIGHT_ENABLED = true + +/** + * highlight a given string on a node by wrapping it in + * span elements with the given class name. + */ +const _highlight = (node, addItems, text, className) => { + if (node.nodeType === Node.TEXT_NODE) { + const val = node.nodeValue; + const parent = node.parentNode; + const pos = val.toLowerCase().indexOf(text); + if ( + pos >= 0 && + !parent.classList.contains(className) && + !parent.classList.contains("nohighlight") + ) { + let span; + + const closestNode = parent.closest("body, svg, foreignObject"); + const isInSVG = closestNode && closestNode.matches("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.classList.add(className); + } + + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + const rest = document.createTextNode(val.substr(pos + text.length)); + parent.insertBefore( + span, + parent.insertBefore( + rest, + node.nextSibling + ) + ); + node.nodeValue = val.substr(0, pos); + /* There may be more occurrences of search term in this node. So call this + * function recursively on the remaining fragment. + */ + _highlight(rest, addItems, text, className); + + if (isInSVG) { + const rect = document.createElementNS( + "http://www.w3.org/2000/svg", + "rect" + ); + const bbox = parent.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute("class", className); + addItems.push({ parent: parent, target: rect }); + } + } + } else if (node.matches && !node.matches("button, select, textarea")) { + node.childNodes.forEach((el) => _highlight(el, addItems, text, className)); + } +}; +const _highlightText = (thisNode, text, className) => { + let addItems = []; + _highlight(thisNode, addItems, text, className); + addItems.forEach((obj) => + obj.parent.insertAdjacentElement("beforebegin", obj.target) + ); +}; + +/** + * Small JavaScript module for the documentation. + */ +const SphinxHighlight = { + + /** + * highlight the search words provided in localstorage in the text + */ + highlightSearchWords: () => { + if (!SPHINX_HIGHLIGHT_ENABLED) return; // bail if no highlight + + // get and clear terms from localstorage + const url = new URL(window.location); + const highlight = + localStorage.getItem("sphinx_highlight_terms") + || url.searchParams.get("highlight") + || ""; + localStorage.removeItem("sphinx_highlight_terms") + url.searchParams.delete("highlight"); + window.history.replaceState({}, "", url); + + // get individual terms from highlight string + const terms = highlight.toLowerCase().split(/\s+/).filter(x => x); + if (terms.length === 0) return; // nothing to do + + // There should never be more than one element matching "div.body" + const divBody = document.querySelectorAll("div.body"); + const body = divBody.length ? divBody[0] : document.querySelector("body"); + window.setTimeout(() => { + terms.forEach((term) => _highlightText(body, term, "highlighted")); + }, 10); + + const searchBox = document.getElementById("searchbox"); + if (searchBox === null) return; + searchBox.appendChild( + document + .createRange() + .createContextualFragment( + '" + ) + ); + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords: () => { + document + .querySelectorAll("#searchbox .highlight-link") + .forEach((el) => el.remove()); + document + .querySelectorAll("span.highlighted") + .forEach((el) => el.classList.remove("highlighted")); + localStorage.removeItem("sphinx_highlight_terms") + }, + + initEscapeListener: () => { + // only install a listener if it is really needed + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; + if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) { + SphinxHighlight.hideSearchWords(); + event.preventDefault(); + } + }); + }, +}; + +_ready(() => { + /* Do not call highlightSearchWords() when we are on the search page. + * It will highlight words from the *previous* search query. + */ + if (typeof Search === "undefined") SphinxHighlight.highlightSearchWords(); + SphinxHighlight.initEscapeListener(); +}); diff --git a/acknowledgements.texinfo b/acknowledgements.texinfo new file mode 100644 index 00000000..a2bb875a --- /dev/null +++ b/acknowledgements.texinfo @@ -0,0 +1,51 @@ +This software was originally developed by the Billinge group as part +of the Distributed Data Analysis of Neutron Scattering Experiments +(DANSE) project funded by the US National Science Foundation under +grant DMR-0520547. Developments of PDFfit2 were funded by NSF grant +DMR-0304391 in the Billinge group, and with support from Michigan State +University and Columbia University. Any opinions, findings, and conclusions +or recommendations expressed in this material are those of the author(s) +and do not necessarily reflect the views of the respective funding bodies. +Subsequent development was done in the Billinge group at Columbia University +and then in collaboration between the Billinge group at Columbia and Pavol +Juhas at Brookhaven National Laboratory. Moving forward, PDFgui will be +maintained as a community project with contributions welcomed from many people. + +Several of the examples in the tutorial part were made possible and benefited from samples +synthesized by J. F. Mitchell, and from data collected and processed by M. +Schmidt, P. G. Radaelli, and X. Qiu. + +@bigskip{} +If you use this program to do productive scientific research that leads +to publication, we ask that you acknowledge use of the program by citing +the following paper in your publication: +@bigskip{} + +@quotation +C. L. Farrow, P. Juhás, J. W. Liu, D. Bryndin, E. S. Božin, +J. Bloch, Th. Proffen and S. J. L. Billinge, +@url{https://stacks.iop.org/0953-8984/19/335219, +PDFfit2 and PDFgui: computer programs for studying nanostructure in crystals}, +@i{@w{J. Phys.:} Condens. Matter}, @b{19}, 335219 (2007) +@end quotation + +@bigskip{} +@insertcopying +@cindex copyright +@bigskip{} +As of February 2017, and the 1.1.2 release, PDFgui has moved to a shared copyright model. +@bigskip{} +PDFgui uses a shared copyright model. Each contributor maintains copyright over their +contributions to PDFgui. But, it is important to note that these contributions are +typically only changes to the repositories. Thus, the PDFgui source code, in its entirety, +is not the copyright of any single person or institution. Instead, it is the collective +copyright of the entire PDFgui Development Team. If individual contributors want to +maintain a record of what changes/contributions they have specific copyright on, they +should indicate their copyright in the commit message of the change, when they commit +the change to one of the PDFgui repositories. +@bigskip{} +The PDFgui Development Team is the set of all contributors to the PDFgui project. +A full list can be obtained from the git version control logs. +@bigskip{} +For more information please visit @url{https://www.diffpy.org} +or contact Prof. Simon Billinge at @email{sb2896@@columbia.edu}. diff --git a/api/diffpy.pdfgui.applications.html b/api/diffpy.pdfgui.applications.html new file mode 100644 index 00000000..1aac16fc --- /dev/null +++ b/api/diffpy.pdfgui.applications.html @@ -0,0 +1,187 @@ + + + + + + + + + diffpy.pdfgui.applications package — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

diffpy.pdfgui.applications package

+
+

Submodules

+
+

diffpy.pdfgui.applications.pdfgui module

+

PDFgui Graphical User Interface for Pair Distribution Function fitting +Usage: pdfgui [project.dpp]

+

PDFgui is graphical user interface to PDFfit2 - a Python library for PDF +simulation and structure refinement. PDFgui has many nice features such +as control of multiple fits, integrated plotting, easy setup of sequential +refinements, and saving of entire project in a single file.

+
+
Options:
+
-h, --help
+

display this message

+
+
-V, --version
+

show program version

+
+
+
+
Debugging options:
+
--db-noed
+

disable exceptions catching to ErrorReportDialog

+
+
--db-nocf
+

exit without asking to save modified project

+
+
--db-pdb
+

use Python debugger to handle error exceptions

+
+
+
+
+
+
+diffpy.pdfgui.applications.pdfgui.main()[source]
+

Main entry point to PDFgui.

+
+ +
+
+diffpy.pdfgui.applications.pdfgui.processArguments(argv1)[source]
+

Process command line arguments and store results in pdfguiglobals. This +method updates cmdopts, cmdargs and dbopts attributes in the pdfguiglobals +module.

+

argv1 – list of command line arguments excluding the executable

+

Returns boolean flag to indicate if the execution should continue. +The flag is False, when options contain –help or –version. +Raises GetoptError for invalid options. +Raises ValueError for more than one project file arguments or +when project is not a valid file.

+
+ +
+
+diffpy.pdfgui.applications.pdfgui.usage()[source]
+

Show usage info.

+
+ +
+
+diffpy.pdfgui.applications.pdfgui.version()[source]
+
+ +
+
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/api/diffpy.pdfgui.control.html b/api/diffpy.pdfgui.control.html new file mode 100644 index 00000000..1d4c9cde --- /dev/null +++ b/api/diffpy.pdfgui.control.html @@ -0,0 +1,2323 @@ + + + + + + + + + diffpy.pdfgui.control package — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

diffpy.pdfgui.control package

+
+

Submodules

+
+

diffpy.pdfgui.control.pdfcomponent module

+
+
+class diffpy.pdfgui.control.pdfcomponent.PDFComponent(name)[source]
+

Bases: object

+

Common base class.

+
+
+close(force=False)[source]
+

Close myself.

+

force – if forcibly (no wait)

+
+ +
+ +
+
+

diffpy.pdfgui.control.constraint module

+

Class Constraint for storage of a single constraint equation constraints +will be stored in { variable : constraint } dictionary.

+
+
+class diffpy.pdfgui.control.constraint.Constraint(formula, value=None)[source]
+

Bases: object

+

Constraint –> storage and check of a single constraint equation.

+
+
Data members:
+
formula – right-side of constraint equation (string). When

assigned it is checked for math correctness and updates +the parguess dictionary

+
+
parguess – read-only dictionary of parameter indices and their

estimated initial values. Values are None if they +cannot be estimated.

+
+
+
+
Private members:

__lhs – last value of constrained variable passed to guess()

+
+
+
+
+evalFormula(parvalues)[source]
+

Evaluate constraint formula.

+

parvalues – dictionary of int parameter indices and float values.

+

returns formula result

+
+ +
+
+guess(value)[source]
+

Guess the initial values of parameters contained in parguess.

+

value – current value of the constrained variable

+

The keys of self.parguess are indices of parameters used in formula, +and the values are suggested parameter values (None if they cannot +be estimated).

+

returns a copy of self.parguess

+
+ +
+
+lambdaFormula()[source]
+

Build lambda function from constraint formula. Lambda function +expects dictionary argument.

+

returns lambda function

+
+ +
+ +
+
+

diffpy.pdfgui.control.controlerrors module

+
+
+exception diffpy.pdfgui.control.controlerrors.ControlConfigError(info)[source]
+

Bases: ControlError

+

PDFGuiControl exception class – object config is invalid.

+
+ +
+
+exception diffpy.pdfgui.control.controlerrors.ControlError(info)[source]
+

Bases: Exception

+

Basic PDFGuiControl exception class.

+
+ +
+
+exception diffpy.pdfgui.control.controlerrors.ControlFileError(info)[source]
+

Bases: ControlError

+

PDFGuiControl exception class – object config is invalid.

+
+ +
+
+exception diffpy.pdfgui.control.controlerrors.ControlIndexError(info)[source]
+

Bases: ControlError

+

PDFGuiControl exception class – index out of bound.

+
+ +
+
+exception diffpy.pdfgui.control.controlerrors.ControlKeyError(info)[source]
+

Bases: ControlError

+

PDFGuiControl exception class – requested object can’t be found.

+
+ +
+
+exception diffpy.pdfgui.control.controlerrors.ControlRuntimeError(info)[source]
+

Bases: ControlError

+

PDFGuiControl exception class – various irrecoverable runtime error.

+
+ +
+
+exception diffpy.pdfgui.control.controlerrors.ControlStatusError(info)[source]
+

Bases: ControlError

+

PDFGuiControl exception class – Fitting status doesn’t match.

+
+ +
+
+exception diffpy.pdfgui.control.controlerrors.ControlSyntaxError(info)[source]
+

Bases: ControlError

+

PDFGuiControl exception class – invalid syntax of constraint +formula.

+
+ +
+
+exception diffpy.pdfgui.control.controlerrors.ControlTypeError(info)[source]
+

Bases: ControlError

+

PDFGuiControl exception class – Type mismatch.

+
+ +
+
+exception diffpy.pdfgui.control.controlerrors.ControlValueError(info)[source]
+

Bases: ControlError

+

PDFGuiControl exception class – Invalid value.

+
+ +
+
+exception diffpy.pdfgui.control.controlerrors.TempControlSelectError(info)[source]
+

Bases: ControlError

+

Temporary define this error to identify the select-control error in +python3.

+
+ +
+
+

diffpy.pdfgui.control.pdflist module

+
+
+class diffpy.pdfgui.control.pdflist.PDFList(*args)[source]
+

Bases: list

+

List class of PDFComponent, which can be accessed through index or a +name string.

+
+
+items()[source]
+

Get name-object pairs.

+

return: a list of tuple ( name, object)

+
+ +
+
+keys()[source]
+

Get the names of the held objects.

+

return: list of names

+
+ +
+
+rename(idnmrf, newname)[source]
+

Rename an item.

+

idnmrf – index,name or reference to the object +newname – new name

+
+ +
+
+values()[source]
+

Get all held objects.

+

return: list of objects

+
+ +
+ +
+
+

diffpy.pdfgui.control.pdfguimacros module

+

Methods for macros used in pdfgui.

+
+
+diffpy.pdfgui.control.pdfguimacros.makeDopingSeries(control, fit, base, dopant, paths, doping)[source]
+

Make a temperature series.

+

control – pdguicontrol instance +fit – The template fit +base – Name of the base element +dopant – Name of the dopant element +paths – list of path names of new datasets +doping – list of doping values corresponding to the datasets

+

returns a list of the new fit organization objects

+
+ +
+
+diffpy.pdfgui.control.pdfguimacros.makeRSeries(control, fit, maxfirst=None, maxlast=None, maxstep=None, minfirst=None, minlast=None, minstep=None)[source]
+

Make an series of fits with an increasing r-range.

+

The new fits are appended to the end of any current fits in the control.

+

control – The control object that will contain the fits +fit – The prototype fit +maxfirst – The first value of the maximum of the fit range +maxlast – The last value of the maximum of the fit range +maxstep – The step size of the maximum of the fit range +minfirst – The first value of the minimum of the fit range +minlast – The last value of the minimum of the fit range +minstep – The step size of the minimum of the fit range

+

returns a list of the new fit organization objects

+
+ +
+
+diffpy.pdfgui.control.pdfguimacros.makeTemperatureSeries(control, fit, paths, temperatures)[source]
+

Make a temperature series.

+

control – pdguicontrol instance +fit – The template fit +paths – list of path names of new datasets +temperatures – list of temperatures corresponding to the datasets

+

returns a list of the new fit organization objects

+
+ +
+
+

diffpy.pdfgui.control.calculation module

+

Class Calculation for performing PDF simulation from model structure.

+
+
+class diffpy.pdfgui.control.calculation.Calculation(name)[source]
+

Bases: PDFComponent

+

Perform a theoretical computation of PDF from model structure.

+

Data members:

+

rmin – read-only lower boundary of rcalc, change with setRGrid() +rstep – read-only r-grid step, use setRGrid() to change it +rmax – read-only upper boundary of rcalc, change with setRGrid() +rlen – read-only number of r points, set by setRGrid().

+
+

To be used in PdfFit.alloc()

+
+

rcalc – list of r values, this is set after calculation is finished +Gcalc – list of calculated G values +stype – scattering type, ‘X’ or ‘N’ +qmax – maximum value of Q in inverse Angstroms. Termination ripples

+
+

are ignored for qmax=0.

+
+
+
qdamp – specifies width of Gaussian damping factor in pdf_obs due

to imperfect Q resolution

+
+
+

qbroad – quadratic peak broadening factor related to dataset +spdiameter – particle diameter for shape damping function.

+
+

Note: this attribute has been moved to FitStructure and is +maintained only for backward compatible reading of PDFgui +project files.

+
+

dscale – total scale factor

+
+
+calculate()[source]
+

Do the real calculation.

+
+ +
+
+copy(other=None)[source]
+

Copy self to other. if other is None, create new instance.

+

other – reference to other object

+

returns reference to copied object

+
+ +
+
+getData(dataname, step=None)[source]
+

Get Calculation data member.

+

name – data item name +step – ignored, just for compatibility with Organizer.getData()

+

returns data object, be it a single number, a list, or a list of list

+
+ +
+
+getMetaData(name)[source]
+

Get meta data value.

+

name – meta data name +returns meta data value

+
+ +
+
+getMetaDataNames()[source]
+

Return all applicable meta data names.

+
+ +
+
+getXNames()[source]
+

Get names of data item which can be plotted as x.

+

returns a name str list

+
+ +
+
+getYNames()[source]
+

Get names of data item which can be plotted as y.

+

returns a name str list

+
+ +
+
+load(z, subpath)[source]
+

Load data from a zipped project file.

+

z – zipped project file +subpath – path to its own storage within project file

+

returns a tree of internal hierarchy

+
+ +
+
+save(z, subpath)[source]
+

Save data from a zipped project file.

+

z – zipped project file +subpath – path to its own storage within project file

+
+ +
+
+setRGrid(rmin=None, rstep=None, rmax=None)[source]
+

Change specified r-grid parameters (rmin, rstep, rmax). Adjust rmax +for integer number of steps.

+

rmin – new low rcalc boundary +rstep – new r-grid step +rmax – new maximum rcalc, slightly adjusted to accommodate rstep

+

No return value. +Raise ControlValueError for invalid range specification.

+
+ +
+
+start()[source]
+

Entry function for calculation.

+
+ +
+
+write(filename)[source]
+

Write this calculated PDF to a file.

+

filename – name of file to write to

+

No return value.

+
+ +
+
+writeStr()[source]
+

String representation of calculated PDF.

+

Returns data string

+
+ +
+ +
+
+

diffpy.pdfgui.control.pdfstructure module

+
+
+class diffpy.pdfgui.control.pdfstructure.PDFStructure(name, *args, **kwargs)[source]
+

Bases: PDFComponent, PDFFitStructure

+

PDFStructure contains structure information, which can be used for 3D +rendering as well as structure refinement.

+
+
+copy(other=None)[source]
+

Copy self to other. if other is None, create an instance.

+

other – ref to other object

+

returns reference to copied object

+
+ +
+
+getvar(var)[source]
+

Obtain value corresponding to PdfFit phase variable var This can be +used when guessing Parameter values from constraints dictionary.

+
+
var – string representation of PdfFit variable. Possible values:

pscale, spdiameter, stepcut, delta1, delta2, sratio, rcut, +lat(n), where n = 1..6, x(i), y(i), z(i), occ(i), u11(i), +u22(i), u33(i), u12(i), u13(i), u23(i), where i=1..Natoms

+
+
+

returns value of var

+
+ +
+
+read(filename, format='auto')[source]
+

Load structure from a file, raise ControlFileError for invalid or +unknown structure format.

+

filename – file to be loaded +format – structure format such as ‘pdffit’, ‘pdb’, ‘xyz’. When

+
+

‘auto’ all available formats are tried in a row.

+
+

Return instance of StructureParser used to load the data. +See Structure.read() for more info.

+
+ +
+
+setvar(var, value)[source]
+

Assign to data member using PdfFit-style variable This can be used +when applying constraint equations with particular parameter values.

+
+
var – string representation of PdfFit variable. Possible values:

pscale, spdiameter, stepcut, delta1, delta2, sratio, rcut, +lat(n), where n=1..6, x(i), y(i), z(i), occ(i), u11(i), +u22(i), u33(i), u12(i), u13(i), u23(i), where i=1..Natoms

+
+
+

value – new value of the variable

+
+ +
+ +
+
+

diffpy.pdfgui.control.fitdataset module

+

Class FitDataSet for experimental PDF data and related fitting +parameters.

+
+
+class diffpy.pdfgui.control.fitdataset.FitDataSet(name)[source]
+

Bases: PDFDataSet

+

FitDataSet stores experimental and calculated PDF data and related +fitting parameters. Inherited from PDFDataSet.

+

Data members (in addition to those in PDFDataSet):

+

fitrmin – lower boundary for data fitting, property +fitrmax – upper boundary for data fitting, property +fitrstep – r-step used for fitted data, property +constraints – dictionary of { var_string : Constraint_instance } +initial – dictionary of initial values of refinable variables +refined – dictionary of refined values of refinable variables

+

Calculated members:

+

rcalc – list of r points where Gcalc is calculated, cached property +Gcalc – list of calculated G values, cached property +dGcalc – list of standard deviations of Gcalc, cached property +Gtrunc – Gobs resampled to rcalc grid, cached property +dGtrunc – dGobs resampled to rcalc grid, cached property +Gdiff – difference curve, Gdiff = Gtrunc - Gcalc, property +crw – cumulative rw of the fit

+

The data in rcalc, Gcalc, dGcalc, Gtrunc, dGtrunc are recalculated +and cached when r-sampling changes. Any change to fitrmin, +fitrmax and fitrstep sets the _rcalc_changed flag.

+

Refinable variables: qdamp, qbroad, dscale +Note: self.refvar is the same as self.initial[refvar].

+

Class data:

+

persistentItems – list of attributes saved in project file

+
+
+property Gcalc
+

List of calculate G values.

+
+ +
+
+property Gdiff
+

Difference between observed and calculated PDF on rcalc grid.

+
+ +
+
+property Gtrunc
+

Gobs resampled to rcalc grid.

+
+ +
+
+applyParameters(parameters)[source]
+

Evaluate constraint formulas and adjust self.initial.

+
+
parameters – dictionary of parameter indices with Parameter instances.

Dictionary may also have float-type values.

+
+
+
+ +
+
+changeParameterIndex(oldidx, newidx)[source]
+

Change a parameter index to a new value.

+

This will replace all instances of one parameter name with +another in this fit.

+
+ +
+
+clear()[source]
+

Reset all data members to initial empty values.

+
+ +
+
+clearRefined()[source]
+

Clear all refinement results.

+
+ +
+
+copy(other=None)[source]
+

Copy self to other. if other is None, create new instance.

+

other – ref to other object

+

returns reference to copied object

+
+ +
+
+property crw
+

cumulative rw on rcalc grid

+
+ +
+
+property dGcalc
+

List of standard deviations of Gcalc.

+
+ +
+
+property dGtrunc
+

dGobs resampled to rcalc grid.

+
+ +
+
+findParameters()[source]
+

Obtain dictionary of parameters used by self.constraints. The keys +of returned dictionary are integer parameter indices, and their values +Parameter instances, with guessed initial values.

+

returns dictionary of indices and Parameter instances

+
+ +
+
+property fitrmax
+

Upper boundary for simulated PDF curve.

+
+ +
+
+property fitrmin
+

Lower boundary for simulated PDF curve.

+
+ +
+
+property fitrstep
+

R-step used for simulated PDF curve.

+
+ +
+
+getData(name, step=-1)[source]
+

Get self’s data member.

+

name – data item name +step – step info, it can be:

+
+
    +
  1. a number ( -1 means latest step ): for single step

  2. +
  3. a list of numbers: for multiple steps

  4. +
  5. None: for all steps

  6. +
+
+

returns data object, be it a single number, a list, or a list of list

+
+ +
+
+getFitSamplingType()[source]
+

Description of r-sampling used in the fit. This method compares +self.fitrstep with r-sampling in the observed data and with Nyquist r +step.

+

Return a string, possible values are “data”, “Nyquist” or +“custom”.

+
+ +
+
+getNyquistSampling()[source]
+

Return r-step corresponding to Nyquist sampling at the qmax value.

+

When qmax is zero, return r-step in the observed data.

+
+ +
+
+getObsSampling()[source]
+

Return the average r-step used in robs or zero when not defined.

+
+ +
+
+getXNames()[source]
+

Get names of data item which can be plotted as x.

+

returns list of strings

+
+ +
+
+getYNames()[source]
+

Get names of data item which can be plotted as y.

+

returns list of strings

+
+ +
+
+load(z, subpath)[source]
+

Load data from a zipped project file.

+

z – zipped project file +subpath – path to its own storage within project file

+
+ +
+
+obtainRefined(server, idataset)[source]
+

Upload refined datataset from PdfFit server instance.

+

server – instance of PdfFit server +idataset – index of this dataset in server

+
+ +
+
+persistentItems = ['rcalc', 'Gcalc', 'dGcalc', 'fitrmin', 'fitrmax', 'fitrstep', 'initial', 'refined']
+
+ +
+
+property rcalc
+

R-grid for refined data, read-only. +Use fitrmin, fitrmax, fitrstep to change it

+
+ +
+
+read(filename)[source]
+

Same as readObs().

+
+ +
+
+readObs(filename)[source]
+

Load experimental PDF data from PDFGetX2 or PDFGetN gr file.

+

filename – file to read from

+

returns self

+
+ +
+
+readObsStr(datastring)[source]
+

Read experimental PDF data from a string.

+

datastring – string of raw data

+

returns self

+
+ +
+
+readStr(datastring)[source]
+

Same as readObsStr().

+
+ +
+
+save(z, subpath)[source]
+

Save data to a zipped project file.

+

z – zipped project file +subpath – path to its own storage within project file

+
+ +
+
+setFitSamplingType(tp, value=None)[source]
+

GUI interface to set fitrstep, i.e., r-grid for fitting.

+
+
tp – description of fit sampling type. Possible values are

“data” … same as used in experimental PDF +“Nyquist” … sampling at Nyquist spacing +“custom” … user specified value

+
+
+

value – new value of fitrstep, only used when tp is “custom”.

+

No return value.

+

Raises ValueError for unknown tp string.

+
+ +
+
+write(filename)[source]
+

Same as writeCalc(). Use writeObs() to save experimental PDF data.

+

filename – name of file to write to

+

No return value.

+
+ +
+
+writeCalc(filename)[source]
+

Write calculated PDF data to a file.

+

filename – name of file to write to

+

No return value.

+
+ +
+
+writeCalcStr()[source]
+

String representation of calculated PDF data.

+

Return data string.

+
+ +
+
+writeObs(filename)[source]
+

Write observed PDF data to a file.

+

filename – name of file to write to

+

No return value.

+
+ +
+
+writeObsStr()[source]
+

String representation of observed PDF data.

+

Return data string.

+
+ +
+
+writeResampledObs(filename)[source]
+

Write resampled PDF data in Gtrunc to a file.

+

filename – name of the file to write to

+

No return value.

+
+ +
+
+writeResampledObsStr()[source]
+

String representation of resampled PDF data in Gtrunc.

+

Return data string.

+
+ +
+
+writeStr()[source]
+

Same as writeCalcStr. Use writeObsStr() for experimental PDF.

+

Return data string.

+
+ +
+ +
+
+diffpy.pdfgui.control.fitdataset.grid_interpolation(x0, y0, x1, left=None, right=None, tp=None)[source]
+

Interpolate values from one grid onto another using either linear or +Whittaker–Shannon interpolation.

+
+
Parameters:
+
    +
  • x0 (array_like) – Original x-grid, must be equally spaced.

  • +
  • y0 (array_like) – Original values defined on x0.

  • +
  • x1 (array_like) – New x-grid upon which to interpolate.

  • +
  • tp ({'data', 'Nyquist', 'custom'}, optional) – Corresponding fit sampling type. Use Whittaker–Shannon interpolation +for Nyquist resampling and linear interpolation otherwise. +If not provided, linear interpolation is used.

  • +
  • left (float, optional) – Value for interpolated y1 for x1 below the x0 range. +Default: if tp=’Nyquist’ then y1[0] is used. Otherwise 0.0 is used.

  • +
  • right (float, optional) – Value for interpolated y1 for x1 above the x0 range. +Default: if tp=’Nyquist’ then y1[-1] is used. Otherwise 0.0 is used.

  • +
+
+
Returns:
+

Array of interpolated values on the new grid x1.

+
+
Return type:
+

numpy.ndarray

+
+
+

Notes

+

When tp=’Nyquist’, the function calls wsinterp() to perform Whittaker–Shannon interpolation. +Otherwise it uses the internal _linear_interpolation() routine.

+
+ +
+
+

diffpy.pdfgui.control.structureviewer module

+

Structure plotting in an external viewer process.

+
+
+class diffpy.pdfgui.control.structureviewer.StructureViewer(executable=None, argstr=None, fileformat=None)[source]
+

Bases: object

+

Class for plotting structure in general structure viewer. It takes care +of creating temporary structure file in a desired format and launching +structure viewer as a background process. The temporary files are removed +when StructureViewer instance goes out of scope.

+

Data attributes:

+
+
executable – full path to the structure viewer executable or an executable

that can be found in system PATH. By default ‘’ (not set).

+
+
argstr – argument string for the viewer program, it can use shell

quoting. Instances of ‘%s’ in the string are replaced with +temporary structure file. By default ‘%s’

+
+
fileformat – structure format that can be loaded by the viewer.

Must be one of output formats supported by diffpy.structure +package. By default ‘pdb’.

+
+
_tmpdir – Temporary directory for structure files opened by the viewer.

tmpdir is None before the first call to plot. The directory +and everything inside is removed when StructureViewer goes +out of the scope.

+
+
+

_plotcount – Number of plots created by this viewer.

+
+
+getConfig()[source]
+

Return current configuration of StructureViewer instance.

+

Returns new dictionary with the following keys: +(‘executable’, ‘argstr’, ‘fileformat’)

+
+ +
+
+static getFileFormats()[source]
+

Return list of valid values for the fileformat attribute.

+
+ +
+
+plot(stru)[source]
+

Launch new structure viewer and open a temporary copy of stru.

+

stru – instance of Structure class from diffpy.structure

+

No return value. +Raise ControlConfigError if structure viewer could not be launched.

+
+ +
+
+setConfig(cfg)[source]
+

Configure StructureViewer instance using values in a dictionary.

+
+
cfg – configuration dictionary, with the same keys as returned

by getConfig(). Any other keys are ignored.

+
+
+

No return value.

+
+ +
+ +
+
+diffpy.pdfgui.control.structureviewer.getStructureViewer()[source]
+

Factory returning singleton instance of the StructureViewer class.

+
+ +
+
+

diffpy.pdfgui.control.plotter module

+
+
+class diffpy.pdfgui.control.plotter.Plotter(name=None)[source]
+

Bases: PDFComponent

+

Plots a single graph.

+

It can have multiple curves.

+
+
+class Curve(name, plotwnd, xStr, yStr, steps, ids, offset, style)[source]
+

Bases: object

+

Curve stores the information for a curve in the plot.

+

There are three ways of forming x and y data lists. +(1) r and g(r) from a single refinement are vectors by themselves +(2) A scalar data item (any item other than r and g(r)) can form a +vector if multiple timeSteps (refinement steps) are specified. +(3) A scalar data item (any item other than r and g(r)) can form a +vector if multiple refinement (multiple ids) are specified

+

name – The curve name +plotwnd – The window where the curve is drawn +xStr – Data name (string) for x axis +yStr – Data name (string) for y axis +steps – refinement step list +ids – The list of object ids that the curve is related to +offset – curve displacement in y direction +style –The drawing style of the curve +xData, yData – data to be plotted +x, y – original data for exporting (curve could be shifted) +bMultiData – if the curve data comes from multiple data objects +bMultiStep – if the curve data comes from multiple refinement step +ref – reference of curve in the plot window +initialized – if curve has been inserted +dataChanged – if curve data has changed

+
+
+draw()[source]
+

Draw the curve in the graph.

+

It will make sure the data is OK, and plot to the screen.

+
+ +
+
+notify(changedIds=None, plotwnd=None)[source]
+

Notify Curve object certain data is updated.

+

changedIds – objects to which changed data is associated with

+
+ +
+
+validate()[source]
+

Validate(self) –> check if the curve is valid.

+

Validity +is broken: +(1) when xStr or yStr doesn’t refer to a legal vector +(2) when sizes of xStr and yStr don’t match

+
+ +
+ +
+
+buildLineStyle(index=-1)[source]
+

Generate a line style.

+

index – plotting style index

+
+ +
+
+buildLineSymbolStyle(index=-1)[source]
+

Generate a linesymbol style.

+

index – plotting style index

+
+ +
+
+buildSymbolStyle(index=-1)[source]
+

Generate a symbol style.

+

index – plotting style index

+
+ +
+
+close(force=True)[source]
+

Close up the plot.

+

force – if True, close forcibly

+
+ +
+
+export(filename)[source]
+

Export current data to external file.

+

filename – the name of the file to save data

+
+ +
+
+notify(data)[source]
+

Change of the data is notified.

+

data – data object that has changed

+
+ +
+
+onWindowClose()[source]
+

Get called when self.window is closed by user.

+
+ +
+
+plot(xName, yNames, ids, shift, dry)[source]
+

Make a 2D plot.

+

xName – x data item name +yNames – list of y data item names +ids – Objects where y data items are taken from +shift – y spacing for different ids +dry – dry run

+
+ +
+
+show(bShow=None)[source]
+

Show the plot on screen.

+

bShow – True to show, False to Hide. None to toggle +return value: current status of window

+
+ +
+ +
+
+diffpy.pdfgui.control.plotter.deblank(s)[source]
+

Remove all whitespace from the given string.

+
+ +
+
+

diffpy.pdfgui.control.fitstructure module

+

Class FitStructure for storage of one phase and related fitting +parameters.

+
+
+class diffpy.pdfgui.control.fitstructure.FitStructure(name, *args, **kwargs)[source]
+

Bases: PDFStructure

+

FitStructure holds initial and refined structure and related fit +parameters. Inherited from PDFStructure.

+
+
Class data members:

symposeps – tolerance for recognizing site as symmetry position

+
+
Data members (in addition to those in PDFStructure):

owner – instance of parent Fitting (set in Organizer.add()) +initial – initial structure, same as self +refined – refined structure when available or None +constraints – dictionary of { refvar_string : Constraint_instance } +selected_pairs – string of selected pairs, by default “all-all”.

+
+

Use setSelectedPairs() and getSelectedPairs() methods +to access its value.

+
+
+
custom_spacegroup – instance of SpaceGroup which has no equivalent

in diffpy.structure.spacegroups module. This can happen +after reading from a CIF file. When equivalent space +group exists, custom_spacegroup is None.

+
+
+
+
Refinable variables: pscale, spdiameter, delta1, delta2, sratio, lat(n),

where n=1..6, x(i), y(i), z(i), occ(i), u11(i), u22(i), u33(i), +u12(i), u13(i), u23(i), where i=1..Natoms

+
+
+

Non-refinable variable: rcut, stepcut

+
+
+applyPairSelection(server, phaseidx)[source]
+

Apply pair selection for calculations of partial PDF.

+

server – instance of PdfFit engine +phaseidx – phase index in PdfFit engine starting from 1

+
+ +
+
+applyParameters(parameters)[source]
+

Evaluate constraint formulas and adjust initial PDFStructure.

+
+
parameters – dictionary of parameter indices with Parameter

instance values. Values may also be float type.

+
+
+
+ +
+
+applySymmetryConstraints(spacegroup, indices, posflag, Uijflag, sgoffset=[0, 0, 0])[source]
+

Generate symmetry constraints for positions and thermal factors. +Both positions and thermal factors may get corrected to reflect space +group symmetry. Old positional and thermal constraints get erased. New +parameter indices start at fist decade after the last used parameter.

+

spacegroup – instance of SpaceGroup from diffpy.structure +indices – list of integer indices of atoms to be expanded +posflag – required bool flag for constraining positions +Uijflag – required bool flag for Uij constrainment +sgoffset – optional offset of space group origin [0,0,0]

+
+ +
+
+changeParameterIndex(oldidx, newidx)[source]
+

Change a parameter index to a new value.

+

This will replace all instances of one parameter name with +another in this fit.

+
+ +
+
+clearRefined()[source]
+

Clear all refinement results.

+
+ +
+
+copy(other=None)[source]
+

Copy self to other. if other is None, create new instance.

+

other – reference to other object

+

returns reference to copied object

+
+ +
+
+deleteAtoms(indices)[source]
+

Removed atoms at given indices and adjust self.constraints.

+

indices – list of integer indices of atoms to be deleted

+
+ +
+
+expandAsymmetricUnit(spacegroup, indices, sgoffset=[0, 0, 0])[source]
+

Perform symmetry expansion for atoms at given indices. Temperature +factors may be corrected to reflect the symmetry. All constraints for +expanded atoms are erased with the exception of the occupancy(“occ”. +Constraints of unaffected atoms are adjusted for new positions +self.initial.

+

spacegroup – instance of SpaceGroup from diffpy.structure +indices – list of integer indices of atoms to be expanded +sgoffset – optional offset of space group origin [0,0,0]

+
+ +
+
+expandSuperCell(mno)[source]
+

Perform supercell expansion for this structure and adjust +constraints for positions and lattice parameters. New lattice +parameters are multiplied and fractional coordinates divided by +corresponding multiplier. New atoms are grouped with their source in +the original cell.

+

mno – tuple or list of three positive integer cell multipliers along +the a, b, c axis

+
+ +
+
+findParameters()[source]
+

Obtain dictionary of parameters used by self.constraints. The keys +of returned dictionary are integer parameter indices, and the values +are Parameter instances, with guessed initial values.

+

returns dictionary of indices and Parameter instances

+
+ +
+
+getData(name, step=-1)[source]
+

Get self’s data member.

+

name – data item name +step – step info, it can be:

+
+
    +
  1. a number ( -1 means latest step ): for single step

  2. +
  3. a list of numbers: for multiple steps

  4. +
  5. None: for all steps

  6. +
+
+

returns data object, be it a single number, a list, or a list of list

+
+ +
+
+getPairSelectionFlags(s=None)[source]
+

Translate string s to a list of allowed values for first and second +pair index. Raise ControlValueError for invalid syntax of s. See +setSelectedPairs() docstring for a definition of pair selection syntax.

+

s – string describing selected pairs (default: self.selected_pairs)

+

Return a dictionary with following keys:

+

firstflags – list of selection flags for first indices +secondflags – list of selection flags for second indices +fixed_pair_string – argument corrected to standard syntax

+
+ +
+
+getSelectedIndices(s)[source]
+

Indices of the atoms that match the specified selection string.

+
+
s – selection string consisting of one or more atom selection

words formatted as [!]{element|indexOrRange|all} +Example: “1:4, 7, Cl”.

+
+
+

Return a list of integers. +Raise ControlValueError for invalid selection string format.

+
+ +
+
+getSelectedPairs()[source]
+
+ +
+
+getSpaceGroup(sgname)[source]
+

Find space group in getSpaceGroupList() by short_name or number. +sgname can be non-standard in case of CIF file defined space group.

+

Return instance of SpaceGroup. Raise ValueError if sgname cannot +be found or when it is not present in getSpaceGroupList().

+
+ +
+
+getSpaceGroupList()[source]
+

Return a list of SpaceGroup instances sorted by International Tables +number.

+

When custom_spacegroup is defined, the list starts with +custom_spacegroup.

+
+ +
+
+getXNames()[source]
+

Get names of data item which can be plotted as x.

+

returns a name str list

+
+ +
+
+getYNames()[source]
+

Get names of data item which can be plotted as y.

+

returns a name str list

+
+ +
+
+insertAtoms(index, atomlist)[source]
+

Insert list of atoms before index and adjust self.constraints.

+
+
index – position in the initial structure, atoms are appended

when larger than len(self.initial).

+
+
+

atomlist – list of atom instances.

+
+ +
+
+isSpaceGroupPossible(spacegroup)[source]
+

Check if space group is consistent with lattice parameters.

+

spacegroup – instance of SpaceGroup

+

Return bool.

+
+ +
+
+load(z, subpath)[source]
+

Load structure from a zipped project file.

+

z – zipped project file +subpath – path to its own storage within project file

+
+ +
+
+obtainRefined(server, iphase)[source]
+

Upload refined phase from PdfFit server instance.

+

server – instance of PdfFit server +iphase – index of this phase in server

+
+ +
+
+read(filename, format='auto')[source]
+

Load structure from a file, raise ControlFileError for invalid or +unknown structure format. Overloads PDFStructure.read() to handle +custom_spacegroup attribute.

+

filename – file to be loaded +format – structure format such as ‘pdffit’, ‘pdb’, ‘xyz’. When

+
+

‘auto’ all available formats are tried in a row.

+
+

Return instance of StructureParser used to load the data. +See Structure.read() for more info.

+
+ +
+
+readStr(s, format='auto')[source]
+

Same as PDFStructure.readStr, but handle the custom_spacegroup data.

+

Return instance of StructureParser used to load the data. See +Structure.readStr() for more info.

+
+ +
+
+save(z, subpath)[source]
+

Save structure to a zipped project file.

+

z – zipped project file +subpath – path to its own storage within project file

+
+ +
+
+setSelectedPairs(s)[source]
+

Set the value of selected_pairs to s, raise ControlValueError when s +has invalid syntax. The selected_pairs is a comma separated list of +words formatted as.

+
+

[!]{element|indexOrRange|all}-[!]{element|indexOrRange|all}

+
+

where ‘!’ excludes the given atoms from first or second pair.

+

Examples

+

all-all all possible pairs +Na-Na only Na-Na pairs +all-all, !Na- all pairs except Na-Na (first index skips Na) +all-all, -!Na same as previous (second index skips Na) +Na-1:4 pairs of Na and first 4 atoms +all-all, !Cl-!Cl exclude any pairs containing Cl +all-all, !Cl-, -!Cl same as previous +1-all only pairs including the first atom

+

Use getPairSelectionFlags() method to get a list of included values +for first and second pair index.

+
+ +
+
+sorted_standard_space_groups = []
+
+ +
+
+symposeps = 0.001
+
+ +
+ +
+
+

diffpy.pdfgui.control.fitting module

+
+
+class diffpy.pdfgui.control.fitting.Fitting(name)[source]
+

Bases: Organizer

+

Fitting is the class to control a PdfFit process running locally. +Fitting will start a new thread to interact with the PdfFit server.

+

rw: fitness parameter +tolerancy: accuracy requirement +step: current refinement step +res: fitting result string +parameters: parameter dictionary

+
+
+CONFIGURED = 4
+
+ +
+
+CONNECTED = 2
+
+ +
+
+DONE = 8
+
+ +
+
+INITIALIZED = 1
+
+ +
+
+PAUSED = 2048
+
+ +
+
+QUEUED = 512
+
+ +
+
+RUNNING = 1024
+
+ +
+
+VOID = 256
+
+ +
+
+class Worker(fitting)[source]
+

Bases: Thread

+

Worker is the daemon thread of fitting.

+
+
+run()[source]
+

Overload function from Thread.

+
+ +
+ +
+
+appendStep(source)[source]
+

After a refinement step is done, append all data from self to the +historical storage, i.e., self.snapshots.

+

source – where to get the fitted data, in deed it’s a PdfFit2 instance

+
+ +
+
+applyParameters()[source]
+

Evaluate all constrained variables using current parameters.

+
+ +
+
+buildNameDict()[source]
+

Build up a data name dictionary, which will map data name to a +unique index.

+

The private dataNameDict has such structure: +{ ‘d_data1’:{‘Gobs’:12, ‘Gcalc’:11, ….},

+
+

‘d_data2’:{‘Gobs’:10, ‘Gcalc’:9, ….}, +… +‘p_ph1’:{‘lat(1)’:1,’lat(2)’:2, …..}, +‘p_ph1’:{‘lat(1)’:3,’lat(2)’:4, …..}, +… +‘f_fit’:{‘rw’:100, 1:101, 2:102}

+
+

}

+

The value of each sub-dict is the corresponding index of this data +item in the snapshot. +The prefix d_ p_ f_ make dataset,struc,fitname unique within the +shared name space of dictionary

+
+ +
+
+changeParameterIndex(oldidx, newidx)[source]
+

Change a parameter index to a new value.

+

This will replace all instances of one parameter name with +another in the containing fit.

+
+ +
+
+close(force=False)[source]
+

Close up the fitting in order to exit.

+

force – if force to exit

+
+ +
+
+configure()[source]
+

Configure fitting.

+
+ +
+
+copy(other=None)[source]
+

Copy self to other. if other is None, create an instance.

+

other – ref to other object +return value: reference to copied object

+
+ +
+
+getData(name, step=-1)[source]
+

Get self’s data member.

+

name – data item name +step – step info, it can be:

+
+
    +
  1. a number ( -1 means latest step ): for single step

  2. +
  3. a list of numbers: for multiple steps

  4. +
  5. None: for all steps

  6. +
+
+

returns data object, be it a single number, a list, or a list of list

+
+ +
+
+getMetaData(name)[source]
+

Get meta data value.

+

name – meta data name +returns meta data value

+
+ +
+
+getMetaDataNames()[source]
+

Return all applicable meta data names.

+
+ +
+
+getServer()[source]
+

Get a PDFfit2 instance either locally or remotely.

+
+ +
+
+getXNames()[source]
+

Get names of data item which can be plotted as x.

+

returns a name str list

+
+ +
+
+getYNames()[source]
+

Get names of data item which can be plotted as y.

+

returns a name str list

+
+ +
+
+isThreadRunning()[source]
+

Check if fitting thread is running.

+

return: True if running, False otherwise

+
+ +
+
+join()[source]
+

Wait for current fitting to finish.

+
+ +
+
+load(z, subpath)[source]
+

Load data from a zipped project file.

+

z – zipped project file +subpath – path to its own storage within project file

+

returns a tree of internal hierarchy

+
+ +
+
+outputBondAngle(struc, i, j, k)[source]
+

Output bond angle defined by atoms i, j, k. The angle is calculated +using the shortest lengths ji and jk with respect to periodic boundary +conditions.

+

struc – instance of PDFStructure +i, j, k – atom indices starting at 1

+

No return value. The result should be automatically added to +the Output Window, because all server output is sent there.

+

Raise ControlValueError for invalid indices i, j, k.

+
+ +
+
+outputBondLengthAtoms(struc, i, j)[source]
+

Output shortest bond between atoms i, j. Periodic boundary +conditions are applied to find the shortest bond.

+

struc – instance of PDFStructure +i, j – atom indices starting at 1

+

No return value. The result should be automatically added to +the Output Window, because all server output is sent there.

+

Raise ControlValueError for invalid indices i, j.

+
+ +
+
+outputBondLengthTypes(struc, a1, a2, lb, ub)[source]
+

Output all a1-a2 bond lengths within specified range.

+

struc – instance of PDFStructure +a1 – symbol of the first element in pair or “ALL” +a2 – symbol of the second element in pair or “ALL” +lb – lower bond length boundary +ub – upper bond length boundary

+

No return value. The result should be automatically added to +the Output Window, because all server output is sent there.

+

Raise ControlValueError for invalid element symbols.

+
+ +
+
+pause(bPause=None)[source]
+

Pause ( self, bPause = None ) –> pause a fitting process.

+
+
bPause – True to pause, False to restart. If None, it will figure out

by itself.

+
+
+
+ +
+
+queue(enter=True)[source]
+

Queue or dequeue self.

+

enter – True to queue, False to dequeue

+
+ +
+
+refine_step()[source]
+

Run a single step of the fit.

+

return value: True if refinement is finished, otherwise False

+
+ +
+
+resetStatus()[source]
+

Reset status back to initialized.

+
+ +
+
+run()[source]
+

Function to be run in daemon thread.

+
+ +
+
+save(z, subpath)[source]
+

Save data from a zipped project file.

+

z – zipped project file +subpath – path to its own storage within project file

+
+ +
+
+start()[source]
+

Start fitting.

+
+ +
+
+stop()[source]
+

Stop the fitting.

+
+ +
+
+stripped()[source]
+

Make a copy stripped of all unpickleable data members. +The copy should be suitable for pickling and has the +following data members removed:

+
+

controlCenter, lock, pauseEvent, thread

+
+

returns reference to stripped copy

+
+ +
+
+updateParameters()[source]
+

Update parameters dictionary from active constraints.

+

returns self.parameters

+
+ +
+ +
+
+diffpy.pdfgui.control.fitting.getEngineExceptions()[source]
+

Return a tuple of possible exceptions from diffpy.pdffit2.pdffit2.

+
+ +
+
+diffpy.pdfgui.control.fitting.handleEngineException(error, gui=None)[source]
+

Common handler of PDFfit2 engine exceptions.

+

error – instance of PDFfit2 exception +gui – reference to GUI when active

+
+ +
+
+

diffpy.pdfgui.control.pdfguicontrol module

+
+
+class diffpy.pdfgui.control.pdfguicontrol.CtrlUnpickler[source]
+

Bases: object

+

Occasionally the project file may be generated on a platform where +PYTHONPATH is not correctly set up.

+

CtrlUnpickler will transform the module path in the project file to +be relative to diffpy so that it can be safely loaded. Only +constraints and parameters need this class to un- pickle.

+
+
+static loads(s)[source]
+
+ +
+ +
+
+class diffpy.pdfgui.control.pdfguicontrol.PDFGuiControl(gui=None)[source]
+

Bases: object

+

PDFGuiControl holds all the data GUI needs to access or change It has a +container of Calculation and Fitting instances.

+

Each Calculation and Fitting has a unique name.

+
+
+class QueueManager(control)[source]
+

Bases: Thread

+
+
+run()[source]
+

Method representing the thread’s activity.

+

You may override this method in a subclass. The standard run() method +invokes the callable object passed to the object’s constructor as the +target argument, if any, with sequential and keyword arguments taken +from the args and kwargs arguments, respectively.

+
+ +
+ +
+
+add(ID, position=None)[source]
+

Add fitting/calculation to internal list.

+

Id – reference to the object to be inserted +position – where the object is to be inserted, default is last

+
+ +
+
+checkQueue()[source]
+

Find next fitting in the queue and start it.

+
+ +
+
+close(force=True)[source]
+

Close a project.

+

force – if exit forciably

+
+ +
+
+copy(src)[source]
+

Copy src object.

+

src – reference to the source object +return: reference to the copy

+
+ +
+
+enqueue(fits, enter=True)[source]
+

Enqueue or dequeue fittings.

+

fits – list of fittings to be queued/dequeued +enter – True to queue, False to dequeue

+
+ +
+
+exit()[source]
+

Exit when program finished.

+
+ +
+
+getEngineOutput()[source]
+

Get the output from the engine.

+
+ +
+
+index(ID)[source]
+

Return position index of an object in its owner list.

+

ID – ID of object +return: index

+
+ +
+
+load(projfile)[source]
+

Load project from projfile.

+

projfile – a zip file of everything

+
+ +
+
+loadDataset(targetID, filename, name=None, position=None)[source]
+

Load Dataset from a file to a Fitting.

+

targetID – reference to Fitting +name – name of the new Dataset, default is file basename +position – where the dataset is to be inserted, default is last

+

return: Dataset reference

+
+ +
+
+loadStructure(targetID, filename, name=None, position=None)[source]
+

Add blank structure to a Fitting.

+

targetID – reference to Fitting +name – name of the new Structure, default is file basename

+

return: Structure reference

+
+ +
+
+newCalculation(targetID, name, position=None)[source]
+

Insert a new instance of Calculation to a Fitting.

+

targetID – reference to Fitting +name – unique name for this Calculation +position – where Calculation is inserted, default is last place

+

return: Calculation reference

+
+ +
+
+newFitting(name, position=None)[source]
+

Insert a new instance of Fitting.

+

name – unique name for this Fitting +position – where Fitting is inserted, default is last place

+

return: Fitting reference

+
+ +
+
+newStructure(targetID, name, position=None)[source]
+

Add blank structure to a Fitting.

+

targetID – reference to Fitting +name – name of the new Structure +position – where the structure is to be inserted, default is last

+

return: Structure reference

+
+ +
+
+paste(dup, target=None, new_name=None, position=None)[source]
+

Paste copied object to target under new_name, the default new_name +will be name of src.

+

dup – reference to the copied object +target – target object where the copy should be inserted +new_name – new name to be given to the copy +position – where in the target object should the copy be inserted

+

return: reference to the pasted object

+
+ +
+
+plot(xItem, yItems, Ids, shift=1.0, dry=False)[source]
+

Make a 2D plot.

+

xItem – x data item name +yItems – list of y data item names +Ids – Objects where y data items are taken from +shift – y displacement for each curve +dry – not a real plot, only check if plot is valid

+
+ +
+
+redirectStdout()[source]
+

Redirect standard out.

+

This redirect engine output to StringIO if not done yet.

+
+ +
+
+remove(ID)[source]
+

Remove Fitting, Calculation, Dataset or Structure identified by ID.

+

ID: reference to the object to be removed +return: removed object

+
+ +
+
+rename(ID, new_name)[source]
+

Rename Fitting, Calculation, Dataset or Structure identified by ID.

+

ID: reference to the object to be renamed +new_name: new name to be given to the object

+
+ +
+
+reset()[source]
+

Clean up for a new project.

+
+ +
+
+save(projfile=None)[source]
+

Save project to projfile, default projfile is self.projfile.

+

This method first writes to a temporary file and only when +successful, it overwrites projfile with the temporary file +content. These steps prevent corruption of existing projects +should something go wrong in the middle of save. As an added +benefit, all permissions and ownership flags in an existing +projfile are preserved.

+
+ +
+
+start(IDlist)[source]
+

Execute Calculations and Fittings in IDlist.

+
+ +
+
+startQueue()[source]
+

Start queue manager.

+
+ +
+
+stop()[source]
+

Stop all Fittings.

+
+ +
+ +
+
+diffpy.pdfgui.control.pdfguicontrol.pdfguicontrol(*args, **kwargs)[source]
+

This function will return the single instance of class PDFGuiControl.

+
+ +
+
+

diffpy.pdfgui.control.parameter module

+

Class Parameter for handling one refined parameter To be stored in +Fitting.parameters { idx : parameter } dictionary.

+
+
+class diffpy.pdfgui.control.parameter.Parameter(idx, initial=0.0)[source]
+

Bases: object

+

Parameter is class for value and properties of refined parameter. +Because the initial value of Parameter may come from another Fitting, it is +accessed by setInitial(), initialStr() and initialValue() methods.

+
+
Data members:

idx – integer identifier of this parameter in PdfFit +name – optional description +refined – refined value of the parameter, float or None. +fixed – flag for fixing the parameter in refinement [False]

+
+
Private members:

__initial – stores the initial value, float, or “=fitname:idx” string +__fitrepr – None or string representation of Fitting instance

+
+
+
+
+initialStr()[source]
+

Convert initial value to string.

+

returns string in “=fitname:idx” or “%f” format

+
+ +
+
+initialValue()[source]
+

Convert initial value to float. +For linked parameters it may raise:

+
+

ControlKeyError if source Fitting does not exist +KeyError when parameter does not exist +ControlRunTimeError for self-dependent parameters

+
+

returns the initial value

+
+ +
+
+setInitial(initial)[source]
+

Set initial value to float or refined value from another Fitting.

+
+
initial – initial value, it can be something convertible to float,

Fitting reference or string in “=fitname” or +“=fitname:idx” format.

+
+
+
+ +
+ +
+
+

diffpy.pdfgui.control.pdfdataset module

+

Class PDFDataSet for experimental PDF data.

+
+
+exception diffpy.pdfgui.control.pdfdataset.PDFDataFormatError[source]
+

Bases: Exception

+

Exception class marking failure to process PDF data string.

+
+ +
+
+class diffpy.pdfgui.control.pdfdataset.PDFDataSet(name)[source]
+

Bases: PDFComponent

+

PDFDataSet is a class for experimental PDF data.

+
+
Data members:

robs – list of observed r points +Gobs – list of observed G values +drobs – list of standard deviations of robs +dGobs – list of standard deviations of Gobs +stype – scattering type, ‘X’ or ‘N’ +qmax – maximum value of Q in inverse Angstroms. Termination

+
+

ripples are neglected for qmax=0.

+
+
+
qdamp – specifies width of Gaussian damping factor in pdf_obs due

to imperfect Q resolution

+
+
+

qbroad – quadratic peak broadening factor related to dataset +spdiameter – particle diameter for shape damping function

+
+

Note: This attribute was moved to PDFStructure. +It is kept for backward compatibility when reading +PDFgui project files.

+
+

dscale – scale factor of this dataset +rmin – same as robs[0] +rmax – same as robs[-1] +filename – set to absolute path after reading from file +metadata – dictionary for other experimental conditions, such as

+
+

temperature or doping

+
+
+
Global member:

persistentItems – list of attributes saved in project file +refinableVars – set (dict) of refinable variable names.

+
+
+
+
+clear()[source]
+

Reset all data members to initial empty values.

+
+ +
+
+copy(other=None)[source]
+

Copy self to other. if other is None, create new instance.

+

other – ref to other object +returns reference to copied object

+
+ +
+
+getvar(var)[source]
+

Obtain value corresponding to PdfFit dataset variable. Used by +findParameters().

+
+
var – string representation of dataset PdfFit variable.

Possible values: qdamp, qbroad, dscale

+
+
+

returns value of var

+
+ +
+
+persistentItems = ['robs', 'Gobs', 'drobs', 'dGobs', 'stype', 'qmax', 'qdamp', 'qbroad', 'dscale', 'rmin', 'rmax', 'metadata']
+
+ +
+
+read(filename)[source]
+

Load data from PDFGetX2 or PDFGetN gr file.

+

filename – file to read from

+

returns self

+
+ +
+
+readStr(datastring)[source]
+

Read experimental PDF data from a string.

+

datastring – string of raw data

+

returns self

+
+ +
+
+refinableVars = {'dscale': None, 'qbroad': None, 'qdamp': None}
+
+ +
+
+setvar(var, value)[source]
+

Assign data member using PdfFit-style variable. Used by +applyParameters().

+
+
var – string representation of dataset PdfFit variable.

Possible values: qdamp, qbroad, dscale

+
+
+

value – new value of the variable

+
+ +
+
+write(filename)[source]
+

Write experimental PDF data to a file.

+

filename – name of file to write to

+

No return value.

+
+ +
+
+writeStr()[source]
+

String representation of experimental PDF data.

+

Return data string.

+
+ +
+ +
+
+

diffpy.pdfgui.control.organizer module

+
+
+class diffpy.pdfgui.control.organizer.Organizer(name)[source]
+

Bases: PDFComponent

+

Base class for Fitting. It holds separate lists of datasets, strucs and +calculations.

+

datasets: dataset list +strucs: structure list +calcs: calculation list

+
+
+add(id, position=None)[source]
+

Add structure/dataset/calculation.

+

id – reference to structure/dataset/calculation +position – position to insert, by default the last one

+
+ +
+
+copy(other=None)[source]
+

Copy self to other. if other is None, create an instance.

+

other – ref to other object +returns reference to copied object

+
+ +
+
+getCalculation(pos)[source]
+

Get calculation by position.

+

pos – the position of calculation in the list

+
+ +
+
+getDataSet(pos)[source]
+

Get dataset by position.

+

pos – the position of dataset in the list

+
+ +
+
+getStructure(pos)[source]
+

Get structure by position.

+

pos – the position of structure in the list

+
+ +
+
+hasCalculations()[source]
+

Check to see if there are calculations.

+
+ +
+
+hasDataSets()[source]
+

Check to see if there are datasets.

+
+ +
+
+hasStructures()[source]
+

Check to see if there are structures.

+
+ +
+
+index(id)[source]
+

Find the position of item in the list.

+

id – id of object +return : object position

+
+ +
+
+load(z, subpath)[source]
+

Load data from a zipped project file.

+

z – zipped project file +subpath – path to its own storage within project file

+

returns a tree of internal hierarchy

+
+ +
+
+organization()[source]
+

Get internal organization.

+

returns a tree of internal hierarchy

+
+ +
+
+remove(id)[source]
+

Remove structure/dataset/calculation.

+

id – reference to structure/dataset/calculation

+
+ +
+
+rename(id, newname)[source]
+

Rename structure/dataset/calculation.

+

id – reference to structure/dataset/calculation +newname – new name to be given

+
+ +
+
+save(z, subpath)[source]
+

Save data from a zipped project file.

+

z – zipped project file +subpath – path to its own storage within project file

+
+ +
+ +
+
+diffpy.pdfgui.control.organizer.spd_assigned(ds)[source]
+
+ +
+
+diffpy.pdfgui.control.organizer.spd_constrained(ds)[source]
+
+ +
+
+
+ + +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/api/diffpy.pdfgui.gui.design.html b/api/diffpy.pdfgui.gui.design.html new file mode 100644 index 00000000..8bba2bc8 --- /dev/null +++ b/api/diffpy.pdfgui.gui.design.html @@ -0,0 +1,126 @@ + + + + + + + + + diffpy.pdfgui.gui.design package — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

diffpy.pdfgui.gui.design package

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/api/diffpy.pdfgui.gui.html b/api/diffpy.pdfgui.gui.html new file mode 100644 index 00000000..12397dc4 --- /dev/null +++ b/api/diffpy.pdfgui.gui.html @@ -0,0 +1,3395 @@ + + + + + + + + + diffpy.pdfgui.gui package — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

diffpy.pdfgui.gui package

+
+

Subpackages

+ +
+
+

Submodules

+
+

diffpy.pdfgui.gui.phaseresultspanel module

+
+
+class diffpy.pdfgui.gui.phaseresultspanel.PhaseResultsPanel(*args, **kwds)[source]
+

Bases: Panel, PDFPanel

+

GUI Panel, holds phase (structure) related constraints.

+
+
+refresh()[source]
+

Refreshes wigets on the panel.

+
+ +
+ +
+
+

diffpy.pdfgui.gui.tooltips module

+

Tooltips for pdfgui panels.

+
+
+diffpy.pdfgui.gui.tooltips.isalias(s)[source]
+
+ +
+
+

diffpy.pdfgui.gui.bondlengthdialog module

+
+
+class diffpy.pdfgui.gui.bondlengthdialog.BondLengthDialog(*args, **kwds)[source]
+

Bases: Dialog

+
+
+getCtrlLetter(ctrl)[source]
+

Get the letter associated with the control.

+
+ +
+
+onCancel(event)[source]
+
+ +
+
+onComboKillFocus(event)[source]
+
+ +
+
+onOk(event)[source]
+
+ +
+
+onSpin(event)[source]
+
+ +
+
+onTextKillFocus(event)[source]
+
+ +
+
+setStructure(structure)[source]
+

Set the structure and update the widgets.

+

This must be called before the spin control boxes will be +settable to anything other than 1.

+
+ +
+ +
+
+

diffpy.pdfgui.gui.datasetresultspanel module

+
+
+class diffpy.pdfgui.gui.datasetresultspanel.DataSetResultsPanel(*args, **kwds)[source]
+

Bases: Panel, PDFPanel

+
+
+onExport(event)[source]
+
+ +
+
+refresh()[source]
+

Refresh the panel.

+
+ +
+
+setResultsData()[source]
+

Set the values in the results panel.

+

The values are taken from the results member dictionary. +dscale – float +qdamp – float +qbroad – float

+
+ +
+ +
+
+

diffpy.pdfgui.gui.phaseconfigurepanel module

+
+
+class diffpy.pdfgui.gui.phaseconfigurepanel.PhaseConfigurePanel(*args, **kwds)[source]
+

Bases: Panel, PDFPanel

+

Panel for configuring a phase.

+
+
Data members:

structure – reference to PDFStructure +_focusedText – value of a cell or textctrl before it changes +lConstraintsMap – map of TextCtrl name to parameter name +_row – row, where rightclick occurred +_col – column, where rightclick occurred

+
+
+
+
+applyCellChange(i, j, value)[source]
+

Update an atom according to a change in a cell.

+

i – cell position +j – cell position +value – new value

+
+ +
+
+applyTextCtrlChange(id, value)[source]
+

Update a structure according to a change in a TextCtrl.

+

id – textctrl id +value – new value

+
+ +
+
+fillCells(value)[source]
+

Fill cells with a given value.

+

value – string value to place into cells

+

This uses the member variable _selectedCells, a list of (i,j) tuples for +the selected cells.

+
+ +
+
+onCellChange(event)[source]
+

Update focused and selected text when a cell changes.

+
+ +
+
+onCellRightClick(event)[source]
+

Bring up right-click menu.

+
+ +
+
+onEditorShown(event)[source]
+

Capture the focused text when the grid editor is shown.

+
+ +
+
+onKey(event)[source]
+

Catch key events in the panel.

+
+ +
+
+onKillFocus(event)[source]
+

Check value of TextCtrl and update structure if necessary.

+
+ +
+
+onLabelRightClick(event)[source]
+

Bring up right-click menu.

+
+ +
+
+onPopupCopy(event)[source]
+

Copy selected cells.

+
+ +
+
+onPopupDelete(event)[source]
+

Deletes the row under mouse pointer from the grid.

+
+ +
+
+onPopupInsert(event)[source]
+

Adds rows to the grid.

+
+ +
+
+onPopupPaste(event)[source]
+

Paste previously copied cells.

+
+ +
+
+onPopupSelect(event)[source]
+

Limit cell selection to specified atom selection string.

+
+ +
+
+onPopupSpaceGroup(event)[source]
+

Create a supercell with the supercell dialog.

+
+ +
+
+onPopupSupercell(event)[source]
+

Create a supercell with the supercell dialog.

+
+ +
+
+onSelectedPairs(event)[source]
+

Check to see if the value of the selected pairs is valid.

+
+ +
+
+onSetFocus(event)[source]
+

Saves a TextCtrl value, to be compared in onKillFocus later.

+
+ +
+
+onTextCtrlKey(event)
+

Process a textCtrl key event as if the textCtrl was a grid cell.

+

This catches ESC and ENTER events in textCtrls and processes them as if the +textCtrl were a grid cell. This method can be bound to the wx.EVT_KEY_DOWN +event of any textCtrl. See phaseconfigurepanel.py in diffpy.pdfgui.gui for +an example.

+
+
ESC – Cancel the edit and highlight the text. This requires that

panel has a _focusedText attribute that stores the previous +value.

+
+
ENTER – Confirm the edit and move to the next cell (the default TAB

behavior).

+
+
+
+ +
+
+popupMenu(window, x, y)[source]
+

Creates the popup menu.

+

window – window, where to popup a menu +x – x coordinate +y – y coordinate

+
+ +
+
+refresh()[source]
+

Refreshes widgets on the panel.

+
+ +
+
+restrictConstrainedParameters()[source]
+

Set ‘read-only’ boxes that correspond to constrained parameters.

+
+ +
+ +
+
+

diffpy.pdfgui.gui.supercelldialog module

+
+
+class diffpy.pdfgui.gui.supercelldialog.SupercellDialog(*args, **kwds)[source]
+

Bases: Dialog

+
+
+getMNO()[source]
+

Get the [m, n, o] expansion parameters from the dialog.

+
+ +
+
+onCancel(event)[source]
+

Get out of here.

+
+ +
+
+onOk(event)[source]
+

Accept the expansion.

+
+ +
+ +
+
+

diffpy.pdfgui.gui.sgstructuredialog module

+
+
+class diffpy.pdfgui.gui.sgstructuredialog.SGStructureDialog(*args, **kwds)[source]
+

Bases: Dialog, PDFPanel

+
+
+getOffset()[source]
+

Get the offset.

+
+ +
+
+getSpaceGroup()[source]
+

Get the current space group.

+
+ +
+
+onCancel(event)[source]
+
+ +
+
+onKillFocus(event)[source]
+

Check value of widgets and update the dialog message.

+
+ +
+
+onOXTextEnter(event)[source]
+
+ +
+
+onOYTextEnter(event)[source]
+
+ +
+
+onOZTextEnter(event)[source]
+
+ +
+
+onOk(event)[source]
+
+ +
+
+onSGSelect(event)[source]
+
+ +
+
+onSGTextEnter(event)[source]
+
+ +
+
+setStructure(structure)[source]
+

Set the structure and update the dialog.

+
+ +
+
+updateSpaceGroupList()[source]
+

Update space group choices in combobox according to +self.structure.getSpaceGroupList().

+

Requires that structure attribute is defined.

+
+ +
+
+updateWidgets()[source]
+

Update the widgets.

+
+ +
+ +
+
+

diffpy.pdfgui.gui.sgconstraindialog module

+
+
+class diffpy.pdfgui.gui.sgconstraindialog.SGConstrainDialog(*args, **kwds)[source]
+

Bases: Dialog, PDFPanel

+
+
+getOffset()[source]
+

Get the offset.

+
+ +
+
+getPosFlag()[source]
+

Get whether the positions should be constrained.

+
+ +
+
+getSpaceGroup()[source]
+

Get the current space group.

+
+ +
+
+getTempFlag()[source]
+

Get whether the positions should be constrained.

+
+ +
+
+onCancel(event)[source]
+
+ +
+
+onKillFocus(event)[source]
+

Check value of widgets and update the dialog message.

+
+ +
+
+onOXTextEnter(event)[source]
+
+ +
+
+onOYTextEnter(event)[source]
+
+ +
+
+onOZTextEnter(event)[source]
+
+ +
+
+onOk(event)[source]
+
+ +
+
+onPosFlag(event)[source]
+
+ +
+
+onSGSelect(event)[source]
+
+ +
+
+onSGTextEnter(event)[source]
+
+ +
+
+onTempFlag(event)[source]
+
+ +
+
+setStructure(structure)[source]
+

Set the structure and update the widgets.

+
+ +
+
+updateSpaceGroupList()[source]
+

Update space group choices in combobox according to +self.structure.getSpaceGroupList().

+

Requires that structure attribute is defined.

+
+ +
+
+updateWidgets()[source]
+

Update the widgets.

+
+ +
+ +
+
+

diffpy.pdfgui.gui.bondangledialog module

+
+
+class diffpy.pdfgui.gui.bondangledialog.BondAngleDialog(*args, **kwds)[source]
+

Bases: Dialog, PDFPanel

+
+
+getCtrlLetter(ctrl)[source]
+

Get the letter associated with the control.

+
+ +
+
+onCancel(event)[source]
+
+ +
+
+onOk(event)[source]
+
+ +
+
+onSpin(event)[source]
+

Handle atom selection events.

+

This makes sure that no two controls can have the same value.

+
+ +
+
+setStructure(structure)[source]
+

Set the structure and update the widgets.

+

This must be called before the spin control boxes will be +settable to anything other than 1.

+
+ +
+ +
+
+

diffpy.pdfgui.gui.adddatapanel module

+
+
+class diffpy.pdfgui.gui.adddatapanel.AddDataPanel(*args, **kwds)[source]
+

Bases: Panel, PDFPanel

+

Panel for adding or changing data.

+

Data members: +Several items must be known to this panel so it knows where to try to insert +the dataset. +entrypoint – The FitTree item id from which we entered this panel. +entryfit – The parent of the new dataset. +entryset – The dataset below which to place the new set. This can be

+
+

None, which means the new dataset is appended to the end of +the entryfit.

+
+
+
+onCancel(event)[source]
+

Cancel this addition.

+

Go back to the last panel.

+
+ +
+
+onOpen(event)[source]
+

Add a dataset to the tree from a file.

+
+ +
+
+readConfiguration()[source]
+

Read the ‘DATASET’ configuration.

+

In the ‘DATASET’ section of the project ConfigurationParser the +following is set by this panel.

+
+
‘last’ – The last dataset file added to the project. This is

stored in the class variable fullpath.

+
+
+
+ +
+
+refresh()[source]
+

Check the necessary tree nodes and bold text the entry point.

+

Update the configuration

+
+ +
+
+updateConfiguration()[source]
+

Update the configuration for the ‘DATASET’.

+
+ +
+ +
+
+

diffpy.pdfgui.gui.phaseconstraintspanel module

+
+
+class diffpy.pdfgui.gui.phaseconstraintspanel.PhaseConstraintsPanel(*args, **kwds)[source]
+

Bases: Panel, PDFPanel

+
+
+applyCellChange(i, j, value)[source]
+

Update an atom according to a change in a cell.

+

i – cell position +j – cell position +value – new value

+

returns the new value stored in the data object, or None if value is +somehow invalid.

+
+ +
+
+applyTextCtrlChange(id, value)[source]
+

Update a structure according to a change in a TextCtrl.

+

id – textctrl id +value – new value

+
+ +
+
+fillCells(value)[source]
+

Fill cells with a given value.

+

value – string value to place into cells

+

This uses the member variable _selectedCells, a list of (i,j) tuples for +the selected cells.

+
+ +
+
+onCellChange(event)[source]
+

Update focused and selected text when a cell changes.

+
+ +
+
+onCellRightClick(event)[source]
+

Bring up right-click menu.

+
+ +
+
+onEditorShown(event)[source]
+

Capture the focused text when the grid editor is shown.

+
+ +
+
+onKey(event)[source]
+

Catch key events in the panel.

+
+ +
+
+onKillFocus(event)[source]
+

Check value of TextCtrl and update structure if necessary.

+
+ +
+
+onLabelRightClick(event)[source]
+

Bring up right-click menu.

+
+ +
+
+onPopupCopy(event)[source]
+

Copy selected cells.

+
+ +
+
+onPopupPaste(event)[source]
+

Paste previously copied cells.

+
+ +
+
+onPopupSelect(event)[source]
+

Limit cell selection to specified atom selection string.

+
+ +
+
+onPopupSpaceGroup(event)[source]
+

Create a supercell with the supercell dialog.

+
+ +
+
+onSetFocus(event)[source]
+

Saves a TextCtrl value, to be compared in onKillFocuse later.

+
+ +
+
+onTextCtrlKey(event)
+

Process a textCtrl key event as if the textCtrl was a grid cell.

+

This catches ESC and ENTER events in textCtrls and processes them as if the +textCtrl were a grid cell. This method can be bound to the wx.EVT_KEY_DOWN +event of any textCtrl. See phaseconfigurepanel.py in diffpy.pdfgui.gui for +an example.

+
+
ESC – Cancel the edit and highlight the text. This requires that

panel has a _focusedText attribute that stores the previous +value.

+
+
ENTER – Confirm the edit and move to the next cell (the default TAB

behavior).

+
+
+
+ +
+
+popupMenu(window, x, y)[source]
+

Creates the popup menu.

+

window – window, where to popup a menu +x – x coordinate +y – y coordinate

+
+ +
+
+refresh()[source]
+

Refresh wigets on the panel.

+
+ +
+
+refreshTextCtrls()[source]
+

Refreshes the TextCtrls.

+
+ +
+ +
+
+

diffpy.pdfgui.gui.temperatureseriespanel module

+
+
+class diffpy.pdfgui.gui.temperatureseriespanel.TemperatureSeriesPanel(*args, **kwds)[source]
+

Bases: Panel, PDFPanel

+
+
+fillList()[source]
+

Fill the list with the datasets.

+
+ +
+
+onAdd(event)[source]
+

Append files to the list.

+
+ +
+
+onCancel(event)[source]
+

Let’s go, but not actually do anything.

+
+ +
+
+onColClick(event)[source]
+

Sort by temperature.

+
+ +
+
+onDelete(event)[source]
+

Delete selected files from the list.

+
+ +
+
+onDown(event)[source]
+

Move an item in the list down.

+
+ +
+
+onEndLabelEdit(event)[source]
+

Update the temperature in the datasets.

+
+ +
+
+onOK(event)[source]
+

Let’s go!

+
+ +
+
+onUp(event)[source]
+

Move an item in the list up.

+
+ +
+
+refresh()[source]
+

Block out OK button if there is no fit.

+

This also blocks OK if the fit has no datasets or structures.

+
+ +
+
+treeSelectionUpdate(node)[source]
+

Set the current fit when the tree selection changes.

+
+ +
+ +
+
+

diffpy.pdfgui.gui.datasetconstraintpanel module

+
+
+class diffpy.pdfgui.gui.datasetconstraintpanel.DataSetConstraintPanel(*args, **kwds)[source]
+

Bases: Panel, PDFPanel

+
+
+onLoseFocus(event)[source]
+

Record the user’s selection for the text ctrl data.

+
+ +
+
+onSetFocus(event)[source]
+

Saves a TextCtrl value, to be compared in onKillFocus later.

+
+ +
+
+onTextCtrlKey(event)
+

Process a textCtrl key event as if the textCtrl was a grid cell.

+

This catches ESC and ENTER events in textCtrls and processes them as if the +textCtrl were a grid cell. This method can be bound to the wx.EVT_KEY_DOWN +event of any textCtrl. See phaseconfigurepanel.py in diffpy.pdfgui.gui for +an example.

+
+
ESC – Cancel the edit and highlight the text. This requires that

panel has a _focusedText attribute that stores the previous +value.

+
+
ENTER – Confirm the edit and move to the next cell (the default TAB

behavior).

+
+
+
+ +
+
+processFormula(value, parname)[source]
+

Process a formula that was entered into a textCtrl.

+
+ +
+
+refresh()[source]
+

Refresh the panel.

+
+ +
+
+setConstraintsData()[source]
+

Set the values in the constraints panel.

+

The values come from the constraints member dictionary. dscale +qdamp qbroad

+
+ +
+ +
+
+

diffpy.pdfgui.gui.journalpanel module

+
+
+class diffpy.pdfgui.gui.journalpanel.JournalPanel(*args, **kwds)[source]
+

Bases: Panel, PDFPanel

+
+
+onClose(event)[source]
+
+ +
+
+onExport(event)[source]
+

Export the journal to an external file.

+
+ +
+
+onKey(event)[source]
+

Catch Ctrl+J to close the journal.

+
+ +
+
+onText(event)[source]
+

Record anything that is written into the journal.

+
+ +
+
+refresh()[source]
+

Fill the jounalTextCtrl with the journal.

+
+ +
+ +
+
+

diffpy.pdfgui.gui.debugoptions module

+

DebugOptions class for storing guess three time what.

+

There should be exactly one instance of DebugOptions in pdfguiglobals +module.

+
+
+class diffpy.pdfgui.gui.debugoptions.DebugOptions[source]
+

Bases: object

+

DebugOptions is a place to store various debugging options. There should +be just one instance defined in pdfguiglobals module. It would be nice to +have a simple way of setting them on command line.

+
+
Options in short and long forms:
+
noed, noerrordialog – [False], disable exceptions catching and

display in ErrorReportDialog

+
+
nocf, noconfirm – boolean (default False), exit without asking to

save modified project file

+
+
pdb, pythondebugger – use python debugger to handle error exceptions

instead of ErrorReportDialog

+
+
+
+
+
+
+alldebugoptions = (('noed', 'noerrordialog'), ('nocf', 'noconfirm'), ('pdb', 'pythondebugger'))
+
+ +
+
+short2long = {'nocf': 'noconfirm', 'noed': 'noerrordialog', 'pdb': 'pythondebugger'}
+
+ +
+ +
+
+

diffpy.pdfgui.gui.fittree module

+

This module contains the FitTree object designed for use in PDFgui.

+
+
Classes:

FitTree – A tree specific to orgainizing data for pdffit

+
+
Exceptions:

FitTreeError – Exception for errors with FitTree operations.

+
+
+
+
+class diffpy.pdfgui.gui.fittree.FitTree(parent, id=-1, pos=wx.Point(-1, -1), size=wx.Size(-1, -1), style=2081, validator=<wx._core.Validator object>, name='FitTree')[source]
+

Bases: TreeCtrl

+

TreeCtrl designed to organize pdffit fits.

+

The root of the tree is hidden. Below that there are several levels +which are diagrammed below.

+

_ fit (*) +| +|____ phase (5) +|____ dataset (*) +|____ calculation (*)

+

Fits are at the top level. Under fits there are phases, datasets, and +calculations (in that order).

+

It is required that the data for each node is a dictionary. In the ‘type’ +entry of this dictionary is the node type (fit, phase, dataset, +calculation). Fit items also have a ‘cdata’ entry in their tree item +dictionary. This is the control center data associated with this node’s +branch.

+

Data members: +control – The pdfguicontrol object that interfaces between the tree

+
+

and the pdffit2 engine. The tree is a mirror of the internal +structure of the control.

+
+
+
+AddCalc(node, label, insertafter=None, makedata=True, cdata=None)[source]
+

Add a new DataSet to the tree as a child of fit.

+

node – The parent node of the calculation. Must be ‘fit’ type. +label – The label of the new node. +insertafter – The node after which to insert the new calculation. If

+
+

insertafter is None (default) the new calculation is +appended to the end of the calculation in the subtree of +the parent node.

+
+
+
makedata – Tells whether the control needs to make data for the

node (default True). If True, cdata is ignored.

+
+
cdata – Control data for the node. If False cdata is None

(default), then it is assumed that the node already has +data in the control. See ExtendProjectTree and +__InsertBranch for examples of how this is used.

+
+
+

Calculations are always placed after datasets.

+
+
Raises:
+
    +
  • FitTreeError if node is not a "fit" node.

  • +
  • FitTreeError if insertafter is not a "calculation" node.

  • +
+
+
+

Returns the id of the new node.

+
+ +
+
+AddDataSet(node, label, insertafter=None, filename=None, makedata=True, cdata=None)[source]
+

Add a new DataSet to the tree as a child of fit.

+

node – The parent node of the dataset. Must be ‘fit’ type. +label – The label of the new node. +insertafter – The node after which to insert the new dataset. If

+
+

insertafter is None (default) the new dataset is +appended to the end of the datasets in the subtree of +the parent node.

+
+

filename – The name of the file from which to load the data. +makedata – Tells whether the control needs to make data for the

+
+

node (default True). If True, cdata is ignored.

+
+
+
cdata – Control data for the node. If False cdata is None

(default), then it is assumed that the node already has +data in the control. See ExtendProjectTree and +__InsertBranch for examples of how this is used.

+
+
+

DataSets are always placed after Phases.

+
+
Raises:
+
    +
  • FitTreeError if node is not a "fit" node.

  • +
  • FitTreeError if insertafter is not a "dataset" node.

  • +
+
+
+

Returns the id of the new node.

+
+ +
+
+AddFit(fitname='Fit 1', cdata=None, paste=False)[source]
+

Append a new fit tree to the end of the current fits.

+
+
fitname – The name of the fit. This is incremented if it already

exists.

+
+
cdata – Control data for the node. If cdata is None (default),

then the control is asked to create new data.

+
+
paste – Whether or not the cdata is being pasted from another

node (default False).

+
+
+

Returns the id of the new node.

+
+ +
+
+AddPhase(node, label, insertafter=None, filename=None, makedata=True, cdata=None)[source]
+

Add a new blank Phase to the tree as a child of node.

+

node – The parent ‘fit’ node. +label – The name of the new node. +insertafter – The node after which to insert the new phase. If

+
+

insertafter is None (default) the new phase is +appended to the end of the phases in the subtree of +the parent node.

+
+
+
filename – The file from which to load the structure. If this is

None (default), a new structure is created.

+
+
makedata – Tells whether the control needs to make data for the

node (default True).

+
+
cdata – Control data for the node. If cdata is None (default),

then it is assumed that the node already has data in the +control. See ExtendProjectTree and __InsertBranch for +examples of how this is used.

+
+
+

Phases are always placed before DataSets.

+
+
Raises:
+
    +
  • FitTreeError if node is not a "fit" node.

  • +
  • FitTreeError if insertafter is not a "phase" node.

  • +
+
+
+

Returns the id of the new node.

+
+ +
+
+CopyBranch(startnode)[source]
+

Make a copy of a tree branch.

+

The branch is held in the system clipboard so it can be used in +another instance of the fittree.

+
+ +
+
+DeleteBranches(selections)[source]
+

Remove the subtree starting from the selected node(s).

+
+ +
+
+ExtendProjectTree(treelist, clear=True, paste=False)[source]
+

Extend the project tree from the treelist.

+
+
treelist – A list of control data returned by

Oraganizer.organization()

+
+
+

clear – Clear the tree before adding new nodes (default True) +paste – Whether or not the cdata is being pasted from another

+
+

node (default False).

+
+

The treelist here is of the type returned from pdfguicontrol.load. +It is a list of fit lists with the following format. +node[0] – fit object +node[1] – list of (name, dataset) tuples +node[2] – list of (name, phase) tuples +node[3] – list of (name, calculation) tuples

+

Note that node[1] should be empty if the node is a calculation.

+

Returns the last inserted fit or calculation node

+
+ +
+
+GetAllType(node)[source]
+

Get the id of each item in the tree of the same type as node.

+
+ +
+
+GetBranchName(node)[source]
+

Get the name of the branch in which node resides.

+
+ +
+
+GetCalculations(node)[source]
+

Get a list of calculations in branch.

+

node is either the fit-root or a node in the fit-branch of +interest.

+
+ +
+
+GetChildren(node)[source]
+

Get the ids of the children of a given node.

+
+ +
+
+GetClipboard()[source]
+

Get the clipboard data.

+

Returns the controldata in the clipboard, or None if the +clipboard is empty or contains the wrong type of data.

+
+ +
+
+GetControlData(node)[source]
+

Get the control center data associated with a node.

+

NOTE: The fit-root of a node holds this data. This method makes it +convenient to retrieve it.

+
+ +
+
+GetDataSets(node)[source]
+

Get a list of datasets in branch.

+

node is either the fit-root or a node in the fit-branch of +interest.

+
+ +
+
+GetFitRoot(node)[source]
+

Return the id of the fit in which the passed node resides.

+
+ +
+
+GetLastDataSet(node)[source]
+

Get the last dataset child of the fit node.

+

If there is no last dataset node, this may return the last phase +node. The purpose of getting this node is to know where to place +another node, so the actual node type is not important.

+
+ +
+
+GetLastPhase(node)[source]
+

Get the last phase child of the parent node.

+

This method is helpful in placing datasets and phases into the +fit tree. This method depends on the fact that phases are placed +before datasets in the fit tree.

+
+ +
+
+GetNodeType(node)[source]
+

Get the node type.

+

This is the “type” entry in the data dictionary of the node.

+
+ +
+
+GetNumDataSets(node)[source]
+

Get the number of datasets in a branch.

+

node – A node in the branch, or the root of the branch.

+
+ +
+
+GetNumPhases(node)[source]
+

Get the number of phases in a branch.

+

node – A node in the branch, or the root of the branch.

+
+ +
+
+GetPhases(node)[source]
+

Get a list of phase in branch.

+

node is either the fit-root or a node in the fit-branch of +interest.

+
+ +
+
+GetPositionInSubtree(node)[source]
+

Get the index if the node in its subtree.

+

For fits the position is absolute within the tree. For phases, +datasets, and calculations, the location is taken to be in +reference to the other nodes of its type. This is designed to be +compatible with the control center.

+
+ +
+
+GetSiblings(node)[source]
+

Get the ids of the siblings of a given node.

+
+ +
+
+GetTreeItemDict(node)[source]
+

Get the data dictionary of the node.

+
+ +
+
+InitializeTree()[source]
+

This initializes the tree by adding a root node.

+
+ +
+
+PasteBranch(entrypoint=None)[source]
+

Paste the branch from the clipboard into tree at the given node.

+

A certain type of branch can only be copied to specific places.

+
+
fit - A fit can be pasted to anywhere. This does not overwrite

an existing node, but simply inserts the fit into the +last available slot.

+
+
phase - A phase can be pasted from anywhere. If pasted from a

fit, it is placed at the end of the phase section of +that node. If inserted from a dataset or a calculation, +it is placed at the end of the phase section.

+
+
dataset - A dataset can be pasted from anywhere. If pasted from a

fit, the dataset is appended at the end of the other +datasets. If pasted from a dataset, the pasted set is +inserted right after that one. If pasted from a phase, +it is placed at the beginning of the dataset section. If +pasted from a calculation, it is placed at the end of +the dataset section.

+
+
calculation - A calculation can be pasted to anywhere, but it appears

at the end of the calculation section of the tree. If +pasted from a calculation node, it is inserted after +that node.

+
+
+
+
Raises:
+

FitTreeError if the entrypoint and branch type are incompatible.

+
+
+
+ +
+
+SelectAll()[source]
+

Select all nodes.

+
+ +
+
+SelectAllType(node=None)[source]
+

Select all nodes of same type as passed node.

+
+
node – Node whose type to select. If node is None (default), then

all fit nodes will be selected.

+
+
+
+ +
+
+SetControlData(node, data)[source]
+

Set the control center data associated with the node.

+

This need only be called for ‘fit’ nodes. This is the “cdata” +entry in the data dictionary of the node. It holds the object +with which the right panel interfaces. For example, for a +‘phase’ node, it contains a Structure object.

+
+ +
+
+SetNodeType(node, tp)[source]
+

Set the node type of a node.

+
+ +
+ +
+
+exception diffpy.pdfgui.gui.fittree.FitTreeError(*args)[source]
+

Bases: ControlError

+
+ +
+
+diffpy.pdfgui.gui.fittree.incrementName(name, namelist, start=1)[source]
+

Increment the name by assigning the lowest number to the end such that +the name does not appear in the namelist.

+
+ +
+
+

diffpy.pdfgui.gui.extendedplotframe module

+

The module contains extensions for GUI plot frame.

+
+
+class diffpy.pdfgui.gui.extendedplotframe.ExtendedPlotFrame(parent=None, *args, **kwargs)[source]
+

Bases: Frame

+

An extended plotting frame with a save and close button.

+

The class has a matplotlib.figure.Figure data member named ‘figure’. +It also has a matplotlib.axes.Axes data member named ‘axes’. The +normal matplotlib plot manipulations can be performed with these two +data members. See the matplotlib API at: +http://matplotlib.sourceforge.net/classdocs.html

+
+
+OnPaint(event)[source]
+
+ +
+
+UpdateStatusBar(event)[source]
+
+ +
+
+changeStyle(curveRef, style)[source]
+

Change curve style.

+

curveRef – internal reference to curves +style – style dictionary

+
+ +
+
+clear()[source]
+

Erase all curves.

+
+ +
+
+close_keys = {'cmd+w', 'ctrl+w', 'q'}
+
+ +
+
+insertCurve(xData, yData, style)[source]
+

Insert a new curve to the plot.

+

xData, yData – x, y data to used for the curve +style – the way curve should be plotted +return: internal reference to the newly added curve

+
+ +
+
+mplKeyPress(event)[source]
+

Process keyboard input in matplotlib plot window.

+

This implements a standard close-window shortcut key.

+
+ +
+
+onClose(evt)[source]
+

Close the frame.

+
+ +
+
+removeCurve(curveRef)[source]
+

Remove curve from plot.

+

curveRef – internal reference to curves

+
+ +
+
+replot()[source]
+

Officially call function in matplotlib to do drawing.

+
+ +
+
+savePlotData(evt)[source]
+

Save the data in the plot in columns.

+
+ +
+
+setTitle(wt, gt)[source]
+

Set graph labels.

+

wt – window title +gt – graph title

+
+ +
+
+setXLabel(x)[source]
+

Set label for x axis.

+

x – x label

+
+ +
+
+setYLabel(y)[source]
+

Set label for y axis.

+

y – y label

+
+ +
+
+updateData(curveRef, xData, yData)[source]
+

Update data for a existing curve.

+

curveRef – internal reference to a curve +xData, yData – x, y data to used for the curve

+
+ +
+ +
+
+class diffpy.pdfgui.gui.extendedplotframe.ExtendedToolbar(canvas)[source]
+

Bases: NavigationToolbar2Wx

+

An extended plotting toolbar with a save and close button.

+
+
+toolitems = (('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous view', 'back', 'back'), ('Forward', 'Forward to next view', 'forward', 'forward'), (None, None, None, None), ('Pan', 'Left button pans, Right button zooms\nx/y fixes axis, CTRL fixes aspect', 'move', 'pan'), ('Zoom', 'Zoom to rectangle\nx/y fixes axis', 'zoom_to_rect', 'zoom'), (None, None, None, None), ('Save', 'Save the figure', 'filesave', 'save_figure'))
+
+ +
+ +
+
+diffpy.pdfgui.gui.extendedplotframe.legendBoxProperties()[source]
+

Legend properties dictionary with keys consistent with MPL version.

+

The argument names have changed in matplotlib 0.98.5. Old arguments +do not work with later versions of matplotlib.

+

Return dictionary of legend properties.

+
+ +
+
+

diffpy.pdfgui.gui.preferencespanel module

+
+
+class diffpy.pdfgui.gui.preferencespanel.PreferencesPanel(*args, **kwds)[source]
+

Bases: Panel, PDFPanel

+
+
+onBrowse(event)[source]
+
+ +
+
+onCancel(event)[source]
+

Cancel the changes.

+

Go back to the last panel.

+
+ +
+
+onOK(event)[source]
+

Record all of the preferences and return to fitting mode.

+
+ +
+
+refresh()[source]
+

Refresh the panel.

+
+ +
+ +
+
+

diffpy.pdfgui.gui.addphasepanel module

+
+
+class diffpy.pdfgui.gui.addphasepanel.AddPhasePanel(*args, **kwds)[source]
+

Bases: Panel, PDFPanel

+

Panel for adding a phase.

+

Several items must know to this panel so it knows where to try to insert the +phase. +entrypoint – The FitTree item id from which we entered this panel.

+
+

dataset or a calculation item.

+
+

entryfit – The parent of the new dataset. +entryphase – The phase below which to place the new phase. This can be

+
+

None, which means the new phase is appended to the end of +the phase section of the entryfit.

+
+
+
+onCancel(event)[source]
+

Cancel this addition.

+

Go back to the last panel.

+
+ +
+
+onNew(event)[source]
+

Add a new item to be created from scratch.

+
+ +
+
+onOpen(event)[source]
+

Add a the new phase to the tree.

+

The phase is added as a child of entryfit, right after the +entryphase, if it exists. If entryphase is None, the new phase +is appended to the end of the children of entryfit.

+
+ +
+
+readConfiguration()[source]
+

Read the ‘PHASE’ configuration.

+

In the ‘PHASE’ section of the project ConfigurationParser the +following is set by this panel.

+
+
‘last’ – The last structure file added to the project. This is

stored in the class variable fullpath.

+
+
+
+ +
+
+refresh()[source]
+

Bold text the entrypoint on the tree.

+

This also reads the configuration.

+
+ +
+
+updateConfiguration()[source]
+

Update the configuration for the ‘DATASET’.

+
+ +
+
+validateStructure(node)[source]
+

Make sure that the structure is valid.

+
+ +
+ +
+
+

diffpy.pdfgui.gui.rseriespanel module

+
+
+class diffpy.pdfgui.gui.rseriespanel.RSeriesPanel(*args, **kwds)[source]
+

Bases: Panel, PDFPanel

+
+
+onCancel(event)[source]
+

Return to the main panel.

+
+ +
+
+onOK(event)[source]
+

Add make a temperature series and add it to the project.

+
+ +
+
+refresh()[source]
+

Block out OK button if there is no fit.

+

This also blocks OK if the fit has no datasets or phases.

+
+ +
+
+treeSelectionUpdate(node)[source]
+

Set the current fit when the tree selection changes.

+
+ +
+ +
+
+

diffpy.pdfgui.gui.fitnotebookpanel module

+
+
+class diffpy.pdfgui.gui.fitnotebookpanel.FitNotebookPanel(*args, **kwds)[source]
+

Bases: Panel, PDFPanel

+
+
+Enable(enable=True)[source]
+

Keep the notebook enabled, just not the panels.

+

outputPanel is immune from this, since it needs to be interacted +with.

+
+ +
+
+onPageChanged(event)[source]
+

Refresh the panel visible panel.

+
+ +
+
+onPageChanging(event)[source]
+
+ +
+
+refresh()[source]
+

Refresh the panels.

+
+ +
+ +
+
+

diffpy.pdfgui.gui.aboutdialog module

+
+
+class diffpy.pdfgui.gui.aboutdialog.DialogAbout(*args, **kwds)[source]
+

Bases: Dialog

+

The “About” Dialog.

+

Shows product name, current version, authors, and link to the +product page. Current version is taken from version.py

+
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+
+diffpy.pdfgui.gui.aboutdialog.launchBrowser(url)[source]
+

Launches browser and opens specified url.

+

In some cases may require BROWSER environment variable to be set up.

+

@param url: URL to open

+
+ +
+
+

diffpy.pdfgui.gui.paneltest module

+
+
+class diffpy.pdfgui.gui.paneltest.MyApp(redirect=False, filename=None, useBestVisual=False, clearSigInt=True)[source]
+

Bases: App

+
+
+OnInit(self) bool[source]
+
+ +
+ +
+
+class diffpy.pdfgui.gui.paneltest.MyFrame(*args, **kwds)[source]
+

Bases: Frame

+
+ +
+
+

diffpy.pdfgui.gui.dopingseriespanel module

+
+
+class diffpy.pdfgui.gui.dopingseriespanel.DopingSeriesPanel(*args, **kwds)[source]
+

Bases: Panel, PDFPanel

+
+
+checkConfiguration()[source]
+

Verify that the dopant and base are elements.

+

More detailed checking is done in the control method.

+
+ +
+
+fillList()[source]
+

Fill the list with the datasets.

+
+ +
+
+onAdd(event)[source]
+

Append files to the list.

+
+ +
+
+onCancel(event)[source]
+

Let’s go, but not actually do anything.

+
+ +
+
+onColClick(event)[source]
+

Sort by doping.

+
+ +
+
+onDelete(event)[source]
+

Delete selected files from the list.

+
+ +
+
+onDown(event)[source]
+

Move an item in the list down.

+
+ +
+
+onEndLabelEdit(event)[source]
+

Update the doping in the datasets.

+
+ +
+
+onOK(event)[source]
+

Let’s go!

+
+ +
+
+onUp(event)[source]
+

Move an item in the list up.

+
+ +
+
+refresh()[source]
+

Block out OK button if there is no fit.

+

This also blocks OK if the fit has no datasets or structures.

+
+ +
+
+treeSelectionUpdate(node)[source]
+

Set the current fit when the tree selection changes.

+
+ +
+ +
+
+

diffpy.pdfgui.gui.blankpanel module

+

This module contains the BlankPanel class.

+
+
+class diffpy.pdfgui.gui.blankpanel.BlankPanel(*args, **kwds)[source]
+

Bases: Panel, PDFPanel

+

A blank panel needed as a right panel in mainframe.py.

+
+
+refresh()[source]
+

Refreshes wigets of the panel.

+

This method must be overloaded in the derived class or else a +NotImplementedError will be raised when this method is called.

+
+ +
+ +
+
+

diffpy.pdfgui.gui.datasetconfigurepanel module

+
+
+class diffpy.pdfgui.gui.datasetconfigurepanel.DataSetConfigurePanel(*args, **kwds)[source]
+

Bases: Panel, PDFPanel

+
+
+onLoseFocus(event)[source]
+

Record the user’s selection for the text ctrl data.

+
+ +
+
+onSampling(event)[source]
+

Record how the data is to be sampled during the fit.

+

This does not use the event argument, so feel free to call this +method programmatically.

+
+ +
+
+onSetFocus(event)[source]
+

Saves a TextCtrl value, to be used later.

+
+ +
+
+onStype(event)[source]
+

Record the user’s selection for stype.

+
+ +
+
+onTextCtrlKey(event)
+

Process a textCtrl key event as if the textCtrl was a grid cell.

+

This catches ESC and ENTER events in textCtrls and processes them as if the +textCtrl were a grid cell. This method can be bound to the wx.EVT_KEY_DOWN +event of any textCtrl. See phaseconfigurepanel.py in diffpy.pdfgui.gui for +an example.

+
+
ESC – Cancel the edit and highlight the text. This requires that

panel has a _focusedText attribute that stores the previous +value.

+
+
ENTER – Confirm the edit and move to the next cell (the default TAB

behavior).

+
+
+
+ +
+
+refresh()[source]
+

Refresh the panel.

+
+ +
+
+restrictConstrainedParameters()[source]
+

Set ‘read-only’ boxes that correspond to constrained parameters.

+
+ +
+
+setConfigurationData()[source]
+

Set the values in the configuration panel.

+

The values come from the configuration member dictionary. +stype – ‘N’ or ‘X’ +dscale – float +qmax – float +qdamp – float +rmin – float +rmax – float +fitrmin – float +fitrmax – float +temperature – float +doping – float

+
+ +
+ +
+
+

diffpy.pdfgui.gui.errorreportdialog_control_fix module

+
+
+class diffpy.pdfgui.gui.errorreportdialog_control_fix.ErrorReportDialogControlFix(*args, **kwds)[source]
+

Bases: Dialog

+
+
+ShowModal() int[source]
+

Shows an application-modal dialog.

+
+ +
+ +
+
+class diffpy.pdfgui.gui.errorreportdialog_control_fix.MyApp(redirect=False, filename=None, useBestVisual=False, clearSigInt=True)[source]
+

Bases: App

+
+
+OnInit(self) bool[source]
+
+ +
+
+test()[source]
+

Testing code goes here.

+
+ +
+ +
+
+

diffpy.pdfgui.gui.plotpanel module

+
+
+class diffpy.pdfgui.gui.plotpanel.PlotPanel(*args, **kwds)[source]
+

Bases: Panel, PDFPanel

+
+
+enableWidgets(on=True)[source]
+

Enable or disable the widgets.

+
+ +
+
+getSelectedYVals()[source]
+

Get the y-values selected in the y-value ListCtrl.

+
+ +
+
+onEnter(event)[source]
+

Reset plot.

+
+ +
+
+onPlot(event)[source]
+

Plot some stuff.

+
+ +
+
+onReset(event)[source]
+

Reset everything.

+
+ +
+
+refresh()[source]
+

Refresh this panel.

+
+ +
+
+updateWidgets()[source]
+

Enable or disable certain widgets depending upon what is selected in +the tree and in the plotting widgets.

+
+ +
+ +
+
+

diffpy.pdfgui.gui.welcomepanel module

+
+
+class diffpy.pdfgui.gui.welcomepanel.WelcomePanel(*args, **kwds)[source]
+

Bases: Panel, PDFPanel

+
+
+refresh()[source]
+

Refreshes wigets of the panel.

+

This method must be overloaded in the derived class or else a +NotImplementedError will be raised when this method is called.

+
+ +
+ +
+
+

diffpy.pdfgui.gui.pdfpanel module

+
+
+class diffpy.pdfgui.gui.pdfpanel.PDFPanel(*args, **kwds)[source]
+

Bases: object

+

Mix-in class for all PDF gui panels.

+

This method is meant to be a secondary parent class for classed +derived from wx.Panel. It defines methods and member variables +necessary to all panels in the PDFgui.

+
+
+refresh()[source]
+

Refreshes wigets of the panel.

+

This method must be overloaded in the derived class or else a +NotImplementedError will be raised when this method is called.

+
+ +
+
+setToolTips(toolTips)[source]
+

Sets tooltips for controls.

+

@param toolTips: dictionary of the form {‘controlname’ : +‘tooltip’}

+
+ +
+ +
+
+

diffpy.pdfgui.gui.resultspanel module

+
+
+class diffpy.pdfgui.gui.resultspanel.ResultsPanel(*args, **kwds)[source]
+

Bases: Panel, PDFPanel

+
+
+refresh()[source]
+

Fill in the resultsTextCtrl with the fit results if they exist.

+
+ +
+ +
+
+

diffpy.pdfgui.gui.outputpanel module

+
+
+class diffpy.pdfgui.gui.outputpanel.OutputPanel(*args, **kwds)[source]
+

Bases: Panel, PDFPanel

+
+
+clearText()[source]
+

Clear the text from the output control.

+
+ +
+
+refresh()[source]
+

Refreshes wigets of the panel.

+

This method must be overloaded in the derived class or else a +NotImplementedError will be raised when this method is called.

+
+ +
+
+updateText(text)[source]
+

Update the text in the window.

+
+ +
+ +
+
+

diffpy.pdfgui.gui.insertrowsdialog module

+
+
+class diffpy.pdfgui.gui.insertrowsdialog.InsertRowsDialog(*args, **kwds)[source]
+

Bases: Dialog

+
+ +
+
+

diffpy.pdfgui.gui.errorreportdialog module

+
+
+class diffpy.pdfgui.gui.errorreportdialog.ErrorReportDialog(*args, **kwds)[source]
+

Bases: Dialog

+
+
+ShowModal() int[source]
+

Shows an application-modal dialog.

+
+ +
+
+onCopyErrorLog(event)[source]
+
+ +
+
+onGoogle(event)[source]
+

Handle the “Google This Error” button.

+

Search for path-independent module and function names and for +error message extracted from exception traceback.

+
+ +
+
+onURL(event)[source]
+
+ +
+ +
+
+class diffpy.pdfgui.gui.errorreportdialog.MyApp(redirect=False, filename=None, useBestVisual=False, clearSigInt=True)[source]
+

Bases: App

+
+
+OnInit(self) bool[source]
+
+ +
+
+test()[source]
+

Testing code goes here.

+
+ +
+ +
+
+

diffpy.pdfgui.gui.parameterspanel module

+
+
+class diffpy.pdfgui.gui.parameterspanel.ParametersPanel(*args, **kwds)[source]
+

Bases: Panel, PDFPanel

+

GUI Panel, parameters viewer/editor.

+
+
Data members:

parameters – parameters dictionary +_focusedText – value of a cell before it changes

+
+
+
+
+applyCellChange(row, col, value)[source]
+

Update parameters dictionary according to a change in a cell.

+

This also updates the cell, if possible, but not the grid. Changes to +the cell that may affect the grid, such as inserting text that is wider +than the column width, must be handled elsewhere.

+

row – row +col – column +value – new value

+
+ +
+
+fillCells(indices, value)[source]
+

Fill cells with a given value.

+

indices – list of (i,j) tuples representing cell coordinates +value – string value to place into cells

+
+ +
+
+getSelectedParameters()[source]
+

Get list of row values of selected cells.

+
+ +
+
+onApplyParameters(event)[source]
+
+ +
+
+onCellChange(event)[source]
+
+ +
+
+onCellLeftClick(event)[source]
+

Toggle a fix/free cell when clicked.

+
+ +
+
+onCellRightClick(event)[source]
+
+ +
+
+onEditorShown(event)[source]
+
+ +
+
+onGridRangeSelect(event)[source]
+

Handle range selections.

+

This is needed to properly handle simple left-clicking of +fix/free cells. It serves no other purpose.

+
+ +
+
+onPopupCopyRefinedToInitial(event)[source]
+

Copy refined parameter to initial value.

+
+ +
+
+onPopupFill(event)[source]
+

Fills cells selected in the grid with a new value.

+
+ +
+
+onPopupFixFree(event)[source]
+

Fixes parameters with selected cells.

+
+ +
+
+onPopupRenameParameters(event)[source]
+

Rename parameters.

+
+ +
+
+popupMenu(window, x, y)[source]
+

Opens a popup menu.

+

window – window, where to popup a menu +x – x coordinate +y – y coordinate

+
+ +
+
+refresh()[source]
+

Refreshes wigets on the panel.

+
+ +
+ +
+
+

diffpy.pdfgui.gui.datasetpanel module

+
+
+class diffpy.pdfgui.gui.datasetpanel.DataSetPanel(*args, **kwds)[source]
+

Bases: Panel, PDFPanel

+
+
+Enable(enable=True)[source]
+

Keep the notebook enabled, just not the panels.

+
+ +
+
+onNotebookChanged(event)[source]
+

Refresh the selected panel.

+
+ +
+
+refresh()[source]
+

Refreshes wigets of the panel.

+

This method must be overloaded in the derived class or else a +NotImplementedError will be raised when this method is called.

+
+ +
+
+refreshSelectedPage()[source]
+

Refresh the panel corresponding to the currently selected page.

+
+ +
+ +
+
+

diffpy.pdfgui.gui.main module

+
+
+class diffpy.pdfgui.gui.main.PDFGuiApp(redirect=False, filename=None, useBestVisual=False, clearSigInt=True)[source]
+

Bases: App

+
+
+OnInit(self) bool[source]
+
+ +
+ +
+
+diffpy.pdfgui.gui.main.main()[source]
+

Kick starter for the PDFgui graphical user interface.

+

This function is normally called from a light-weight console starter +diffpy.pdfgui.applications.pdfgui. Command line options and +arguments can be passed via cmdopts and cmdargs variables of the +pdfguiglobals module.

+
+ +
+
+

diffpy.pdfgui.gui.pdfguiglobals module

+

This module contains global parameters needed by PDFgui.

+
+
+diffpy.pdfgui.gui.pdfguiglobals.iconpath(iconfilename)[source]
+

Full path to the icon file in pdfgui installation. This function should +be used whenever GUI needs access to custom icons.

+

iconfilename – icon file name without any path

+

Return string.

+
+ +
+
+

diffpy.pdfgui.gui.phasepanelutils module

+

Common methods used in the phase panels.

+
+
+diffpy.pdfgui.gui.phasepanelutils.canCopySelectedCells(panel)[source]
+

Check to see if we can copy selected cells.

+

To be copyable, the cells must exist in a single block or there must +be a single cell selected. Note that a block that is selected by +individual cells is considered a collection of individual atoms, not +a block. This is default wxPython behavior.

+
+ +
+
+diffpy.pdfgui.gui.phasepanelutils.canPasteIntoCells(panel)[source]
+

Check if clipboard contents are formatted for grid insertion.

+

This also checks to see if the cell selection is appropriate for +pasting.

+
+ +
+
+diffpy.pdfgui.gui.phasepanelutils.copySelectedCells(panel)[source]
+

Copy block of selected cells or individual cell into clipboard.

+
+

This stores the cells as a plain text grid so that it can be copied +to and from other applications. Columns are delimited by tabs ‘ ‘. +Rows are delimited by newlines ‘

+
+

‘.

+
+ +
+
+diffpy.pdfgui.gui.phasepanelutils.float2str(x)[source]
+

Compact string representation of float.

+
+ +
+
+diffpy.pdfgui.gui.phasepanelutils.pasteIntoCells(panel)[source]
+

Paste clipboard contents into cells.

+

canPasteIntoCells must be called before this method in order to +format clipboard text for pasting.

+
+ +
+
+diffpy.pdfgui.gui.phasepanelutils.refreshGrid(panel)[source]
+

Refreshes grid on the panel.

+

This is used by phaseconfigurepanel and phaseresultspanel.

+

This method fills the grid with the contents of the structure member +variable of the panel. It is expected that the grid is named +‘gridAtoms’.

+
+ +
+
+diffpy.pdfgui.gui.phasepanelutils.refreshTextCtrls(panel)[source]
+

Refreshes the TextCtrls on the panel.

+

This is used by phaseconfigurepanel and phaseresultspanel.

+

This method updates the following TextCtrls with with contents of +the structure member variable of the panel. textCtrlA textCtrlB +textCtrlC textCtrlAlpha textCtrlBeta textCtrlGamma +textCtrlScaleFactor textCtrlDelta1 textCtrlDelta2 textCtrlSratio +textCtrlRcut textCtrlStepcut textCtrlSpdiameter

+
+ +
+
+diffpy.pdfgui.gui.phasepanelutils.showSelectAtomsDialog(panel)[source]
+

Extend or limit selection to a string atom selection.

+

panel – instance of PhaseConfigurePanel or PhaseConstraintsPanel

+

No return value.

+
+ +
+
+

diffpy.pdfgui.gui.phasenotebookpanel module

+
+
+class diffpy.pdfgui.gui.phasenotebookpanel.PhaseNotebookPanel(*args, **kwds)[source]
+

Bases: Panel, PDFPanel

+
+
+Enable(enable=True)[source]
+

Keep the notebook enabled, just not the panels.

+
+ +
+
+onNotebookPageChanged(event)[source]
+

Called after the page selection is changed.

+
+ +
+
+onNotebookPageChanging(event)[source]
+

Called during the page selection change.

+
+ +
+
+refresh()[source]
+

Refreshes the currently shown panel.

+
+ +
+ +
+
+

diffpy.pdfgui.gui.errorwrapper module

+

This module contains a function wrapper and an object wrapper that catch +control errors and shows them in an error report dialog.

+

This is used by PDFPanel and MainFrame.

+
+
+diffpy.pdfgui.gui.errorwrapper.catchFunctionErrors(obj, funcName)[source]
+

Wrap a function so its errors get transferred to a dialog.

+
+
obj – Object containing the function. It is assumed that the

object has an attribute named ‘mainFrame’, which is a +reference to the MainFrame instance, which contains +information about how and when to display errors.

+
+
+

funcName – Name of a function to wrap.

+

Returns the wrapped function

+
+ +
+
+diffpy.pdfgui.gui.errorwrapper.catchObjectErrors(obj, exclude=None)[source]
+

Wrap all functions of an object so that the exceptions are caught.

+
+
obj – Object containing the function. It is assumed that the object has an

attribute named ‘mainFrame’, which is a reference to the MainFrame +instance, which contains information about how and when to display +errors.

+
+
exclude – An iterable of additional function names to exclude. These are

excluded in addition to names in _EXCLUDED_METHODS defined above.

+
+
+

All functions starting with ‘_’ are excluded.

+
+ +
+
+

diffpy.pdfgui.gui.windowperspective module

+

This contains the default perspective for the gui window.

+
+
+

diffpy.pdfgui.gui.calculationpanel module

+
+
+class diffpy.pdfgui.gui.calculationpanel.CalculationPanel(*args, **kwds)[source]
+

Bases: Panel, PDFPanel

+
+
+onCalcRange(event)[source]
+
+ +
+
+onExport(event)[source]
+
+ +
+
+onKillFocus(event)[source]
+
+ +
+
+onSetFocus(event)[source]
+

Saves a TextCtrl value, to be used later.

+
+ +
+
+onStype(event)[source]
+
+ +
+
+onTextCtrlKey(event)
+

Process a textCtrl key event as if the textCtrl was a grid cell.

+

This catches ESC and ENTER events in textCtrls and processes them as if the +textCtrl were a grid cell. This method can be bound to the wx.EVT_KEY_DOWN +event of any textCtrl. See phaseconfigurepanel.py in diffpy.pdfgui.gui for +an example.

+
+
ESC – Cancel the edit and highlight the text. This requires that

panel has a _focusedText attribute that stores the previous +value.

+
+
ENTER – Confirm the edit and move to the next cell (the default TAB

behavior).

+
+
+
+ +
+
+refresh()[source]
+

Refresh the panel.

+
+ +
+
+setConfigurationData()[source]
+

Set the data in the panel.

+
+ +
+ +
+
+

diffpy.pdfgui.gui.mainframe module

+

This module contains the main window of PDFgui.

+
+
+class diffpy.pdfgui.gui.mainframe.MainFrame(*args, **kwds)[source]
+

Bases: Frame

+

The left pane is a FitTree (from fittree.py), the right is a dynamic +panel, accessed via the data member rightPanel, which can hold one of any +number of panels. The panels that can appear in the right pane must be +derived from PDFPanel (in pdfpanel.py) and are defined in the dynamicPanels +dictionary, which is defined in __customProperties. A panel is placed in +the right pane by passing its dynamicPanels dictionary key to the +switchRightPanel method. This method takes care of displaying the panel, +giving the data it needs, and calling its refresh() method.

+

** NODE TYPES ** +The FitTree is essential to the functionality of the Gui. +The tree contains one of five types of items: +“fit” – This represents a fit that is to be run by pdffit. +“dataset” – This represents a data for a fit. +“phase” – This represents the theoretical phases needed for a

+
+

dataset or a calculation.

+
+
+
“calculation” – This represents a calculation which is to be made from

using a configured fit.

+
+
+

Depending upon what type of item is selected in the tree, the right pane +will display the properties and configuration of that item (if in “fitting +mode”, see below.) More on these item types is given in the documentation +for the FitTree in fittree.py. See r

+

** MODES ** +The program has various modes of operation. +“fitting” – In this mode the right pane changes depending upon what

+
+

type of item is selected in the FitTree. When the +fitting button is pressed, the program is in “fitting” +mode.

+
+

“addingdata” – This mode is for adding data. +“addingphase” – This mode is for adding the phase +“config” – This mode is used for preferences and structure viewer

+
+

configuration.

+
+

“rseries” – The mode used when configuring an r-series macro. +“tseries” – The mode used when configuring a temperature series

+
+

macro.

+
+

“dseries” – The mode used when configuring a doping series macro.

+

The mode determines how the tree and other widgets react to user +interaction. The mode of the program is changed with the method setMode. +This method outright enables or disables certain widgets that should not be +used when in certain modes.

+

** DATA MEMBERS ** +dynamicPanels – The dictionary of right panels. This is used to change the

+
+
+

right panel in the method switchRightPanel. The panels held +by the dynamicPanels dictionary are listed below by their +dictionary keys:

+
+
    +
  • Miscellaneous panels:

  • +
+

“blank” – A blank panel +“rseries” – The r-series macro panel +“tseries” – The temperature series macro panel +“dseries” – The doping series macro panel +“welcome” – A welcome panel

+
    +
  • ‘fitting’ mode panels

  • +
+

“fit” – The panel for ‘fit’ nodes +“phase” – The panel for ‘phase’ nodes +“dataset” – The panel for ‘dataset’ nodes +“calculation” – The panel for ‘calculation’ nodes

+
    +
  • Panels specific to other program modes

  • +
+

“adddata” – The panel used in ‘addingdata’ mode +“addphase” – The panel used in ‘addingphase’ mode

+
    +
  • Panels for future implementation

  • +
+

“configuration” – Another ‘config’ mode panel

+
+

rightPanel – The current right panel. +fullpath – The full path to the most recently accessed project file. +workpath – The full path to the working directory. This is modified

+
+

whenever something is loaded or saved to file. It is +preserved in the current session and across new projects.

+
+
+
cP – A python SafeConfigurationParser object. This is in charge

of storing configuration information about the most recently +used files list. It is also used by addphasepanel and +adddatapanel to store their respective fullpath variables. +The code that handles the MRU files interacts directly +with cP.

+
+
mode – The current mode of the program. This is modified using the

setMode method. See the MODES section above.

+
+
+

name – The name of the program as defined in pdfguiglobals. +control – The pdfguicontrol object needed for interfacing with the

+
+

engine pdffit2 code.

+
+
+
isAltered – A Boolean flag that indicates when the program has been

altered. This should be changed with the method needsSave so +that the save menu item and toolbar button can be updated +accordingly.

+
+
runningDict – A dictionary of running fits and calculations indexed by

name. This dictionary is used to change the status colors of +running fits and to keep the user from editing a running +fit.

+
+
quitting – A boolean that is set when the program is quitting. This

flag tells the error handlers to ignore any errors that take +place during shutdown.

+
+
+
+
+checkForSave()[source]
+

Pop up a dialog if the project needs to be saved.

+

returns: +wx.ID_YES if the user chose to save the project. +wx.ID_NO if the user chose not to save the project. +wx.ID_CANCEL if they changed their mind about their action.

+
+ +
+
+disableMainMenuItems()[source]
+

Disable main menu items.

+
+ +
+
+disableSharedMenuItems(menu)[source]
+

Disable some menu items based upon what is selected in the tree.

+

menu – The menu which to apply the changes.

+

Note that this method is meant to disable only the shared menu items, +that is, those that use the same menu item Ids. These are defined in the +top part of __defineLocalIds(). Putting this logic into a single method +makes it easier to make changes with the menus. If a specific menu needs +additional logic, put that in a separate method.

+
+ +
+
+loadConfiguration()[source]
+

Load the configuration from file.

+

The MRU list is handled by the local member fileHistory, which +is a wxFileHistory object.

+
+ +
+
+lock()[source]
+
+ +
+
+makeTreeSelection(node)[source]
+

Manually select a node of the tree and update according to +selection.

+

This makes sure that the node is visible after selection.

+

If node is None, this does nothing.

+
+ +
+
+needsSave(altered=True)[source]
+

Tell the gui that the program needs to be saved.

+

This changes the state of the save menu and tool bar items.

+

altered – Whether or not the program needs saving (default True).

+
+ +
+
+onAbout(event)[source]
+
+ +
+
+onBeginLabelEdit(event)[source]
+

Veto editing of some items and in some modes.

+

The following editing attempts are Veto()’d +* Editing any item in “addingdata”, “addingphase”, or “config” mode.

+
+ +
+
+onCommunity(event)[source]
+

Open the browser and go to the diffpy-users Google Group.

+
+ +
+
+onCopy(event)[source]
+

Copy the subtree of the current selected item into the clipboard.

+
+ +
+
+onCustom(event)[source]
+

This handles the custom events sent by the control.

+
+ +
+
+onDSeries(event)[source]
+

Open up the doping series panel.

+
+ +
+
+onDefaultLayout(event)[source]
+

Place the fit tree and plot panel in default locations.

+
+ +
+
+onDelete(event)[source]
+

Remove the subtrees starting from the selected nodes.

+
+ +
+
+onDocumentation(event)[source]
+

Show information about the documentation.

+
+ +
+
+onDoubleClick(event)[source]
+

Select-all type on item double click.

+
+ +
+
+onDoubleClick2(event)[source]
+

Select-all type on item double click.

+
+ +
+
+onEndLabelEdit(event)[source]
+

Allow only certain types of renaming.

+

The following rename attempts are Veto()’d +* Giving a node the same name as a sibling. Cousins can share names. +* Giving a node the name ‘’. Everything needs a name.

+
+ +
+
+onExportNewStruct(event)[source]
+

Export a structure that was created from scratch.

+
+ +
+
+onExportPDF(event)[source]
+

Export a fit PDF.

+
+ +
+
+onExportRes(event)[source]
+

Export the results file for the selected calculation.

+
+ +
+
+onExportStruct(event)[source]
+

Export a fit structure.

+
+ +
+
+onInsCalc(event)[source]
+

Insert a new calculation item.

+

A calculation is given the name “Calculation n”, where n is the +smallest positive integer such that the name is not already +taken.

+
+ +
+
+onInsData(event)[source]
+

Insert a new dataset item.

+

This opens up the new data set panel from adddatapanel.py. That +panel is in charge of inserting a new phase. See the module for +details.

+
+ +
+
+onInsPhase(event)[source]
+

Insert a new phase item.

+

This opens up the new phase panel from addphasepanel.py. That +panel is in charge of inserting a new phase. See the module for +details.

+
+ +
+
+onKey(event)[source]
+

Catch key events in the panel.

+
+ +
+
+onMRUFile(event)[source]
+

Open a recently used file.

+
+ +
+
+onMainMenu(event)[source]
+

Prepare the main menu whenever it is activated.

+
+ +
+
+onMiddleClick(event)[source]
+

Quickplot on item middle click.

+
+ +
+
+onNew(event)[source]
+

Create a new project.

+
+ +
+
+onNewFit(event)[source]
+

Start a new fit tree.

+

A fit is given the name “Fit n”, where n is the smallest +positive integer such that the name is not already taken.

+
+ +
+
+onOpen(event)[source]
+

Open a file dialog so an existing project can be opened.

+
+ +
+
+onPaste(event)[source]
+

Paste the subtree from the clipboard into the tree.

+
+ +
+ +

Paste a copied fit and link it to the original.

+

This should only be called on a ‘fit’ node, and only if the +original ‘fit’ node, or at least one with the same name as the +original still exists in the tree.

+
+ +
+
+onPlotFStruct(event)[source]
+

Plots the phase structure.

+

Opens Atomeye and plots the structure.

+
+ +
+
+onPlotIStruct(event)[source]
+

Plots the phase structure.

+

Opens Atomeye and plots the structure.

+
+ +
+
+onPreferences(event)[source]
+

Switch the right panel to the ‘preferences’ panel.

+

The ‘preferences’ panel uses the ‘config’ mode.

+
+ +
+
+onPrintBA(event)[source]
+

Print the bond angles of a selected structure to the output +panel.

+
+ +
+
+onPrintBL(event)[source]
+

Print the bond lengths of a selected structure to the output +panel.

+
+ +
+
+onQuickPlot(event)[source]
+

Quickly plot information for the selected node.

+
+ +
+
+onQuit(event)[source]
+

Shut down gracefully.

+
+ +
+
+onRSeries(event)[source]
+

Open up the r-series panel.

+
+ +
+
+onRequest(event)[source]
+
+ +
+
+onRightClick(event)[source]
+

Bring up the right-click menu.

+

This menu can give a different menu depending upon which mode the +program is in. It can even give a different menu depending upon what +part of the tree is selected.

+

“fitting” mode +The menu appears for right-clicks both on and off of tree items. +The menu has the following items: +“New Fit” – Append a new fit from anywhere on the tree. +“Copy” – Copy a fit, phase, dataset, or calc branch +“Paste” – Paste a copied branch into the tree. Branches

+
+

of a given type can only be pasted in certain +places.

+
+

“Delete” – Delete a branch from the tree. +“Insert Phase” – Insert a phase in the phase section of a fit or

+
+

calculation branch.

+
+
+
“Insert Data Set” – Insert a dataset in the dataset section of a fit

branch.

+
+
“Insert Calculation”– Insert a calculation in the calculation section

of a fit.

+
+
+

The menu appears for right-clicks both on and off of tree items. +The menu has the following items: +“Select All” – The tree automatically selects all items of the

+
+

type the user clicked on.

+
+
+ +
+
+onRun(event)[source]
+

Run the selected fits/calculations and disable their tree entries.

+

This also runs calculations that are children of a running fit.

+
+ +
+
+onSave(event)[source]
+

Save the project to a predetermined location.

+
+ +
+
+onSaveAs(event)[source]
+

Open a save dialog so the current project can be saved.

+
+ +
+
+onSaveCalc(event)[source]
+

Export a calculated PDF.

+
+ +
+
+onShowFit(event)[source]
+

Make sure the fit tree is visible.

+
+ +
+
+onShowJournal(event)[source]
+

Bring up or hide the journal window.

+
+ +
+
+onShowOutput(event)[source]
+

Make sure the output panel is visible.

+
+ +
+
+onShowPlot(event)[source]
+

Make sure the plot panel is visible.

+
+ +
+
+onStop(event)[source]
+

Stop all fits.

+

This removes all items from the runningDict and changes the +status colors back to wxWHITE.

+
+ +
+
+onTSeries(event)[source]
+

Open up the temperature series panel.

+
+ +
+
+onTreeSelChanged(event)[source]
+

Set the click behavior for each mode.

+
+ +
+
+onTreeSelChanging(event)[source]
+

Set the click behavior for each mode.

+

Note that this doesn’t work on Windows. Be sure to build in redundancy +so that the program behaves as if this does not even get called. If the +Windows bug does not get fixed, this method will probably be +eliminated.

+
+
“addingdata” mode:
    +
  • can select nothing

  • +
+
+
“addingphase” mode:
+
    +
  • can select nothing

  • +
+
+
+
“config” mode:
    +
  • can select nothing

  • +
+
+
“rseries” mode:
    +
  • can only select fit items

  • +
+
+
“tseries” mode:
    +
  • can only select fit items

  • +
+
+
“dseries” mode:
    +
  • can only select fit items

  • +
+
+
+
+
+
+ +
+
+postEvent(type, info)[source]
+

This method is called by the control.

+

Whenever the control needs to communicate directly with the gui +it can call this method. The event is processed by onCustom and +then handled by the gui on its own terms.

+
+ +
+
+setMode(mode)[source]
+

Set the mode of the program.

+

This method takes care of any widget properties that must change when +the mode is changed. If the mode is changing due to the change in the +right panel, always call setMode before switchRightPanel.

+
+
“fitting” mode:
    +
  • treeCtrlMain is enabled

  • +
  • plotPanel panel is enabled

  • +
  • toolBar is enabled

  • +
  • menuBar is enabled

  • +
+
+
+

“addingdata” mode: +“addingphase” mode: +“config” mode:

+
+
    +
  • treeCtrlMain is disabled

  • +
  • plotPanel panel is disabled

  • +
  • toolBar is disabled

  • +
  • menuBar is disabled

  • +
+
+

“rseries” mode: +“tseries” mode: +“dseries” mode:

+
+
    +
  • treeCtrlMain is enabled

  • +
  • plotPanel panel is disabled

  • +
  • toolBar is disabled

  • +
  • menuBar is disabled

  • +
+
+
+ +
+
+setPanelSpecificData(paneltype)[source]
+

This method sets the panel specific data for the right panel.

+

This method gets panel-specific data and sends it to the rightPanel. The +different types of data assignment are listed below.

+

“fit” type: +* Give the fit object to the panel

+

“phase” type: +* initialize constraints dictionary and configuration and results +* Structure objects.

+

“dataset” type: +* initialize configuration, constraints, and results objects

+

“calculation” type: +* Give the calculation object to the panel

+

“rseries” type: +* Give the fit object to the panel

+

“tseries” type: +* Give the fit object to the panel

+

“dseries” type: +* Give the fit object to the panel

+
+ +
+
+showMessage(info, title='PDF Control Error')[source]
+

ShowMessage(self, info) –> tell user about an exception and so on.

+

title – window title +info – message

+
+ +
+
+switchRightPanel(paneltype)[source]
+

Switch the panel which is visible in the right hand side.

+

This sets any panel-specific data and calls the refresh() method of the +new rightPanel. All right panels must be derived from wxPanel and +PDFPanel (in pdfpanel module).

+

Inputs: +paneltype – The code used in self.dynamicPanels that indicates the

+
+

panel to be displayed. If paneltype is None, the blank +panel is displayed.

+
+
+ +
+
+treeSelectionUpdate(node)[source]
+

Update the widgets based on a tree selection.

+

“fitting” mode: +* Right panel changes depending upon the type of item selected from the +tree.

+

“rseries”, “tseries”, “dseries” mode: +* The behavior is defined in the associated panel

+
+ +
+
+unlock()[source]
+
+ +
+
+updateConfiguration()[source]
+

Update the configuration information.

+

This updates the ‘MRU’ section of the configuration.

+
+ +
+
+updateFittingStatus(job)[source]
+

Update the fitting status.

+

This will alter the local member runningDict so that the running items +cannot be altered. The following status ids are defined in the fitting +module. Some are given a color which gives the user an indication of the +fit status. job is actually a fitting or a calculation object.

+

Fit status +INITIALIZED – ‘LIGHT GRAY’ +CONNECTED – ‘GREEN’ +CONFIGURED – ‘GREEN’ +DONE – ‘WHITE’

+

JOB Status +VOID +QUEUED +RUNNING +PAUSED

+
+ +
+
+updateOutput()[source]
+

Update text in outputPanel with text in stdout.

+
+ +
+
+updateTitle()[source]
+

Update the title according to the name of the current file.

+
+ +
+
+updateToolbar()[source]
+

Update the toolbar based upon the status of the program.

+
+ +
+
+writeConfiguration()[source]
+

Write the program configuration to file.

+
+ +
+ +
+
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/api/diffpy.pdfgui.gui.wxextensions.html b/api/diffpy.pdfgui.gui.wxextensions.html new file mode 100644 index 00000000..8ae5a744 --- /dev/null +++ b/api/diffpy.pdfgui.gui.wxextensions.html @@ -0,0 +1,332 @@ + + + + + + + + + diffpy.pdfgui.gui.wxextensions package — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

diffpy.pdfgui.gui.wxextensions package

+

Extensions to wxPython used in PDFgui.

+
+

Submodules

+
+

diffpy.pdfgui.gui.wxextensions.listctrls module

+

This module contains custom wxListCtrl subclasses. +AutoWidthListCtrl - A wxListCtrl object that automatically adjusts the width of +its columns. +ColumnSortListCtrl - An AutoWidthListCtrl that sorts its entries when the column +header is clicked. +KeyEventsListCtrl - A ColumnSortListCtrl that selects and item as you type its +name.

+
+
+class diffpy.pdfgui.gui.wxextensions.listctrls.AutoWidthListCtrl(parent, ID, pos=wx.Point(-1, -1), size=wx.Size(-1, -1), style=0, *args, **kwargs)[source]
+

Bases: ListCtrl, ListCtrlAutoWidthMixin

+

WxListCtrl subclass that automatically adjusts its column width.

+
+
+clearSelections()[source]
+

Clear all selections in the list.

+
+ +
+
+setSelection(itemtext=None)[source]
+

Convenience function for simple selection of a list item by label.

+
+
itemtext – The label of the item to select. If itemtext is None

(default) then all items will be deselected.

+
+
+
+ +
+ +
+
+class diffpy.pdfgui.gui.wxextensions.listctrls.ColumnSortListCtrl(parent, ID, pos=wx.Point(-1, -1), size=wx.Size(-1, -1), style=0, *args, **kwargs)[source]
+

Bases: AutoWidthListCtrl, ColumnSorterMixin

+

AutoWidthListCtrl subclass that sorts its columns when the column header +is pressed.

+

This ListCtrl requires an itemDataMap member dictionary to be +initialized before the sorting capabilities can be realized. This +dictionary simply references the ListCtrl’s entries by a unique +number. This number must be stored as the ItemData (with +SetItemData) of the entry. The member data must be in the form of a +tuple, where the tuple has a number of entries as the ListCtrl has +columns. The sorting routine sorts the items in the ListCtrl by the +entries in this tuple.

+
+
+GetListCtrl()[source]
+

This method is required by the sorter mixin.

+
+ +
+
+initializeSorter()[source]
+

Initialize the column sorter mixin after the ListCtrl is filled.

+

This method must be called whenever the itemDataMap is altered.

+
+ +
+
+makeIDM()[source]
+

This method automatically sets up the itemDataMap.

+

The itemDataMap gets filled with the current ListCtrl entries. +The itemDataMap does not update automatically when the list is +changed. To update the itemDataMap this method must be called +again. initializeSorter should be called after a call to this +method.

+
+ +
+ +
+
+class diffpy.pdfgui.gui.wxextensions.listctrls.KeyEventsListCtrl(parent, id, pos=wx.Point(-1, -1), size=wx.Size(-1, -1), style=0, *args, **kwargs)[source]
+

Bases: ColumnSortListCtrl

+

ColumnSortListCtrl that catches key events and selects the item that +matches.

+

It only searches for items in the first column.

+
+
+OnKey(evt)[source]
+
+ +
+
+OnKeyDown(evt)[source]
+
+ +
+
+findPrefix(prefix)[source]
+
+ +
+ +
+
+

diffpy.pdfgui.gui.wxextensions.validators module

+
+
+class diffpy.pdfgui.gui.wxextensions.validators.TextValidator(flag=2, allowNeg=False)[source]
+

Bases: Validator

+

This validator is designed to check text input for wxTextCtrls.

+

(It might have uses in other widgets.) It can validate for letters +only, digits only, floats only, and can allow for a negative at the +beginning of a digit string or a negative float.

+
+
+Clone() Object[source]
+

All validator classes must implement the Clone() function, which +returns an identical copy of itself.

+
+ +
+
+OnChar(event)[source]
+
+ +
+
+TransferFromWindow() bool[source]
+

This overridable function is called when the value in the window must +be transferred to the validator.

+
+ +
+
+TransferToWindow() bool[source]
+

This overridable function is called when the value associated with the +validator must be transferred to the window.

+
+ +
+
+Validate(parent) bool[source]
+

This overridable function is called when the value in the associated +window must be validated.

+
+ +
+ +
+
+

diffpy.pdfgui.gui.wxextensions.autowidthlabelsgrid module

+

This module contains AutoWidthListCtrl, a wxListCtrl object that +automatically adjusts the width of its columns.

+
+
+class diffpy.pdfgui.gui.wxextensions.autowidthlabelsgrid.AutoWidthLabelsGrid[source]
+

Bases: Grid

+

Wx grid which allows labels auto sizing.

+
+
+AutosizeLabels(rows=True, cols=False)[source]
+
+ +
+ +
+
+

diffpy.pdfgui.gui.wxextensions.textctrlutils module

+

This module contains utilities that can be used with wxTextCtrls.

+
+
+diffpy.pdfgui.gui.wxextensions.textctrlutils.textCtrlAsGridCell(panel, event)[source]
+

Process a textCtrl key event as if the textCtrl was a grid cell.

+

This catches ESC and ENTER events in textCtrls and processes them as if the +textCtrl were a grid cell. This method can be bound to the wx.EVT_KEY_DOWN +event of any textCtrl. See phaseconfigurepanel.py in diffpy.pdfgui.gui for +an example.

+
+
ESC – Cancel the edit and highlight the text. This requires that

panel has a _focusedText attribute that stores the previous +value.

+
+
ENTER – Confirm the edit and move to the next cell (the default TAB

behavior).

+
+
+
+ +
+
+

diffpy.pdfgui.gui.wxextensions.paneldialog module

+

This module contains the PanelDialog class, a simple class that turns any +panel into a dialog.

+
+
+class diffpy.pdfgui.gui.wxextensions.paneldialog.PanelDialog(*args, **kwds)[source]
+

Bases: Dialog

+

This class will turn any panel into a dialog.

+

Using this makes for quicker development and encourages the +developer to design a gui as a collection of panels, instead of a +monolithic mega-panel.

+
+
+setPanel(panel)[source]
+

Call this method to add the panel to the dialog.

+
+ +
+ +
+
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/api/diffpy.pdfgui.html b/api/diffpy.pdfgui.html new file mode 100644 index 00000000..30098487 --- /dev/null +++ b/api/diffpy.pdfgui.html @@ -0,0 +1,269 @@ + + + + + + + + + diffpy.pdfgui package — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

diffpy.pdfgui package

+

GUI for PDF simulation and structure refinement.

+
+

Subpackages

+ +
+
+

Submodules

+
+

diffpy.pdfgui.utils module

+

Small shared routines: +numericStringSort – sort list of strings according to numeric value +safeCPickleDumps – same as pickle.dumps, but safe for NaN and Inf

+
+
+diffpy.pdfgui.utils.asunicode(s)[source]
+

Convert string or bytes object to a text type.

+
+ +
+
+diffpy.pdfgui.utils.numericStringSort(lst)[source]
+

Sort list of strings inplace according to general numeric value. Each +string gets split to string and integer segments to create keys for +comparison. Signs, decimal points and exponents are ignored.

+

lst – sorted list of strings

+

No return value to highlight inplace sorting.

+
+ +
+
+diffpy.pdfgui.utils.safeCPickleDumps(obj)[source]
+

Get pickle representation of an object possibly containing NaN or Inf. +By default it uses pickle.HIGHEST_PROTOCOL, but falls back to ASCII +protocol 0 if there is SystemError frexp() exception.

+

obj – object to be pickled

+

Return pickle string.

+
+ +
+
+

diffpy.pdfgui.tui module

+

Text user interface - utilities for extracting data from project files.

+
+
+class diffpy.pdfgui.tui.LoadProject(filename=None)[source]
+

Bases: object

+

Load and access data in pdfgui project file.

+

Protected instance data:

+

_project – instance of PDFGuiControl with loaded project file.

+
+
+getCalculations(fits=None)[source]
+

Return list of all calculations contained in specified fits.

+
+
fits – optional list of Fitting objects that own datasets.

When not specified, get datasets from all fits defined +in the project.

+
+
+

Return list of Calculation objects.

+
+ +
+
+getDataSets(fits=None)[source]
+

Return a list of all datasets contained in specified fits.

+
+
fits – optional list of Fitting objects that own datasets.

When not specified, get datasets from all fits defined +in the project.

+
+
+

Return list of FitDataSet objects.

+
+ +
+
+getDopings(datasets=None)[source]
+

Extract doping values from a list of datasets.

+
+
datasets – optional list of FitDataSet objects. When not

specified, doping values are extracted from all +datasets in the project.

+
+
+

Return list of floating point values. The list may contain +None-s for datasets with undefined doping.

+
+ +
+
+getFits()[source]
+

Get all fits defined in the project file.

+

Return list of Fitting objects.

+
+ +
+
+getPhases(fits=None)[source]
+

Collect all phases contained in specified fits.

+
+
fits – optional list of Fitting objects that own datasets.

When not specified, get phases from all fits defined +in the project.

+
+
+

Return list of FitStructure objects.

+
+ +
+
+getTemperatures(datasets=None)[source]
+

Extract temperatures from a list of datasets.

+
+
datasets – optional list of FitDataSet objects. When not

specified, temperatures are extracted from all +datasets in the project.

+
+
+

Return list of floating point values. The list may contain +None-s for datasets with undefined temperature.

+
+ +
+
+load(filename)[source]
+

Load a project.

+

filename – path to PDFgui project file.

+

No return value.

+
+ +
+
+save(filename)[source]
+

Save the project.

+

filename – path where to write the PDFgui project.

+

No return value.

+
+ +
+ +
+
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/api/diffpy.pdfgui.icons.html b/api/diffpy.pdfgui.icons.html new file mode 100644 index 00000000..400bc27e --- /dev/null +++ b/api/diffpy.pdfgui.icons.html @@ -0,0 +1,121 @@ + + + + + + + + + diffpy.pdfgui.icons package — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

diffpy.pdfgui.icons package

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/disclaimer.texinfo b/disclaimer.texinfo new file mode 100644 index 00000000..acd7dba3 --- /dev/null +++ b/disclaimer.texinfo @@ -0,0 +1,11 @@ +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 +OWNER 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/doc/Makefile b/doc/Makefile deleted file mode 100644 index ebad7585..00000000 --- a/doc/Makefile +++ /dev/null @@ -1,194 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -PAPER = -BUILDDIR = build -BASENAME = $(subst .,,$(subst $() $(),,diffpy.pdfgui)) - -# User-friendly check for sphinx-build -ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) -$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) -endif - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source -# the i18n builder cannot share the environment and doctrees with the others -I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source - -.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext - -help: - @echo "Please use \`make ' where is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " singlehtml to make a single large HTML file" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " devhelp to make HTML files and a Devhelp project" - @echo " epub to make an epub" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " latexpdf to make LaTeX files and run them through pdflatex" - @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" - @echo " text to make text files" - @echo " man to make manual pages" - @echo " texinfo to make Texinfo files" - @echo " info to make Texinfo files and run them through makeinfo" - @echo " gettext to make PO message catalogs" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " xml to make Docutils-native XML files" - @echo " pseudoxml to make pseudoxml-XML files for display purposes" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - -clean: - rm -rf $(BUILDDIR)/* - -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -singlehtml: - $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml - @echo - @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." - -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." - -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." - -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/$(BASENAME).qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/$(BASENAME).qhc" - -devhelp: - $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp - @echo - @echo "Build finished." - @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/$(BASENAME)" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/$(BASENAME)" - @echo "# devhelp" - -epub: - $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub - @echo - @echo "Build finished. The epub file is in $(BUILDDIR)/epub." - -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make' in that directory to run these through (pdf)latex" \ - "(use \`make latexpdf' here to do that automatically)." - -latexpdf: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through pdflatex..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -latexpdfja: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through platex and dvipdfmx..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -text: - $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text - @echo - @echo "Build finished. The text files are in $(BUILDDIR)/text." - -man: - $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man - @echo - @echo "Build finished. The manual pages are in $(BUILDDIR)/man." - -texinfo: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo - @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." - @echo "Run \`make' in that directory to run these through makeinfo" \ - "(use \`make info' here to do that automatically)." - -info: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo "Running Texinfo files through makeinfo..." - make -C $(BUILDDIR)/texinfo info - @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." - -gettext: - $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale - @echo - @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." - -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." - -# Manual publishing to the gh-pages branch - -GITREPOPATH = $(shell cd $(CURDIR) && git rev-parse --git-dir) -GITREMOTE = origin -GITREMOTEURL = $(shell git config --get remote.$(GITREMOTE).url) -GITLASTCOMMIT = $(shell git rev-parse --short HEAD) - -publish: - @test -d build/html || \ - ( echo >&2 "Run 'make html' first!"; false ) - git show-ref --verify --quiet refs/heads/gh-pages || \ - git branch --track gh-pages $(GITREMOTE)/gh-pages - test -d build/gh-pages || \ - git clone -s -b gh-pages $(GITREPOPATH) build/gh-pages - cd build/gh-pages && \ - git pull $(GITREMOTEURL) gh-pages - rsync -acv --delete --exclude=.git --exclude=.rsync-exclude \ - --exclude-from=build/gh-pages/.rsync-exclude \ - --link-dest=$(CURDIR)/build/html build/html/ build/gh-pages/ - cd build/gh-pages && \ - git add --all . && \ - git diff --cached --quiet || \ - git commit -m "Sync with the source at $(GITLASTCOMMIT)." - cd build/gh-pages && \ - git push origin gh-pages diff --git a/doc/make.bat b/doc/make.bat deleted file mode 100644 index ac53d5bd..00000000 --- a/doc/make.bat +++ /dev/null @@ -1,36 +0,0 @@ -@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/doc/source/conf.py b/doc/source/conf.py deleted file mode 100644 index 47bd02ca..00000000 --- a/doc/source/conf.py +++ /dev/null @@ -1,323 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# diffpy.pdfgui documentation build configuration file, created by -# sphinx-quickstart on Thu Jan 30 15:49:41 2014. -# -# 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. - -# Attempt to import the version dynamically from GitHub tag. -try: - fullversion = version("diffpy.pdfgui") -except Exception: - fullversion = "No version found. The correct version will appear in the released version." # noqa: E501 - -import sys -import time -from importlib.metadata import version -from pathlib import Path - -# 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 Path().resolve() to make it absolute, like shown here. -# sys.path.insert(0, str(Path(".").resolve())) -sys.path.insert(0, str(Path("../..").resolve())) -sys.path.insert(0, str(Path("../../src").resolve())) - -# abbreviations -ab_authors = "Billinge Group members and community contributors" - -# -- 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.napoleon", - "sphinx.ext.todo", - "sphinx.ext.viewcode", - "sphinx.ext.intersphinx", - "sphinx_copybutton", - "sphinx_rtd_theme", - "m2r", -] - -# 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"] - -# The encoding of source files. -# source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = "index" - -# General information about the project. -project = "diffpy.pdfgui" -copyright = "%Y, The Trustees of Columbia University in the City of New York" - -# For sphinx_copybutton extension. -# Do not copy "$" for shell commands in code-blocks. -copybutton_prompt_text = r"^\$ " -copybutton_prompt_is_regexp = True - -# 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. - -fullversion = version(project) -# The short X.Y version. -version = "".join(fullversion.split(".post")[:1]) -# The full version, including alpha/beta/rc tags. -release = fullversion - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -# today = '' -today = time.strftime("%B %d, %Y", time.localtime()) -year = today.split()[-1] -# Else, today_fmt is used as the format for a strftime call. -# today_fmt = '%B %d, %Y' -# substitute YEAR in the copyright string -copyright = copyright.replace("%Y", year) - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = ["build"] - -# The reST default role (used for this markup: `text`) to use for all -# documents. -# default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -# add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -# add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -# show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = "sphinx" - -# A list of ignored prefixes for module index sorting. -modindex_common_prefix = ["diffpy.pdfgui"] - -# Display all warnings for missing links. -nitpicky = True - -# -- 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" - -html_context = { - "display_github": True, - "github_user": "diffpy", - "github_repo": "diffpy.pdfgui", - "github_version": "main", - "conf_py_path": "/doc/source/", -} - -# 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 = { - "navigation_with_keys": "true", -} - -# Add any paths that contain custom themes here, relative to this directory. -# html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -# html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -# html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -# html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -# html_favicon = None - -# 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'] - -# Add any extra paths that contain custom files (such as robots.txt or -# .htaccess) here, relative to this directory. These files are copied -# directly to the root of the documentation. -html_extra_path = [] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -# html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -# html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -# html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -# html_additional_pages = {} - -# If false, no module index is generated. -# html_domain_indices = True - -# If false, no index is generated. -# html_use_index = True - -# If true, the index is split into individual pages for each letter. -# html_split_index = False - -# If true, links to the reST sources are added to the pages. -# html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -# html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -# html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -# html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -# html_file_suffix = None - -# Output file base name for HTML help builder. -basename = "diffpy.pdfgui".replace(" ", "").replace(".", "") -htmlhelp_basename = basename + "doc" - - -# -- 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': '', -} - -# 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 = [ - ( - "index", - "diffpy.pdfgui.tex", - "diffpy.pdfgui Documentation", - ab_authors, - "manual", - ), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -# latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -# latex_use_parts = False - -# If true, show page references after internal links. -# latex_show_pagerefs = False - -# If true, show URL addresses after external links. -# latex_show_urls = False - -# Documents to append as an appendix to all manuals. -# latex_appendices = [] - -# If false, no module index is generated. -# latex_domain_indices = True - - -# -- Options for manual page output --------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ( - "index", - "diffpy.pdfgui", - "diffpy.pdfgui Documentation", - ab_authors, - 1, - ) -] - -# If true, show URL addresses after external links. -# man_show_urls = False - - -# -- 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 = [ - ( - "index", - "diffpy.pdfgui", - "diffpy.pdfgui Documentation", - ab_authors, - "diffpy.pdfgui", - "One line description of project.", - "Miscellaneous", - ), -] - -# Documents to append as an appendix to all manuals. -# texinfo_appendices = [] - -# If false, no module index is generated. -# texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -# texinfo_show_urls = 'footnote' - -# If true, do not generate a @detailmenu in the "Top" node's menu. -# texinfo_no_detailmenu = False - - -# Example configuration for intersphinx: refer to the Python standard library. -# intersphinx_mapping = {'http://docs.python.org/': None} diff --git a/doc/source/examples.rst b/doc/source/examples.rst deleted file mode 100644 index 1bdc7530..00000000 --- a/doc/source/examples.rst +++ /dev/null @@ -1,391 +0,0 @@ -.. _examples: - -Examples -######## - -=================== -Sequential fitting -=================== - ---------- -r series ---------- - -It is sometimes desired to understand how structure changes as a -function of length-scale, for example, if there is local symmetry -breaking in a structure. In this case it may be desired to -carry outa series of refinements that differ one from another by the -corresponding fitting ranges. -PDFgui has a pre-written macro that automates the setup of this type of -refinement. - - -1. Create a fit as in :ref:`lesson1`. - -2. Select the fit from the fit tree. From the “Fits” menu, select Macros, and - choose “r-Series” option. The Current Action panel will display following - setting requirements - -3. type "5" for the first upper limit, "20" for the last upper limit, and the - step of "5" Angstroms. Leave the second row blank. - -4. click “OK” in the current action panel and 4 new fits with desired - incremental limits are generated below the original fit. - - .. figure:: images/fig3-05.png - :align: center - :figwidth: 100% - - Figure 2.1: Appearance of the setup panel for specifying an - incremental r-series fit conditions. - - - The first row deals with the incremental setup of the upper r of the - refinements. The user should specify the first and the last fit maximum - r-value, and corresponding step (increment), all in units of Angstroms. - - In the second row, information is needed to specify the lower r refinement - limit. Again, the user sets the first and the last value, and step. This - allows for a box car of either fixed or variable width to be defined. If - the second row is left blank, the corresponding refinement series will be - with incremental maximum r only, and fixed lower limit. - -5. Select all four of them and execute the refinement. Once the sequence is - done, you can review the results using the plot control. - - - -.. _temperature-series: ------------------- -temperature series ------------------- - -Frequently, one must handle a large number of data sets originating from a -single sample collected at various temperatures. One of the common modeling -schemes in such cases is to perform sequential fitting of such data series, -which is known to yield well behaved modeling parameters. - -Input files: - -- :download:`Temperature data series ` containing: - - 1. a temperature series of data collected on LaMnO3 at various - temperatures from 300 K to 1150 K. - 2. a template project named ``lmo-template.dpp``. - -LaMnO3 exhibits Jahn-Teller (JT) order-disorder phase transition just above -700 K, where the long range orbital order is lost at high temperature, but -the local JT distortion survives. The formal space group does not change at -this transition. - -The data collected at NPDF instrument at LANSCE at Los Alamos National -Laboratory. The project consists of a fit called lmo-pbnm , which will serve -as a template and which contains *Pbnm* phase of LaMnO3 and a 300 K data set. -The fit refinement is set up to cover 1.7-19.5 Angstroms range, and all the -parameter values are set to their converged values for this temperature. The -fit setup uses isotropic ADPs for all atomic sites. - - - -1. open ``lmo-template.dpp`` use "Open Project" selection from "File" menu. -2. Select Macros from the “Fit” menu on the menu bar, and choose “Temperature - Series”. The current action panel will reflect the selection. -3. Click on “Add” button. Using “Shift” and mouse-select operation you should - select all the data sets mentioned in the above list, except the 300 K one - , as this is already in the template fit, and then press “Open”. - - - .. figure:: images/fig3-06.png - :align: center - :figwidth: 100% - - Figure 2.2: Setting up a T-series sequential refinement for LaMnO3. - Ordering by temperature will ensure that the fits are linked correctly. - -4. Order the data by temperature. The data can be ordered by temperature by - clicking the “Temperature” header. - - Since the files contain meta-data, the GUI is going to pick up temperature - information from the files. User should verify that the information is - correct. - -5. Ensure that the template fit is selected on the fit tree. Click on the “OK - ” button. This will generate a sequence of linked fits in the fit tree in - the order of the temperature increase. Each fit is linked to the previous, - except for the template fit for the 300 K data - -6. Highlight all the fits in the fit tree which can be done by selecting a - fit and hitting “Ctrl”+“Shift”+“A” . - -7. start the sequential refinement by clicking |gear|. - -8. On the plot control choose the temperature for x axis, and select the Uiso - of O2 (for example atom 20) for the y axis. Clicking “Plot” will display - the plot of Uiso(20) vs T. - - - .. figure:: images/fig3-07.png - :align: center - :figwidth: 100% - - - Figure 2.3: Displaying the refinement results as a function of external - parameter: T-series refinement of LaMnO3, example of isotropic ADP of - oxygen atom on general position in *Pbnm* setting. Notable are the - offsets just above 700 K (Jahn-Teller transition), and at around 1000 K - when sample converts from orthorhombic to rhombohedral symmetry. - - -Despite quite high temperatures, an onset of the static offset above the -transition temperature is clearly marked by this parameter, as apparent in -Figure 3.7. Curious user could repeat the same T-series refinement -restricting the refinement range upper limit to say 5-6 Angstroms and observe -the outcome. The refinement sequence execution should be very quick in this -case. - - ------------------------------------ -doping series ------------------------------------ - -Fitting a series of PDF data that correspond to a set of samples with related -chemistry, such as various doping series, represents another important -sequential modeling aspect that is supported in PDFgui. - - -Input files: - -- :download:`Doping data series ` containing: - - 1. series of Ca-doped LaMnO3 samples with various Ca content data from 0 - to 0.28. - 2. a template project named ``lcmo-template.dpp``. - - -The data are collected on LaMnO3 at GEM instrument at ISIS, UK. The project -consists of a fit called lcmo-pbnm, which will serve as a template and which -contains *Pbnm* phase of LaMnO3 and a 10 K data set, x000t010q35.gr. - -The difference here with respect to the template used in the previous example -is that Ca sites are introduced in the structure, but are assigned zero -occupancy. However, existence of the Ca dopant species in the structure of -the template is essential for the macro to operate. Also, upper limit used in -Fourier transform for obtaining this set of data is 35 inverse Angstroms, in -contrast to 32 inverse Angstroms in previous example. - -1. open ``lcmo-template.dpp`` use "Open Project" selection from "File" menu. -2. Select Macros from the “Fit” menu on the menu bar, and choose "Doing series" - The current action panel will reflect the selection. - - - .. figure:: images/fig3-08.png - :align: center - :figwidth: 100% - - Figure 2.4: After loading of the Ca-doping data series of LaMnO3 system, - proper doping assignment needs to be carried out, as the doping levels - introspected from the file names in this example incorrectly reflect the - scientific situation. Note that dopant atom has to be present in the - template seed used to generate the linked sequence of fits. - - -3. Click on “Add” button. Using “Shift” and mouse-select operation you should - select all the data sets mentioned in the above list, and then press "Open" - button. - - -3. Specify the base element and dopant. Verify the doping information and fix - them by clicking on the corresponding values and simply typing in the - correct values. - - It should be noted at this point that the data files do not contain any - relevant meta-data in the file headers. the GUI fill the fields by picking - up doping information from the file names. These values should be checked - manually. - -4. Order the data by clicking the header. - -5. Ensure that the template fit is selected on the fit tree. Click on the “OK - ” button. This will generate a sequence of linked fits in the fit tree in - the order of the Ca content increase. - -6. Highlight all the fits in the fit tree which can be done by selecting a - fit and hitting “Ctrl”+“Shift”+“A” . - -After the convergence is achieved for all the fits in the fit tree, the -results can be displayed graphically such that various converged fit -parameters are plotted versus Ca content. - - - - .. figure:: images/fig3-09.png - :align: center - :figwidth: 100% - - Figure 2.5: Sequence of refined parameters, such as lattice constants, - can be plotted vs doping using PDFgui plotting facilities. Figure - features lattice parameter *b* in *Pbnm* space group setting for series - of Ca-doped LaMnO3 samples for doping concentrations between 0 and 0.28 - at 10 K temperature. - - - - -================================================= -Advanced post-processing of sequential refinement -================================================= - -While PDFgui allows to collate data from a series of sequential refinements, -there are many data query options that are not possible or very tedious with -a GUI. A particularly tedious task would be to extract bond lengths for every -temperature refined in a large series. In fact, the GUI just does not seem to -be suitable interface and things are much easier and more flexible to -accomplish with Python scripts. - -As a first example, let us assume that a converged sequential refinement from -:ref:`temperature-series` , has been saved under the same name as -*lmotemplate.ddp*. The following Python script extracts temperatures and -refined values of the lattice parameter c:: - - # python script - from diffpy.pdfgui import tui - # import the tui library - prj = tui.LoadProject('lmo-template.ddp') # read PDFgui project file - temperatures = prj.getTemperatures() - # list of temperature values - phases = prj.getPhases() - # list of phase objects - tcount = len(temperatures) - # number of temperature points - for i in range(tcount): - Ti = temperatures[i] - # get the refined lattice parameter c - ci = phases[i].r - - -Save the example above to a file, say “lmo refined c.py” and run it as:: - - python lmo_refined_c.py - -Note that the script cannot load the unmodified *lmo-template.ddp* file, -because it does not have any refinement results. - -The tutorial directory contains an advanced script -:download:`tui mno_bond_ lengths.py `, -which extracts the shortest Mn-O bond lengths from the same PDFgui project. -Please, see the comments in the script for detailed explanation. - -To learn more about the tui module and about the objects and functions that -it returns, please see the API documentation for -`diffpy.pdfgui `_ . - -Feel free to ask at the -`diffpy-users `_ -group if you need help with data extracting scripts. - - - -====================== -Nanoparticle structure -====================== - -Determining the structure of a nanoparticle is notoriously difficult. -Diffraction experiments on nanoparticle samples yield broad diffraction -patterns that are hard to analyze using conventional crystallographic -approaches. The PDF analysis of nanoparticles is becoming increasingly common. - - -The PDF signal gets damped at higher distances due to the diminished number -of pairs in the nanoparticle structure that contribute to those distances. -For certain simpler cases when nanoparticles can be assumed to have spherical -shape, characteristic parameters such as nanoparticle diameter can be obtained. - -PDFgui is capable of modeling the effect of the finite nanoparticle size -using a spherical shape factor. Relevant PDF parameter is ``spdiameter`` -which is the diameter of the nanoparticle. This parameter is highly -correlated with various other parameters one would like to refine, such as -``anisotropic ADPs``, ``scale factors``, ``correlated motion parameters`` and -so on. The refinement procedure is therefore rather delicate and the -solutions are not as robust as we are used to in cases of crystalline materials. - -To illustrate the program capabilities we present a case of CdSe nanoparticle -approx- imately 3nm in size. - -Input files: - -- :download:`Nanoparticle structure` containing: - - 1. two PDF data collected from the bulk and naoparticle material. - 2. a project named ``CdSe-nano.ddp`` - 3. a structure model named ``CdSe-wurtzite.stru`` - - -This project contains two fits: the first one is a bulk CdSe reference, and -the other pertains to the CdSe nanoparticle. For consistency the PDFs of both -bulk and nano samples were obtained using Qmax of 14 inverse Angstroms, -although the bulk material PDF could have been processed using a higher value. -Synchrotron x-ray radiation was used to obtain the data at 300 K, based on -an experiment carried out at 6-ID-D at the Advanced Photon Source at Argonne -National Laboratory. - - -The structure used for both data sets is wurtzite, -space group P63mc. From calibrations on Ni standard Qdamp value of 0.0486 was -obtained and is used here. - - -1. Refine the parameter on the bulk references. - - The fit is carried out over a ``Fit Range`` from 1.7 to 19.8 Angstroms, - using 7 parameters: lattice parameters ``a`` and ``c`` (``@1`` and ``@2`` - respectively), selenium ``z`` fractional coordinate (``@11``), isotropic - ADPs for Cd and Se (``@21`` and ``@23`` respectively), the data - ``Scale Factor`` (``@100``), and finally correlated motion related - quadratic term coefficient ``delta2`` (``@200``). - - We note that while the fit is reasonable, the values of the isotropic ADPs - are enlarged. The fit can be further improved if anisotropic ADPs are - introduced, although the z-direction related components will remain - enlarged due to the stacking disorder present in the structure. The - referent value of 5.69 for ``delta2`` will be used as a starting value for - the nanoparticle fit. - - -2. Refine the parameter on the nanoparticle. - - we will use the same starting values for all the parameters, except for - ``delta2`` and the nanoparticle diameter, ``spdiameter``. The former is set - to 5.69, and the later to 25 Angstroms. - - - In other cases an approximate value of the spherical nanoparticle size is - usually known, and it is the best to start from a reasonably good guess. - Refining the nanoparticle data reveals nanoparticle diameter of - approximately 30 Angstroms, as further illustrated in Figure 2.6. - Enlarged values of isotropic ADPs are again observed, and the fit is - reasonably good. - - - .. figure:: images/fig3-10.png - :align: center - :figwidth: 100% - - Figure 2.6: Fitting the structure of a nanoparticle: 3nm CdSe nanoparticle example. - - -Further improvements can be obtained by introducing anisotropic ADPs, where -again values related to the z-direction will remain abnormally large most -probably due to the stacking related disorder.A detailed description of this -system and successful PDF modeling can be found in this publication: -`Quantitative size-dependent structure and strain determination of CdSe nanoparticles using atomic pair distribution function analysis `_. - - -In general, a successful fitting scenario depends on particular details of a -structural prob- lem one is determined to solve. The problem of determining -the structure of a nanoparticle remains difficult. PDFgui is not intended to -necessarily provide the solution, it is rather a helpful tool in the process -of determining new details and exploring the space of possible solution -candidates, yielding success in some instances. - -.. |gear| image:: /images/gear-icon.png -.. |stop| image:: /images/stop-icon.png diff --git a/doc/source/extras.rst b/doc/source/extras.rst deleted file mode 100644 index 9a38bb37..00000000 --- a/doc/source/extras.rst +++ /dev/null @@ -1,108 +0,0 @@ -.. _extras: - -Extras -###### - -============ -PDF plotting -============ - - -Plotting capabilities of PDFgui are provided through the plot control panel -and the quick-plot icon on the tool bar. A quick-plot is created by selecting -a node in the fit tree and then clicking the quick-plot icon in the tool bar. -The same quick-plot can be created by middle-clicking on a node in the fit tree. - -The plot control allows for selection of x and y coordinates for plotting. -The **actual quantities** that could be assigned to the coordinates is -determined by selection of either ``Fit``, or ``Phase``, or ``Data`` on the -fit tree. The choices for x and y coordinates varies depending on what is -selected on the fit tree. **Special options** like *index*, *temperature* and -*doping* are available as choices for x in cases of plotting multiple fit -results from sequential fitting protocols. The **plot window** provides -essential functionality such as *zoom*, *pan*, *cursor* *coordinate tracking -*, and *shifts*. Features such as *saving*, *exporting* and *printing* are -also available. - -The principal intent of the plotting functionality is to allow quick access -to the fitting results to enhance the scientific process. If ``Data`` is -selected on the fit tree, the user can plot various aspects of the PDF -function, such as data, model and difference PDF profiles as a function of -inter-atomic distance r. If the ``Fit`` or the ``Phase`` are selected, then -various parameters, both structural and internal can be plotted instead. - - -Since several formal plotting examples were given through the tutorial -exercise, and having simplicity of usage in mind, no other plotting examples -are provided, hoping that the usage is sufficiently simple for users to -master individually with ease. An example plot of Rw vs refinement step is -shown in Figure 3.1 for Ni example. - - - - .. figure:: images/fig4-01.png - :align: center - :figwidth: 100% - - Figure 3.1: Plotting window featuring Rw vs refinement step for Ni - example. The basic functionality for manipulating the plot is provided - through icons on the tool bar of the plotting window. - - - -======================== -Displaying the structure -======================== - -PDFgui can visualize 3D structures by displaying them with an external -visualization program. The visualization program needs to be specified -together with a suitable structure format in the “Edit → Preferences” menu in -PDFgui. The structure plotting feature has been tested with the following -programs: - -=================================== =============================== -VESTA structure viewer https://jp-minerals.org/vesta/ -=================================== =============================== -PyMOL structure viewer, PDB format https://www.pymol.org -=================================== =============================== - - -With a structural visualizer available, PDFgui allows for initial or refined -structures to be visualized by passing required structural information that -program. This is achieved by highlighting a desired phase on the -``Fit Tree``, and then selecting ``Plot Initial Structure`` or -``Plot Refined Structure`` from the “Phases” drop-down menu. The quick-plot -button (or middle-click) will also invoke the structure viewer with the -refined structure, or initial structure if the refined structure does not yet -exist. The control of the visualization is dependent on the viewer used. - -An example Ni structure visualization with VESTA is shown in Figure 3.2. - - - - .. figure:: images/fig4-02.png - :align: center - :figwidth: 100% - - Figure 3.2: Using VESTA functionality (if installed on your system) - for 3D visualization of the initial and refined PDF structures: example - of Ni structure. - -================================ -Advanced usage and special needs -================================ - -The PDFgui is designed to accommodate most common modeling situations. However, -it does not encapsulate all the capabilities available within the modeling -engine, such as calculation of differential PDFs, handling atoms with special -scattering properties, etc. - -Advanced usage of PDFfit2 engine to resolve any such special modeling need -that user may have is available through usage of Python scripts in the expert -command line mode, similar to that featured in the PDFFIT program. Handling -these situations requires de-tailed knowledge of the PDFfit2 syntax based on -Python, which is beyond the scope of this user guide and will be described -elsewhere. -Refer to the `PDFfit2 API `_ -and the `diffpy-users group `_ -for help with PDFfit2 scripting. diff --git a/doc/source/images/fig4-02.png b/doc/source/images/fig4-02.png deleted file mode 100644 index 4b673ce6..00000000 Binary files a/doc/source/images/fig4-02.png and /dev/null differ diff --git a/doc/source/images/gear-icon.png b/doc/source/images/gear-icon.png deleted file mode 100644 index 56465404..00000000 Binary files a/doc/source/images/gear-icon.png and /dev/null differ diff --git a/doc/source/images/plot-icon.png b/doc/source/images/plot-icon.png deleted file mode 100644 index b7ab766a..00000000 Binary files a/doc/source/images/plot-icon.png and /dev/null differ diff --git a/doc/source/images/stop-icon.png b/doc/source/images/stop-icon.png deleted file mode 100644 index 4a0473bc..00000000 Binary files a/doc/source/images/stop-icon.png and /dev/null differ diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst deleted file mode 100644 index d13d2050..00000000 --- a/doc/source/tutorial.rst +++ /dev/null @@ -1,580 +0,0 @@ -.. _tutorial: - -Tutorial -######## - -Please, have your co-workers or students try it out and let us know if you -have any comments. We want to make it really easy for the new users to get -started with PDFgui. - -Input files: - -- :download:`Ni data ` containing: - 1. Ni-xray.gr - experimental X-ray PDF data - 2. Ni.stru - Ni f.c.c. structure in PDFfit format - -In this exercise Ni PDF data obtained using synchrotron x-ray radiation -collected at 6-ID-D at the Advanced Photon Source is used. Note that among -the exercise files there is also a file Ni-neutron.gr, obtained using neutron -radiation at the GPPD diffractometer at the IPNS facility at the Argonne -National Laboratory. Both x-ray and neutron datasets were collected at 300 K. - - -This manual will help you to get started with ``PDFgui``. We strongly -recommend that that you refer to the book `Atomic pair distribution function -analysis: a primer` by Simon J. L. Billinge, Kirsten Jensen Soham Banerjee, -Emil S. Bozin, Benjamin A. Frandsen, Maxwell W. Terban and Robert J. Koch, -Oxford: Oxford University Press, 2024. URL: -https://global.oup.com/academic/product/atomic-pair-distribution-function-analysis-9780198885801 -for much more extensive and detailed descriptions of carrying out fits with -PDFgui (and the related program diffpy-cmi). - -============= -PDFgui layout -============= - -First, open ``pdfgui``. Instructions for doing this depend on your system, -but an example would be to open a terminal, activate your pdfgui conda -environment, and type ``pdfgui`` at the prompt, or to double-click a project -file on windows. - -Once PDFgui is invoked, a PDFgui window comes up. Its layout consists of a -``Menu Bar``, a ``Tool Bar``, and a set of four panes. The menu bar contains -drop-down menus that provide various aspects of PDFgui functionality. The tool -bar features icons for commonly used operations: creating a new project, -opening an existing project, saving a project, executing a refinement or -calculation, stopping a refinement or calculation, and making a quick plot. The -four panes consist of the ``Fit Tree``, ``Plot Control``, the ``Current Action`` -pane, and the ``PDFfit2 Output`` panel. - -.. figure:: images/fig2-01.png - :align: center - :figwidth: 100% - - Figure 1.1: Appearance of a PDFgui window after a structure model is - loaded. - -The ``Fit Tree`` is used in setting up a fit protocol. The ``Plot Control`` -serves the user’s needs for graphically displaying the fits, as well as -various fit-related parameters. The content of the ``Current Action`` panel -changes as the refinement is being set up. It is a functional panel through -which the user configures the fit attributes, sets the fit constraints, -reviews the fit settings, displays fitting results, and also carries out -other setup steps. The progress of the PDFfit2 refinement engine is displayed -in the ``PDFfit2 output`` panel. - - - -All panels except the current action panel are dockable windows that can be -dragged across the screen, resized and arranged to accommodate the individual -visual needs of the user. The window layout can also be controlled via the “ -View” drop-down menu on the menu bar. An important part of the PDFgui -operativity is also conveniently available through mouse operations such as -select and right-click. - - -.. _lesson1: - -======================================= -Lesson 1: Creating simple fit of Ni PDF -======================================= - - -Procedure: - -1. Open ``pdfgui``. - -2. Create a new Fit: - - 1. In the GUI locate the ``Fit Tree`` panel. In the default layout it is - at the top left of the page. - - 2. With your mouse on that panel, right-click the mouse and select "New - Fit" from the pop-up menu. - - 3. By default, your fit will be called ``Fit 1``. To give it a more - meaningful name, left click the ``Fit 1`` name. It should open an - editable box and you can type in a name for your fit such as "Fit of - Ni structure to Ni data" - - 4. Note, an alternative workflow to create a new fit is to find ``New fit - `` under the ``Fits`` dropdown menu. - -3. Load structure model: - - 1. Carefully place your cursor on to the title of the Fit and right-click - . Select "Insert Phase" from the pop-up menu. - - 2. Click the "Open" button and navigate to and load the ``Ni.stru`` file - that you downloaded. You could select valid structure model file, a - ``.stru`` or a ``.cif`` file. - - 3. Note, an alternative workflow for adding structural models is to - select ``New Phase`` from the ``Phases`` dropdown menu. - - If you select the Phase in the ``Fit Tree`` by left clicking on it, you - will see in the right panel 3 tabs, ``Configure``, ``Constraints``, - `` Results``. As shown in the Figure 1.1. Feel free to click one these - tabs and look inside. - - - The ``Configure`` panel displays configuration information from the - structure file. The top portion contains lattice parameters, phase scale - factor, and a set of parameters intended to be used to account for - correlated atomic motion effects that typically sharpen the nearest - neighbor PDF peak. These are ``delta1``, ``delta2``, ``sratio``, and - ``rcut``. The ``spdiameter`` and ``stepcut`` parameters include scatterer - size effects in the PDF. These parameters will be described later. The - bottom part of the panel contains standard unit cell content related - information such as atomic species, their fractional coordinates, - anisotropic ADPs, and site occupancies. The ``Constraints`` panel will - hold the constraints we will set up for our fits, it should be empty now, - and the results tab will contain the results of any fit. - - - Note that what you see on the right is "Context Dependent", it depends on - what you have selected on the left. By selecting a phase on the left, the - tabs on the right contain information about that phase, and so on. - - -4. Load experimental PDF data: - - 1. As before, hover over your cursor over the title of your fit and right- - click. This time select ``Insert Data Set`` from the pop-up menu. - - 2. Navigate to and load the `Ni-xray.gr` file that you downloaded. - - Again, the right panel shows 3 tabs, now for properties of this dataset. - - - .. figure:: images/fig2-02.png - :align: center - :figwidth: 100% - - Figure 1.2: Appearance of a PDFgui window after a PDF dataset is loaded. - - The ``Configure`` panel displays configuration information from the data - file. It should be noted that depend-ing on the software used to prepare - the experimental PDF from the raw data, the file may (or may not) contain - meta-data reflecting the experimental conditions and configuration. For - example, software ``PDFgetX2`` and ``PDFgetN``, which can be used to - prepare PDFs from x-ray and neutron total scattering experiments - respectively, supply meta-data in the header oset configuration panel. - - Caution should be exercised by the user to verify that these data indeed - correspond to the experimental conditions. In the present example, x-ray - radiation is used, and so the x-ray selection is turned on for the `` - Scatterer Type``. The ``data range``, ``fit range``, - ``data scale factor``, ``maximum Q value`` used in Fourier transform to - obtain the experi- mental PDF and the experiment specific parameters are - displayed. Parameters describing experimental resolution effects, - ``Qdamp `` and ``Qbroad``, and experimental conditions, such as - `` temperature`` and ``doping`` (used for bookkeeping and for parametric - plots) are also shown. If no meta-data are present in a data file, this - information should be supplied by the user. - - Note also that the changes occurred at this stage in the plot control panel - , allowing user to plot the data. This is achieved by selecting r in the X- - choice box and Gobs (the observed :math:`G(r))` in the Y-list box and then - pressing the “Plot” button. Since no fitting has occurred so far, an - attempt to plot calculated PDF profile or a difference yields a blank plot - . The data can also be displayed by clicking the rightmost "plot" button - |plot| in the tool bar. - - -5. Define what is refined: - - Having specified the initial structure to be refined, and the data set to - be fit, we proceed to the refinement setup. The adjustments and constraint - setup are done on both the experimental data and the refined structure - levels, toggling between the corresponding ``Configure`` and - ``Constraints`` tabs. - - 1. Click on the `Ni-xray.gr` data and select the ``Configure`` tab. - - 2. Type "1.7" into the ``Fit Range`` edit box and "0.08" into the - ``Qdamp`` edit box. - - .. figure:: images/fig2-03.png - :align: center - :figwidth: 100% - - Figure 1.3: Adjusting data set related configuration. - - Since there is no physical information in the region of of r below the - nearest neighbor PDF peak position (as seen in the plot), and since this - region is often affected by noise and experimental artifacts, it is wise to - exclude it from fitting. We therefore set the value of the lower boundary - of the ``Fit range`` to 1.7. (Note that the units are Angstroms). In - addition, we set ``Qdamp parameter`` to a more realistic starting value of 0 - .08. This is an instrument-dependent parameter is typically obtained - through a conventional calibration process at each PDF experiment using a - standard sample such as Ni or Si. - - - 3. select the ``Constraints`` tab. - - 4. Type ``@1`` into the "Scale Factor" edit box and ``@2`` into the - "Qdamp" edit box. - - .. figure:: images/fig2-04.png - :align: center - :figwidth: 100% - - Figure 1.4: Setting up the refinement parameters and constraints of the - structure model. - - Here we are defining "variables" that will be refined and giving them names - variable "@1", "@2", etc. and linking them to model parameters by typing them - in the text-box associated with the parameter. So by typing ``@1`` in the - data "Scale-Factor" text box we are saying that we are logically assigning - the constraint equation ``data.scale_factor = variable("@1")``. - - - 5. Select the `Ni.stru` phase, adjusting the initial parameter values if - necessary (not done here) and proceeding to ``Constraints`` tab. - - 6. Fill "a", "b", "c" boxes with ``@3``. Fill "u11", "u22", "u33" cells - with ``@4``. - - - .. figure:: images/fig2-05.png - :align: center - :figwidth: 100% - - Figure 1.5: Setting up the refinement parameters and constraints of the - PDF data. - - When we assign the three parameters ``a``, ``b`` and ``c`` to the same - variable, ``@2``, we are implicitly ensuring that the refinement will - respect the cubic symmetry of the nickel structure and that ``a = b = c``, - because the three parameters are assigned to the same variable, so however - much ``a`` is changed in the refinement, ``b`` and ``c`` will be changed - by the same amount. Note that the variable ensures that changes to ``a``, - ``b`` and ``c`` are always the same, so we have to also ensure that the - initial values of ``a``, ``b`` and ``c`` are the same as each other to - ensure that the structure is cubic and remains so. - - Also, isotropic ADPs are assigned to all Ni atoms in the refined cell as - refinement parameter ``@4``. This can conveniently be done by highlighting - the “u11”, “u22” and “u33” cells for all four atoms, and typing ``@4`` . - - PDFgui allows us to express more complex constraint equations than - simply assigning a parameter to a variable. - In general, we can type into be Constraints tab text box any math expression: - ``f(@n1, @n2, @n3, ...)`` where - ``@n1`` stands for the fitted parameter, where it is understood that - ``n1, n2, ...`` are arbitrary positive integers. - This allows simple linking of related variables. For example, if we want - to allow a crystallographic site to contain either Ni or Pt, we don't know - how much Ni or Pt is on the site, but we want it to be always fully - occupied, we could create two lattice site entries with the same - fractional coordinates, with one assigned Ni as the element and the other - assigned Pt as the element. Then we could assign the Ni occupancy as - ``@100``. Then typing ``1-@100`` into the constraint text box of the Pt - occupancy ensures that however much the occupancy of the Ni site goes down - in a refinement, the occupancy of the Pt on that same site goes up by the - same amount. This ensures full occupancy of that site, as long - as the initial occupancies of the Ni and Pt added up to 1. - -6. Start the refinement: - - 1. Select the fit to run by left clicking the title of the fit in the - ``Fit Tree`` panel. The ``Parameters`` panel on the right shows a list - of variables that you have defined and their initial values. Each one - also has a check-box that allows you to fix them (prevent them from - varying in the subsequent refinement). Unchecked boxes mean the - variable will be refined. - - .. figure:: images/fig2-06.png - :align: center - :figwidth: 100% - - Figure 1.6: Reviewing the fit parameters and conditions. - - - 2. When you are satisfied with the configuration, click the "gear" icon - |gear| on the toolbar and watch the fit progress in the terminal window. - The refinement can be stopped prematurely by clicking on the “stop” - icon |stop| on the tool bar. During the refinement the refinement - progress will be directly reported in the PDFfit2 Output panel. - - - After the fitting is completed, the fit summary is provided in the “ - Results” tab of the current action panel associated with the fit node. - - - .. figure:: images/fig2-07.png - :align: center - :figwidth: 100% - - Figure 1.7: Refinement progress is displayed in the PDFfit2 Output - panel. - - - 3. If the fit results are acceptable, one or more refined values could be - copied to become new initial parameters for possible further refinement, - where appropriate. This is be done in the ``Parameters`` tab of the - fit by highlighting refined parameters to be copied, right-clicking, - and and selecting "Copy Refined To Initial". - - - .. figure:: images/fig2-08.png - :align: center - :figwidth: 100% - - Figure 1.8: Updating the set of initial values of refined parameters. - - -7. Plot the results: - - 1. Select the data in the fit (in this case the `Ni-xray.gr` dataset) by - left clicking it. - - 2. Click the "plot" icon |plot| in the toolbar. - - A new window pops up with the plots. It will show the data in blue, the - best-fit model curve in red, and offset below, the difference curve in - green. The offset of the difference curve appears at a default value of - ``-5.0``. You can make your plot more pretty and meaningful by typing a - different offset into the ``offset`` text box and hitting "plot" |plot| - again. - - Depending on whether the structure or the data are selected on the fit - tree, either refined structural parameters or the experiment related - parameters and fit could be plotted. - - It is also possible to configure the plot in the ``Plot Control`` panel - in the GUI. In the default layout it will be at the lower-left of the GUI - panel. - - 1. To plot the fit (as was done above) select "r" as the X plotting - variable. - - 2. Hold down shift and select "Gcalc" and "Gtrunc" as the Y plotting - variables. - - 3. Click the "Plot" button. - - This panel allows more plotting options for advanced cases such as - plotting the values of parameters refined across multiple fits to extract - temperature dependent information. - - .. figure:: images/fig2-09.png - :align: center - :figwidth: 100% - - Figure 1.9: An example of PDFgui plotting capabilities: displaying a - fit. - - .. figure:: images/fig2-10.png - :align: center - :figwidth: 100% - - Figure 1.10: An example of PDFgui plotting capabilities: displaying - a parameter. - - -8. Save your project for later use. - - The project can be saved at any stage in its present configuration - through choice of Save Project as or Save Project as appropriate from the - ``File`` drop-down menu. The PDFgui project file has “ddp” extension. In - addition to saving a project, various parts of the project, both - structure related and data related, can be exported to external files by - making an appropriate selection from the ``Phases`` and ``Data`` drop- - down menus. The phases (starting or converged) can be saved in one of - many formats. The model PDF profile can be exported through ``Data`` menu - and will be saved as a five-column “.fgr” file. The first four columns - are :math:`r, G(r), dr, \text{and }dG(r)`, and the fifth column is the - difference curve between the data and the model. Note that the model PDF - and the difference are only calculated within the user-specified fitting - range. - -========================================================= -Lesson 2: Building structure model using crystal symmetry -========================================================= - -In the previous example the initial structure was defined by an existing file -. However, PDFgui makes it very easy to build a structure model from scratch -and constrain it with arbitrary crystal symmetry. - -1. Create a blank structure: - 1. Click the "Fitting" tab. - 2. Repeat steps 1-3a from Lesson 1, but choose the "New" button. Rename - "New Phase" to "Ni fcc". - -2. Define asymmetric unit: - 1. Right click the header of the empty atoms grid in the "Configure" page. - 2. Insert 1 atom using the popup menu. - 3. Change the elem cell to "Ni". - 4. Select the u11-u33 cells and type "0.004" and press Enter. - -3. Expand to all equivalent positions: - 1. Right click the first Ni atom and select "Expand space group". A " - Space Group Expansion" dialog should open. - 2. In the dialog, select Fm-3m or just type 225 in the "Space Group" box - and hit "OK". - - You should now have four atoms in the atoms grid. - - .. figure:: images/fig3-01.png - :align: center - :figwidth: 100% - - Figure 1.11: Expanding the unit cell using space group information. - -4. Generate symmetry constraints: - 1. Select the "Constraints" tab. - 2. Select all atoms. This can be done by dragging the mouse over the atom - names or by clicking on the "elem" header. - 3. Right click in a selected cell and select "Symmetry constraints." A " - Space Group Constraints" dialog should open. - 4. "Fm-3m" should already appear in the "Space Group" box. If it does not - , select it as you did in step 3 and hit "OK". - - The u11-u33 cells should all read the same value. The "x", "y" and "z" - cells should be all empty because Ni atoms are at special positions in Fm- - 3m. You may try to select lower-symmetry space and check what happens with - the constraints. The space group constraints may be mixed by selecting - different groups of atoms, for example, when only certain species show - lowered symmetry. - - It is important to - note that the table reflecting constraints is the only place that program - refers to for the symmetry. What is written there will be used, and if the - table is tampered with, then the original symmetry obtained using symmetry - expansion feature will not be preserved. Therefore, the expansion tool - represents a convenience tool and nothing more than that. - -5. Continue the fit as in Lesson 1. - - -========================================== -Lesson 3: Calculating PDF from a structure -========================================== - -There is often a need for obtaining a calculated PDF profile for a given -structure instead of performing a fit. Suppose that we have a Ni structure -populating a fit tree, and that we would like to calculate Ni PDF using -neutron radiation. - -1. Highlight the Ni structure on fit tree. -2. Either right-click and select Insert Calculation or select New Calculation - from “Calculation” menu. -3. select "Neutron scatterer type", choose 0.01 for the r-grid size, and use - 0 .08 and 25.0 for resolution and maximum momentum transfer parameters - respectively. - - - - .. figure:: images/fig3-03.png - :align: center - :figwidth: 100% - - Figure 1.12: An example of the calculation configuration panel. - -Conditions to be specified include radiation type, calculation range and -corresponding r-grid size, as well as instrument resolution and maximum -momentum transfer parameters. For the later two, the default values of -parameters could be used, or values could be specified that closely mimic the -experimental conditions on some particular instrument of interest. - -4. Press "gear" icon |gear| in the tool bar. Alternatively select Run - Selected Calculation from the “Calculations” menu. - -5. Click the "plot" icon |plot| in the toolbar. - -6. To export the calculated PDF, use the Export Selected Calculation choice - on the “Calculations” menu. - -============================= -Lesson 4: Multi-stage fitting -============================= - -Learn how to string together fits. - -1. Create a fit as in Lesson 1. - - -2. Copy the fit: - 1. Right click on the fit name "Fit 1" in the right panel (the fit tree). - 2. Select "Copy" from the pop-up menu. - -3. Paste the fit: - 1. Right click in the empty space between the first fit in the fit tree. - 2. Select "Paste Fit." This will create "Fit 1_copy", a copy of "Fit 1" - in the fit tree. - -4. Link the fits: - 1. Click on "Fit 1_copy" in the fit tree. - 2. In the "Parameters" panel, select the entire "Initial" column. - 3. Type ``=Fit 1`` and then press Enter. The "Initial" values of the - parameters should now read ``=Fit1:n``, where "n" is the index of the - parameter. - - This is the linking syntax: ``=name:index``. - "name" is the name of another fit. - "index" is the index of a parameter in that fit. - If you omit "index", it will default to the index of the parameter you are - linking from. A linked parameter uses the refined value of the link as its - initial value. This is useful when you are running several related fits. - An example of this is shown below. - - - .. figure:: images/fig3-04.png - :align: center - :figwidth: 100% - - Figure 1.13: An example of linked fits. - -5. Add more fit parameters: - 1. Select the "Constraints" tab of the `Ni.stru` phase below "Fit 1_copy". - 2. Write ``@9`` in the ``delta2`` box. - -6. Run the fit and plot the results: - 1. Hold down Control and select the data sets from "Fit 1" and - "Fit 1_copy". Alternately, select a single fit and hit “Ctrl”+“Shift”+“A” - simultaneously on the keyboard. - 2. Press "gear" icon |gear| in the tool bar. - 3. Change the offset in the plotting window to 0 and plot Gcalc versus r. - - Notice that Once the when running the fits by pressing the “gear” icon - |gear|, only the highlighted fits will be executed. The fitting will - proceed in stages, so the first fit is executed first, and, after it is - converged, the second one. - - -``delta2`` is a quadratic atomic correlation factor, a parameter related to -the correlated motion of atoms, and as such should help in sharpening up the -nearest neighbor PDF peak in the model PDF profile. - -We note here that there is also a linear atomic correlation factor -``delta1``. This one is appropriate to use in cases of high temperature, -while ``delta2`` is more appropriate for the case of low temperatures. An -alternative way to include the correlated motion effects on PDF is to -introduce ``sratio`` parameter that defines low-r to high-r PDF peak ratio, -and ``rcut`` limit needs to be specified that defines a cutoff distance. The -two approaches of accounting for correlated motion should not be used -simultaneously. See the PDFgui publication and references therein for a more -thorough description of these parameters. - - -========== -References -========== - -1. :download:`(pdf) `, - Th. Proffen and S. J. L. Billinge, PDFFIT a program for full profile - structural refinement of the atomic pair distribution function, J. Appl. - Crystallogr. 32, 572-575 (1999) - -2. :download:`(pdf) `, - C. L. Farrow, P. Juhas, J. W. Liu, D. Bryndin, J. Bloch, Th. Proffen and - S. J. L. Billinge, PDFfit2 and PDFgui: Computer programs for studying - nanostructure in crystals, J. Phys.: Condens. Matter 19, 335219 (2007) - - -.. |plot| image:: images/plot-icon.png -.. |gear| image:: images/gear-icon.png -.. |stop| image:: images/stop-icon.png diff --git a/environment.yml b/environment.yml deleted file mode 100644 index a3904941..00000000 --- a/environment.yml +++ /dev/null @@ -1,6 +0,0 @@ -name: diffpy.pdfgui -channels: - - conda-forge -dependencies: - - python=3 - - pip diff --git a/extractEquations.py b/extractEquations.py new file mode 100644 index 00000000..6be47249 --- /dev/null +++ b/extractEquations.py @@ -0,0 +1,156 @@ +#!/usr/bin/python +import os +import shutil +import sys + +"""Read one or more texinfo files and extract any equations marked +in the code with '@EquationMark' macro as PNG files to the images +directory. +""" + +# constants + +rc = { + "directory": "../source/images", # output directory + "resolution": 72, # equation images resolution + "eqns": [], # list of raw equation codes + "tmpdir": None, # temporary directory +} + +eqlatex = r""" +\documentclass{article} +\usepackage{exscale} +\pagestyle{empty} +\setlength{\oddsidemargin}{0in} +\setlength{\textwidth}{7in} +\begin{document} +\huge +%s +\end{document} +""".lstrip() + +eqmark = "@EquationMark" + +############################################################################## +# business + + +def loadEquations(): + """Search for equation codes preceded by @EquationMark macro. + + Store equation codes in rc['eqns']. + """ + lines = [] + for f in sys.argv[1:]: + fhandle = open(f) + lines.extend(fhandle.readlines()) + # process all lines in sequence + atmark = False + attex = False + eqlines = [] + for line in lines: + bareline = line.strip().rstrip("{}") + if bareline == eqmark: + atmark = True + continue + elif atmark and bareline == "@tex": + attex = True + continue + elif attex and bareline == "@end tex": + atmark = False + attex = False + eq = "".join(eqlines) + "\n" + rc["eqns"].append(eq) + eqlines = [] + elif attex: + eqlines.append(line) + return + + +def writePNGFiles(): + from tempfile import mkdtemp + + rc["tmpdir"] = mkdtemp() + rc["directory"] = os.path.abspath(rc["directory"]) + neqn = len(rc["eqns"]) + for i in range(neqn): + fname = "eq-%02i.tex" % (i + 1) + fpath = os.path.join(rc["tmpdir"], fname) + fhandle = open(fpath, "w") + s = eqlatex % rc["eqns"][i] + fhandle.write(s) + fhandle.close() + convertToPNG(fpath) + pngsrc = fpath[:-4] + ".png" + pngdst = os.path.join(rc["directory"], fname[:-4] + ".png") + shutil.copyfile(pngsrc, pngdst) + return + + +def convertToPNG(texfile): + """Compile texfile and convert it to PNG.""" + os.chdir(os.path.dirname(texfile)) + texbasename = os.path.splitext(os.path.basename(texfile))[0] + cmd = "latex --interaction nonstopmode %r" % texbasename + os.system(cmd) != 0 and sys.exit(1) + cmd = "dvips %r" % texbasename + os.system(cmd) != 0 and sys.exit(1) + psfilename = texbasename + ".ps" + bb = getBoundingBox(psfilename) + pgbb = getPageBoundingBox(psfilename) + pt2px = rc["resolution"] / 72.0 + xpx = pt2px * bb[0] + ypx = pt2px * (pgbb[3] - bb[3]) + wpx = pt2px * (bb[2] - bb[0]) + hpx = pt2px * (bb[3] - bb[1]) + geometry = "%ix%i+%i+%i" % (wpx, hpx, xpx, ypx) + pngfilename = texbasename + ".png" + cmd = "convert -strip -density %i %r -crop %s +repage %r" % ( + rc["resolution"], + psfilename, + geometry, + pngfilename, + ) + os.system(cmd) != 0 and sys.exit(1) + return + + +def getBoundingBox(psfilename): + """Run ghostscript to obtain effective bounding box of psfilename. + + Return a list of bounding box coordinates. + """ + cmd = "gs -dNOPAUSE -dBATCH -q -sDEVICE=bbox %r" % psfilename + # gs sends bbox output to stderr + i, o, e = os.popen3(cmd) + i.close() + out = o.read() + o.close() + out += e.read() + e.close() + bb = [int(w) for w in out.split()[1:5]] + return bb + + +def getPageBoundingBox(psfilename): + """Obtain bounding box value defined in psfilename. + + Return a list of bounding box coordinates. + """ + import re + + with open(psfilename) as fp: + s = fp.read() + bbline = re.search("^%%BoundingBox: *(.*)$", s, re.M) + pgbb = [int(w) for w in bbline.group(1).split()[:4]] + return pgbb + + +def main(): + loadEquations() + writePNGFiles() + shutil.rmtree(rc["tmpdir"]) + + +if __name__ == "__main__": + main() diff --git a/fixHTMLCode.py b/fixHTMLCode.py new file mode 100644 index 00000000..3929573a --- /dev/null +++ b/fixHTMLCode.py @@ -0,0 +1,62 @@ +#!/usr/bin/python + +import os +import re +import sys + +"""Replace all equation marks in HTML file with tag to display +corresponding PNG file. This assumes PNG files are in correct sequence. +Also fix any accented characters texinfo does not get right. +""" + +# constants + +rc = { + "directory": "../source/images", # directory with equation images +} + +eqmark = "" + +############################################################################## +# business + + +eqcnt = 0 + + +def eqreplace(mx): + """Helper function to replace equation marks. + + mx -- regular expression match object + + Return replacement string. + """ + global eqcnt + eqcnt += 1 + imgfile = "eq-%02i.png" % eqcnt + imgurl = os.path.join(rc["directory"], imgfile) + s = '

%s' % (imgurl, imgurl) + return s + + +def replaceEquationMarks(s): + """Replace equation marks in given string. + + Return modified string. + """ + s1 = re.sub(eqmark, eqreplace, s) + return s1 + + +def main(): + for f in sys.argv[1:]: + with open(f) as fp: + s = fp.read() + s1 = replaceEquationMarks(s) + if s1 != s: + with open(f, "w") as fpout: + fpout.write(s1) + + +if __name__ == "__main__": + main() diff --git a/genindex.html b/genindex.html new file mode 100644 index 00000000..14cb7388 --- /dev/null +++ b/genindex.html @@ -0,0 +1,2523 @@ + + + + + + + + Index — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + +

+ + +
+ +
+
+
+
    +
  • + +
  • +
  • +
+
+
+
+
+ + +

Index

+ +
+ A + | B + | C + | D + | E + | F + | G + | H + | I + | J + | K + | L + | M + | N + | O + | P + | Q + | R + | S + | T + | U + | V + | W + +
+

A

+ + + +
+ +

B

+ + + +
+ +

C

+ + + +
+ +

D

+ + + +
+ +

E

+ + + +
+ +

F

+ + + +
+ +

G

+ + + +
+ +

H

+ + + +
+ +

I

+ + + +
+ +

J

+ + + +
+ +

K

+ + + +
+ +

L

+ + + +
+ +

M

+ + + +
+ +

N

+ + + +
+ +

O

+ + + +
+ +

P

+ + + +
+ +

Q

+ + + +
+ +

R

+ + + +
+ +

S

+ + + +
+ +

T

+ + + +
+ +

U

+ + + +
+ +

V

+ + + +
+ +

W

+ + + +
+ + + +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/doc/source/images/Makefile b/images/Makefile similarity index 100% rename from doc/source/images/Makefile rename to images/Makefile diff --git a/doc/source/images/eq-01.png b/images/eq-01.png similarity index 100% rename from doc/source/images/eq-01.png rename to images/eq-01.png diff --git a/doc/source/images/eq-02.png b/images/eq-02.png similarity index 100% rename from doc/source/images/eq-02.png rename to images/eq-02.png diff --git a/doc/source/images/fig2-01.png b/images/fig2-01.png similarity index 100% rename from doc/source/images/fig2-01.png rename to images/fig2-01.png diff --git a/doc/source/images/fig2-02.png b/images/fig2-02.png similarity index 100% rename from doc/source/images/fig2-02.png rename to images/fig2-02.png diff --git a/doc/source/images/fig2-03.png b/images/fig2-03.png similarity index 100% rename from doc/source/images/fig2-03.png rename to images/fig2-03.png diff --git a/doc/source/images/fig2-04.png b/images/fig2-04.png similarity index 100% rename from doc/source/images/fig2-04.png rename to images/fig2-04.png diff --git a/doc/source/images/fig2-05.png b/images/fig2-05.png similarity index 100% rename from doc/source/images/fig2-05.png rename to images/fig2-05.png diff --git a/doc/source/images/fig2-06.png b/images/fig2-06.png similarity index 100% rename from doc/source/images/fig2-06.png rename to images/fig2-06.png diff --git a/doc/source/images/fig2-07.png b/images/fig2-07.png similarity index 100% rename from doc/source/images/fig2-07.png rename to images/fig2-07.png diff --git a/doc/source/images/fig2-08.png b/images/fig2-08.png similarity index 100% rename from doc/source/images/fig2-08.png rename to images/fig2-08.png diff --git a/doc/source/images/fig2-09.png b/images/fig2-09.png similarity index 100% rename from doc/source/images/fig2-09.png rename to images/fig2-09.png diff --git a/doc/source/images/fig2-10.png b/images/fig2-10.png similarity index 100% rename from doc/source/images/fig2-10.png rename to images/fig2-10.png diff --git a/doc/source/images/fig2-11.png b/images/fig2-11.png similarity index 100% rename from doc/source/images/fig2-11.png rename to images/fig2-11.png diff --git a/doc/source/images/fig3-01.png b/images/fig3-01.png similarity index 100% rename from doc/source/images/fig3-01.png rename to images/fig3-01.png diff --git a/doc/source/images/fig3-02.png b/images/fig3-02.png similarity index 100% rename from doc/source/images/fig3-02.png rename to images/fig3-02.png diff --git a/doc/source/images/fig3-03.png b/images/fig3-03.png similarity index 100% rename from doc/source/images/fig3-03.png rename to images/fig3-03.png diff --git a/doc/source/images/fig3-04.png b/images/fig3-04.png similarity index 100% rename from doc/source/images/fig3-04.png rename to images/fig3-04.png diff --git a/doc/source/images/fig3-05.png b/images/fig3-05.png similarity index 100% rename from doc/source/images/fig3-05.png rename to images/fig3-05.png diff --git a/doc/source/images/fig3-06.png b/images/fig3-06.png similarity index 100% rename from doc/source/images/fig3-06.png rename to images/fig3-06.png diff --git a/doc/source/images/fig3-07.png b/images/fig3-07.png similarity index 100% rename from doc/source/images/fig3-07.png rename to images/fig3-07.png diff --git a/doc/source/images/fig3-08.png b/images/fig3-08.png similarity index 100% rename from doc/source/images/fig3-08.png rename to images/fig3-08.png diff --git a/doc/source/images/fig3-09.png b/images/fig3-09.png similarity index 100% rename from doc/source/images/fig3-09.png rename to images/fig3-09.png diff --git a/doc/source/images/fig3-10.png b/images/fig3-10.png similarity index 100% rename from doc/source/images/fig3-10.png rename to images/fig3-10.png diff --git a/doc/source/images/fig4-01.png b/images/fig4-01.png similarity index 100% rename from doc/source/images/fig4-01.png rename to images/fig4-01.png diff --git a/doc/source/images/originals/fig4-02.png b/images/fig4-02.png similarity index 100% rename from doc/source/images/originals/fig4-02.png rename to images/fig4-02.png diff --git a/doc/source/images/originals/fig2-01.png b/images/originals/fig2-01.png similarity index 100% rename from doc/source/images/originals/fig2-01.png rename to images/originals/fig2-01.png diff --git a/doc/source/images/originals/fig2-01.xcf b/images/originals/fig2-01.xcf similarity index 100% rename from doc/source/images/originals/fig2-01.xcf rename to images/originals/fig2-01.xcf diff --git a/doc/source/images/originals/fig2-02.png b/images/originals/fig2-02.png similarity index 100% rename from doc/source/images/originals/fig2-02.png rename to images/originals/fig2-02.png diff --git a/doc/source/images/originals/fig2-03.png b/images/originals/fig2-03.png similarity index 100% rename from doc/source/images/originals/fig2-03.png rename to images/originals/fig2-03.png diff --git a/doc/source/images/originals/fig2-04.png b/images/originals/fig2-04.png similarity index 100% rename from doc/source/images/originals/fig2-04.png rename to images/originals/fig2-04.png diff --git a/doc/source/images/originals/fig2-05.png b/images/originals/fig2-05.png similarity index 100% rename from doc/source/images/originals/fig2-05.png rename to images/originals/fig2-05.png diff --git a/doc/source/images/originals/fig2-06.png b/images/originals/fig2-06.png similarity index 100% rename from doc/source/images/originals/fig2-06.png rename to images/originals/fig2-06.png diff --git a/doc/source/images/originals/fig2-07.png b/images/originals/fig2-07.png similarity index 100% rename from doc/source/images/originals/fig2-07.png rename to images/originals/fig2-07.png diff --git a/doc/source/images/originals/fig2-08.png b/images/originals/fig2-08.png similarity index 100% rename from doc/source/images/originals/fig2-08.png rename to images/originals/fig2-08.png diff --git a/doc/source/images/originals/fig2-09.png b/images/originals/fig2-09.png similarity index 100% rename from doc/source/images/originals/fig2-09.png rename to images/originals/fig2-09.png diff --git a/doc/source/images/originals/fig2-10.png b/images/originals/fig2-10.png similarity index 100% rename from doc/source/images/originals/fig2-10.png rename to images/originals/fig2-10.png diff --git a/doc/source/images/originals/fig2-11.png b/images/originals/fig2-11.png similarity index 100% rename from doc/source/images/originals/fig2-11.png rename to images/originals/fig2-11.png diff --git a/doc/source/images/originals/fig3-01.png b/images/originals/fig3-01.png similarity index 100% rename from doc/source/images/originals/fig3-01.png rename to images/originals/fig3-01.png diff --git a/doc/source/images/originals/fig3-02.png b/images/originals/fig3-02.png similarity index 100% rename from doc/source/images/originals/fig3-02.png rename to images/originals/fig3-02.png diff --git a/doc/source/images/originals/fig3-03.png b/images/originals/fig3-03.png similarity index 100% rename from doc/source/images/originals/fig3-03.png rename to images/originals/fig3-03.png diff --git a/doc/source/images/originals/fig3-04.png b/images/originals/fig3-04.png similarity index 100% rename from doc/source/images/originals/fig3-04.png rename to images/originals/fig3-04.png diff --git a/doc/source/images/originals/fig3-05.png b/images/originals/fig3-05.png similarity index 100% rename from doc/source/images/originals/fig3-05.png rename to images/originals/fig3-05.png diff --git a/doc/source/images/originals/fig3-06.png b/images/originals/fig3-06.png similarity index 100% rename from doc/source/images/originals/fig3-06.png rename to images/originals/fig3-06.png diff --git a/doc/source/images/originals/fig3-07.png b/images/originals/fig3-07.png similarity index 100% rename from doc/source/images/originals/fig3-07.png rename to images/originals/fig3-07.png diff --git a/doc/source/images/originals/fig3-08.png b/images/originals/fig3-08.png similarity index 100% rename from doc/source/images/originals/fig3-08.png rename to images/originals/fig3-08.png diff --git a/doc/source/images/originals/fig3-09.png b/images/originals/fig3-09.png similarity index 100% rename from doc/source/images/originals/fig3-09.png rename to images/originals/fig3-09.png diff --git a/doc/source/images/originals/fig3-10.png b/images/originals/fig3-10.png similarity index 100% rename from doc/source/images/originals/fig3-10.png rename to images/originals/fig3-10.png diff --git a/doc/source/images/originals/fig4-01.png b/images/originals/fig4-01.png similarity index 100% rename from doc/source/images/originals/fig4-01.png rename to images/originals/fig4-01.png diff --git a/images/originals/fig4-02.png b/images/originals/fig4-02.png new file mode 100644 index 00000000..710606f5 Binary files /dev/null and b/images/originals/fig4-02.png differ diff --git a/index.html b/index.html new file mode 100644 index 00000000..32294976 --- /dev/null +++ b/index.html @@ -0,0 +1,213 @@ + + + + + + + + + diffpy.pdfgui documentation — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

diffpy.pdfgui documentation

+

diffpy.pdfgui - GUI for PDF simulation and structure refinement.

+
+
Software version 3.1.0
+
Last updated February 17, 2025
+
+

For users who do not have the expertise or necessity for command +line analysis, PDFgui is a convenient and easy to use graphical front +end for the PDFfit2 refinement program. It is capable of full-profile +fitting of the atomic pair distribution function (PDF) derived from x-ray +or neutron diffraction data and comes with built in graphical and structure +visualization capabilities.

+

PDFgui is a friendly interface to the PDFfit2 refinement engine, with many +powerful extensions. To get started, please open the Manual +(pdf) from the help menu or follow the Tutorial.

+
+

Authors

+

DiffPy was initiated as part of the Distributed Data Analysis of Neutron +Scattering Experiments (DANSE) project, funded by the National Science +Foundation under grant DMR-0520547. Any opinions, findings, and conclusions or +recommendations expressed in this material are those of the author(s) +and do not necessarily reflect the views of the NSF.

+

The main contributors to this package were

+
+

Chris Farrow, +Jiwu Liu, +Pavol Juhas, +Dmitriy Bryndin

+
+

Other current and former contributors of the DiffPy project include

+
+

Simon Billinge, +Chris Farrow, +Emil Bozin, +Wenduo Zhou, +Peng Tian

+
+

The DiffPy team is part of the Billinge Group at Columbia University in New York, +within the Department of Applied Physics and Applied Mathematics.

+

For a detailed list of contributors see +https://github.com/diffpy/diffpy.pdfgui/graphs/contributors.

+
+
+

Reference

+

If you use this program for a scientific research that leads to publication, +we ask that you acknowledge use of the program by citing the following paper +in your publication:

+
+

C L Farrow, P Juhas, J W Liu, D Bryndin, E S Božin, +J Bloch, Th Proffen and S J L Billinge, PDFfit2 and PDFgui: +computer programs for studying nanostructure in crystals, +J. Phys.: Condens. Matter 19 (2007) 335219.

+
+
+
+

Installation

+

See the README +file included with the distribution.

+
+
+

Tutorial

+

The tutorial for the package can be found here:

+ +
+
+

Table of contents

+ +
+
+

Indices

+ +
+
+ + +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/license.html b/license.html new file mode 100644 index 00000000..5faf6d87 --- /dev/null +++ b/license.html @@ -0,0 +1,194 @@ + + + + + + + + + License — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

License

+
This software was originally developed by the Billinge group as part
+of the Distributed Data Analysis of Neutron Scattering Experiments
+(DANSE) project funded by the US National Science Foundation under
+grant DMR-0520547. Developments of PDFfit2 were funded by NSF grant
+DMR-0304391 in the Billinge group, and with support from Michigan State
+University and Columbia University. Any opinions, findings, and conclusions
+or recommendations expressed in this material are those of the author(s)
+and do not necessarily reflect the views of the respective funding bodies.
+Subsequent development was done in the Billinge group at Columbia University
+and then in collaboration between the Billinge group at Columbia and Pavol
+Juhas at Brookhaven National Laboratory. Moving forward, PDFgui will be
+maintained as a community project with contributions welcomed from many people.
+
+If you use this program to do productive scientific research that leads
+to publication, we ask that you acknowledge use of the program by citing
+the following paper in your publication:
+
+    C. L. Farrow, P. Juhas, J. W. Liu, D. Bryndin, E. S. Bozin,
+    J. Bloch, Th. Proffen and S. J. L. Billinge, PDFfit2 and
+    PDFgui: computer programs for studying nanostructure in
+    crystals, J. Phys.: Condens.  Matter 19, 335219 (2007)
+
+Up to the release 1.1.2 (February 2017) the copyright was held by
+the institutions that hosted the work as follows:
+Copyright 2006-2007, Board of Trustees of Michigan State University,
+Copyright 2008-2012, Board of Trustees of Columbia University in the
+city of New York.
+Copyright 2013, Brookhaven National Laboratory (Copyright holder
+indicated in each source file).
+
+As of February 2017, and the 1.1.2 release, PDFgui has moved to a shared copyright model.
+
+PDFgui uses a shared copyright model. Each contributor maintains copyright over their
+contributions to PDFgui. But, it is important to note that these contributions are
+typically only changes to the repositories. Thus, the PDFgui source code, in its entirety,
+is not the copyright of any single person or institution. Instead, it is the collective
+copyright of the entire PDFgui Development Team. If individual contributors want to
+maintain a record of what changes/contributions they have specific copyright on, they
+should indicate their copyright in the commit message of the change, when they commit
+the change to one of the PDFgui repositories.
+
+The PDFgui Development Team is the set of all contributors to the PDFgui project.
+A full list can be obtained from the git version control logs.
+
+For more information please visit the project web-page:
+    https://www.diffpy.org
+or email Prof. Simon Billinge at sb2896@columbia.edu
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+* 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.
+
+* 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 COPYRIGHT HOLDER "AS IS".  COPYRIGHT HOLDER
+EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES AND CONDITIONS, EITHER
+EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, TITLE, FITNESS, ADEQUACY OR SUITABILITY
+FOR A PARTICULAR PURPOSE, AND ANY WARRANTIES OF FREEDOM FROM
+INFRINGEMENT OF ANY DOMESTIC OR FOREIGN PATENT, COPYRIGHTS, TRADE
+SECRETS OR OTHER PROPRIETARY RIGHTS OF ANY PARTY.  IN NO EVENT SHALL
+COPYRIGHT HOLDER BE LIABLE TO ANY PARTY 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 OR RELATING TO THIS AGREEMENT, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/manual.html b/manual.html new file mode 100644 index 00000000..b644ba9e --- /dev/null +++ b/manual.html @@ -0,0 +1,5684 @@ + + + + + + + + + Manual — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Manual

+
+

Resources used

+ + + + + + + PDFgui user guide, release 2.0, May 2023 + + + + + + + + + + + +

PDFgui user guide

+

2.0 release

+

May 2023

+ C. L. Farrow, P. Juhás, J. W. Liu, D. Bryndin, E. S. Božin,
+ J. Bloch, Th. Proffen, and S. J. L. Billinge
+ +
+ + + + + + + + + + +
[ < ] + [ + > ] +   + [Contents] + + [Index] + + [ ? ] +
+ +

Acknowledgments

+ +

+ This software was originally developed by the Billinge group as part of + the Distributed Data Analysis of Neutron Scattering Experiments (DANSE) + project funded by the US National Science Foundation under grant + DMR-0520547. Developments of PDFfit2 were funded by NSF grant DMR-0304391 + in the Billinge group, and with support from Michigan State University and + Columbia University. Any opinions, findings, and conclusions or + recommendations expressed in this material are those of the author(s) and + do not necessarily reflect the views of the respective funding bodies. + Subsequent development was done in the Billinge group at Columbia + University and then in collaboration between the Billinge group at + Columbia and Pavol Juhas at Brookhaven National Laboratory. Moving + forward, PDFgui will be maintained as a community project with + contributions welcomed from many people. +

+

+ Several of the examples in the tutorial part were made possible and + benefited from samples synthesized by J. F. Mitchell, and from data + collected and processed by M. Schmidt, P. G. Radaelli, and X. Qiu. +

+

+ If you use this program to do productive scientific research that leads to + publication, we ask that you acknowledge use of the program by citing the + following paper in your publication: +

+
+

+ C. L. Farrow, P. Juhás, J. W. Liu, D. Bryndin, E. S. Božin, J. Bloch, + Th. Proffen and S. J. L. Billinge, + PDFfit2 and PDFgui: computer programs for studying nanostructure in + crystals, J. Phys.: Condens. Matter, 19, 335219 (2007) +

+
+ +

+ Up to the release 1.1.2 (February 2017) the copyright was held by the + institutions that hosted the work as follows: Copyright 2006-2007, Board + of Trustees of Michigan State University, Copyright 2008-2012, Board of + Trustees of Columbia University in the city of New York. Copyright 2013, + Brookhaven National Laboratory (Copyright holder indicated in each source + file). +

+ +

+ As of February 2017, and the 1.1.2 release, PDFgui has moved to a shared + copyright model. PDFgui uses a shared copyright model. Each contributor + maintains copyright over their contributions to PDFgui. But, it is + important to note that these contributions are typically only changes to + the repositories. Thus, the PDFgui source code, in its entirety, is not + the copyright of any single person or institution. Instead, it is the + collective copyright of the entire PDFgui Development Team. If individual + contributors want to maintain a record of what changes/contributions they + have specific copyright on, they should indicate their copyright in the + commit message of the change, when they commit the change to one of the + PDFgui repositories. The PDFgui Development Team is the set of all + contributors to the PDFgui project. A full list can be obtained from the + git version control logs. For more information please visit + https://www.diffpy.org or contact + Prof. Simon Billinge at + sb2896@columbia.edu. +

+ + +

Preface

+ +

Using PDFgui and PDFfit2

+

+ Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: +

+ +

+ Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +

+ +

+ 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. +

+ +

+ Neither the names of COLUMBIA UNIVERSITY, MICHIGAN STATE UNIVERSITY nor + the names of their contributors may be used to endorse or promote products + derived from this software without specific prior written permission. +

+ + +

Disclaimer

+ +

+ 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 OWNER + 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. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ < ] + + [ Up ] + + [ > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

1 Introduction

+ + +

+ PDFgui is a graphical interface built on the PDFfit2 engine, which is a + program and programming library for real-space refinement of crystal + structures based on the atomic pair distribution function (PDF) method. + PDFgui organizes fits and simplifies many data analysis tasks, such as + configuring and plotting multiple fits. PDFfit2 is capable of fitting a + theoretical three dimensional structure to atomic pair distribution + function data and is ideal for nanoscale investigations. The fit system + accounts for lattice constants, atomic positions and anisotropic atomic + displacement parameters, correlated atomic motion, and experimental + factors that may affect the data. The atomic positions and thermal + coefficients can be constrained to follow symmetry requirements of an + arbitrary space group. The PDFfit2 engine is written in C++ and accessible + via Python, allowing it to inter-operate with other Python programs. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

1.1 PDFfit2

+ + +

+ PDFfit2 is a major upgrade to PDFfit, and inherits many of its features. + PDFfit is capable of fitting a theoretical three-dimensional structure to + an experimentally determined PDF. It can simultaneously fit multiple + structures, accounting for different structural phases in a material. + PDFfit has a constraint system that allows expressing structure variables + as simple functions of fitted parameters. PDFfit structure variables + include lattice constants, data and phase scale factors, atomic site + occupation, anisotropic atomic displacement parameters (ADPs), and atomic + vibrational correlations. PDFfit has a built-in FORTRAN-style command + language that understands simple FOR loops and some built in arithmetic + functions. +

+

+ The original PDFfit was written in FORTRAN-77, which imposes some + limitations on the program. For example, it uses fixed-size arrays for + internal storage. This precludes the analysis of structures with large + cells without modifying the code. Though the constraint system is + powerful, it requires that a constraint equation be accompanied by its + first derivative. This places the burden of determining the derivatives on + the user, which can introduce errors that lead to instability in the + convergence. Furthermore, the code is monolithic, not easily extensible + and hard to integrate with external programs. +

+

+ The primary focus of PDFfit2 development was to remedy the limitations of + PDFfit while extending its functionality. The old PDFfit engine has been + completely rewritten in C++, and many bugs have been fixed. The new engine + uses dynamic memory allocation so that the size of the structure or extent + of the fit-range of the PDF is limited only by the physical memory + available. The constraint system has also been upgraded. The program + automatically + computes the analytical derivatives of the constraints that are required + by the minimization routine. This simplifies user input and reduces the + possibility of errors. In addition, new fitting parameters for handling + dynamic atomic correlations and experimental resolution have been + introduced as well. +

+

+ Instead of rewriting the PDFfit command interpreter, which is used to + define the fitting problem and to control and run the refinement, its + functions are carried out using the Python language (https://www.python.org). Python is a powerful, cross-platform, open-source interpreted + programming language (i.e., it does not need to be compiled to run, + similar to scripting) that emphasizes object-oriented and modular design. + PDFfit2 scripts written in Python syntax take the place of PDFfit macros + and the Python interpreter can handle everything that the old interpreter + could, and more. Using Python as an interpreter allows PDFfit2 to be + combined with and enhanced by other Python libraries. We make use of this + capability with PDFgui as described below. +

+ +
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

1.2 PDFgui

+ + +

+ The PDFfit2 engine can be used either directly from the Python command + line, or as part of larger and more complex software applications. The + first application built on PDFfit2 is PDFgui, a graphical environment for + PDF fitting. +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+

1.2.1 Design principles

+ +

+ PDFgui has been designed to provide users with an easy-to-use yet powerful + interface for fitting structure models to PDF data. It makes use of an + object-oriented architecture, which makes it highly extensible and + maintainable. This allows for powerful usability features such as + real-time plotting. PDFgui has been designed with multitasking in mind. It + is multi-threaded so that the work being done by the PDFfit2 engine does + not interfere with the tasks of the user interface. +

+

+ PDFgui is written in the Python programming language. Python features a + relaxed and friendly syntax, supports “write once, run + anywhere” portability, and has extensive libraries and modules for + virtually every task. Software codes written in a variety of programming + languages can be bound into Python, which allows them to be used together. + Python is becoming a popular choice in the scientific computation + community. +

+

+ PDFgui’s interface is built using wxPython (https://www.wxpython.org), the Python package for wxWidgets, a mature cross-platform GUI library. + Graphical applications written in wxPython provide a look and feel native + to the platform on which they are run. PDFgui is designed to run on + Windows, Mac OS, Linux, and all major Unix systems. +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+

1.2.2 Capabilities

+ +

+ PDFgui contains all of the functionality of PDFfit2 along with additional + enhancements for usability. Mundane tasks are handled by the program and + difficult tasks are made simple. PDFgui can manage multiple fits at once. + Each fit can have multiple experimental data sets and structure models. + Fits in a sequence can call upon other fits for their starting parameters, + and configured fits can be queued to run while the user is away. All the + initial, final, and intermediate data are stored in a platform independent + project file that can be loaded on any computer. All management tasks, + such as fit creation, configuration, modification, and visualization, can + be done through the graphical interface. +

+

+ PDFgui supports space group operations. Users can define an asymmetric + unit and let PDFgui expand it to a full cell with all symmetry related + positions. PDFgui can also generate symmetry constraints for atom + positions and atomic ADPs. Users just need to specify the space group, and + the program will identify equivalent sites and generate constraint + equations for their coordinates and temperature factors to keep the + structure consistent with the symmetry requirements. This can be done + either for all atoms in the structure or for an arbitrary subset - for + example when it is known that only a certain species show a local + distortion. The code for space group definitions was provided by the + Python Macromolecular Library (mmLib, + http://pymmlib.sourceforge.net). This was extened to include non-standard space groups using the + Computational Crystallography Toolbox (cctbx, + https://cctbx.github.io). PDFgui + also supports supercell expansion of a normal unit cell. +

+

+ PDFgui uses the matplotlib (https://matplotlib.org) Python package for 2D plotting of data and results. Matplotlib has a + friendly interface so the user can quickly and easily view the results of + a fitting. PDFgui lets users plot data from a series of fits and plot it + against selected meta-data (temperature, doping, etc.), plot the results + of several fits in the same window, plot the PDF in real time as the + fitting is running, plot the parameters or variables in real time as the + refinement evolves, and save plots in common image formats or export the + data to a text file. PDFgui can be configured to use one of many structure + visualization packages, such as AtomEye (http://li.mit.edu/A/Graphics/A/) or PyMOL (https://www.pymol.org). +

+

+ PDFgui supports built-in macros for advanced fits. For a set of + experimental data from one system at different temperatures or doping + levels, PDFgui can expand a template fit to a series of related fits. + Another PDFgui macro makes it easy to set up boxcar fits, where the same + model is fit over different r-ranges of the PDF data. +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

1.3 Availability

+ + +

+ PDFfit2 and PDFgui are open source and distributed under a BSD license. + They run on Windows, Mac OS, Linux, and all major Unix systems. The source + code is freely available. For more information please contact Professor + Simon Billinge (sb2896@columbia.edu) or consult the web-page + https://www.diffpy.org. News of + updates and releases will be posted at this website and on the + diffpy-users group at + https://groups.google.com/d/forum/diffpy-users. +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

1.4 Installation

+ + +

+ PDFgui is included as a part of DiffPy, a suite of Python and C++ + libraries for structure analysis from diffraction data. For more + information about DiffPy products visit the project homepage at + https://www.diffpy.org. +

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

1.4.1 Installation for Anaconda Python

+ +

+ As of version 1.1 PDFgui is distributed as a pre-built package for + Anaconda Python. This method makes + it easier to distribute software updates and also results in the same + installation procedure on all supported platforms. +

+

+ To install PDFgui, download and install Anaconda for Python 2.7 from + https://www.anaconda.com/download. When ready open a terminal application (or + Anaconda Command Prompt on Windows) and use the + conda package manager to install PDFgui from the + “diffpy” channel of Anaconda packages +

+
+
+conda config --add channels diffpy
+conda install diffpy.pdfgui
+
+
+ +

+ The first command instructs Anaconda system to always check the + “diffpy” channel for any new software. Such configuration + allows to obtain PDFgui updates using +

+
+
+conda update diffpy.pdfgui
+
+
+ +

+ It is however not strictly necessary to make the “diffpy” + channel permanent. The same effect can be accomplished by adding the + ‘--channel=diffpy’ option to either of conda install or + conda update commands. +

+

+ After installation is complete PDFgui can be started from a terminal by + entering pdfgui command or on Windows by using the DiffPy + start menu. PDFgui can be also started from the “Launcher” + program that is included with Anaconda. +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

1.4.2 Configuration of structure viewer

+ + +

+ PDFgui can visualize 3D structures by displaying them with an external + visualization program. The visualization program needs to be specified + together with a suitable structure format in the “Edit → + Preferences” menu in PDFgui. The structure plotting feature has been + tested with the following programs: +

+
+
AtomEye
+
+

+ AtomEye structure viewer, XCFG format
+ http://li.mit.edu/A/Graphics/A/ +

+
+
PyMOL
+
+

+ PyMOL structure viewer, PDB format
+ https://www.pymol.org +

+
+
+ +

+ A note for AtomEye users: + +

+

+ AtomEye requires its standard output is connected to a terminal. On Unix + this happens when pdfgui is started from a terminal. However + if you prefer to start PDFgui using a desktop shortcut or via “Run + Application” dialog of the window manager, you need to put the + following information to the “Edit → Preferences” menu of + PDFgui. +

+
+
+Structure viewer executable: xterm
+Argument string: -iconic -e ATOMEYE %s
+Structure format: xcfg
+
+
+

In the above, ATOMEYE is the path to the ATOMEYE executable.

+

+ For Cygwin users, the workaround is to launch the executable from a batch + file. Batch files can only run in a command window on Windows and so + AtomEye’s requirements would be for sure satisfied. In addition the + batch file can be used to adjust environment variables: +

+
+
+atomeye.bat
+------------------------------------------------------------------------
+set DISPLAY=localhost:0
+set PATH=C:\cygwin\bin;C:\cygwin\usr\X11R6\bin;C:\ATOMEYE_DIR;%PATH%
+start A.exe %*
+------------------------------------------------------------------------
+
+
+ +

+ Here ATOMEYE_DIR needs to be replaced with a proper path. Make + sure that the X-server application included with Cygwin is started. +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

1.4.3 Installation from sources

+ + + + +

+ PDFgui sources are available in a public + Git repository at + https://github.com/diffpy/diffpy.pdfgui. Feel free to fork this project on GitHub and contribute. To use the + latest development version clone the Git repository to your computer and + install it in a development mode so that sources are used directly rather + than copied to a system location. It is also recommended to uninstall the + Anaconda package for PDFgui, so that there is no confusion as to what + version is the active one. Here are the shell commands that would do it: +

+
+
+# Install PDFgui together with software dependencies.
+conda install --channel=diffpy diffpy.pdfgui
+
+# Make room for the version from sources.  Keep dependencies installed.
+conda remove diffpy.pdfgui
+
+# Obtain a clone of the PDFgui Git repository.
+git clone https://github.com/diffpy/diffpy.pdfgui.git
+
+# Install PDFgui sources in a development mode.
+cd diffpy.pdfgui
+python setup.py develop
+
+
+ +

+ To verify that PDFgui is indeed loaded from the local source repository + run +

+
+
+python -m pydoc diffpy.pdfgui
+
+
+ +

+ and check the path displayed in the FILE section. The application + integrity can be verified by executing all builtin tests using +

+
+
+python -m diffpy.pdfgui.tests.rundeps
+
+
+ +

+ Use git pull to bring your source directory into sync with + the latest updates in the main repository. It is recommend to afterwards + do `setup.py develop again to refresh the version metadata + associated with the program: +

+
+
+git pull
+python setup.py develop
+
+
+ +

+ To revert PDFgui installation from the source-code installation back to + the pre-built Anaconda package do +

+
+
+pip uninstall diffpy.pdfgui
+conda install --channel=diffpy diffpy.pdfgui
+
+
+ +
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

1.5 What is new

+ + + + +

Version 1.1, released March 2016

+ +

+ Improvements and modifications since the last major release 1.0-r3067 from + April 2009. +

+
+
Anaconda installer
+
+

+ PDFgui is now distributed as a pre-built package for Anaconda Python. + The program is available for all platforms supported by Anaconda, + i.e., for 32 and 64-bit Linux, Mac OS X, and for 32 and 64-bit + Windows. +

+
+
upgrade for recent GUI libraries
+
+

+ Source codes were updated to work with WX GUI toolkit 2.9 or later. + Fixed blacked-out text fields on Mac OS X. Fixed missing toolbar in + plot-windows on Mac OS X. +

+
+
select atoms menu
+
+

+ Added “Select Atoms” context menu to the Phase + Configuration and Phase Constraints panels. This selects atom rows by + a range of indices or by atom type. Added keyboard shortcut + / for activating the atom-selection dialog. +

+
+
small enhancements
+
+

+ Fixed problems with r-grid interpolation near data boundaries. + Allow use of CIF-defined space groups for symmetry constraints. Use + consistent numbering for parameters created by symmetry constraints. + Improved export data tool in plot windows to group y-arrays + that are on the same x grid. Enhanced supercell expansion to + also adjust the coordinate constraints. +

+
+
project moved to GitHub
+
+

+ PDFgui source repository was converted from subversion to a Git + repository at + https://github.com/diffpy/diffpy.pdfgui. Project now uses Git tags to define software release and version + data. +

+
+
Unicode support
+
+

+ Allow accented characters in project filenames and in folder paths + where located. Allow accented characters for naming the fit tree + items. Note that such projects are unlikely to work with older + versions of PDFgui. Fix failure to exit when there is some uncaught + error in the at-exit cleanup functions. +

+
+
PDFgui tests
+
+

+ PDFgui installation now includes built-in tests. Added facility to + test PDFgui and all its DiffPy components. Implemented automated + testing and generation of test coverage reports when sources on GitHub + change. +

+
+
bug fixes
+
+

+ Quite a few. Consult the code history at + https://github.com/diffpy/diffpy.pdfgui/commits. +

+
+
+ + +

Version 1.0, released April 2009

+ +

+ This section describes improvements and modifications since the last + beta-release 1.0b.1792 from December 2007. +

+
+
updates and installation
+
+

+ PDFgui can be installed or updated with a simple run of the + easy_install script. easy_install checks our online code repository + for any newer versions and takes care of their download and + installation. It can be also used to add future DiffPy components as + they become available. This should work for Linux, Mac and Windows. +

+
+
Windows installer
+
+

+ The updated Windows package includes full installation of Python 2.5 + and script for code updates. PDFgui can be installed under normal + Python2.5 tree if it has the easy_install script. +

+
+
particle shape correction stored with phase
+
+

+ The previous release of PDFgui had spherical shape correction factors + stored with PDF dataset. The new layout is more logical and allows + multi-phase refinements with separate shape corrections. +

+
+
step shape factor
+
+

+ Defined new shape factor that cuts off the simulated PDF at user + defined r-limit. +

+
+
cumulative Rw
+
+

+ Implemented calculation of cumulative Rw and option to show it in + PDFgui plot window. +

+
+
project post-processing
+
+

+ Implemented new module ‘tui’ (text user + interface) for simple access to the data in PDFgui project files. The + ‘tui’ module can be used in + easy-to-understand Python scripts for arbitrary data extraction or + conversion. It should be useful for project files with large + temperature or compositional series of PDF refinements. +

+
+
structure visualization
+
+

+ PDFgui can now show structures with any external structure viewer, + that accepts structure file as a command-line argument. +

+
+
space group representations
+
+

+ Added 249 space group representations in non-standard settings. The + new representations were generated using the + cctbx library and helpful hints + from Ralf W. Grosse-Kunstleve. +

+
+
symmetry constraints
+
+

+ Fixed issues with generation of symmetry requirements for the ADP + tensors. +

+
+
default ADP tensors
+
+

+ PDF contributions are not counted for atoms that have ADP tensors + Uij equal zero. Atoms are now inserted with a non-zero + Uij matrix. Added warning when a phase loaded from file has + atoms with zero ADPs. +

+
+
temperature series macro
+
+

+ The temperature series macro was broken for datasets at equal + temperature or when temperature contained decimal point. Improved file + and temperature sorting in the temperature series dialog. +

+
+
journal panel
+

Fixed shortcut key handling and font size issues.

+
startup option ‘--db-pdb
+
+

+ The new command-line option starts Python debugger on PDFgui crash + instead of displaying error report dialog. +

+
+
grid interpolation
+
+

+ Fixed problems with r-grid interpolation appearing due to round-off + errors. +

+
+
data load on Windows
+
+

+ Windows version could not read PDF datasets with NaN (not-a-number) + values in the dGr column, because NaN is not supported by the Windows + C-library. Added check for NaN-s before converting to float. +

+
+
+ +
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

1.6 Community

+ + + + +

+ There are two Google groups for support and development of PDFgui and + other DiffPy software. Visit the links below for message archives or + instructions on subscription and posting. +

+
+
+ diffpy-users + https://groups.google.com/d/forum/diffpy-users +
+
+

+ Help on usage of PDFgui, PDFfit2 and other DiffPy packages. This group + should become a knowledge base of PDFgui user tips, tricks and + troubleshooting. Feel free to ask your question here. +

+
+
+ diffpy-dev + https://groups.google.com/d/forum/diffpy-dev +
+
+

+ For discussions about development and changes of PDFgui, PDFfit2 and + DiffPy library in general. +

+
+
+ +
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

2 Quick start

+ + +

+ In this chapter the PDFgui layout is briefly described, followed by a + simple tutorial example, spanning the GUI functionality and aimed at + novice users. Users familiar with the basics can proceed to + Examples and tutorials, or use + PDFgui reference sheets. All the + files used in examples are available in the source distribution or can be + downloaded from the DiffPy website. +

+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

2.1 PDFgui layout

+ + +

+ Once PDFgui is invoked, a PDFgui window comes up. Its layout consists of a + “Menu Bar”, a “Tool Bar”, and a set of four panes. + The menu bar contains drop-down menus that provide various aspects of + PDFgui functionality. The tool bar features icons for commonly used + operations: creating a new project, opening an existing project, saving a + project, executing a refinement or calculation, stopping a refinement or + calculation, and making a quick plot. The four panes consist of the + “Fit Tree”, “Plot Control”, the“Current + Action” pane, and the “PDFfit2 Output” panel. These are + all shown in Figure 2.1. +

+

+ The fit tree is used in setting up a fit protocol. The plot control serves + the user’s needs for graphically displaying the fits, as well as + various fit-related parameters. The content of the current action panel + changes as the refinement is being set up. It is a functional panel + through which the user configures the fit attributes, sets the fit + constraints, reviews the fit settings, displays fitting results, and also + carries out other setup steps. The progress of the PDFfit2 refinement + engine is displayed in the PDFfit2 output panel. All panels except the + current action panel are dockable windows that can be dragged across the + screen, resized and arranged to accommodate the individual visual needs of + the user. The window layout can also be controlled via the + “View” drop-down menu on the menu bar. An important part of + the PDFgui operativity is also conveniently available through mouse + operations such as select and right-click. +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

+ 2.2 Creating a simple fit using a preexisting structure file +

+ + + +

+ The purpose of this example is to familiarize the novice user with the + PDFgui basics. The goal is to create a simple fit of Ni PDF from a + preexisting structure file, associate a dataset with the refinement, + configure and execute a refinement, and display the result. Files to be + used in this exercise are Ni.stru and Ni-xray.gr (found in + the tutorial directory). To start, invoke PDFgui by clicking on the icon + on your desktop, selecting the program from your system’s program + menu, or by typing pdfgui in a terminal window. +

+

+ First a new fit needs to be established. In the fit tree right-click the + mouse button, and select New Fit. This will generate a new fit + called “Fit 1” in the fit tree. The name of the fit is + highlighted and editable, so you need only to start typing to give the fit + a new name. The current action panel will display the pages that will hold + the fit and the results output. Note that the same action could be + achieved by selecting the New Fit option from the + “Fits” drop-down menu on the menu bar. +

+

+ The next step in populating the fit tree is to load a structural model. + First, select the fit icon in the fit tree pane. Then, right-click the + mouse, invoking a drop-down menu. Select Insert Phase, which will + modify the current action panel. The same action could be performed from + the “Phases” drop-down menu on the menu bar by selecting + New Phase. In the current action panel options are offered to load + a structure from a file or to generate it from scratch. In this exercise a + preexisting structure file Ni.stru is to be loaded. +

+
+ + images/fig2-01 +
+

+ Figure 2.1: PDFgui window with fit tree and Plot Control panels to the + left and current action panel to the right. The fit tree panel features + the current fit and the loaded Ni structure which is selected. The + current action panel displays phase configuration within the + “Configure” tab. + +

+

+ Figure 2.1 shows the PDFgui appearance at this + stage of the exercise. The current action panel has three tabs, + “Configure”, “Constraints”, and + “Results” that could be selected using mouse. These will be + returned to later. The “Configure” panel displays + configuration information from the structure file. The top portion + contains lattice parameters, phase scale factor, and a set of parameters + intended to be used to account for correlated atomic motion effects that + typically sharpen the nearest neighbor PDF peak. These are delta1, + delta2, sratio, and rcut. The spdiameter and + stepcut parameters include scatterer size effects in the PDF. These + parameters will be described later. The bottom part of the panel contains + standard unit cell content related information such as atomic species, + their fractional coordinates, anisotropic ADPs, and site occupancies. +

+

+ The next step is to load an experimental data set to be fit. Selected the + fit and right-click to bring up the context menu. From the menu choose + Insert Data Set. The same action could be performed through the + “Data” menu on the menu bar. The current action panel changes + accordingly, giving an option for a data set to be loaded from a file. In + this exercise Ni PDF data obtained using synchrotron x-ray radiation + collected at 6-ID-D at the Advanced Photon Source is used. This is + contained in a file Ni-xray.gr, which is to be loaded. Note that + among the exercise files there is also a file Ni-neutron.gr, + obtained using neutron radiation at the GPPD diffractometer at the IPNS + facility at the Argonne National Laboratory. Both x-ray and neutron + datasets were collected at 300 K. +

+
+ + images/fig2-02 +
+

+ Figure 2.2: Appearance of a PDFgui window after a PDF dataset is + loaded. The Fit Tree panel features the current fit, loaded Ni + structure, and loaded Ni PDF dataset, G(r), which is selected. The + current action panel displays data set configuration within the + “Configure” tab. + +

+

+ Figure 2.2 shows the PDFgui appearance at this + stage of the exercise. The “Configure” panel displays + configuration information from the data file. It should be noted that + depending on the software used to prepare the experimental PDF from the + raw data, the file may (or may not) contain meta-data reflecting the + experimental conditions and configuration. For example, software PDFgetX2 + and PDFgetN, which can be used to prepare PDFs from x-ray and neutron + total scattering experiments respectively, supply meta-data in the header + of the data file. PDFgui reads this information and fills the appropriate + fields in the data set configuration panel. Caution should be exercised by + the user to verify that these data indeed correspond to the experimental + conditions. In the present example, x-ray radiation is used, and so the + x-ray selection is turned on for the scatterer type. The data range, fit + range, data scale factor, maximum Q value used in Fourier transform to + obtain the experimental PDF and the experiment specific parameters are + displayed. Parameters describing experimental resolution effects, Qdamp + and Qbroad, and experimental conditions, such as temperature and doping + (used for bookkeeping and for parametric plots) are also shown. If no + meta-data are present in a data file, this information should be supplied + by the user. Note also that the changes occurred at this stage in the plot + control panel, allowing user to plot the data. This is achieved by + selecting r in the X-choice box and Gobs (the observed G(r)) + in the Y-list box and then pressing the “Plot” button. Since + no fitting has occurred so far, an attempt to plot calculated PDF profile + or a difference yields a blank plot. The data can also be displayed by + clicking the rightmost “quick-plot” button in the tool bar. +

+
+ + images/fig2-03 +
+

+ Figure 2.3: Adjusting data set related configuration. +

+

+ Having specified the initial structure to be refined, and the data set to + be fit, we proceed to the refinement setup. First we adjust the initial + parameters and variables, and set up the constraints. The adjustments and + constraint setup are done on both the experimental data and the refined + structure levels, toggling between the corresponding + “Configure” and “Constraints” tabs. In the present + example the data related setup will be done first. +

+

+ Click on the data set node (Ni-xray.gr) in the fit tree. In + Figure 2.3 the “Data Set + Configuration” panel is shown. We will adjust the fitting range, as + well as other parameters that reflect the experimental conditions. Since + there is no physical information in the region of r below the + nearest neighbor PDF peak position (as seen in the plot), and since this + region is often affected by noise and experimental artifacts, it is wise + to exclude it from fitting. We therefore set the value of the lower + boundary of the fitting range to 1.7. (Note that the units are Angstroms). + In addition, we set Qdamp parameter to a more realistic starting + value of 0.08. This is an instrument-dependent parameter is typically + obtained through a conventional calibration process at each PDF experiment + using a standard sample such as Ni or Si. Next, we select the + “Constraints” tab, and type @1 into the “Scale + Factor” edit box. This will assign refinement parameter 1 to the + data scale factor. Note that this is the syntax used for assigning the + refinement parameters in PDFfit2 engine. Similarly, assign parameter 2 to + Qdamp by inserting @2 into the appropriate edit box. This is + illustrated in Figure Figure 2.4. +

+
+ + images/fig2-04 +
+

+ Figure 2.4: Setting up the refinement parameters and constraints. + +

+

+ Further, we set constraints related to the structural model, by selecting + the phase node (Ni.stru) on the fit tree, adjusting the initial + parameter values if necessary (not done here), and proceeding to the + “Constraints” tab. We note that the phase configuration was + performed automatically when the structure file was loaded. We assign the + refinement parameter 3 to all three lattice constants, a, b, and c, + reflecting the fact that the structure is cubic. Isotropic ADPs are + assigned to all Ni atoms in the refined cell as refinement parameter 4. + This can conveniently be done by highlighting the “u11”, + “u22” and “u33” cells for all four atoms, and + typing @4 and then pressing “Enter” on your keyboard. + The outcome is shown in Figure Figure 2.5. +

+ +
+ + images/fig2-05 +
+

+ Figure 2.5: Setting up the refinement parameters and constraints. + +

+

+ Note that constrained parameters cannot be adjusted on the + “Configuration” panel since they are no longer independent. It + should also be noted that as a part of the PDFfit2 syntax a refinement + parameter can also be defined as a math expression + f(@n1,@n2,@n3,...) where @n1 stands for fitted parameter, + and n1, n2,... are arbitrary positive integers enumerating + the parameters. This allows simple linking of related variables. For + example, since cell lengths a, b, and c are all expressed as @3, + the refined structure will remain cubic. Also note that the enumeration of + the parameters can be arbitrary, enumeration does not have to follow any + particular order. The quantities within a fit that are enumerated with the + same number will be assigned the same parameter, hence caution should be + exercised to avoid unintentional assignment of the same parameter to + physically different quantities. Automatic parameter assignment (see + further below) is done in such a way as to disallow for such situations to + happen. If assignment is done in part manually, in particular for complex + setups, it is recommended to verify that the parameter assignment is done + correctly. +

+
+ + images/fig2-06 +
+

+ Figure 2.6: Reviewing the fit parameters and conditions. +

+

+ The setup for the present example is now completed. By selecting the fit + node on the fit tree the current action window shows + “Parameters” tab, which displays the used refinement + parameters for review, Figure 2.6. It shows the + initial values, and allows for updates and for refinement parameters to be + released or fixed depending on whether the corresponding + “Fixed” box is unchecked or checked, respectively. The + “Refined” column, which is currently empty, will be populated + with the refined values of the parameters with the fit completes. If the + initial parameter values are to be changed, using “Apply + parameters” button will update the values of the parameters on all + relevant “Configuration” panels. The refinement is executed by + clicking the “gear” icon on the tool bar. The refinement can + be stopped prematurely by clicking on the “stop” icon on the + tool bar. During the refinement the refinement progress will be directly + reported in the PDFfit2 Output panel. This is illustrated in + Figure 2.7. +

+
+ + images/fig2-07 +
+

+ Figure 2.7: While the refinement is running, the refinement progress is + displayed in the PDFfit2 Output panel. + +

+

+ After the fitting is completed, the fit summary is provided in the + “Results” tab of the current action panel associated with the + fit node. Similarly, if the “Results” tab is displayed when + Ni.stru or Ni-xray.gr are selected, values of all + corresponding refined parameters for the converged model are displayed. +

+

+ If the fit results are acceptable, one or more refined values could be + copied to become new initial parameters for possible further refinement, + where appropriate. This is be done in the “Parameters” tab of + the fit by highlighting refined parameters to be copied, right-clicking, + and and selecting Copy Refined To Initial. This is illustrated in + Figure 2.8. Note that you loose the original + starting values when copying values in this way, which may make it + difficult to reproduce the fit. +

+
+ + images/fig2-08 +
+

+ Figure 2.8: Updating the set of initial values of refined parameters. + +

+

+ The fit can be displayed graphically by clicking at the “quick + plot” icon on the tool bar. Alternatively, desired items to be + displayed can be selected from the plot control and plotted on the screen. + Depending on whether the structure or the data are selected on the fit + tree, either refined structural parameters or the experiment related + parameters and fit could be plotted. An example of the fit display is + shown in Figure 2.9, and a selected parameter + plot vs iteration step in Figure 2.10. If the + plotting window remains open while the fitting is in progress, the content + will be updated after each fit iteration. +

+
+ + images/fig2-09 +
+

+ Figure 2.9: An example of PDFgui plotting capabilities: displaying a + fit. + +

+
+ + images/fig2-10 +
+

+ Figure 2.10: An example of PDFgui plotting capabilities: displaying a + parameter. + +

+

+ PDFgui is furnished with “Journal” capability, which can be + found under the “View” menu, and represents a convenient way + to archive project-related notes, as illustrated in + Figure 2.11. These notes can be exported as a + text file, or saved along with the entire project for future reference. +

+
+ + images/fig2-11 +
+

+ Figure 2.11: Using “Journal” feature can be a convenient + way for taking notes. + +

+

+ The project can be saved at any stage in its present configuration through + choice of Save Project as or Save Project as appropriate + from the “File” drop-down menu. The PDFgui project file has + “ddp” extension. In addition to saving a project, various + parts of the project, both structure related and data related, can be + exported to external files by making an appropriate selection from the + “Phases” and “Data” drop-down menus. The phases + (starting or converged) can be saved in one of many formats. The model PDF + profile can be exported through “Data” menu and will be saved + as a five-column “.fgr” file. The first four columns are + r, G(r), dr, and dG(r), and the fifth column + is the difference curve between the data and the model. Note that the + model PDF and the difference are only calculated within the user-specified + fitting range. +

+ +
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

3 Examples and tutorials

+ + + +

+ In this chapter we present series of examples and tutorials aimed at users + already comfortable with the GUI, to provide training in advanced GUI + features designed for most common modeling situations, such as building + the structure from scratch, calculating the PDF based on a given + structure, linking fits, and creating and executing a series of fits on a + sequence of data sets. +

+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

3.1 Building structure model using crystal symmetry

+ + + +

+ The purpose of this example is to demonstrate to the user the symmetry + expansion capabilities of PDFgui. The goal is again to create a simple fit + of Ni PDF, but this time from scratch rather than from a preexisting + structure file. The focus will be on the symmetry expansion of the + structure, and the steps that are described earlier in + Creating a simple fit using a preexisting structure file + are left for the user to recreate. File to be used in this exercise is + Ni-xray.gr. To start, invoke PDFgui. +

+

+ To begin, a new fit again needs to be established by right-clicking the + mouse button on the fit tree pane, and selecting New Fit. This will + generate a new fit called Fit 1 as in the previous example. The next step + in populating the fitting tree is to introduce a structural model. This + time a new phase will be added and the model built up from scratch. Select + the fit icon in the Fit Tree pane. Then right-click the mouse and select + Insert Phase, which will modify the current action panel. In the + current action panel options are offered to load a structure from a file + or to generate it from scratch. Select “New” to build up + structure from scratch. The Fit Tree will be populated with a new item + “New Phase”. Rename this phase to “Ni fcc”. The + current action panel now displays default phase configuration with + “dummy” values and no atoms. Edit the lattice parameters and + set them to reflect the symmetry, in this case set the lengths to 3.52 + Angstroms and all the angles to 90 degrees. Pressing “Tab” on + the keyboard will take you from one form-field to the next. To introduce + new atoms right-click with your mouse onto elem tab in the Phase + Constraints grid, and select desired number of atoms in the asymmetric + unit via the dialog box that pops up. For the Ni case, select one row + only. A new row will then show up in the table and the name of the element + will be highlighted. Type in Ni for the element name. It is + important that the element name is typed in correctly, as this is further + used to search a database for the scattering characteristics of that + site(1). Further, highlight cells in the + u11, u22, and u33 columns and type in the initial + value 0.0025. +

+ +

+ Now right-click with the mouse on the element name, and select + “Expand space group...” option. A dialog box will appear, as + shown in Figure 3.1, requesting space group + information and the choice of origin. Choose “Fm-3m” in the + choice box and hit enter. You can also type in the choice box + “Fm-3m” or “225”, the space group number. This + will expand the unit cell to four Ni sites with the proper symmetry. +

+
+ + images/fig3-01 +
+

+ Figure 3.1: Expanding the unit cell using space group information. + +

+

+ In order to set the symmetry constraints for the refinement, select + “Constraints” tab, highlight all the atoms, and right-click to + invoke a menu. Note that hitting “Control” and “A” + simultaneously will select all the atoms if the grid is active. (If the + fit tree is active, it will select all tree items). Click on + “Symmetry constraints...”, and a dialog box will appear asking + for the space group to be used and whether you want the positions and/or + the thermal parameters to be constrained, as shown in + Figure 3.2. The default is to use the space + group used for expansion, and to constrain everything according to the + symmetry. Since all the positions are special, these will not be refinable + by symmetry, and the thermal parameters will be isotropic. The program + will assign parameters according to symmetry using default names that can + be renamed and/or reassigned by the user. To be consistent with the naming + from the first example, one could assign the lattice parameters as + @3 and the isotropic ADPs as @4. Note that parameters can be + quickly renamed or consolidated in the “Parameters” panel of + the fit node using the right-click menu. It is important to note that the + table reflecting constraints is the only place that program refers + to for the symmetry. What is written there will be used, and if the table + is tampered with, then the original symmetry obtained using symmetry + expansion feature will not be preserved. Therefore, the expansion + tool represents a convenience tool and nothing more than that. The + remaining steps of this example are identical to these described in + Creating a simple fit using a preexisting structure file. +

+
+ + images/fig3-02 +
+

+ Figure 3.2: Setting up symmetry constraints to be used in a refinement. + +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

3.2 Calculating PDF from a structure

+ + +

+ There is often a need for obtaining a calculated PDF profile for a given + structure instead of performing a fit. In order to carry out a + calculation, an underlying structure needs to be specified. This can + either be loaded from a file or generated from scratch. Suppose that we + have a Ni structure populating a fit tree using steps described in either + Creating a simple fit using a preexisting structure file + or in + Building structure model using crystal symmetry, and that we would like to calculate Ni PDF using neutron radiation. + Highlight the Ni structure on fit tree. Either right-click and select + Insert Calculation or select New Calculation from + “Calculation” menu. The current action panel will display + information very similar to that when a data set is loaded, as shown in + Figure 3.3. +

+
+ + images/fig3-03 +
+

+ Figure 3.3: An example of the calculation configuration panel. + +

+

+ Now specify conditions to be used for the calculation, such as radiation + type, calculation range and corresponding r-grid size, as well as + instrument resolution and maximum momentum transfer parameters. For the + later two, the default values of parameters could be used, or values could + be specified that closely mimic the experimental conditions on some + particular instrument of interest. After the conditions are set, the gear + icon on the tool bar can be used to execute the calculation (or + alternatively select Run Selected Calculation from the + “Calculations” menu). For our exercise, select + Neutron scatterer type. To mimic the experimental data used earlier + in the tutorial, select for example 0.01 for the r-grid size, and + use 0.08 and 25.0 for resolution and maximum momentum transfer parameters + respectively. Execute the calculation and observe the result by clicking + on the quick plot icon on the tool bar. To export the calculated PDF, use + the Export Selected Calculation choice on the + “Calculations” menu. +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

3.3 Sequential fitting

+ + +

+ In many practical situations there is a need to set a series of + refinements that are linked in a sequence. In what follows we will + describe multi-stage fitting capabilities of PDFgui, followed by + description of three pre-made macros that implement sequential fitting: + fitting of r-series on a single data set, temperature series on a + set of data corresponding to various temperatures, and a doping series on + a set of data corresponding to samples whose chemical content changes in + some systematic way. These macros can be accessed from the menu bar, + “Fits” menu, Macros selection on the drop-down menu. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

3.3.1 Multistage fitting

+ + +

+ Here we describe how to string together several fits. To begin, create a + fit as explained earlier. We assume this fit is named “Fit 1”. + The next step is to copy the fit. This is achieved by right-clicking on + the fit node in the the fit tree, and selecting “Copy” option + from the pop-up menu. Once this is done, the fit can be pasted by + selecting either “Paste Fit” or “Paste Linked Fit” + from the pop-up menu. We will link the fits manually for the sake of + instruction, so select “Paste Fit”. (“Paste Linked + Fit” will do all of what follows automatically.) Selecting + “Paste Fit” will create “Fit 1_copy”, a copy of + “Fit 1” in the fit, which has the. The next step is to link + the fits. Select the new fit node on the fit tree. All aspects of the fit + are duplicated in the new fit, but so far are not associated with the + original fit. +

+

+ In the “Parameters” panel, select the entire + “Initial” column. Type “=Fit 1” and then press + “Enter”. The “Initial” values of the parameters + should now read “=Fit 1:n”, where n is the index of the + parameter. This brings us to the linking syntax. A parameter in this fit + can be linked to any other parameter in any other fit with + “=name:index” syntax. Here, “name” is the name of + another fit to which the link is made, and “index” is the + index of a parameter in that fit. If “:index” is omitted, it + will default to the index of the parameter one is linking from. A linked + parameter uses the refined value of the link as its initial value, + or the initial value if the linked parameter is not yet refined. An + example of this is shown in Figure 3.4. +

+
+ + images/fig3-04 +
+

+ Figure 3.4: An example of linked fits. The output of a converged fit + will be fed into the succeeding fit in the sequence as an input. + +

+

+ Now that we have a linked fit, we can change it in some aspect. We could + delete and replace the data set or phase, or we could or we can add + parameter to see if we can improve the fit, without modifying the + configuration of the original fit. Here we will add additional parameters + to improve the fit. If our Ni example was used and copied in this + exercise, one can select Ni.stru phase of “Fit 1_copy” + and introduce parameter delta2 by inserting “@5” in the + appropriate box of the “Constraints” tab of that phase. This + is a quadratic atomic correlation factor, a parameter related to the + correlated motion of atoms, and as such should help in sharpening up the + nearest neighbor PDF peak in the model PDF profile. Highlight the fits on + the fit tree by holding down “Ctrl” on the keyboard while + selecting each in sequence. Alternately, select a single fit and hit + “Ctrl”+“Shift”+“A” simultaneously on + the keyboard. Once the fits are selected, run them by pressing the + “gear” icon in the tool bar. Only the highlighted fits will be + executed. The fitting will proceed in stages, so the first fit is executed + first, and, after it is converged, the second one. After the fitting of + the sequence is over, you may plot the results in the same window by + selecting both data set nodes. Change the offset in the plotting window to + 0 and plot Gcalc versus r. Notable is a sharper nearest + neighbor PDF peak in the second fit, improving the fit to the Ni data + compared to the “Fit 1” achievement. +

+

+ We note here that there is also a linear atomic correlation factor + delta1. This one is appropriate to use in cases of high + temperature, while delta2 is more appropriate for the case of low + temperatures. An alternative way to include the correlated motion effects + on PDF is to introduce sratio parameter that defines low-r + to high-r PDF peak ratio, and rcut limit needs to be + specified that defines a cutoff distance. The two approaches of accounting + for correlated motion should not be used simultaneously. See the + PDFgui publication and references therein for a more thorough description + of these parameters. +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

3.3.2 Sequential fitting of incremental r-series

+ + + +

+ In certain modeling situations the user could benefit from fitting a data + set through a series of refinements that differ one from another by the + corresponding fitting ranges. This could either be a case when upper + r-limit is to be changed incrementally, or when a fixed width + r-window is to be defined for a box-car fitting approach. An + example of this when one wants to study the details of the local- to + average-structure crossover in a complex material. PDFgui has a + pre-written macro that automates the setup of this type of refinement. We + will illustrate these capabilities through a simple Ni example. +

+

+ Generate a complete fit, including a phase and a dataset, as explained in + Creating a simple fit using a preexisting structure file. Select the fit from the fit tree. From the “Fits” menu, + select Macros, and choose “r-Series” option. The + Current Action panel will display simple setting requirements, arranged in + two rows of three dialog boxes each, that need to be filled with values to + be specified by the user. An example of this is shown in Figure + Figure 3.5. +

+

+ The first row deals with the increment setup of the upper r of the + refinements. User should specify the first and the last fit maximum + r-value, and corresponding step (increment), all in units of + Angstroms. In the second row information is needed to specify the lower + r refinement limit. Again, the user sets the first and the last + value, and step. This allows for a box car of either fixed or variable + width to be defined. If the second row is left blank, the corresponding + refinement series will be with incremental maximum r only, and + fixed lower limit. For the purpose of this exercise lets perform + incremental fitting of Ni-data with 4 steps total, and fixed lower limit. + To achieve this, type 5 for the first upper limit, 20 for the last upper + limit, and the step of 5 Angstroms. Leave the second row blank. Once this + is done, make sure that the Ni fit, which in this situation serves as a + template, is highlighted in the fit tree, and then click “OK” + in the current action panel. This will generate 4 new fits below the + original fit, and these four fits will constitute your series, with + desired incremental limits. Select all four of them and execute the + refinement. Once the sequence is done, you can review the results using + the plot control. +

+
+ + images/fig3-05 +
+

+ Figure 3.5: Appearance of the setup panel for specifying an incremental + r-series fit conditions. + +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

3.3.3 Sequential fitting of temperature series

+ + + +

+ Frequently, one must handle a large number of data sets originating from a + single sample collected at various temperatures. One of the common + modeling schemes in such cases is to perform sequential fitting of such + data series, which is known to yield well behaved modeling parameters. + PDFgui has a pre-written macro that allows for this modeling situation to + be accommodated. +

+

+ We will describe the procedure using an example of a temperature series of + data collected on LaMnO3 at various temperatures from 300 K to 1150 K at + NPDF instrument at LANSCE at Los Alamos National Laboratory. This material + exhibits Jahn-Teller (JT) order-disorder phase transition just above 700 + K, where the long range orbital order is lost at high temperature, but the + local JT distortion survives. The formal space group does not change at + this transition. +

+

+ To begin, from the “File” menu use + Open Project selection to open lmo-template.dpp project from + the tutorial directory. This project consists of a fit called + lmo-pbnm , which will serve as a template and which contains + Pbnm phase of LaMnO3 and a 300 K data set. The fit refinement is + set up to cover 1.7-19.5 Angstroms range, and all the parameter values are + set to their converged values for this temperature. The fit setup uses + isotropic ADPs for all atomic sites. In the same directory data + corresponding to various temperatures exist, in particular 300K.gr, + 550K.gr, 650K.gr, 700K.gr, 720K.gr, + 730K.gr, 740K.gr, 750K.gr, 800K.gr, + 880K.gr, 980K.gr, 1050K.gr, 1100K.gr, and + 1150K.gr. We will establish a T-series fit sequence. Select + Macros + from the “Fit” menu on the menu bar, and choose + “Temperature Series”. The current action panel will reflect + the selection. A tool is provided that allows for data sets to be added. + Click on “Add” button. Using “Shift” and + mouse-select operation you should select all the data sets mentioned in + the above list, except the 300 K one, as this is already in the template + fit, and then press “Open”. All the data sets will be loaded. + Since the files contain meta-data, as mentioned earlier, the GUI is going + to pick up temperature information from the files. User should verify that + the information is correct. The data can be ordered by temperature by + clicking the “Temperature” header. +

+
+ + images/fig3-06 +
+

+ Figure 3.6: Setting up a T-series sequential refinement for LaMnO3. + Ordering by temperature will ensure that the fits are linked correctly. + +

+

+ Order the data by temperature (Figure 3.6), as + otherwise the series of fits that is to be automatically generated in the + next step will be linked in an arbitrary way in which the data were + loaded, rather than to reflect the scientific logic. There should be 13 + data sets. Next, ensure that the template fit is selected on the fit tree. + If this is the case, the “OK” button becomes clickable. + Clicking on the “OK” button will generate a sequence of linked + fits in the fit tree in the order of the temperature increase. Each fit is + linked to the previous, except for the template fit for the 300 K data. + Highlight all the fits in the fit tree to start the sequential refinement + of the T-series. The results can then be displayed in Fit Control such + that various converged fit parameters are plotted versus temperature. +

+

+ In terms of the science behind the LaMnO3 example, it is interesting to + plot isotropic ADP of the oxygen at general position. Select all the + phases on the fit tree by selecting one and then hitting the + “Control”, “Shift” and “A” keys on + your keyboard simultaneously. This will select all the phases at once. On + the plot control choose the temperature for x axis, and select the + Uiso of O2 (for example atom 20) for the y axis. Clicking + “Plot” will display the plot of Uiso(20) vs T. +

+
+ + images/fig3-07 +
+

+ Figure 3.7: Displaying the refinement results as a function of external + parameter: T-series refinement of LaMnO3, example of isotropic ADP of + oxygen atom on general position in Pbnm setting. Notable are the + offsets just above 700 K (Jahn-Teller transition), and at around 1000 K + when sample converts from orthorhombic to rhombohedral symmetry. + +

+

+ Despite quite high temperatures, an onset of the static offset above the + transition temperature is clearly marked by this parameter, as apparent in + Figure 3.7. Curious user could repeat the same + T-series refinement restricting the refinement range upper limit to say + 5-6 Angstroms and observe the outcome. The refinement sequence execution + should be very quick in this case. +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

3.3.4 Sequential fitting of doping series

+ + + +

+ Fitting a series of PDF data that correspond to a set of samples with + related chemistry, such as various doping series, represents another + important sequential modeling aspect that is supported in PDFgui. +

+

+ We will describe the procedure using an example of a series of data + collected on LaMnO3 and series of Ca-doped LaMnO3 samples with various Ca + content from 0 to 0.28 at GEM instrument at ISIS, UK. To begin, from the + “File” menu use Open Project selection to open + lcmo-template.dpp project from the tutorial directory, which has an + initial setup for this exercise. Note the letter c in the file + name, in contrast to the name used in the previous example. This project + consists of a fit called lcmo-pbnm, which will serve as a template + and which contains Pbnm phase of LaMnO3 and a 10 K data set, + x000t010q35.gr. The difference here with respect to the template + used in the previous example is that Ca sites are introduced in the + structure, but are assigned zero occupancy. However, existence of the Ca + dopant species in the structure of the template is essential for the macro + to operate. Also, upper limit used in Fourier transform for obtaining this + set of data is 35 inverse Angstroms, in contrast to 32 inverse Angstroms + in previous example. Since different instrument was used, the value of + Qdamp is different than in previous example. +

+
+ + images/fig3-08 +
+

+ Figure 3.8: After loading of the Ca-doping data series of LaMnO3 + system, proper doping assignment needs to be carried out, as the doping + levels introspected from the file names in this example incorrectly + reflect the scientific situation. Note that dopant atom has to be + present in the template seed used to generate the linked sequence of + fits. + +

+

+ In the same directory data corresponding to various Ca contents exist, + collected at 10 K temperature, in particular x004t010q35.gr, + x012t010q35.gr, x016t010q35.gr, x020t010q35.gr, + x024t010q35.gr, and x028t010q35.gr. It should be noted at + this point that the data files do not contain any relevant meta-data in + the file headers. However, the doping level is somehow encrypted into the + file names. We will establish a doping series fit sequence. Select + Macros from the “Fit” menu on the menu bar, and choose + “Doping Series”. The current action panel will reflect the + selection. The base element and dopant need to be specified. A tool is + provided that allows for data sets to be added. Click on “Add” + button. Using “Shift” and mouse-select operation you should + select all the data sets mentioned in the above list, and then press + “Open” button. All the data sets will be loaded. The GUI will + introspect both the file names and files themselves in attempt to obtain + the doping (or in previous example temperature) information. Since the + files do not contain meta-data, as mentioned earlier, the GUI is going to + pick up doping information from the file names. The user should verify + that the information is correct. In this particular case the doping + information will not be correctly picked up, as for example 004 from the + name is meant to be 0.04 doping, and the GUI would try to interpret it as + 4.0 doping. Similarly 028 would be interpreted as 28.0, while it was + intended to mean 0.28 doping. These values should be edited and fixed + manually by clicking on the corresponding values and simply typing in the + correct values (Figure Figure 3.8). The data + can be ordered by doping by clicking the header. After you are done with + editing, order the data by doping, as otherwise the series of fits that is + to be automatically generated in the next step will be linked in an + arbitrary way in which the data were loaded, rather than to reflect the + scientific logic. There should be 6 data sets (with the initial x=0.0 data + set there will be 7 chained fits total after this setup is done). Next, + ensure that the template fit is selected on the fit tree. If this is the + case, the “OK” button becomes clickable. Clicking on the + “OK” button will generate a sequence of linked fits in the fit + tree in the order of the Ca content increase. Highlight all the fits in + the fit tree to start the sequential refinement of the doping series. +

+
+ + images/fig3-09 +
+

+ Figure 3.9: Sequence of refined parameters, such as lattice constants, + can be plotted vs doping using PDFgui plotting facilities. Figure + features lattice parameter b in Pbnm space group setting + for series of Ca-doped LaMnO3 samples for doping concentrations between + 0 and 0.28 at 10 K temperature. + +

+

+ After the convergence is achieved for all the fits in the fit tree, the + results can be displayed graphically such that various converged fit + parameters are plotted versus Ca content. An example is provided in Figure + Figure 3.9 + featuring one of the lattice parameters. +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

+ 3.3.5 Advanced post-processing of sequential refinement +

+ + + + +

+ While PDFgui allows to collate data from a series of sequential + refinements, there are many data query options that are not possible or + very tedious with a GUI. A particularly tedious task would be to extract + bond lengths for every temperature refined in a large series. The GUI + could supply menus for these tasks, but there are just too many options to + serve them all. In fact, the GUI just does not seem to be suitable + interface and things are much easier and more flexible to accomplish with + Python scripts. +

+

+ The idea is to setup and run sequential refinement with PDFgui, but to do + complicated data extractions with simple Python scripts. The PDFgui + installation includes a ‘tui’ (Text User + Interface) module that allows simple access to the data in a PDFgui + project. +

+

+ As a first example, let us assume that a converged sequential refinement + from + Sequential fitting of temperature series + has been saved under the same name as lmo-template.ddp. The + following Python script extracts temperatures and refined values of the + lattice parameter c +

+
+
+# python script
+from diffpy.pdfgui import tui             # import the tui library
+prj = tui.LoadProject('lmo-template.ddp') # read PDFgui project file
+temperatures = prj.getTemperatures()      # list of temperature values
+phases = prj.getPhases()                  # list of phase objects
+tcount = len(temperatures)                # number of temperature points
+
+for i in range(tcount):
+    Ti = temperatures[i]
+    # get the refined lattice parameter c
+    ci = phases[i].refined.lattice.c
+    print(Ti, ci)
+
+
+ +

+ Save the example above to a file, say “lmo_refined_c.py” and + run it as +

+
+
+python lmo_refined_c.py
+
+
+

+ Note that the script cannot load the unmodified + lmo-template.ddp file, because it does not have any refinement + results. +

+ +

+ The tutorial directory contains an advanced script + “tui_mno_bond_lengths.py”, which extracts the shortest Mn-O + bond lengths from the same PDFgui project. Please, see the comments in the + script for detailed explanation. +

+

+ To learn more about the tui module and about the objects and functions + that it returns, please see the API documentation for diffpy.pdfgui at + https://diffpy.github.io/diffpy.pdfgui. +

+

+ Feel free to ask at the + diffpy-users + group if you need help with data extracting scripts. +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

3.4 Nanoparticle structure

+ + + +

+ Determining the structure of a nanoparticle is notoriously difficult. + Diffraction experiments on nanoparticle samples yield broad diffraction + patterns that are hard to analyze using conventional crystallographic + approaches. The PDF analysis of nanoparticles is becoming increasingly + common. The PDF of a nanoparticle features sharp peaks conveying + structural information. The PDF signal gets damped at higher distances due + to the diminished number of pairs in the nanoparticle structure that + contribute to those distances. For certain simpler cases when + nanoparticles can be assumed to have spherical shape, characteristic + parameters such as nanoparticle diameter can be obtained. +

+

+ PDFgui is capable of modeling the effect of the finite nanoparticle size + using a spherical shape factor. Relevant PDF parameter is + spdiameter which is the diameter of the nanoparticle. This + parameter is highly correlated with various other parameters one would + like to refine, such as anisotropic ADPs, scale factors, correlated motion + parameters and so on. The refinement procedure is therefore rather + delicate and the solutions are not as robust as we are used to in cases of + crystalline materials. +

+

+ To illustrate the program capabilities we present a case of CdSe + nanoparticle approximately 3nm in size. It useful to have PDF data for a + crystalline reference, where available/applicable. In this exercise we + start from a prepared project file CdSe-nano.ddp. This project + contains two fits: the first one is a bulk CdSe reference, and the other + pertains to the CdSe nanoparticle. For consistency the PDFs of both bulk + and nano samples were obtained using Qmax of 14 inverse Angstroms, + although the bulk material PDF could have been processed using a higher + value. Synchrotron x-ray radiation was used to obtain the data at 300 K, + based on an experiment carried out at 6-ID-D at the Advanced Photon Source + at Argonne National Laboratory. The structure used for both data sets is + wurtzite, space group P63mc. From calibrations on Ni standard + Qdamp value of 0.0486 was obtained and is used here. +

+

+ We first carry out a refinement on the bulk reference. This is carried out + over a range from 1.7 to 19.8 Angstroms, using 7 parameters: lattice + parameters a and c (@1 and @2 respectively), + selenium z fractional coordinate (@11), isotropic ADPs for + Cd and Se (@21 and @23 respectively), the data scale factor + (@100), and finally correlated motion related quadratic term + coefficient delta2 (@200). The converged fit results in + parameter values that can be further used for reference when modeling the + nanoparticle data. We note that while the fit is reasonable, the values of + the isotropic ADPs are enlarged. The fit can be further improved if + anisotropic ADPs are introduced, although the z-direction related + components will remain enlarged due to the stacking disorder present in + the structure. The referent value of 5.69 for delta2 will be used + as a starting value for the nanoparticle fit. +

+

+ In the nanoparticle refinement we will use the same starting values for + all the parameters, except for delta2 and the nanoparticle + diameter, spdiameter. The former is set to 5.69, and the later to + 25 Angstroms. In other cases an approximate value of the spherical + nanoparticle size is usually known, and it is the best to start from a + reasonably good guess. Refining the nanoparticle data reveals nanoparticle + diameter of approximately 30 Angstroms, as further illustrated in + Figure 3.10. Enlarged values of isotropic ADPs + are again observed, and the fit is reasonably good. Further improvements + can be obtained by introducing anisotropic ADPs, where again values + related to the z-direction will remain abnormally large most probably due + to the stacking related disorder. A detailed description of this system + and successful PDF modeling can be found in this publication: + Quantitative size-dependent structure and strain determination of CdSe + nanoparticles using atomic pair distribution function analysis. +

+
+ + images/fig3-10 +
+

+ Figure 3.10: Fitting the structure of a nanoparticle: 3nm CdSe + nanoparticle example. + +

+

+ In general, a successful fitting scenario depends on particular details of + a structural problem one is determined to solve. The problem of + determining the structure of a nanoparticle remains difficult. PDFgui is + not intended to necessarily provide the solution, it is rather a + helpful tool in the process of determining new details and exploring the + space of possible solution candidates, yielding success in some instances. +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

4 Extras

+ + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

4.1 PDF plotting

+ + +

+ Plotting capabilities of PDFgui are provided through the plot control + panel and the quick-plot icon on the tool bar. A quick-plot is created by + selecting a node in the fit tree and then clicking the quick-plot icon in + the tool bar. The same quick-plot can be created by middle-clicking on a + node in the fit tree. +

+

+ The plot control allows for selection of x and y coordinates + for plotting. The actual quantities that could be assigned to the + coordinates is determined by selection of either Fit, or Phase, or Data on + the fit tree. The choices for x and y coordinates varies + depending on what is selected on the fit tree. Special options like index, + temperature and doping are available as choices for x in cases of + plotting multiple fit results from sequential fitting protocols. The plot + window provides essential functionality such as zoom, pan, cursor + coordinate tracking, and shifts. Features such as saving, exporting and + printing are also available. The principal intent of the plotting + functionality is to allow quick access to the fitting results to enhance + the scientific process. If data is selected on the fit tree, the user can + plot various aspects of the PDF function, such as data, model and + difference PDF profiles as a function of inter-atomic distance r. + If the fit or the phase are selected, then various parameters, both + structural and internal can be plotted instead. Since several formal + plotting examples were given through the tutorial exercise, and having + simplicity of usage in mind, no other plotting examples are provided, + hoping that the usage is sufficiently simple for users to master + individually with ease. An example plot of Rw vs refinement step is shown + in Figure 4.1 for Ni example. +

+ +
+ + images/fig4-01 +
+

+ Figure 4.1: Plotting window featuring Rw vs refinement step for Ni + example. The basic functionality for manipulating the plot is provided + through icons on the tool bar of the plotting window. + +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

4.2 Displaying the structure

+ + + +

+ For those users with a structural visualizer available in their system + configuration, PDFgui allows for initial or refined structures to be + visualized by passing required structural information that program. This + is achieved by highlighting a desired phase on the fit tree, and then + selecting Plot Initial Structure or + Plot Refined Structure from the “Phases” drop-down + menu. The quick-plot button (or middle-click) will also invoke the + structure viewer with the refined structure, or initial structure if the + refined structure does not yet exist. The control of the visualization is + dependent on the viewer used. The viewer can set under the + “Edit->Preferences” menu, see full details in + Configuration of structure viewer. +

+ +

+ An example Ni structure visualization with AtomEye is shown in + Figure 4.2. +

+
+ + images/fig4-02 +
+

+ Figure 4.2: Using AtomEye functionality (if installed on your system) + for 3D visualization of the initial and refined PDF structures: example + of Ni structure. + +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

4.3 Advanced usage and special needs

+ + + +

+ The PDFgui is designed to accommodate most common modeling situations. + However, it does not encapsulate all the capabilities available within the + modeling engine, such as calculation of differential PDFs, handling atoms + with special scattering properties, etc. Advanced usage of PDFfit2 engine + to resolve any such special modeling need that user may have is available + through usage of Python scripts in the expert command line mode, similar + to that featured in the PDFFIT program. Handling these situations requires + detailed knowledge of the PDFfit2 syntax based on Python, which is beyond + the scope of this user guide and will be described elsewhere. Refer to the + PDFfit2 API (https://www.diffpy.org/doc/pdffit2 + and the diffpy-users group (https://groups.google.com/d/forum/diffpy-users) for help with PDFfit2 scripting. +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

5 PDFgui reference sheets

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

5.1 PDFgui shortcut keys

+ + + + +

Fit tree

+
+
Ctrl+A
+

Select all items in the fit tree.

+
Ctrl+Shift+A
+
+

+ Once an object is selected on the fit tree, using this shortcut key + will select all the objects on the tree that are of the same type. For + example, if a single data set is selected on the tree, hitting this + hot key will make all the data sets belonging to all the fits in the + tree to become selected. This is particularly useful for + simultaneously plotting various fit results across the fit tree. +

+
+
Ctrl+C
+

Copy selected item.

+
Ctrl+X
+

Copy and delete selected item.

+
Ctrl+V
+
+

+ Paste previously copied item. Note that this will only paste the item + to a legal position in the tree. For example, a phase node cannot be + pasted into an empty tree. +

+
+
+ +

Phase configuration grid

+
+
Ctrl+A
+

Select all items.

+
/
+

Extend existing selection by atom types or indices.

+
Delete
+

Delete row. This will delete any wholly selected row.

+
Ctrl++
+

Add an atom to the grid.

+
Ctrl+-
+

Same as Delete.

+
+ +

Phase constraints grid

+
+
Ctrl+A
+

Select all items.

+
/
+

Extend existing selection by atom types or indices.

+
Delete
+

Delete contents of selected cells.

+
+ +
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

5.2 Command line arguments

+ + + + +

+ PDFgui can be started with an existing project file if it is given as a + command line argument. If the project file cannot be loaded, the program + terminates without starting the GUI an returns nonzero exit code. In + addition the pdfgui executable accepts the following command + line options: +

+
+
-h, --help
+

Show a brief usage information.

+
-V, --version
+

Show program version.

+
+ +

Debugging

+
+
--db-noed
+
+

+ Disable exception catching to error report dialog. Unhandled + exceptions should then result in program crash. +

+
+
--db-nocf
+
+

No confirmation - exit without asking to save modified project.

+
+
--db-pdb
+
+

+ Start Python debugger for unhandled error exceptions instead of + showing the error report dialog. +

+
+
+ +
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

5.3 List of PDFfit2 variables

+ + + +

+ The following is the list of PDFfit2 variables, including their default + values in parentheses, and a brief description and a note, where + appropriate. Note that some of the variables used in PDFFIT are renamed in + PDFfit2. The reference of these changes is provided for the convenience + and orientation of those users that are used to the old naming scheme. +

+ + + + + + + + + + + + + + + + + + + + +

New variables

+ +
+
Phase: spdiameter
+
+

+ (float Å, default 0 Å)
+ spdiameter is a particle diameter for PDF shape damping + function. Shape damping is not applied when + spdiameter equals zero. +

+
+
+ +
+
Phase: stepcut
+
+

+ (float Å, default 0 Å)
+ The PDF is truncated to zero at r-values greater than + stepcut, when positive. +

+
+
+ +
+
+ Phase: anisotropy(n) +
+
+

+ anisotropy(n) (bool, inferred from uij(n) values) +
+ Flag for anisotropic thermal displacements of atom n. Setting of + anisotropy(n) updates the uij(n) or + uisoequiv(n) values. +

+
+
+ +
+
+ Phase: uisoequiv(n) +
+
+

+ (float Å^2, calculated from uij(n) values) +
+ Isotropic thermal displacement of atom n or equivalent displacement + for anisotropic atom. For anisotropic sites the setting of + uisoequiv(n) scales values of the + uij(n) elements. uisoequiv(n) can be constrained + only for isotropic atoms. +

+
+
+ + + +

Renamed variables

+ +
+
Dataset: dscale
+
+

+ (float unitless, dsca[s] in PDFFIT)
+ Scale factor for the selected dataset. +

+
+
+ +
+
Dataset: qdamp
+
+

+ (float Å^-1, default 0 Å^-1, + qsig in PDFFIT)
+ PDF Gaussian dampening envelope due to limited Q-resolution. Not + applied when equal to zero. The Gaussian envelope is of the form +

+

+ images/eq-01.png +

+
+
+ +
+
Dataset: qbroad
+
+

+ (float Å^-1, default 0 Å^-1, + qalp in PDFFIT)
+ PDF peak broadening from increased intensity noise at high Q. Not + applied when equal zero. See the definition of the + PDF peak width for a detailed + explanation. +

+
+
+ +
+
Phase: uij(n)
+
+

+ (float Å^2, ij=(11, 22, 33, 12, 13, 23), + u[i,n] in PDFFIT)
+ Elements of anisotropic displacement tensor of atom n. +

+
+
+ +
+
Phase: occ(n)
+
+

+ (float unitless, o[n] in PDFFIT)
+ Occupancy of site n. +

+
+
+ +
+
Phase: pscale
+
+

+ (float unitless, csca[p] in PDFFIT)
+ Scale factor of the current phase. +

+
+
+ +
+
Phase: delta1
+
+

+ (float Å, default 0 Å, gamm in PDFFIT)
+ Coefficient for (1/r) contribution to the peak sharpening. See the + definition of the PDF peak width for a + detailed explanation. +

+
+
+ +
+
Phase: delta2
+
+

+ (float Å^2, default 0 Å^2, + delt in PDFFIT)
+ Coefficient for 1/r^2 contribution to the peak sharpening. + See the definition of the + PDF peak width for a detailed + explanation. +

+
+
+ +
+
Phase: sratio
+
+

+ (float unitless, default 1, srat in PDFFIT)
+ Sigma ratio for bonded atoms. Reduction factor for PDF peak width + accounting for correlated motion of bonded atoms. +

+
+
+ + + +

Preserved variables

+ +
+
Dataset: qmax
+
+

+ (float Å^-1, default 0 Å)
+ qmax cutoff is an experimental parameter having fixed value + determined during the PDF data processing in the Fourier transform + step. Finite data range used in the Fourier transform is a source of + termination ripples. Termination ripples are not applied in PDF + calculation when qmax is set to zero. The effect is + simulated using fast Fourier transformation (FFT). The original array + of G values is first padded by the same number of zeros and + then by more zeros to reach the next power of 2. The padded + G array is transformed by FFT and any coefficients + F that correspond to Q values greater than + qmax are reset to zero. The adjusted coefficient array + F is then transformed by inverse FFT back to + G’ and cut out at the original length of G. The + imaginary components in G’ are ignored as they are only + due to round-off errors. +

+
+
+ +
+
Phase: lat(i)
+
+

+ (float Å or degrees, i=1,2,...,6)
+ Lattice parameters a, b, c, alpha, beta, gamma of the current phase. + Can be also used as lat(’a’) etc. +

+
+
+ +
+
+ Phase: x(n), y(n), z(n) +
+
+

+ (float unitless)
+ Fractional coordinates for atom n. +

+
+
+ +
+
Phase: rcut
+
+

+ (float Å, default 0 Å)
+ Radius cutoff for applying sratio sharpening factor. +

+
+
+ +
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

5.4 PDF peak width

+ +

+ The PDF peak width contains contributions from thermal and zero point + displacements as well as static disorder. For large distances r the + motion of the two contributing atoms is uncorrelated. For small distances, + however, the motion can be strongly correlated leading to a sharpening of + the first peak(s) in the observed PDF. PDFfit2 provides three different + correction terms for the PDF peak width. The final width is given by +

+

images/eq-02.png

+

+ Here the primed sigma is the peak width without correlation, which is + computed from the anisotropic displacement parameters. The first two terms + correct for the effects of correlated motion. Within the scope of the + users guide, we just mention that the term + delta2/r^2 describes the low temperature behavior, and + term delta1/r describes the high temperature case. Since the + two parameters are highly correlated, one will in practice choose which + one to refine. The last term in the equation models the PDF peak + broadening as a result of the Q resolution of the diffractometer. In many + cases this term will only be significant for refinements over wider + r-ranges. Note that the Q resolution also results in an exponential + dampening of the PDF peaks which is modeled using the parameter + qdamp. +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + [ > ][ >> ]     + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

Index

+ + + + + + +
Jump to:   + A +   + C +   + D +   + E +   + F +   + G +   + H +   + I +   + M +   + N +   + P +   + Q +   + R +   + S +   + T +   + U +   + V +   + W +   +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Index Entry Section

A
+ acknowledgments +  Acknowledgments
advanced usage  + 4.3 Advanced usage and special needs +
AtomEye viewer  + 1.4.2 Configuration of structure viewer +
availability 1.3 Availability

C
+ calculating PDF +   + 3.2 Calculating PDF from a structure +
+ command line options +   + 5.2 Command line arguments +
Community 1.6 Community
copyright Acknowledgments
+ create new structure +   + 3.1 Building structure model using crystal symmetry +

D
+ data extraction +   + 3.3.5 Advanced post-processing of sequential refinement +
development  + 1.4.3 Installation from sources +
+ displaying the structure +   + 4.2 Displaying the structure +
doping series  + 3.3.4 Sequential fitting of doping series +

E
examples  + 3 Examples and tutorials +
extras 4 Extras

F
+ fit configuration +   + 2.2 Creating a simple fit using a preexisting structure file +

G
Git repository  + 1.4.3 Installation from sources +

H
hot keys  + 5.1 PDFgui shortcut keys +

I
installation 1.4 Installation
introduction 1 Introduction
isotope Footnotes

M
mail-list 1.6 Community
+ multistage fitting +   + 3.3.1 Multistage fitting +

N
+ nanoparticle diameter +   + 3.4 Nanoparticle structure +
+ nanoparticle structure +   + 3.4 Nanoparticle structure +

P
PDF plotting 4.1 PDF plotting
PDFfit2 1.1 PDFfit2
+ PDFfit2 variables +   + 5.3 List of PDFfit2 variables +
PDFgui 1.2 PDFgui
+ pdfgui arguments +   + 5.2 Command line arguments +
PDFgui layout 2.1 PDFgui layout
+ PDFgui reference sheets +   + 5 PDFgui reference sheets +
+ PDFgui shortcut keys +   + 5.1 PDFgui shortcut keys +
+ project post-processing +   + 3.3.5 Advanced post-processing of sequential refinement +

Q
quick start 2 Quick start

R
r-series  + 3.3.2 Sequential fitting of incremental r-series +
+ reference sheets +   + 5 PDFgui reference sheets +
+ refinement configuration +   + 2.2 Creating a simple fit using a preexisting structure file +

S
+ sequential fitting +   + 3.3 Sequential fitting +
+ sequential fitting +   + 3.3.2 Sequential fitting of incremental r-series +
+ sequential fitting +   + 3.3.3 Sequential fitting of temperature series +
+ sequential fitting +   + 3.3.4 Sequential fitting of doping series +
shortcuts  + 5.1 PDFgui shortcut keys +
special needs  + 4.3 Advanced usage and special needs +
+ startup options +   + 5.2 Command line arguments +
+ structure visualization +   + 4.2 Displaying the structure +
+ symmetry expansion +   + 3.1 Building structure model using crystal symmetry +

T
+ temperature series +   + 3.3.3 Sequential fitting of temperature series +
tui scripts  + 3.3.5 Advanced post-processing of sequential refinement +
tutorials  + 3 Examples and tutorials +

U
user groups 1.6 Community

V
variables  + 5.3 List of PDFfit2 variables +
versions 1.5 What is new
+ visualization setup +   + 1.4.2 Configuration of structure viewer +

W
whatisnew 1.5 What is new

+ + + + + +
Jump to:   + A +   + C +   + D +   + E +   + F +   + G +   + H +   + I +   + M +   + N +   + P +   + Q +   + R +   + S +   + T +   + U +   + V +   + W +   +
+ +
+ + + + + + + + +
+ [Top] + + [Contents] + + [Index] + + [ ? ] +
+

Footnotes

+ +

(1)

+ + +

+ To enter a specific isotope, use the “NucleonNumber-Symbol” + syntax, for example “12-C”. Deuterium and tritium can be + entered also as “D” and “T” in addition to the + normal syntax “2-H” and “3-H”. +

+
+ + + + + + + + +
+ [Top] + + [Contents] + + [Index] + + [ ? ] +
+

Table of Contents

+ + +
+ + + + + + + + +
+ [Top] + + [Contents] + + [Index] + + [ ? ] +
+

About This Document

+ +

+ This document was generated on April 25, 2023 using + texi2html 5.0. +

+

The buttons in the navigation panels have the following meaning:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ButtonNameGo toFrom 1.2.3 go to
[ << ]FastBackBeginning of this chapter or previous chapter1
[ < ]BackPrevious section in reading order1.2.2
[ Up ]UpUp section1.2
[ > ]ForwardNext section in reading order1.2.4
[ >> ]FastForwardNext chapter2
[Top]TopCover (top) of document 
[Contents]ContentsTable of contents 
[Index]IndexIndex 
[ ? ]AboutAbout (help) 
+ +

+ where the Example assumes that the current position is + at Subsubsection One-Two-Three of a document of the + following structure: +

+ +
    +
  • + 1. Section One +
      +
    • + 1.1 Subsection One-One +
        +
      • ...
      • +
      +
    • +
    • + 1.2 Subsection One-Two +
        +
      • 1.2.1 Subsubsection One-Two-One
      • +
      • 1.2.2 Subsubsection One-Two-Two
      • +
      • + 1.2.3 Subsubsection One-Two-Three     + <== Current Position +
      • +
      • 1.2.4 Subsubsection One-Two-Four
      • +
      +
    • +
    • + 1.3 Subsection One-Three +
        +
      • ...
      • +
      +
    • +
    • 1.4 Subsection One-Four
    • +
    +
  • +
+ +
+

+ + This document was generated on April 25, 2023 using + texi2html 5.0. + +
+

+ + +
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/news/TEMPLATE.rst b/news/TEMPLATE.rst deleted file mode 100644 index 790d30b1..00000000 --- a/news/TEMPLATE.rst +++ /dev/null @@ -1,23 +0,0 @@ -**Added:** - -* - -**Changed:** - -* - -**Deprecated:** - -* - -**Removed:** - -* - -**Fixed:** - -* - -**Security:** - -* diff --git a/news/doc.rst b/news/doc.rst deleted file mode 100644 index b0ec659f..00000000 --- a/news/doc.rst +++ /dev/null @@ -1,23 +0,0 @@ -**Added:** - -* - -**Changed:** - -* - -**Deprecated:** - -* - -**Removed:** - -* - -**Fixed:** - -* Support ``scikit-package`` Level 5 standard (https://scikit-package.github.io/scikit-package/). - -**Security:** - -* diff --git a/news/rm-texinfo.rst b/news/rm-texinfo.rst deleted file mode 100644 index 7c70206f..00000000 --- a/news/rm-texinfo.rst +++ /dev/null @@ -1,23 +0,0 @@ -**Added:** - -* Information from the old manual is merged into the nline docs. - -**Changed:** - -* - -**Deprecated:** - -* - -**Removed:** - -* Old PDF version of the manual. - -**Fixed:** - -* - -**Security:** - -* diff --git a/objects.inv b/objects.inv new file mode 100644 index 00000000..f77a0854 Binary files /dev/null and b/objects.inv differ diff --git a/pdfgui.html b/pdfgui.html new file mode 100644 index 00000000..50c9c499 --- /dev/null +++ b/pdfgui.html @@ -0,0 +1,5560 @@ + + + + + + PDFgui user guide, release 2.0, May 2023 + + + + + + + + + + + +

PDFgui user guide

+

2.0 release

+

May 2023

+ C. L. Farrow, P. Juhás, J. W. Liu, D. Bryndin, E. S. Božin,
+ J. Bloch, Th. Proffen, and S. J. L. Billinge
+ +
+ + + + + + + + + + +
[ < ] + [ + > ] +   + [Contents] + + [Index] + + [ ? ] +
+ +

Acknowledgments

+ +

+ This software was originally developed by the Billinge group as part of + the Distributed Data Analysis of Neutron Scattering Experiments (DANSE) + project funded by the US National Science Foundation under grant + DMR-0520547. Developments of PDFfit2 were funded by NSF grant DMR-0304391 + in the Billinge group, and with support from Michigan State University and + Columbia University. Any opinions, findings, and conclusions or + recommendations expressed in this material are those of the author(s) and + do not necessarily reflect the views of the respective funding bodies. + Subsequent development was done in the Billinge group at Columbia + University and then in collaboration between the Billinge group at + Columbia and Pavol Juhas at Brookhaven National Laboratory. Moving + forward, PDFgui will be maintained as a community project with + contributions welcomed from many people. +

+

+ Several of the examples in the tutorial part were made possible and + benefited from samples synthesized by J. F. Mitchell, and from data + collected and processed by M. Schmidt, P. G. Radaelli, and X. Qiu. +

+

+ If you use this program to do productive scientific research that leads to + publication, we ask that you acknowledge use of the program by citing the + following paper in your publication: +

+
+

+ C. L. Farrow, P. Juhás, J. W. Liu, D. Bryndin, E. S. Božin, J. Bloch, + Th. Proffen and S. J. L. Billinge, + PDFfit2 and PDFgui: computer programs for studying nanostructure in + crystals, J. Phys.: Condens. Matter, 19, 335219 (2007) +

+
+ +

+ Up to the release 1.1.2 (February 2017) the copyright was held by the + institutions that hosted the work as follows: Copyright 2006-2007, Board + of Trustees of Michigan State University, Copyright 2008-2012, Board of + Trustees of Columbia University in the city of New York. Copyright 2013, + Brookhaven National Laboratory (Copyright holder indicated in each source + file). +

+ +

+ As of February 2017, and the 1.1.2 release, PDFgui has moved to a shared + copyright model. PDFgui uses a shared copyright model. Each contributor + maintains copyright over their contributions to PDFgui. But, it is + important to note that these contributions are typically only changes to + the repositories. Thus, the PDFgui source code, in its entirety, is not + the copyright of any single person or institution. Instead, it is the + collective copyright of the entire PDFgui Development Team. If individual + contributors want to maintain a record of what changes/contributions they + have specific copyright on, they should indicate their copyright in the + commit message of the change, when they commit the change to one of the + PDFgui repositories. The PDFgui Development Team is the set of all + contributors to the PDFgui project. A full list can be obtained from the + git version control logs. For more information please visit + https://www.diffpy.org or contact + Prof. Simon Billinge at + sb2896@columbia.edu. +

+ + +

Preface

+ +

Using PDFgui and PDFfit2

+

+ Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: +

+ +

+ Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +

+ +

+ 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. +

+ +

+ Neither the names of COLUMBIA UNIVERSITY, MICHIGAN STATE UNIVERSITY nor + the names of their contributors may be used to endorse or promote products + derived from this software without specific prior written permission. +

+ + +

Disclaimer

+ +

+ 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 OWNER + 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. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ < ] + + [ Up ] + + [ > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

1 Introduction

+ + +

+ PDFgui is a graphical interface built on the PDFfit2 engine, which is a + program and programming library for real-space refinement of crystal + structures based on the atomic pair distribution function (PDF) method. + PDFgui organizes fits and simplifies many data analysis tasks, such as + configuring and plotting multiple fits. PDFfit2 is capable of fitting a + theoretical three dimensional structure to atomic pair distribution + function data and is ideal for nanoscale investigations. The fit system + accounts for lattice constants, atomic positions and anisotropic atomic + displacement parameters, correlated atomic motion, and experimental + factors that may affect the data. The atomic positions and thermal + coefficients can be constrained to follow symmetry requirements of an + arbitrary space group. The PDFfit2 engine is written in C++ and accessible + via Python, allowing it to inter-operate with other Python programs. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

1.1 PDFfit2

+ + +

+ PDFfit2 is a major upgrade to PDFfit, and inherits many of its features. + PDFfit is capable of fitting a theoretical three-dimensional structure to + an experimentally determined PDF. It can simultaneously fit multiple + structures, accounting for different structural phases in a material. + PDFfit has a constraint system that allows expressing structure variables + as simple functions of fitted parameters. PDFfit structure variables + include lattice constants, data and phase scale factors, atomic site + occupation, anisotropic atomic displacement parameters (ADPs), and atomic + vibrational correlations. PDFfit has a built-in FORTRAN-style command + language that understands simple FOR loops and some built in arithmetic + functions. +

+

+ The original PDFfit was written in FORTRAN-77, which imposes some + limitations on the program. For example, it uses fixed-size arrays for + internal storage. This precludes the analysis of structures with large + cells without modifying the code. Though the constraint system is + powerful, it requires that a constraint equation be accompanied by its + first derivative. This places the burden of determining the derivatives on + the user, which can introduce errors that lead to instability in the + convergence. Furthermore, the code is monolithic, not easily extensible + and hard to integrate with external programs. +

+

+ The primary focus of PDFfit2 development was to remedy the limitations of + PDFfit while extending its functionality. The old PDFfit engine has been + completely rewritten in C++, and many bugs have been fixed. The new engine + uses dynamic memory allocation so that the size of the structure or extent + of the fit-range of the PDF is limited only by the physical memory + available. The constraint system has also been upgraded. The program + automatically + computes the analytical derivatives of the constraints that are required + by the minimization routine. This simplifies user input and reduces the + possibility of errors. In addition, new fitting parameters for handling + dynamic atomic correlations and experimental resolution have been + introduced as well. +

+

+ Instead of rewriting the PDFfit command interpreter, which is used to + define the fitting problem and to control and run the refinement, its + functions are carried out using the Python language (https://www.python.org). Python is a powerful, cross-platform, open-source interpreted + programming language (i.e., it does not need to be compiled to run, + similar to scripting) that emphasizes object-oriented and modular design. + PDFfit2 scripts written in Python syntax take the place of PDFfit macros + and the Python interpreter can handle everything that the old interpreter + could, and more. Using Python as an interpreter allows PDFfit2 to be + combined with and enhanced by other Python libraries. We make use of this + capability with PDFgui as described below. +

+ +
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

1.2 PDFgui

+ + +

+ The PDFfit2 engine can be used either directly from the Python command + line, or as part of larger and more complex software applications. The + first application built on PDFfit2 is PDFgui, a graphical environment for + PDF fitting. +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+

1.2.1 Design principles

+ +

+ PDFgui has been designed to provide users with an easy-to-use yet powerful + interface for fitting structure models to PDF data. It makes use of an + object-oriented architecture, which makes it highly extensible and + maintainable. This allows for powerful usability features such as + real-time plotting. PDFgui has been designed with multitasking in mind. It + is multi-threaded so that the work being done by the PDFfit2 engine does + not interfere with the tasks of the user interface. +

+

+ PDFgui is written in the Python programming language. Python features a + relaxed and friendly syntax, supports “write once, run + anywhere” portability, and has extensive libraries and modules for + virtually every task. Software codes written in a variety of programming + languages can be bound into Python, which allows them to be used together. + Python is becoming a popular choice in the scientific computation + community. +

+

+ PDFgui’s interface is built using wxPython (https://www.wxpython.org), the Python package for wxWidgets, a mature cross-platform GUI library. + Graphical applications written in wxPython provide a look and feel native + to the platform on which they are run. PDFgui is designed to run on + Windows, Mac OS, Linux, and all major Unix systems. +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+

1.2.2 Capabilities

+ +

+ PDFgui contains all of the functionality of PDFfit2 along with additional + enhancements for usability. Mundane tasks are handled by the program and + difficult tasks are made simple. PDFgui can manage multiple fits at once. + Each fit can have multiple experimental data sets and structure models. + Fits in a sequence can call upon other fits for their starting parameters, + and configured fits can be queued to run while the user is away. All the + initial, final, and intermediate data are stored in a platform independent + project file that can be loaded on any computer. All management tasks, + such as fit creation, configuration, modification, and visualization, can + be done through the graphical interface. +

+

+ PDFgui supports space group operations. Users can define an asymmetric + unit and let PDFgui expand it to a full cell with all symmetry related + positions. PDFgui can also generate symmetry constraints for atom + positions and atomic ADPs. Users just need to specify the space group, and + the program will identify equivalent sites and generate constraint + equations for their coordinates and temperature factors to keep the + structure consistent with the symmetry requirements. This can be done + either for all atoms in the structure or for an arbitrary subset - for + example when it is known that only a certain species show a local + distortion. The code for space group definitions was provided by the + Python Macromolecular Library (mmLib, + http://pymmlib.sourceforge.net). This was extened to include non-standard space groups using the + Computational Crystallography Toolbox (cctbx, + https://cctbx.github.io). PDFgui + also supports supercell expansion of a normal unit cell. +

+

+ PDFgui uses the matplotlib (https://matplotlib.org) Python package for 2D plotting of data and results. Matplotlib has a + friendly interface so the user can quickly and easily view the results of + a fitting. PDFgui lets users plot data from a series of fits and plot it + against selected meta-data (temperature, doping, etc.), plot the results + of several fits in the same window, plot the PDF in real time as the + fitting is running, plot the parameters or variables in real time as the + refinement evolves, and save plots in common image formats or export the + data to a text file. PDFgui can be configured to use one of many structure + visualization packages, such as AtomEye (http://li.mit.edu/A/Graphics/A/) or PyMOL (https://www.pymol.org). +

+

+ PDFgui supports built-in macros for advanced fits. For a set of + experimental data from one system at different temperatures or doping + levels, PDFgui can expand a template fit to a series of related fits. + Another PDFgui macro makes it easy to set up boxcar fits, where the same + model is fit over different r-ranges of the PDF data. +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

1.3 Availability

+ + +

+ PDFfit2 and PDFgui are open source and distributed under a BSD license. + They run on Windows, Mac OS, Linux, and all major Unix systems. The source + code is freely available. For more information please contact Professor + Simon Billinge (sb2896@columbia.edu) or consult the web-page + https://www.diffpy.org. News of + updates and releases will be posted at this website and on the + diffpy-users group at + https://groups.google.com/d/forum/diffpy-users. +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

1.4 Installation

+ + +

+ PDFgui is included as a part of DiffPy, a suite of Python and C++ + libraries for structure analysis from diffraction data. For more + information about DiffPy products visit the project homepage at + https://www.diffpy.org. +

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

1.4.1 Installation for Anaconda Python

+ +

+ As of version 1.1 PDFgui is distributed as a pre-built package for + Anaconda Python. This method makes + it easier to distribute software updates and also results in the same + installation procedure on all supported platforms. +

+

+ To install PDFgui, download and install Anaconda for Python 2.7 from + https://www.anaconda.com/download. When ready open a terminal application (or + Anaconda Command Prompt on Windows) and use the + conda package manager to install PDFgui from the + “diffpy” channel of Anaconda packages +

+
+
+conda config --add channels diffpy
+conda install diffpy.pdfgui
+
+
+ +

+ The first command instructs Anaconda system to always check the + “diffpy” channel for any new software. Such configuration + allows to obtain PDFgui updates using +

+
+
+conda update diffpy.pdfgui
+
+
+ +

+ It is however not strictly necessary to make the “diffpy” + channel permanent. The same effect can be accomplished by adding the + ‘--channel=diffpy’ option to either of conda install or + conda update commands. +

+

+ After installation is complete PDFgui can be started from a terminal by + entering pdfgui command or on Windows by using the DiffPy + start menu. PDFgui can be also started from the “Launcher” + program that is included with Anaconda. +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

1.4.2 Configuration of structure viewer

+ + +

+ PDFgui can visualize 3D structures by displaying them with an external + visualization program. The visualization program needs to be specified + together with a suitable structure format in the “Edit → + Preferences” menu in PDFgui. The structure plotting feature has been + tested with the following programs: +

+
+
AtomEye
+
+

+ AtomEye structure viewer, XCFG format
+ http://li.mit.edu/A/Graphics/A/ +

+
+
PyMOL
+
+

+ PyMOL structure viewer, PDB format
+ https://www.pymol.org +

+
+
+ +

+ A note for AtomEye users: + +

+

+ AtomEye requires its standard output is connected to a terminal. On Unix + this happens when pdfgui is started from a terminal. However + if you prefer to start PDFgui using a desktop shortcut or via “Run + Application” dialog of the window manager, you need to put the + following information to the “Edit → Preferences” menu of + PDFgui. +

+
+
+Structure viewer executable: xterm
+Argument string: -iconic -e ATOMEYE %s
+Structure format: xcfg
+
+
+

In the above, ATOMEYE is the path to the ATOMEYE executable.

+

+ For Cygwin users, the workaround is to launch the executable from a batch + file. Batch files can only run in a command window on Windows and so + AtomEye’s requirements would be for sure satisfied. In addition the + batch file can be used to adjust environment variables: +

+
+
+atomeye.bat
+------------------------------------------------------------------------
+set DISPLAY=localhost:0
+set PATH=C:\cygwin\bin;C:\cygwin\usr\X11R6\bin;C:\ATOMEYE_DIR;%PATH%
+start A.exe %*
+------------------------------------------------------------------------
+
+
+ +

+ Here ATOMEYE_DIR needs to be replaced with a proper path. Make + sure that the X-server application included with Cygwin is started. +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

1.4.3 Installation from sources

+ + + + +

+ PDFgui sources are available in a public + Git repository at + https://github.com/diffpy/diffpy.pdfgui. Feel free to fork this project on GitHub and contribute. To use the + latest development version clone the Git repository to your computer and + install it in a development mode so that sources are used directly rather + than copied to a system location. It is also recommended to uninstall the + Anaconda package for PDFgui, so that there is no confusion as to what + version is the active one. Here are the shell commands that would do it: +

+
+
+# Install PDFgui together with software dependencies.
+conda install --channel=diffpy diffpy.pdfgui
+
+# Make room for the version from sources.  Keep dependencies installed.
+conda remove diffpy.pdfgui
+
+# Obtain a clone of the PDFgui Git repository.
+git clone https://github.com/diffpy/diffpy.pdfgui.git
+
+# Install PDFgui sources in a development mode.
+cd diffpy.pdfgui
+python setup.py develop
+
+
+ +

+ To verify that PDFgui is indeed loaded from the local source repository + run +

+
+
+python -m pydoc diffpy.pdfgui
+
+
+ +

+ and check the path displayed in the FILE section. The application + integrity can be verified by executing all builtin tests using +

+
+
+python -m diffpy.pdfgui.tests.rundeps
+
+
+ +

+ Use git pull to bring your source directory into sync with + the latest updates in the main repository. It is recommend to afterwards + do `setup.py develop again to refresh the version metadata + associated with the program: +

+
+
+git pull
+python setup.py develop
+
+
+ +

+ To revert PDFgui installation from the source-code installation back to + the pre-built Anaconda package do +

+
+
+pip uninstall diffpy.pdfgui
+conda install --channel=diffpy diffpy.pdfgui
+
+
+ +
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

1.5 What is new

+ + + + +

Version 1.1, released March 2016

+ +

+ Improvements and modifications since the last major release 1.0-r3067 from + April 2009. +

+
+
Anaconda installer
+
+

+ PDFgui is now distributed as a pre-built package for Anaconda Python. + The program is available for all platforms supported by Anaconda, + i.e., for 32 and 64-bit Linux, Mac OS X, and for 32 and 64-bit + Windows. +

+
+
upgrade for recent GUI libraries
+
+

+ Source codes were updated to work with WX GUI toolkit 2.9 or later. + Fixed blacked-out text fields on Mac OS X. Fixed missing toolbar in + plot-windows on Mac OS X. +

+
+
select atoms menu
+
+

+ Added “Select Atoms” context menu to the Phase + Configuration and Phase Constraints panels. This selects atom rows by + a range of indices or by atom type. Added keyboard shortcut + / for activating the atom-selection dialog. +

+
+
small enhancements
+
+

+ Fixed problems with r-grid interpolation near data boundaries. + Allow use of CIF-defined space groups for symmetry constraints. Use + consistent numbering for parameters created by symmetry constraints. + Improved export data tool in plot windows to group y-arrays + that are on the same x grid. Enhanced supercell expansion to + also adjust the coordinate constraints. +

+
+
project moved to GitHub
+
+

+ PDFgui source repository was converted from subversion to a Git + repository at + https://github.com/diffpy/diffpy.pdfgui. Project now uses Git tags to define software release and version + data. +

+
+
Unicode support
+
+

+ Allow accented characters in project filenames and in folder paths + where located. Allow accented characters for naming the fit tree + items. Note that such projects are unlikely to work with older + versions of PDFgui. Fix failure to exit when there is some uncaught + error in the at-exit cleanup functions. +

+
+
PDFgui tests
+
+

+ PDFgui installation now includes built-in tests. Added facility to + test PDFgui and all its DiffPy components. Implemented automated + testing and generation of test coverage reports when sources on GitHub + change. +

+
+
bug fixes
+
+

+ Quite a few. Consult the code history at + https://github.com/diffpy/diffpy.pdfgui/commits. +

+
+
+ + +

Version 1.0, released April 2009

+ +

+ This section describes improvements and modifications since the last + beta-release 1.0b.1792 from December 2007. +

+
+
updates and installation
+
+

+ PDFgui can be installed or updated with a simple run of the + easy_install script. easy_install checks our online code repository + for any newer versions and takes care of their download and + installation. It can be also used to add future DiffPy components as + they become available. This should work for Linux, Mac and Windows. +

+
+
Windows installer
+
+

+ The updated Windows package includes full installation of Python 2.5 + and script for code updates. PDFgui can be installed under normal + Python2.5 tree if it has the easy_install script. +

+
+
particle shape correction stored with phase
+
+

+ The previous release of PDFgui had spherical shape correction factors + stored with PDF dataset. The new layout is more logical and allows + multi-phase refinements with separate shape corrections. +

+
+
step shape factor
+
+

+ Defined new shape factor that cuts off the simulated PDF at user + defined r-limit. +

+
+
cumulative Rw
+
+

+ Implemented calculation of cumulative Rw and option to show it in + PDFgui plot window. +

+
+
project post-processing
+
+

+ Implemented new module ‘tui’ (text user + interface) for simple access to the data in PDFgui project files. The + ‘tui’ module can be used in + easy-to-understand Python scripts for arbitrary data extraction or + conversion. It should be useful for project files with large + temperature or compositional series of PDF refinements. +

+
+
structure visualization
+
+

+ PDFgui can now show structures with any external structure viewer, + that accepts structure file as a command-line argument. +

+
+
space group representations
+
+

+ Added 249 space group representations in non-standard settings. The + new representations were generated using the + cctbx library and helpful hints + from Ralf W. Grosse-Kunstleve. +

+
+
symmetry constraints
+
+

+ Fixed issues with generation of symmetry requirements for the ADP + tensors. +

+
+
default ADP tensors
+
+

+ PDF contributions are not counted for atoms that have ADP tensors + Uij equal zero. Atoms are now inserted with a non-zero + Uij matrix. Added warning when a phase loaded from file has + atoms with zero ADPs. +

+
+
temperature series macro
+
+

+ The temperature series macro was broken for datasets at equal + temperature or when temperature contained decimal point. Improved file + and temperature sorting in the temperature series dialog. +

+
+
journal panel
+

Fixed shortcut key handling and font size issues.

+
startup option ‘--db-pdb
+
+

+ The new command-line option starts Python debugger on PDFgui crash + instead of displaying error report dialog. +

+
+
grid interpolation
+
+

+ Fixed problems with r-grid interpolation appearing due to round-off + errors. +

+
+
data load on Windows
+
+

+ Windows version could not read PDF datasets with NaN (not-a-number) + values in the dGr column, because NaN is not supported by the Windows + C-library. Added check for NaN-s before converting to float. +

+
+
+ +
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

1.6 Community

+ + + + +

+ There are two Google groups for support and development of PDFgui and + other DiffPy software. Visit the links below for message archives or + instructions on subscription and posting. +

+
+
+ diffpy-users + https://groups.google.com/d/forum/diffpy-users +
+
+

+ Help on usage of PDFgui, PDFfit2 and other DiffPy packages. This group + should become a knowledge base of PDFgui user tips, tricks and + troubleshooting. Feel free to ask your question here. +

+
+
+ diffpy-dev + https://groups.google.com/d/forum/diffpy-dev +
+
+

+ For discussions about development and changes of PDFgui, PDFfit2 and + DiffPy library in general. +

+
+
+ +
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

2 Quick start

+ + +

+ In this chapter the PDFgui layout is briefly described, followed by a + simple tutorial example, spanning the GUI functionality and aimed at + novice users. Users familiar with the basics can proceed to + Examples and tutorials, or use + PDFgui reference sheets. All the + files used in examples are available in the source distribution or can be + downloaded from the DiffPy website. +

+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

2.1 PDFgui layout

+ + +

+ Once PDFgui is invoked, a PDFgui window comes up. Its layout consists of a + “Menu Bar”, a “Tool Bar”, and a set of four panes. + The menu bar contains drop-down menus that provide various aspects of + PDFgui functionality. The tool bar features icons for commonly used + operations: creating a new project, opening an existing project, saving a + project, executing a refinement or calculation, stopping a refinement or + calculation, and making a quick plot. The four panes consist of the + “Fit Tree”, “Plot Control”, the“Current + Action” pane, and the “PDFfit2 Output” panel. These are + all shown in Figure 2.1. +

+

+ The fit tree is used in setting up a fit protocol. The plot control serves + the user’s needs for graphically displaying the fits, as well as + various fit-related parameters. The content of the current action panel + changes as the refinement is being set up. It is a functional panel + through which the user configures the fit attributes, sets the fit + constraints, reviews the fit settings, displays fitting results, and also + carries out other setup steps. The progress of the PDFfit2 refinement + engine is displayed in the PDFfit2 output panel. All panels except the + current action panel are dockable windows that can be dragged across the + screen, resized and arranged to accommodate the individual visual needs of + the user. The window layout can also be controlled via the + “View” drop-down menu on the menu bar. An important part of + the PDFgui operativity is also conveniently available through mouse + operations such as select and right-click. +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

+ 2.2 Creating a simple fit using a preexisting structure file +

+ + + +

+ The purpose of this example is to familiarize the novice user with the + PDFgui basics. The goal is to create a simple fit of Ni PDF from a + preexisting structure file, associate a dataset with the refinement, + configure and execute a refinement, and display the result. Files to be + used in this exercise are Ni.stru and Ni-xray.gr (found in + the tutorial directory). To start, invoke PDFgui by clicking on the icon + on your desktop, selecting the program from your system’s program + menu, or by typing pdfgui in a terminal window. +

+

+ First a new fit needs to be established. In the fit tree right-click the + mouse button, and select New Fit. This will generate a new fit + called “Fit 1” in the fit tree. The name of the fit is + highlighted and editable, so you need only to start typing to give the fit + a new name. The current action panel will display the pages that will hold + the fit and the results output. Note that the same action could be + achieved by selecting the New Fit option from the + “Fits” drop-down menu on the menu bar. +

+

+ The next step in populating the fit tree is to load a structural model. + First, select the fit icon in the fit tree pane. Then, right-click the + mouse, invoking a drop-down menu. Select Insert Phase, which will + modify the current action panel. The same action could be performed from + the “Phases” drop-down menu on the menu bar by selecting + New Phase. In the current action panel options are offered to load + a structure from a file or to generate it from scratch. In this exercise a + preexisting structure file Ni.stru is to be loaded. +

+
+ + images/fig2-01 +
+

+ Figure 2.1: PDFgui window with fit tree and Plot Control panels to the + left and current action panel to the right. The fit tree panel features + the current fit and the loaded Ni structure which is selected. The + current action panel displays phase configuration within the + “Configure” tab. + +

+

+ Figure 2.1 shows the PDFgui appearance at this + stage of the exercise. The current action panel has three tabs, + “Configure”, “Constraints”, and + “Results” that could be selected using mouse. These will be + returned to later. The “Configure” panel displays + configuration information from the structure file. The top portion + contains lattice parameters, phase scale factor, and a set of parameters + intended to be used to account for correlated atomic motion effects that + typically sharpen the nearest neighbor PDF peak. These are delta1, + delta2, sratio, and rcut. The spdiameter and + stepcut parameters include scatterer size effects in the PDF. These + parameters will be described later. The bottom part of the panel contains + standard unit cell content related information such as atomic species, + their fractional coordinates, anisotropic ADPs, and site occupancies. +

+

+ The next step is to load an experimental data set to be fit. Selected the + fit and right-click to bring up the context menu. From the menu choose + Insert Data Set. The same action could be performed through the + “Data” menu on the menu bar. The current action panel changes + accordingly, giving an option for a data set to be loaded from a file. In + this exercise Ni PDF data obtained using synchrotron x-ray radiation + collected at 6-ID-D at the Advanced Photon Source is used. This is + contained in a file Ni-xray.gr, which is to be loaded. Note that + among the exercise files there is also a file Ni-neutron.gr, + obtained using neutron radiation at the GPPD diffractometer at the IPNS + facility at the Argonne National Laboratory. Both x-ray and neutron + datasets were collected at 300 K. +

+
+ + images/fig2-02 +
+

+ Figure 2.2: Appearance of a PDFgui window after a PDF dataset is + loaded. The Fit Tree panel features the current fit, loaded Ni + structure, and loaded Ni PDF dataset, G(r), which is selected. The + current action panel displays data set configuration within the + “Configure” tab. + +

+

+ Figure 2.2 shows the PDFgui appearance at this + stage of the exercise. The “Configure” panel displays + configuration information from the data file. It should be noted that + depending on the software used to prepare the experimental PDF from the + raw data, the file may (or may not) contain meta-data reflecting the + experimental conditions and configuration. For example, software PDFgetX2 + and PDFgetN, which can be used to prepare PDFs from x-ray and neutron + total scattering experiments respectively, supply meta-data in the header + of the data file. PDFgui reads this information and fills the appropriate + fields in the data set configuration panel. Caution should be exercised by + the user to verify that these data indeed correspond to the experimental + conditions. In the present example, x-ray radiation is used, and so the + x-ray selection is turned on for the scatterer type. The data range, fit + range, data scale factor, maximum Q value used in Fourier transform to + obtain the experimental PDF and the experiment specific parameters are + displayed. Parameters describing experimental resolution effects, Qdamp + and Qbroad, and experimental conditions, such as temperature and doping + (used for bookkeeping and for parametric plots) are also shown. If no + meta-data are present in a data file, this information should be supplied + by the user. Note also that the changes occurred at this stage in the plot + control panel, allowing user to plot the data. This is achieved by + selecting r in the X-choice box and Gobs (the observed G(r)) + in the Y-list box and then pressing the “Plot” button. Since + no fitting has occurred so far, an attempt to plot calculated PDF profile + or a difference yields a blank plot. The data can also be displayed by + clicking the rightmost “quick-plot” button in the tool bar. +

+
+ + images/fig2-03 +
+

+ Figure 2.3: Adjusting data set related configuration. +

+

+ Having specified the initial structure to be refined, and the data set to + be fit, we proceed to the refinement setup. First we adjust the initial + parameters and variables, and set up the constraints. The adjustments and + constraint setup are done on both the experimental data and the refined + structure levels, toggling between the corresponding + “Configure” and “Constraints” tabs. In the present + example the data related setup will be done first. +

+

+ Click on the data set node (Ni-xray.gr) in the fit tree. In + Figure 2.3 the “Data Set + Configuration” panel is shown. We will adjust the fitting range, as + well as other parameters that reflect the experimental conditions. Since + there is no physical information in the region of r below the + nearest neighbor PDF peak position (as seen in the plot), and since this + region is often affected by noise and experimental artifacts, it is wise + to exclude it from fitting. We therefore set the value of the lower + boundary of the fitting range to 1.7. (Note that the units are Angstroms). + In addition, we set Qdamp parameter to a more realistic starting + value of 0.08. This is an instrument-dependent parameter is typically + obtained through a conventional calibration process at each PDF experiment + using a standard sample such as Ni or Si. Next, we select the + “Constraints” tab, and type @1 into the “Scale + Factor” edit box. This will assign refinement parameter 1 to the + data scale factor. Note that this is the syntax used for assigning the + refinement parameters in PDFfit2 engine. Similarly, assign parameter 2 to + Qdamp by inserting @2 into the appropriate edit box. This is + illustrated in Figure Figure 2.4. +

+
+ + images/fig2-04 +
+

+ Figure 2.4: Setting up the refinement parameters and constraints. + +

+

+ Further, we set constraints related to the structural model, by selecting + the phase node (Ni.stru) on the fit tree, adjusting the initial + parameter values if necessary (not done here), and proceeding to the + “Constraints” tab. We note that the phase configuration was + performed automatically when the structure file was loaded. We assign the + refinement parameter 3 to all three lattice constants, a, b, and c, + reflecting the fact that the structure is cubic. Isotropic ADPs are + assigned to all Ni atoms in the refined cell as refinement parameter 4. + This can conveniently be done by highlighting the “u11”, + “u22” and “u33” cells for all four atoms, and + typing @4 and then pressing “Enter” on your keyboard. + The outcome is shown in Figure Figure 2.5. +

+ +
+ + images/fig2-05 +
+

+ Figure 2.5: Setting up the refinement parameters and constraints. + +

+

+ Note that constrained parameters cannot be adjusted on the + “Configuration” panel since they are no longer independent. It + should also be noted that as a part of the PDFfit2 syntax a refinement + parameter can also be defined as a math expression + f(@n1,@n2,@n3,...) where @n1 stands for fitted parameter, + and n1, n2,... are arbitrary positive integers enumerating + the parameters. This allows simple linking of related variables. For + example, since cell lengths a, b, and c are all expressed as @3, + the refined structure will remain cubic. Also note that the enumeration of + the parameters can be arbitrary, enumeration does not have to follow any + particular order. The quantities within a fit that are enumerated with the + same number will be assigned the same parameter, hence caution should be + exercised to avoid unintentional assignment of the same parameter to + physically different quantities. Automatic parameter assignment (see + further below) is done in such a way as to disallow for such situations to + happen. If assignment is done in part manually, in particular for complex + setups, it is recommended to verify that the parameter assignment is done + correctly. +

+
+ + images/fig2-06 +
+

+ Figure 2.6: Reviewing the fit parameters and conditions. +

+

+ The setup for the present example is now completed. By selecting the fit + node on the fit tree the current action window shows + “Parameters” tab, which displays the used refinement + parameters for review, Figure 2.6. It shows the + initial values, and allows for updates and for refinement parameters to be + released or fixed depending on whether the corresponding + “Fixed” box is unchecked or checked, respectively. The + “Refined” column, which is currently empty, will be populated + with the refined values of the parameters with the fit completes. If the + initial parameter values are to be changed, using “Apply + parameters” button will update the values of the parameters on all + relevant “Configuration” panels. The refinement is executed by + clicking the “gear” icon on the tool bar. The refinement can + be stopped prematurely by clicking on the “stop” icon on the + tool bar. During the refinement the refinement progress will be directly + reported in the PDFfit2 Output panel. This is illustrated in + Figure 2.7. +

+
+ + images/fig2-07 +
+

+ Figure 2.7: While the refinement is running, the refinement progress is + displayed in the PDFfit2 Output panel. + +

+

+ After the fitting is completed, the fit summary is provided in the + “Results” tab of the current action panel associated with the + fit node. Similarly, if the “Results” tab is displayed when + Ni.stru or Ni-xray.gr are selected, values of all + corresponding refined parameters for the converged model are displayed. +

+

+ If the fit results are acceptable, one or more refined values could be + copied to become new initial parameters for possible further refinement, + where appropriate. This is be done in the “Parameters” tab of + the fit by highlighting refined parameters to be copied, right-clicking, + and and selecting Copy Refined To Initial. This is illustrated in + Figure 2.8. Note that you loose the original + starting values when copying values in this way, which may make it + difficult to reproduce the fit. +

+
+ + images/fig2-08 +
+

+ Figure 2.8: Updating the set of initial values of refined parameters. + +

+

+ The fit can be displayed graphically by clicking at the “quick + plot” icon on the tool bar. Alternatively, desired items to be + displayed can be selected from the plot control and plotted on the screen. + Depending on whether the structure or the data are selected on the fit + tree, either refined structural parameters or the experiment related + parameters and fit could be plotted. An example of the fit display is + shown in Figure 2.9, and a selected parameter + plot vs iteration step in Figure 2.10. If the + plotting window remains open while the fitting is in progress, the content + will be updated after each fit iteration. +

+
+ + images/fig2-09 +
+

+ Figure 2.9: An example of PDFgui plotting capabilities: displaying a + fit. + +

+
+ + images/fig2-10 +
+

+ Figure 2.10: An example of PDFgui plotting capabilities: displaying a + parameter. + +

+

+ PDFgui is furnished with “Journal” capability, which can be + found under the “View” menu, and represents a convenient way + to archive project-related notes, as illustrated in + Figure 2.11. These notes can be exported as a + text file, or saved along with the entire project for future reference. +

+
+ + images/fig2-11 +
+

+ Figure 2.11: Using “Journal” feature can be a convenient + way for taking notes. + +

+

+ The project can be saved at any stage in its present configuration through + choice of Save Project as or Save Project as appropriate + from the “File” drop-down menu. The PDFgui project file has + “ddp” extension. In addition to saving a project, various + parts of the project, both structure related and data related, can be + exported to external files by making an appropriate selection from the + “Phases” and “Data” drop-down menus. The phases + (starting or converged) can be saved in one of many formats. The model PDF + profile can be exported through “Data” menu and will be saved + as a five-column “.fgr” file. The first four columns are + r, G(r), dr, and dG(r), and the fifth column + is the difference curve between the data and the model. Note that the + model PDF and the difference are only calculated within the user-specified + fitting range. +

+ +
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

3 Examples and tutorials

+ + + +

+ In this chapter we present series of examples and tutorials aimed at users + already comfortable with the GUI, to provide training in advanced GUI + features designed for most common modeling situations, such as building + the structure from scratch, calculating the PDF based on a given + structure, linking fits, and creating and executing a series of fits on a + sequence of data sets. +

+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

3.1 Building structure model using crystal symmetry

+ + + +

+ The purpose of this example is to demonstrate to the user the symmetry + expansion capabilities of PDFgui. The goal is again to create a simple fit + of Ni PDF, but this time from scratch rather than from a preexisting + structure file. The focus will be on the symmetry expansion of the + structure, and the steps that are described earlier in + Creating a simple fit using a preexisting structure file + are left for the user to recreate. File to be used in this exercise is + Ni-xray.gr. To start, invoke PDFgui. +

+

+ To begin, a new fit again needs to be established by right-clicking the + mouse button on the fit tree pane, and selecting New Fit. This will + generate a new fit called Fit 1 as in the previous example. The next step + in populating the fitting tree is to introduce a structural model. This + time a new phase will be added and the model built up from scratch. Select + the fit icon in the Fit Tree pane. Then right-click the mouse and select + Insert Phase, which will modify the current action panel. In the + current action panel options are offered to load a structure from a file + or to generate it from scratch. Select “New” to build up + structure from scratch. The Fit Tree will be populated with a new item + “New Phase”. Rename this phase to “Ni fcc”. The + current action panel now displays default phase configuration with + “dummy” values and no atoms. Edit the lattice parameters and + set them to reflect the symmetry, in this case set the lengths to 3.52 + Angstroms and all the angles to 90 degrees. Pressing “Tab” on + the keyboard will take you from one form-field to the next. To introduce + new atoms right-click with your mouse onto elem tab in the Phase + Constraints grid, and select desired number of atoms in the asymmetric + unit via the dialog box that pops up. For the Ni case, select one row + only. A new row will then show up in the table and the name of the element + will be highlighted. Type in Ni for the element name. It is + important that the element name is typed in correctly, as this is further + used to search a database for the scattering characteristics of that + site(1). Further, highlight cells in the + u11, u22, and u33 columns and type in the initial + value 0.0025. +

+ +

+ Now right-click with the mouse on the element name, and select + “Expand space group...” option. A dialog box will appear, as + shown in Figure 3.1, requesting space group + information and the choice of origin. Choose “Fm-3m” in the + choice box and hit enter. You can also type in the choice box + “Fm-3m” or “225”, the space group number. This + will expand the unit cell to four Ni sites with the proper symmetry. +

+
+ + images/fig3-01 +
+

+ Figure 3.1: Expanding the unit cell using space group information. + +

+

+ In order to set the symmetry constraints for the refinement, select + “Constraints” tab, highlight all the atoms, and right-click to + invoke a menu. Note that hitting “Control” and “A” + simultaneously will select all the atoms if the grid is active. (If the + fit tree is active, it will select all tree items). Click on + “Symmetry constraints...”, and a dialog box will appear asking + for the space group to be used and whether you want the positions and/or + the thermal parameters to be constrained, as shown in + Figure 3.2. The default is to use the space + group used for expansion, and to constrain everything according to the + symmetry. Since all the positions are special, these will not be refinable + by symmetry, and the thermal parameters will be isotropic. The program + will assign parameters according to symmetry using default names that can + be renamed and/or reassigned by the user. To be consistent with the naming + from the first example, one could assign the lattice parameters as + @3 and the isotropic ADPs as @4. Note that parameters can be + quickly renamed or consolidated in the “Parameters” panel of + the fit node using the right-click menu. It is important to note that the + table reflecting constraints is the only place that program refers + to for the symmetry. What is written there will be used, and if the table + is tampered with, then the original symmetry obtained using symmetry + expansion feature will not be preserved. Therefore, the expansion + tool represents a convenience tool and nothing more than that. The + remaining steps of this example are identical to these described in + Creating a simple fit using a preexisting structure file. +

+
+ + images/fig3-02 +
+

+ Figure 3.2: Setting up symmetry constraints to be used in a refinement. + +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

3.2 Calculating PDF from a structure

+ + +

+ There is often a need for obtaining a calculated PDF profile for a given + structure instead of performing a fit. In order to carry out a + calculation, an underlying structure needs to be specified. This can + either be loaded from a file or generated from scratch. Suppose that we + have a Ni structure populating a fit tree using steps described in either + Creating a simple fit using a preexisting structure file + or in + Building structure model using crystal symmetry, and that we would like to calculate Ni PDF using neutron radiation. + Highlight the Ni structure on fit tree. Either right-click and select + Insert Calculation or select New Calculation from + “Calculation” menu. The current action panel will display + information very similar to that when a data set is loaded, as shown in + Figure 3.3. +

+
+ + images/fig3-03 +
+

+ Figure 3.3: An example of the calculation configuration panel. + +

+

+ Now specify conditions to be used for the calculation, such as radiation + type, calculation range and corresponding r-grid size, as well as + instrument resolution and maximum momentum transfer parameters. For the + later two, the default values of parameters could be used, or values could + be specified that closely mimic the experimental conditions on some + particular instrument of interest. After the conditions are set, the gear + icon on the tool bar can be used to execute the calculation (or + alternatively select Run Selected Calculation from the + “Calculations” menu). For our exercise, select + Neutron scatterer type. To mimic the experimental data used earlier + in the tutorial, select for example 0.01 for the r-grid size, and + use 0.08 and 25.0 for resolution and maximum momentum transfer parameters + respectively. Execute the calculation and observe the result by clicking + on the quick plot icon on the tool bar. To export the calculated PDF, use + the Export Selected Calculation choice on the + “Calculations” menu. +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

3.3 Sequential fitting

+ + +

+ In many practical situations there is a need to set a series of + refinements that are linked in a sequence. In what follows we will + describe multi-stage fitting capabilities of PDFgui, followed by + description of three pre-made macros that implement sequential fitting: + fitting of r-series on a single data set, temperature series on a + set of data corresponding to various temperatures, and a doping series on + a set of data corresponding to samples whose chemical content changes in + some systematic way. These macros can be accessed from the menu bar, + “Fits” menu, Macros selection on the drop-down menu. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

3.3.1 Multistage fitting

+ + +

+ Here we describe how to string together several fits. To begin, create a + fit as explained earlier. We assume this fit is named “Fit 1”. + The next step is to copy the fit. This is achieved by right-clicking on + the fit node in the the fit tree, and selecting “Copy” option + from the pop-up menu. Once this is done, the fit can be pasted by + selecting either “Paste Fit” or “Paste Linked Fit” + from the pop-up menu. We will link the fits manually for the sake of + instruction, so select “Paste Fit”. (“Paste Linked + Fit” will do all of what follows automatically.) Selecting + “Paste Fit” will create “Fit 1_copy”, a copy of + “Fit 1” in the fit, which has the. The next step is to link + the fits. Select the new fit node on the fit tree. All aspects of the fit + are duplicated in the new fit, but so far are not associated with the + original fit. +

+

+ In the “Parameters” panel, select the entire + “Initial” column. Type “=Fit 1” and then press + “Enter”. The “Initial” values of the parameters + should now read “=Fit 1:n”, where n is the index of the + parameter. This brings us to the linking syntax. A parameter in this fit + can be linked to any other parameter in any other fit with + “=name:index” syntax. Here, “name” is the name of + another fit to which the link is made, and “index” is the + index of a parameter in that fit. If “:index” is omitted, it + will default to the index of the parameter one is linking from. A linked + parameter uses the refined value of the link as its initial value, + or the initial value if the linked parameter is not yet refined. An + example of this is shown in Figure 3.4. +

+
+ + images/fig3-04 +
+

+ Figure 3.4: An example of linked fits. The output of a converged fit + will be fed into the succeeding fit in the sequence as an input. + +

+

+ Now that we have a linked fit, we can change it in some aspect. We could + delete and replace the data set or phase, or we could or we can add + parameter to see if we can improve the fit, without modifying the + configuration of the original fit. Here we will add additional parameters + to improve the fit. If our Ni example was used and copied in this + exercise, one can select Ni.stru phase of “Fit 1_copy” + and introduce parameter delta2 by inserting “@5” in the + appropriate box of the “Constraints” tab of that phase. This + is a quadratic atomic correlation factor, a parameter related to the + correlated motion of atoms, and as such should help in sharpening up the + nearest neighbor PDF peak in the model PDF profile. Highlight the fits on + the fit tree by holding down “Ctrl” on the keyboard while + selecting each in sequence. Alternately, select a single fit and hit + “Ctrl”+“Shift”+“A” simultaneously on + the keyboard. Once the fits are selected, run them by pressing the + “gear” icon in the tool bar. Only the highlighted fits will be + executed. The fitting will proceed in stages, so the first fit is executed + first, and, after it is converged, the second one. After the fitting of + the sequence is over, you may plot the results in the same window by + selecting both data set nodes. Change the offset in the plotting window to + 0 and plot Gcalc versus r. Notable is a sharper nearest + neighbor PDF peak in the second fit, improving the fit to the Ni data + compared to the “Fit 1” achievement. +

+

+ We note here that there is also a linear atomic correlation factor + delta1. This one is appropriate to use in cases of high + temperature, while delta2 is more appropriate for the case of low + temperatures. An alternative way to include the correlated motion effects + on PDF is to introduce sratio parameter that defines low-r + to high-r PDF peak ratio, and rcut limit needs to be + specified that defines a cutoff distance. The two approaches of accounting + for correlated motion should not be used simultaneously. See the + PDFgui publication and references therein for a more thorough description + of these parameters. +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

3.3.2 Sequential fitting of incremental r-series

+ + + +

+ In certain modeling situations the user could benefit from fitting a data + set through a series of refinements that differ one from another by the + corresponding fitting ranges. This could either be a case when upper + r-limit is to be changed incrementally, or when a fixed width + r-window is to be defined for a box-car fitting approach. An + example of this when one wants to study the details of the local- to + average-structure crossover in a complex material. PDFgui has a + pre-written macro that automates the setup of this type of refinement. We + will illustrate these capabilities through a simple Ni example. +

+

+ Generate a complete fit, including a phase and a dataset, as explained in + Creating a simple fit using a preexisting structure file. Select the fit from the fit tree. From the “Fits” menu, + select Macros, and choose “r-Series” option. The + Current Action panel will display simple setting requirements, arranged in + two rows of three dialog boxes each, that need to be filled with values to + be specified by the user. An example of this is shown in Figure + Figure 3.5. +

+

+ The first row deals with the increment setup of the upper r of the + refinements. User should specify the first and the last fit maximum + r-value, and corresponding step (increment), all in units of + Angstroms. In the second row information is needed to specify the lower + r refinement limit. Again, the user sets the first and the last + value, and step. This allows for a box car of either fixed or variable + width to be defined. If the second row is left blank, the corresponding + refinement series will be with incremental maximum r only, and + fixed lower limit. For the purpose of this exercise lets perform + incremental fitting of Ni-data with 4 steps total, and fixed lower limit. + To achieve this, type 5 for the first upper limit, 20 for the last upper + limit, and the step of 5 Angstroms. Leave the second row blank. Once this + is done, make sure that the Ni fit, which in this situation serves as a + template, is highlighted in the fit tree, and then click “OK” + in the current action panel. This will generate 4 new fits below the + original fit, and these four fits will constitute your series, with + desired incremental limits. Select all four of them and execute the + refinement. Once the sequence is done, you can review the results using + the plot control. +

+
+ + images/fig3-05 +
+

+ Figure 3.5: Appearance of the setup panel for specifying an incremental + r-series fit conditions. + +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

3.3.3 Sequential fitting of temperature series

+ + + +

+ Frequently, one must handle a large number of data sets originating from a + single sample collected at various temperatures. One of the common + modeling schemes in such cases is to perform sequential fitting of such + data series, which is known to yield well behaved modeling parameters. + PDFgui has a pre-written macro that allows for this modeling situation to + be accommodated. +

+

+ We will describe the procedure using an example of a temperature series of + data collected on LaMnO3 at various temperatures from 300 K to 1150 K at + NPDF instrument at LANSCE at Los Alamos National Laboratory. This material + exhibits Jahn-Teller (JT) order-disorder phase transition just above 700 + K, where the long range orbital order is lost at high temperature, but the + local JT distortion survives. The formal space group does not change at + this transition. +

+

+ To begin, from the “File” menu use + Open Project selection to open lmo-template.dpp project from + the tutorial directory. This project consists of a fit called + lmo-pbnm , which will serve as a template and which contains + Pbnm phase of LaMnO3 and a 300 K data set. The fit refinement is + set up to cover 1.7-19.5 Angstroms range, and all the parameter values are + set to their converged values for this temperature. The fit setup uses + isotropic ADPs for all atomic sites. In the same directory data + corresponding to various temperatures exist, in particular 300K.gr, + 550K.gr, 650K.gr, 700K.gr, 720K.gr, + 730K.gr, 740K.gr, 750K.gr, 800K.gr, + 880K.gr, 980K.gr, 1050K.gr, 1100K.gr, and + 1150K.gr. We will establish a T-series fit sequence. Select + Macros + from the “Fit” menu on the menu bar, and choose + “Temperature Series”. The current action panel will reflect + the selection. A tool is provided that allows for data sets to be added. + Click on “Add” button. Using “Shift” and + mouse-select operation you should select all the data sets mentioned in + the above list, except the 300 K one, as this is already in the template + fit, and then press “Open”. All the data sets will be loaded. + Since the files contain meta-data, as mentioned earlier, the GUI is going + to pick up temperature information from the files. User should verify that + the information is correct. The data can be ordered by temperature by + clicking the “Temperature” header. +

+
+ + images/fig3-06 +
+

+ Figure 3.6: Setting up a T-series sequential refinement for LaMnO3. + Ordering by temperature will ensure that the fits are linked correctly. + +

+

+ Order the data by temperature (Figure 3.6), as + otherwise the series of fits that is to be automatically generated in the + next step will be linked in an arbitrary way in which the data were + loaded, rather than to reflect the scientific logic. There should be 13 + data sets. Next, ensure that the template fit is selected on the fit tree. + If this is the case, the “OK” button becomes clickable. + Clicking on the “OK” button will generate a sequence of linked + fits in the fit tree in the order of the temperature increase. Each fit is + linked to the previous, except for the template fit for the 300 K data. + Highlight all the fits in the fit tree to start the sequential refinement + of the T-series. The results can then be displayed in Fit Control such + that various converged fit parameters are plotted versus temperature. +

+

+ In terms of the science behind the LaMnO3 example, it is interesting to + plot isotropic ADP of the oxygen at general position. Select all the + phases on the fit tree by selecting one and then hitting the + “Control”, “Shift” and “A” keys on + your keyboard simultaneously. This will select all the phases at once. On + the plot control choose the temperature for x axis, and select the + Uiso of O2 (for example atom 20) for the y axis. Clicking + “Plot” will display the plot of Uiso(20) vs T. +

+
+ + images/fig3-07 +
+

+ Figure 3.7: Displaying the refinement results as a function of external + parameter: T-series refinement of LaMnO3, example of isotropic ADP of + oxygen atom on general position in Pbnm setting. Notable are the + offsets just above 700 K (Jahn-Teller transition), and at around 1000 K + when sample converts from orthorhombic to rhombohedral symmetry. + +

+

+ Despite quite high temperatures, an onset of the static offset above the + transition temperature is clearly marked by this parameter, as apparent in + Figure 3.7. Curious user could repeat the same + T-series refinement restricting the refinement range upper limit to say + 5-6 Angstroms and observe the outcome. The refinement sequence execution + should be very quick in this case. +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

3.3.4 Sequential fitting of doping series

+ + + +

+ Fitting a series of PDF data that correspond to a set of samples with + related chemistry, such as various doping series, represents another + important sequential modeling aspect that is supported in PDFgui. +

+

+ We will describe the procedure using an example of a series of data + collected on LaMnO3 and series of Ca-doped LaMnO3 samples with various Ca + content from 0 to 0.28 at GEM instrument at ISIS, UK. To begin, from the + “File” menu use Open Project selection to open + lcmo-template.dpp project from the tutorial directory, which has an + initial setup for this exercise. Note the letter c in the file + name, in contrast to the name used in the previous example. This project + consists of a fit called lcmo-pbnm, which will serve as a template + and which contains Pbnm phase of LaMnO3 and a 10 K data set, + x000t010q35.gr. The difference here with respect to the template + used in the previous example is that Ca sites are introduced in the + structure, but are assigned zero occupancy. However, existence of the Ca + dopant species in the structure of the template is essential for the macro + to operate. Also, upper limit used in Fourier transform for obtaining this + set of data is 35 inverse Angstroms, in contrast to 32 inverse Angstroms + in previous example. Since different instrument was used, the value of + Qdamp is different than in previous example. +

+
+ + images/fig3-08 +
+

+ Figure 3.8: After loading of the Ca-doping data series of LaMnO3 + system, proper doping assignment needs to be carried out, as the doping + levels introspected from the file names in this example incorrectly + reflect the scientific situation. Note that dopant atom has to be + present in the template seed used to generate the linked sequence of + fits. + +

+

+ In the same directory data corresponding to various Ca contents exist, + collected at 10 K temperature, in particular x004t010q35.gr, + x012t010q35.gr, x016t010q35.gr, x020t010q35.gr, + x024t010q35.gr, and x028t010q35.gr. It should be noted at + this point that the data files do not contain any relevant meta-data in + the file headers. However, the doping level is somehow encrypted into the + file names. We will establish a doping series fit sequence. Select + Macros from the “Fit” menu on the menu bar, and choose + “Doping Series”. The current action panel will reflect the + selection. The base element and dopant need to be specified. A tool is + provided that allows for data sets to be added. Click on “Add” + button. Using “Shift” and mouse-select operation you should + select all the data sets mentioned in the above list, and then press + “Open” button. All the data sets will be loaded. The GUI will + introspect both the file names and files themselves in attempt to obtain + the doping (or in previous example temperature) information. Since the + files do not contain meta-data, as mentioned earlier, the GUI is going to + pick up doping information from the file names. The user should verify + that the information is correct. In this particular case the doping + information will not be correctly picked up, as for example 004 from the + name is meant to be 0.04 doping, and the GUI would try to interpret it as + 4.0 doping. Similarly 028 would be interpreted as 28.0, while it was + intended to mean 0.28 doping. These values should be edited and fixed + manually by clicking on the corresponding values and simply typing in the + correct values (Figure Figure 3.8). The data + can be ordered by doping by clicking the header. After you are done with + editing, order the data by doping, as otherwise the series of fits that is + to be automatically generated in the next step will be linked in an + arbitrary way in which the data were loaded, rather than to reflect the + scientific logic. There should be 6 data sets (with the initial x=0.0 data + set there will be 7 chained fits total after this setup is done). Next, + ensure that the template fit is selected on the fit tree. If this is the + case, the “OK” button becomes clickable. Clicking on the + “OK” button will generate a sequence of linked fits in the fit + tree in the order of the Ca content increase. Highlight all the fits in + the fit tree to start the sequential refinement of the doping series. +

+
+ + images/fig3-09 +
+

+ Figure 3.9: Sequence of refined parameters, such as lattice constants, + can be plotted vs doping using PDFgui plotting facilities. Figure + features lattice parameter b in Pbnm space group setting + for series of Ca-doped LaMnO3 samples for doping concentrations between + 0 and 0.28 at 10 K temperature. + +

+

+ After the convergence is achieved for all the fits in the fit tree, the + results can be displayed graphically such that various converged fit + parameters are plotted versus Ca content. An example is provided in Figure + Figure 3.9 + featuring one of the lattice parameters. +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

+ 3.3.5 Advanced post-processing of sequential refinement +

+ + + + +

+ While PDFgui allows to collate data from a series of sequential + refinements, there are many data query options that are not possible or + very tedious with a GUI. A particularly tedious task would be to extract + bond lengths for every temperature refined in a large series. The GUI + could supply menus for these tasks, but there are just too many options to + serve them all. In fact, the GUI just does not seem to be suitable + interface and things are much easier and more flexible to accomplish with + Python scripts. +

+

+ The idea is to setup and run sequential refinement with PDFgui, but to do + complicated data extractions with simple Python scripts. The PDFgui + installation includes a ‘tui’ (Text User + Interface) module that allows simple access to the data in a PDFgui + project. +

+

+ As a first example, let us assume that a converged sequential refinement + from + Sequential fitting of temperature series + has been saved under the same name as lmo-template.ddp. The + following Python script extracts temperatures and refined values of the + lattice parameter c +

+
+
+# python script
+from diffpy.pdfgui import tui             # import the tui library
+prj = tui.LoadProject('lmo-template.ddp') # read PDFgui project file
+temperatures = prj.getTemperatures()      # list of temperature values
+phases = prj.getPhases()                  # list of phase objects
+tcount = len(temperatures)                # number of temperature points
+
+for i in range(tcount):
+    Ti = temperatures[i]
+    # get the refined lattice parameter c
+    ci = phases[i].refined.lattice.c
+    print(Ti, ci)
+
+
+ +

+ Save the example above to a file, say “lmo_refined_c.py” and + run it as +

+
+
+python lmo_refined_c.py
+
+
+

+ Note that the script cannot load the unmodified + lmo-template.ddp file, because it does not have any refinement + results. +

+ +

+ The tutorial directory contains an advanced script + “tui_mno_bond_lengths.py”, which extracts the shortest Mn-O + bond lengths from the same PDFgui project. Please, see the comments in the + script for detailed explanation. +

+

+ To learn more about the tui module and about the objects and functions + that it returns, please see the API documentation for diffpy.pdfgui at + https://diffpy.github.io/diffpy.pdfgui. +

+

+ Feel free to ask at the + diffpy-users + group if you need help with data extracting scripts. +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

3.4 Nanoparticle structure

+ + + +

+ Determining the structure of a nanoparticle is notoriously difficult. + Diffraction experiments on nanoparticle samples yield broad diffraction + patterns that are hard to analyze using conventional crystallographic + approaches. The PDF analysis of nanoparticles is becoming increasingly + common. The PDF of a nanoparticle features sharp peaks conveying + structural information. The PDF signal gets damped at higher distances due + to the diminished number of pairs in the nanoparticle structure that + contribute to those distances. For certain simpler cases when + nanoparticles can be assumed to have spherical shape, characteristic + parameters such as nanoparticle diameter can be obtained. +

+

+ PDFgui is capable of modeling the effect of the finite nanoparticle size + using a spherical shape factor. Relevant PDF parameter is + spdiameter which is the diameter of the nanoparticle. This + parameter is highly correlated with various other parameters one would + like to refine, such as anisotropic ADPs, scale factors, correlated motion + parameters and so on. The refinement procedure is therefore rather + delicate and the solutions are not as robust as we are used to in cases of + crystalline materials. +

+

+ To illustrate the program capabilities we present a case of CdSe + nanoparticle approximately 3nm in size. It useful to have PDF data for a + crystalline reference, where available/applicable. In this exercise we + start from a prepared project file CdSe-nano.ddp. This project + contains two fits: the first one is a bulk CdSe reference, and the other + pertains to the CdSe nanoparticle. For consistency the PDFs of both bulk + and nano samples were obtained using Qmax of 14 inverse Angstroms, + although the bulk material PDF could have been processed using a higher + value. Synchrotron x-ray radiation was used to obtain the data at 300 K, + based on an experiment carried out at 6-ID-D at the Advanced Photon Source + at Argonne National Laboratory. The structure used for both data sets is + wurtzite, space group P63mc. From calibrations on Ni standard + Qdamp value of 0.0486 was obtained and is used here. +

+

+ We first carry out a refinement on the bulk reference. This is carried out + over a range from 1.7 to 19.8 Angstroms, using 7 parameters: lattice + parameters a and c (@1 and @2 respectively), + selenium z fractional coordinate (@11), isotropic ADPs for + Cd and Se (@21 and @23 respectively), the data scale factor + (@100), and finally correlated motion related quadratic term + coefficient delta2 (@200). The converged fit results in + parameter values that can be further used for reference when modeling the + nanoparticle data. We note that while the fit is reasonable, the values of + the isotropic ADPs are enlarged. The fit can be further improved if + anisotropic ADPs are introduced, although the z-direction related + components will remain enlarged due to the stacking disorder present in + the structure. The referent value of 5.69 for delta2 will be used + as a starting value for the nanoparticle fit. +

+

+ In the nanoparticle refinement we will use the same starting values for + all the parameters, except for delta2 and the nanoparticle + diameter, spdiameter. The former is set to 5.69, and the later to + 25 Angstroms. In other cases an approximate value of the spherical + nanoparticle size is usually known, and it is the best to start from a + reasonably good guess. Refining the nanoparticle data reveals nanoparticle + diameter of approximately 30 Angstroms, as further illustrated in + Figure 3.10. Enlarged values of isotropic ADPs + are again observed, and the fit is reasonably good. Further improvements + can be obtained by introducing anisotropic ADPs, where again values + related to the z-direction will remain abnormally large most probably due + to the stacking related disorder. A detailed description of this system + and successful PDF modeling can be found in this publication: + Quantitative size-dependent structure and strain determination of CdSe + nanoparticles using atomic pair distribution function analysis. +

+
+ + images/fig3-10 +
+

+ Figure 3.10: Fitting the structure of a nanoparticle: 3nm CdSe + nanoparticle example. + +

+

+ In general, a successful fitting scenario depends on particular details of + a structural problem one is determined to solve. The problem of + determining the structure of a nanoparticle remains difficult. PDFgui is + not intended to necessarily provide the solution, it is rather a + helpful tool in the process of determining new details and exploring the + space of possible solution candidates, yielding success in some instances. +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

4 Extras

+ + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

4.1 PDF plotting

+ + +

+ Plotting capabilities of PDFgui are provided through the plot control + panel and the quick-plot icon on the tool bar. A quick-plot is created by + selecting a node in the fit tree and then clicking the quick-plot icon in + the tool bar. The same quick-plot can be created by middle-clicking on a + node in the fit tree. +

+

+ The plot control allows for selection of x and y coordinates + for plotting. The actual quantities that could be assigned to the + coordinates is determined by selection of either Fit, or Phase, or Data on + the fit tree. The choices for x and y coordinates varies + depending on what is selected on the fit tree. Special options like index, + temperature and doping are available as choices for x in cases of + plotting multiple fit results from sequential fitting protocols. The plot + window provides essential functionality such as zoom, pan, cursor + coordinate tracking, and shifts. Features such as saving, exporting and + printing are also available. The principal intent of the plotting + functionality is to allow quick access to the fitting results to enhance + the scientific process. If data is selected on the fit tree, the user can + plot various aspects of the PDF function, such as data, model and + difference PDF profiles as a function of inter-atomic distance r. + If the fit or the phase are selected, then various parameters, both + structural and internal can be plotted instead. Since several formal + plotting examples were given through the tutorial exercise, and having + simplicity of usage in mind, no other plotting examples are provided, + hoping that the usage is sufficiently simple for users to master + individually with ease. An example plot of Rw vs refinement step is shown + in Figure 4.1 for Ni example. +

+ +
+ + images/fig4-01 +
+

+ Figure 4.1: Plotting window featuring Rw vs refinement step for Ni + example. The basic functionality for manipulating the plot is provided + through icons on the tool bar of the plotting window. + +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

4.2 Displaying the structure

+ + + +

+ For those users with a structural visualizer available in their system + configuration, PDFgui allows for initial or refined structures to be + visualized by passing required structural information that program. This + is achieved by highlighting a desired phase on the fit tree, and then + selecting Plot Initial Structure or + Plot Refined Structure from the “Phases” drop-down + menu. The quick-plot button (or middle-click) will also invoke the + structure viewer with the refined structure, or initial structure if the + refined structure does not yet exist. The control of the visualization is + dependent on the viewer used. The viewer can set under the + “Edit->Preferences” menu, see full details in + Configuration of structure viewer. +

+ +

+ An example Ni structure visualization with AtomEye is shown in + Figure 4.2. +

+
+ + images/fig4-02 +
+

+ Figure 4.2: Using AtomEye functionality (if installed on your system) + for 3D visualization of the initial and refined PDF structures: example + of Ni structure. + +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

4.3 Advanced usage and special needs

+ + + +

+ The PDFgui is designed to accommodate most common modeling situations. + However, it does not encapsulate all the capabilities available within the + modeling engine, such as calculation of differential PDFs, handling atoms + with special scattering properties, etc. Advanced usage of PDFfit2 engine + to resolve any such special modeling need that user may have is available + through usage of Python scripts in the expert command line mode, similar + to that featured in the PDFFIT program. Handling these situations requires + detailed knowledge of the PDFfit2 syntax based on Python, which is beyond + the scope of this user guide and will be described elsewhere. Refer to the + PDFfit2 API (https://www.diffpy.org/doc/pdffit2 + and the diffpy-users group (https://groups.google.com/d/forum/diffpy-users) for help with PDFfit2 scripting. +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

5 PDFgui reference sheets

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

5.1 PDFgui shortcut keys

+ + + + +

Fit tree

+
+
Ctrl+A
+

Select all items in the fit tree.

+
Ctrl+Shift+A
+
+

+ Once an object is selected on the fit tree, using this shortcut key + will select all the objects on the tree that are of the same type. For + example, if a single data set is selected on the tree, hitting this + hot key will make all the data sets belonging to all the fits in the + tree to become selected. This is particularly useful for + simultaneously plotting various fit results across the fit tree. +

+
+
Ctrl+C
+

Copy selected item.

+
Ctrl+X
+

Copy and delete selected item.

+
Ctrl+V
+
+

+ Paste previously copied item. Note that this will only paste the item + to a legal position in the tree. For example, a phase node cannot be + pasted into an empty tree. +

+
+
+ +

Phase configuration grid

+
+
Ctrl+A
+

Select all items.

+
/
+

Extend existing selection by atom types or indices.

+
Delete
+

Delete row. This will delete any wholly selected row.

+
Ctrl++
+

Add an atom to the grid.

+
Ctrl+-
+

Same as Delete.

+
+ +

Phase constraints grid

+
+
Ctrl+A
+

Select all items.

+
/
+

Extend existing selection by atom types or indices.

+
Delete
+

Delete contents of selected cells.

+
+ +
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

5.2 Command line arguments

+ + + + +

+ PDFgui can be started with an existing project file if it is given as a + command line argument. If the project file cannot be loaded, the program + terminates without starting the GUI an returns nonzero exit code. In + addition the pdfgui executable accepts the following command + line options: +

+
+
-h, --help
+

Show a brief usage information.

+
-V, --version
+

Show program version.

+
+ +

Debugging

+
+
--db-noed
+
+

+ Disable exception catching to error report dialog. Unhandled + exceptions should then result in program crash. +

+
+
--db-nocf
+
+

No confirmation - exit without asking to save modified project.

+
+
--db-pdb
+
+

+ Start Python debugger for unhandled error exceptions instead of + showing the error report dialog. +

+
+
+ +
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ + > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

5.3 List of PDFfit2 variables

+ + + +

+ The following is the list of PDFfit2 variables, including their default + values in parentheses, and a brief description and a note, where + appropriate. Note that some of the variables used in PDFFIT are renamed in + PDFfit2. The reference of these changes is provided for the convenience + and orientation of those users that are used to the old naming scheme. +

+ + + + + + + + + + + + + + + + + + + + +

New variables

+ +
+
Phase: spdiameter
+
+

+ (float Å, default 0 Å)
+ spdiameter is a particle diameter for PDF shape damping + function. Shape damping is not applied when + spdiameter equals zero. +

+
+
+ +
+
Phase: stepcut
+
+

+ (float Å, default 0 Å)
+ The PDF is truncated to zero at r-values greater than + stepcut, when positive. +

+
+
+ +
+
+ Phase: anisotropy(n) +
+
+

+ anisotropy(n) (bool, inferred from uij(n) values) +
+ Flag for anisotropic thermal displacements of atom n. Setting of + anisotropy(n) updates the uij(n) or + uisoequiv(n) values. +

+
+
+ +
+
+ Phase: uisoequiv(n) +
+
+

+ (float Å^2, calculated from uij(n) values) +
+ Isotropic thermal displacement of atom n or equivalent displacement + for anisotropic atom. For anisotropic sites the setting of + uisoequiv(n) scales values of the + uij(n) elements. uisoequiv(n) can be constrained + only for isotropic atoms. +

+
+
+ + + +

Renamed variables

+ +
+
Dataset: dscale
+
+

+ (float unitless, dsca[s] in PDFFIT)
+ Scale factor for the selected dataset. +

+
+
+ +
+
Dataset: qdamp
+
+

+ (float Å^-1, default 0 Å^-1, + qsig in PDFFIT)
+ PDF Gaussian dampening envelope due to limited Q-resolution. Not + applied when equal to zero. The Gaussian envelope is of the form +

+

+ images/eq-01.png +

+
+
+ +
+
Dataset: qbroad
+
+

+ (float Å^-1, default 0 Å^-1, + qalp in PDFFIT)
+ PDF peak broadening from increased intensity noise at high Q. Not + applied when equal zero. See the definition of the + PDF peak width for a detailed + explanation. +

+
+
+ +
+
Phase: uij(n)
+
+

+ (float Å^2, ij=(11, 22, 33, 12, 13, 23), + u[i,n] in PDFFIT)
+ Elements of anisotropic displacement tensor of atom n. +

+
+
+ +
+
Phase: occ(n)
+
+

+ (float unitless, o[n] in PDFFIT)
+ Occupancy of site n. +

+
+
+ +
+
Phase: pscale
+
+

+ (float unitless, csca[p] in PDFFIT)
+ Scale factor of the current phase. +

+
+
+ +
+
Phase: delta1
+
+

+ (float Å, default 0 Å, gamm in PDFFIT)
+ Coefficient for (1/r) contribution to the peak sharpening. See the + definition of the PDF peak width for a + detailed explanation. +

+
+
+ +
+
Phase: delta2
+
+

+ (float Å^2, default 0 Å^2, + delt in PDFFIT)
+ Coefficient for 1/r^2 contribution to the peak sharpening. + See the definition of the + PDF peak width for a detailed + explanation. +

+
+
+ +
+
Phase: sratio
+
+

+ (float unitless, default 1, srat in PDFFIT)
+ Sigma ratio for bonded atoms. Reduction factor for PDF peak width + accounting for correlated motion of bonded atoms. +

+
+
+ + + +

Preserved variables

+ +
+
Dataset: qmax
+
+

+ (float Å^-1, default 0 Å)
+ qmax cutoff is an experimental parameter having fixed value + determined during the PDF data processing in the Fourier transform + step. Finite data range used in the Fourier transform is a source of + termination ripples. Termination ripples are not applied in PDF + calculation when qmax is set to zero. The effect is + simulated using fast Fourier transformation (FFT). The original array + of G values is first padded by the same number of zeros and + then by more zeros to reach the next power of 2. The padded + G array is transformed by FFT and any coefficients + F that correspond to Q values greater than + qmax are reset to zero. The adjusted coefficient array + F is then transformed by inverse FFT back to + G’ and cut out at the original length of G. The + imaginary components in G’ are ignored as they are only + due to round-off errors. +

+
+
+ +
+
Phase: lat(i)
+
+

+ (float Å or degrees, i=1,2,...,6)
+ Lattice parameters a, b, c, alpha, beta, gamma of the current phase. + Can be also used as lat(’a’) etc. +

+
+
+ +
+
+ Phase: x(n), y(n), z(n) +
+
+

+ (float unitless)
+ Fractional coordinates for atom n. +

+
+
+ +
+
Phase: rcut
+
+

+ (float Å, default 0 Å)
+ Radius cutoff for applying sratio sharpening factor. +

+
+
+ +
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + + [ > ] + + [ >> ] +      + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

5.4 PDF peak width

+ +

+ The PDF peak width contains contributions from thermal and zero point + displacements as well as static disorder. For large distances r the + motion of the two contributing atoms is uncorrelated. For small distances, + however, the motion can be strongly correlated leading to a sharpening of + the first peak(s) in the observed PDF. PDFfit2 provides three different + correction terms for the PDF peak width. The final width is given by +

+

images/eq-02.png

+

+ Here the primed sigma is the peak width without correlation, which is + computed from the anisotropic displacement parameters. The first two terms + correct for the effects of correlated motion. Within the scope of the + users guide, we just mention that the term + delta2/r^2 describes the low temperature behavior, and + term delta1/r describes the high temperature case. Since the + two parameters are highly correlated, one will in practice choose which + one to refine. The last term in the equation models the PDF peak + broadening as a result of the Q resolution of the diffractometer. In many + cases this term will only be significant for refinements over wider + r-ranges. Note that the Q resolution also results in an exponential + dampening of the PDF peaks which is modeled using the parameter + qdamp. +

+
+ + + + + + + + + + + + + + + + + +
+ [ + << ] + + [ + < ] + + [ Up ] + [ > ][ >> ]     + [Top] + + [Contents] + + [Index] + + [ ? ] +
+ +

Index

+ + + + + + +
Jump to:   + A +   + C +   + D +   + E +   + F +   + G +   + H +   + I +   + M +   + N +   + P +   + Q +   + R +   + S +   + T +   + U +   + V +   + W +   +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Index Entry Section

A
+ acknowledgments +  Acknowledgments
advanced usage  + 4.3 Advanced usage and special needs +
AtomEye viewer  + 1.4.2 Configuration of structure viewer +
availability 1.3 Availability

C
+ calculating PDF +   + 3.2 Calculating PDF from a structure +
+ command line options +   + 5.2 Command line arguments +
Community 1.6 Community
copyright Acknowledgments
+ create new structure +   + 3.1 Building structure model using crystal symmetry +

D
+ data extraction +   + 3.3.5 Advanced post-processing of sequential refinement +
development  + 1.4.3 Installation from sources +
+ displaying the structure +   + 4.2 Displaying the structure +
doping series  + 3.3.4 Sequential fitting of doping series +

E
examples  + 3 Examples and tutorials +
extras 4 Extras

F
+ fit configuration +   + 2.2 Creating a simple fit using a preexisting structure file +

G
Git repository  + 1.4.3 Installation from sources +

H
hot keys  + 5.1 PDFgui shortcut keys +

I
installation 1.4 Installation
introduction 1 Introduction
isotope Footnotes

M
mail-list 1.6 Community
+ multistage fitting +   + 3.3.1 Multistage fitting +

N
+ nanoparticle diameter +   + 3.4 Nanoparticle structure +
+ nanoparticle structure +   + 3.4 Nanoparticle structure +

P
PDF plotting 4.1 PDF plotting
PDFfit2 1.1 PDFfit2
+ PDFfit2 variables +   + 5.3 List of PDFfit2 variables +
PDFgui 1.2 PDFgui
+ pdfgui arguments +   + 5.2 Command line arguments +
PDFgui layout 2.1 PDFgui layout
+ PDFgui reference sheets +   + 5 PDFgui reference sheets +
+ PDFgui shortcut keys +   + 5.1 PDFgui shortcut keys +
+ project post-processing +   + 3.3.5 Advanced post-processing of sequential refinement +

Q
quick start 2 Quick start

R
r-series  + 3.3.2 Sequential fitting of incremental r-series +
+ reference sheets +   + 5 PDFgui reference sheets +
+ refinement configuration +   + 2.2 Creating a simple fit using a preexisting structure file +

S
+ sequential fitting +   + 3.3 Sequential fitting +
+ sequential fitting +   + 3.3.2 Sequential fitting of incremental r-series +
+ sequential fitting +   + 3.3.3 Sequential fitting of temperature series +
+ sequential fitting +   + 3.3.4 Sequential fitting of doping series +
shortcuts  + 5.1 PDFgui shortcut keys +
special needs  + 4.3 Advanced usage and special needs +
+ startup options +   + 5.2 Command line arguments +
+ structure visualization +   + 4.2 Displaying the structure +
+ symmetry expansion +   + 3.1 Building structure model using crystal symmetry +

T
+ temperature series +   + 3.3.3 Sequential fitting of temperature series +
tui scripts  + 3.3.5 Advanced post-processing of sequential refinement +
tutorials  + 3 Examples and tutorials +

U
user groups 1.6 Community

V
variables  + 5.3 List of PDFfit2 variables +
versions 1.5 What is new
+ visualization setup +   + 1.4.2 Configuration of structure viewer +

W
whatisnew 1.5 What is new

+ + + + + +
Jump to:   + A +   + C +   + D +   + E +   + F +   + G +   + H +   + I +   + M +   + N +   + P +   + Q +   + R +   + S +   + T +   + U +   + V +   + W +   +
+ +
+ + + + + + + + +
+ [Top] + + [Contents] + + [Index] + + [ ? ] +
+

Footnotes

+ +

(1)

+ + +

+ To enter a specific isotope, use the “NucleonNumber-Symbol” + syntax, for example “12-C”. Deuterium and tritium can be + entered also as “D” and “T” in addition to the + normal syntax “2-H” and “3-H”. +

+
+ + + + + + + + +
+ [Top] + + [Contents] + + [Index] + + [ ? ] +
+

Table of Contents

+ + +
+ + + + + + + + +
+ [Top] + + [Contents] + + [Index] + + [ ? ] +
+

About This Document

+ +

+ This document was generated on April 25, 2023 using + texi2html 5.0. +

+

The buttons in the navigation panels have the following meaning:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ButtonNameGo toFrom 1.2.3 go to
[ << ]FastBackBeginning of this chapter or previous chapter1
[ < ]BackPrevious section in reading order1.2.2
[ Up ]UpUp section1.2
[ > ]ForwardNext section in reading order1.2.4
[ >> ]FastForwardNext chapter2
[Top]TopCover (top) of document 
[Contents]ContentsTable of contents 
[Index]IndexIndex 
[ ? ]AboutAbout (help) 
+ +

+ where the Example assumes that the current position is + at Subsubsection One-Two-Three of a document of the + following structure: +

+ +
    +
  • + 1. Section One +
      +
    • + 1.1 Subsection One-One +
        +
      • ...
      • +
      +
    • +
    • + 1.2 Subsection One-Two +
        +
      • 1.2.1 Subsubsection One-Two-One
      • +
      • 1.2.2 Subsubsection One-Two-Two
      • +
      • + 1.2.3 Subsubsection One-Two-Three     + <== Current Position +
      • +
      • 1.2.4 Subsubsection One-Two-Four
      • +
      +
    • +
    • + 1.3 Subsection One-Three +
        +
      • ...
      • +
      +
    • +
    • 1.4 Subsection One-Four
    • +
    +
  • +
+ +
+

+ + This document was generated on April 25, 2023 using + texi2html 5.0. + +
+

+ + diff --git a/pdfgui.pdf b/pdfgui.pdf new file mode 100644 index 00000000..c7fbdd15 Binary files /dev/null and b/pdfgui.pdf differ diff --git a/pdfgui.texinfo b/pdfgui.texinfo new file mode 100644 index 00000000..14bd3834 --- /dev/null +++ b/pdfgui.texinfo @@ -0,0 +1,1946 @@ +\input texinfo @c -*-texinfo-*- + +@documentencoding UTF-8 + +@ifnottex +@macro smallskip{} +@vskip 6pt +@end macro + +@macro medskip{} +@vskip 12pt +@end macro + +@macro bigskip{} +@vskip 24pt +@end macro +@end ifnottex + +@macro EquationMark{} +@html + +@end html +@end macro + +@macro ScreenShot{f} +@center @image{\f\, 5in} +@end macro + +@macro ReleaseDate{} +May 2023 +@end macro + +@exampleindent 2 + +@c start of header +@setfilename pdfgui +@settitle PDFgui user guide, release 2.0, @ReleaseDate{} +@c @setcontentsaftertitlepage +@c end of header + +@c Part 1: copying +@copying +Up to the release 1.1.2 (February 2017) the copyright was held by +the institutions that hosted the work as follows: +Copyright 2006-2007, Board of Trustees of Michigan State University, +Copyright 2008-2012, Board of Trustees of Columbia University in the +city of New York. +Copyright 2013, Brookhaven National Laboratory (Copyright holder +indicated in each source file). +@end copying + +@c Part 2: title +@titlepage + +@title PDFgui user guide +@subtitle 2.0 release +@subtitle @ReleaseDate{} +@author C. L. Farrow, P. Juhás, J. W. Liu, D. Bryndin, E. S. Božin, +@author J. Bloch, Th. Proffen, and S. J. L. Billinge + +@page +@vskip 0pt plus 1filll +@c @insertcopying + +@c HTML needs node to make index link, but PDF format does not like it. +@ifhtml +@node acknowledgments +@end ifhtml +@heading Acknowledgments +@cindex acknowledgments +@include acknowledgements.texinfo + + +@page +@vskip 0pt plus 1filll +@majorheading Preface +@heading Using PDFgui and PDFfit2 +@include redistribution.texinfo + + +@heading Disclaimer + +@include disclaimer.texinfo + +@end titlepage + + +@c Part 3: content +@contents + + +@c Make menu if html +@ifhtml + +@node Top +@top + + +@menu +* Introduction:: +* Quick start:: +* Examples and tutorials:: +* Extras:: +* PDFgui reference sheets:: +* Index:: +@end menu + +@end ifhtml + +@page +@vskip 0pt plus 1filll +@node Introduction, PDFfit2, Top +@chapter Introduction +@cindex introduction + +PDFgui is a graphical interface built on the PDFfit2 engine, which is a program +and programming library for real-space refinement of crystal structures based +on the atomic pair distribution function (PDF) method. PDFgui organizes fits +and simplifies many data analysis tasks, such as configuring and plotting +multiple fits. PDFfit2 is capable of fitting a theoretical three dimensional +structure to atomic pair distribution function data and is ideal for nanoscale +investigations. The fit system accounts for lattice constants, atomic positions +and anisotropic atomic displacement parameters, correlated atomic motion, and +experimental factors that may affect the data. The atomic positions and thermal +coefficients can be constrained to follow symmetry requirements of an arbitrary +space group. The PDFfit2 engine is written in C++ and accessible via Python, +allowing it to inter-operate with other Python programs. + + +@menu +* PDFfit2:: +* PDFgui:: +* Availability:: +* Installation:: +* What is new:: +* Community:: +@end menu + +@node PDFfit2, PDFgui, Introduction, Introduction +@section PDFfit2 +@cindex PDFfit2 + +PDFfit2 is a major upgrade to PDFfit, and inherits many of its +features. PDFfit is capable of fitting a theoretical three-dimensional +structure to an experimentally determined PDF. It can simultaneously +fit multiple structures, accounting for different structural phases +in a material. PDFfit has a constraint system that allows expressing +structure variables as simple functions of fitted parameters. PDFfit +structure variables include lattice constants, data and phase scale +factors, atomic site occupation, anisotropic atomic displacement +parameters (ADPs), and atomic vibrational correlations. PDFfit has a built-in +FORTRAN-style command language that understands simple FOR loops and +some built in arithmetic functions. + +The original PDFfit was written in FORTRAN-77, which imposes some +limitations on the program. For example, it uses fixed-size arrays +for internal storage. This precludes the analysis of structures with +large cells without modifying the code. Though the constraint system +is powerful, it requires that a constraint equation be accompanied +by its first derivative. This places the burden of determining the +derivatives on the user, which can introduce errors that lead to +instability in the convergence. Furthermore, the code is monolithic, +not easily extensible and hard to integrate with external programs. + +The primary focus of PDFfit2 development was to remedy the limitations of +PDFfit while extending its functionality. The old PDFfit engine has been +completely rewritten in C++, and many bugs have been fixed. The new engine +uses dynamic memory allocation so that the size of the structure or extent +of the fit-range of the PDF is limited only by the physical memory available. +The constraint system has also been upgraded. The program @i{automatically} +computes the analytical derivatives of the constraints that are required by +the minimization routine. This simplifies user input and reduces the +possibility of errors. In addition, new fitting parameters for handling +dynamic atomic correlations and experimental resolution have been introduced +as well. + +Instead of rewriting the PDFfit command interpreter, which is used +to define the fitting problem and to control and run the refinement, +its functions are carried out using the Python language +(@url{https://www.python.org}). Python is a powerful, cross-platform, +open-source interpreted programming language (i.e., it does not need +to be compiled to run, similar to scripting) that emphasizes +object-oriented and modular design. PDFfit2 scripts written in +Python syntax take the place of PDFfit macros and the Python +interpreter can handle everything that the old interpreter could, +and more. Using Python as an interpreter allows PDFfit2 to be +combined with and enhanced by other Python libraries. We make use +of this capability with PDFgui as described below. + + +@c @node NODE-NAME, NEXT, PREVIOUS, UP +@node PDFgui, Availability, PDFfit2, Introduction +@section PDFgui +@cindex PDFgui + +The PDFfit2 engine can be used either directly from the Python command line, or +as part of larger and more complex software applications. The first application +built on PDFfit2 is PDFgui, a graphical environment for PDF fitting. + +@subsection Design principles + +PDFgui has been designed to provide users with an easy-to-use yet powerful +interface for fitting structure models to PDF data. It makes use of an +object-oriented architecture, which makes it highly extensible and +maintainable. This allows for powerful usability features such as real-time +plotting. PDFgui has been designed with multitasking in mind. It is +multi-threaded so that the work being done by the PDFfit2 engine does not +interfere with the tasks of the user interface. + +PDFgui is written in the Python programming language. Python features a relaxed +and friendly syntax, supports ``write once, run anywhere'' portability, and has +extensive libraries and modules for virtually every task. Software codes +written in a variety of programming languages can be bound into Python, which +allows them to be used together. Python is becoming a popular choice in the +scientific computation community. + +PDFgui's interface is built using wxPython (@url{https://www.wxpython.org}), the +Python package for wxWidgets, a mature cross-platform GUI library. Graphical +applications written in wxPython provide a look and feel native to the platform +on which they are run. PDFgui is designed to run on Windows, Mac OS, Linux, +and all major Unix systems. + +@subsection Capabilities + +PDFgui contains all of the functionality of PDFfit2 along with additional +enhancements for usability. Mundane tasks are handled by the program and +difficult tasks are made simple. PDFgui can manage multiple fits at once. Each +fit can have multiple experimental data sets and structure models. Fits in a +sequence can call upon other fits for their starting parameters, and configured +fits can be queued to run while the user is away. All the initial, final, and +intermediate data are stored in a platform independent project file that can be +loaded on any computer. All management tasks, such as fit creation, +configuration, modification, and visualization, can be done through the +graphical interface. + +PDFgui supports space group operations. Users can define an asymmetric unit +and let PDFgui expand it to a full cell with all symmetry related positions. +PDFgui can also generate symmetry constraints for atom positions and atomic +ADPs. Users just need to specify the space group, and the program will identify +equivalent sites and generate constraint equations for their coordinates and +temperature factors to keep the structure consistent with the symmetry +requirements. This can be done either for all atoms in the structure or for an +arbitrary subset - for example when it is known that only a certain species +show a local distortion. The code for space group definitions was provided by +the Python Macromolecular Library (mmLib, +@url{http://pymmlib.sourceforge.net}). This was extended to include +non-standard space groups using the Computational Crystallography Toolbox +(cctbx, @uref{https://cctbx.github.io}). PDFgui also supports supercell +expansion of a normal unit cell. + +PDFgui uses the matplotlib (@url{https://matplotlib.org}) Python +package for 2D plotting of data and results. Matplotlib has a friendly +interface so the user can quickly and easily view the results of a fitting. +PDFgui lets users plot data from a series of fits and plot it against selected +meta-data (temperature, doping, etc.), plot the results of several fits in the +same window, plot the PDF in real time as the fitting is running, plot the +parameters or variables in real time as the refinement evolves, and save plots +in common image formats or export the data to a text file. PDFgui can be +configured to use one of many structure visualization packages, such as AtomEye +(@url{http://li.mit.edu/A/Graphics/A/}) or PyMOL +(@url{https://www.pymol.org}). + +PDFgui supports built-in macros for advanced fits. For a set of experimental +data from one system at different temperatures or doping levels, PDFgui can +expand a template fit to a series of related fits. Another PDFgui macro makes +it easy to set up boxcar fits, where the same model is fit over different +r-ranges of the PDF data. + +@c @node NODE-NAME, NEXT, PREVIOUS, UP +@node Availability, Installation, PDFgui, Introduction +@section Availability +@cindex availability + +PDFfit2 and PDFgui are open source and distributed under a BSD license. They +run on Windows, Mac OS, Linux, and all major Unix systems. The source code is +freely available. For more information please contact Professor Simon Billinge +(@email{sb2896@@columbia.edu}) or consult the web-page +@url{https://www.diffpy.org}. News of updates and releases will be posted at +this website and on the diffpy-users group at +@url{https://groups.google.com/d/forum/diffpy-users}. + +@c @node NODE-NAME, NEXT, PREVIOUS, UP +@node Installation, What is new, Availability, Introduction +@section Installation +@cindex installation + +PDFgui is included as a part of DiffPy, a suite of Python and C++ +libraries for structure analysis from diffraction data. For more +information about DiffPy products visit the project homepage at +@url{https://www.diffpy.org}. + +@menu +* Installation for Anaconda Python:: +* Configuration of structure viewer:: +* Installation from sources:: +@end menu + +@node Installation for Anaconda Python +@subsection Installation for Anaconda Python + +As of version 1.1 PDFgui is distributed as a pre-built package for +@url{https://www.anaconda.com, Anaconda Python}. This method makes it +easier to distribute software updates and also results in the same +installation procedure on all supported platforms. + +To install PDFgui, download and install Anaconda for Python 2.7 from +@url{https://www.anaconda.com/download}. When ready open a terminal +application (or @i{Anaconda Command Prompt} on Windows) and use the +@command{conda} package manager to install PDFgui from the ``diffpy'' +channel of Anaconda packages + +@example +conda config --add channels diffpy +conda install diffpy.pdfgui +@end example + +The first command instructs Anaconda system to always check the +``diffpy'' channel for any new software. Such configuration +allows to obtain PDFgui updates using + +@example +conda update diffpy.pdfgui +@end example + +It is however not strictly necessary to make the ``diffpy'' +channel permanent. The same effect can be accomplished by adding the +@w{@option{--channel=diffpy}} option to either of +@w{@command{conda install}} or @w{@command{conda update}} commands. + +After installation is complete PDFgui can be started from a terminal by +entering @command{pdfgui} command or on Windows by using the DiffPy +start menu. PDFgui can be also started from the ``Launcher'' program +that is included with Anaconda. + +@node Configuration of structure viewer +@subsection Configuration of structure viewer +@cindex visualization setup + +PDFgui can visualize 3D structures by displaying them with an external +visualization program. The visualization program needs to +be specified together with a suitable structure format in the +``@w{Edit →} Preferences'' menu in PDFgui. The structure plotting +feature has been tested with the following programs: + +@table @emph +@item AtomEye +AtomEye structure viewer, XCFG format @* +@url{http://li.mit.edu/A/Graphics/A/} + +@item PyMOL +PyMOL structure viewer, PDB format @* +@url{https://www.pymol.org} +@end table + +@noindent +@b{A note for AtomEye users:} +@cindex AtomEye viewer + +AtomEye requires its standard output is connected to a terminal. +On Unix this happens when @command{pdfgui} is started from a terminal. +However if you prefer to start PDFgui using a desktop shortcut or via +``Run Application'' dialog of the window manager, you need to put the +following information to the ``Edit → Preferences'' menu of PDFgui. +@example +Structure viewer executable: xterm +Argument string: -iconic -e ATOMEYE %s +Structure format: xcfg +@end example +@noindent +In the above, ATOMEYE is the path to the ATOMEYE executable. + +For Cygwin users, +the workaround is to launch the executable from a batch file. +Batch files can only run in a command window on Windows and so +AtomEye's requirements would be for sure satisfied. +In addition the batch file can be used to adjust environment +variables: +@example +atomeye.bat +------------------------------------------------------------------------ +set DISPLAY=localhost:0 +set PATH=C:\cygwin\bin;C:\cygwin\usr\X11R6\bin;C:\ATOMEYE_DIR;%PATH% +start A.exe %* +------------------------------------------------------------------------ +@end example + +@noindent +Here @t{ATOMEYE_DIR} needs to be replaced with a proper path. Make sure +that the X-server application included with Cygwin is started. + +@node Installation from sources +@subsection Installation from sources + +@cindex Git repository +@cindex development + +PDFgui sources are available in a public +@url{https://git-scm.com, Git} repository at +@url{https://github.com/diffpy/diffpy.pdfgui}. +Feel free to fork this project on GitHub and contribute. To +use the latest development version clone the Git repository +to your computer and install it in a development mode so that sources +are used directly rather than copied to a system location. It is also +recommended to uninstall the Anaconda package for PDFgui, so that +there is no confusion as to what version is the active one. +Here are the shell commands that would do it: + +@example +# Install PDFgui together with software dependencies. +conda install --channel=diffpy diffpy.pdfgui + +# Make room for the version from sources. Keep dependencies installed. +conda remove diffpy.pdfgui + +# Obtain a clone of the PDFgui Git repository. +git clone https://github.com/diffpy/diffpy.pdfgui.git + +# Install PDFgui sources in a development mode. +cd diffpy.pdfgui +python setup.py develop +@end example + +To verify that PDFgui is indeed loaded from the local source +repository run + +@example +python -m pydoc diffpy.pdfgui +@end example + +and check the path displayed in the FILE section. The application +integrity can be verified by executing all builtin tests using + +@example +python -m diffpy.pdfgui.tests.rundeps +@end example + +Use @command{git pull} to bring your source directory into sync +with the latest updates in the main repository. It is recommend +to afterwards do @command{`setup.py develop} again to refresh +the version metadata associated with the program: + +@example +git pull +python setup.py develop +@end example + +To revert PDFgui installation from the source-code installation +back to the pre-built Anaconda package do + +@example +pip uninstall diffpy.pdfgui +conda install --channel=diffpy diffpy.pdfgui +@end example + + +@c @node NODE-NAME, NEXT, PREVIOUS, UP +@node What is new +@section What is new +@cindex versions +@cindex whatisnew + +@subheading Version 1.1, released March 2016 + +Improvements and modifications since the last major release +1.0-r3067 from April 2009. + +@table @emph + +@item Anaconda installer + +PDFgui is now distributed as a pre-built package for Anaconda Python. +The program is available for all platforms supported by Anaconda, i.e., +for 32 and 64-bit Linux, Mac OS X, and for 32 and 64-bit Windows. + +@item upgrade for recent GUI libraries + +Source codes were updated to work with WX GUI toolkit 2.9 or later. +Fixed blacked-out text fields on Mac OS X. Fixed missing toolbar +in plot-windows on Mac OS X. + +@item select atoms menu + +Added ``Select Atoms'' context menu to the Phase Configuration and Phase +Constraints panels. This selects atom rows by a range of indices +or by atom type. Added keyboard shortcut @kbd{/} for activating the +atom-selection dialog. + +@item small enhancements + +Fixed problems with @i{r}-grid interpolation near data boundaries. Allow +use of CIF-defined space groups for symmetry constraints. Use consistent +numbering for parameters created by symmetry constraints. Improved +export data tool in plot windows to group @i{y}-arrays that are on +the same @i{x} grid. Enhanced supercell expansion to also adjust +the coordinate constraints. + +@item project moved to GitHub + +PDFgui source repository was converted from subversion to a Git repository at +@url{https://github.com/diffpy/diffpy.pdfgui}. Project now uses Git tags +to define software release and version data. + +@item Unicode support + +Allow accented characters in project filenames and in folder paths +where located. Allow accented characters for naming the fit tree +items. Note that such projects are unlikely to work with older +versions of PDFgui. Fix failure to exit when there is some +uncaught error in the at-exit cleanup functions. + +@item PDFgui tests + +PDFgui installation now includes built-in tests. Added facility to +test PDFgui and all its DiffPy components. Implemented automated +testing and generation of test coverage reports when sources on +GitHub change. + +@item bug fixes +Quite a few. Consult the code history at +@url{https://github.com/diffpy/diffpy.pdfgui/commits}. + +@end table + +@subheading Version 1.0, released April 2009 + +This section describes improvements and modifications since the +last beta-release 1.0b.1792 from December 2007. + +@table @emph + +@item updates and installation +PDFgui can be installed or updated +with a simple run of the easy_install script. easy_install +checks our online code repository for any newer versions and takes +care of their download and installation. It can be also used to +add future DiffPy components as they become available. This should +work for Linux, Mac and Windows. + +@item Windows installer +The updated Windows package includes full installation of +Python 2.5 and script for code updates. PDFgui +can be installed under normal Python2.5 tree if it has the +easy_install script. + +@item particle shape correction stored with phase +The previous release of PDFgui had +spherical shape correction factors stored with PDF dataset. The +new layout is more logical and allows multi-phase refinements with +separate shape corrections. + +@item step shape factor +Defined new shape factor that cuts off the +simulated PDF at user defined r-limit. + +@item cumulative Rw +Implemented calculation of cumulative Rw +and option to show it in PDFgui plot window. + +@item project post-processing +Implemented new module +@samp{tui} (text user interface) for simple access to the data +in PDFgui project files. The @samp{tui} module can be used +in easy-to-understand Python scripts for arbitrary data extraction +or conversion. It should be useful for project files with large +temperature or compositional series of PDF refinements. + +@item structure visualization +PDFgui can now show structures with any external structure viewer, +that accepts structure file as a command-line argument. + +@item space group representations +Added 249 space group +representations in non-standard settings. The new representations +were generated using the +@uref{https://cctbx.github.io,cctbx library} and helpful +hints from Ralf W. Grosse-Kunstleve. + +@item symmetry constraints +Fixed issues with generation of +symmetry requirements for the ADP tensors. + +@item default ADP tensors +PDF contributions are not counted for atoms that have +ADP tensors @i{Uij} equal zero. Atoms are now inserted with +a non-zero @i{Uij} matrix. Added warning when a phase +loaded from file has atoms with zero ADPs. + +@item temperature series macro +The temperature series macro was broken for datasets at equal temperature +or when temperature contained decimal point. Improved file +and temperature sorting in the temperature series dialog. + +@item journal panel +Fixed shortcut key handling and font size issues. + +@item startup option @option{--db-pdb} +The new command-line option starts Python debugger on +PDFgui crash instead of displaying error report dialog. + +@item grid interpolation +Fixed problems with r-grid interpolation appearing due to round-off errors. + +@item data load on Windows +Windows version could not read PDF datasets with NaN (not-a-number) +values in the dGr column, because NaN is not supported by the Windows +C-library. Added check for NaN-s before converting to float. + +@end table + +@c @node NODE-NAME, NEXT, PREVIOUS, UP +@node Community, Quick start, Installation, Introduction +@section Community +@cindex Community +@cindex mail-list +@cindex user groups + +There are two Google groups for support and development of PDFgui and other +DiffPy software. Visit the links below for message archives or instructions on +subscription and posting. + +@table @emph +@item @b{diffpy-users} @url{https://groups.google.com/d/forum/diffpy-users} +Help on usage of PDFgui, PDFfit2 and other DiffPy packages. This group should +become a knowledge base of PDFgui user tips, tricks and troubleshooting. Feel +free to ask your question here. + +@item @b{diffpy-dev} @url{https://groups.google.com/d/forum/diffpy-dev} +For discussions about development and changes of PDFgui, PDFfit2 and DiffPy +library in general. +@end table + +@page +@vskip 0pt plus 1filll + +@c @node NODE-NAME, NEXT, PREVIOUS, UP +@node Quick start, PDFgui layout, Installation, Top +@chapter Quick start +@cindex quick start + +In this chapter the PDFgui layout is briefly described, followed by a simple +tutorial example, spanning the GUI functionality and aimed at novice users. +Users familiar with the basics can proceed to @ref{Examples and tutorials}, or +use @ref{PDFgui reference sheets}. All the files used in examples are +available in the source distribution or can be downloaded from the DiffPy +website. + +@menu +* PDFgui layout:: +* Simple fit:: +@end menu + +@node PDFgui layout, Simple fit, Quick start, Quick start +@section PDFgui layout +@cindex PDFgui layout + +Once PDFgui is invoked, a PDFgui window comes up. Its layout consists of a +``Menu Bar'', a ``Tool Bar'', and a set of four panes. The menu bar contains +drop-down menus that provide various aspects of PDFgui functionality. The tool +bar features icons for commonly used operations: creating a new project, +opening an existing project, saving a project, executing a refinement or +calculation, stopping a refinement or calculation, and making a quick plot. The +four panes consist of the ``Fit Tree'', ``Plot Control'', the``Current Action'' +pane, and the ``PDFfit2 Output'' panel. These are all shown in @ref{fig2-01}. + +The fit tree is used in setting up a fit protocol. The plot control serves the +user's needs for graphically displaying the fits, as well as various +fit-related parameters. The content of the current action panel changes as the +refinement is being set up. It is a functional panel through which the user +configures the fit attributes, sets the fit constraints, reviews the fit +settings, displays fitting results, and also carries out other setup steps. The +progress of the PDFfit2 refinement engine is displayed in the PDFfit2 output +panel. All panels except the current action panel are dockable windows that can +be dragged across the screen, resized and arranged to accommodate the +individual visual needs of the user. The window layout can also be controlled +via the ``View'' drop-down menu on the menu bar. An important part of the PDFgui +operativity is also conveniently available through mouse operations such as +select and right-click. + +@c @node NODE-NAME, NEXT, PREVIOUS, UP +@node Simple fit, Symmetry expansion, PDFgui layout, Quick start +@section Creating a simple fit using a preexisting structure file +@cindex fit configuration +@cindex refinement configuration + +The purpose of this example is to familiarize the novice user with the PDFgui +basics. The goal is to create a simple fit of Ni PDF from a preexisting +structure file, associate a dataset with the refinement, configure and execute +a refinement, and display the result. Files to be used in this exercise are +@i{Ni.stru} and @i{Ni-xray.gr} (found in the tutorial directory). To start, +invoke PDFgui by clicking on the icon on your desktop, selecting the program +from your system's program menu, or by typing @command{pdfgui} in a terminal window. + +First a new fit needs to be established. In the fit tree right-click the mouse +button, and select @b{New Fit}. This will generate a new fit called ``Fit 1'' +in the fit tree. The name of the fit is highlighted and editable, so you need +only to start typing to give the fit a new name. The current action panel will +display the pages that will hold the fit and the results output. Note that the +same action could be achieved by selecting the @b{New Fit} option from the +``Fits'' drop-down menu on the menu bar. + +The next step in populating the fit tree is to load a structural model. First, +select the fit icon in the fit tree pane. Then, right-click the mouse, invoking a +drop-down menu. Select @b{Insert Phase}, which will modify the current action +panel. The same action could be performed from the ``Phases'' drop-down menu on +the menu bar by selecting @b{New Phase}. In the current action panel options are +offered to load a structure from a file or to generate it from scratch. In this +exercise a preexisting structure file @i{Ni.stru} is to be loaded. + +@float Figure,fig2-01 +@ScreenShot{images/fig2-01} +@caption{PDFgui window with fit tree and Plot Control panels to the left and +current action panel to the right. The fit tree panel features the current fit +and the loaded Ni structure which is selected. The current action panel displays +phase configuration within the ``Configure'' tab.} +@end float + +@ref{fig2-01} shows the PDFgui appearance at this stage of the exercise. The +current action panel has three tabs, ``Configure'', ``Constraints'', and +``Results'' that could be selected using mouse. These will be returned to +later. The ``Configure'' panel displays configuration information from the +structure file. The top portion contains lattice parameters, phase scale factor, +and a set of parameters intended to be used to account for correlated atomic +motion effects that typically sharpen the nearest neighbor PDF peak. These are +@i{delta1}, @i{delta2}, @i{sratio}, and @i{rcut}. The @i{spdiameter} and +@i{stepcut} parameters include scatterer size effects in the PDF. These +parameters will be described later. The bottom part of the panel contains +standard unit cell content related information such as atomic species, their +fractional coordinates, anisotropic ADPs, and site occupancies. + +The next step is to load an experimental data set to be fit. Selected the fit +and right-click to bring up the context menu. From the menu choose @b{Insert +Data Set}. The same action could be performed through the ``Data'' menu on the +menu bar. The current action panel changes accordingly, giving an option for a +data set to be loaded from a file. In this exercise Ni PDF data obtained using +synchrotron x-ray radiation collected at 6-ID-D at the Advanced Photon Source +is used. This is contained in a file @i{Ni-xray.gr}, which is to be loaded. +Note that among the exercise files there is also a file @i{Ni-neutron.gr}, +obtained using neutron radiation at the GPPD diffractometer at the IPNS +facility at the Argonne National Laboratory. Both x-ray and neutron datasets +were collected at 300 K. + +@float Figure,fig2-02 +@ScreenShot{images/fig2-02} +@caption{Appearance of a PDFgui window after a PDF dataset is loaded. The Fit +Tree panel features the current fit, loaded Ni structure, and loaded Ni PDF +dataset, G(r), which is selected. The current action panel displays data set +configuration within the ``Configure'' tab.} +@end float + +@ref{fig2-02} shows the PDFgui appearance at this stage of the exercise. The +``Configure'' panel displays configuration information from the data file. It +should be noted that depending on the software used to prepare the experimental +PDF from the raw data, the file may (or may not) contain meta-data reflecting +the experimental conditions and configuration. For example, software PDFgetX2 +and PDFgetN, which can be used to prepare PDFs from x-ray and neutron total +scattering experiments respectively, supply meta-data in the header of the data +file. PDFgui reads this information and fills the appropriate fields in the +data set configuration panel. Caution should be exercised by the user to +verify that these data indeed correspond to the experimental conditions. In the +present example, x-ray radiation is used, and so the x-ray selection is turned +on for the scatterer type. The data range, fit range, data scale factor, +maximum Q value used in Fourier transform to obtain the experimental PDF and +the experiment specific parameters are displayed. Parameters describing +experimental resolution effects, Qdamp and Qbroad, and experimental conditions, +such as temperature and doping (used for bookkeeping and for parametric plots) +are also shown. If no meta-data are present in a data file, this information +should be supplied by the user. Note also that the changes occurred at this +stage in the plot control panel, allowing user to plot the data. This is +achieved by selecting @i{r} in the X-choice box and @i{Gobs} (the observed +G(r)) in the Y-list box and then pressing the ``Plot'' button. Since no +fitting has occurred so far, an attempt to plot calculated PDF profile or a +difference yields a blank plot. The data can also be displayed by clicking the +rightmost ``quick-plot'' button in the tool bar. + +@float Figure,fig2-03 +@ScreenShot{images/fig2-03} +@caption{Adjusting data set related configuration.} +@end float + +Having specified the initial structure to be refined, and the data set to be +fit, we proceed to the refinement setup. First we adjust the initial parameters +and variables, and set up the constraints. The adjustments and constraint setup +are done on both the experimental data and the refined structure levels, +toggling between the corresponding ``Configure'' and ``Constraints'' tabs. In +the present example the data related setup will be done first. + +Click on the data set node (@i{Ni-xray.gr}) in the fit tree. In @ref{fig2-03} +the ``Data Set Configuration'' panel is shown. We will adjust the fitting +range, as well as other parameters that reflect the experimental conditions. +Since there is no physical information in the region of @i{r} below the nearest +neighbor PDF peak position (as seen in the plot), and since this region is +often affected by noise and experimental artifacts, it is wise to exclude it +from fitting. We therefore set the value of the lower boundary of the fitting +range to 1.7. (Note that the units are Angstroms). In addition, we set +@i{Qdamp} parameter to a more realistic starting value of 0.08. This is an +instrument-dependent parameter is typically obtained through a conventional +calibration process at each PDF experiment using a standard sample such as Ni +or Si. Next, we select the ``Constraints'' tab, and type @i{@@1} into the +``Scale Factor'' edit box. This will assign refinement parameter 1 to the data +scale factor. Note that this is the syntax used for assigning the refinement +parameters in PDFfit2 engine. Similarly, assign parameter 2 to @i{Qdamp} by +inserting @i{@@2} into the appropriate edit box. This is illustrated in Figure +@ref{fig2-04}. + +@float Figure,fig2-04 +@ScreenShot{images/fig2-04} +@caption{Setting up the refinement parameters and constraints.} +@end float + +Further, we set constraints related to the structural model, by selecting the +phase node (@i{Ni.stru}) on the fit tree, adjusting the initial parameter +values if necessary (not done here), and proceeding to the ``Constraints'' tab. +We note that the phase configuration was performed automatically when the +structure file was loaded. We assign the refinement parameter 3 to all three +lattice constants, a, b, and c, reflecting the fact that the structure is +cubic. Isotropic ADPs are assigned to all Ni atoms in the refined cell as +refinement parameter 4. This can conveniently be done by highlighting the +``u11'', ``u22'' and ``u33'' cells for all four atoms, and typing @i{@@4} and +then pressing ``Enter'' on your keyboard. The outcome is shown in Figure +@ref{fig2-05}. + + +@float Figure,fig2-05 +@ScreenShot{images/fig2-05} +@caption{Setting up the refinement parameters and constraints.} +@end float + +Note that constrained parameters cannot be adjusted on the ``Configuration'' +panel since they are no longer independent. It should also be noted that as a +part of the PDFfit2 syntax a refinement parameter can also be defined as a math +expression @i{f(@@n1,@@n2,@@n3,...)} where @i{@@n1} stands for fitted +parameter, and @i{n1}, @i{n2},... are arbitrary positive integers enumerating +the parameters. This allows simple linking of related variables. For example, +since cell lengths a, b, and c are all expressed as @i{@@3}, the refined +structure will remain cubic. Also note that the enumeration of the parameters +can be arbitrary, enumeration does not have to follow any particular order. The +quantities within a fit that are enumerated with the same number will be +assigned the same parameter, hence caution should be exercised to avoid +unintentional assignment of the same parameter to physically different +quantities. Automatic parameter assignment (see further below) is done in such +a way as to disallow for such situations to happen. If assignment is done in +part manually, in particular for complex setups, it is recommended to verify +that the parameter assignment is done correctly. + +@float Figure,fig2-06 +@ScreenShot{images/fig2-06} +@caption{Reviewing the fit parameters and conditions.} +@end float + +The setup for the present example is now completed. By selecting the fit node +on the fit tree the current action window shows ``Parameters'' tab, which +displays the used refinement parameters for review, @ref{fig2-06}. It shows +the initial values, and allows for updates and for refinement parameters to be +released or fixed depending on whether the corresponding ``Fixed'' box is +unchecked or checked, respectively. The ``Refined'' column, which is currently +empty, will be populated with the refined values of the parameters with the fit +completes. If the initial parameter values are to be changed, using ``Apply +parameters'' button will update the values of the parameters on all relevant +``Configuration'' panels. The refinement is executed by clicking the ``gear'' +icon on the tool bar. The refinement can be stopped prematurely by clicking on +the ``stop'' icon on the tool bar. During the refinement the refinement +progress will be directly reported in the PDFfit2 Output panel. This is +illustrated in @ref{fig2-07}. + +@float Figure,fig2-07 +@ScreenShot{images/fig2-07} +@caption{While the refinement is running, the refinement progress is +displayed in the PDFfit2 Output panel.} +@end float + +After the fitting is completed, the fit summary is provided in the ``Results'' +tab of the current action panel associated with the fit node. Similarly, if +the ``Results'' tab is displayed when @i{Ni.stru} or @i{Ni-xray.gr} are +selected, values of all corresponding refined parameters for the converged +model are displayed. + +If the fit results are acceptable, one or more refined values could be copied +to become new initial parameters for possible further refinement, where +appropriate. This is be done in the ``Parameters'' tab of the fit by +highlighting refined parameters to be copied, right-clicking, and and selecting +@b{Copy Refined To Initial}. This is illustrated in @ref{fig2-08}. Note that +you loose the original starting values when copying values in this way, which +may make it difficult to reproduce the fit. + +@float Figure,fig2-08 +@ScreenShot{images/fig2-08} +@caption{Updating the set of initial values of refined parameters.} +@end float + +The fit can be displayed graphically by clicking at the ``quick plot'' icon on +the tool bar. Alternatively, desired items to be displayed can be selected from +the plot control and plotted on the screen. Depending on whether the structure +or the data are selected on the fit tree, either refined structural parameters +or the experiment related parameters and fit could be plotted. An example of +the fit display is shown in @ref{fig2-09}, and a selected parameter plot vs +iteration step in @ref{fig2-10}. If the plotting window remains open while the +fitting is in progress, the content will be updated after each fit iteration. + +@float Figure,fig2-09 +@ScreenShot{images/fig2-09} +@caption{An example of PDFgui plotting capabilities: displaying a fit.} +@end float + +@float Figure,fig2-10 +@ScreenShot{images/fig2-10} +@caption{An example of PDFgui plotting capabilities: displaying a parameter.} +@end float + +PDFgui is furnished with ``Journal'' capability, which can be found under the +``View'' menu, and represents a convenient way to archive project-related +notes, as illustrated in @ref{fig2-11}. These notes can be exported as a text +file, or saved along with the entire project for future reference. + +@float Figure,fig2-11 +@ScreenShot{images/fig2-11} +@caption{Using ``Journal'' feature can be a convenient way for taking notes.} +@end float + +The project can be saved at any stage in its present configuration through +choice of @b{Save Project as} or @b{Save Project} as appropriate from the +``File'' drop-down menu. The PDFgui project file has ``ddp'' extension. In +addition to saving a project, various parts of the project, both structure +related and data related, can be exported to external files by making an +appropriate selection from the ``Phases'' and ``Data'' drop-down menus. The +phases (starting or converged) can be saved in one of many formats. The model +PDF profile can be exported through ``Data'' menu and will be saved as a +five-column ``.fgr'' file. The first four columns are @i{r}, @i{G(r)}, @i{dr}, +and @i{dG(r)}, and the fifth column is the difference curve between the data +and the model. Note that the model PDF and the difference are only calculated +within the user-specified fitting range. + +@page +@vskip 0pt plus 1filll +@c @node NODE-NAME, NEXT, PREVIOUS, UP +@node Examples and tutorials, Symmetry expansion, Simple fit, Top +@chapter Examples and tutorials +@cindex examples +@cindex tutorials + +In this chapter we present series of examples and tutorials aimed at users +already comfortable with the GUI, to provide training in advanced GUI features +designed for most common modeling situations, such as building the structure +from scratch, calculating the PDF based on a given structure, linking fits, and +creating and executing a series of fits on a sequence of data sets. + +@c @node NODE-NAME, NEXT, PREVIOUS, UP +@menu +* Symmetry expansion:: +* Calculating PDF:: +* Sequential fitting:: +* Nanoparticle structure:: +@end menu + +@node Symmetry expansion, Calculating PDF, Examples and tutorials, Examples and tutorials +@section Building structure model using crystal symmetry +@cindex create new structure +@cindex symmetry expansion + +@c @b{NB: this part either can be kept or replaced, I felt it's kind of useful +@c to have it to define the purpose of the expansion tool. Please read through +@c and decide if needed, or erase it.-- +@c It should be noted that PDFfit2 operates within the P1 symmetry framework, +@c and extended unit is traditionally used for refinement with the constraints +@c explicitly set, since PDF is used to obtain structure beyond crystallography. +@c Note that the expansion tool is provided in PDFgui for the convenience of the +@c user, and that the space group information serves the purpose of building the +@c constraints within the P1 framework, rather than maintaining the symmetry. +@c Once the constraints are built the symmetry expansion tool finished its job +@c and its services (and more importantly information typed in) are no longer +@c available to the fitting program. The symmetry can be (and frequently is) +@c broken by the user, hopefully intentionally.} + +The purpose of this example is to demonstrate to the user the symmetry +expansion capabilities of PDFgui. The goal is again to create a simple fit of +Ni PDF, but this time from scratch rather than from a preexisting structure +file. The focus will be on the symmetry expansion of the structure, and the +steps that are described earlier in @ref{Simple fit} are left for the user to +recreate. File to be used in this exercise is @i{Ni-xray.gr}. To start, invoke +PDFgui. + +To begin, a new fit again needs to be established by right-clicking the mouse +button on the fit tree pane, and selecting @b{New Fit}. This will generate a +new fit called Fit 1 as in the previous example. The next step in populating +the fitting tree is to introduce a structural model. This time a new phase will +be added and the model built up from scratch. Select the fit icon in the Fit +Tree pane. Then right-click the mouse and select @b{Insert Phase}, which will +modify the current action panel. In the current action panel options are +offered to load a structure from a file or to generate it from scratch. Select +``New'' to build up structure from scratch. The Fit Tree will be populated +with a new item ``New Phase''. Rename this phase to ``Ni fcc''. The current +action panel now displays default phase configuration with ``dummy'' values and +no atoms. Edit the lattice parameters and set them to reflect the symmetry, in +this case set the lengths to 3.52 Angstroms and all the angles to 90 degrees. +Pressing ``Tab'' on the keyboard will take you from one form-field to the next. +To introduce new atoms right-click with your mouse onto @i{elem} tab in the +Phase Constraints grid, and select desired number of atoms in the asymmetric +unit via the dialog box that pops up. For the Ni case, select one row only. A +new row will then show up in the table and the name of the element will be +highlighted. Type in @i{Ni} for the element name. It is important that the +element name is typed in correctly, as this is further used to search a +database for the scattering characteristics of that site@footnote{ +@cindex isotope +To enter a specific isotope, use the ``NucleonNumber-Symbol'' syntax, +for example ``12-C''. Deuterium and tritium can be entered also as +``D'' and ``T'' in addition to the normal syntax ``2-H'' and ``3-H''. +}. +Further, highlight cells in the +@i{u11}, @i{u22}, and @i{u33} columns and type in the initial value 0.0025. + + +Now right-click with the mouse on the element name, and select ``Expand space +group...'' option. A dialog box will appear, as shown in @ref{fig3-01}, +requesting space group information and the choice of origin. Choose ``Fm-3m'' +in the choice box and hit enter. You can also type in the choice box ``Fm-3m'' +or ``225'', the space group number. This will expand the unit cell to four Ni +sites with the proper symmetry. + +@float Figure,fig3-01 +@ScreenShot{images/fig3-01} +@caption{Expanding the unit cell using space group information.} +@end float + +In order to set the symmetry constraints for the refinement, select +``Constraints'' tab, highlight all the atoms, and right-click to invoke a menu. +Note that hitting ``Control'' and ``A'' simultaneously will select all the +atoms if the grid is active. (If the fit tree is active, it will select all +tree items). Click on ``Symmetry constraints...'', and a dialog box will appear +asking for the space group to be used and whether you want the positions and/or +the thermal parameters to be constrained, as shown in @ref{fig3-02}. The +default is to use the space group used for expansion, and to constrain +everything according to the symmetry. Since all the positions are special, +these will not be refinable by symmetry, and the thermal parameters will be +isotropic. The program will assign parameters according to symmetry using +default names that can be renamed and/or reassigned by the user. To be +consistent with the naming from the first example, one could assign the lattice +parameters as @i{@@3} and the isotropic ADPs as @i{@@4}. Note that parameters +can be quickly renamed or consolidated in the ``Parameters'' panel of the fit +node using the right-click menu. It is important to note that the table +reflecting constraints is @i{the only place} that program refers to for the +symmetry. What is written there will be used, and if the table is tampered +with, then the original symmetry obtained using symmetry expansion feature will +@i{not} be preserved. Therefore, the expansion tool represents a convenience +tool and nothing more than that. The remaining steps of this example are +identical to these described in @ref{Simple fit}. + +@float Figure,fig3-02 +@ScreenShot{images/fig3-02} +@caption{Setting up symmetry constraints to be used in a refinement.} +@end float + +@c @node NODE-NAME, NEXT, PREVIOUS, UP +@node Calculating PDF, Sequential fitting, Symmetry expansion, Examples and tutorials +@section Calculating PDF from a structure +@cindex calculating PDF + +There is often a need for obtaining a calculated PDF profile for a given +structure instead of performing a fit. In order to carry out a calculation, an +underlying structure needs to be specified. This can either be loaded from a +file or generated from scratch. Suppose that we have a Ni structure populating +a fit tree using steps described in either @ref{Simple fit} or in @ref{Symmetry +expansion}, and that we would like to calculate Ni PDF using neutron radiation. +Highlight the Ni structure on fit tree. Either right-click and select @b{Insert +Calculation} or select @b{New Calculation} from ``Calculation'' menu. The +current action panel will display information very similar to that when a data +set is loaded, as shown in @ref{fig3-03}. + +@float Figure,fig3-03 +@ScreenShot{images/fig3-03} +@caption{An example of the calculation configuration panel.} +@end float + +Now specify conditions to be used for the calculation, such as radiation type, +calculation range and corresponding @i{r}-grid size, as well as instrument +resolution and maximum momentum transfer parameters. For the later two, the +default values of parameters could be used, or values could be specified that +closely mimic the experimental conditions on some particular instrument of +interest. After the conditions are set, the gear icon on the tool bar can be +used to execute the calculation (or alternatively select @b{Run Selected +Calculation} from the ``Calculations'' menu). For our exercise, select +@i{Neutron} scatterer type. To mimic the experimental data used earlier in the +tutorial, select for example 0.01 for the @i{r}-grid size, and use 0.08 and +25.0 for resolution and maximum momentum transfer parameters respectively. +Execute the calculation and observe the result by clicking on the quick plot +icon on the tool bar. To export the calculated PDF, use the @b{Export Selected +Calculation} choice on the ``Calculations'' menu. + +@c @node NODE-NAME, NEXT, PREVIOUS, UP +@node Sequential fitting, Multistage fitting, Calculating PDF, Examples and tutorials +@section Sequential fitting +@cindex sequential fitting + +In many practical situations there is a need to set a series of refinements +that are linked in a sequence. In what follows we will describe multi-stage +fitting capabilities of PDFgui, followed by description of three pre-made +macros that implement sequential fitting: fitting of @i{r}-series on a single +data set, temperature series on a set of data corresponding to various +temperatures, and a doping series on a set of data corresponding to samples +whose chemical content changes in some systematic way. These macros can be +accessed from the menu bar, ``Fits'' menu, @b{Macros} selection on the +drop-down menu. + + +@c @node NODE-NAME, NEXT, PREVIOUS, UP +@menu +* Multistage fitting:: +* r-series:: +* Temperature series:: +* Doping series:: +* Advanced post-processing of sequential refinement:: +@end menu + +@node Multistage fitting, r-series, Sequential fitting, Sequential fitting +@subsection Multistage fitting +@cindex multistage fitting + +Here we describe how to string together several fits. To begin, create a fit as +explained earlier. We assume this fit is named ``Fit 1''. The next step is to +copy the fit. This is achieved by right-clicking on the fit node in the the fit +tree, and selecting ``Copy'' option from the pop-up menu. Once this is done, +the fit can be pasted by selecting either ``Paste Fit'' or ``Paste Linked Fit'' +from the pop-up menu. We will link the fits manually for the sake of +instruction, so select ``Paste Fit''. (``Paste Linked Fit'' will do all of what +follows automatically.) Selecting ``Paste Fit'' will create ``Fit 1_copy'', a +copy of ``Fit 1'' in the fit, which has the. The next step is to link the fits. +Select the new fit node on the fit tree. All aspects of the fit are duplicated +in the new fit, but so far are not associated with the original fit. + +In the ``Parameters'' panel, select the entire ``Initial'' column. Type ``=Fit +1'' and then press ``Enter''. The ``Initial'' values of the parameters should +now read ``=Fit 1:n'', where @i{n} is the index of the parameter. This brings +us to the linking syntax. A parameter in this fit can be linked to any other +parameter in any other fit with ``=name:index'' syntax. Here, ``name'' is the +name of another fit to which the link is made, and ``index'' is the index of a +parameter in that fit. If ``:index'' is omitted, it will default to the index +of the parameter one is linking from. A linked parameter uses the refined value +of the link as its @i{initial} value, or the initial value if the linked +parameter is not yet refined. An example of this is shown in @ref{fig3-04}. + +@float Figure,fig3-04 +@ScreenShot{images/fig3-04} +@caption{An example of linked fits. The output of a converged fit will +be fed into the succeeding fit in the sequence as an input.} +@end float + +Now that we have a linked fit, we can change it in some aspect. We could delete +and replace the data set or phase, or we could or we can add parameter to see +if we can improve the fit, without modifying the configuration of the original +fit. Here we will add additional parameters to improve the fit. If our Ni +example was used and copied in this exercise, one can select @i{Ni.stru} phase +of ``Fit 1_copy'' and introduce parameter @i{delta2} by inserting ``@@5'' in +the appropriate box of the ``Constraints'' tab of that phase. This is a +quadratic atomic correlation factor, a parameter related to the correlated +motion of atoms, and as such should help in sharpening up the nearest neighbor +PDF peak in the model PDF profile. Highlight the fits on the fit tree by +holding down ``Ctrl'' on the keyboard while selecting each in sequence. +Alternately, select a single fit and hit ``Ctrl''+``Shift''+``A'' +simultaneously on the keyboard. Once the fits are selected, run them by +pressing the ``gear'' icon in the tool bar. Only the highlighted fits will be +executed. The fitting will proceed in stages, so the first fit is executed +first, and, after it is converged, the second one. After the fitting of the +sequence is over, you may plot the results in the same window by selecting both +data set nodes. Change the offset in the plotting window to 0 and plot +@i{Gcalc} versus @i{r}. Notable is a sharper nearest neighbor PDF peak in the +second fit, improving the fit to the Ni data compared to the ``Fit 1'' +achievement. + +We note here that there is also a linear atomic correlation factor @i{delta1}. +This one is appropriate to use in cases of high temperature, while @i{delta2} +is more appropriate for the case of low temperatures. An alternative way to +include the correlated motion effects on PDF is to introduce @i{sratio} +parameter that defines low-@i{r} to high-@i{r} PDF peak ratio, and @i{rcut} +limit needs to be specified that defines a cutoff distance. The two approaches +of accounting for correlated motion should @i{not} be used simultaneously. See +the PDFgui publication and references therein for a more thorough description +of these parameters. + +@c @node NODE-NAME, NEXT, PREVIOUS, UP +@node r-series, Temperature series, Multistage fitting, Sequential fitting +@subsection Sequential fitting of incremental r-series +@cindex sequential fitting +@cindex r-series + +In certain modeling situations the user could benefit from fitting a data set +through a series of refinements that differ one from another by the +corresponding fitting ranges. This could either be a case when upper +@i{r}-limit is to be changed incrementally, or when a fixed width @i{r}-window +is to be defined for a box-car fitting approach. An example of this when one +wants to study the details of the local- to average-structure crossover in a +complex material. PDFgui has a pre-written macro that automates the setup of +this type of refinement. We will illustrate these capabilities through a +simple Ni example. + +Generate a complete fit, including a phase and a dataset, as explained in +@ref{Simple fit}. Select the fit from the fit tree. From the ``Fits'' menu, +select @b{Macros}, and choose ``r-Series'' option. The Current Action panel +will display simple setting requirements, arranged in two rows of three dialog +boxes each, that need to be filled with values to be specified by the user. An +example of this is shown in Figure @ref{fig3-05}. + +The first row deals with the increment setup of the upper @i{r} of the +refinements. User should specify the first and the last fit maximum +@i{r}-value, and corresponding step (increment), all in units of Angstroms. In +the second row information is needed to specify the lower @i{r} refinement +limit. Again, the user sets the first and the last value, and step. This allows +for a box car of either fixed or variable width to be defined. If the second +row is left blank, the corresponding refinement series will be with +incremental maximum @i{r} only, and fixed lower limit. For the purpose of this +exercise lets perform incremental fitting of Ni-data with 4 steps total, and +fixed lower limit. To achieve this, type 5 for the first upper limit, 20 for +the last upper limit, and the step of 5 Angstroms. Leave the second row blank. +Once this is done, make sure that the Ni fit, which in this situation serves as +a template, is highlighted in the fit tree, and then click ``OK'' in the +current action panel. This will generate 4 new fits below the original fit, +and these four fits will constitute your series, with desired incremental +limits. Select all four of them and execute the refinement. Once the sequence +is done, you can review the results using the plot control. + +@float Figure,fig3-05 +@ScreenShot{images/fig3-05} +@caption{Appearance of the setup panel for specifying an incremental r-series +fit conditions.} +@end float + +@c @node NODE-NAME, NEXT, PREVIOUS, UP +@node Temperature series, Doping series, r-series, Sequential fitting +@subsection Sequential fitting of temperature series +@cindex sequential fitting +@cindex temperature series + +Frequently, one must handle a large number of data sets originating from a +single sample collected at various temperatures. One of the common modeling +schemes in such cases is to perform sequential fitting of such data series, +which is known to yield well behaved modeling parameters. PDFgui has a +pre-written macro that allows for this modeling situation to be accommodated. + +We will describe the procedure using an example of a temperature series of data +collected on LaMnO3 at various temperatures from 300 K to 1150 K at NPDF +instrument at LANSCE at Los Alamos National Laboratory. This material exhibits +Jahn-Teller (JT) order-disorder phase transition just above 700 K, where the +long range orbital order is lost at high temperature, but the local JT +distortion survives. The formal space group does not change at this transition. + +To begin, from the ``File'' menu use @b{Open Project} selection to open +@i{lmo-template.dpp} project from the tutorial directory. This project +consists of a fit called @i{lmo-pbnm }, which will serve as a template and +which contains @i{Pbnm} phase of LaMnO3 and a 300 K data set. The fit +refinement is set up to cover 1.7-19.5 Angstroms range, and all the parameter +values are set to their converged values for this temperature. The fit setup +uses isotropic ADPs for all atomic sites. In the same directory data +corresponding to various temperatures exist, in particular @i{300K.gr}, +@i{550K.gr}, @i{650K.gr}, @i{700K.gr}, @i{720K.gr}, @i{730K.gr}, @i{740K.gr}, +@i{750K.gr}, @i{800K.gr}, @i{880K.gr}, @i{980K.gr}, @i{1050K.gr}, @i{1100K.gr}, +and @i{1150K.gr}. We will establish a T-series fit sequence. Select @b{Macros} +from the ``Fit'' menu on the menu bar, and choose ``Temperature Series''. The +current action panel will reflect the selection. A tool is provided that +allows for data sets to be added. Click on ``Add'' button. Using ``Shift'' and +mouse-select operation you should select all the data sets mentioned in the +above list, except the 300 K one, as this is already in the template fit, and +then press ``Open''. All the data sets will be loaded. Since the files contain +meta-data, as mentioned earlier, the GUI is going to pick up temperature +information from the files. User should verify that the information is correct. +The data can be ordered by temperature by clicking the ``Temperature'' header. + +@float Figure,fig3-06 +@ScreenShot{images/fig3-06} +@caption{Setting up a T-series sequential refinement for LaMnO3. Ordering +by temperature will ensure that the fits are linked correctly.} +@end float + +Order the data by temperature (@ref{fig3-06}), as otherwise the series of fits +that is to be automatically generated in the next step will be linked in an +arbitrary way in which the data were loaded, rather than to reflect the +scientific logic. There should be 13 data sets. Next, ensure that the template +fit is selected on the fit tree. If this is the case, the ``OK'' button becomes +clickable. Clicking on the ``OK'' button will generate a sequence of linked +fits in the fit tree in the order of the temperature increase. Each fit is +linked to the previous, except for the template fit for the 300 K data. +Highlight all the fits in the fit tree to start the sequential refinement of +the T-series. The results can then be displayed in Fit Control such that +various converged fit parameters are plotted versus temperature. + +In terms of the science behind the LaMnO3 example, it is interesting to plot +isotropic ADP of the oxygen at general position. Select all the phases on the +fit tree by selecting one and then hitting the ``Control'', ``Shift'' and ``A'' +keys on your keyboard simultaneously. This will select all the phases at once. +On the plot control choose the temperature for @i{x} axis, and select the Uiso +of O2 (for example atom 20) for the @i{y} axis. Clicking ``Plot'' will display +the plot of Uiso(20) vs T. + +@float Figure,fig3-07 +@ScreenShot{images/fig3-07} +@caption{Displaying the refinement results as a function of external +parameter: T-series refinement of LaMnO3, example of isotropic ADP of +oxygen atom on general position in @i{Pbnm} setting. Notable are the offsets +just above 700 K (Jahn-Teller transition), and at around 1000 K when sample +converts from orthorhombic to rhombohedral symmetry.} +@end float + +Despite quite high temperatures, an onset of the static offset above the +transition temperature is clearly marked by this parameter, as apparent in +@ref{fig3-07}. Curious user could repeat the same T-series refinement +restricting the refinement range upper limit to say 5-6 Angstroms and observe +the outcome. The refinement sequence execution should be very quick in this +case. + +@c @node NODE-NAME, NEXT, PREVIOUS, UP +@node Doping series +@subsection Sequential fitting of doping series +@cindex sequential fitting +@cindex doping series + +Fitting a series of PDF data that correspond to a set of samples with related +chemistry, such as various doping series, represents another important +sequential modeling aspect that is supported in PDFgui. + +We will describe the procedure using an example of a series of data collected +on LaMnO3 and series of Ca-doped LaMnO3 samples with various Ca content from 0 +to 0.28 at GEM instrument at ISIS, UK. To begin, from the ``File'' menu use +@b{Open Project} selection to open @i{lcmo-template.dpp} project from the +tutorial directory, which has an initial setup for this exercise. Note the +letter @i{c} in the file name, in contrast to the name used in the previous +example. This project consists of a fit called @i{lcmo-pbnm}, which will serve +as a template and which contains @i{Pbnm} phase of LaMnO3 and a 10 K data set, +@i{x000t010q35.gr}. The difference here with respect to the template used in +the previous example is that Ca sites are introduced in the structure, but are +assigned zero occupancy. However, existence of the Ca dopant species in the +structure of the template is essential for the macro to operate. Also, upper +limit used in Fourier transform for obtaining this set of data is 35 inverse +Angstroms, in contrast to 32 inverse Angstroms in previous example. Since +different instrument was used, the value of @i{Qdamp} is different than in +previous example. + +@float Figure,fig3-08 +@ScreenShot{images/fig3-08} +@caption{After loading of the Ca-doping data series of LaMnO3 system, proper +doping assignment needs to be carried out, as the doping levels introspected +from the file names in this example incorrectly reflect the scientific +situation. Note that dopant atom has to be present in the template seed used +to generate the linked sequence of fits.} +@end float + +In the same directory data corresponding to various Ca contents exist, +collected at 10 K temperature, in particular @i{x004t010q35.gr}, +@i{x012t010q35.gr}, @i{x016t010q35.gr}, @i{x020t010q35.gr}, @i{x024t010q35.gr}, +and @i{x028t010q35.gr}. It should be noted at this point that the data files do +not contain any relevant meta-data in the file headers. However, the doping +level is somehow encrypted into the file names. We will establish a doping +series fit sequence. Select @b{Macros} from the ``Fit'' menu on the menu bar, +and choose ``Doping Series''. The current action panel will reflect the +selection. The base element and dopant need to be specified. A tool is provided +that allows for data sets to be added. Click on ``Add'' button. Using +``Shift'' and mouse-select operation you should select all the data sets +mentioned in the above list, and then press ``Open'' button. All the data sets +will be loaded. The GUI will introspect both the file names and files +themselves in attempt to obtain the doping (or in previous example temperature) +information. Since the files do not contain meta-data, as mentioned earlier, +the GUI is going to pick up doping information from the file names. The user +should verify that the information is correct. In this particular case the +doping information will not be correctly picked up, as for example 004 from the +name is meant to be 0.04 doping, and the GUI would try to interpret it as 4.0 +doping. Similarly 028 would be interpreted as 28.0, while it was intended to +mean 0.28 doping. These values should be edited and fixed manually by clicking +on the corresponding values and simply typing in the correct values (Figure +@ref{fig3-08}). The data can be ordered by doping by clicking the header. +After you are done with editing, order the data by doping, as otherwise the +series of fits that is to be automatically generated in the next step will be +linked in an arbitrary way in which the data were loaded, rather than to +reflect the scientific logic. There should be 6 data sets (with the initial +x=0.0 data set there will be 7 chained fits total after this setup is done). +Next, ensure that the template fit is selected on the fit tree. If this is the +case, the ``OK'' button becomes clickable. Clicking on the ``OK'' button will +generate a sequence of linked fits in the fit tree in the order of the Ca +content increase. Highlight all the fits in the fit tree to start the +sequential refinement of the doping series. + +@float Figure,fig3-09 +@ScreenShot{images/fig3-09} +@caption{Sequence of refined parameters, such as lattice constants, can be +plotted vs doping using PDFgui plotting facilities. Figure features lattice +parameter @i{b} in @i{Pbnm} space group setting for series of Ca-doped LaMnO3 +samples for doping concentrations between 0 and 0.28 at 10 K temperature.} +@end float + +After the convergence is achieved for all the fits in the fit tree, the results +can be displayed graphically such that various converged fit parameters are +plotted versus Ca content. An example is provided in Figure @ref{fig3-09} +featuring one of the lattice parameters. + +@c @node NODE-NAME, NEXT, PREVIOUS, UP +@node Advanced post-processing of sequential refinement +@subsection Advanced post-processing of sequential refinement +@cindex project post-processing +@cindex data extraction +@cindex tui scripts + +While PDFgui allows to collate data from a series of sequential +refinements, there are many data query options that are not +possible or very tedious with a GUI. A particularly tedious task would +be to extract bond lengths for every temperature refined in +a large series. The GUI could supply menus for these tasks, +but there are just too many options to serve them all. In fact, +the GUI just does not seem to be suitable interface and things +are much easier and more flexible to accomplish with Python scripts. + +The idea is to setup and run sequential refinement with PDFgui, but to +do complicated data extractions with simple Python scripts. +The PDFgui installation includes a @samp{tui} (Text User Interface) +module that allows simple access to the data in a PDFgui project. + +As a first example, let us assume that a converged sequential refinement +from @ref{Temperature series} has been saved under the same name as +@i{lmo-template.ddp}. +The following Python script extracts temperatures and refined +values of the lattice parameter @i{c} +@example +# python script +from diffpy.pdfgui import tui # import the tui library +prj = tui.LoadProject('lmo-template.ddp') # read PDFgui project file +temperatures = prj.getTemperatures() # list of temperature values +phases = prj.getPhases() # list of phase objects +tcount = len(temperatures) # number of temperature points + +for i in range(tcount): + Ti = temperatures[i] + # get the refined lattice parameter c + ci = phases[i].refined.lattice.c + print(Ti, ci) +@end example + +@noindent +Save the example above to a file, say ``lmo_refined_c.py'' and run +it as +@example +python lmo_refined_c.py +@end example +@noindent +Note that the script cannot load the unmodified @i{lmo-template.ddp} file, +because it does not have any refinement results. + + +The tutorial directory contains an advanced script +``tui_mno_bond_lengths.py'', which extracts the shortest +Mn-O bond lengths from the same PDFgui project. Please, see +the comments in the script for detailed explanation. + +To learn more about the tui module and about the objects +and functions that it returns, please see the API +documentation for diffpy.pdfgui at +@url{https://diffpy.github.io/diffpy.pdfgui}. + +Feel free to ask at the +@url{https://groups.google.com/d/forum/diffpy-users, diffpy-users} +group if you need help with data extracting scripts. + +@c @node NODE-NAME, NEXT, PREVIOUS, UP +@node Nanoparticle structure +@section Nanoparticle structure +@cindex nanoparticle structure +@cindex nanoparticle diameter + +Determining the structure of a nanoparticle is notoriously difficult. +Diffraction experiments on nanoparticle samples yield broad diffraction +patterns that are hard to analyze using conventional crystallographic +approaches. The PDF analysis of nanoparticles is becoming increasingly common. +The PDF of a nanoparticle features sharp peaks conveying structural +information. The PDF signal gets damped at higher distances due to the +diminished number of pairs in the nanoparticle structure that contribute to +those distances. For certain simpler cases when nanoparticles can be assumed to +have spherical shape, characteristic parameters such as nanoparticle diameter +can be obtained. + +PDFgui is capable of modeling the effect of the finite nanoparticle size using +a spherical shape factor. Relevant PDF parameter is @i{spdiameter} which is the +diameter of the nanoparticle. This parameter is highly correlated with various +other parameters one would like to refine, such as anisotropic ADPs, scale +factors, correlated motion parameters and so on. The refinement procedure is +therefore rather delicate and the solutions are not as robust as we are used to +in cases of crystalline materials. + +To illustrate the program capabilities we present a case of CdSe nanoparticle +approximately 3nm in size. It useful to have PDF data for a crystalline +reference, where available/applicable. In this exercise we start from a +prepared project file @i{CdSe-nano.ddp}. This project contains two fits: the +first one is a bulk CdSe reference, and the other pertains to the CdSe +nanoparticle. For consistency the PDFs of both bulk and nano samples were +obtained using @i{Qmax} of 14 inverse Angstroms, although the bulk material PDF +could have been processed using a higher value. Synchrotron x-ray radiation +was used to obtain the data at 300 K, based on an experiment carried out at +6-ID-D at the Advanced Photon Source at Argonne National Laboratory. The +structure used for both data sets is wurtzite, space group P63mc. From +calibrations on Ni standard @i{Qdamp} value of 0.0486 was obtained and is used +here. + +We first carry out a refinement on the bulk reference. This is carried +out over a range from 1.7 to 19.8 Angstroms, using 7 parameters: lattice +parameters @i{a} and @i{c} (@i{@@1} and @i{@@2} respectively), selenium @i{z} +fractional coordinate (@i{@@11}), isotropic ADPs for Cd and Se (@i{@@21} and +@i{@@23} respectively), the data scale factor (@i{@@100}), and finally +correlated motion related quadratic term coefficient @i{delta2} (@i{@@200}). +The converged fit results in parameter values that can be further used for +reference when modeling the nanoparticle data. We note that while the fit is +reasonable, the values of the isotropic ADPs are enlarged. The fit can be +further improved if anisotropic ADPs are introduced, although the z-direction +related components will remain enlarged due to the stacking disorder present in +the structure. The referent value of 5.69 for @i{delta2} will be used as a +starting value for the nanoparticle fit. + +In the nanoparticle refinement we will use the same starting values for all the +parameters, except for @i{delta2} and the nanoparticle diameter, +@i{spdiameter}. The former is set to 5.69, and the later to 25 Angstroms. In +other cases an approximate value of the spherical nanoparticle size is usually +known, and it is the best to start from a reasonably good guess. Refining the +nanoparticle data reveals nanoparticle diameter of approximately 30 Angstroms, +as further illustrated in @ref{fig3-10}. Enlarged values of isotropic ADPs are +again observed, and the fit is reasonably good. Further improvements can be +obtained by introducing anisotropic ADPs, where again values related to the +z-direction will remain abnormally large most probably due to the stacking +related disorder. A detailed description of this system and successful +PDF modeling can be found in this publication: +@url{https://link.aps.org/doi/10.1103/PhysRevB.76.115413,Quantitative +size-dependent structure and strain determination of CdSe nanoparticles using +atomic pair distribution function analysis}. + +@float Figure,fig3-10 +@ScreenShot{images/fig3-10} +@caption{Fitting the structure of a nanoparticle: 3nm CdSe +nanoparticle example.} +@end float + +In general, a successful fitting scenario depends on particular details of a +structural problem one is determined to solve. The problem of determining the +structure of a nanoparticle remains difficult. PDFgui is not intended to +necessarily provide @i{the} solution, it is rather a helpful tool in the +process of determining new details and exploring the space of possible solution +candidates, yielding success in some instances. + +@c @node NODE-NAME, NEXT, PREVIOUS, UP +@node Extras, PDF plotting, Nanoparticle structure, Top +@chapter Extras +@cindex extras + +@menu +* PDF plotting:: +* Displaying the structure:: +* Advanced usage and special needs:: +@end menu + +@node PDF plotting, Displaying the structure, Extras, Extras +@section PDF plotting +@cindex PDF plotting + +Plotting capabilities of PDFgui are provided through the plot control panel and +the quick-plot icon on the tool bar. A quick-plot is created by selecting a +node in the fit tree and then clicking the quick-plot icon in the tool bar. The +same quick-plot can be created by middle-clicking on a node in the fit tree. + +The plot control allows for selection of @i{x} and @i{y} coordinates for +plotting. The actual quantities that could be assigned to the coordinates is +determined by selection of either Fit, or Phase, or Data on the fit tree. The +choices for @i{x} and @i{y} coordinates varies depending on what is selected on +the fit tree. Special options like index, temperature and doping are available +as choices for @i{x} in cases of plotting multiple fit results from sequential +fitting protocols. The plot window provides essential functionality such as +zoom, pan, cursor coordinate tracking, and shifts. Features such as saving, +exporting and printing are also available. The principal intent of the plotting +functionality is to allow quick access to the fitting results to enhance the +scientific process. If data is selected on the fit tree, the user can plot +various aspects of the PDF function, such as data, model and difference PDF +profiles as a function of inter-atomic distance @i{r}. If the fit or the phase +are selected, then various parameters, both structural and internal can be +plotted instead. Since several formal plotting examples were given through the +tutorial exercise, and having simplicity of usage in mind, no other plotting +examples are provided, hoping that the usage is sufficiently simple for users +to master individually with ease. An example plot of Rw vs refinement step is +shown in @ref{fig4-01} for Ni example. + +@page + +@float Figure,fig4-01 +@ScreenShot{images/fig4-01} +@caption{Plotting window featuring Rw vs refinement step for Ni example. +The basic functionality for manipulating the plot is provided through icons +on the tool bar of the plotting window.} +@end float + +@c @node NODE-NAME, NEXT, PREVIOUS, UP +@node Displaying the structure, Advanced usage and special needs, PDF plotting, Extras +@section Displaying the structure +@cindex displaying the structure +@cindex structure visualization + +For those users with a structural visualizer available in their system +configuration, PDFgui allows for initial or refined structures to be visualized +by passing required structural information that program. This is achieved by +highlighting a desired phase on the fit tree, and then selecting @b{Plot +Initial Structure} or @b{Plot Refined Structure} from the ``Phases'' drop-down +menu. The quick-plot button (or middle-click) will also invoke the structure +viewer with the refined structure, or initial structure if the refined +structure does not yet exist. The control of the visualization is dependent on +the viewer used. The viewer can set under the ``Edit->Preferences'' menu, see +full details in @ref{Configuration of structure viewer}. + + +An example Ni structure visualization with AtomEye is shown in @ref{fig4-02}. + +@float Figure,fig4-02 +@ScreenShot{images/fig4-02} +@caption{Using AtomEye functionality (if installed on your system) for 3D +visualization of the initial and refined PDF structures: example of Ni +structure.} +@end float + +@c @node NODE-NAME, NEXT, PREVIOUS, UP +@node Advanced usage and special needs, PDFgui reference sheets, Displaying the structure, Extras +@section Advanced usage and special needs +@cindex advanced usage +@cindex special needs + +The PDFgui is designed to accommodate most common modeling situations. However, +it does not encapsulate all the capabilities available within the modeling +engine, such as calculation of differential PDFs, handling atoms with special +scattering properties, etc. Advanced usage of PDFfit2 engine to resolve any +such special modeling need that user may have is available through usage of +Python scripts in the expert command line mode, similar to that featured in the +PDFFIT program. Handling these situations requires detailed knowledge of the +PDFfit2 syntax based on Python, which is beyond the scope of this user guide +and will be described elsewhere. Refer to the PDFfit2 API +(@url{https://www.diffpy.org/doc/pdffit2} and the diffpy-users +group (@url{https://groups.google.com/d/forum/diffpy-users}) for help with PDFfit2 +scripting. + +@c @node NODE-NAME, NEXT, PREVIOUS, UP +@node PDFgui reference sheets, PDFgui shortcut keys, Advanced usage and special needs, Top +@chapter PDFgui reference sheets +@cindex PDFgui reference sheets +@cindex reference sheets + +@menu +* PDFgui shortcut keys:: +* Command line arguments:: +* List of PDFfit2 variables:: +* PDF peak width:: +@end menu + +@node PDFgui shortcut keys +@section PDFgui shortcut keys +@cindex PDFgui shortcut keys +@cindex shortcuts +@cindex hot keys + + +@noindent +@b{Fit tree} + +@table @kbd + +@item Ctrl+A +Select all items in the fit tree. + +@item Ctrl+Shift+A +Once an object is selected on the fit tree, using this shortcut key will +select all the objects on the tree that are of the same type. For example, if +a single data set is selected on the tree, hitting this hot key will make all +the data sets belonging to all the fits in the tree to become selected. This is +particularly useful for simultaneously plotting various fit results across the +fit tree. + +@item Ctrl+C +Copy selected item. + +@item Ctrl+X +Copy and delete selected item. + +@item Ctrl+V +Paste previously copied item. Note that this will only paste the item to a +legal position in the tree. For example, a phase node cannot be pasted into an +empty tree. + +@end table + + +@noindent +@b{Phase configuration grid} + +@table @kbd + +@item Ctrl+A +Select all items. + +@item / +Extend existing selection by atom types or indices. + +@item Delete +Delete row. This will delete any wholly selected row. + +@item Ctrl++ +Add an atom to the grid. + +@item Ctrl+- +Same as Delete. + +@end table + + +@noindent +@b{Phase constraints grid} + +@table @kbd + +@item Ctrl+A +Select all items. + +@item / +Extend existing selection by atom types or indices. + +@item Delete +Delete contents of selected cells. + +@end table + + +@node Command line arguments +@section Command line arguments +@cindex command line options +@cindex startup options +@cindex pdfgui arguments + +PDFgui can be started with an existing project file if it is given +as a command line argument. If the project file cannot be loaded, +the program terminates without starting the GUI an returns nonzero +exit code. In addition the @command{pdfgui} executable accepts the +following command line options: + +@table @option + +@item -h, --help +Show a brief usage information. + +@item -V, --version +Show program version. + +@end table + +@page +@noindent +@b{Debugging} + +@table @option + +@item --db-noed +Disable exception catching to error report dialog. Unhandled +exceptions should then result in program crash. + +@item --db-nocf +No confirmation - exit without asking to save modified project. + +@item --db-pdb +Start Python debugger for unhandled error exceptions instead +of showing the error report dialog. + +@end table + + +@node List of PDFfit2 variables +@section List of PDFfit2 variables +@cindex PDFfit2 variables +@cindex variables + + +The following is the list of PDFfit2 variables, including their default values +in parentheses, and a brief description and a note, where appropriate. Note +that some of the variables used in PDFFIT are renamed in PDFfit2. The reference +of these changes is provided for the convenience and orientation of those users +that are used to the old naming scheme. + +@menu +* New variables:: +* Renamed variables:: +* Preserved variables:: +@end menu + +@c --------------------------------------------------------------------- +@node New variables, Renamed variables, List of PDFfit2 variables, List of PDFfit2 variables +@subheading New variables + +@defvr {Phase} spdiameter +(float @AA{}, default 0 @AA{}) @* +@var{spdiameter} is a particle diameter for PDF shape damping function. +Shape damping is not applied when @var{spdiameter} equals zero. +@end defvr + +@defvr {Phase} stepcut +(float @AA{}, default 0 @AA{}) @* +The PDF is truncated to zero at r-values greater than @var{stepcut}, when +positive. +@end defvr + +@defvr {Phase} anisotropy(n) +@b{anisotropy(n)} +(bool, inferred from @var{uij(n)} values) @* +Flag for anisotropic thermal displacements of atom n. +Setting of @var{anisotropy(n)} updates the @var{uij(n)} +or @var{uisoequiv(n)} values. +@end defvr + +@defvr {Phase} uisoequiv(n) +(float @AA{}@math{^2}, calculated from @var{uij(n)} values) @* +Isotropic thermal displacement of atom n or equivalent displacement for +anisotropic atom. For anisotropic sites the setting of @var{uisoequiv(n)} +scales values of the @var{uij(n)} elements. @var{uisoequiv(n)} can be +constrained only for isotropic atoms. +@end defvr + +@c --------------------------------------------------------------------- +@node Renamed variables, New variables, Preserved variables, List of PDFfit2 variables +@subheading Renamed variables + +@defvr {Dataset} dscale +(float unitless, @var{dsca[s]} in PDFFIT) @* +Scale factor for the selected dataset. +@end defvr + +@defvr {Dataset} qdamp +(float @AA{}@math{^-1}, default 0 @AA{}@math{^-1}, @var{qsig} in PDFFIT) @* +PDF Gaussian dampening envelope due to limited Q-resolution. +Not applied when equal to zero. The Gaussian envelope is of the form +@EquationMark{} +@tex +$$ B(r) = e^{-{(r Q_{damp})^{2} \over 2} } $$ +@end tex +@end defvr + +@defvr {Dataset} qbroad +(float @AA{}@math{^-1}, default 0 @AA{}@math{^-1}, @var{qalp} in PDFFIT) @* +PDF peak broadening from increased intensity noise at high Q. +Not applied when equal zero. +See the definition of the @ref{PDF peak width} for a detailed explanation. +@end defvr + +@defvr {Phase} uij(n) +(float @AA{}@math{^2}, ij=(11, 22, 33, 12, 13, 23), @var{u[i,n]} in PDFFIT) @* +Elements of anisotropic displacement tensor of atom n. +@end defvr + +@defvr {Phase} occ(n) +(float unitless, @var{o[n]} in PDFFIT) @* +Occupancy of site n. +@end defvr + +@defvr {Phase} pscale +(float unitless, @var{csca[p]} in PDFFIT) @* +Scale factor of the current phase. +@end defvr + +@defvr {Phase} delta1 +(float @AA{}, default 0 @AA{}, @var{gamm} in PDFFIT) @* +Coefficient for (1/r) contribution to the peak sharpening. +See the definition of the @ref{PDF peak width} for a detailed explanation. +@end defvr + +@defvr {Phase} delta2 +(float @AA{}@math{^2}, default 0 @AA{}@math{^2}, @var{delt} in PDFFIT) @* +Coefficient for 1/r@math{^2} contribution to the peak sharpening. +See the definition of the @ref{PDF peak width} for a detailed explanation. +@end defvr + +@defvr {Phase} sratio +(float unitless, default 1, @var{srat} in PDFFIT) @* +Sigma ratio for bonded atoms. Reduction factor for PDF peak width accounting +for correlated motion of bonded atoms. +@end defvr + +@c --------------------------------------------------------------------- +@node Preserved variables, PDF peak width, Renamed variables, List of PDFfit2 variables +@subheading Preserved variables + +@defvr {Dataset} qmax +(float @AA{}@math{^-1}, default 0 @AA{}) @* +@var{qmax} cutoff is an experimental parameter having fixed +value determined during the PDF data processing in the Fourier +transform step. Finite data range used in the Fourier transform +is a source of termination ripples. Termination ripples are +@i{not} applied in PDF calculation when @var{qmax} is set to zero. The +effect is simulated using fast Fourier transformation (FFT). +The original array of @i{G} values is first padded by the same number of zeros +and then by more zeros to reach the next power of 2. The padded +@i{G} array is transformed by FFT and any coefficients @i{F} that correspond +to @i{Q} values greater than @var{qmax} are reset to zero. The adjusted +coefficient array @i{F} is then transformed by inverse FFT back to @i{G'} +and cut out at the original length of @i{G}. The imaginary components +in @i{G'} are ignored as they are only due to round-off errors. +@end defvr + +@defvr {Phase} lat(i) +(float @AA{} or degrees, i=1,2,...,6) @* +Lattice parameters a, b, c, alpha, beta, gamma of the current phase. +Can be also used as lat('a') etc. +@end defvr + +@defvr {Phase} {x(n), y(n), z(n)} +(float unitless) @* +Fractional coordinates for atom n. +@end defvr + +@defvr {Phase} rcut +(float @AA{}, default 0 @AA{}) @* +Radius cutoff for applying @var{sratio} sharpening factor. +@end defvr + +@c --------------------------------------------------------------------- +@node PDF peak width +@section PDF peak width + +The PDF peak width contains contributions from thermal and zero point +displacements as well as static disorder. For large distances @i{r} the motion +of the two contributing atoms is uncorrelated. For small distances, however, +the motion can be strongly correlated leading to a sharpening of the first +peak(s) in the observed PDF. PDFfit2 provides three different correction terms +for the PDF peak width. The final width is given by +@EquationMark{} +@tex +$$ +\sigma_{ij} = \sigma^{\prime}_{ij} \sqrt{ 1 - {\delta_1 \over r_{ij}} - + {\delta_2 \over r_{ij}^2} + Q_{broad}^2 \, r_{ij}^2 } +$$ +@end tex + +@noindent Here the primed sigma is the peak width without correlation, which is +computed from the anisotropic displacement parameters. The first two terms +correct for the effects of correlated motion. Within the scope of the users +guide, we just mention that the term @var{delta2/r@math{^2}} describes the low +temperature behavior, and term @var{delta1/r} describes the high temperature +case. Since the two parameters are highly correlated, one will in practice +choose which one to refine. The last term in the equation models the PDF peak +broadening as a result of the Q resolution of the diffractometer. In many cases +this term will only be significant for refinements over wider @i{r}-ranges. +Note that the Q resolution also results in an exponential dampening of the PDF +peaks which is modeled using the parameter @var{qdamp}. + +@c Ending of a TexInfo File +@node Index, Top +@unnumbered Index + +@printindex cp + +@bye diff --git a/py-modindex.html b/py-modindex.html new file mode 100644 index 00000000..69265e63 --- /dev/null +++ b/py-modindex.html @@ -0,0 +1,504 @@ + + + + + + + + Python Module Index — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + +
  • +
  • +
+
+
+
+
+ + +

Python Module Index

+ +
+ . | + d +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 
+ .
    + diffpy.pdfgui.applications +
    + diffpy.pdfgui.applications.pdfgui +
    + diffpy.pdfgui.control +
    + diffpy.pdfgui.control.calculation +
    + diffpy.pdfgui.control.constraint +
    + diffpy.pdfgui.control.controlerrors +
    + diffpy.pdfgui.control.fitdataset +
    + diffpy.pdfgui.control.fitstructure +
    + diffpy.pdfgui.control.fitting +
    + diffpy.pdfgui.control.organizer +
    + diffpy.pdfgui.control.parameter +
    + diffpy.pdfgui.control.pdfcomponent +
    + diffpy.pdfgui.control.pdfdataset +
    + diffpy.pdfgui.control.pdfguicontrol +
    + diffpy.pdfgui.control.pdfguimacros +
    + diffpy.pdfgui.control.pdflist +
    + diffpy.pdfgui.control.pdfstructure +
    + diffpy.pdfgui.control.plotter +
    + diffpy.pdfgui.control.structureviewer +
    + diffpy.pdfgui.gui +
    + diffpy.pdfgui.gui.aboutdialog +
    + diffpy.pdfgui.gui.adddatapanel +
    + diffpy.pdfgui.gui.addphasepanel +
    + diffpy.pdfgui.gui.blankpanel +
    + diffpy.pdfgui.gui.bondangledialog +
    + diffpy.pdfgui.gui.bondlengthdialog +
    + diffpy.pdfgui.gui.calculationpanel +
    + diffpy.pdfgui.gui.datasetconfigurepanel +
    + diffpy.pdfgui.gui.datasetconstraintpanel +
    + diffpy.pdfgui.gui.datasetpanel +
    + diffpy.pdfgui.gui.datasetresultspanel +
    + diffpy.pdfgui.gui.debugoptions +
    + diffpy.pdfgui.gui.design +
    + diffpy.pdfgui.gui.dopingseriespanel +
    + diffpy.pdfgui.gui.errorreportdialog +
    + diffpy.pdfgui.gui.errorreportdialog_control_fix +
    + diffpy.pdfgui.gui.errorwrapper +
    + diffpy.pdfgui.gui.extendedplotframe +
    + diffpy.pdfgui.gui.fitnotebookpanel +
    + diffpy.pdfgui.gui.fittree +
    + diffpy.pdfgui.gui.insertrowsdialog +
    + diffpy.pdfgui.gui.journalpanel +
    + diffpy.pdfgui.gui.main +
    + diffpy.pdfgui.gui.mainframe +
    + diffpy.pdfgui.gui.outputpanel +
    + diffpy.pdfgui.gui.paneltest +
    + diffpy.pdfgui.gui.parameterspanel +
    + diffpy.pdfgui.gui.pdfguiglobals +
    + diffpy.pdfgui.gui.pdfpanel +
    + diffpy.pdfgui.gui.phaseconfigurepanel +
    + diffpy.pdfgui.gui.phaseconstraintspanel +
    + diffpy.pdfgui.gui.phasenotebookpanel +
    + diffpy.pdfgui.gui.phasepanelutils +
    + diffpy.pdfgui.gui.phaseresultspanel +
    + diffpy.pdfgui.gui.plotpanel +
    + diffpy.pdfgui.gui.preferencespanel +
    + diffpy.pdfgui.gui.resultspanel +
    + diffpy.pdfgui.gui.rseriespanel +
    + diffpy.pdfgui.gui.sgconstraindialog +
    + diffpy.pdfgui.gui.sgstructuredialog +
    + diffpy.pdfgui.gui.supercelldialog +
    + diffpy.pdfgui.gui.temperatureseriespanel +
    + diffpy.pdfgui.gui.tooltips +
    + diffpy.pdfgui.gui.welcomepanel +
    + diffpy.pdfgui.gui.windowperspective +
    + diffpy.pdfgui.gui.wxextensions +
    + diffpy.pdfgui.gui.wxextensions.autowidthlabelsgrid +
    + diffpy.pdfgui.gui.wxextensions.listctrls +
    + diffpy.pdfgui.gui.wxextensions.paneldialog +
    + diffpy.pdfgui.gui.wxextensions.textctrlutils +
    + diffpy.pdfgui.gui.wxextensions.validators +
    + diffpy.pdfgui.icons +
    + diffpy.pdfgui.tui +
    + diffpy.pdfgui.utils +
 
+ d
+ diffpy +
    + diffpy.pdfgui +
+ + +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index cd6baea4..00000000 --- a/pyproject.toml +++ /dev/null @@ -1,87 +0,0 @@ -[build-system] -requires = ["setuptools>=62.0", "setuptools-git-versioning>=2.0"] -build-backend = "setuptools.build_meta" - -[project] -name = "diffpy.pdfgui" -dynamic=['version', 'dependencies'] -authors = [ - { name="Simon J.L. Billinge group", email="sb2896@columbia.edu" }, -] -maintainers = [ - { name="Simon J.L. Billinge group", email="sb2896@columbia.edu" }, -] -description = "Graphical user interface program for structure refinements to the atomic pair distribution function." -keywords = ['PDF structure refinement GUI'] -readme = "README.rst" -requires-python = ">=3.11, <3.14" -classifiers = [ - 'Development Status :: 5 - Production/Stable', - 'Environment :: Console', - 'Intended Audience :: Developers', - 'Intended Audience :: Science/Research', - 'License :: OSI Approved :: BSD License', - 'Operating System :: MacOS :: MacOS X', - 'Operating System :: Microsoft :: Windows', - 'Operating System :: POSIX', - 'Operating System :: Unix', - 'Programming Language :: Python :: 3.11', - 'Programming Language :: Python :: 3.12', - 'Programming Language :: Python :: 3.13', - 'Topic :: Scientific/Engineering :: Physics', - 'Topic :: Scientific/Engineering :: Chemistry', -] - -[project.scripts] -pdfgui = "diffpy.pdfgui.applications.pdfgui:main" - -[project.urls] -Homepage = "https://github.com/diffpy/diffpy.pdfgui/" -Issues = "https://github.com/diffpy/diffpy.pdfgui/issues/" - -[tool.setuptools-git-versioning] -enabled = true -template = "{tag}" -dev_template = "{tag}" -dirty_template = "{tag}" - -[tool.setuptools.packages.find] -where = ["src"] # list of folders that contain the packages (["."] by default) -include = ["*"] # package names should match these glob patterns (["*"] by default) -exclude = [] # exclude packages matching these glob patterns (empty by default) -namespaces = false # to disable scanning PEP 420 namespaces (true by default) - -[tool.setuptools.dynamic] -dependencies = {file = ["requirements/pip.txt"]} - -[tool.codespell] -exclude-file = ".codespell/ignore_lines.txt" -ignore-words = ".codespell/ignore_words.txt" -skip = "*.cif,*.dat,*.html,*.m,*.textinfo" - -[tool.black] -line-length = 115 -include = '\.pyi?$' -exclude = ''' -/( - \.git - | \.hg - | \.mypy_cache - | \.tox - | \.venv - | \.rst - | \.txt - | _build - | buck-out - | build - | dist - - # The following are specific to Black, you probably don't want those. - | blib2to3 - | tests/data -)/ -''' -[tool.docformatter] -recursive = true -wrap-summaries = 72 -wrap-descriptions = 72 diff --git a/redistribution.texinfo b/redistribution.texinfo new file mode 100644 index 00000000..9d5f5dae --- /dev/null +++ b/redistribution.texinfo @@ -0,0 +1,19 @@ +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +@bigskip{} + +Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +@bigskip{} + +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. + +@bigskip{} + +Neither the names of COLUMBIA UNIVERSITY, MICHIGAN STATE UNIVERSITY nor the +names of their contributors may be used to endorse or promote products derived +from this software without specific prior written permission. diff --git a/release.html b/release.html new file mode 100644 index 00000000..c294a80a --- /dev/null +++ b/release.html @@ -0,0 +1,181 @@ + + + + + + + + + Release Notes — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Release Notes

+
+

3.1.0

+

Added:

+
    +
  • numpy >= 2.0 support

  • +
  • Codecov coverage report in PRs

  • +
  • Spelling check with Codespell in pre-commit

  • +
  • Added Whittaker-Shannon interpolation option for grid_interpolation.

  • +
  • Added support for python 3.13

  • +
  • no-news needed: just tweaking installation instructions

  • +
+

Changed:

+
    +
  • Package reformatted to comply with new Billinge Group package structure

  • +
  • Changed the removed local manual link to the online page.

  • +
  • Use WS interpolation for Nyquist grid.

  • +
  • Refreshed tutorial manual and brought documentation up to date

  • +
  • Plots now use colors from the billinge-group matplotlib stylesheet, bg-mpl-stylesheets

  • +
  • Updated install instructions in README.rst.

  • +
+

Fixed:

+
    +
  • Change background color to match system settings in Phase Configuration.

  • +
  • inability to find gui resources bug in py < 3.12

  • +
  • fixed date rendering in ‘about’ dialog box

  • +
  • fix “absent from setuptools’ packages configuration” warnings during python -m build

  • +
  • use conda.txt instead of run.txt for conda package dependencies

  • +
  • remove conda-recipe folder - feedstock repo has the latest version

  • +
  • two warnings with (1) linestyle redundantly defined and (2) no artists with labels found to put in legend

  • +
  • Use miniforge in CI to avoid strange error of incorrect MacOS version logged from base env

  • +
  • Re-cookiecut to include GH issues templates, getting started, and install updates

  • +
  • Fixed TypeError when using Nyquist interp.

  • +
  • Fixed online manual not showing images.

  • +
  • Code linted up to PEP8 and group standards

  • +
+

Removed:

+
    +
  • Removed wx3 support that was previously deprecated.

  • +
  • Remove diffpy.structure and numpy in macOS Arm64 readme installation since they are installed by other conda-forge dependencies.

  • +
  • six dependency in run.txt

  • +
+
+
+

v3.0.5

+
+
+

Version 2.0.3 – 2023-05-18

+

Added

+
    +
  • Support for Python 3.8, 3.9.

  • +
  • Use .ddp3 instead of .ddp to store project files.

  • +
+

Changed

+
    +
  • Update wxpython to 4.1.1 and remove incompatible align flags.

  • +
  • Update configparser use strict as False.

  • +
  • Update tutorial project files for py3.

  • +
+

Deprecated

+

Removed

+

Fixed

+
    +
  • Incompatible conversion between bytes and str from py2 to py3.

  • +
  • The listCtrlFiles.InsertItem error in windows.

  • +
  • Make the string parser in doping series working.

  • +
+
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/requirements/conda.txt b/requirements/conda.txt deleted file mode 100644 index 5b4d7ebd..00000000 --- a/requirements/conda.txt +++ /dev/null @@ -1,6 +0,0 @@ -numpy -wxpython -diffpy.pdffit2 -diffpy.structure -diffpy.utils -matplotlib-base diff --git a/requirements/docs.txt b/requirements/docs.txt deleted file mode 100644 index 5f34c6ed..00000000 --- a/requirements/docs.txt +++ /dev/null @@ -1,5 +0,0 @@ -sphinx -sphinx_rtd_theme -sphinx-copybutton -doctr -m2r diff --git a/requirements/pip.txt b/requirements/pip.txt deleted file mode 100644 index d398d156..00000000 --- a/requirements/pip.txt +++ /dev/null @@ -1,6 +0,0 @@ -numpy -wxpython -diffpy.pdffit2 -diffpy.structure -diffpy.utils -matplotlib diff --git a/requirements/test.txt b/requirements/test.txt deleted file mode 100644 index eca1f580..00000000 --- a/requirements/test.txt +++ /dev/null @@ -1,7 +0,0 @@ -flake8 -pytest -freezegun -codecov -coverage -pytest-cov -pytest-env diff --git a/search.html b/search.html new file mode 100644 index 00000000..1073c016 --- /dev/null +++ b/search.html @@ -0,0 +1,125 @@ + + + + + + + + Search — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + +
  • +
  • +
+
+
+
+
+ + + + +
+ +
+ +
+
+
+ +
+ +
+

© Copyright 2025, The Trustees of Columbia University in the City of New York.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/searchindex.js b/searchindex.js new file mode 100644 index 00000000..a74e4366 --- /dev/null +++ b/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({"alltitles": {"3.1.0": [[10, "id1"]], "Authors": [[7, "authors"]], "Indices": [[7, "indices"]], "Installation": [[7, "installation"]], "Lesson 1: Creating simple fit of Ni PDF": [[11, "lesson-1-creating-simple-fit-of-ni-pdf"]], "Lesson 2: Build structure model using crystal symmetry": [[11, "lesson-2-build-structure-model-using-crystal-symmetry"]], "Lesson 3: Multi-stage fitting": [[11, "lesson-3-multi-stage-fitting"]], "License": [[8, null]], "Manual": [[9, null]], "Reference": [[7, "reference"]], "References": [[11, "references"]], "Release Notes": [[10, null]], "Resources used": [[9, "resources-used"]], "Submodules": [[0, "submodules"], [1, "submodules"], [2, "submodules"], [3, "submodules"], [5, "submodules"]], "Subpackages": [[0, "subpackages"], [3, "subpackages"]], "Table of contents": [[7, "table-of-contents"]], "Tutorial": [[7, "tutorial"], [11, null]], "Version 2.0.3 \u2013 2023-05-18": [[10, "version-2-0-3-2023-05-18"]], "diffpy.pdfgui documentation": [[7, null]], "diffpy.pdfgui package": [[0, null]], "diffpy.pdfgui.applications package": [[1, null]], "diffpy.pdfgui.applications.pdfgui module": [[1, "module-diffpy.pdfgui.applications.pdfgui"]], "diffpy.pdfgui.control package": [[2, null]], "diffpy.pdfgui.control.calculation module": [[2, "module-diffpy.pdfgui.control.calculation"]], "diffpy.pdfgui.control.constraint module": [[2, "module-diffpy.pdfgui.control.constraint"]], "diffpy.pdfgui.control.controlerrors module": [[2, "module-diffpy.pdfgui.control.controlerrors"]], "diffpy.pdfgui.control.fitdataset module": [[2, "module-diffpy.pdfgui.control.fitdataset"]], "diffpy.pdfgui.control.fitstructure module": [[2, "module-diffpy.pdfgui.control.fitstructure"]], "diffpy.pdfgui.control.fitting module": [[2, "module-diffpy.pdfgui.control.fitting"]], "diffpy.pdfgui.control.organizer module": [[2, "module-diffpy.pdfgui.control.organizer"]], "diffpy.pdfgui.control.parameter module": [[2, "module-diffpy.pdfgui.control.parameter"]], "diffpy.pdfgui.control.pdfcomponent module": [[2, "module-diffpy.pdfgui.control.pdfcomponent"]], "diffpy.pdfgui.control.pdfdataset module": [[2, "module-diffpy.pdfgui.control.pdfdataset"]], "diffpy.pdfgui.control.pdfguicontrol module": [[2, "module-diffpy.pdfgui.control.pdfguicontrol"]], "diffpy.pdfgui.control.pdfguimacros module": [[2, "module-diffpy.pdfgui.control.pdfguimacros"]], "diffpy.pdfgui.control.pdflist module": [[2, "module-diffpy.pdfgui.control.pdflist"]], "diffpy.pdfgui.control.pdfstructure module": [[2, "module-diffpy.pdfgui.control.pdfstructure"]], "diffpy.pdfgui.control.plotter module": [[2, "module-diffpy.pdfgui.control.plotter"]], "diffpy.pdfgui.control.structureviewer module": [[2, "module-diffpy.pdfgui.control.structureviewer"]], "diffpy.pdfgui.gui package": [[3, null]], "diffpy.pdfgui.gui.aboutdialog module": [[3, "module-diffpy.pdfgui.gui.aboutdialog"]], "diffpy.pdfgui.gui.adddatapanel module": [[3, "module-diffpy.pdfgui.gui.adddatapanel"]], "diffpy.pdfgui.gui.addphasepanel module": [[3, "module-diffpy.pdfgui.gui.addphasepanel"]], "diffpy.pdfgui.gui.blankpanel module": [[3, "module-diffpy.pdfgui.gui.blankpanel"]], "diffpy.pdfgui.gui.bondangledialog module": [[3, "module-diffpy.pdfgui.gui.bondangledialog"]], "diffpy.pdfgui.gui.bondlengthdialog module": [[3, "module-diffpy.pdfgui.gui.bondlengthdialog"]], "diffpy.pdfgui.gui.calculationpanel module": [[3, "module-diffpy.pdfgui.gui.calculationpanel"]], "diffpy.pdfgui.gui.datasetconfigurepanel module": [[3, "module-diffpy.pdfgui.gui.datasetconfigurepanel"]], "diffpy.pdfgui.gui.datasetconstraintpanel module": [[3, "module-diffpy.pdfgui.gui.datasetconstraintpanel"]], "diffpy.pdfgui.gui.datasetpanel module": [[3, "module-diffpy.pdfgui.gui.datasetpanel"]], "diffpy.pdfgui.gui.datasetresultspanel module": [[3, "module-diffpy.pdfgui.gui.datasetresultspanel"]], "diffpy.pdfgui.gui.debugoptions module": [[3, "module-diffpy.pdfgui.gui.debugoptions"]], "diffpy.pdfgui.gui.design package": [[4, null]], "diffpy.pdfgui.gui.dopingseriespanel module": [[3, "module-diffpy.pdfgui.gui.dopingseriespanel"]], "diffpy.pdfgui.gui.errorreportdialog module": [[3, "module-diffpy.pdfgui.gui.errorreportdialog"]], "diffpy.pdfgui.gui.errorreportdialog_control_fix module": [[3, "module-diffpy.pdfgui.gui.errorreportdialog_control_fix"]], "diffpy.pdfgui.gui.errorwrapper module": [[3, "module-diffpy.pdfgui.gui.errorwrapper"]], "diffpy.pdfgui.gui.extendedplotframe module": [[3, "module-diffpy.pdfgui.gui.extendedplotframe"]], "diffpy.pdfgui.gui.fitnotebookpanel module": [[3, "module-diffpy.pdfgui.gui.fitnotebookpanel"]], "diffpy.pdfgui.gui.fittree module": [[3, "module-diffpy.pdfgui.gui.fittree"]], "diffpy.pdfgui.gui.insertrowsdialog module": [[3, "module-diffpy.pdfgui.gui.insertrowsdialog"]], "diffpy.pdfgui.gui.journalpanel module": [[3, "module-diffpy.pdfgui.gui.journalpanel"]], "diffpy.pdfgui.gui.main module": [[3, "module-diffpy.pdfgui.gui.main"]], "diffpy.pdfgui.gui.mainframe module": [[3, "module-diffpy.pdfgui.gui.mainframe"]], "diffpy.pdfgui.gui.outputpanel module": [[3, "module-diffpy.pdfgui.gui.outputpanel"]], "diffpy.pdfgui.gui.paneltest module": [[3, "module-diffpy.pdfgui.gui.paneltest"]], "diffpy.pdfgui.gui.parameterspanel module": [[3, "module-diffpy.pdfgui.gui.parameterspanel"]], "diffpy.pdfgui.gui.pdfguiglobals module": [[3, "module-diffpy.pdfgui.gui.pdfguiglobals"]], "diffpy.pdfgui.gui.pdfpanel module": [[3, "module-diffpy.pdfgui.gui.pdfpanel"]], "diffpy.pdfgui.gui.phaseconfigurepanel module": [[3, "module-diffpy.pdfgui.gui.phaseconfigurepanel"]], "diffpy.pdfgui.gui.phaseconstraintspanel module": [[3, "module-diffpy.pdfgui.gui.phaseconstraintspanel"]], "diffpy.pdfgui.gui.phasenotebookpanel module": [[3, "module-diffpy.pdfgui.gui.phasenotebookpanel"]], "diffpy.pdfgui.gui.phasepanelutils module": [[3, "module-diffpy.pdfgui.gui.phasepanelutils"]], "diffpy.pdfgui.gui.phaseresultspanel module": [[3, "module-diffpy.pdfgui.gui.phaseresultspanel"]], "diffpy.pdfgui.gui.plotpanel module": [[3, "module-diffpy.pdfgui.gui.plotpanel"]], "diffpy.pdfgui.gui.preferencespanel module": [[3, "module-diffpy.pdfgui.gui.preferencespanel"]], "diffpy.pdfgui.gui.resultspanel module": [[3, "module-diffpy.pdfgui.gui.resultspanel"]], "diffpy.pdfgui.gui.rseriespanel module": [[3, "module-diffpy.pdfgui.gui.rseriespanel"]], "diffpy.pdfgui.gui.sgconstraindialog module": [[3, "module-diffpy.pdfgui.gui.sgconstraindialog"]], "diffpy.pdfgui.gui.sgstructuredialog module": [[3, "module-diffpy.pdfgui.gui.sgstructuredialog"]], "diffpy.pdfgui.gui.supercelldialog module": [[3, "module-diffpy.pdfgui.gui.supercelldialog"]], "diffpy.pdfgui.gui.temperatureseriespanel module": [[3, "module-diffpy.pdfgui.gui.temperatureseriespanel"]], "diffpy.pdfgui.gui.tooltips module": [[3, "module-diffpy.pdfgui.gui.tooltips"]], "diffpy.pdfgui.gui.welcomepanel module": [[3, "module-diffpy.pdfgui.gui.welcomepanel"]], "diffpy.pdfgui.gui.windowperspective module": [[3, "module-diffpy.pdfgui.gui.windowperspective"]], "diffpy.pdfgui.gui.wxextensions package": [[5, null]], "diffpy.pdfgui.gui.wxextensions.autowidthlabelsgrid module": [[5, "module-diffpy.pdfgui.gui.wxextensions.autowidthlabelsgrid"]], "diffpy.pdfgui.gui.wxextensions.listctrls module": [[5, "module-diffpy.pdfgui.gui.wxextensions.listctrls"]], "diffpy.pdfgui.gui.wxextensions.paneldialog module": [[5, "module-diffpy.pdfgui.gui.wxextensions.paneldialog"]], "diffpy.pdfgui.gui.wxextensions.textctrlutils module": [[5, "module-diffpy.pdfgui.gui.wxextensions.textctrlutils"]], "diffpy.pdfgui.gui.wxextensions.validators module": [[5, "module-diffpy.pdfgui.gui.wxextensions.validators"]], "diffpy.pdfgui.icons package": [[6, null]], "diffpy.pdfgui.tui module": [[0, "module-diffpy.pdfgui.tui"]], "diffpy.pdfgui.utils module": [[0, "module-diffpy.pdfgui.utils"]], "v3.0.5": [[10, "v3-0-5"]]}, "docnames": ["api/diffpy.pdfgui", "api/diffpy.pdfgui.applications", "api/diffpy.pdfgui.control", "api/diffpy.pdfgui.gui", "api/diffpy.pdfgui.gui.design", "api/diffpy.pdfgui.gui.wxextensions", "api/diffpy.pdfgui.icons", "index", "license", "manual", "release", "tutorial"], "envversion": {"sphinx": 64, "sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.intersphinx": 1, "sphinx.ext.todo": 2, "sphinx.ext.viewcode": 1}, "filenames": ["api/diffpy.pdfgui.rst", "api/diffpy.pdfgui.applications.rst", "api/diffpy.pdfgui.control.rst", "api/diffpy.pdfgui.gui.rst", "api/diffpy.pdfgui.gui.design.rst", "api/diffpy.pdfgui.gui.wxextensions.rst", "api/diffpy.pdfgui.icons.rst", "index.rst", "license.rst", "manual.rst", "release.rst", "tutorial.rst"], "indexentries": {"add() (diffpy.pdfgui.control.organizer.organizer method)": [[2, "diffpy.pdfgui.control.organizer.Organizer.add", false]], "add() (diffpy.pdfgui.control.pdfguicontrol.pdfguicontrol method)": [[2, "diffpy.pdfgui.control.pdfguicontrol.PDFGuiControl.add", false]], "addcalc() (diffpy.pdfgui.gui.fittree.fittree method)": [[3, "diffpy.pdfgui.gui.fittree.FitTree.AddCalc", false]], "adddatapanel (class in diffpy.pdfgui.gui.adddatapanel)": [[3, "diffpy.pdfgui.gui.adddatapanel.AddDataPanel", false]], "adddataset() (diffpy.pdfgui.gui.fittree.fittree method)": [[3, "diffpy.pdfgui.gui.fittree.FitTree.AddDataSet", false]], "addfit() (diffpy.pdfgui.gui.fittree.fittree method)": [[3, "diffpy.pdfgui.gui.fittree.FitTree.AddFit", false]], "addphase() (diffpy.pdfgui.gui.fittree.fittree method)": [[3, "diffpy.pdfgui.gui.fittree.FitTree.AddPhase", false]], "addphasepanel (class in diffpy.pdfgui.gui.addphasepanel)": [[3, "diffpy.pdfgui.gui.addphasepanel.AddPhasePanel", false]], "alldebugoptions (diffpy.pdfgui.gui.debugoptions.debugoptions attribute)": [[3, "diffpy.pdfgui.gui.debugoptions.DebugOptions.alldebugoptions", false]], "appendstep() (diffpy.pdfgui.control.fitting.fitting method)": [[2, "diffpy.pdfgui.control.fitting.Fitting.appendStep", false]], "applycellchange() (diffpy.pdfgui.gui.parameterspanel.parameterspanel method)": [[3, "diffpy.pdfgui.gui.parameterspanel.ParametersPanel.applyCellChange", false]], "applycellchange() (diffpy.pdfgui.gui.phaseconfigurepanel.phaseconfigurepanel method)": [[3, "diffpy.pdfgui.gui.phaseconfigurepanel.PhaseConfigurePanel.applyCellChange", false]], "applycellchange() (diffpy.pdfgui.gui.phaseconstraintspanel.phaseconstraintspanel method)": [[3, "diffpy.pdfgui.gui.phaseconstraintspanel.PhaseConstraintsPanel.applyCellChange", false]], "applypairselection() (diffpy.pdfgui.control.fitstructure.fitstructure method)": [[2, "diffpy.pdfgui.control.fitstructure.FitStructure.applyPairSelection", false]], "applyparameters() (diffpy.pdfgui.control.fitdataset.fitdataset method)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.applyParameters", false]], "applyparameters() (diffpy.pdfgui.control.fitstructure.fitstructure method)": [[2, "diffpy.pdfgui.control.fitstructure.FitStructure.applyParameters", false]], "applyparameters() (diffpy.pdfgui.control.fitting.fitting method)": [[2, "diffpy.pdfgui.control.fitting.Fitting.applyParameters", false]], "applysymmetryconstraints() (diffpy.pdfgui.control.fitstructure.fitstructure method)": [[2, "diffpy.pdfgui.control.fitstructure.FitStructure.applySymmetryConstraints", false]], "applytextctrlchange() (diffpy.pdfgui.gui.phaseconfigurepanel.phaseconfigurepanel method)": [[3, "diffpy.pdfgui.gui.phaseconfigurepanel.PhaseConfigurePanel.applyTextCtrlChange", false]], "applytextctrlchange() (diffpy.pdfgui.gui.phaseconstraintspanel.phaseconstraintspanel method)": [[3, "diffpy.pdfgui.gui.phaseconstraintspanel.PhaseConstraintsPanel.applyTextCtrlChange", false]], "asunicode() (in module diffpy.pdfgui.utils)": [[0, "diffpy.pdfgui.utils.asunicode", false]], "autosizelabels() (diffpy.pdfgui.gui.wxextensions.autowidthlabelsgrid.autowidthlabelsgrid method)": [[5, "diffpy.pdfgui.gui.wxextensions.autowidthlabelsgrid.AutoWidthLabelsGrid.AutosizeLabels", false]], "autowidthlabelsgrid (class in diffpy.pdfgui.gui.wxextensions.autowidthlabelsgrid)": [[5, "diffpy.pdfgui.gui.wxextensions.autowidthlabelsgrid.AutoWidthLabelsGrid", false]], "autowidthlistctrl (class in diffpy.pdfgui.gui.wxextensions.listctrls)": [[5, "diffpy.pdfgui.gui.wxextensions.listctrls.AutoWidthListCtrl", false]], "blankpanel (class in diffpy.pdfgui.gui.blankpanel)": [[3, "diffpy.pdfgui.gui.blankpanel.BlankPanel", false]], "bondangledialog (class in diffpy.pdfgui.gui.bondangledialog)": [[3, "diffpy.pdfgui.gui.bondangledialog.BondAngleDialog", false]], "bondlengthdialog (class in diffpy.pdfgui.gui.bondlengthdialog)": [[3, "diffpy.pdfgui.gui.bondlengthdialog.BondLengthDialog", false]], "buildlinestyle() (diffpy.pdfgui.control.plotter.plotter method)": [[2, "diffpy.pdfgui.control.plotter.Plotter.buildLineStyle", false]], "buildlinesymbolstyle() (diffpy.pdfgui.control.plotter.plotter method)": [[2, "diffpy.pdfgui.control.plotter.Plotter.buildLineSymbolStyle", false]], "buildnamedict() (diffpy.pdfgui.control.fitting.fitting method)": [[2, "diffpy.pdfgui.control.fitting.Fitting.buildNameDict", false]], "buildsymbolstyle() (diffpy.pdfgui.control.plotter.plotter method)": [[2, "diffpy.pdfgui.control.plotter.Plotter.buildSymbolStyle", false]], "calculate() (diffpy.pdfgui.control.calculation.calculation method)": [[2, "diffpy.pdfgui.control.calculation.Calculation.calculate", false]], "calculation (class in diffpy.pdfgui.control.calculation)": [[2, "diffpy.pdfgui.control.calculation.Calculation", false]], "calculationpanel (class in diffpy.pdfgui.gui.calculationpanel)": [[3, "diffpy.pdfgui.gui.calculationpanel.CalculationPanel", false]], "cancopyselectedcells() (in module diffpy.pdfgui.gui.phasepanelutils)": [[3, "diffpy.pdfgui.gui.phasepanelutils.canCopySelectedCells", false]], "canpasteintocells() (in module diffpy.pdfgui.gui.phasepanelutils)": [[3, "diffpy.pdfgui.gui.phasepanelutils.canPasteIntoCells", false]], "catchfunctionerrors() (in module diffpy.pdfgui.gui.errorwrapper)": [[3, "diffpy.pdfgui.gui.errorwrapper.catchFunctionErrors", false]], "catchobjecterrors() (in module diffpy.pdfgui.gui.errorwrapper)": [[3, "diffpy.pdfgui.gui.errorwrapper.catchObjectErrors", false]], "changeparameterindex() (diffpy.pdfgui.control.fitdataset.fitdataset method)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.changeParameterIndex", false]], "changeparameterindex() (diffpy.pdfgui.control.fitstructure.fitstructure method)": [[2, "diffpy.pdfgui.control.fitstructure.FitStructure.changeParameterIndex", false]], "changeparameterindex() (diffpy.pdfgui.control.fitting.fitting method)": [[2, "diffpy.pdfgui.control.fitting.Fitting.changeParameterIndex", false]], "changestyle() (diffpy.pdfgui.gui.extendedplotframe.extendedplotframe method)": [[3, "diffpy.pdfgui.gui.extendedplotframe.ExtendedPlotFrame.changeStyle", false]], "checkconfiguration() (diffpy.pdfgui.gui.dopingseriespanel.dopingseriespanel method)": [[3, "diffpy.pdfgui.gui.dopingseriespanel.DopingSeriesPanel.checkConfiguration", false]], "checkforsave() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.checkForSave", false]], "checkqueue() (diffpy.pdfgui.control.pdfguicontrol.pdfguicontrol method)": [[2, "diffpy.pdfgui.control.pdfguicontrol.PDFGuiControl.checkQueue", false]], "clear() (diffpy.pdfgui.control.fitdataset.fitdataset method)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.clear", false]], "clear() (diffpy.pdfgui.control.pdfdataset.pdfdataset method)": [[2, "diffpy.pdfgui.control.pdfdataset.PDFDataSet.clear", false]], "clear() (diffpy.pdfgui.gui.extendedplotframe.extendedplotframe method)": [[3, "diffpy.pdfgui.gui.extendedplotframe.ExtendedPlotFrame.clear", false]], "clearrefined() (diffpy.pdfgui.control.fitdataset.fitdataset method)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.clearRefined", false]], "clearrefined() (diffpy.pdfgui.control.fitstructure.fitstructure method)": [[2, "diffpy.pdfgui.control.fitstructure.FitStructure.clearRefined", false]], "clearselections() (diffpy.pdfgui.gui.wxextensions.listctrls.autowidthlistctrl method)": [[5, "diffpy.pdfgui.gui.wxextensions.listctrls.AutoWidthListCtrl.clearSelections", false]], "cleartext() (diffpy.pdfgui.gui.outputpanel.outputpanel method)": [[3, "diffpy.pdfgui.gui.outputpanel.OutputPanel.clearText", false]], "clone() (diffpy.pdfgui.gui.wxextensions.validators.textvalidator method)": [[5, "diffpy.pdfgui.gui.wxextensions.validators.TextValidator.Clone", false]], "close() (diffpy.pdfgui.control.fitting.fitting method)": [[2, "diffpy.pdfgui.control.fitting.Fitting.close", false]], "close() (diffpy.pdfgui.control.pdfcomponent.pdfcomponent method)": [[2, "diffpy.pdfgui.control.pdfcomponent.PDFComponent.close", false]], "close() (diffpy.pdfgui.control.pdfguicontrol.pdfguicontrol method)": [[2, "diffpy.pdfgui.control.pdfguicontrol.PDFGuiControl.close", false]], "close() (diffpy.pdfgui.control.plotter.plotter method)": [[2, "diffpy.pdfgui.control.plotter.Plotter.close", false]], "close_keys (diffpy.pdfgui.gui.extendedplotframe.extendedplotframe attribute)": [[3, "diffpy.pdfgui.gui.extendedplotframe.ExtendedPlotFrame.close_keys", false]], "columnsortlistctrl (class in diffpy.pdfgui.gui.wxextensions.listctrls)": [[5, "diffpy.pdfgui.gui.wxextensions.listctrls.ColumnSortListCtrl", false]], "configure() (diffpy.pdfgui.control.fitting.fitting method)": [[2, "diffpy.pdfgui.control.fitting.Fitting.configure", false]], "configured (diffpy.pdfgui.control.fitting.fitting attribute)": [[2, "diffpy.pdfgui.control.fitting.Fitting.CONFIGURED", false]], "connected (diffpy.pdfgui.control.fitting.fitting attribute)": [[2, "diffpy.pdfgui.control.fitting.Fitting.CONNECTED", false]], "constraint (class in diffpy.pdfgui.control.constraint)": [[2, "diffpy.pdfgui.control.constraint.Constraint", false]], "controlconfigerror": [[2, "diffpy.pdfgui.control.controlerrors.ControlConfigError", false]], "controlerror": [[2, "diffpy.pdfgui.control.controlerrors.ControlError", false]], "controlfileerror": [[2, "diffpy.pdfgui.control.controlerrors.ControlFileError", false]], "controlindexerror": [[2, "diffpy.pdfgui.control.controlerrors.ControlIndexError", false]], "controlkeyerror": [[2, "diffpy.pdfgui.control.controlerrors.ControlKeyError", false]], "controlruntimeerror": [[2, "diffpy.pdfgui.control.controlerrors.ControlRuntimeError", false]], "controlstatuserror": [[2, "diffpy.pdfgui.control.controlerrors.ControlStatusError", false]], "controlsyntaxerror": [[2, "diffpy.pdfgui.control.controlerrors.ControlSyntaxError", false]], "controltypeerror": [[2, "diffpy.pdfgui.control.controlerrors.ControlTypeError", false]], "controlvalueerror": [[2, "diffpy.pdfgui.control.controlerrors.ControlValueError", false]], "copy() (diffpy.pdfgui.control.calculation.calculation method)": [[2, "diffpy.pdfgui.control.calculation.Calculation.copy", false]], "copy() (diffpy.pdfgui.control.fitdataset.fitdataset method)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.copy", false]], "copy() (diffpy.pdfgui.control.fitstructure.fitstructure method)": [[2, "diffpy.pdfgui.control.fitstructure.FitStructure.copy", false]], "copy() (diffpy.pdfgui.control.fitting.fitting method)": [[2, "diffpy.pdfgui.control.fitting.Fitting.copy", false]], "copy() (diffpy.pdfgui.control.organizer.organizer method)": [[2, "diffpy.pdfgui.control.organizer.Organizer.copy", false]], "copy() (diffpy.pdfgui.control.pdfdataset.pdfdataset method)": [[2, "diffpy.pdfgui.control.pdfdataset.PDFDataSet.copy", false]], "copy() (diffpy.pdfgui.control.pdfguicontrol.pdfguicontrol method)": [[2, "diffpy.pdfgui.control.pdfguicontrol.PDFGuiControl.copy", false]], "copy() (diffpy.pdfgui.control.pdfstructure.pdfstructure method)": [[2, "diffpy.pdfgui.control.pdfstructure.PDFStructure.copy", false]], "copybranch() (diffpy.pdfgui.gui.fittree.fittree method)": [[3, "diffpy.pdfgui.gui.fittree.FitTree.CopyBranch", false]], "copyselectedcells() (in module diffpy.pdfgui.gui.phasepanelutils)": [[3, "diffpy.pdfgui.gui.phasepanelutils.copySelectedCells", false]], "crw (diffpy.pdfgui.control.fitdataset.fitdataset property)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.crw", false]], "ctrlunpickler (class in diffpy.pdfgui.control.pdfguicontrol)": [[2, "diffpy.pdfgui.control.pdfguicontrol.CtrlUnpickler", false]], "datasetconfigurepanel (class in diffpy.pdfgui.gui.datasetconfigurepanel)": [[3, "diffpy.pdfgui.gui.datasetconfigurepanel.DataSetConfigurePanel", false]], "datasetconstraintpanel (class in diffpy.pdfgui.gui.datasetconstraintpanel)": [[3, "diffpy.pdfgui.gui.datasetconstraintpanel.DataSetConstraintPanel", false]], "datasetpanel (class in diffpy.pdfgui.gui.datasetpanel)": [[3, "diffpy.pdfgui.gui.datasetpanel.DataSetPanel", false]], "datasetresultspanel (class in diffpy.pdfgui.gui.datasetresultspanel)": [[3, "diffpy.pdfgui.gui.datasetresultspanel.DataSetResultsPanel", false]], "deblank() (in module diffpy.pdfgui.control.plotter)": [[2, "diffpy.pdfgui.control.plotter.deblank", false]], "debugoptions (class in diffpy.pdfgui.gui.debugoptions)": [[3, "diffpy.pdfgui.gui.debugoptions.DebugOptions", false]], "deleteatoms() (diffpy.pdfgui.control.fitstructure.fitstructure method)": [[2, "diffpy.pdfgui.control.fitstructure.FitStructure.deleteAtoms", false]], "deletebranches() (diffpy.pdfgui.gui.fittree.fittree method)": [[3, "diffpy.pdfgui.gui.fittree.FitTree.DeleteBranches", false]], "dgcalc (diffpy.pdfgui.control.fitdataset.fitdataset property)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.dGcalc", false]], "dgtrunc (diffpy.pdfgui.control.fitdataset.fitdataset property)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.dGtrunc", false]], "dialogabout (class in diffpy.pdfgui.gui.aboutdialog)": [[3, "diffpy.pdfgui.gui.aboutdialog.DialogAbout", false]], "diffpy.pdfgui": [[0, "module-diffpy.pdfgui", false]], "diffpy.pdfgui.applications": [[1, "module-diffpy.pdfgui.applications", false]], "diffpy.pdfgui.applications.pdfgui": [[1, "module-diffpy.pdfgui.applications.pdfgui", false]], "diffpy.pdfgui.control": [[2, "module-diffpy.pdfgui.control", false]], "diffpy.pdfgui.control.calculation": [[2, "module-diffpy.pdfgui.control.calculation", false]], "diffpy.pdfgui.control.constraint": [[2, "module-diffpy.pdfgui.control.constraint", false]], "diffpy.pdfgui.control.controlerrors": [[2, "module-diffpy.pdfgui.control.controlerrors", false]], "diffpy.pdfgui.control.fitdataset": [[2, "module-diffpy.pdfgui.control.fitdataset", false]], "diffpy.pdfgui.control.fitstructure": [[2, "module-diffpy.pdfgui.control.fitstructure", false]], "diffpy.pdfgui.control.fitting": [[2, "module-diffpy.pdfgui.control.fitting", false]], "diffpy.pdfgui.control.organizer": [[2, "module-diffpy.pdfgui.control.organizer", false]], "diffpy.pdfgui.control.parameter": [[2, "module-diffpy.pdfgui.control.parameter", false]], "diffpy.pdfgui.control.pdfcomponent": [[2, "module-diffpy.pdfgui.control.pdfcomponent", false]], "diffpy.pdfgui.control.pdfdataset": [[2, "module-diffpy.pdfgui.control.pdfdataset", false]], "diffpy.pdfgui.control.pdfguicontrol": [[2, "module-diffpy.pdfgui.control.pdfguicontrol", false]], "diffpy.pdfgui.control.pdfguimacros": [[2, "module-diffpy.pdfgui.control.pdfguimacros", false]], "diffpy.pdfgui.control.pdflist": [[2, "module-diffpy.pdfgui.control.pdflist", false]], "diffpy.pdfgui.control.pdfstructure": [[2, "module-diffpy.pdfgui.control.pdfstructure", false]], "diffpy.pdfgui.control.plotter": [[2, "module-diffpy.pdfgui.control.plotter", false]], "diffpy.pdfgui.control.structureviewer": [[2, "module-diffpy.pdfgui.control.structureviewer", false]], "diffpy.pdfgui.gui": [[3, "module-diffpy.pdfgui.gui", false]], "diffpy.pdfgui.gui.aboutdialog": [[3, "module-diffpy.pdfgui.gui.aboutdialog", false]], "diffpy.pdfgui.gui.adddatapanel": [[3, "module-diffpy.pdfgui.gui.adddatapanel", false]], "diffpy.pdfgui.gui.addphasepanel": [[3, "module-diffpy.pdfgui.gui.addphasepanel", false]], "diffpy.pdfgui.gui.blankpanel": [[3, "module-diffpy.pdfgui.gui.blankpanel", false]], "diffpy.pdfgui.gui.bondangledialog": [[3, "module-diffpy.pdfgui.gui.bondangledialog", false]], "diffpy.pdfgui.gui.bondlengthdialog": [[3, "module-diffpy.pdfgui.gui.bondlengthdialog", false]], "diffpy.pdfgui.gui.calculationpanel": [[3, "module-diffpy.pdfgui.gui.calculationpanel", false]], "diffpy.pdfgui.gui.datasetconfigurepanel": [[3, "module-diffpy.pdfgui.gui.datasetconfigurepanel", false]], "diffpy.pdfgui.gui.datasetconstraintpanel": [[3, "module-diffpy.pdfgui.gui.datasetconstraintpanel", false]], "diffpy.pdfgui.gui.datasetpanel": [[3, "module-diffpy.pdfgui.gui.datasetpanel", false]], "diffpy.pdfgui.gui.datasetresultspanel": [[3, "module-diffpy.pdfgui.gui.datasetresultspanel", false]], "diffpy.pdfgui.gui.debugoptions": [[3, "module-diffpy.pdfgui.gui.debugoptions", false]], "diffpy.pdfgui.gui.design": [[4, "module-diffpy.pdfgui.gui.design", false]], "diffpy.pdfgui.gui.dopingseriespanel": [[3, "module-diffpy.pdfgui.gui.dopingseriespanel", false]], "diffpy.pdfgui.gui.errorreportdialog": [[3, "module-diffpy.pdfgui.gui.errorreportdialog", false]], "diffpy.pdfgui.gui.errorreportdialog_control_fix": [[3, "module-diffpy.pdfgui.gui.errorreportdialog_control_fix", false]], "diffpy.pdfgui.gui.errorwrapper": [[3, "module-diffpy.pdfgui.gui.errorwrapper", false]], "diffpy.pdfgui.gui.extendedplotframe": [[3, "module-diffpy.pdfgui.gui.extendedplotframe", false]], "diffpy.pdfgui.gui.fitnotebookpanel": [[3, "module-diffpy.pdfgui.gui.fitnotebookpanel", false]], "diffpy.pdfgui.gui.fittree": [[3, "module-diffpy.pdfgui.gui.fittree", false]], "diffpy.pdfgui.gui.insertrowsdialog": [[3, "module-diffpy.pdfgui.gui.insertrowsdialog", false]], "diffpy.pdfgui.gui.journalpanel": [[3, "module-diffpy.pdfgui.gui.journalpanel", false]], "diffpy.pdfgui.gui.main": [[3, "module-diffpy.pdfgui.gui.main", false]], "diffpy.pdfgui.gui.mainframe": [[3, "module-diffpy.pdfgui.gui.mainframe", false]], "diffpy.pdfgui.gui.outputpanel": [[3, "module-diffpy.pdfgui.gui.outputpanel", false]], "diffpy.pdfgui.gui.paneltest": [[3, "module-diffpy.pdfgui.gui.paneltest", false]], "diffpy.pdfgui.gui.parameterspanel": [[3, "module-diffpy.pdfgui.gui.parameterspanel", false]], "diffpy.pdfgui.gui.pdfguiglobals": [[3, "module-diffpy.pdfgui.gui.pdfguiglobals", false]], "diffpy.pdfgui.gui.pdfpanel": [[3, "module-diffpy.pdfgui.gui.pdfpanel", false]], "diffpy.pdfgui.gui.phaseconfigurepanel": [[3, "module-diffpy.pdfgui.gui.phaseconfigurepanel", false]], "diffpy.pdfgui.gui.phaseconstraintspanel": [[3, "module-diffpy.pdfgui.gui.phaseconstraintspanel", false]], "diffpy.pdfgui.gui.phasenotebookpanel": [[3, "module-diffpy.pdfgui.gui.phasenotebookpanel", false]], "diffpy.pdfgui.gui.phasepanelutils": [[3, "module-diffpy.pdfgui.gui.phasepanelutils", false]], "diffpy.pdfgui.gui.phaseresultspanel": [[3, "module-diffpy.pdfgui.gui.phaseresultspanel", false]], "diffpy.pdfgui.gui.plotpanel": [[3, "module-diffpy.pdfgui.gui.plotpanel", false]], "diffpy.pdfgui.gui.preferencespanel": [[3, "module-diffpy.pdfgui.gui.preferencespanel", false]], "diffpy.pdfgui.gui.resultspanel": [[3, "module-diffpy.pdfgui.gui.resultspanel", false]], "diffpy.pdfgui.gui.rseriespanel": [[3, "module-diffpy.pdfgui.gui.rseriespanel", false]], "diffpy.pdfgui.gui.sgconstraindialog": [[3, "module-diffpy.pdfgui.gui.sgconstraindialog", false]], "diffpy.pdfgui.gui.sgstructuredialog": [[3, "module-diffpy.pdfgui.gui.sgstructuredialog", false]], "diffpy.pdfgui.gui.supercelldialog": [[3, "module-diffpy.pdfgui.gui.supercelldialog", false]], "diffpy.pdfgui.gui.temperatureseriespanel": [[3, "module-diffpy.pdfgui.gui.temperatureseriespanel", false]], "diffpy.pdfgui.gui.tooltips": [[3, "module-diffpy.pdfgui.gui.tooltips", false]], "diffpy.pdfgui.gui.welcomepanel": [[3, "module-diffpy.pdfgui.gui.welcomepanel", false]], "diffpy.pdfgui.gui.windowperspective": [[3, "module-diffpy.pdfgui.gui.windowperspective", false]], "diffpy.pdfgui.gui.wxextensions": [[5, "module-diffpy.pdfgui.gui.wxextensions", false]], "diffpy.pdfgui.gui.wxextensions.autowidthlabelsgrid": [[5, "module-diffpy.pdfgui.gui.wxextensions.autowidthlabelsgrid", false]], "diffpy.pdfgui.gui.wxextensions.listctrls": [[5, "module-diffpy.pdfgui.gui.wxextensions.listctrls", false]], "diffpy.pdfgui.gui.wxextensions.paneldialog": [[5, "module-diffpy.pdfgui.gui.wxextensions.paneldialog", false]], "diffpy.pdfgui.gui.wxextensions.textctrlutils": [[5, "module-diffpy.pdfgui.gui.wxextensions.textctrlutils", false]], "diffpy.pdfgui.gui.wxextensions.validators": [[5, "module-diffpy.pdfgui.gui.wxextensions.validators", false]], "diffpy.pdfgui.icons": [[6, "module-diffpy.pdfgui.icons", false]], "diffpy.pdfgui.tui": [[0, "module-diffpy.pdfgui.tui", false]], "diffpy.pdfgui.utils": [[0, "module-diffpy.pdfgui.utils", false]], "disablemainmenuitems() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.disableMainMenuItems", false]], "disablesharedmenuitems() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.disableSharedMenuItems", false]], "done (diffpy.pdfgui.control.fitting.fitting attribute)": [[2, "diffpy.pdfgui.control.fitting.Fitting.DONE", false]], "dopingseriespanel (class in diffpy.pdfgui.gui.dopingseriespanel)": [[3, "diffpy.pdfgui.gui.dopingseriespanel.DopingSeriesPanel", false]], "draw() (diffpy.pdfgui.control.plotter.plotter.curve method)": [[2, "diffpy.pdfgui.control.plotter.Plotter.Curve.draw", false]], "enable() (diffpy.pdfgui.gui.datasetpanel.datasetpanel method)": [[3, "diffpy.pdfgui.gui.datasetpanel.DataSetPanel.Enable", false]], "enable() (diffpy.pdfgui.gui.fitnotebookpanel.fitnotebookpanel method)": [[3, "diffpy.pdfgui.gui.fitnotebookpanel.FitNotebookPanel.Enable", false]], "enable() (diffpy.pdfgui.gui.phasenotebookpanel.phasenotebookpanel method)": [[3, "diffpy.pdfgui.gui.phasenotebookpanel.PhaseNotebookPanel.Enable", false]], "enablewidgets() (diffpy.pdfgui.gui.plotpanel.plotpanel method)": [[3, "diffpy.pdfgui.gui.plotpanel.PlotPanel.enableWidgets", false]], "enqueue() (diffpy.pdfgui.control.pdfguicontrol.pdfguicontrol method)": [[2, "diffpy.pdfgui.control.pdfguicontrol.PDFGuiControl.enqueue", false]], "errorreportdialog (class in diffpy.pdfgui.gui.errorreportdialog)": [[3, "diffpy.pdfgui.gui.errorreportdialog.ErrorReportDialog", false]], "errorreportdialogcontrolfix (class in diffpy.pdfgui.gui.errorreportdialog_control_fix)": [[3, "diffpy.pdfgui.gui.errorreportdialog_control_fix.ErrorReportDialogControlFix", false]], "evalformula() (diffpy.pdfgui.control.constraint.constraint method)": [[2, "diffpy.pdfgui.control.constraint.Constraint.evalFormula", false]], "exit() (diffpy.pdfgui.control.pdfguicontrol.pdfguicontrol method)": [[2, "diffpy.pdfgui.control.pdfguicontrol.PDFGuiControl.exit", false]], "expandasymmetricunit() (diffpy.pdfgui.control.fitstructure.fitstructure method)": [[2, "diffpy.pdfgui.control.fitstructure.FitStructure.expandAsymmetricUnit", false]], "expandsupercell() (diffpy.pdfgui.control.fitstructure.fitstructure method)": [[2, "diffpy.pdfgui.control.fitstructure.FitStructure.expandSuperCell", false]], "export() (diffpy.pdfgui.control.plotter.plotter method)": [[2, "diffpy.pdfgui.control.plotter.Plotter.export", false]], "extendedplotframe (class in diffpy.pdfgui.gui.extendedplotframe)": [[3, "diffpy.pdfgui.gui.extendedplotframe.ExtendedPlotFrame", false]], "extendedtoolbar (class in diffpy.pdfgui.gui.extendedplotframe)": [[3, "diffpy.pdfgui.gui.extendedplotframe.ExtendedToolbar", false]], "extendprojecttree() (diffpy.pdfgui.gui.fittree.fittree method)": [[3, "diffpy.pdfgui.gui.fittree.FitTree.ExtendProjectTree", false]], "fillcells() (diffpy.pdfgui.gui.parameterspanel.parameterspanel method)": [[3, "diffpy.pdfgui.gui.parameterspanel.ParametersPanel.fillCells", false]], "fillcells() (diffpy.pdfgui.gui.phaseconfigurepanel.phaseconfigurepanel method)": [[3, "diffpy.pdfgui.gui.phaseconfigurepanel.PhaseConfigurePanel.fillCells", false]], "fillcells() (diffpy.pdfgui.gui.phaseconstraintspanel.phaseconstraintspanel method)": [[3, "diffpy.pdfgui.gui.phaseconstraintspanel.PhaseConstraintsPanel.fillCells", false]], "filllist() (diffpy.pdfgui.gui.dopingseriespanel.dopingseriespanel method)": [[3, "diffpy.pdfgui.gui.dopingseriespanel.DopingSeriesPanel.fillList", false]], "filllist() (diffpy.pdfgui.gui.temperatureseriespanel.temperatureseriespanel method)": [[3, "diffpy.pdfgui.gui.temperatureseriespanel.TemperatureSeriesPanel.fillList", false]], "findparameters() (diffpy.pdfgui.control.fitdataset.fitdataset method)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.findParameters", false]], "findparameters() (diffpy.pdfgui.control.fitstructure.fitstructure method)": [[2, "diffpy.pdfgui.control.fitstructure.FitStructure.findParameters", false]], "findprefix() (diffpy.pdfgui.gui.wxextensions.listctrls.keyeventslistctrl method)": [[5, "diffpy.pdfgui.gui.wxextensions.listctrls.KeyEventsListCtrl.findPrefix", false]], "fitdataset (class in diffpy.pdfgui.control.fitdataset)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet", false]], "fitnotebookpanel (class in diffpy.pdfgui.gui.fitnotebookpanel)": [[3, "diffpy.pdfgui.gui.fitnotebookpanel.FitNotebookPanel", false]], "fitrmax (diffpy.pdfgui.control.fitdataset.fitdataset property)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.fitrmax", false]], "fitrmin (diffpy.pdfgui.control.fitdataset.fitdataset property)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.fitrmin", false]], "fitrstep (diffpy.pdfgui.control.fitdataset.fitdataset property)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.fitrstep", false]], "fitstructure (class in diffpy.pdfgui.control.fitstructure)": [[2, "diffpy.pdfgui.control.fitstructure.FitStructure", false]], "fitting (class in diffpy.pdfgui.control.fitting)": [[2, "diffpy.pdfgui.control.fitting.Fitting", false]], "fitting.worker (class in diffpy.pdfgui.control.fitting)": [[2, "diffpy.pdfgui.control.fitting.Fitting.Worker", false]], "fittree (class in diffpy.pdfgui.gui.fittree)": [[3, "diffpy.pdfgui.gui.fittree.FitTree", false]], "fittreeerror": [[3, "diffpy.pdfgui.gui.fittree.FitTreeError", false]], "float2str() (in module diffpy.pdfgui.gui.phasepanelutils)": [[3, "diffpy.pdfgui.gui.phasepanelutils.float2str", false]], "gcalc (diffpy.pdfgui.control.fitdataset.fitdataset property)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.Gcalc", false]], "gdiff (diffpy.pdfgui.control.fitdataset.fitdataset property)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.Gdiff", false]], "getalltype() (diffpy.pdfgui.gui.fittree.fittree method)": [[3, "diffpy.pdfgui.gui.fittree.FitTree.GetAllType", false]], "getbranchname() (diffpy.pdfgui.gui.fittree.fittree method)": [[3, "diffpy.pdfgui.gui.fittree.FitTree.GetBranchName", false]], "getcalculation() (diffpy.pdfgui.control.organizer.organizer method)": [[2, "diffpy.pdfgui.control.organizer.Organizer.getCalculation", false]], "getcalculations() (diffpy.pdfgui.gui.fittree.fittree method)": [[3, "diffpy.pdfgui.gui.fittree.FitTree.GetCalculations", false]], "getcalculations() (diffpy.pdfgui.tui.loadproject method)": [[0, "diffpy.pdfgui.tui.LoadProject.getCalculations", false]], "getchildren() (diffpy.pdfgui.gui.fittree.fittree method)": [[3, "diffpy.pdfgui.gui.fittree.FitTree.GetChildren", false]], "getclipboard() (diffpy.pdfgui.gui.fittree.fittree method)": [[3, "diffpy.pdfgui.gui.fittree.FitTree.GetClipboard", false]], "getconfig() (diffpy.pdfgui.control.structureviewer.structureviewer method)": [[2, "diffpy.pdfgui.control.structureviewer.StructureViewer.getConfig", false]], "getcontroldata() (diffpy.pdfgui.gui.fittree.fittree method)": [[3, "diffpy.pdfgui.gui.fittree.FitTree.GetControlData", false]], "getctrlletter() (diffpy.pdfgui.gui.bondangledialog.bondangledialog method)": [[3, "diffpy.pdfgui.gui.bondangledialog.BondAngleDialog.getCtrlLetter", false]], "getctrlletter() (diffpy.pdfgui.gui.bondlengthdialog.bondlengthdialog method)": [[3, "diffpy.pdfgui.gui.bondlengthdialog.BondLengthDialog.getCtrlLetter", false]], "getdata() (diffpy.pdfgui.control.calculation.calculation method)": [[2, "diffpy.pdfgui.control.calculation.Calculation.getData", false]], "getdata() (diffpy.pdfgui.control.fitdataset.fitdataset method)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.getData", false]], "getdata() (diffpy.pdfgui.control.fitstructure.fitstructure method)": [[2, "diffpy.pdfgui.control.fitstructure.FitStructure.getData", false]], "getdata() (diffpy.pdfgui.control.fitting.fitting method)": [[2, "diffpy.pdfgui.control.fitting.Fitting.getData", false]], "getdataset() (diffpy.pdfgui.control.organizer.organizer method)": [[2, "diffpy.pdfgui.control.organizer.Organizer.getDataSet", false]], "getdatasets() (diffpy.pdfgui.gui.fittree.fittree method)": [[3, "diffpy.pdfgui.gui.fittree.FitTree.GetDataSets", false]], "getdatasets() (diffpy.pdfgui.tui.loadproject method)": [[0, "diffpy.pdfgui.tui.LoadProject.getDataSets", false]], "getdopings() (diffpy.pdfgui.tui.loadproject method)": [[0, "diffpy.pdfgui.tui.LoadProject.getDopings", false]], "getengineexceptions() (in module diffpy.pdfgui.control.fitting)": [[2, "diffpy.pdfgui.control.fitting.getEngineExceptions", false]], "getengineoutput() (diffpy.pdfgui.control.pdfguicontrol.pdfguicontrol method)": [[2, "diffpy.pdfgui.control.pdfguicontrol.PDFGuiControl.getEngineOutput", false]], "getfileformats() (diffpy.pdfgui.control.structureviewer.structureviewer static method)": [[2, "diffpy.pdfgui.control.structureviewer.StructureViewer.getFileFormats", false]], "getfitroot() (diffpy.pdfgui.gui.fittree.fittree method)": [[3, "diffpy.pdfgui.gui.fittree.FitTree.GetFitRoot", false]], "getfits() (diffpy.pdfgui.tui.loadproject method)": [[0, "diffpy.pdfgui.tui.LoadProject.getFits", false]], "getfitsamplingtype() (diffpy.pdfgui.control.fitdataset.fitdataset method)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.getFitSamplingType", false]], "getlastdataset() (diffpy.pdfgui.gui.fittree.fittree method)": [[3, "diffpy.pdfgui.gui.fittree.FitTree.GetLastDataSet", false]], "getlastphase() (diffpy.pdfgui.gui.fittree.fittree method)": [[3, "diffpy.pdfgui.gui.fittree.FitTree.GetLastPhase", false]], "getlistctrl() (diffpy.pdfgui.gui.wxextensions.listctrls.columnsortlistctrl method)": [[5, "diffpy.pdfgui.gui.wxextensions.listctrls.ColumnSortListCtrl.GetListCtrl", false]], "getmetadata() (diffpy.pdfgui.control.calculation.calculation method)": [[2, "diffpy.pdfgui.control.calculation.Calculation.getMetaData", false]], "getmetadata() (diffpy.pdfgui.control.fitting.fitting method)": [[2, "diffpy.pdfgui.control.fitting.Fitting.getMetaData", false]], "getmetadatanames() (diffpy.pdfgui.control.calculation.calculation method)": [[2, "diffpy.pdfgui.control.calculation.Calculation.getMetaDataNames", false]], "getmetadatanames() (diffpy.pdfgui.control.fitting.fitting method)": [[2, "diffpy.pdfgui.control.fitting.Fitting.getMetaDataNames", false]], "getmno() (diffpy.pdfgui.gui.supercelldialog.supercelldialog method)": [[3, "diffpy.pdfgui.gui.supercelldialog.SupercellDialog.getMNO", false]], "getnodetype() (diffpy.pdfgui.gui.fittree.fittree method)": [[3, "diffpy.pdfgui.gui.fittree.FitTree.GetNodeType", false]], "getnumdatasets() (diffpy.pdfgui.gui.fittree.fittree method)": [[3, "diffpy.pdfgui.gui.fittree.FitTree.GetNumDataSets", false]], "getnumphases() (diffpy.pdfgui.gui.fittree.fittree method)": [[3, "diffpy.pdfgui.gui.fittree.FitTree.GetNumPhases", false]], "getnyquistsampling() (diffpy.pdfgui.control.fitdataset.fitdataset method)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.getNyquistSampling", false]], "getobssampling() (diffpy.pdfgui.control.fitdataset.fitdataset method)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.getObsSampling", false]], "getoffset() (diffpy.pdfgui.gui.sgconstraindialog.sgconstraindialog method)": [[3, "diffpy.pdfgui.gui.sgconstraindialog.SGConstrainDialog.getOffset", false]], "getoffset() (diffpy.pdfgui.gui.sgstructuredialog.sgstructuredialog method)": [[3, "diffpy.pdfgui.gui.sgstructuredialog.SGStructureDialog.getOffset", false]], "getpairselectionflags() (diffpy.pdfgui.control.fitstructure.fitstructure method)": [[2, "diffpy.pdfgui.control.fitstructure.FitStructure.getPairSelectionFlags", false]], "getphases() (diffpy.pdfgui.gui.fittree.fittree method)": [[3, "diffpy.pdfgui.gui.fittree.FitTree.GetPhases", false]], "getphases() (diffpy.pdfgui.tui.loadproject method)": [[0, "diffpy.pdfgui.tui.LoadProject.getPhases", false]], "getposflag() (diffpy.pdfgui.gui.sgconstraindialog.sgconstraindialog method)": [[3, "diffpy.pdfgui.gui.sgconstraindialog.SGConstrainDialog.getPosFlag", false]], "getpositioninsubtree() (diffpy.pdfgui.gui.fittree.fittree method)": [[3, "diffpy.pdfgui.gui.fittree.FitTree.GetPositionInSubtree", false]], "getselectedindices() (diffpy.pdfgui.control.fitstructure.fitstructure method)": [[2, "diffpy.pdfgui.control.fitstructure.FitStructure.getSelectedIndices", false]], "getselectedpairs() (diffpy.pdfgui.control.fitstructure.fitstructure method)": [[2, "diffpy.pdfgui.control.fitstructure.FitStructure.getSelectedPairs", false]], "getselectedparameters() (diffpy.pdfgui.gui.parameterspanel.parameterspanel method)": [[3, "diffpy.pdfgui.gui.parameterspanel.ParametersPanel.getSelectedParameters", false]], "getselectedyvals() (diffpy.pdfgui.gui.plotpanel.plotpanel method)": [[3, "diffpy.pdfgui.gui.plotpanel.PlotPanel.getSelectedYVals", false]], "getserver() (diffpy.pdfgui.control.fitting.fitting method)": [[2, "diffpy.pdfgui.control.fitting.Fitting.getServer", false]], "getsiblings() (diffpy.pdfgui.gui.fittree.fittree method)": [[3, "diffpy.pdfgui.gui.fittree.FitTree.GetSiblings", false]], "getspacegroup() (diffpy.pdfgui.control.fitstructure.fitstructure method)": [[2, "diffpy.pdfgui.control.fitstructure.FitStructure.getSpaceGroup", false]], "getspacegroup() (diffpy.pdfgui.gui.sgconstraindialog.sgconstraindialog method)": [[3, "diffpy.pdfgui.gui.sgconstraindialog.SGConstrainDialog.getSpaceGroup", false]], "getspacegroup() (diffpy.pdfgui.gui.sgstructuredialog.sgstructuredialog method)": [[3, "diffpy.pdfgui.gui.sgstructuredialog.SGStructureDialog.getSpaceGroup", false]], "getspacegrouplist() (diffpy.pdfgui.control.fitstructure.fitstructure method)": [[2, "diffpy.pdfgui.control.fitstructure.FitStructure.getSpaceGroupList", false]], "getstructure() (diffpy.pdfgui.control.organizer.organizer method)": [[2, "diffpy.pdfgui.control.organizer.Organizer.getStructure", false]], "getstructureviewer() (in module diffpy.pdfgui.control.structureviewer)": [[2, "diffpy.pdfgui.control.structureviewer.getStructureViewer", false]], "gettemperatures() (diffpy.pdfgui.tui.loadproject method)": [[0, "diffpy.pdfgui.tui.LoadProject.getTemperatures", false]], "gettempflag() (diffpy.pdfgui.gui.sgconstraindialog.sgconstraindialog method)": [[3, "diffpy.pdfgui.gui.sgconstraindialog.SGConstrainDialog.getTempFlag", false]], "gettreeitemdict() (diffpy.pdfgui.gui.fittree.fittree method)": [[3, "diffpy.pdfgui.gui.fittree.FitTree.GetTreeItemDict", false]], "getvar() (diffpy.pdfgui.control.pdfdataset.pdfdataset method)": [[2, "diffpy.pdfgui.control.pdfdataset.PDFDataSet.getvar", false]], "getvar() (diffpy.pdfgui.control.pdfstructure.pdfstructure method)": [[2, "diffpy.pdfgui.control.pdfstructure.PDFStructure.getvar", false]], "getxnames() (diffpy.pdfgui.control.calculation.calculation method)": [[2, "diffpy.pdfgui.control.calculation.Calculation.getXNames", false]], "getxnames() (diffpy.pdfgui.control.fitdataset.fitdataset method)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.getXNames", false]], "getxnames() (diffpy.pdfgui.control.fitstructure.fitstructure method)": [[2, "diffpy.pdfgui.control.fitstructure.FitStructure.getXNames", false]], "getxnames() (diffpy.pdfgui.control.fitting.fitting method)": [[2, "diffpy.pdfgui.control.fitting.Fitting.getXNames", false]], "getynames() (diffpy.pdfgui.control.calculation.calculation method)": [[2, "diffpy.pdfgui.control.calculation.Calculation.getYNames", false]], "getynames() (diffpy.pdfgui.control.fitdataset.fitdataset method)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.getYNames", false]], "getynames() (diffpy.pdfgui.control.fitstructure.fitstructure method)": [[2, "diffpy.pdfgui.control.fitstructure.FitStructure.getYNames", false]], "getynames() (diffpy.pdfgui.control.fitting.fitting method)": [[2, "diffpy.pdfgui.control.fitting.Fitting.getYNames", false]], "grid_interpolation() (in module diffpy.pdfgui.control.fitdataset)": [[2, "diffpy.pdfgui.control.fitdataset.grid_interpolation", false]], "gtrunc (diffpy.pdfgui.control.fitdataset.fitdataset property)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.Gtrunc", false]], "guess() (diffpy.pdfgui.control.constraint.constraint method)": [[2, "diffpy.pdfgui.control.constraint.Constraint.guess", false]], "handleengineexception() (in module diffpy.pdfgui.control.fitting)": [[2, "diffpy.pdfgui.control.fitting.handleEngineException", false]], "hascalculations() (diffpy.pdfgui.control.organizer.organizer method)": [[2, "diffpy.pdfgui.control.organizer.Organizer.hasCalculations", false]], "hasdatasets() (diffpy.pdfgui.control.organizer.organizer method)": [[2, "diffpy.pdfgui.control.organizer.Organizer.hasDataSets", false]], "hasstructures() (diffpy.pdfgui.control.organizer.organizer method)": [[2, "diffpy.pdfgui.control.organizer.Organizer.hasStructures", false]], "iconpath() (in module diffpy.pdfgui.gui.pdfguiglobals)": [[3, "diffpy.pdfgui.gui.pdfguiglobals.iconpath", false]], "incrementname() (in module diffpy.pdfgui.gui.fittree)": [[3, "diffpy.pdfgui.gui.fittree.incrementName", false]], "index() (diffpy.pdfgui.control.organizer.organizer method)": [[2, "diffpy.pdfgui.control.organizer.Organizer.index", false]], "index() (diffpy.pdfgui.control.pdfguicontrol.pdfguicontrol method)": [[2, "diffpy.pdfgui.control.pdfguicontrol.PDFGuiControl.index", false]], "initialized (diffpy.pdfgui.control.fitting.fitting attribute)": [[2, "diffpy.pdfgui.control.fitting.Fitting.INITIALIZED", false]], "initializesorter() (diffpy.pdfgui.gui.wxextensions.listctrls.columnsortlistctrl method)": [[5, "diffpy.pdfgui.gui.wxextensions.listctrls.ColumnSortListCtrl.initializeSorter", false]], "initializetree() (diffpy.pdfgui.gui.fittree.fittree method)": [[3, "diffpy.pdfgui.gui.fittree.FitTree.InitializeTree", false]], "initialstr() (diffpy.pdfgui.control.parameter.parameter method)": [[2, "diffpy.pdfgui.control.parameter.Parameter.initialStr", false]], "initialvalue() (diffpy.pdfgui.control.parameter.parameter method)": [[2, "diffpy.pdfgui.control.parameter.Parameter.initialValue", false]], "insertatoms() (diffpy.pdfgui.control.fitstructure.fitstructure method)": [[2, "diffpy.pdfgui.control.fitstructure.FitStructure.insertAtoms", false]], "insertcurve() (diffpy.pdfgui.gui.extendedplotframe.extendedplotframe method)": [[3, "diffpy.pdfgui.gui.extendedplotframe.ExtendedPlotFrame.insertCurve", false]], "insertrowsdialog (class in diffpy.pdfgui.gui.insertrowsdialog)": [[3, "diffpy.pdfgui.gui.insertrowsdialog.InsertRowsDialog", false]], "isalias() (in module diffpy.pdfgui.gui.tooltips)": [[3, "diffpy.pdfgui.gui.tooltips.isalias", false]], "isspacegrouppossible() (diffpy.pdfgui.control.fitstructure.fitstructure method)": [[2, "diffpy.pdfgui.control.fitstructure.FitStructure.isSpaceGroupPossible", false]], "isthreadrunning() (diffpy.pdfgui.control.fitting.fitting method)": [[2, "diffpy.pdfgui.control.fitting.Fitting.isThreadRunning", false]], "items() (diffpy.pdfgui.control.pdflist.pdflist method)": [[2, "diffpy.pdfgui.control.pdflist.PDFList.items", false]], "join() (diffpy.pdfgui.control.fitting.fitting method)": [[2, "diffpy.pdfgui.control.fitting.Fitting.join", false]], "journalpanel (class in diffpy.pdfgui.gui.journalpanel)": [[3, "diffpy.pdfgui.gui.journalpanel.JournalPanel", false]], "keyeventslistctrl (class in diffpy.pdfgui.gui.wxextensions.listctrls)": [[5, "diffpy.pdfgui.gui.wxextensions.listctrls.KeyEventsListCtrl", false]], "keys() (diffpy.pdfgui.control.pdflist.pdflist method)": [[2, "diffpy.pdfgui.control.pdflist.PDFList.keys", false]], "lambdaformula() (diffpy.pdfgui.control.constraint.constraint method)": [[2, "diffpy.pdfgui.control.constraint.Constraint.lambdaFormula", false]], "launchbrowser() (in module diffpy.pdfgui.gui.aboutdialog)": [[3, "diffpy.pdfgui.gui.aboutdialog.launchBrowser", false]], "legendboxproperties() (in module diffpy.pdfgui.gui.extendedplotframe)": [[3, "diffpy.pdfgui.gui.extendedplotframe.legendBoxProperties", false]], "license": [[8, "index-0", false]], "load() (diffpy.pdfgui.control.calculation.calculation method)": [[2, "diffpy.pdfgui.control.calculation.Calculation.load", false]], "load() (diffpy.pdfgui.control.fitdataset.fitdataset method)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.load", false]], "load() (diffpy.pdfgui.control.fitstructure.fitstructure method)": [[2, "diffpy.pdfgui.control.fitstructure.FitStructure.load", false]], "load() (diffpy.pdfgui.control.fitting.fitting method)": [[2, "diffpy.pdfgui.control.fitting.Fitting.load", false]], "load() (diffpy.pdfgui.control.organizer.organizer method)": [[2, "diffpy.pdfgui.control.organizer.Organizer.load", false]], "load() (diffpy.pdfgui.control.pdfguicontrol.pdfguicontrol method)": [[2, "diffpy.pdfgui.control.pdfguicontrol.PDFGuiControl.load", false]], "load() (diffpy.pdfgui.tui.loadproject method)": [[0, "diffpy.pdfgui.tui.LoadProject.load", false]], "loadconfiguration() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.loadConfiguration", false]], "loaddataset() (diffpy.pdfgui.control.pdfguicontrol.pdfguicontrol method)": [[2, "diffpy.pdfgui.control.pdfguicontrol.PDFGuiControl.loadDataset", false]], "loadproject (class in diffpy.pdfgui.tui)": [[0, "diffpy.pdfgui.tui.LoadProject", false]], "loads() (diffpy.pdfgui.control.pdfguicontrol.ctrlunpickler static method)": [[2, "diffpy.pdfgui.control.pdfguicontrol.CtrlUnpickler.loads", false]], "loadstructure() (diffpy.pdfgui.control.pdfguicontrol.pdfguicontrol method)": [[2, "diffpy.pdfgui.control.pdfguicontrol.PDFGuiControl.loadStructure", false]], "lock() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.lock", false]], "main() (in module diffpy.pdfgui.applications.pdfgui)": [[1, "diffpy.pdfgui.applications.pdfgui.main", false]], "main() (in module diffpy.pdfgui.gui.main)": [[3, "diffpy.pdfgui.gui.main.main", false]], "mainframe (class in diffpy.pdfgui.gui.mainframe)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame", false]], "makedopingseries() (in module diffpy.pdfgui.control.pdfguimacros)": [[2, "diffpy.pdfgui.control.pdfguimacros.makeDopingSeries", false]], "makeidm() (diffpy.pdfgui.gui.wxextensions.listctrls.columnsortlistctrl method)": [[5, "diffpy.pdfgui.gui.wxextensions.listctrls.ColumnSortListCtrl.makeIDM", false]], "makerseries() (in module diffpy.pdfgui.control.pdfguimacros)": [[2, "diffpy.pdfgui.control.pdfguimacros.makeRSeries", false]], "maketemperatureseries() (in module diffpy.pdfgui.control.pdfguimacros)": [[2, "diffpy.pdfgui.control.pdfguimacros.makeTemperatureSeries", false]], "maketreeselection() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.makeTreeSelection", false]], "module": [[0, "module-diffpy.pdfgui", false], [0, "module-diffpy.pdfgui.tui", false], [0, "module-diffpy.pdfgui.utils", false], [1, "module-diffpy.pdfgui.applications", false], [1, "module-diffpy.pdfgui.applications.pdfgui", false], [2, "module-diffpy.pdfgui.control", false], [2, "module-diffpy.pdfgui.control.calculation", false], [2, "module-diffpy.pdfgui.control.constraint", false], [2, "module-diffpy.pdfgui.control.controlerrors", false], [2, "module-diffpy.pdfgui.control.fitdataset", false], [2, "module-diffpy.pdfgui.control.fitstructure", false], [2, "module-diffpy.pdfgui.control.fitting", false], [2, "module-diffpy.pdfgui.control.organizer", false], [2, "module-diffpy.pdfgui.control.parameter", false], [2, "module-diffpy.pdfgui.control.pdfcomponent", false], [2, "module-diffpy.pdfgui.control.pdfdataset", false], [2, "module-diffpy.pdfgui.control.pdfguicontrol", false], [2, "module-diffpy.pdfgui.control.pdfguimacros", false], [2, "module-diffpy.pdfgui.control.pdflist", false], [2, "module-diffpy.pdfgui.control.pdfstructure", false], [2, "module-diffpy.pdfgui.control.plotter", false], [2, "module-diffpy.pdfgui.control.structureviewer", false], [3, "module-diffpy.pdfgui.gui", false], [3, "module-diffpy.pdfgui.gui.aboutdialog", false], [3, "module-diffpy.pdfgui.gui.adddatapanel", false], [3, "module-diffpy.pdfgui.gui.addphasepanel", false], [3, "module-diffpy.pdfgui.gui.blankpanel", false], [3, "module-diffpy.pdfgui.gui.bondangledialog", false], [3, "module-diffpy.pdfgui.gui.bondlengthdialog", false], [3, "module-diffpy.pdfgui.gui.calculationpanel", false], [3, "module-diffpy.pdfgui.gui.datasetconfigurepanel", false], [3, "module-diffpy.pdfgui.gui.datasetconstraintpanel", false], [3, "module-diffpy.pdfgui.gui.datasetpanel", false], [3, "module-diffpy.pdfgui.gui.datasetresultspanel", false], [3, "module-diffpy.pdfgui.gui.debugoptions", false], [3, "module-diffpy.pdfgui.gui.dopingseriespanel", false], [3, "module-diffpy.pdfgui.gui.errorreportdialog", false], [3, "module-diffpy.pdfgui.gui.errorreportdialog_control_fix", false], [3, "module-diffpy.pdfgui.gui.errorwrapper", false], [3, "module-diffpy.pdfgui.gui.extendedplotframe", false], [3, "module-diffpy.pdfgui.gui.fitnotebookpanel", false], [3, "module-diffpy.pdfgui.gui.fittree", false], [3, "module-diffpy.pdfgui.gui.insertrowsdialog", false], [3, "module-diffpy.pdfgui.gui.journalpanel", false], [3, "module-diffpy.pdfgui.gui.main", false], [3, "module-diffpy.pdfgui.gui.mainframe", false], [3, "module-diffpy.pdfgui.gui.outputpanel", false], [3, "module-diffpy.pdfgui.gui.paneltest", false], [3, "module-diffpy.pdfgui.gui.parameterspanel", false], [3, "module-diffpy.pdfgui.gui.pdfguiglobals", false], [3, "module-diffpy.pdfgui.gui.pdfpanel", false], [3, "module-diffpy.pdfgui.gui.phaseconfigurepanel", false], [3, "module-diffpy.pdfgui.gui.phaseconstraintspanel", false], [3, "module-diffpy.pdfgui.gui.phasenotebookpanel", false], [3, "module-diffpy.pdfgui.gui.phasepanelutils", false], [3, "module-diffpy.pdfgui.gui.phaseresultspanel", false], [3, "module-diffpy.pdfgui.gui.plotpanel", false], [3, "module-diffpy.pdfgui.gui.preferencespanel", false], [3, "module-diffpy.pdfgui.gui.resultspanel", false], [3, "module-diffpy.pdfgui.gui.rseriespanel", false], [3, "module-diffpy.pdfgui.gui.sgconstraindialog", false], [3, "module-diffpy.pdfgui.gui.sgstructuredialog", false], [3, "module-diffpy.pdfgui.gui.supercelldialog", false], [3, "module-diffpy.pdfgui.gui.temperatureseriespanel", false], [3, "module-diffpy.pdfgui.gui.tooltips", false], [3, "module-diffpy.pdfgui.gui.welcomepanel", false], [3, "module-diffpy.pdfgui.gui.windowperspective", false], [4, "module-diffpy.pdfgui.gui.design", false], [5, "module-diffpy.pdfgui.gui.wxextensions", false], [5, "module-diffpy.pdfgui.gui.wxextensions.autowidthlabelsgrid", false], [5, "module-diffpy.pdfgui.gui.wxextensions.listctrls", false], [5, "module-diffpy.pdfgui.gui.wxextensions.paneldialog", false], [5, "module-diffpy.pdfgui.gui.wxextensions.textctrlutils", false], [5, "module-diffpy.pdfgui.gui.wxextensions.validators", false], [6, "module-diffpy.pdfgui.icons", false]], "mplkeypress() (diffpy.pdfgui.gui.extendedplotframe.extendedplotframe method)": [[3, "diffpy.pdfgui.gui.extendedplotframe.ExtendedPlotFrame.mplKeyPress", false]], "myapp (class in diffpy.pdfgui.gui.errorreportdialog)": [[3, "diffpy.pdfgui.gui.errorreportdialog.MyApp", false]], "myapp (class in diffpy.pdfgui.gui.errorreportdialog_control_fix)": [[3, "diffpy.pdfgui.gui.errorreportdialog_control_fix.MyApp", false]], "myapp (class in diffpy.pdfgui.gui.paneltest)": [[3, "diffpy.pdfgui.gui.paneltest.MyApp", false]], "myframe (class in diffpy.pdfgui.gui.paneltest)": [[3, "diffpy.pdfgui.gui.paneltest.MyFrame", false]], "needssave() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.needsSave", false]], "newcalculation() (diffpy.pdfgui.control.pdfguicontrol.pdfguicontrol method)": [[2, "diffpy.pdfgui.control.pdfguicontrol.PDFGuiControl.newCalculation", false]], "newfitting() (diffpy.pdfgui.control.pdfguicontrol.pdfguicontrol method)": [[2, "diffpy.pdfgui.control.pdfguicontrol.PDFGuiControl.newFitting", false]], "newstructure() (diffpy.pdfgui.control.pdfguicontrol.pdfguicontrol method)": [[2, "diffpy.pdfgui.control.pdfguicontrol.PDFGuiControl.newStructure", false]], "notify() (diffpy.pdfgui.control.plotter.plotter method)": [[2, "diffpy.pdfgui.control.plotter.Plotter.notify", false]], "notify() (diffpy.pdfgui.control.plotter.plotter.curve method)": [[2, "diffpy.pdfgui.control.plotter.Plotter.Curve.notify", false]], "numericstringsort() (in module diffpy.pdfgui.utils)": [[0, "diffpy.pdfgui.utils.numericStringSort", false]], "obtainrefined() (diffpy.pdfgui.control.fitdataset.fitdataset method)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.obtainRefined", false]], "obtainrefined() (diffpy.pdfgui.control.fitstructure.fitstructure method)": [[2, "diffpy.pdfgui.control.fitstructure.FitStructure.obtainRefined", false]], "onabout() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onAbout", false]], "onadd() (diffpy.pdfgui.gui.dopingseriespanel.dopingseriespanel method)": [[3, "diffpy.pdfgui.gui.dopingseriespanel.DopingSeriesPanel.onAdd", false]], "onadd() (diffpy.pdfgui.gui.temperatureseriespanel.temperatureseriespanel method)": [[3, "diffpy.pdfgui.gui.temperatureseriespanel.TemperatureSeriesPanel.onAdd", false]], "onapplyparameters() (diffpy.pdfgui.gui.parameterspanel.parameterspanel method)": [[3, "diffpy.pdfgui.gui.parameterspanel.ParametersPanel.onApplyParameters", false]], "onbeginlabeledit() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onBeginLabelEdit", false]], "onbrowse() (diffpy.pdfgui.gui.preferencespanel.preferencespanel method)": [[3, "diffpy.pdfgui.gui.preferencespanel.PreferencesPanel.onBrowse", false]], "oncalcrange() (diffpy.pdfgui.gui.calculationpanel.calculationpanel method)": [[3, "diffpy.pdfgui.gui.calculationpanel.CalculationPanel.onCalcRange", false]], "oncancel() (diffpy.pdfgui.gui.adddatapanel.adddatapanel method)": [[3, "diffpy.pdfgui.gui.adddatapanel.AddDataPanel.onCancel", false]], "oncancel() (diffpy.pdfgui.gui.addphasepanel.addphasepanel method)": [[3, "diffpy.pdfgui.gui.addphasepanel.AddPhasePanel.onCancel", false]], "oncancel() (diffpy.pdfgui.gui.bondangledialog.bondangledialog method)": [[3, "diffpy.pdfgui.gui.bondangledialog.BondAngleDialog.onCancel", false]], "oncancel() (diffpy.pdfgui.gui.bondlengthdialog.bondlengthdialog method)": [[3, "diffpy.pdfgui.gui.bondlengthdialog.BondLengthDialog.onCancel", false]], "oncancel() (diffpy.pdfgui.gui.dopingseriespanel.dopingseriespanel method)": [[3, "diffpy.pdfgui.gui.dopingseriespanel.DopingSeriesPanel.onCancel", false]], "oncancel() (diffpy.pdfgui.gui.preferencespanel.preferencespanel method)": [[3, "diffpy.pdfgui.gui.preferencespanel.PreferencesPanel.onCancel", false]], "oncancel() (diffpy.pdfgui.gui.rseriespanel.rseriespanel method)": [[3, "diffpy.pdfgui.gui.rseriespanel.RSeriesPanel.onCancel", false]], "oncancel() (diffpy.pdfgui.gui.sgconstraindialog.sgconstraindialog method)": [[3, "diffpy.pdfgui.gui.sgconstraindialog.SGConstrainDialog.onCancel", false]], "oncancel() (diffpy.pdfgui.gui.sgstructuredialog.sgstructuredialog method)": [[3, "diffpy.pdfgui.gui.sgstructuredialog.SGStructureDialog.onCancel", false]], "oncancel() (diffpy.pdfgui.gui.supercelldialog.supercelldialog method)": [[3, "diffpy.pdfgui.gui.supercelldialog.SupercellDialog.onCancel", false]], "oncancel() (diffpy.pdfgui.gui.temperatureseriespanel.temperatureseriespanel method)": [[3, "diffpy.pdfgui.gui.temperatureseriespanel.TemperatureSeriesPanel.onCancel", false]], "oncellchange() (diffpy.pdfgui.gui.parameterspanel.parameterspanel method)": [[3, "diffpy.pdfgui.gui.parameterspanel.ParametersPanel.onCellChange", false]], "oncellchange() (diffpy.pdfgui.gui.phaseconfigurepanel.phaseconfigurepanel method)": [[3, "diffpy.pdfgui.gui.phaseconfigurepanel.PhaseConfigurePanel.onCellChange", false]], "oncellchange() (diffpy.pdfgui.gui.phaseconstraintspanel.phaseconstraintspanel method)": [[3, "diffpy.pdfgui.gui.phaseconstraintspanel.PhaseConstraintsPanel.onCellChange", false]], "oncellleftclick() (diffpy.pdfgui.gui.parameterspanel.parameterspanel method)": [[3, "diffpy.pdfgui.gui.parameterspanel.ParametersPanel.onCellLeftClick", false]], "oncellrightclick() (diffpy.pdfgui.gui.parameterspanel.parameterspanel method)": [[3, "diffpy.pdfgui.gui.parameterspanel.ParametersPanel.onCellRightClick", false]], "oncellrightclick() (diffpy.pdfgui.gui.phaseconfigurepanel.phaseconfigurepanel method)": [[3, "diffpy.pdfgui.gui.phaseconfigurepanel.PhaseConfigurePanel.onCellRightClick", false]], "oncellrightclick() (diffpy.pdfgui.gui.phaseconstraintspanel.phaseconstraintspanel method)": [[3, "diffpy.pdfgui.gui.phaseconstraintspanel.PhaseConstraintsPanel.onCellRightClick", false]], "onchar() (diffpy.pdfgui.gui.wxextensions.validators.textvalidator method)": [[5, "diffpy.pdfgui.gui.wxextensions.validators.TextValidator.OnChar", false]], "onclose() (diffpy.pdfgui.gui.extendedplotframe.extendedplotframe method)": [[3, "diffpy.pdfgui.gui.extendedplotframe.ExtendedPlotFrame.onClose", false]], "onclose() (diffpy.pdfgui.gui.journalpanel.journalpanel method)": [[3, "diffpy.pdfgui.gui.journalpanel.JournalPanel.onClose", false]], "oncolclick() (diffpy.pdfgui.gui.dopingseriespanel.dopingseriespanel method)": [[3, "diffpy.pdfgui.gui.dopingseriespanel.DopingSeriesPanel.onColClick", false]], "oncolclick() (diffpy.pdfgui.gui.temperatureseriespanel.temperatureseriespanel method)": [[3, "diffpy.pdfgui.gui.temperatureseriespanel.TemperatureSeriesPanel.onColClick", false]], "oncolumbialogo() (diffpy.pdfgui.gui.aboutdialog.dialogabout method)": [[3, "diffpy.pdfgui.gui.aboutdialog.DialogAbout.onColumbiaLogo", false]], "oncombokillfocus() (diffpy.pdfgui.gui.bondlengthdialog.bondlengthdialog method)": [[3, "diffpy.pdfgui.gui.bondlengthdialog.BondLengthDialog.onComboKillFocus", false]], "oncommunity() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onCommunity", false]], "oncopy() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onCopy", false]], "oncopyerrorlog() (diffpy.pdfgui.gui.errorreportdialog.errorreportdialog method)": [[3, "diffpy.pdfgui.gui.errorreportdialog.ErrorReportDialog.onCopyErrorLog", false]], "oncustom() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onCustom", false]], "ondanselogo() (diffpy.pdfgui.gui.aboutdialog.dialogabout method)": [[3, "diffpy.pdfgui.gui.aboutdialog.DialogAbout.onDanseLogo", false]], "ondefaultlayout() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onDefaultLayout", false]], "ondelete() (diffpy.pdfgui.gui.dopingseriespanel.dopingseriespanel method)": [[3, "diffpy.pdfgui.gui.dopingseriespanel.DopingSeriesPanel.onDelete", false]], "ondelete() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onDelete", false]], "ondelete() (diffpy.pdfgui.gui.temperatureseriespanel.temperatureseriespanel method)": [[3, "diffpy.pdfgui.gui.temperatureseriespanel.TemperatureSeriesPanel.onDelete", false]], "ondocumentation() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onDocumentation", false]], "ondoubleclick() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onDoubleClick", false]], "ondoubleclick2() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onDoubleClick2", false]], "ondown() (diffpy.pdfgui.gui.dopingseriespanel.dopingseriespanel method)": [[3, "diffpy.pdfgui.gui.dopingseriespanel.DopingSeriesPanel.onDown", false]], "ondown() (diffpy.pdfgui.gui.temperatureseriespanel.temperatureseriespanel method)": [[3, "diffpy.pdfgui.gui.temperatureseriespanel.TemperatureSeriesPanel.onDown", false]], "ondseries() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onDSeries", false]], "oneditorshown() (diffpy.pdfgui.gui.parameterspanel.parameterspanel method)": [[3, "diffpy.pdfgui.gui.parameterspanel.ParametersPanel.onEditorShown", false]], "oneditorshown() (diffpy.pdfgui.gui.phaseconfigurepanel.phaseconfigurepanel method)": [[3, "diffpy.pdfgui.gui.phaseconfigurepanel.PhaseConfigurePanel.onEditorShown", false]], "oneditorshown() (diffpy.pdfgui.gui.phaseconstraintspanel.phaseconstraintspanel method)": [[3, "diffpy.pdfgui.gui.phaseconstraintspanel.PhaseConstraintsPanel.onEditorShown", false]], "onendlabeledit() (diffpy.pdfgui.gui.dopingseriespanel.dopingseriespanel method)": [[3, "diffpy.pdfgui.gui.dopingseriespanel.DopingSeriesPanel.onEndLabelEdit", false]], "onendlabeledit() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onEndLabelEdit", false]], "onendlabeledit() (diffpy.pdfgui.gui.temperatureseriespanel.temperatureseriespanel method)": [[3, "diffpy.pdfgui.gui.temperatureseriespanel.TemperatureSeriesPanel.onEndLabelEdit", false]], "onenter() (diffpy.pdfgui.gui.plotpanel.plotpanel method)": [[3, "diffpy.pdfgui.gui.plotpanel.PlotPanel.onEnter", false]], "onexport() (diffpy.pdfgui.gui.calculationpanel.calculationpanel method)": [[3, "diffpy.pdfgui.gui.calculationpanel.CalculationPanel.onExport", false]], "onexport() (diffpy.pdfgui.gui.datasetresultspanel.datasetresultspanel method)": [[3, "diffpy.pdfgui.gui.datasetresultspanel.DataSetResultsPanel.onExport", false]], "onexport() (diffpy.pdfgui.gui.journalpanel.journalpanel method)": [[3, "diffpy.pdfgui.gui.journalpanel.JournalPanel.onExport", false]], "onexportnewstruct() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onExportNewStruct", false]], "onexportpdf() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onExportPDF", false]], "onexportres() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onExportRes", false]], "onexportstruct() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onExportStruct", false]], "ongoogle() (diffpy.pdfgui.gui.errorreportdialog.errorreportdialog method)": [[3, "diffpy.pdfgui.gui.errorreportdialog.ErrorReportDialog.onGoogle", false]], "ongridrangeselect() (diffpy.pdfgui.gui.parameterspanel.parameterspanel method)": [[3, "diffpy.pdfgui.gui.parameterspanel.ParametersPanel.onGridRangeSelect", false]], "oninit() (diffpy.pdfgui.gui.errorreportdialog.myapp method)": [[3, "diffpy.pdfgui.gui.errorreportdialog.MyApp.OnInit", false]], "oninit() (diffpy.pdfgui.gui.errorreportdialog_control_fix.myapp method)": [[3, "diffpy.pdfgui.gui.errorreportdialog_control_fix.MyApp.OnInit", false]], "oninit() (diffpy.pdfgui.gui.main.pdfguiapp method)": [[3, "diffpy.pdfgui.gui.main.PDFGuiApp.OnInit", false]], "oninit() (diffpy.pdfgui.gui.paneltest.myapp method)": [[3, "diffpy.pdfgui.gui.paneltest.MyApp.OnInit", false]], "oninscalc() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onInsCalc", false]], "oninsdata() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onInsData", false]], "oninsphase() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onInsPhase", false]], "onkey() (diffpy.pdfgui.gui.journalpanel.journalpanel method)": [[3, "diffpy.pdfgui.gui.journalpanel.JournalPanel.onKey", false]], "onkey() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onKey", false]], "onkey() (diffpy.pdfgui.gui.phaseconfigurepanel.phaseconfigurepanel method)": [[3, "diffpy.pdfgui.gui.phaseconfigurepanel.PhaseConfigurePanel.onKey", false]], "onkey() (diffpy.pdfgui.gui.phaseconstraintspanel.phaseconstraintspanel method)": [[3, "diffpy.pdfgui.gui.phaseconstraintspanel.PhaseConstraintsPanel.onKey", false]], "onkey() (diffpy.pdfgui.gui.wxextensions.listctrls.keyeventslistctrl method)": [[5, "diffpy.pdfgui.gui.wxextensions.listctrls.KeyEventsListCtrl.OnKey", false]], "onkeydown() (diffpy.pdfgui.gui.wxextensions.listctrls.keyeventslistctrl method)": [[5, "diffpy.pdfgui.gui.wxextensions.listctrls.KeyEventsListCtrl.OnKeyDown", false]], "onkillfocus() (diffpy.pdfgui.gui.calculationpanel.calculationpanel method)": [[3, "diffpy.pdfgui.gui.calculationpanel.CalculationPanel.onKillFocus", false]], "onkillfocus() (diffpy.pdfgui.gui.phaseconfigurepanel.phaseconfigurepanel method)": [[3, "diffpy.pdfgui.gui.phaseconfigurepanel.PhaseConfigurePanel.onKillFocus", false]], "onkillfocus() (diffpy.pdfgui.gui.phaseconstraintspanel.phaseconstraintspanel method)": [[3, "diffpy.pdfgui.gui.phaseconstraintspanel.PhaseConstraintsPanel.onKillFocus", false]], "onkillfocus() (diffpy.pdfgui.gui.sgconstraindialog.sgconstraindialog method)": [[3, "diffpy.pdfgui.gui.sgconstraindialog.SGConstrainDialog.onKillFocus", false]], "onkillfocus() (diffpy.pdfgui.gui.sgstructuredialog.sgstructuredialog method)": [[3, "diffpy.pdfgui.gui.sgstructuredialog.SGStructureDialog.onKillFocus", false]], "onlabelrightclick() (diffpy.pdfgui.gui.phaseconfigurepanel.phaseconfigurepanel method)": [[3, "diffpy.pdfgui.gui.phaseconfigurepanel.PhaseConfigurePanel.onLabelRightClick", false]], "onlabelrightclick() (diffpy.pdfgui.gui.phaseconstraintspanel.phaseconstraintspanel method)": [[3, "diffpy.pdfgui.gui.phaseconstraintspanel.PhaseConstraintsPanel.onLabelRightClick", false]], "onlosefocus() (diffpy.pdfgui.gui.datasetconfigurepanel.datasetconfigurepanel method)": [[3, "diffpy.pdfgui.gui.datasetconfigurepanel.DataSetConfigurePanel.onLoseFocus", false]], "onlosefocus() (diffpy.pdfgui.gui.datasetconstraintpanel.datasetconstraintpanel method)": [[3, "diffpy.pdfgui.gui.datasetconstraintpanel.DataSetConstraintPanel.onLoseFocus", false]], "onmainmenu() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onMainMenu", false]], "onmiddleclick() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onMiddleClick", false]], "onmrufile() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onMRUFile", false]], "onmsulogo() (diffpy.pdfgui.gui.aboutdialog.dialogabout method)": [[3, "diffpy.pdfgui.gui.aboutdialog.DialogAbout.onMsuLogo", false]], "onnew() (diffpy.pdfgui.gui.addphasepanel.addphasepanel method)": [[3, "diffpy.pdfgui.gui.addphasepanel.AddPhasePanel.onNew", false]], "onnew() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onNew", false]], "onnewfit() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onNewFit", false]], "onnotebookchanged() (diffpy.pdfgui.gui.datasetpanel.datasetpanel method)": [[3, "diffpy.pdfgui.gui.datasetpanel.DataSetPanel.onNotebookChanged", false]], "onnotebookpagechanged() (diffpy.pdfgui.gui.phasenotebookpanel.phasenotebookpanel method)": [[3, "diffpy.pdfgui.gui.phasenotebookpanel.PhaseNotebookPanel.onNotebookPageChanged", false]], "onnotebookpagechanging() (diffpy.pdfgui.gui.phasenotebookpanel.phasenotebookpanel method)": [[3, "diffpy.pdfgui.gui.phasenotebookpanel.PhaseNotebookPanel.onNotebookPageChanging", false]], "onnsflogo() (diffpy.pdfgui.gui.aboutdialog.dialogabout method)": [[3, "diffpy.pdfgui.gui.aboutdialog.DialogAbout.onNsfLogo", false]], "onok() (diffpy.pdfgui.gui.bondangledialog.bondangledialog method)": [[3, "diffpy.pdfgui.gui.bondangledialog.BondAngleDialog.onOk", false]], "onok() (diffpy.pdfgui.gui.bondlengthdialog.bondlengthdialog method)": [[3, "diffpy.pdfgui.gui.bondlengthdialog.BondLengthDialog.onOk", false]], "onok() (diffpy.pdfgui.gui.dopingseriespanel.dopingseriespanel method)": [[3, "diffpy.pdfgui.gui.dopingseriespanel.DopingSeriesPanel.onOK", false]], "onok() (diffpy.pdfgui.gui.preferencespanel.preferencespanel method)": [[3, "diffpy.pdfgui.gui.preferencespanel.PreferencesPanel.onOK", false]], "onok() (diffpy.pdfgui.gui.rseriespanel.rseriespanel method)": [[3, "diffpy.pdfgui.gui.rseriespanel.RSeriesPanel.onOK", false]], "onok() (diffpy.pdfgui.gui.sgconstraindialog.sgconstraindialog method)": [[3, "diffpy.pdfgui.gui.sgconstraindialog.SGConstrainDialog.onOk", false]], "onok() (diffpy.pdfgui.gui.sgstructuredialog.sgstructuredialog method)": [[3, "diffpy.pdfgui.gui.sgstructuredialog.SGStructureDialog.onOk", false]], "onok() (diffpy.pdfgui.gui.supercelldialog.supercelldialog method)": [[3, "diffpy.pdfgui.gui.supercelldialog.SupercellDialog.onOk", false]], "onok() (diffpy.pdfgui.gui.temperatureseriespanel.temperatureseriespanel method)": [[3, "diffpy.pdfgui.gui.temperatureseriespanel.TemperatureSeriesPanel.onOK", false]], "onopen() (diffpy.pdfgui.gui.adddatapanel.adddatapanel method)": [[3, "diffpy.pdfgui.gui.adddatapanel.AddDataPanel.onOpen", false]], "onopen() (diffpy.pdfgui.gui.addphasepanel.addphasepanel method)": [[3, "diffpy.pdfgui.gui.addphasepanel.AddPhasePanel.onOpen", false]], "onopen() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onOpen", false]], "onoxtextenter() (diffpy.pdfgui.gui.sgconstraindialog.sgconstraindialog method)": [[3, "diffpy.pdfgui.gui.sgconstraindialog.SGConstrainDialog.onOXTextEnter", false]], "onoxtextenter() (diffpy.pdfgui.gui.sgstructuredialog.sgstructuredialog method)": [[3, "diffpy.pdfgui.gui.sgstructuredialog.SGStructureDialog.onOXTextEnter", false]], "onoytextenter() (diffpy.pdfgui.gui.sgconstraindialog.sgconstraindialog method)": [[3, "diffpy.pdfgui.gui.sgconstraindialog.SGConstrainDialog.onOYTextEnter", false]], "onoytextenter() (diffpy.pdfgui.gui.sgstructuredialog.sgstructuredialog method)": [[3, "diffpy.pdfgui.gui.sgstructuredialog.SGStructureDialog.onOYTextEnter", false]], "onoztextenter() (diffpy.pdfgui.gui.sgconstraindialog.sgconstraindialog method)": [[3, "diffpy.pdfgui.gui.sgconstraindialog.SGConstrainDialog.onOZTextEnter", false]], "onoztextenter() (diffpy.pdfgui.gui.sgstructuredialog.sgstructuredialog method)": [[3, "diffpy.pdfgui.gui.sgstructuredialog.SGStructureDialog.onOZTextEnter", false]], "onpagechanged() (diffpy.pdfgui.gui.fitnotebookpanel.fitnotebookpanel method)": [[3, "diffpy.pdfgui.gui.fitnotebookpanel.FitNotebookPanel.onPageChanged", false]], "onpagechanging() (diffpy.pdfgui.gui.fitnotebookpanel.fitnotebookpanel method)": [[3, "diffpy.pdfgui.gui.fitnotebookpanel.FitNotebookPanel.onPageChanging", false]], "onpaint() (diffpy.pdfgui.gui.extendedplotframe.extendedplotframe method)": [[3, "diffpy.pdfgui.gui.extendedplotframe.ExtendedPlotFrame.OnPaint", false]], "onpaste() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onPaste", false]], "onpastelink() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onPasteLink", false]], "onplot() (diffpy.pdfgui.gui.plotpanel.plotpanel method)": [[3, "diffpy.pdfgui.gui.plotpanel.PlotPanel.onPlot", false]], "onplotfstruct() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onPlotFStruct", false]], "onplotistruct() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onPlotIStruct", false]], "onpopupcopy() (diffpy.pdfgui.gui.phaseconfigurepanel.phaseconfigurepanel method)": [[3, "diffpy.pdfgui.gui.phaseconfigurepanel.PhaseConfigurePanel.onPopupCopy", false]], "onpopupcopy() (diffpy.pdfgui.gui.phaseconstraintspanel.phaseconstraintspanel method)": [[3, "diffpy.pdfgui.gui.phaseconstraintspanel.PhaseConstraintsPanel.onPopupCopy", false]], "onpopupcopyrefinedtoinitial() (diffpy.pdfgui.gui.parameterspanel.parameterspanel method)": [[3, "diffpy.pdfgui.gui.parameterspanel.ParametersPanel.onPopupCopyRefinedToInitial", false]], "onpopupdelete() (diffpy.pdfgui.gui.phaseconfigurepanel.phaseconfigurepanel method)": [[3, "diffpy.pdfgui.gui.phaseconfigurepanel.PhaseConfigurePanel.onPopupDelete", false]], "onpopupfill() (diffpy.pdfgui.gui.parameterspanel.parameterspanel method)": [[3, "diffpy.pdfgui.gui.parameterspanel.ParametersPanel.onPopupFill", false]], "onpopupfixfree() (diffpy.pdfgui.gui.parameterspanel.parameterspanel method)": [[3, "diffpy.pdfgui.gui.parameterspanel.ParametersPanel.onPopupFixFree", false]], "onpopupinsert() (diffpy.pdfgui.gui.phaseconfigurepanel.phaseconfigurepanel method)": [[3, "diffpy.pdfgui.gui.phaseconfigurepanel.PhaseConfigurePanel.onPopupInsert", false]], "onpopuppaste() (diffpy.pdfgui.gui.phaseconfigurepanel.phaseconfigurepanel method)": [[3, "diffpy.pdfgui.gui.phaseconfigurepanel.PhaseConfigurePanel.onPopupPaste", false]], "onpopuppaste() (diffpy.pdfgui.gui.phaseconstraintspanel.phaseconstraintspanel method)": [[3, "diffpy.pdfgui.gui.phaseconstraintspanel.PhaseConstraintsPanel.onPopupPaste", false]], "onpopuprenameparameters() (diffpy.pdfgui.gui.parameterspanel.parameterspanel method)": [[3, "diffpy.pdfgui.gui.parameterspanel.ParametersPanel.onPopupRenameParameters", false]], "onpopupselect() (diffpy.pdfgui.gui.phaseconfigurepanel.phaseconfigurepanel method)": [[3, "diffpy.pdfgui.gui.phaseconfigurepanel.PhaseConfigurePanel.onPopupSelect", false]], "onpopupselect() (diffpy.pdfgui.gui.phaseconstraintspanel.phaseconstraintspanel method)": [[3, "diffpy.pdfgui.gui.phaseconstraintspanel.PhaseConstraintsPanel.onPopupSelect", false]], "onpopupspacegroup() (diffpy.pdfgui.gui.phaseconfigurepanel.phaseconfigurepanel method)": [[3, "diffpy.pdfgui.gui.phaseconfigurepanel.PhaseConfigurePanel.onPopupSpaceGroup", false]], "onpopupspacegroup() (diffpy.pdfgui.gui.phaseconstraintspanel.phaseconstraintspanel method)": [[3, "diffpy.pdfgui.gui.phaseconstraintspanel.PhaseConstraintsPanel.onPopupSpaceGroup", false]], "onpopupsupercell() (diffpy.pdfgui.gui.phaseconfigurepanel.phaseconfigurepanel method)": [[3, "diffpy.pdfgui.gui.phaseconfigurepanel.PhaseConfigurePanel.onPopupSupercell", false]], "onposflag() (diffpy.pdfgui.gui.sgconstraindialog.sgconstraindialog method)": [[3, "diffpy.pdfgui.gui.sgconstraindialog.SGConstrainDialog.onPosFlag", false]], "onpreferences() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onPreferences", false]], "onprintba() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onPrintBA", false]], "onprintbl() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onPrintBL", false]], "onquickplot() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onQuickPlot", false]], "onquit() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onQuit", false]], "onrequest() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onRequest", false]], "onreset() (diffpy.pdfgui.gui.plotpanel.plotpanel method)": [[3, "diffpy.pdfgui.gui.plotpanel.PlotPanel.onReset", false]], "onrightclick() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onRightClick", false]], "onrseries() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onRSeries", false]], "onrun() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onRun", false]], "onsampling() (diffpy.pdfgui.gui.datasetconfigurepanel.datasetconfigurepanel method)": [[3, "diffpy.pdfgui.gui.datasetconfigurepanel.DataSetConfigurePanel.onSampling", false]], "onsave() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onSave", false]], "onsaveas() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onSaveAs", false]], "onsavecalc() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onSaveCalc", false]], "onselectedpairs() (diffpy.pdfgui.gui.phaseconfigurepanel.phaseconfigurepanel method)": [[3, "diffpy.pdfgui.gui.phaseconfigurepanel.PhaseConfigurePanel.onSelectedPairs", false]], "onsetfocus() (diffpy.pdfgui.gui.calculationpanel.calculationpanel method)": [[3, "diffpy.pdfgui.gui.calculationpanel.CalculationPanel.onSetFocus", false]], "onsetfocus() (diffpy.pdfgui.gui.datasetconfigurepanel.datasetconfigurepanel method)": [[3, "diffpy.pdfgui.gui.datasetconfigurepanel.DataSetConfigurePanel.onSetFocus", false]], "onsetfocus() (diffpy.pdfgui.gui.datasetconstraintpanel.datasetconstraintpanel method)": [[3, "diffpy.pdfgui.gui.datasetconstraintpanel.DataSetConstraintPanel.onSetFocus", false]], "onsetfocus() (diffpy.pdfgui.gui.phaseconfigurepanel.phaseconfigurepanel method)": [[3, "diffpy.pdfgui.gui.phaseconfigurepanel.PhaseConfigurePanel.onSetFocus", false]], "onsetfocus() (diffpy.pdfgui.gui.phaseconstraintspanel.phaseconstraintspanel method)": [[3, "diffpy.pdfgui.gui.phaseconstraintspanel.PhaseConstraintsPanel.onSetFocus", false]], "onsgselect() (diffpy.pdfgui.gui.sgconstraindialog.sgconstraindialog method)": [[3, "diffpy.pdfgui.gui.sgconstraindialog.SGConstrainDialog.onSGSelect", false]], "onsgselect() (diffpy.pdfgui.gui.sgstructuredialog.sgstructuredialog method)": [[3, "diffpy.pdfgui.gui.sgstructuredialog.SGStructureDialog.onSGSelect", false]], "onsgtextenter() (diffpy.pdfgui.gui.sgconstraindialog.sgconstraindialog method)": [[3, "diffpy.pdfgui.gui.sgconstraindialog.SGConstrainDialog.onSGTextEnter", false]], "onsgtextenter() (diffpy.pdfgui.gui.sgstructuredialog.sgstructuredialog method)": [[3, "diffpy.pdfgui.gui.sgstructuredialog.SGStructureDialog.onSGTextEnter", false]], "onshowfit() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onShowFit", false]], "onshowjournal() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onShowJournal", false]], "onshowoutput() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onShowOutput", false]], "onshowplot() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onShowPlot", false]], "onspin() (diffpy.pdfgui.gui.bondangledialog.bondangledialog method)": [[3, "diffpy.pdfgui.gui.bondangledialog.BondAngleDialog.onSpin", false]], "onspin() (diffpy.pdfgui.gui.bondlengthdialog.bondlengthdialog method)": [[3, "diffpy.pdfgui.gui.bondlengthdialog.BondLengthDialog.onSpin", false]], "onstop() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onStop", false]], "onstype() (diffpy.pdfgui.gui.calculationpanel.calculationpanel method)": [[3, "diffpy.pdfgui.gui.calculationpanel.CalculationPanel.onStype", false]], "onstype() (diffpy.pdfgui.gui.datasetconfigurepanel.datasetconfigurepanel method)": [[3, "diffpy.pdfgui.gui.datasetconfigurepanel.DataSetConfigurePanel.onStype", false]], "ontempflag() (diffpy.pdfgui.gui.sgconstraindialog.sgconstraindialog method)": [[3, "diffpy.pdfgui.gui.sgconstraindialog.SGConstrainDialog.onTempFlag", false]], "ontext() (diffpy.pdfgui.gui.journalpanel.journalpanel method)": [[3, "diffpy.pdfgui.gui.journalpanel.JournalPanel.onText", false]], "ontextctrlkey() (diffpy.pdfgui.gui.calculationpanel.calculationpanel method)": [[3, "diffpy.pdfgui.gui.calculationpanel.CalculationPanel.onTextCtrlKey", false]], "ontextctrlkey() (diffpy.pdfgui.gui.datasetconfigurepanel.datasetconfigurepanel method)": [[3, "diffpy.pdfgui.gui.datasetconfigurepanel.DataSetConfigurePanel.onTextCtrlKey", false]], "ontextctrlkey() (diffpy.pdfgui.gui.datasetconstraintpanel.datasetconstraintpanel method)": [[3, "diffpy.pdfgui.gui.datasetconstraintpanel.DataSetConstraintPanel.onTextCtrlKey", false]], "ontextctrlkey() (diffpy.pdfgui.gui.phaseconfigurepanel.phaseconfigurepanel method)": [[3, "diffpy.pdfgui.gui.phaseconfigurepanel.PhaseConfigurePanel.onTextCtrlKey", false]], "ontextctrlkey() (diffpy.pdfgui.gui.phaseconstraintspanel.phaseconstraintspanel method)": [[3, "diffpy.pdfgui.gui.phaseconstraintspanel.PhaseConstraintsPanel.onTextCtrlKey", false]], "ontextkillfocus() (diffpy.pdfgui.gui.bondlengthdialog.bondlengthdialog method)": [[3, "diffpy.pdfgui.gui.bondlengthdialog.BondLengthDialog.onTextKillFocus", false]], "ontreeselchanged() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onTreeSelChanged", false]], "ontreeselchanging() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onTreeSelChanging", false]], "ontseries() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.onTSeries", false]], "onup() (diffpy.pdfgui.gui.dopingseriespanel.dopingseriespanel method)": [[3, "diffpy.pdfgui.gui.dopingseriespanel.DopingSeriesPanel.onUp", false]], "onup() (diffpy.pdfgui.gui.temperatureseriespanel.temperatureseriespanel method)": [[3, "diffpy.pdfgui.gui.temperatureseriespanel.TemperatureSeriesPanel.onUp", false]], "onurl() (diffpy.pdfgui.gui.errorreportdialog.errorreportdialog method)": [[3, "diffpy.pdfgui.gui.errorreportdialog.ErrorReportDialog.onURL", false]], "onwindowclose() (diffpy.pdfgui.control.plotter.plotter method)": [[2, "diffpy.pdfgui.control.plotter.Plotter.onWindowClose", false]], "organization() (diffpy.pdfgui.control.organizer.organizer method)": [[2, "diffpy.pdfgui.control.organizer.Organizer.organization", false]], "organizer (class in diffpy.pdfgui.control.organizer)": [[2, "diffpy.pdfgui.control.organizer.Organizer", false]], "outputbondangle() (diffpy.pdfgui.control.fitting.fitting method)": [[2, "diffpy.pdfgui.control.fitting.Fitting.outputBondAngle", false]], "outputbondlengthatoms() (diffpy.pdfgui.control.fitting.fitting method)": [[2, "diffpy.pdfgui.control.fitting.Fitting.outputBondLengthAtoms", false]], "outputbondlengthtypes() (diffpy.pdfgui.control.fitting.fitting method)": [[2, "diffpy.pdfgui.control.fitting.Fitting.outputBondLengthTypes", false]], "outputpanel (class in diffpy.pdfgui.gui.outputpanel)": [[3, "diffpy.pdfgui.gui.outputpanel.OutputPanel", false]], "paneldialog (class in diffpy.pdfgui.gui.wxextensions.paneldialog)": [[5, "diffpy.pdfgui.gui.wxextensions.paneldialog.PanelDialog", false]], "parameter (class in diffpy.pdfgui.control.parameter)": [[2, "diffpy.pdfgui.control.parameter.Parameter", false]], "parameterspanel (class in diffpy.pdfgui.gui.parameterspanel)": [[3, "diffpy.pdfgui.gui.parameterspanel.ParametersPanel", false]], "paste() (diffpy.pdfgui.control.pdfguicontrol.pdfguicontrol method)": [[2, "diffpy.pdfgui.control.pdfguicontrol.PDFGuiControl.paste", false]], "pastebranch() (diffpy.pdfgui.gui.fittree.fittree method)": [[3, "diffpy.pdfgui.gui.fittree.FitTree.PasteBranch", false]], "pasteintocells() (in module diffpy.pdfgui.gui.phasepanelutils)": [[3, "diffpy.pdfgui.gui.phasepanelutils.pasteIntoCells", false]], "pause() (diffpy.pdfgui.control.fitting.fitting method)": [[2, "diffpy.pdfgui.control.fitting.Fitting.pause", false]], "paused (diffpy.pdfgui.control.fitting.fitting attribute)": [[2, "diffpy.pdfgui.control.fitting.Fitting.PAUSED", false]], "pdfcomponent (class in diffpy.pdfgui.control.pdfcomponent)": [[2, "diffpy.pdfgui.control.pdfcomponent.PDFComponent", false]], "pdfdataformaterror": [[2, "diffpy.pdfgui.control.pdfdataset.PDFDataFormatError", false]], "pdfdataset (class in diffpy.pdfgui.control.pdfdataset)": [[2, "diffpy.pdfgui.control.pdfdataset.PDFDataSet", false]], "pdfguiapp (class in diffpy.pdfgui.gui.main)": [[3, "diffpy.pdfgui.gui.main.PDFGuiApp", false]], "pdfguicontrol (class in diffpy.pdfgui.control.pdfguicontrol)": [[2, "diffpy.pdfgui.control.pdfguicontrol.PDFGuiControl", false]], "pdfguicontrol() (in module diffpy.pdfgui.control.pdfguicontrol)": [[2, "diffpy.pdfgui.control.pdfguicontrol.pdfguicontrol", false]], "pdfguicontrol.queuemanager (class in diffpy.pdfgui.control.pdfguicontrol)": [[2, "diffpy.pdfgui.control.pdfguicontrol.PDFGuiControl.QueueManager", false]], "pdflist (class in diffpy.pdfgui.control.pdflist)": [[2, "diffpy.pdfgui.control.pdflist.PDFList", false]], "pdfpanel (class in diffpy.pdfgui.gui.pdfpanel)": [[3, "diffpy.pdfgui.gui.pdfpanel.PDFPanel", false]], "pdfstructure (class in diffpy.pdfgui.control.pdfstructure)": [[2, "diffpy.pdfgui.control.pdfstructure.PDFStructure", false]], "persistentitems (diffpy.pdfgui.control.fitdataset.fitdataset attribute)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.persistentItems", false]], "persistentitems (diffpy.pdfgui.control.pdfdataset.pdfdataset attribute)": [[2, "diffpy.pdfgui.control.pdfdataset.PDFDataSet.persistentItems", false]], "phaseconfigurepanel (class in diffpy.pdfgui.gui.phaseconfigurepanel)": [[3, "diffpy.pdfgui.gui.phaseconfigurepanel.PhaseConfigurePanel", false]], "phaseconstraintspanel (class in diffpy.pdfgui.gui.phaseconstraintspanel)": [[3, "diffpy.pdfgui.gui.phaseconstraintspanel.PhaseConstraintsPanel", false]], "phasenotebookpanel (class in diffpy.pdfgui.gui.phasenotebookpanel)": [[3, "diffpy.pdfgui.gui.phasenotebookpanel.PhaseNotebookPanel", false]], "phaseresultspanel (class in diffpy.pdfgui.gui.phaseresultspanel)": [[3, "diffpy.pdfgui.gui.phaseresultspanel.PhaseResultsPanel", false]], "plot() (diffpy.pdfgui.control.pdfguicontrol.pdfguicontrol method)": [[2, "diffpy.pdfgui.control.pdfguicontrol.PDFGuiControl.plot", false]], "plot() (diffpy.pdfgui.control.plotter.plotter method)": [[2, "diffpy.pdfgui.control.plotter.Plotter.plot", false]], "plot() (diffpy.pdfgui.control.structureviewer.structureviewer method)": [[2, "diffpy.pdfgui.control.structureviewer.StructureViewer.plot", false]], "plotpanel (class in diffpy.pdfgui.gui.plotpanel)": [[3, "diffpy.pdfgui.gui.plotpanel.PlotPanel", false]], "plotter (class in diffpy.pdfgui.control.plotter)": [[2, "diffpy.pdfgui.control.plotter.Plotter", false]], "plotter.curve (class in diffpy.pdfgui.control.plotter)": [[2, "diffpy.pdfgui.control.plotter.Plotter.Curve", false]], "popupmenu() (diffpy.pdfgui.gui.parameterspanel.parameterspanel method)": [[3, "diffpy.pdfgui.gui.parameterspanel.ParametersPanel.popupMenu", false]], "popupmenu() (diffpy.pdfgui.gui.phaseconfigurepanel.phaseconfigurepanel method)": [[3, "diffpy.pdfgui.gui.phaseconfigurepanel.PhaseConfigurePanel.popupMenu", false]], "popupmenu() (diffpy.pdfgui.gui.phaseconstraintspanel.phaseconstraintspanel method)": [[3, "diffpy.pdfgui.gui.phaseconstraintspanel.PhaseConstraintsPanel.popupMenu", false]], "postevent() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.postEvent", false]], "preferencespanel (class in diffpy.pdfgui.gui.preferencespanel)": [[3, "diffpy.pdfgui.gui.preferencespanel.PreferencesPanel", false]], "processarguments() (in module diffpy.pdfgui.applications.pdfgui)": [[1, "diffpy.pdfgui.applications.pdfgui.processArguments", false]], "processformula() (diffpy.pdfgui.gui.datasetconstraintpanel.datasetconstraintpanel method)": [[3, "diffpy.pdfgui.gui.datasetconstraintpanel.DataSetConstraintPanel.processFormula", false]], "queue() (diffpy.pdfgui.control.fitting.fitting method)": [[2, "diffpy.pdfgui.control.fitting.Fitting.queue", false]], "queued (diffpy.pdfgui.control.fitting.fitting attribute)": [[2, "diffpy.pdfgui.control.fitting.Fitting.QUEUED", false]], "rcalc (diffpy.pdfgui.control.fitdataset.fitdataset property)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.rcalc", false]], "read() (diffpy.pdfgui.control.fitdataset.fitdataset method)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.read", false]], "read() (diffpy.pdfgui.control.fitstructure.fitstructure method)": [[2, "diffpy.pdfgui.control.fitstructure.FitStructure.read", false]], "read() (diffpy.pdfgui.control.pdfdataset.pdfdataset method)": [[2, "diffpy.pdfgui.control.pdfdataset.PDFDataSet.read", false]], "read() (diffpy.pdfgui.control.pdfstructure.pdfstructure method)": [[2, "diffpy.pdfgui.control.pdfstructure.PDFStructure.read", false]], "readconfiguration() (diffpy.pdfgui.gui.adddatapanel.adddatapanel method)": [[3, "diffpy.pdfgui.gui.adddatapanel.AddDataPanel.readConfiguration", false]], "readconfiguration() (diffpy.pdfgui.gui.addphasepanel.addphasepanel method)": [[3, "diffpy.pdfgui.gui.addphasepanel.AddPhasePanel.readConfiguration", false]], "readobs() (diffpy.pdfgui.control.fitdataset.fitdataset method)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.readObs", false]], "readobsstr() (diffpy.pdfgui.control.fitdataset.fitdataset method)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.readObsStr", false]], "readstr() (diffpy.pdfgui.control.fitdataset.fitdataset method)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.readStr", false]], "readstr() (diffpy.pdfgui.control.fitstructure.fitstructure method)": [[2, "diffpy.pdfgui.control.fitstructure.FitStructure.readStr", false]], "readstr() (diffpy.pdfgui.control.pdfdataset.pdfdataset method)": [[2, "diffpy.pdfgui.control.pdfdataset.PDFDataSet.readStr", false]], "redirectstdout() (diffpy.pdfgui.control.pdfguicontrol.pdfguicontrol method)": [[2, "diffpy.pdfgui.control.pdfguicontrol.PDFGuiControl.redirectStdout", false]], "refinablevars (diffpy.pdfgui.control.pdfdataset.pdfdataset attribute)": [[2, "diffpy.pdfgui.control.pdfdataset.PDFDataSet.refinableVars", false]], "refine_step() (diffpy.pdfgui.control.fitting.fitting method)": [[2, "diffpy.pdfgui.control.fitting.Fitting.refine_step", false]], "refresh() (diffpy.pdfgui.gui.adddatapanel.adddatapanel method)": [[3, "diffpy.pdfgui.gui.adddatapanel.AddDataPanel.refresh", false]], "refresh() (diffpy.pdfgui.gui.addphasepanel.addphasepanel method)": [[3, "diffpy.pdfgui.gui.addphasepanel.AddPhasePanel.refresh", false]], "refresh() (diffpy.pdfgui.gui.blankpanel.blankpanel method)": [[3, "diffpy.pdfgui.gui.blankpanel.BlankPanel.refresh", false]], "refresh() (diffpy.pdfgui.gui.calculationpanel.calculationpanel method)": [[3, "diffpy.pdfgui.gui.calculationpanel.CalculationPanel.refresh", false]], "refresh() (diffpy.pdfgui.gui.datasetconfigurepanel.datasetconfigurepanel method)": [[3, "diffpy.pdfgui.gui.datasetconfigurepanel.DataSetConfigurePanel.refresh", false]], "refresh() (diffpy.pdfgui.gui.datasetconstraintpanel.datasetconstraintpanel method)": [[3, "diffpy.pdfgui.gui.datasetconstraintpanel.DataSetConstraintPanel.refresh", false]], "refresh() (diffpy.pdfgui.gui.datasetpanel.datasetpanel method)": [[3, "diffpy.pdfgui.gui.datasetpanel.DataSetPanel.refresh", false]], "refresh() (diffpy.pdfgui.gui.datasetresultspanel.datasetresultspanel method)": [[3, "diffpy.pdfgui.gui.datasetresultspanel.DataSetResultsPanel.refresh", false]], "refresh() (diffpy.pdfgui.gui.dopingseriespanel.dopingseriespanel method)": [[3, "diffpy.pdfgui.gui.dopingseriespanel.DopingSeriesPanel.refresh", false]], "refresh() (diffpy.pdfgui.gui.fitnotebookpanel.fitnotebookpanel method)": [[3, "diffpy.pdfgui.gui.fitnotebookpanel.FitNotebookPanel.refresh", false]], "refresh() (diffpy.pdfgui.gui.journalpanel.journalpanel method)": [[3, "diffpy.pdfgui.gui.journalpanel.JournalPanel.refresh", false]], "refresh() (diffpy.pdfgui.gui.outputpanel.outputpanel method)": [[3, "diffpy.pdfgui.gui.outputpanel.OutputPanel.refresh", false]], "refresh() (diffpy.pdfgui.gui.parameterspanel.parameterspanel method)": [[3, "diffpy.pdfgui.gui.parameterspanel.ParametersPanel.refresh", false]], "refresh() (diffpy.pdfgui.gui.pdfpanel.pdfpanel method)": [[3, "diffpy.pdfgui.gui.pdfpanel.PDFPanel.refresh", false]], "refresh() (diffpy.pdfgui.gui.phaseconfigurepanel.phaseconfigurepanel method)": [[3, "diffpy.pdfgui.gui.phaseconfigurepanel.PhaseConfigurePanel.refresh", false]], "refresh() (diffpy.pdfgui.gui.phaseconstraintspanel.phaseconstraintspanel method)": [[3, "diffpy.pdfgui.gui.phaseconstraintspanel.PhaseConstraintsPanel.refresh", false]], "refresh() (diffpy.pdfgui.gui.phasenotebookpanel.phasenotebookpanel method)": [[3, "diffpy.pdfgui.gui.phasenotebookpanel.PhaseNotebookPanel.refresh", false]], "refresh() (diffpy.pdfgui.gui.phaseresultspanel.phaseresultspanel method)": [[3, "diffpy.pdfgui.gui.phaseresultspanel.PhaseResultsPanel.refresh", false]], "refresh() (diffpy.pdfgui.gui.plotpanel.plotpanel method)": [[3, "diffpy.pdfgui.gui.plotpanel.PlotPanel.refresh", false]], "refresh() (diffpy.pdfgui.gui.preferencespanel.preferencespanel method)": [[3, "diffpy.pdfgui.gui.preferencespanel.PreferencesPanel.refresh", false]], "refresh() (diffpy.pdfgui.gui.resultspanel.resultspanel method)": [[3, "diffpy.pdfgui.gui.resultspanel.ResultsPanel.refresh", false]], "refresh() (diffpy.pdfgui.gui.rseriespanel.rseriespanel method)": [[3, "diffpy.pdfgui.gui.rseriespanel.RSeriesPanel.refresh", false]], "refresh() (diffpy.pdfgui.gui.temperatureseriespanel.temperatureseriespanel method)": [[3, "diffpy.pdfgui.gui.temperatureseriespanel.TemperatureSeriesPanel.refresh", false]], "refresh() (diffpy.pdfgui.gui.welcomepanel.welcomepanel method)": [[3, "diffpy.pdfgui.gui.welcomepanel.WelcomePanel.refresh", false]], "refreshgrid() (in module diffpy.pdfgui.gui.phasepanelutils)": [[3, "diffpy.pdfgui.gui.phasepanelutils.refreshGrid", false]], "refreshselectedpage() (diffpy.pdfgui.gui.datasetpanel.datasetpanel method)": [[3, "diffpy.pdfgui.gui.datasetpanel.DataSetPanel.refreshSelectedPage", false]], "refreshtextctrls() (diffpy.pdfgui.gui.phaseconstraintspanel.phaseconstraintspanel method)": [[3, "diffpy.pdfgui.gui.phaseconstraintspanel.PhaseConstraintsPanel.refreshTextCtrls", false]], "refreshtextctrls() (in module diffpy.pdfgui.gui.phasepanelutils)": [[3, "diffpy.pdfgui.gui.phasepanelutils.refreshTextCtrls", false]], "release notes": [[10, "index-0", false]], "remove() (diffpy.pdfgui.control.organizer.organizer method)": [[2, "diffpy.pdfgui.control.organizer.Organizer.remove", false]], "remove() (diffpy.pdfgui.control.pdfguicontrol.pdfguicontrol method)": [[2, "diffpy.pdfgui.control.pdfguicontrol.PDFGuiControl.remove", false]], "removecurve() (diffpy.pdfgui.gui.extendedplotframe.extendedplotframe method)": [[3, "diffpy.pdfgui.gui.extendedplotframe.ExtendedPlotFrame.removeCurve", false]], "rename() (diffpy.pdfgui.control.organizer.organizer method)": [[2, "diffpy.pdfgui.control.organizer.Organizer.rename", false]], "rename() (diffpy.pdfgui.control.pdfguicontrol.pdfguicontrol method)": [[2, "diffpy.pdfgui.control.pdfguicontrol.PDFGuiControl.rename", false]], "rename() (diffpy.pdfgui.control.pdflist.pdflist method)": [[2, "diffpy.pdfgui.control.pdflist.PDFList.rename", false]], "replot() (diffpy.pdfgui.gui.extendedplotframe.extendedplotframe method)": [[3, "diffpy.pdfgui.gui.extendedplotframe.ExtendedPlotFrame.replot", false]], "reset() (diffpy.pdfgui.control.pdfguicontrol.pdfguicontrol method)": [[2, "diffpy.pdfgui.control.pdfguicontrol.PDFGuiControl.reset", false]], "resetstatus() (diffpy.pdfgui.control.fitting.fitting method)": [[2, "diffpy.pdfgui.control.fitting.Fitting.resetStatus", false]], "restrictconstrainedparameters() (diffpy.pdfgui.gui.datasetconfigurepanel.datasetconfigurepanel method)": [[3, "diffpy.pdfgui.gui.datasetconfigurepanel.DataSetConfigurePanel.restrictConstrainedParameters", false]], "restrictconstrainedparameters() (diffpy.pdfgui.gui.phaseconfigurepanel.phaseconfigurepanel method)": [[3, "diffpy.pdfgui.gui.phaseconfigurepanel.PhaseConfigurePanel.restrictConstrainedParameters", false]], "resultspanel (class in diffpy.pdfgui.gui.resultspanel)": [[3, "diffpy.pdfgui.gui.resultspanel.ResultsPanel", false]], "rseriespanel (class in diffpy.pdfgui.gui.rseriespanel)": [[3, "diffpy.pdfgui.gui.rseriespanel.RSeriesPanel", false]], "run() (diffpy.pdfgui.control.fitting.fitting method)": [[2, "diffpy.pdfgui.control.fitting.Fitting.run", false]], "run() (diffpy.pdfgui.control.fitting.fitting.worker method)": [[2, "diffpy.pdfgui.control.fitting.Fitting.Worker.run", false]], "run() (diffpy.pdfgui.control.pdfguicontrol.pdfguicontrol.queuemanager method)": [[2, "diffpy.pdfgui.control.pdfguicontrol.PDFGuiControl.QueueManager.run", false]], "running (diffpy.pdfgui.control.fitting.fitting attribute)": [[2, "diffpy.pdfgui.control.fitting.Fitting.RUNNING", false]], "safecpickledumps() (in module diffpy.pdfgui.utils)": [[0, "diffpy.pdfgui.utils.safeCPickleDumps", false]], "save() (diffpy.pdfgui.control.calculation.calculation method)": [[2, "diffpy.pdfgui.control.calculation.Calculation.save", false]], "save() (diffpy.pdfgui.control.fitdataset.fitdataset method)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.save", false]], "save() (diffpy.pdfgui.control.fitstructure.fitstructure method)": [[2, "diffpy.pdfgui.control.fitstructure.FitStructure.save", false]], "save() (diffpy.pdfgui.control.fitting.fitting method)": [[2, "diffpy.pdfgui.control.fitting.Fitting.save", false]], "save() (diffpy.pdfgui.control.organizer.organizer method)": [[2, "diffpy.pdfgui.control.organizer.Organizer.save", false]], "save() (diffpy.pdfgui.control.pdfguicontrol.pdfguicontrol method)": [[2, "diffpy.pdfgui.control.pdfguicontrol.PDFGuiControl.save", false]], "save() (diffpy.pdfgui.tui.loadproject method)": [[0, "diffpy.pdfgui.tui.LoadProject.save", false]], "saveplotdata() (diffpy.pdfgui.gui.extendedplotframe.extendedplotframe method)": [[3, "diffpy.pdfgui.gui.extendedplotframe.ExtendedPlotFrame.savePlotData", false]], "selectall() (diffpy.pdfgui.gui.fittree.fittree method)": [[3, "diffpy.pdfgui.gui.fittree.FitTree.SelectAll", false]], "selectalltype() (diffpy.pdfgui.gui.fittree.fittree method)": [[3, "diffpy.pdfgui.gui.fittree.FitTree.SelectAllType", false]], "setconfig() (diffpy.pdfgui.control.structureviewer.structureviewer method)": [[2, "diffpy.pdfgui.control.structureviewer.StructureViewer.setConfig", false]], "setconfigurationdata() (diffpy.pdfgui.gui.calculationpanel.calculationpanel method)": [[3, "diffpy.pdfgui.gui.calculationpanel.CalculationPanel.setConfigurationData", false]], "setconfigurationdata() (diffpy.pdfgui.gui.datasetconfigurepanel.datasetconfigurepanel method)": [[3, "diffpy.pdfgui.gui.datasetconfigurepanel.DataSetConfigurePanel.setConfigurationData", false]], "setconstraintsdata() (diffpy.pdfgui.gui.datasetconstraintpanel.datasetconstraintpanel method)": [[3, "diffpy.pdfgui.gui.datasetconstraintpanel.DataSetConstraintPanel.setConstraintsData", false]], "setcontroldata() (diffpy.pdfgui.gui.fittree.fittree method)": [[3, "diffpy.pdfgui.gui.fittree.FitTree.SetControlData", false]], "setfitsamplingtype() (diffpy.pdfgui.control.fitdataset.fitdataset method)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.setFitSamplingType", false]], "setinitial() (diffpy.pdfgui.control.parameter.parameter method)": [[2, "diffpy.pdfgui.control.parameter.Parameter.setInitial", false]], "setmode() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.setMode", false]], "setnodetype() (diffpy.pdfgui.gui.fittree.fittree method)": [[3, "diffpy.pdfgui.gui.fittree.FitTree.SetNodeType", false]], "setpanel() (diffpy.pdfgui.gui.wxextensions.paneldialog.paneldialog method)": [[5, "diffpy.pdfgui.gui.wxextensions.paneldialog.PanelDialog.setPanel", false]], "setpanelspecificdata() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.setPanelSpecificData", false]], "setresultsdata() (diffpy.pdfgui.gui.datasetresultspanel.datasetresultspanel method)": [[3, "diffpy.pdfgui.gui.datasetresultspanel.DataSetResultsPanel.setResultsData", false]], "setrgrid() (diffpy.pdfgui.control.calculation.calculation method)": [[2, "diffpy.pdfgui.control.calculation.Calculation.setRGrid", false]], "setselectedpairs() (diffpy.pdfgui.control.fitstructure.fitstructure method)": [[2, "diffpy.pdfgui.control.fitstructure.FitStructure.setSelectedPairs", false]], "setselection() (diffpy.pdfgui.gui.wxextensions.listctrls.autowidthlistctrl method)": [[5, "diffpy.pdfgui.gui.wxextensions.listctrls.AutoWidthListCtrl.setSelection", false]], "setstructure() (diffpy.pdfgui.gui.bondangledialog.bondangledialog method)": [[3, "diffpy.pdfgui.gui.bondangledialog.BondAngleDialog.setStructure", false]], "setstructure() (diffpy.pdfgui.gui.bondlengthdialog.bondlengthdialog method)": [[3, "diffpy.pdfgui.gui.bondlengthdialog.BondLengthDialog.setStructure", false]], "setstructure() (diffpy.pdfgui.gui.sgconstraindialog.sgconstraindialog method)": [[3, "diffpy.pdfgui.gui.sgconstraindialog.SGConstrainDialog.setStructure", false]], "setstructure() (diffpy.pdfgui.gui.sgstructuredialog.sgstructuredialog method)": [[3, "diffpy.pdfgui.gui.sgstructuredialog.SGStructureDialog.setStructure", false]], "settitle() (diffpy.pdfgui.gui.extendedplotframe.extendedplotframe method)": [[3, "diffpy.pdfgui.gui.extendedplotframe.ExtendedPlotFrame.setTitle", false]], "settooltips() (diffpy.pdfgui.gui.pdfpanel.pdfpanel method)": [[3, "diffpy.pdfgui.gui.pdfpanel.PDFPanel.setToolTips", false]], "setvar() (diffpy.pdfgui.control.pdfdataset.pdfdataset method)": [[2, "diffpy.pdfgui.control.pdfdataset.PDFDataSet.setvar", false]], "setvar() (diffpy.pdfgui.control.pdfstructure.pdfstructure method)": [[2, "diffpy.pdfgui.control.pdfstructure.PDFStructure.setvar", false]], "setxlabel() (diffpy.pdfgui.gui.extendedplotframe.extendedplotframe method)": [[3, "diffpy.pdfgui.gui.extendedplotframe.ExtendedPlotFrame.setXLabel", false]], "setylabel() (diffpy.pdfgui.gui.extendedplotframe.extendedplotframe method)": [[3, "diffpy.pdfgui.gui.extendedplotframe.ExtendedPlotFrame.setYLabel", false]], "sgconstraindialog (class in diffpy.pdfgui.gui.sgconstraindialog)": [[3, "diffpy.pdfgui.gui.sgconstraindialog.SGConstrainDialog", false]], "sgstructuredialog (class in diffpy.pdfgui.gui.sgstructuredialog)": [[3, "diffpy.pdfgui.gui.sgstructuredialog.SGStructureDialog", false]], "short2long (diffpy.pdfgui.gui.debugoptions.debugoptions attribute)": [[3, "diffpy.pdfgui.gui.debugoptions.DebugOptions.short2long", false]], "show() (diffpy.pdfgui.control.plotter.plotter method)": [[2, "diffpy.pdfgui.control.plotter.Plotter.show", false]], "showmessage() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.showMessage", false]], "showmodal() (diffpy.pdfgui.gui.errorreportdialog.errorreportdialog method)": [[3, "diffpy.pdfgui.gui.errorreportdialog.ErrorReportDialog.ShowModal", false]], "showmodal() (diffpy.pdfgui.gui.errorreportdialog_control_fix.errorreportdialogcontrolfix method)": [[3, "diffpy.pdfgui.gui.errorreportdialog_control_fix.ErrorReportDialogControlFix.ShowModal", false]], "showselectatomsdialog() (in module diffpy.pdfgui.gui.phasepanelutils)": [[3, "diffpy.pdfgui.gui.phasepanelutils.showSelectAtomsDialog", false]], "sorted_standard_space_groups (diffpy.pdfgui.control.fitstructure.fitstructure attribute)": [[2, "diffpy.pdfgui.control.fitstructure.FitStructure.sorted_standard_space_groups", false]], "spd_assigned() (in module diffpy.pdfgui.control.organizer)": [[2, "diffpy.pdfgui.control.organizer.spd_assigned", false]], "spd_constrained() (in module diffpy.pdfgui.control.organizer)": [[2, "diffpy.pdfgui.control.organizer.spd_constrained", false]], "start() (diffpy.pdfgui.control.calculation.calculation method)": [[2, "diffpy.pdfgui.control.calculation.Calculation.start", false]], "start() (diffpy.pdfgui.control.fitting.fitting method)": [[2, "diffpy.pdfgui.control.fitting.Fitting.start", false]], "start() (diffpy.pdfgui.control.pdfguicontrol.pdfguicontrol method)": [[2, "diffpy.pdfgui.control.pdfguicontrol.PDFGuiControl.start", false]], "startqueue() (diffpy.pdfgui.control.pdfguicontrol.pdfguicontrol method)": [[2, "diffpy.pdfgui.control.pdfguicontrol.PDFGuiControl.startQueue", false]], "stop() (diffpy.pdfgui.control.fitting.fitting method)": [[2, "diffpy.pdfgui.control.fitting.Fitting.stop", false]], "stop() (diffpy.pdfgui.control.pdfguicontrol.pdfguicontrol method)": [[2, "diffpy.pdfgui.control.pdfguicontrol.PDFGuiControl.stop", false]], "stripped() (diffpy.pdfgui.control.fitting.fitting method)": [[2, "diffpy.pdfgui.control.fitting.Fitting.stripped", false]], "structureviewer (class in diffpy.pdfgui.control.structureviewer)": [[2, "diffpy.pdfgui.control.structureviewer.StructureViewer", false]], "supercelldialog (class in diffpy.pdfgui.gui.supercelldialog)": [[3, "diffpy.pdfgui.gui.supercelldialog.SupercellDialog", false]], "switchrightpanel() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.switchRightPanel", false]], "symposeps (diffpy.pdfgui.control.fitstructure.fitstructure attribute)": [[2, "diffpy.pdfgui.control.fitstructure.FitStructure.symposeps", false]], "tempcontrolselecterror": [[2, "diffpy.pdfgui.control.controlerrors.TempControlSelectError", false]], "temperatureseriespanel (class in diffpy.pdfgui.gui.temperatureseriespanel)": [[3, "diffpy.pdfgui.gui.temperatureseriespanel.TemperatureSeriesPanel", false]], "test() (diffpy.pdfgui.gui.errorreportdialog.myapp method)": [[3, "diffpy.pdfgui.gui.errorreportdialog.MyApp.test", false]], "test() (diffpy.pdfgui.gui.errorreportdialog_control_fix.myapp method)": [[3, "diffpy.pdfgui.gui.errorreportdialog_control_fix.MyApp.test", false]], "textctrlasgridcell() (in module diffpy.pdfgui.gui.wxextensions.textctrlutils)": [[5, "diffpy.pdfgui.gui.wxextensions.textctrlutils.textCtrlAsGridCell", false]], "textvalidator (class in diffpy.pdfgui.gui.wxextensions.validators)": [[5, "diffpy.pdfgui.gui.wxextensions.validators.TextValidator", false]], "toolitems (diffpy.pdfgui.gui.extendedplotframe.extendedtoolbar attribute)": [[3, "diffpy.pdfgui.gui.extendedplotframe.ExtendedToolbar.toolitems", false]], "transferfromwindow() (diffpy.pdfgui.gui.wxextensions.validators.textvalidator method)": [[5, "diffpy.pdfgui.gui.wxextensions.validators.TextValidator.TransferFromWindow", false]], "transfertowindow() (diffpy.pdfgui.gui.wxextensions.validators.textvalidator method)": [[5, "diffpy.pdfgui.gui.wxextensions.validators.TextValidator.TransferToWindow", false]], "treeselectionupdate() (diffpy.pdfgui.gui.dopingseriespanel.dopingseriespanel method)": [[3, "diffpy.pdfgui.gui.dopingseriespanel.DopingSeriesPanel.treeSelectionUpdate", false]], "treeselectionupdate() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.treeSelectionUpdate", false]], "treeselectionupdate() (diffpy.pdfgui.gui.rseriespanel.rseriespanel method)": [[3, "diffpy.pdfgui.gui.rseriespanel.RSeriesPanel.treeSelectionUpdate", false]], "treeselectionupdate() (diffpy.pdfgui.gui.temperatureseriespanel.temperatureseriespanel method)": [[3, "diffpy.pdfgui.gui.temperatureseriespanel.TemperatureSeriesPanel.treeSelectionUpdate", false]], "unlock() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.unlock", false]], "updateconfiguration() (diffpy.pdfgui.gui.adddatapanel.adddatapanel method)": [[3, "diffpy.pdfgui.gui.adddatapanel.AddDataPanel.updateConfiguration", false]], "updateconfiguration() (diffpy.pdfgui.gui.addphasepanel.addphasepanel method)": [[3, "diffpy.pdfgui.gui.addphasepanel.AddPhasePanel.updateConfiguration", false]], "updateconfiguration() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.updateConfiguration", false]], "updatedata() (diffpy.pdfgui.gui.extendedplotframe.extendedplotframe method)": [[3, "diffpy.pdfgui.gui.extendedplotframe.ExtendedPlotFrame.updateData", false]], "updatefittingstatus() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.updateFittingStatus", false]], "updateoutput() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.updateOutput", false]], "updateparameters() (diffpy.pdfgui.control.fitting.fitting method)": [[2, "diffpy.pdfgui.control.fitting.Fitting.updateParameters", false]], "updatespacegrouplist() (diffpy.pdfgui.gui.sgconstraindialog.sgconstraindialog method)": [[3, "diffpy.pdfgui.gui.sgconstraindialog.SGConstrainDialog.updateSpaceGroupList", false]], "updatespacegrouplist() (diffpy.pdfgui.gui.sgstructuredialog.sgstructuredialog method)": [[3, "diffpy.pdfgui.gui.sgstructuredialog.SGStructureDialog.updateSpaceGroupList", false]], "updatestatusbar() (diffpy.pdfgui.gui.extendedplotframe.extendedplotframe method)": [[3, "diffpy.pdfgui.gui.extendedplotframe.ExtendedPlotFrame.UpdateStatusBar", false]], "updatetext() (diffpy.pdfgui.gui.outputpanel.outputpanel method)": [[3, "diffpy.pdfgui.gui.outputpanel.OutputPanel.updateText", false]], "updatetitle() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.updateTitle", false]], "updatetoolbar() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.updateToolbar", false]], "updatewidgets() (diffpy.pdfgui.gui.plotpanel.plotpanel method)": [[3, "diffpy.pdfgui.gui.plotpanel.PlotPanel.updateWidgets", false]], "updatewidgets() (diffpy.pdfgui.gui.sgconstraindialog.sgconstraindialog method)": [[3, "diffpy.pdfgui.gui.sgconstraindialog.SGConstrainDialog.updateWidgets", false]], "updatewidgets() (diffpy.pdfgui.gui.sgstructuredialog.sgstructuredialog method)": [[3, "diffpy.pdfgui.gui.sgstructuredialog.SGStructureDialog.updateWidgets", false]], "usage() (in module diffpy.pdfgui.applications.pdfgui)": [[1, "diffpy.pdfgui.applications.pdfgui.usage", false]], "validate() (diffpy.pdfgui.control.plotter.plotter.curve method)": [[2, "diffpy.pdfgui.control.plotter.Plotter.Curve.validate", false]], "validate() (diffpy.pdfgui.gui.wxextensions.validators.textvalidator method)": [[5, "diffpy.pdfgui.gui.wxextensions.validators.TextValidator.Validate", false]], "validatestructure() (diffpy.pdfgui.gui.addphasepanel.addphasepanel method)": [[3, "diffpy.pdfgui.gui.addphasepanel.AddPhasePanel.validateStructure", false]], "values() (diffpy.pdfgui.control.pdflist.pdflist method)": [[2, "diffpy.pdfgui.control.pdflist.PDFList.values", false]], "version() (in module diffpy.pdfgui.applications.pdfgui)": [[1, "diffpy.pdfgui.applications.pdfgui.version", false]], "void (diffpy.pdfgui.control.fitting.fitting attribute)": [[2, "diffpy.pdfgui.control.fitting.Fitting.VOID", false]], "welcomepanel (class in diffpy.pdfgui.gui.welcomepanel)": [[3, "diffpy.pdfgui.gui.welcomepanel.WelcomePanel", false]], "write() (diffpy.pdfgui.control.calculation.calculation method)": [[2, "diffpy.pdfgui.control.calculation.Calculation.write", false]], "write() (diffpy.pdfgui.control.fitdataset.fitdataset method)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.write", false]], "write() (diffpy.pdfgui.control.pdfdataset.pdfdataset method)": [[2, "diffpy.pdfgui.control.pdfdataset.PDFDataSet.write", false]], "writecalc() (diffpy.pdfgui.control.fitdataset.fitdataset method)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.writeCalc", false]], "writecalcstr() (diffpy.pdfgui.control.fitdataset.fitdataset method)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.writeCalcStr", false]], "writeconfiguration() (diffpy.pdfgui.gui.mainframe.mainframe method)": [[3, "diffpy.pdfgui.gui.mainframe.MainFrame.writeConfiguration", false]], "writeobs() (diffpy.pdfgui.control.fitdataset.fitdataset method)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.writeObs", false]], "writeobsstr() (diffpy.pdfgui.control.fitdataset.fitdataset method)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.writeObsStr", false]], "writeresampledobs() (diffpy.pdfgui.control.fitdataset.fitdataset method)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.writeResampledObs", false]], "writeresampledobsstr() (diffpy.pdfgui.control.fitdataset.fitdataset method)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.writeResampledObsStr", false]], "writestr() (diffpy.pdfgui.control.calculation.calculation method)": [[2, "diffpy.pdfgui.control.calculation.Calculation.writeStr", false]], "writestr() (diffpy.pdfgui.control.fitdataset.fitdataset method)": [[2, "diffpy.pdfgui.control.fitdataset.FitDataSet.writeStr", false]], "writestr() (diffpy.pdfgui.control.pdfdataset.pdfdataset method)": [[2, "diffpy.pdfgui.control.pdfdataset.PDFDataSet.writeStr", false]]}, "objects": {"diffpy": [[0, 0, 0, "-", "pdfgui"]], "diffpy.pdfgui": [[1, 0, 0, "-", "applications"], [2, 0, 0, "-", "control"], [3, 0, 0, "-", "gui"], [6, 0, 0, "-", "icons"], [0, 0, 0, "-", "tui"], [0, 0, 0, "-", "utils"]], "diffpy.pdfgui.applications": [[1, 0, 0, "-", "pdfgui"]], "diffpy.pdfgui.applications.pdfgui": [[1, 1, 1, "", "main"], [1, 1, 1, "", "processArguments"], [1, 1, 1, "", "usage"], [1, 1, 1, "", "version"]], "diffpy.pdfgui.control": [[2, 0, 0, "-", "calculation"], [2, 0, 0, "-", "constraint"], [2, 0, 0, "-", "controlerrors"], [2, 0, 0, "-", "fitdataset"], [2, 0, 0, "-", "fitstructure"], [2, 0, 0, "-", "fitting"], [2, 0, 0, "-", "organizer"], [2, 0, 0, "-", "parameter"], [2, 0, 0, "-", "pdfcomponent"], [2, 0, 0, "-", "pdfdataset"], [2, 0, 0, "-", "pdfguicontrol"], [2, 0, 0, "-", "pdfguimacros"], [2, 0, 0, "-", "pdflist"], [2, 0, 0, "-", "pdfstructure"], [2, 0, 0, "-", "plotter"], [2, 0, 0, "-", "structureviewer"]], "diffpy.pdfgui.control.calculation": [[2, 2, 1, "", "Calculation"]], "diffpy.pdfgui.control.calculation.Calculation": [[2, 3, 1, "", "calculate"], [2, 3, 1, "", "copy"], [2, 3, 1, "", "getData"], [2, 3, 1, "", "getMetaData"], [2, 3, 1, "", "getMetaDataNames"], [2, 3, 1, "", "getXNames"], [2, 3, 1, "", "getYNames"], [2, 3, 1, "", "load"], [2, 3, 1, "", "save"], [2, 3, 1, "", "setRGrid"], [2, 3, 1, "", "start"], [2, 3, 1, "", "write"], [2, 3, 1, "", "writeStr"]], "diffpy.pdfgui.control.constraint": [[2, 2, 1, "", "Constraint"]], "diffpy.pdfgui.control.constraint.Constraint": [[2, 3, 1, "", "evalFormula"], [2, 3, 1, "", "guess"], [2, 3, 1, "", "lambdaFormula"]], "diffpy.pdfgui.control.controlerrors": [[2, 4, 1, "", "ControlConfigError"], [2, 4, 1, "", "ControlError"], [2, 4, 1, "", "ControlFileError"], [2, 4, 1, "", "ControlIndexError"], [2, 4, 1, "", "ControlKeyError"], [2, 4, 1, "", "ControlRuntimeError"], [2, 4, 1, "", "ControlStatusError"], [2, 4, 1, "", "ControlSyntaxError"], [2, 4, 1, "", "ControlTypeError"], [2, 4, 1, "", "ControlValueError"], [2, 4, 1, "", "TempControlSelectError"]], "diffpy.pdfgui.control.fitdataset": [[2, 2, 1, "", "FitDataSet"], [2, 1, 1, "", "grid_interpolation"]], "diffpy.pdfgui.control.fitdataset.FitDataSet": [[2, 5, 1, "", "Gcalc"], [2, 5, 1, "", "Gdiff"], [2, 5, 1, "", "Gtrunc"], [2, 3, 1, "", "applyParameters"], [2, 3, 1, "", "changeParameterIndex"], [2, 3, 1, "", "clear"], [2, 3, 1, "", "clearRefined"], [2, 3, 1, "", "copy"], [2, 5, 1, "", "crw"], [2, 5, 1, "", "dGcalc"], [2, 5, 1, "", "dGtrunc"], [2, 3, 1, "", "findParameters"], [2, 5, 1, "", "fitrmax"], [2, 5, 1, "", "fitrmin"], [2, 5, 1, "", "fitrstep"], [2, 3, 1, "", "getData"], [2, 3, 1, "", "getFitSamplingType"], [2, 3, 1, "", "getNyquistSampling"], [2, 3, 1, "", "getObsSampling"], [2, 3, 1, "", "getXNames"], [2, 3, 1, "", "getYNames"], [2, 3, 1, "", "load"], [2, 3, 1, "", "obtainRefined"], [2, 6, 1, "", "persistentItems"], [2, 5, 1, "", "rcalc"], [2, 3, 1, "", "read"], [2, 3, 1, "", "readObs"], [2, 3, 1, "", "readObsStr"], [2, 3, 1, "", "readStr"], [2, 3, 1, "", "save"], [2, 3, 1, "", "setFitSamplingType"], [2, 3, 1, "", "write"], [2, 3, 1, "", "writeCalc"], [2, 3, 1, "", "writeCalcStr"], [2, 3, 1, "", "writeObs"], [2, 3, 1, "", "writeObsStr"], [2, 3, 1, "", "writeResampledObs"], [2, 3, 1, "", "writeResampledObsStr"], [2, 3, 1, "", "writeStr"]], "diffpy.pdfgui.control.fitstructure": [[2, 2, 1, "", "FitStructure"]], "diffpy.pdfgui.control.fitstructure.FitStructure": [[2, 3, 1, "", "applyPairSelection"], [2, 3, 1, "", "applyParameters"], [2, 3, 1, "", "applySymmetryConstraints"], [2, 3, 1, "", "changeParameterIndex"], [2, 3, 1, "", "clearRefined"], [2, 3, 1, "", "copy"], [2, 3, 1, "", "deleteAtoms"], [2, 3, 1, "", "expandAsymmetricUnit"], [2, 3, 1, "", "expandSuperCell"], [2, 3, 1, "", "findParameters"], [2, 3, 1, "", "getData"], [2, 3, 1, "", "getPairSelectionFlags"], [2, 3, 1, "", "getSelectedIndices"], [2, 3, 1, "", "getSelectedPairs"], [2, 3, 1, "", "getSpaceGroup"], [2, 3, 1, "", "getSpaceGroupList"], [2, 3, 1, "", "getXNames"], [2, 3, 1, "", "getYNames"], [2, 3, 1, "", "insertAtoms"], [2, 3, 1, "", "isSpaceGroupPossible"], [2, 3, 1, "", "load"], [2, 3, 1, "", "obtainRefined"], [2, 3, 1, "", "read"], [2, 3, 1, "", "readStr"], [2, 3, 1, "", "save"], [2, 3, 1, "", "setSelectedPairs"], [2, 6, 1, "", "sorted_standard_space_groups"], [2, 6, 1, "", "symposeps"]], "diffpy.pdfgui.control.fitting": [[2, 2, 1, "", "Fitting"], [2, 1, 1, "", "getEngineExceptions"], [2, 1, 1, "", "handleEngineException"]], "diffpy.pdfgui.control.fitting.Fitting": [[2, 6, 1, "", "CONFIGURED"], [2, 6, 1, "", "CONNECTED"], [2, 6, 1, "", "DONE"], [2, 6, 1, "", "INITIALIZED"], [2, 6, 1, "", "PAUSED"], [2, 6, 1, "", "QUEUED"], [2, 6, 1, "", "RUNNING"], [2, 6, 1, "", "VOID"], [2, 2, 1, "", "Worker"], [2, 3, 1, "", "appendStep"], [2, 3, 1, "", "applyParameters"], [2, 3, 1, "", "buildNameDict"], [2, 3, 1, "", "changeParameterIndex"], [2, 3, 1, "", "close"], [2, 3, 1, "", "configure"], [2, 3, 1, "", "copy"], [2, 3, 1, "", "getData"], [2, 3, 1, "", "getMetaData"], [2, 3, 1, "", "getMetaDataNames"], [2, 3, 1, "", "getServer"], [2, 3, 1, "", "getXNames"], [2, 3, 1, "", "getYNames"], [2, 3, 1, "", "isThreadRunning"], [2, 3, 1, "", "join"], [2, 3, 1, "", "load"], [2, 3, 1, "", "outputBondAngle"], [2, 3, 1, "", "outputBondLengthAtoms"], [2, 3, 1, "", "outputBondLengthTypes"], [2, 3, 1, "", "pause"], [2, 3, 1, "", "queue"], [2, 3, 1, "", "refine_step"], [2, 3, 1, "", "resetStatus"], [2, 3, 1, "", "run"], [2, 3, 1, "", "save"], [2, 3, 1, "", "start"], [2, 3, 1, "", "stop"], [2, 3, 1, "", "stripped"], [2, 3, 1, "", "updateParameters"]], "diffpy.pdfgui.control.fitting.Fitting.Worker": [[2, 3, 1, "", "run"]], "diffpy.pdfgui.control.organizer": [[2, 2, 1, "", "Organizer"], [2, 1, 1, "", "spd_assigned"], [2, 1, 1, "", "spd_constrained"]], "diffpy.pdfgui.control.organizer.Organizer": [[2, 3, 1, "", "add"], [2, 3, 1, "", "copy"], [2, 3, 1, "", "getCalculation"], [2, 3, 1, "", "getDataSet"], [2, 3, 1, "", "getStructure"], [2, 3, 1, "", "hasCalculations"], [2, 3, 1, "", "hasDataSets"], [2, 3, 1, "", "hasStructures"], [2, 3, 1, "", "index"], [2, 3, 1, "", "load"], [2, 3, 1, "", "organization"], [2, 3, 1, "", "remove"], [2, 3, 1, "", "rename"], [2, 3, 1, "", "save"]], "diffpy.pdfgui.control.parameter": [[2, 2, 1, "", "Parameter"]], "diffpy.pdfgui.control.parameter.Parameter": [[2, 3, 1, "", "initialStr"], [2, 3, 1, "", "initialValue"], [2, 3, 1, "", "setInitial"]], "diffpy.pdfgui.control.pdfcomponent": [[2, 2, 1, "", "PDFComponent"]], "diffpy.pdfgui.control.pdfcomponent.PDFComponent": [[2, 3, 1, "", "close"]], "diffpy.pdfgui.control.pdfdataset": [[2, 4, 1, "", "PDFDataFormatError"], [2, 2, 1, "", "PDFDataSet"]], "diffpy.pdfgui.control.pdfdataset.PDFDataSet": [[2, 3, 1, "", "clear"], [2, 3, 1, "", "copy"], [2, 3, 1, "", "getvar"], [2, 6, 1, "", "persistentItems"], [2, 3, 1, "", "read"], [2, 3, 1, "", "readStr"], [2, 6, 1, "", "refinableVars"], [2, 3, 1, "", "setvar"], [2, 3, 1, "", "write"], [2, 3, 1, "", "writeStr"]], "diffpy.pdfgui.control.pdfguicontrol": [[2, 2, 1, "", "CtrlUnpickler"], [2, 2, 1, "", "PDFGuiControl"], [2, 1, 1, "", "pdfguicontrol"]], "diffpy.pdfgui.control.pdfguicontrol.CtrlUnpickler": [[2, 3, 1, "", "loads"]], "diffpy.pdfgui.control.pdfguicontrol.PDFGuiControl": [[2, 2, 1, "", "QueueManager"], [2, 3, 1, "", "add"], [2, 3, 1, "", "checkQueue"], [2, 3, 1, "", "close"], [2, 3, 1, "", "copy"], [2, 3, 1, "", "enqueue"], [2, 3, 1, "", "exit"], [2, 3, 1, "", "getEngineOutput"], [2, 3, 1, "", "index"], [2, 3, 1, "", "load"], [2, 3, 1, "", "loadDataset"], [2, 3, 1, "", "loadStructure"], [2, 3, 1, "", "newCalculation"], [2, 3, 1, "", "newFitting"], [2, 3, 1, "", "newStructure"], [2, 3, 1, "", "paste"], [2, 3, 1, "", "plot"], [2, 3, 1, "", "redirectStdout"], [2, 3, 1, "", "remove"], [2, 3, 1, "", "rename"], [2, 3, 1, "", "reset"], [2, 3, 1, "", "save"], [2, 3, 1, "", "start"], [2, 3, 1, "", "startQueue"], [2, 3, 1, "", "stop"]], "diffpy.pdfgui.control.pdfguicontrol.PDFGuiControl.QueueManager": [[2, 3, 1, "", "run"]], "diffpy.pdfgui.control.pdfguimacros": [[2, 1, 1, "", "makeDopingSeries"], [2, 1, 1, "", "makeRSeries"], [2, 1, 1, "", "makeTemperatureSeries"]], "diffpy.pdfgui.control.pdflist": [[2, 2, 1, "", "PDFList"]], "diffpy.pdfgui.control.pdflist.PDFList": [[2, 3, 1, "", "items"], [2, 3, 1, "", "keys"], [2, 3, 1, "", "rename"], [2, 3, 1, "", "values"]], "diffpy.pdfgui.control.pdfstructure": [[2, 2, 1, "", "PDFStructure"]], "diffpy.pdfgui.control.pdfstructure.PDFStructure": [[2, 3, 1, "", "copy"], [2, 3, 1, "", "getvar"], [2, 3, 1, "", "read"], [2, 3, 1, "", "setvar"]], "diffpy.pdfgui.control.plotter": [[2, 2, 1, "", "Plotter"], [2, 1, 1, "", "deblank"]], "diffpy.pdfgui.control.plotter.Plotter": [[2, 2, 1, "", "Curve"], [2, 3, 1, "", "buildLineStyle"], [2, 3, 1, "", "buildLineSymbolStyle"], [2, 3, 1, "", "buildSymbolStyle"], [2, 3, 1, "", "close"], [2, 3, 1, "", "export"], [2, 3, 1, "", "notify"], [2, 3, 1, "", "onWindowClose"], [2, 3, 1, "", "plot"], [2, 3, 1, "", "show"]], "diffpy.pdfgui.control.plotter.Plotter.Curve": [[2, 3, 1, "", "draw"], [2, 3, 1, "", "notify"], [2, 3, 1, "", "validate"]], "diffpy.pdfgui.control.structureviewer": [[2, 2, 1, "", "StructureViewer"], [2, 1, 1, "", "getStructureViewer"]], "diffpy.pdfgui.control.structureviewer.StructureViewer": [[2, 3, 1, "", "getConfig"], [2, 3, 1, "", "getFileFormats"], [2, 3, 1, "", "plot"], [2, 3, 1, "", "setConfig"]], "diffpy.pdfgui.gui": [[3, 0, 0, "-", "aboutdialog"], [3, 0, 0, "-", "adddatapanel"], [3, 0, 0, "-", "addphasepanel"], [3, 0, 0, "-", "blankpanel"], [3, 0, 0, "-", "bondangledialog"], [3, 0, 0, "-", "bondlengthdialog"], [3, 0, 0, "-", "calculationpanel"], [3, 0, 0, "-", "datasetconfigurepanel"], [3, 0, 0, "-", "datasetconstraintpanel"], [3, 0, 0, "-", "datasetpanel"], [3, 0, 0, "-", "datasetresultspanel"], [3, 0, 0, "-", "debugoptions"], [4, 0, 0, "-", "design"], [3, 0, 0, "-", "dopingseriespanel"], [3, 0, 0, "-", "errorreportdialog"], [3, 0, 0, "-", "errorreportdialog_control_fix"], [3, 0, 0, "-", "errorwrapper"], [3, 0, 0, "-", "extendedplotframe"], [3, 0, 0, "-", "fitnotebookpanel"], [3, 0, 0, "-", "fittree"], [3, 0, 0, "-", "insertrowsdialog"], [3, 0, 0, "-", "journalpanel"], [3, 0, 0, "-", "main"], [3, 0, 0, "-", "mainframe"], [3, 0, 0, "-", "outputpanel"], [3, 0, 0, "-", "paneltest"], [3, 0, 0, "-", "parameterspanel"], [3, 0, 0, "-", "pdfguiglobals"], [3, 0, 0, "-", "pdfpanel"], [3, 0, 0, "-", "phaseconfigurepanel"], [3, 0, 0, "-", "phaseconstraintspanel"], [3, 0, 0, "-", "phasenotebookpanel"], [3, 0, 0, "-", "phasepanelutils"], [3, 0, 0, "-", "phaseresultspanel"], [3, 0, 0, "-", "plotpanel"], [3, 0, 0, "-", "preferencespanel"], [3, 0, 0, "-", "resultspanel"], [3, 0, 0, "-", "rseriespanel"], [3, 0, 0, "-", "sgconstraindialog"], [3, 0, 0, "-", "sgstructuredialog"], [3, 0, 0, "-", "supercelldialog"], [3, 0, 0, "-", "temperatureseriespanel"], [3, 0, 0, "-", "tooltips"], [3, 0, 0, "-", "welcomepanel"], [3, 0, 0, "-", "windowperspective"], [5, 0, 0, "-", "wxextensions"]], "diffpy.pdfgui.gui.aboutdialog": [[3, 2, 1, "", "DialogAbout"], [3, 1, 1, "", "launchBrowser"]], "diffpy.pdfgui.gui.aboutdialog.DialogAbout": [[3, 3, 1, "", "onColumbiaLogo"], [3, 3, 1, "", "onDanseLogo"], [3, 3, 1, "", "onMsuLogo"], [3, 3, 1, "", "onNsfLogo"]], "diffpy.pdfgui.gui.adddatapanel": [[3, 2, 1, "", "AddDataPanel"]], "diffpy.pdfgui.gui.adddatapanel.AddDataPanel": [[3, 3, 1, "", "onCancel"], [3, 3, 1, "", "onOpen"], [3, 3, 1, "", "readConfiguration"], [3, 3, 1, "", "refresh"], [3, 3, 1, "", "updateConfiguration"]], "diffpy.pdfgui.gui.addphasepanel": [[3, 2, 1, "", "AddPhasePanel"]], "diffpy.pdfgui.gui.addphasepanel.AddPhasePanel": [[3, 3, 1, "", "onCancel"], [3, 3, 1, "", "onNew"], [3, 3, 1, "", "onOpen"], [3, 3, 1, "", "readConfiguration"], [3, 3, 1, "", "refresh"], [3, 3, 1, "", "updateConfiguration"], [3, 3, 1, "", "validateStructure"]], "diffpy.pdfgui.gui.blankpanel": [[3, 2, 1, "", "BlankPanel"]], "diffpy.pdfgui.gui.blankpanel.BlankPanel": [[3, 3, 1, "", "refresh"]], "diffpy.pdfgui.gui.bondangledialog": [[3, 2, 1, "", "BondAngleDialog"]], "diffpy.pdfgui.gui.bondangledialog.BondAngleDialog": [[3, 3, 1, "", "getCtrlLetter"], [3, 3, 1, "", "onCancel"], [3, 3, 1, "", "onOk"], [3, 3, 1, "", "onSpin"], [3, 3, 1, "", "setStructure"]], "diffpy.pdfgui.gui.bondlengthdialog": [[3, 2, 1, "", "BondLengthDialog"]], "diffpy.pdfgui.gui.bondlengthdialog.BondLengthDialog": [[3, 3, 1, "", "getCtrlLetter"], [3, 3, 1, "", "onCancel"], [3, 3, 1, "", "onComboKillFocus"], [3, 3, 1, "", "onOk"], [3, 3, 1, "", "onSpin"], [3, 3, 1, "", "onTextKillFocus"], [3, 3, 1, "", "setStructure"]], "diffpy.pdfgui.gui.calculationpanel": [[3, 2, 1, "", "CalculationPanel"]], "diffpy.pdfgui.gui.calculationpanel.CalculationPanel": [[3, 3, 1, "", "onCalcRange"], [3, 3, 1, "", "onExport"], [3, 3, 1, "", "onKillFocus"], [3, 3, 1, "", "onSetFocus"], [3, 3, 1, "", "onStype"], [3, 3, 1, "", "onTextCtrlKey"], [3, 3, 1, "", "refresh"], [3, 3, 1, "", "setConfigurationData"]], "diffpy.pdfgui.gui.datasetconfigurepanel": [[3, 2, 1, "", "DataSetConfigurePanel"]], "diffpy.pdfgui.gui.datasetconfigurepanel.DataSetConfigurePanel": [[3, 3, 1, "", "onLoseFocus"], [3, 3, 1, "", "onSampling"], [3, 3, 1, "", "onSetFocus"], [3, 3, 1, "", "onStype"], [3, 3, 1, "", "onTextCtrlKey"], [3, 3, 1, "", "refresh"], [3, 3, 1, "", "restrictConstrainedParameters"], [3, 3, 1, "", "setConfigurationData"]], "diffpy.pdfgui.gui.datasetconstraintpanel": [[3, 2, 1, "", "DataSetConstraintPanel"]], "diffpy.pdfgui.gui.datasetconstraintpanel.DataSetConstraintPanel": [[3, 3, 1, "", "onLoseFocus"], [3, 3, 1, "", "onSetFocus"], [3, 3, 1, "", "onTextCtrlKey"], [3, 3, 1, "", "processFormula"], [3, 3, 1, "", "refresh"], [3, 3, 1, "", "setConstraintsData"]], "diffpy.pdfgui.gui.datasetpanel": [[3, 2, 1, "", "DataSetPanel"]], "diffpy.pdfgui.gui.datasetpanel.DataSetPanel": [[3, 3, 1, "", "Enable"], [3, 3, 1, "", "onNotebookChanged"], [3, 3, 1, "", "refresh"], [3, 3, 1, "", "refreshSelectedPage"]], "diffpy.pdfgui.gui.datasetresultspanel": [[3, 2, 1, "", "DataSetResultsPanel"]], "diffpy.pdfgui.gui.datasetresultspanel.DataSetResultsPanel": [[3, 3, 1, "", "onExport"], [3, 3, 1, "", "refresh"], [3, 3, 1, "", "setResultsData"]], "diffpy.pdfgui.gui.debugoptions": [[3, 2, 1, "", "DebugOptions"]], "diffpy.pdfgui.gui.debugoptions.DebugOptions": [[3, 6, 1, "", "alldebugoptions"], [3, 6, 1, "", "short2long"]], "diffpy.pdfgui.gui.dopingseriespanel": [[3, 2, 1, "", "DopingSeriesPanel"]], "diffpy.pdfgui.gui.dopingseriespanel.DopingSeriesPanel": [[3, 3, 1, "", "checkConfiguration"], [3, 3, 1, "", "fillList"], [3, 3, 1, "", "onAdd"], [3, 3, 1, "", "onCancel"], [3, 3, 1, "", "onColClick"], [3, 3, 1, "", "onDelete"], [3, 3, 1, "", "onDown"], [3, 3, 1, "", "onEndLabelEdit"], [3, 3, 1, "", "onOK"], [3, 3, 1, "", "onUp"], [3, 3, 1, "", "refresh"], [3, 3, 1, "", "treeSelectionUpdate"]], "diffpy.pdfgui.gui.errorreportdialog": [[3, 2, 1, "", "ErrorReportDialog"], [3, 2, 1, "", "MyApp"]], "diffpy.pdfgui.gui.errorreportdialog.ErrorReportDialog": [[3, 3, 1, "", "ShowModal"], [3, 3, 1, "", "onCopyErrorLog"], [3, 3, 1, "", "onGoogle"], [3, 3, 1, "", "onURL"]], "diffpy.pdfgui.gui.errorreportdialog.MyApp": [[3, 3, 1, "", "OnInit"], [3, 3, 1, "", "test"]], "diffpy.pdfgui.gui.errorreportdialog_control_fix": [[3, 2, 1, "", "ErrorReportDialogControlFix"], [3, 2, 1, "", "MyApp"]], "diffpy.pdfgui.gui.errorreportdialog_control_fix.ErrorReportDialogControlFix": [[3, 3, 1, "", "ShowModal"]], "diffpy.pdfgui.gui.errorreportdialog_control_fix.MyApp": [[3, 3, 1, "", "OnInit"], [3, 3, 1, "", "test"]], "diffpy.pdfgui.gui.errorwrapper": [[3, 1, 1, "", "catchFunctionErrors"], [3, 1, 1, "", "catchObjectErrors"]], "diffpy.pdfgui.gui.extendedplotframe": [[3, 2, 1, "", "ExtendedPlotFrame"], [3, 2, 1, "", "ExtendedToolbar"], [3, 1, 1, "", "legendBoxProperties"]], "diffpy.pdfgui.gui.extendedplotframe.ExtendedPlotFrame": [[3, 3, 1, "", "OnPaint"], [3, 3, 1, "", "UpdateStatusBar"], [3, 3, 1, "", "changeStyle"], [3, 3, 1, "", "clear"], [3, 6, 1, "", "close_keys"], [3, 3, 1, "", "insertCurve"], [3, 3, 1, "", "mplKeyPress"], [3, 3, 1, "", "onClose"], [3, 3, 1, "", "removeCurve"], [3, 3, 1, "", "replot"], [3, 3, 1, "", "savePlotData"], [3, 3, 1, "", "setTitle"], [3, 3, 1, "", "setXLabel"], [3, 3, 1, "", "setYLabel"], [3, 3, 1, "", "updateData"]], "diffpy.pdfgui.gui.extendedplotframe.ExtendedToolbar": [[3, 6, 1, "", "toolitems"]], "diffpy.pdfgui.gui.fitnotebookpanel": [[3, 2, 1, "", "FitNotebookPanel"]], "diffpy.pdfgui.gui.fitnotebookpanel.FitNotebookPanel": [[3, 3, 1, "", "Enable"], [3, 3, 1, "", "onPageChanged"], [3, 3, 1, "", "onPageChanging"], [3, 3, 1, "", "refresh"]], "diffpy.pdfgui.gui.fittree": [[3, 2, 1, "", "FitTree"], [3, 4, 1, "", "FitTreeError"], [3, 1, 1, "", "incrementName"]], "diffpy.pdfgui.gui.fittree.FitTree": [[3, 3, 1, "", "AddCalc"], [3, 3, 1, "", "AddDataSet"], [3, 3, 1, "", "AddFit"], [3, 3, 1, "", "AddPhase"], [3, 3, 1, "", "CopyBranch"], [3, 3, 1, "", "DeleteBranches"], [3, 3, 1, "", "ExtendProjectTree"], [3, 3, 1, "", "GetAllType"], [3, 3, 1, "", "GetBranchName"], [3, 3, 1, "", "GetCalculations"], [3, 3, 1, "", "GetChildren"], [3, 3, 1, "", "GetClipboard"], [3, 3, 1, "", "GetControlData"], [3, 3, 1, "", "GetDataSets"], [3, 3, 1, "", "GetFitRoot"], [3, 3, 1, "", "GetLastDataSet"], [3, 3, 1, "", "GetLastPhase"], [3, 3, 1, "", "GetNodeType"], [3, 3, 1, "", "GetNumDataSets"], [3, 3, 1, "", "GetNumPhases"], [3, 3, 1, "", "GetPhases"], [3, 3, 1, "", "GetPositionInSubtree"], [3, 3, 1, "", "GetSiblings"], [3, 3, 1, "", "GetTreeItemDict"], [3, 3, 1, "", "InitializeTree"], [3, 3, 1, "", "PasteBranch"], [3, 3, 1, "", "SelectAll"], [3, 3, 1, "", "SelectAllType"], [3, 3, 1, "", "SetControlData"], [3, 3, 1, "", "SetNodeType"]], "diffpy.pdfgui.gui.insertrowsdialog": [[3, 2, 1, "", "InsertRowsDialog"]], "diffpy.pdfgui.gui.journalpanel": [[3, 2, 1, "", "JournalPanel"]], "diffpy.pdfgui.gui.journalpanel.JournalPanel": [[3, 3, 1, "", "onClose"], [3, 3, 1, "", "onExport"], [3, 3, 1, "", "onKey"], [3, 3, 1, "", "onText"], [3, 3, 1, "", "refresh"]], "diffpy.pdfgui.gui.main": [[3, 2, 1, "", "PDFGuiApp"], [3, 1, 1, "", "main"]], "diffpy.pdfgui.gui.main.PDFGuiApp": [[3, 3, 1, "", "OnInit"]], "diffpy.pdfgui.gui.mainframe": [[3, 2, 1, "", "MainFrame"]], "diffpy.pdfgui.gui.mainframe.MainFrame": [[3, 3, 1, "", "checkForSave"], [3, 3, 1, "", "disableMainMenuItems"], [3, 3, 1, "", "disableSharedMenuItems"], [3, 3, 1, "", "loadConfiguration"], [3, 3, 1, "", "lock"], [3, 3, 1, "", "makeTreeSelection"], [3, 3, 1, "", "needsSave"], [3, 3, 1, "", "onAbout"], [3, 3, 1, "", "onBeginLabelEdit"], [3, 3, 1, "", "onCommunity"], [3, 3, 1, "", "onCopy"], [3, 3, 1, "", "onCustom"], [3, 3, 1, "", "onDSeries"], [3, 3, 1, "", "onDefaultLayout"], [3, 3, 1, "", "onDelete"], [3, 3, 1, "", "onDocumentation"], [3, 3, 1, "", "onDoubleClick"], [3, 3, 1, "", "onDoubleClick2"], [3, 3, 1, "", "onEndLabelEdit"], [3, 3, 1, "", "onExportNewStruct"], [3, 3, 1, "", "onExportPDF"], [3, 3, 1, "", "onExportRes"], [3, 3, 1, "", "onExportStruct"], [3, 3, 1, "", "onInsCalc"], [3, 3, 1, "", "onInsData"], [3, 3, 1, "", "onInsPhase"], [3, 3, 1, "", "onKey"], [3, 3, 1, "", "onMRUFile"], [3, 3, 1, "", "onMainMenu"], [3, 3, 1, "", "onMiddleClick"], [3, 3, 1, "", "onNew"], [3, 3, 1, "", "onNewFit"], [3, 3, 1, "", "onOpen"], [3, 3, 1, "", "onPaste"], [3, 3, 1, "", "onPasteLink"], [3, 3, 1, "", "onPlotFStruct"], [3, 3, 1, "", "onPlotIStruct"], [3, 3, 1, "", "onPreferences"], [3, 3, 1, "", "onPrintBA"], [3, 3, 1, "", "onPrintBL"], [3, 3, 1, "", "onQuickPlot"], [3, 3, 1, "", "onQuit"], [3, 3, 1, "", "onRSeries"], [3, 3, 1, "", "onRequest"], [3, 3, 1, "", "onRightClick"], [3, 3, 1, "", "onRun"], [3, 3, 1, "", "onSave"], [3, 3, 1, "", "onSaveAs"], [3, 3, 1, "", "onSaveCalc"], [3, 3, 1, "", "onShowFit"], [3, 3, 1, "", "onShowJournal"], [3, 3, 1, "", "onShowOutput"], [3, 3, 1, "", "onShowPlot"], [3, 3, 1, "", "onStop"], [3, 3, 1, "", "onTSeries"], [3, 3, 1, "", "onTreeSelChanged"], [3, 3, 1, "", "onTreeSelChanging"], [3, 3, 1, "", "postEvent"], [3, 3, 1, "", "setMode"], [3, 3, 1, "", "setPanelSpecificData"], [3, 3, 1, "", "showMessage"], [3, 3, 1, "", "switchRightPanel"], [3, 3, 1, "", "treeSelectionUpdate"], [3, 3, 1, "", "unlock"], [3, 3, 1, "", "updateConfiguration"], [3, 3, 1, "", "updateFittingStatus"], [3, 3, 1, "", "updateOutput"], [3, 3, 1, "", "updateTitle"], [3, 3, 1, "", "updateToolbar"], [3, 3, 1, "", "writeConfiguration"]], "diffpy.pdfgui.gui.outputpanel": [[3, 2, 1, "", "OutputPanel"]], "diffpy.pdfgui.gui.outputpanel.OutputPanel": [[3, 3, 1, "", "clearText"], [3, 3, 1, "", "refresh"], [3, 3, 1, "", "updateText"]], "diffpy.pdfgui.gui.paneltest": [[3, 2, 1, "", "MyApp"], [3, 2, 1, "", "MyFrame"]], "diffpy.pdfgui.gui.paneltest.MyApp": [[3, 3, 1, "", "OnInit"]], "diffpy.pdfgui.gui.parameterspanel": [[3, 2, 1, "", "ParametersPanel"]], "diffpy.pdfgui.gui.parameterspanel.ParametersPanel": [[3, 3, 1, "", "applyCellChange"], [3, 3, 1, "", "fillCells"], [3, 3, 1, "", "getSelectedParameters"], [3, 3, 1, "", "onApplyParameters"], [3, 3, 1, "", "onCellChange"], [3, 3, 1, "", "onCellLeftClick"], [3, 3, 1, "", "onCellRightClick"], [3, 3, 1, "", "onEditorShown"], [3, 3, 1, "", "onGridRangeSelect"], [3, 3, 1, "", "onPopupCopyRefinedToInitial"], [3, 3, 1, "", "onPopupFill"], [3, 3, 1, "", "onPopupFixFree"], [3, 3, 1, "", "onPopupRenameParameters"], [3, 3, 1, "", "popupMenu"], [3, 3, 1, "", "refresh"]], "diffpy.pdfgui.gui.pdfguiglobals": [[3, 1, 1, "", "iconpath"]], "diffpy.pdfgui.gui.pdfpanel": [[3, 2, 1, "", "PDFPanel"]], "diffpy.pdfgui.gui.pdfpanel.PDFPanel": [[3, 3, 1, "", "refresh"], [3, 3, 1, "", "setToolTips"]], "diffpy.pdfgui.gui.phaseconfigurepanel": [[3, 2, 1, "", "PhaseConfigurePanel"]], "diffpy.pdfgui.gui.phaseconfigurepanel.PhaseConfigurePanel": [[3, 3, 1, "", "applyCellChange"], [3, 3, 1, "", "applyTextCtrlChange"], [3, 3, 1, "", "fillCells"], [3, 3, 1, "", "onCellChange"], [3, 3, 1, "", "onCellRightClick"], [3, 3, 1, "", "onEditorShown"], [3, 3, 1, "", "onKey"], [3, 3, 1, "", "onKillFocus"], [3, 3, 1, "", "onLabelRightClick"], [3, 3, 1, "", "onPopupCopy"], [3, 3, 1, "", "onPopupDelete"], [3, 3, 1, "", "onPopupInsert"], [3, 3, 1, "", "onPopupPaste"], [3, 3, 1, "", "onPopupSelect"], [3, 3, 1, "", "onPopupSpaceGroup"], [3, 3, 1, "", "onPopupSupercell"], [3, 3, 1, "", "onSelectedPairs"], [3, 3, 1, "", "onSetFocus"], [3, 3, 1, "", "onTextCtrlKey"], [3, 3, 1, "", "popupMenu"], [3, 3, 1, "", "refresh"], [3, 3, 1, "", "restrictConstrainedParameters"]], "diffpy.pdfgui.gui.phaseconstraintspanel": [[3, 2, 1, "", "PhaseConstraintsPanel"]], "diffpy.pdfgui.gui.phaseconstraintspanel.PhaseConstraintsPanel": [[3, 3, 1, "", "applyCellChange"], [3, 3, 1, "", "applyTextCtrlChange"], [3, 3, 1, "", "fillCells"], [3, 3, 1, "", "onCellChange"], [3, 3, 1, "", "onCellRightClick"], [3, 3, 1, "", "onEditorShown"], [3, 3, 1, "", "onKey"], [3, 3, 1, "", "onKillFocus"], [3, 3, 1, "", "onLabelRightClick"], [3, 3, 1, "", "onPopupCopy"], [3, 3, 1, "", "onPopupPaste"], [3, 3, 1, "", "onPopupSelect"], [3, 3, 1, "", "onPopupSpaceGroup"], [3, 3, 1, "", "onSetFocus"], [3, 3, 1, "", "onTextCtrlKey"], [3, 3, 1, "", "popupMenu"], [3, 3, 1, "", "refresh"], [3, 3, 1, "", "refreshTextCtrls"]], "diffpy.pdfgui.gui.phasenotebookpanel": [[3, 2, 1, "", "PhaseNotebookPanel"]], "diffpy.pdfgui.gui.phasenotebookpanel.PhaseNotebookPanel": [[3, 3, 1, "", "Enable"], [3, 3, 1, "", "onNotebookPageChanged"], [3, 3, 1, "", "onNotebookPageChanging"], [3, 3, 1, "", "refresh"]], "diffpy.pdfgui.gui.phasepanelutils": [[3, 1, 1, "", "canCopySelectedCells"], [3, 1, 1, "", "canPasteIntoCells"], [3, 1, 1, "", "copySelectedCells"], [3, 1, 1, "", "float2str"], [3, 1, 1, "", "pasteIntoCells"], [3, 1, 1, "", "refreshGrid"], [3, 1, 1, "", "refreshTextCtrls"], [3, 1, 1, "", "showSelectAtomsDialog"]], "diffpy.pdfgui.gui.phaseresultspanel": [[3, 2, 1, "", "PhaseResultsPanel"]], "diffpy.pdfgui.gui.phaseresultspanel.PhaseResultsPanel": [[3, 3, 1, "", "refresh"]], "diffpy.pdfgui.gui.plotpanel": [[3, 2, 1, "", "PlotPanel"]], "diffpy.pdfgui.gui.plotpanel.PlotPanel": [[3, 3, 1, "", "enableWidgets"], [3, 3, 1, "", "getSelectedYVals"], [3, 3, 1, "", "onEnter"], [3, 3, 1, "", "onPlot"], [3, 3, 1, "", "onReset"], [3, 3, 1, "", "refresh"], [3, 3, 1, "", "updateWidgets"]], "diffpy.pdfgui.gui.preferencespanel": [[3, 2, 1, "", "PreferencesPanel"]], "diffpy.pdfgui.gui.preferencespanel.PreferencesPanel": [[3, 3, 1, "", "onBrowse"], [3, 3, 1, "", "onCancel"], [3, 3, 1, "", "onOK"], [3, 3, 1, "", "refresh"]], "diffpy.pdfgui.gui.resultspanel": [[3, 2, 1, "", "ResultsPanel"]], "diffpy.pdfgui.gui.resultspanel.ResultsPanel": [[3, 3, 1, "", "refresh"]], "diffpy.pdfgui.gui.rseriespanel": [[3, 2, 1, "", "RSeriesPanel"]], "diffpy.pdfgui.gui.rseriespanel.RSeriesPanel": [[3, 3, 1, "", "onCancel"], [3, 3, 1, "", "onOK"], [3, 3, 1, "", "refresh"], [3, 3, 1, "", "treeSelectionUpdate"]], "diffpy.pdfgui.gui.sgconstraindialog": [[3, 2, 1, "", "SGConstrainDialog"]], "diffpy.pdfgui.gui.sgconstraindialog.SGConstrainDialog": [[3, 3, 1, "", "getOffset"], [3, 3, 1, "", "getPosFlag"], [3, 3, 1, "", "getSpaceGroup"], [3, 3, 1, "", "getTempFlag"], [3, 3, 1, "", "onCancel"], [3, 3, 1, "", "onKillFocus"], [3, 3, 1, "", "onOXTextEnter"], [3, 3, 1, "", "onOYTextEnter"], [3, 3, 1, "", "onOZTextEnter"], [3, 3, 1, "", "onOk"], [3, 3, 1, "", "onPosFlag"], [3, 3, 1, "", "onSGSelect"], [3, 3, 1, "", "onSGTextEnter"], [3, 3, 1, "", "onTempFlag"], [3, 3, 1, "", "setStructure"], [3, 3, 1, "", "updateSpaceGroupList"], [3, 3, 1, "", "updateWidgets"]], "diffpy.pdfgui.gui.sgstructuredialog": [[3, 2, 1, "", "SGStructureDialog"]], "diffpy.pdfgui.gui.sgstructuredialog.SGStructureDialog": [[3, 3, 1, "", "getOffset"], [3, 3, 1, "", "getSpaceGroup"], [3, 3, 1, "", "onCancel"], [3, 3, 1, "", "onKillFocus"], [3, 3, 1, "", "onOXTextEnter"], [3, 3, 1, "", "onOYTextEnter"], [3, 3, 1, "", "onOZTextEnter"], [3, 3, 1, "", "onOk"], [3, 3, 1, "", "onSGSelect"], [3, 3, 1, "", "onSGTextEnter"], [3, 3, 1, "", "setStructure"], [3, 3, 1, "", "updateSpaceGroupList"], [3, 3, 1, "", "updateWidgets"]], "diffpy.pdfgui.gui.supercelldialog": [[3, 2, 1, "", "SupercellDialog"]], "diffpy.pdfgui.gui.supercelldialog.SupercellDialog": [[3, 3, 1, "", "getMNO"], [3, 3, 1, "", "onCancel"], [3, 3, 1, "", "onOk"]], "diffpy.pdfgui.gui.temperatureseriespanel": [[3, 2, 1, "", "TemperatureSeriesPanel"]], "diffpy.pdfgui.gui.temperatureseriespanel.TemperatureSeriesPanel": [[3, 3, 1, "", "fillList"], [3, 3, 1, "", "onAdd"], [3, 3, 1, "", "onCancel"], [3, 3, 1, "", "onColClick"], [3, 3, 1, "", "onDelete"], [3, 3, 1, "", "onDown"], [3, 3, 1, "", "onEndLabelEdit"], [3, 3, 1, "", "onOK"], [3, 3, 1, "", "onUp"], [3, 3, 1, "", "refresh"], [3, 3, 1, "", "treeSelectionUpdate"]], "diffpy.pdfgui.gui.tooltips": [[3, 1, 1, "", "isalias"]], "diffpy.pdfgui.gui.welcomepanel": [[3, 2, 1, "", "WelcomePanel"]], "diffpy.pdfgui.gui.welcomepanel.WelcomePanel": [[3, 3, 1, "", "refresh"]], "diffpy.pdfgui.gui.wxextensions": [[5, 0, 0, "-", "autowidthlabelsgrid"], [5, 0, 0, "-", "listctrls"], [5, 0, 0, "-", "paneldialog"], [5, 0, 0, "-", "textctrlutils"], [5, 0, 0, "-", "validators"]], "diffpy.pdfgui.gui.wxextensions.autowidthlabelsgrid": [[5, 2, 1, "", "AutoWidthLabelsGrid"]], "diffpy.pdfgui.gui.wxextensions.autowidthlabelsgrid.AutoWidthLabelsGrid": [[5, 3, 1, "", "AutosizeLabels"]], "diffpy.pdfgui.gui.wxextensions.listctrls": [[5, 2, 1, "", "AutoWidthListCtrl"], [5, 2, 1, "", "ColumnSortListCtrl"], [5, 2, 1, "", "KeyEventsListCtrl"]], "diffpy.pdfgui.gui.wxextensions.listctrls.AutoWidthListCtrl": [[5, 3, 1, "", "clearSelections"], [5, 3, 1, "", "setSelection"]], "diffpy.pdfgui.gui.wxextensions.listctrls.ColumnSortListCtrl": [[5, 3, 1, "", "GetListCtrl"], [5, 3, 1, "", "initializeSorter"], [5, 3, 1, "", "makeIDM"]], "diffpy.pdfgui.gui.wxextensions.listctrls.KeyEventsListCtrl": [[5, 3, 1, "", "OnKey"], [5, 3, 1, "", "OnKeyDown"], [5, 3, 1, "", "findPrefix"]], "diffpy.pdfgui.gui.wxextensions.paneldialog": [[5, 2, 1, "", "PanelDialog"]], "diffpy.pdfgui.gui.wxextensions.paneldialog.PanelDialog": [[5, 3, 1, "", "setPanel"]], "diffpy.pdfgui.gui.wxextensions.textctrlutils": [[5, 1, 1, "", "textCtrlAsGridCell"]], "diffpy.pdfgui.gui.wxextensions.validators": [[5, 2, 1, "", "TextValidator"]], "diffpy.pdfgui.gui.wxextensions.validators.TextValidator": [[5, 3, 1, "", "Clone"], [5, 3, 1, "", "OnChar"], [5, 3, 1, "", "TransferFromWindow"], [5, 3, 1, "", "TransferToWindow"], [5, 3, 1, "", "Validate"]], "diffpy.pdfgui.tui": [[0, 2, 1, "", "LoadProject"]], "diffpy.pdfgui.tui.LoadProject": [[0, 3, 1, "", "getCalculations"], [0, 3, 1, "", "getDataSets"], [0, 3, 1, "", "getDopings"], [0, 3, 1, "", "getFits"], [0, 3, 1, "", "getPhases"], [0, 3, 1, "", "getTemperatures"], [0, 3, 1, "", "load"], [0, 3, 1, "", "save"]], "diffpy.pdfgui.utils": [[0, 1, 1, "", "asunicode"], [0, 1, 1, "", "numericStringSort"], [0, 1, 1, "", "safeCPickleDumps"]]}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "function", "Python function"], "2": ["py", "class", "Python class"], "3": ["py", "method", "Python method"], "4": ["py", "exception", "Python exception"], "5": ["py", "property", "Python property"], "6": ["py", "attribute", "Python attribute"]}, "objtypes": {"0": "py:module", "1": "py:function", "2": "py:class", "3": "py:method", "4": "py:exception", "5": "py:property", "6": "py:attribute"}, "terms": {"": [0, 2, 3, 5, 7, 8, 9, 11], "0": [0, 2, 3, 5, 7, 9, 11], "001": 2, "0025": 9, "004": [9, 11], "01": 9, "028": 9, "0304391": [8, 9], "04": 9, "0486": 9, "0520547": [7, 8, 9], "08": 9, "0b": 9, "1": [2, 3, 5, 7, 8, 9], "10": [2, 9], "100": [2, 9, 11], "1000": 9, "101": 2, "102": 2, "1024": 2, "1050k": 9, "11": [2, 9], "1100k": 9, "1150": 9, "1150k": 9, "12": [2, 9, 10], "13": [9, 10], "14": 9, "17": 7, "1792": 9, "19": [7, 8, 9, 11], "1999": 11, "1_copi": [9, 11], "2": [2, 3, 5, 7, 8, 9], "20": 9, "200": 9, "2006": [8, 9], "2007": [7, 8, 9, 11], "2008": [8, 9], "2009": 9, "2012": [8, 9], "2013": [8, 9], "2016": 9, "2017": [8, 9], "2023": 9, "2024": 11, "2025": 7, "2048": 2, "2081": 3, "21": 9, "22": 9, "225": [9, 11], "23": 9, "249": 9, "25": 9, "256": 2, "28": 9, "2d": [2, 9], "3": [2, 3, 7, 9], "30": 9, "300": 9, "300k": 9, "32": [9, 11], "33": 9, "335219": [7, 8, 9, 11], "35": 9, "3a": 11, "3d": [2, 9], "3m": [9, 11], "3nm": 9, "4": [2, 9, 10], "5": [3, 9, 11], "512": 2, "52": 9, "550k": 9, "572": 11, "575": 11, "6": [2, 9], "64": 9, "650k": 9, "69": 9, "7": [2, 9], "700": 9, "700k": 9, "720k": 9, "730k": 9, "740k": 9, "750k": 9, "77": 9, "8": [2, 9, 10], "800k": 9, "880k": 9, "9": [2, 9, 10, 11], "90": 9, "9780198885801": 11, "98": 3, "980k": 9, "A": [2, 3, 5, 8, 9, 11], "AND": [8, 9], "AS": [8, 9], "As": [2, 8, 9, 11], "BE": [8, 9], "BUT": [8, 9], "BY": [8, 9], "Be": 3, "But": [8, 9], "By": [0, 2, 9, 11], "FOR": [8, 9], "For": [2, 3, 7, 8, 9, 11], "IF": [8, 9], "IN": [8, 9], "If": [2, 3, 5, 7, 8, 9, 11], "In": [3, 9, 11], "It": [2, 3, 5, 7, 9, 11], "Its": 9, "NO": [8, 9], "NOT": [8, 9], "No": [0, 2, 3, 9], "Not": 9, "OF": [8, 9], "ON": [8, 9], "OR": [8, 9], "On": 9, "One": 9, "SUCH": [8, 9], "Such": 9, "THE": [8, 9], "TO": [8, 9], "That": 3, "The": [0, 1, 2, 3, 5, 7, 8, 9, 10, 11], "Then": [9, 11], "There": [2, 3, 9], "These": [2, 3, 9], "To": [2, 3, 5, 7, 9, 11], "With": 11, "_": 3, "____": 3, "__customproperti": 3, "__definelocalid": 3, "__fitrepr": 2, "__initi": 2, "__insertbranch": 3, "__lh": 2, "_col": 3, "_core": 3, "_excluded_method": 3, "_focusedtext": [3, 5], "_linear_interpol": 2, "_plotcount": 2, "_project": 0, "_rcalc_chang": 2, "_row": 3, "_selectedcel": 3, "_tmpdir": 2, "a1": 2, "a2": 2, "abnorm": 9, "about": [3, 9, 10, 11], "abov": [2, 3, 8, 9, 11], "absent": 10, "absolut": [2, 3], "academ": 11, "accent": 9, "accept": [3, 9], "access": [0, 2, 3, 9], "accommod": [2, 9], "accompani": 9, "accomplish": 9, "accord": [0, 3, 9], "accordingli": [3, 9], "account": 9, "accuraci": 2, "achiev": 9, "acknowledg": [7, 8, 9], "across": [3, 9, 11], "action": [3, 9], "activ": [2, 3, 9, 11], "actual": [3, 9], "ad": [2, 3, 9, 10, 11], "add": [2, 3, 5, 9, 11], "addcalc": 3, "adddata": 3, "adddataset": 3, "addfit": 3, "addingdata": 3, "addingphas": 3, "addit": [2, 3, 9], "addphas": 3, "adequaci": 8, "adjust": [2, 5, 9], "adp": 9, "advanc": [9, 11], "advis": [8, 9], "affect": [3, 9], "after": [2, 3, 5, 9], "afterward": 9, "again": [5, 9, 11], "against": 9, "agreement": 8, "aim": 9, "alamo": 9, "align": 10, "all": [0, 2, 3, 5, 8, 9, 11], "alldebugopt": 3, "alloc": [2, 9], "allow": [2, 3, 5, 9, 11], "allowneg": 5, "along": [2, 9], "alpha": 9, "alreadi": [3, 9, 11], "also": [2, 3, 9, 11], "alter": [3, 5], "altern": [9, 11], "although": 9, "alwai": [3, 9, 11], "among": 9, "amount": 11, "an": [0, 2, 3, 5, 9, 11], "anaconda": 9, "analysi": [7, 8, 9, 11], "analyt": 9, "analyz": 9, "angl": [2, 3, 9], "angstrom": [2, 9], "ani": [2, 3, 5, 7, 8, 9, 11], "anisotrop": 9, "anisotropi": 9, "anoth": [2, 3, 9, 11], "anyth": 3, "anywher": [3, 9], "api": [3, 7, 9], "app": 3, "appar": 9, "appear": [3, 9, 11], "append": [2, 3], "appendstep": 2, "appl": 11, "appli": [2, 3, 7, 9], "applic": [0, 2, 3, 7, 9], "applycellchang": 3, "applypairselect": 2, "applyparamet": 2, "applysymmetryconstraint": 2, "applytextctrlchang": 3, "approach": 9, "appropri": [3, 9], "approxim": 9, "april": 9, "ar": [0, 2, 3, 7, 8, 9, 10, 11], "arbitrari": [9, 11], "architectur": 9, "archiv": 9, "arg": [2, 3, 5], "argonn": 9, "argstr": 2, "argument": [1, 2, 3, 9], "argv1": 1, "aris": [8, 9], "arithmet": 9, "arm64": 10, "around": 9, "arrai": [2, 9], "arrang": 9, "array_lik": 2, "artifact": 9, "artist": 10, "ascii": 0, "ask": [1, 3, 7, 8, 9], "aspect": [3, 9], "assign": [2, 3, 9, 11], "associ": [2, 3, 5, 9, 11], "assum": [3, 9], "asunicod": 0, "asymmetr": [9, 11], "atom": [2, 3, 7, 9, 11], "atomey": [3, 9], "atomeye_dir": 9, "atomlist": 2, "attempt": [3, 9], "attribut": [1, 2, 3, 5, 9], "author": [3, 8, 9], "auto": [2, 5], "autom": 9, "automat": [2, 3, 5, 9], "autosizelabel": 5, "autowidthlistctrl": 5, "avail": [2, 3, 9], "averag": [2, 9], "avoid": [9, 10], "awai": 9, "ax": 3, "axi": [2, 3, 9], "b": [2, 9, 11], "bachmann": 9, "back": [0, 2, 3, 9], "background": [2, 10], "backward": 2, "banerje": 11, "bar": [3, 9], "base": [0, 2, 3, 5, 9, 10], "basenam": 2, "basic": [2, 9], "bat": 9, "batch": 9, "becaus": [2, 9, 11], "becom": 9, "been": [2, 3, 9], "befor": [2, 3, 5, 9, 11], "begin": [3, 5, 9], "behav": [3, 9], "behavior": [3, 5, 9], "behind": 9, "being": [3, 9], "belong": 9, "below": [2, 3, 9, 11], "benefit": [2, 9], "benjamin": 11, "berri": 9, "best": [9, 11], "beta": 9, "between": [2, 3, 8, 9, 10, 11], "beyond": 9, "bg": 10, "billing": [7, 8, 9, 10, 11], "bin": 9, "binari": [8, 9], "bit": [9, 11], "black": 9, "blank": [2, 3, 9, 11], "bloch": [7, 8, 9, 11], "block": 3, "blue": 11, "bmultidata": 2, "bmultistep": 2, "board": [8, 9], "bodi": [8, 9], "bold": 3, "bond": [2, 3, 9], "book": 11, "bookkeep": 9, "bool": [2, 3, 5, 9], "boolean": [1, 3], "both": [2, 3, 9], "bottom": 9, "bound": [2, 3, 5, 9], "boundari": [2, 9], "box": [3, 9, 10, 11], "boxcar": 9, "bozin": [7, 8, 11], "bo\u017ein": [7, 9], "bpaus": 2, "branch": 3, "brief": 9, "briefli": 9, "bring": [3, 9], "broad": 9, "broaden": [2, 9], "broken": [2, 9], "brookhaven": [8, 9], "brought": 10, "browser": 3, "bryndin": [7, 8, 9, 11], "bsd": 9, "bshow": 2, "bug": [3, 9, 10], "build": [2, 3, 7, 9, 10], "buildlinestyl": 2, "buildlinesymbolstyl": 2, "buildnamedict": 2, "buildsymbolstyl": 2, "built": [7, 9], "builtin": 9, "bulk": 9, "bull": 9, "burden": 9, "busi": [8, 9], "button": [3, 9, 11], "byte": [0, 10], "c": [2, 7, 8, 9, 11], "ca": 9, "cach": 2, "calc": [2, 3], "calcul": [0, 3, 9], "calibr": 9, "call": [2, 3, 5, 9, 11], "callabl": 2, "can": [2, 3, 5, 7, 8, 9, 11], "cancel": [3, 5], "cancopyselectedcel": 3, "candid": 9, "cannot": [2, 3, 9], "canpasteintocel": 3, "canva": 3, "capabl": [5, 7, 9], "captur": 3, "car": 9, "care": [2, 3, 9], "carefulli": 11, "carri": [9, 11], "case": [2, 3, 9, 11], "catch": [1, 3, 5, 9], "catchfunctionerror": 3, "catchobjecterror": 3, "caught": 3, "caus": [8, 9], "caution": 9, "cc": 11, "cctbx": 9, "cd": 9, "cdata": 3, "cdse": 9, "cell": [2, 3, 5, 9, 11], "center": 3, "certain": [2, 3, 9, 11], "cfg": 2, "chain": 9, "chang": [2, 3, 5, 8, 9, 10, 11], "changedid": 2, "changeparameterindex": 2, "changestyl": 3, "channel": 9, "chapter": 9, "charact": 9, "characterist": 9, "charg": 3, "check": [2, 3, 5, 9, 10, 11], "checkconfigur": 3, "checkforsav": 3, "checkqueu": 2, "chemic": 9, "chemistri": 9, "child": 3, "children": 3, "choic": [3, 9], "choos": [9, 11], "chose": 3, "chri": 7, "ci": [9, 10], "cif": [2, 9, 11], "cite": [7, 8, 9], "citi": [8, 9], "cl": 2, "class": [0, 2, 3, 5], "classdoc": 3, "clean": 2, "cleanup": 9, "clear": [2, 3, 5], "clearli": 9, "clearrefin": 2, "clearselect": 5, "clearsigint": 3, "cleartext": 3, "click": [3, 5, 9, 11], "clickabl": 9, "clipboard": 3, "clone": [5, 9], "close": [2, 3, 9], "close_kei": 3, "cmd": 3, "cmdarg": [1, 3], "cmdopt": [1, 3], "cmi": 11, "co": 11, "code": [3, 8, 9, 10], "codecov": 10, "codespel": 10, "coeffici": 9, "col": [3, 5], "collabor": [8, 9], "collat": 9, "collect": [0, 3, 5, 8, 9], "color": [3, 10], "columbia": [7, 8, 9], "column": [3, 5, 9, 11], "columnsortermixin": 5, "columnsortlistctrl": 5, "com": [7, 9, 11], "combin": 9, "combobox": 3, "come": [2, 3, 7, 9], "comfort": 9, "comma": 2, "command": [1, 3, 7, 9], "comment": [9, 11], "commit": [8, 9, 10], "common": [2, 3, 9], "commonli": 9, "commun": [3, 8, 9], "compact": 3, "compar": [2, 3, 9], "comparison": 0, "compat": [2, 3], "compil": 9, "complet": 9, "complex": [9, 11], "compli": 10, "complic": 9, "compon": 9, "composit": 9, "comput": [2, 7, 8, 9, 11], "con": 9, "concentr": 9, "conclus": [7, 8, 9], "conda": [9, 10, 11], "conden": [7, 8, 9, 11], "condit": [2, 8, 9], "config": [2, 3, 9], "configpars": 10, "configur": [2, 3, 9, 10, 11], "configurationpars": 3, "confirm": [3, 5, 9], "confus": 9, "connect": [2, 3, 9], "consequenti": [8, 9], "consid": 3, "consist": [2, 3, 9], "consol": 3, "consolid": 9, "constant": 9, "constitut": 9, "constrain": [2, 3, 9, 11], "constraint": [3, 9, 11], "constraint_inst": 2, "constructor": 2, "consult": 9, "contact": 9, "contain": [0, 1, 2, 3, 5, 9, 11], "content": [2, 3, 9], "context": [9, 11], "continu": [1, 11], "contract": [8, 9], "contrast": 9, "contribut": [8, 9], "contributor": [7, 8, 9], "control": [0, 1, 3, 7, 8, 9, 11], "controlcent": 2, "controlconfigerror": 2, "controldata": 3, "controlerror": 3, "controlfileerror": 2, "controlindexerror": 2, "controlkeyerror": 2, "controlnam": 3, "controlruntimeerror": 2, "controlstatuserror": 2, "controlsyntaxerror": 2, "controltypeerror": 2, "controlvalueerror": 2, "convei": 9, "conveni": [3, 5, 7, 9], "convent": 9, "converg": 9, "convers": [9, 10], "convert": [0, 2, 9], "cookiecut": 10, "coordin": [2, 3, 9, 11], "copi": [2, 3, 5, 9, 11], "copyabl": 3, "copybranch": 3, "copyright": [8, 9], "copyselectedcel": 3, "correct": [2, 9], "correctli": [2, 9], "correl": 9, "correspond": [2, 3, 9], "corrupt": 2, "could": [2, 9, 11], "count": 9, "cousin": 3, "cover": 9, "coverag": [9, 10], "cp": 3, "crash": 9, "creat": [0, 2, 3, 7, 9], "creation": 9, "creativ": 9, "cross": 9, "crossov": 9, "crw": 2, "crystal": [7, 8, 9], "crystallin": 9, "crystallogr": 11, "crystallograph": [9, 11], "crystallographi": 9, "csca": 9, "ctrl": [3, 9], "ctrlunpickl": 2, "cubic": [9, 11], "cumul": [2, 9], "curiou": 9, "current": [2, 3, 5, 7, 9], "cursor": [9, 11], "curv": [2, 3, 9, 11], "curveref": 3, "custom": [2, 3, 5], "custom_spacegroup": 2, "cut": 9, "cutoff": 9, "cygwin": 9, "d": [2, 3, 7, 8, 9, 11], "d_": 2, "d_data1": 2, "d_data2": 2, "daemon": 2, "damag": [8, 9], "damp": [2, 9], "dampen": 9, "dans": [7, 8, 9], "data": [0, 2, 3, 5, 7, 8, 9, 11], "databas": 9, "datachang": 2, "datanam": 2, "datanamedict": 2, "dataset": [0, 2, 3, 9, 11], "datastr": 2, "datataset": 2, "date": 10, "db": [1, 9], "dbopt": 1, "ddp": [9, 10], "ddp3": 10, "deal": 9, "deblank": 2, "debug": [1, 3, 9], "debugg": [1, 3, 9], "decad": 2, "decemb": 9, "decim": [0, 9], "deed": 2, "default": [0, 2, 3, 5, 9, 11], "defin": [0, 2, 3, 9, 10, 11], "definit": [2, 9], "degre": 9, "delet": [2, 3, 9], "deleteatom": 2, "deletebranch": 3, "delic": 9, "delimit": 3, "delt": 9, "delta1": [2, 9], "delta2": [2, 9, 11], "demonstr": 9, "depart": 7, "depend": [2, 3, 9, 10, 11], "deprec": 10, "dequeu": 2, "deriv": [3, 7, 8, 9], "describ": [2, 9], "descript": [2, 9, 11], "deselect": 5, "design": [0, 3, 5, 7, 9], "desir": [2, 9], "desktop": 9, "despit": 9, "detail": [3, 7, 9, 11], "determin": [3, 9], "deuterium": 9, "dev": 9, "develop": [5, 8, 9], "deviat": 2, "dg": 9, "dgcalc": 2, "dgob": 2, "dgr": 9, "dgtrunc": 2, "diagram": 3, "dialog": [3, 5, 9, 10, 11], "dialogabout": 3, "diamet": [2, 9], "dict": 2, "dictionari": [2, 3, 5], "did": 11, "differ": [2, 3, 9, 11], "differenti": 9, "difficult": 9, "diffpi": [8, 9, 10, 11], "diffract": [7, 9], "diffractomet": 9, "digit": 5, "dimension": 9, "diminish": 9, "direct": [2, 8, 9], "directli": [3, 9], "directori": [2, 3, 9], "disabl": [1, 3, 9], "disablemainmenuitem": 3, "disablesharedmenuitem": 3, "disallow": 9, "disclaim": [8, 9], "discuss": 9, "disord": 9, "displac": [2, 9], "displai": [1, 3, 9], "distanc": 9, "distort": 9, "distribut": [1, 7, 8, 9, 11], "divid": 2, "dmitrii": 7, "dmr": [7, 8, 9], "do": [2, 3, 7, 8, 9, 11], "doc": 9, "dockabl": 9, "docstr": 2, "document": [3, 8, 9, 10], "doe": [2, 3, 5, 9, 11], "doesn": [2, 3], "domest": 8, "don": [2, 11], "done": [2, 3, 8, 9, 11], "dopant": [2, 3, 9], "dope": [0, 2, 3, 9, 10], "doubl": [3, 11], "down": [3, 9, 11], "download": [9, 11], "dpp": [1, 9], "dr": 9, "drag": [9, 11], "draw": [2, 3], "drawn": 2, "drob": 2, "drop": 9, "dropdown": 11, "dry": 2, "dsca": 9, "dscale": [2, 3, 9], "dseri": 3, "due": [2, 3, 9], "dummi": 9, "dump": 0, "dup": 2, "duplic": 9, "dure": [3, 9, 10], "dynam": [3, 9], "dynamicpanel": 3, "e": [2, 7, 8, 9], "each": [0, 2, 3, 8, 9, 11], "earlier": 9, "eas": 9, "easi": [1, 7, 9, 11], "easier": [3, 9], "easili": 9, "easy_instal": 9, "edit": [3, 5, 9, 11], "editor": 3, "edu": [8, 9], "effect": 9, "either": [2, 3, 8, 9, 11], "elect": 11, "elem": [9, 11], "element": [2, 3, 9, 11], "elimin": 3, "els": 3, "elsewher": [3, 9], "email": 8, "emil": [7, 11], "emphas": 9, "empti": [2, 3, 9, 11], "en": 11, "enabl": 3, "enablewidget": 3, "encapsul": 9, "encourag": 5, "encrypt": 9, "end": [2, 3, 7], "endors": [8, 9], "engin": [2, 3, 7, 9], "enhanc": 9, "enlarg": 9, "enqueu": 2, "ensur": [9, 11], "enter": [2, 3, 5, 9, 11], "entir": [1, 8, 9, 11], "entireti": [8, 9], "entri": [1, 2, 3, 5, 9, 11], "entryfit": 3, "entryphas": 3, "entrypoint": 3, "entryset": 3, "enumer": 9, "env": 10, "envelop": 9, "environ": [3, 9, 11], "equal": [2, 9], "equat": [2, 9, 11], "equival": [2, 9, 11], "eras": [2, 3], "error": [1, 2, 3, 9, 10], "errorreportdialog": 1, "errorreportdialogcontrolfix": 3, "esc": [3, 5], "essenti": [3, 9], "establish": 9, "estim": 2, "etc": [9, 11], "evalformula": 2, "evalu": 2, "even": [3, 8, 9], "event": [3, 5, 8, 9], "everi": 9, "everyth": [2, 3, 9], "evolv": 9, "evt": [3, 5], "evt_key_down": [3, 5], "ex": 9, "exactli": 3, "exampl": [2, 3, 5, 9, 11], "except": [0, 1, 2, 3, 9], "exclud": [1, 2, 3, 9], "execut": [1, 2, 9], "exemplari": [8, 9], "exercis": 9, "exhibit": 9, "exist": [2, 3, 9, 11], "exit": [1, 2, 3, 9], "expand": [2, 9, 11], "expandasymmetricunit": 2, "expandsupercel": 2, "expans": [2, 3, 9, 11], "expect": [2, 3], "experi": [7, 8, 9], "experiment": [2, 9, 11], "expert": 9, "expertis": 7, "explain": 9, "explan": 9, "explor": 9, "expon": 0, "exponenti": 9, "export": [2, 3, 9], "express": [7, 8, 9, 11], "expressli": 8, "exten": 9, "extend": [3, 9], "extendedtoolbar": 3, "extendprojecttre": 3, "extens": [3, 5, 7, 9, 11], "extent": 9, "extern": [2, 3, 9], "extra": 9, "extract": [0, 3, 9, 11], "f": [2, 9, 11], "f_": 2, "f_fit": 2, "facil": 9, "fact": [3, 9], "factor": [2, 9, 11], "factori": 2, "failur": [2, 9], "fall": 0, "fals": [1, 2, 3, 5, 10], "familiar": 9, "far": 9, "farrow": [7, 8, 9, 11], "fast": 9, "fastback": 9, "fastforward": 9, "fcc": [9, 11], "featur": [1, 9], "februari": [7, 8, 9], "fed": 9, "feedstock": 10, "feel": [3, 9, 11], "few": 9, "fft": 9, "fgr": 9, "field": 9, "fifth": 9, "figur": [2, 3, 9], "file": [0, 1, 2, 3, 7, 8, 9, 10, 11], "fileformat": 2, "filehistori": 3, "filenam": [0, 2, 3, 9], "filesav": 3, "fill": [3, 5, 9, 11], "fillcel": 3, "filllist": 3, "final": 9, "find": [2, 7, 8, 9, 10, 11], "findparamet": 2, "findprefix": 5, "finish": 2, "finit": 9, "first": [2, 5, 9, 11], "firstflag": 2, "fist": 2, "fit": [0, 1, 3, 7, 8, 9], "fit1": 11, "fitdataset": 0, "fitnam": [2, 3], "fitrmax": [2, 3], "fitrmin": [2, 3], "fitrstep": 2, "fitstructur": 0, "fittreeerror": 3, "five": [3, 9], "fix": [2, 3, 9, 10, 11], "fixed_pair_str": 2, "flag": [1, 2, 3, 5, 9, 10], "flexibl": 9, "float": [0, 2, 3, 5, 9], "float2str": 3, "fm": [9, 11], "focu": 9, "focus": 3, "folder": [9, 10], "follow": [2, 3, 7, 8, 9], "font": 9, "footnot": 9, "forc": 2, "forciabl": 2, "forcibli": 2, "foreign": 8, "forg": 10, "fork": 9, "form": [2, 3, 5, 8, 9], "formal": 9, "format": [2, 3, 9, 11], "former": [7, 9], "formula": [2, 3], "fortran": 9, "forum": 9, "forward": [3, 8, 9], "found": [2, 7, 9, 10], "foundat": [7, 8, 9], "four": [9, 11], "fourier": 9, "fraction": [2, 9, 11], "frame": 3, "frandsen": 11, "free": [3, 9, 11], "freedom": 8, "freeli": 9, "frequent": 9, "frexp": 0, "friendli": [7, 9], "from": [0, 2, 3, 7, 8, 9, 10, 11], "front": 7, "full": [2, 3, 7, 8, 9, 11], "fulli": 11, "fullpath": 3, "funcnam": 3, "function": [1, 2, 3, 5, 7, 9, 11], "fund": [7, 8, 9], "furnish": 9, "further": 9, "furthermor": 9, "futur": [3, 9], "g": [2, 9], "gamm": 9, "gamma": 9, "gaussian": [2, 9], "gcalc": [2, 9, 11], "gdiff": 2, "gear": [9, 11], "gem": 9, "gener": [0, 2, 9, 11], "get": [0, 2, 3, 5, 7, 9, 10, 11], "getalltyp": 3, "getbranchnam": 3, "getcalcul": [0, 2, 3], "getchildren": 3, "getclipboard": 3, "getconfig": 2, "getcontroldata": 3, "getctrllett": 3, "getdata": 2, "getdataset": [0, 2, 3], "getdop": 0, "getengineexcept": 2, "getengineoutput": 2, "getfileformat": 2, "getfit": 0, "getfitroot": 3, "getfitsamplingtyp": 2, "getlastdataset": 3, "getlastphas": 3, "getlistctrl": 5, "getmetadata": 2, "getmetadatanam": 2, "getmno": 3, "getnodetyp": 3, "getnumdataset": 3, "getnumphas": 3, "getnyquistsampl": 2, "getobssampl": 2, "getoffset": 3, "getopterror": 1, "getpairselectionflag": 2, "getphas": [0, 3, 9], "getposflag": 3, "getpositioninsubtre": 3, "getselectedindic": 2, "getselectedpair": 2, "getselectedparamet": 3, "getselectedyv": 3, "getserv": 2, "getsibl": 3, "getspacegroup": [2, 3], "getspacegrouplist": [2, 3], "getstructur": 2, "getstructureview": 2, "gettemperatur": [0, 9], "gettempflag": 3, "gettreeitemdict": 3, "getvar": 2, "getxnam": 2, "getynam": 2, "gh": 10, "git": [8, 9], "github": [7, 9], "give": [3, 9, 11], "given": [2, 3, 9], "global": [2, 3, 11], "go": [2, 3, 9], "goal": 9, "gob": [2, 9], "goe": [2, 3, 11], "good": [8, 9], "googl": [3, 9], "gppd": 9, "gr": [2, 9, 11], "gracefulli": 3, "grai": 3, "grant": [7, 8, 9], "graph": [2, 3, 7], "graphic": [1, 3, 7, 9], "greater": 9, "green": [3, 11], "grei": 11, "grid": [2, 3, 5, 9, 10, 11], "grid_interpol": [2, 10], "gridatom": 3, "gross": 9, "group": [2, 3, 7, 8, 9, 10, 11], "gt": [3, 9], "gtrunc": [2, 11], "guess": [2, 3, 9], "gui": [0, 2, 7, 9, 10, 11], "guid": 9, "h": [1, 9], "ha": [1, 2, 3, 5, 8, 9, 10, 11], "had": 9, "hand": 3, "handl": [1, 2, 3, 9], "handleengineexcept": 2, "handler": [2, 3], "happen": [2, 9, 11], "hard": 9, "hascalcul": 2, "hasdataset": 2, "hasstructur": 2, "have": [2, 3, 5, 7, 8, 9, 11], "header": [5, 9, 11], "held": [2, 3, 8, 9], "help": [1, 3, 7, 9, 11], "henc": 9, "here": [3, 7, 9, 11], "hidden": 3, "hide": [2, 3], "hierarchi": 2, "high": 9, "higher": 9, "highest_protocol": 0, "highli": 9, "highlight": [0, 3, 5, 9], "hint": 9, "histor": 2, "histori": 9, "hit": [9, 11], "hold": [2, 3, 9, 11], "holder": [8, 9], "home": 3, "homepag": 9, "hope": 9, "host": [8, 9], "hot": 9, "hover": 11, "how": [3, 9, 11], "howev": [8, 9, 11], "html": 3, "http": [3, 7, 8, 9, 11], "i": [0, 1, 2, 3, 5, 7, 8, 9, 11], "icon": [0, 3, 7, 9, 11], "iconfilenam": 3, "iconpath": 3, "id": [2, 3, 5, 9], "id_cancel": 3, "id_no": 3, "id_y": 3, "idataset": 2, "idea": 9, "ideal": 9, "ident": [5, 9], "identifi": [2, 9], "idlist": 2, "idnmrf": 2, "idx": 2, "ignor": [0, 2, 3, 9], "ij": 9, "illustr": 9, "imag": [9, 10], "imaginari": 9, "immun": 3, "imperfect": 2, "implement": [3, 5, 9], "impli": [8, 9], "implicitli": 11, "import": [3, 8, 9], "impos": 9, "improv": 9, "inabl": 10, "incident": [8, 9], "includ": [2, 7, 8, 9, 10], "incompat": [3, 10], "incorrect": 10, "incorrectli": 9, "increas": [2, 9], "increasingli": 9, "increment": [3, 9], "incrementnam": 3, "inde": 9, "independ": [3, 9], "index": [2, 3, 7, 9, 11], "indexorrang": 2, "indic": [1, 2, 3, 8, 9], "indirect": [8, 9], "individu": [3, 8, 9], "inf": 0, "infer": 9, "info": [1, 2, 3], "inform": [2, 3, 8, 9, 11], "infring": 8, "inherit": [2, 9], "initi": [2, 3, 5, 7, 9, 11], "initializesort": 5, "initializetre": 3, "initialstr": 2, "initialvalu": 2, "inplac": 0, "input": [3, 5, 9, 11], "insert": [2, 3, 9, 11], "insertaft": 3, "insertatom": 2, "insertcurv": 3, "insertitem": 10, "insid": [2, 11], "instabl": 9, "instal": [3, 9, 10], "instanc": [0, 2, 3, 9], "instead": [3, 5, 8, 9, 10], "institut": [8, 9], "instruct": [9, 10, 11], "instrument": 9, "int": [2, 3], "integ": [0, 2, 3, 9, 11], "integr": [1, 9], "intend": 9, "intens": 9, "intent": 9, "inter": 9, "interact": [2, 3], "interest": [3, 9], "interfac": [0, 1, 2, 3, 7, 9], "interfer": 9, "intermedi": 9, "intern": [2, 3, 9], "interp": 10, "interpol": [2, 9, 10], "interpret": 9, "interrupt": [8, 9], "introduc": 9, "introduct": 9, "introspect": 9, "invalid": [1, 2, 3], "invers": [2, 9], "investig": 9, "invok": [2, 9], "io": 9, "iphas": 2, "ipn": 9, "irrecover": 2, "isalia": 3, "isalt": 3, "isi": 9, "isotop": 9, "isotrop": 9, "isspacegroupposs": 2, "issu": [9, 10], "isthreadrun": 2, "item": [2, 3, 5, 9], "itemdata": 5, "itemdatamap": 5, "itemtext": 5, "iter": [3, 9], "its": [2, 3, 5, 8, 9, 11], "itself": [2, 5], "j": [2, 3, 7, 8, 9, 11], "jahn": 9, "jensen": 11, "ji": 2, "jiwu": 7, "jk": 2, "job": 3, "join": 2, "jounaltextctrl": 3, "journal": [3, 9], "jt": 9, "juha": [7, 8, 9, 11], "juh\u00e1": 9, "jump": 9, "just": [2, 3, 9, 10, 11], "k": [2, 9], "karl": 9, "keep": [3, 9], "kei": [0, 2, 3, 5, 9], "kept": 2, "keyboard": [3, 9], "keyerror": 2, "keyeventslistctrl": 5, "keyword": 2, "kick": 3, "kirsten": 11, "know": [3, 11], "knowledg": 9, "known": [3, 9], "koch": 11, "kunstlev": 9, "kwarg": [2, 3, 5], "kwd": [3, 5], "l": [7, 8, 9, 11], "label": [3, 5, 10], "laboratori": [8, 9], "lambda": 2, "lambdaformula": 2, "lamno3": 9, "lang": 11, "languag": 9, "lansc": 9, "larg": 9, "larger": [2, 9], "last": [2, 3, 7, 9], "lat": [2, 9], "later": [3, 9, 11], "latest": [2, 9, 10], "lattic": [2, 9, 11], "launch": [2, 3, 9], "launchbrows": 3, "launcher": 9, "layout": [9, 11], "lb": 2, "lcmo": 9, "lconstraintsmap": 3, "ldquo": 9, "lead": [7, 8, 9], "learn": [9, 11], "least": 3, "leav": 9, "left": [2, 3, 9, 11], "legal": [2, 9], "legend": [3, 10], "legendboxproperti": 3, "len": [2, 9], "length": [2, 3, 9], "lesson": 7, "let": [3, 9, 11], "letter": [3, 5, 9], "level": [3, 9], "li": 9, "liabil": [8, 9], "liabl": [8, 9], "librari": [1, 9], "licens": [7, 9], "light": 3, "like": [9, 11], "limit": [3, 8, 9], "line": [1, 2, 3, 7, 9], "linear": [2, 9], "linestyl": 10, "linesymbol": 2, "link": [2, 3, 9, 10, 11], "lint": 10, "linux": 9, "lionel": 9, "list": [0, 1, 2, 3, 5, 7, 8, 9, 11], "listctrl": 3, "listctrlautowidthmixin": 5, "listctrlfil": 10, "liu": [7, 8, 9, 11], "lmo": 9, "lmo_refined_c": 9, "lo": 9, "load": [0, 2, 3, 9, 11], "loadconfigur": 3, "loaddataset": 2, "loadproject": [0, 9], "loadstructur": 2, "local": [2, 3, 9, 10], "localhost": 9, "locat": [3, 9, 11], "lock": [2, 3], "log": [8, 9, 10], "logic": [3, 9, 11], "long": [3, 9, 11], "longer": 9, "look": [9, 11], "loop": 9, "loos": 9, "loss": [8, 9], "lost": 9, "low": [2, 9], "lower": [2, 9, 11], "lowest": 3, "lsquo": 9, "lst": 0, "lt": 9, "m": [3, 9, 10], "mac": 9, "maco": 10, "macro": [2, 3, 9], "macromolecular": 9, "made": [3, 9], "mai": [0, 2, 3, 8, 9, 11], "mail": 9, "main": [1, 7, 9], "maintain": [2, 8, 9], "major": 9, "make": [2, 3, 5, 9, 10, 11], "makedata": 3, "makedopingseri": 2, "makeidm": 5, "makerseri": 2, "maketemperatureseri": 2, "maketreeselect": 3, "manag": [2, 9], "mani": [1, 7, 8, 9], "manipul": [3, 9], "manual": [3, 7, 10, 11], "map": [2, 3], "march": 9, "mark": [2, 9], "master": 9, "match": [2, 5, 10], "materi": [7, 8, 9], "math": [2, 9, 11], "mathemat": 7, "matplotlib": [3, 9, 10], "matrix": 9, "matter": [7, 8, 9, 11], "matur": 9, "maxfirst": 2, "maximum": [2, 9], "maxlast": 2, "maxstep": 2, "maxwel": 11, "mean": [2, 3, 9, 11], "meaning": 11, "meant": [3, 9], "mega": 5, "member": [2, 3, 5], "memori": 9, "mention": 9, "menu": [3, 7, 9, 11], "menubar": 3, "merchant": [8, 9], "messag": [1, 3, 8, 9], "met": [8, 9], "meta": [2, 9], "metadata": [2, 9], "method": [1, 2, 3, 5, 9], "michigan": [8, 9], "middl": [2, 3, 9], "might": 5, "mimic": 9, "mind": [3, 9], "minfirst": 2, "miniforg": 10, "minim": 9, "minimum": 2, "minlast": 2, "minstep": 2, "mirror": 3, "miscellan": 3, "mismatch": 2, "miss": 9, "mit": 9, "mitchel": 9, "mix": [3, 11], "mixin": 5, "mmlib": 9, "mn": 9, "mno": 2, "modal": 3, "mode": [3, 9], "model": [2, 7, 8, 9], "modif": [8, 9], "modifi": [1, 3, 9], "modul": 9, "modular": 9, "momentum": 9, "monolith": [5, 9], "more": [1, 2, 3, 8, 9, 11], "most": [3, 9], "motion": 9, "mous": [3, 9, 11], "move": [2, 3, 5, 8, 9], "mpl": [3, 10], "mplkeypress": 3, "mru": 3, "much": [9, 11], "multi": [7, 9], "multipl": [1, 2, 9, 11], "multipli": 2, "multistag": 9, "multitask": 9, "mundan": 9, "must": [2, 3, 5, 8, 9], "myapp": 3, "myfram": 3, "myself": 2, "n": [2, 3, 9, 11], "n1": [9, 11], "n2": [9, 11], "n3": [9, 11], "na": 2, "name": [2, 3, 5, 8, 9, 11], "namelist": 3, "nan": [0, 9], "nano": 9, "nanoparticl": 9, "nanoscal": 9, "nanostructur": [7, 8, 9, 11], "nation": [7, 8, 9], "nativ": 9, "natom": 2, "navig": [9, 11], "navigationtoolbar2wx": 3, "nbsp": 9, "ndarrai": 2, "nearest": 9, "necess": 7, "necessari": [3, 9], "necessarili": [7, 8, 9], "need": [2, 3, 9, 10], "needssav": 3, "neg": 5, "neglect": 2, "neglig": [8, 9], "neighbor": 9, "neither": [8, 9], "net": [3, 9], "neutron": [7, 8, 9], "new": [2, 3, 7, 8, 9, 10, 11], "new_nam": 2, "newcalcul": 2, "newer": 9, "newfit": 2, "newidx": 2, "newli": 3, "newlin": 3, "newnam": 2, "newstructur": 2, "next": [2, 3, 5, 9], "ni": [7, 9], "nice": [1, 3], "nickel": 11, "nocf": [1, 3, 9], "noconfirm": 3, "node": [3, 9], "noed": [1, 3, 9], "noerrordialog": 3, "nois": 9, "non": [2, 9], "none": [0, 2, 3, 5], "nonzero": 9, "nor": [8, 9], "normal": [3, 9], "notabl": 9, "note": [2, 3, 7, 8, 9, 11], "notebook": 3, "noth": [3, 9], "notic": [8, 9], "notifi": 2, "notimplementederror": 3, "notori": 9, "novic": 9, "now": [9, 10, 11], "npdf": 9, "nsf": [7, 8, 9], "nucleonnumb": 9, "number": [2, 3, 5, 9], "numer": 0, "numericstringsort": 0, "numpi": [2, 10], "nx": 3, "nyquist": [2, 10], "o": [3, 9], "o2": 9, "obj": [0, 3], "object": [0, 2, 3, 5, 9], "observ": [2, 9], "obtain": [2, 8, 9], "obtainrefin": 2, "occ": [2, 9], "occasion": 2, "occup": [2, 9, 11], "occupi": 11, "occur": [3, 9], "off": [3, 9], "offer": 9, "offici": 3, "offset": [2, 3, 9, 11], "often": 9, "ok": [2, 3, 9, 11], "olaf": 9, "old": [2, 3, 9], "older": 9, "oldidx": 2, "omit": [9, 11], "onabout": 3, "onadd": 3, "onapplyparamet": 3, "onbeginlabeledit": 3, "onbrows": 3, "onc": 9, "oncalcrang": 3, "oncancel": 3, "oncellchang": 3, "oncellleftclick": 3, "oncellrightclick": 3, "onchar": 5, "onclos": 3, "oncolclick": 3, "oncolumbialogo": 3, "oncombokillfocu": 3, "oncommun": 3, "oncopi": 3, "oncopyerrorlog": 3, "oncustom": 3, "ondanselogo": 3, "ondefaultlayout": 3, "ondelet": 3, "ondocument": 3, "ondoubleclick": 3, "ondoubleclick2": 3, "ondown": 3, "ondseri": 3, "one": [1, 2, 3, 8, 9, 11], "oneditorshown": 3, "onendlabeledit": 3, "onent": 3, "onexport": 3, "onexportnewstruct": 3, "onexportpdf": 3, "onexportr": 3, "onexportstruct": 3, "ongoogl": 3, "ongridrangeselect": 3, "oninit": 3, "oninscalc": 3, "oninsdata": 3, "oninsphas": 3, "onkei": [3, 5], "onkeydown": 5, "onkillfocu": 3, "onkillfocus": 3, "onlabelrightclick": 3, "onli": [2, 3, 5, 8, 9, 11], "onlin": [9, 10], "onlosefocu": 3, "onmainmenu": 3, "onmiddleclick": 3, "onmrufil": 3, "onmsulogo": 3, "onnew": 3, "onnewfit": 3, "onnotebookchang": 3, "onnotebookpagechang": 3, "onnsflogo": 3, "onok": 3, "onopen": 3, "onoxtextent": 3, "onoytextent": 3, "onoztextent": 3, "onpagechang": 3, "onpaint": 3, "onpast": 3, "onpastelink": 3, "onplot": 3, "onplotfstruct": 3, "onplotistruct": 3, "onpopupcopi": 3, "onpopupcopyrefinedtoiniti": 3, "onpopupdelet": 3, "onpopupfil": 3, "onpopupfixfre": 3, "onpopupinsert": 3, "onpopuppast": 3, "onpopuprenameparamet": 3, "onpopupselect": 3, "onpopupspacegroup": 3, "onpopupsupercel": 3, "onposflag": 3, "onprefer": 3, "onprintba": 3, "onprintbl": 3, "onquickplot": 3, "onquit": 3, "onrequest": 3, "onreset": 3, "onrightclick": 3, "onrseri": 3, "onrun": 3, "onsampl": 3, "onsav": 3, "onsavea": 3, "onsavecalc": 3, "onselectedpair": 3, "onset": 9, "onsetfocu": 3, "onsgselect": 3, "onsgtextent": 3, "onshowfit": 3, "onshowjourn": 3, "onshowoutput": 3, "onshowplot": 3, "onspin": 3, "onstop": 3, "onstyp": 3, "ontempflag": 3, "ontext": 3, "ontextctrlkei": 3, "ontextkillfocu": 3, "onto": [2, 9], "ontreeselchang": 3, "ontseri": 3, "onup": 3, "onurl": 3, "onwindowclos": 2, "open": [2, 3, 7, 9, 11], "oper": [3, 9], "opinion": [7, 8, 9], "option": [0, 1, 2, 3, 9, 10, 11], "oragan": 3, "orbit": 9, "order": [2, 3, 9], "org": [8, 9], "orgain": 3, "organ": [3, 9], "orient": 9, "origin": [2, 3, 8, 9], "orthorhomb": 9, "other": [2, 3, 5, 7, 8, 9, 10, 11], "otherwis": [2, 8, 9], "oup": 11, "our": [9, 11], "out": [2, 3, 8, 9, 11], "outcom": 9, "output": [2, 3, 9], "outputbondangl": 2, "outputbondlengthatom": 2, "outputbondlengthtyp": 2, "outright": 3, "over": [8, 9, 11], "overload": [2, 3], "overrid": [2, 5], "overwrit": [2, 3], "own": [0, 2, 3], "owner": [2, 9], "ownership": 2, "oxford": 11, "oxygen": 9, "p": [7, 8, 9, 11], "p63mc": 9, "p_": 2, "p_ph1": 2, "packag": [7, 9, 10], "pad": 9, "page": [3, 7, 8, 9, 10, 11], "pair": [1, 2, 3, 7, 9, 11], "pan": [3, 9], "pane": [3, 9], "panel": [3, 5, 9, 11], "paneltyp": 3, "paper": [7, 8, 9], "param": 3, "paramet": [3, 9, 11], "parametr": 9, "parent": [2, 3, 5], "parenthes": 9, "parguess": 2, "parnam": 3, "parser": 10, "part": [3, 7, 8, 9], "parti": 8, "partial": 2, "particl": [2, 9], "particular": [2, 8, 9], "particularli": 9, "parvalu": 2, "pass": [2, 3, 9], "past": [2, 3, 9, 11], "pastebranch": 3, "pasteintocel": 3, "patent": 8, "path": [0, 2, 3, 9], "pattern": 9, "paus": [2, 3], "pauseev": 2, "pavol": [7, 8, 9], "pbnm": 9, "pdb": [1, 2, 3, 9], "pdf": [0, 1, 2, 3, 7, 9], "pdf_ob": 2, "pdfdataformaterror": 2, "pdffit": [2, 3, 9, 11], "pdffit2": [1, 2, 3, 7, 8, 9, 11], "pdffitstructur": 2, "pdfgetn": [2, 9], "pdfgetx2": [2, 9], "pdfgui": [8, 9, 11], "pdfguiapp": 3, "pdfguicontrol": [0, 3], "pdfguiglob": 1, "pdfstructur": 3, "pdguicontrol": 2, "peak": [2, 9], "peng": 7, "peopl": [8, 9], "pep8": 10, "perform": [2, 3, 9], "period": 2, "perman": 9, "permiss": [2, 8, 9], "permit": [8, 9], "persistentitem": 2, "person": [8, 9], "perspect": 3, "pertain": 9, "phase": [0, 2, 3, 9, 10, 11], "phaseconfigurepanel": 5, "phaseidx": 2, "photon": 9, "phy": [7, 8, 9, 11], "physic": [7, 9], "pick": 9, "pickl": [0, 2], "pip": 9, "place": [2, 3, 9, 11], "plain": 3, "platform": [2, 9], "pleas": [7, 8, 9, 11], "plot": [1, 2, 3, 9, 10, 11], "plotwnd": 2, "po": [2, 3, 5], "point": [0, 1, 2, 3, 5, 9], "pointer": 3, "pop": [3, 9, 11], "popul": 9, "popular": 9, "popup": [3, 11], "popupmenu": 3, "portabl": 9, "portion": 9, "posflag": 2, "posit": [2, 3, 9, 11], "possibl": [2, 3, 8, 9, 11], "possibli": 0, "post": 9, "postev": 3, "power": [7, 9], "pr": 10, "practic": 9, "pre": [9, 10], "preclud": 9, "predetermin": 3, "preexist": 9, "prefac": 9, "prefer": [3, 9], "prefix": [2, 5], "prematur": 9, "prepar": [3, 9], "present": [2, 9], "preserv": [2, 3, 9], "press": [3, 5, 9, 11], "pretti": 11, "prevent": [2, 11], "previou": [2, 3, 5, 9, 11], "previous": [3, 9, 10], "primari": 9, "prime": 9, "primer": 11, "princip": 9, "principl": 9, "print": [3, 9], "prior": [8, 9], "privat": 2, "prj": 9, "probabl": [3, 9], "problem": 9, "proce": 9, "procedur": [9, 11], "proceed": 9, "process": [1, 2, 3, 5, 9], "processargu": 1, "processformula": 3, "procur": [8, 9], "product": [3, 8, 9, 11], "prof": [8, 9], "professor": 9, "proffen": [7, 8, 9, 11], "profil": [7, 9, 11], "profit": [8, 9], "program": [1, 2, 3, 7, 8, 9, 11], "programmat": 3, "progress": [9, 11], "project": [0, 1, 2, 3, 7, 8, 9, 10, 11], "projfil": 2, "promot": [8, 9], "prompt": [9, 11], "proper": 9, "properli": 3, "properti": [2, 3, 9, 11], "proprietari": 8, "protect": 0, "protocol": [0, 9], "prototyp": 2, "provid": [2, 8, 9], "pscale": [2, 9], "pt": 11, "public": [7, 8, 9], "pull": 9, "purpos": [3, 8, 9], "put": [3, 9, 10], "py": [3, 5, 9, 10], "py2": 10, "py3": 10, "pydoc": 9, "pymmlib": 9, "pymol": 9, "python": [1, 3, 9, 10], "python2": 9, "python3": 2, "pythondebugg": 3, "pythonpath": 2, "q": [2, 3, 9], "qalp": 9, "qbroad": [2, 3, 9], "qdamp": [2, 3, 9], "qiu": 9, "qmax": [2, 3, 9], "qsig": 9, "quadrat": [2, 9], "quantit": 9, "quantiti": 9, "queri": 9, "question": 9, "queu": [2, 3, 9], "queue": 2, "queuemanag": 2, "quick": 9, "quicker": 5, "quickli": [3, 9], "quickplot": 3, "quit": [3, 9], "quot": [2, 9], "r": [2, 3, 9, 11], "r3067": 9, "radaelli": 9, "radiat": 9, "radiu": 9, "rai": [7, 9, 11], "rais": [1, 2, 3], "ralf": 9, "rang": [2, 3, 9], "rather": 9, "ratio": 9, "raw": [2, 9], "rcalc": 2, "rcut": [2, 9], "rdquo": 9, "re": [2, 10], "reach": 9, "react": 3, "read": [2, 3, 9, 11], "readconfigur": 3, "readi": 9, "readm": [7, 10], "readob": 2, "readobsstr": 2, "readstr": 2, "real": [2, 9], "realist": 9, "realiz": 5, "realli": 11, "reason": 9, "reassign": 9, "recalcul": 2, "recent": [3, 9], "recip": 10, "recogn": 2, "recommend": [7, 8, 9, 11], "record": [3, 8, 9], "recreat": 9, "rectangl": 3, "red": 11, "redirect": [2, 3], "redirectstdout": 2, "redistribut": [8, 9], "reduc": 9, "reduct": 9, "redund": 3, "redundantli": 10, "ref": 2, "refer": [2, 3, 5, 9], "refin": [0, 1, 2, 3, 7, 9, 11], "refinablevar": 2, "refine_step": 2, "reflect": [2, 7, 8, 9], "reformat": 10, "refresh": [3, 9, 10], "refreshgrid": 3, "refreshselectedpag": 3, "refreshtextctrl": 3, "refvar": 2, "refvar_str": 2, "region": 9, "rel": 2, "relat": [2, 3, 8, 9, 11], "relax": 9, "releas": [7, 8, 9], "relev": 9, "remain": [9, 11], "remedi": 9, "remot": 2, "remov": [2, 3, 9, 10], "removecurv": 3, "renam": [2, 3, 9, 11], "render": [2, 10], "repeat": [9, 11], "replac": [2, 9], "replot": 3, "repo": 10, "report": [3, 9, 10], "repositori": [8, 9], "repres": [2, 3, 9], "represent": [0, 2, 3, 9], "reproduc": [8, 9], "request": [2, 9], "requir": [2, 3, 5, 9], "resampl": 2, "research": [7, 8, 9], "reset": [2, 3, 9], "resetstatu": 2, "resid": 3, "resiz": 9, "resolut": [2, 9], "resolv": 9, "resourc": 10, "respect": [2, 3, 8, 9, 11], "restart": 2, "restrict": 9, "restrictconstrainedparamet": 3, "result": [1, 2, 3, 9, 11], "resultstextctrl": 3, "retain": [8, 9], "retriev": 3, "return": [0, 1, 2, 3, 5, 9], "reveal": 9, "revert": 9, "review": 9, "rewrit": 9, "rewritten": 9, "rhombohedr": 9, "right": [2, 3, 8, 9, 11], "rightclick": 3, "rightmost": 9, "rightpanel": 3, "rippl": [2, 9], "rlen": 2, "rmax": [2, 3], "rmin": [2, 3], "rob": 2, "robert": 11, "robust": 9, "room": 9, "root": 3, "round": 9, "routin": [0, 2, 5, 9], "row": [2, 3, 5, 9], "rseri": 3, "rsquo": 9, "rst": 10, "rstep": 2, "run": [2, 3, 9, 10, 11], "rundep": 9, "runningdict": 3, "runtim": 2, "rw": [2, 9], "safe": [0, 2], "safeconfigurationpars": 3, "safecpickledump": 0, "sai": [9, 11], "sake": 9, "same": [0, 2, 3, 9, 11], "sampl": [2, 3, 9], "satisfi": [9, 11], "save": [0, 1, 2, 3, 9, 11], "save_figur": 3, "saveplotdata": 3, "sb2896": [8, 9], "scalar": 2, "scale": [2, 9, 11], "scale_factor": 11, "scatter": [2, 7, 8, 9], "scenario": 9, "scheme": 9, "schmidt": 9, "scienc": [7, 8, 9], "scientif": [7, 8, 9], "scope": [2, 9], "scratch": [3, 9, 11], "screen": [2, 9], "script": 9, "se": 9, "search": [3, 5, 7, 9], "second": [2, 9], "secondari": 3, "secondflag": 2, "secret": 8, "section": [3, 9], "see": [2, 3, 5, 7, 9, 11], "seed": 9, "seem": 9, "seen": 9, "segment": 0, "select": [2, 3, 5, 9, 11], "selectal": 3, "selectalltyp": 3, "selected_pair": 2, "selenium": 9, "self": [2, 3], "send": [3, 9], "sent": [2, 3], "separ": [2, 3, 9], "sequenc": 9, "sequenti": [1, 2, 9], "seri": [2, 3, 9, 10], "serv": [3, 9], "server": [2, 9], "servic": [8, 9], "session": 3, "set": [2, 3, 5, 8, 9, 10, 11], "setconfig": 2, "setconfigurationdata": 3, "setconstraintsdata": 3, "setcontroldata": 3, "setfitsamplingtyp": 2, "setiniti": 2, "setitemdata": 5, "setmod": 3, "setnodetyp": 3, "setpanel": 5, "setpanelspecificdata": 3, "setresultsdata": 3, "setrgrid": 2, "setselect": 5, "setselectedpair": 2, "setstructur": 3, "settabl": 3, "settitl": 3, "settooltip": 3, "setup": [1, 9], "setuptool": 10, "setvar": 2, "setxlabel": 3, "setylabel": 3, "sever": [3, 9, 11], "sgname": 2, "sgoffset": 2, "shall": [8, 9], "shannon": [2, 10], "shape": [2, 9], "share": [0, 2, 3, 8, 9], "sharp": 9, "sharpen": 9, "sharper": 9, "sheet": 9, "shell": [2, 9], "shift": [2, 9, 11], "short": 3, "short2long": 3, "short_nam": 2, "shortcut": [3, 9], "shortest": [2, 9], "should": [1, 2, 3, 5, 8, 9, 11], "show": [1, 2, 3, 9, 10, 11], "showmessag": 3, "showmod": 3, "shown": [3, 9], "showselectatomsdialog": 3, "shut": 3, "shutdown": 3, "si": 9, "sibl": 3, "side": [2, 3], "sigma": 9, "sign": 0, "signal": 9, "signific": 9, "similar": 9, "similarli": 9, "simon": [7, 8, 9, 11], "simpl": [3, 5, 7, 9], "simpler": 9, "simpli": [3, 5, 9, 11], "simplic": 9, "simplifi": 9, "simul": [0, 1, 2, 7, 9], "simultan": 9, "sinc": [3, 9, 10], "singl": [1, 2, 3, 8, 9], "singleton": 2, "site": [2, 9, 11], "situat": 9, "six": 10, "size": [2, 3, 5, 9], "skip": 2, "slightli": 2, "slot": 3, "small": [0, 9], "smallest": 3, "snapshot": 2, "so": [2, 3, 9, 11], "softwar": [7, 8, 9], "soham": 11, "solut": 9, "solv": 9, "some": [3, 9], "somehow": [3, 9], "someth": [2, 3], "sort": [0, 2, 3, 5, 9], "sorted_standard_space_group": 2, "sorter": 5, "sourc": [0, 1, 2, 3, 5, 8, 9], "sourceforg": [3, 9], "space": [2, 3, 9, 11], "spacegroup": 2, "span": 9, "spd_assign": 2, "spd_constrain": 2, "spdiamet": [2, 9], "speci": [9, 11], "special": [8, 9, 11], "specif": [2, 3, 8, 9], "specifi": [0, 2, 3, 9], "spell": 10, "spheric": 9, "spin": 3, "split": 0, "srat": 9, "sratio": [2, 9], "src": 2, "stack": 9, "stage": [7, 9], "stand": [9, 11], "standard": [2, 3, 9, 10], "start": [2, 3, 7, 9, 10, 11], "starter": 3, "startnod": 3, "startqueu": 2, "startup": 9, "state": [3, 8, 9], "static": [2, 9], "statu": [2, 3], "stdout": 3, "step": [2, 9, 11], "stepcut": [2, 9], "still": 3, "stop": [2, 3, 9], "storag": [2, 9], "store": [1, 2, 3, 5, 9, 10], "str": [2, 10, 11], "strain": 9, "strang": 10, "strict": [8, 9, 10], "strictli": 9, "string": [0, 2, 3, 5, 9, 10, 11], "stringio": 2, "strip": 2, "strongli": [9, 11], "stru": [2, 9, 11], "struc": 2, "structur": [0, 1, 2, 3, 7, 9, 10], "structurepars": 2, "student": 11, "studi": [7, 8, 9, 11], "stuff": 3, "style": [2, 3, 5, 9], "stylesheet": 10, "stype": [2, 3], "sub": 2, "subclass": [2, 5], "subpath": 2, "subscript": 9, "subsect": 9, "subsequ": [8, 9, 11], "subset": 9, "substitut": [8, 9], "subsubsect": 9, "subtre": 3, "subvers": 9, "succeed": 9, "success": [2, 9], "suffici": 9, "suggest": [2, 9], "suit": 9, "suitabl": [2, 8, 9], "summari": 9, "supercel": [2, 3, 9], "suppli": 9, "support": [2, 8, 9, 10], "suppos": 9, "sure": [2, 3, 9], "surviv": 9, "switch": 3, "switchrightpanel": 3, "symbol": [2, 9], "symmetri": [2, 7, 9], "symposep": 2, "sync": 9, "synchrotron": 9, "syntax": [2, 9, 11], "synthes": 9, "system": [2, 3, 9, 10, 11], "systemat": 9, "systemerror": 0, "t": [2, 3, 9, 11], "tab": [3, 5, 9, 11], "tabl": [2, 9], "tag": 9, "take": [2, 3, 9], "taken": [2, 3], "tamper": 9, "target": 2, "targetid": 2, "task": 9, "tcount": 9, "team": [7, 8, 9], "tediou": 9, "tell": 3, "teller": 9, "tempcontrolselecterror": 2, "temperatur": [0, 2, 3, 9, 11], "templat": [2, 9, 10], "temporari": 2, "tensor": 9, "terban": 11, "term": [3, 9], "termin": [2, 9, 11], "test": [3, 9], "texi2html": 9, "text": [0, 3, 5, 9, 11], "textctrl": [3, 5], "textctrla": 3, "textctrlalpha": 3, "textctrlasgridcel": 5, "textctrlb": 3, "textctrlbeta": 3, "textctrlc": 3, "textctrldelta1": 3, "textctrldelta2": 3, "textctrlgamma": 3, "textctrlrcut": 3, "textctrlscalefactor": 3, "textctrlspdiamet": 3, "textctrlsratio": 3, "textctrlstepcut": 3, "textvalid": 5, "th": [7, 8, 9, 11], "than": [1, 2, 3, 9, 11], "thei": [2, 3, 8, 9, 10], "them": [3, 5, 9, 11], "themselv": [2, 9], "theoret": [2, 3, 9], "theori": [8, 9], "therefor": 9, "therein": 9, "thermal": [2, 9], "thi": [1, 2, 3, 5, 7, 8, 9, 11], "thing": 9, "thorough": 9, "those": [2, 3, 7, 8, 9], "though": 9, "thread": [2, 9], "three": [2, 3, 9, 11], "through": [2, 9], "thu": [8, 9], "ti": 9, "tian": 7, "time": [3, 9, 11], "timestep": 2, "tip": 9, "titl": [3, 8, 11], "tmpdir": 2, "togeth": [9, 11], "toggl": [2, 3, 9], "toler": 2, "too": 9, "tool": [3, 9], "toolbar": [3, 9, 11], "toolbox": 9, "toolitem": 3, "toolkit": 9, "top": [3, 9, 11], "tort": [8, 9], "total": [2, 9], "tp": [2, 3], "traceback": 3, "track": 9, "trade": 8, "train": 9, "transfer": [3, 5, 9], "transferfromwindow": 5, "transfertowindow": 5, "transform": [2, 9], "transit": 9, "translat": 2, "tree": [2, 3, 9, 11], "treectrl": 3, "treectrlmain": 3, "treelist": 3, "treeselectionupd": 3, "tri": 2, "trick": 9, "tritium": 9, "troubleshoot": 9, "true": [2, 3, 5], "truncat": 9, "truste": [8, 9], "try": [3, 9, 11], "tseri": 3, "tui": 9, "tui_mno_bond_length": 9, "tupl": [2, 3, 5], "turn": [5, 9], "tutori": [9, 10], "tweak": 10, "two": [3, 9, 10, 11], "txt": 10, "type": [0, 2, 3, 5, 9, 11], "typeerror": 10, "typic": [8, 9], "u": [8, 9, 11], "u11": [2, 9, 11], "u12": 2, "u13": 2, "u22": [2, 9], "u23": 2, "u33": [2, 9, 11], "ub": 2, "uij": [2, 9], "uijflag": 2, "uiso": 9, "uisoequiv": 9, "uk": 9, "un": 2, "unaffect": 2, "uncaught": 9, "uncheck": [9, 11], "uncorrel": 9, "undefin": 0, "under": [2, 3, 7, 8, 9, 11], "underli": 9, "understand": 9, "understood": 11, "unhandl": 9, "unicod": 9, "uninstal": 9, "unintent": 9, "uniqu": [2, 5], "unit": [9, 11], "unitless": 9, "univers": [7, 8, 9, 11], "unix": 9, "unknown": 2, "unlik": 9, "unlock": 3, "unmodifi": 9, "unpickl": 2, "up": [2, 3, 5, 8, 9, 10, 11], "updat": [1, 2, 3, 5, 7, 9, 10], "updateconfigur": 3, "updatedata": 3, "updatefittingstatu": 3, "updateoutput": 3, "updateparamet": 2, "updatespacegrouplist": 3, "updatestatusbar": 3, "updatetext": 3, "updatetitl": 3, "updatetoolbar": 3, "updatewidget": 3, "upgrad": 9, "upload": 2, "upon": [2, 3, 9], "upper": [2, 9], "url": [3, 11], "us": [0, 1, 2, 3, 5, 7, 8, 10], "usabl": 9, "usag": [1, 9], "usebestvisu": 3, "user": [0, 1, 2, 3, 7, 9, 11], "usr": 9, "usual": 9, "util": 5, "v": [1, 9], "valid": [1, 2, 3, 11], "validatestructur": 3, "valu": [0, 2, 3, 5, 9, 11], "valueerror": [1, 2], "var": 2, "var_str": 2, "vari": [9, 11], "variabl": [2, 3, 9, 11], "varieti": 9, "variou": [2, 3, 9], "vector": 2, "veri": [9, 11], "verifi": [3, 9], "version": [1, 3, 7, 8, 9], "versu": 9, "veto": 3, "via": [3, 9], "vibrat": 9, "view": [3, 7, 8, 9], "viewer": [2, 3, 9], "virtual": 9, "visibl": 3, "visit": [8, 9], "visual": [7, 9], "void": [2, 3], "w": [3, 7, 8, 9, 10, 11], "wa": [2, 3, 5, 7, 8, 9, 10, 11], "wai": [2, 3, 8, 9], "wait": 2, "want": [8, 9, 11], "warn": [9, 10], "warranti": [8, 9], "watch": 11, "we": [3, 7, 8, 9, 11], "web": [8, 9], "websit": 9, "weight": 3, "welcom": [3, 8, 9], "well": [2, 9], "wenduo": 7, "were": [3, 5, 7, 8, 9], "what": [3, 8, 9, 11], "whatisnew": 9, "when": [0, 1, 2, 3, 5, 8, 9, 10, 11], "whenev": [3, 5], "where": [0, 2, 3, 5, 9, 11], "whether": [3, 8, 9], "which": [2, 3, 5, 9], "while": 9, "white": 3, "whitespac": 2, "whittak": [2, 10], "who": 7, "wholli": 9, "whose": [3, 9], "wider": [3, 9], "widget": [3, 5], "width": [2, 3, 5, 9], "wiget": 3, "window": [2, 3, 5, 9, 10, 11], "wise": 9, "within": [2, 3, 7, 9], "without": [1, 3, 8, 9], "word": 2, "work": [3, 8, 9, 10], "workaround": 9, "worker": [2, 11], "workflow": 11, "workpath": 3, "would": [3, 9, 11], "wrap": 3, "wrapper": 3, "write": [0, 2, 3, 9, 11], "writecalc": 2, "writecalcstr": 2, "writeconfigur": 3, "writeob": 2, "writeobsstr": 2, "writeresampledob": 2, "writeresampledobsstr": 2, "writestr": 2, "written": [3, 8, 9], "wrong": [2, 3], "wsinterp": 2, "wt": 3, "wurtzit": 9, "www": [8, 9], "wx": [3, 5, 9], "wx3": 10, "wxextens": [0, 3, 7], "wxfilehistori": 3, "wxlistctrl": 5, "wxpanel": 3, "wxpython": [3, 5, 9, 10], "wxtextctrl": 5, "wxwhite": 3, "wxwidget": 9, "x": [2, 3, 7, 9, 11], "x0": 2, "x000t010q35": 9, "x004t010q35": 9, "x012t010q35": 9, "x016t010q35": 9, "x020t010q35": 9, "x024t010q35": 9, "x028t010q35": 9, "x1": 2, "x11r6": 9, "xcfg": 9, "xdata": [2, 3], "xitem": 2, "xname": 2, "xrai": [9, 11], "xstr": 2, "xterm": 9, "xyz": 2, "y": [2, 3, 9, 11], "y0": 2, "y1": 2, "ydata": [2, 3], "yet": [2, 9], "yield": 9, "yitem": 2, "yname": 2, "york": [7, 8, 9], "you": [2, 5, 7, 8, 9, 11], "your": [7, 8, 9, 11], "ystr": 2, "z": [2, 9, 11], "zero": [2, 9], "zhou": 7, "zip": 2, "zoom": [3, 9], "zoom_to_rect": 3}, "titles": ["diffpy.pdfgui package", "diffpy.pdfgui.applications package", "diffpy.pdfgui.control package", "diffpy.pdfgui.gui package", "diffpy.pdfgui.gui.design package", "diffpy.pdfgui.gui.wxextensions package", "diffpy.pdfgui.icons package", "diffpy.pdfgui documentation", "License", "Manual", "Release Notes", "Tutorial"], "titleterms": {"0": 10, "05": 10, "1": [10, 11], "18": 10, "2": [10, 11], "2023": 10, "3": [10, 11], "5": 10, "aboutdialog": 3, "adddatapanel": 3, "addphasepanel": 3, "applic": 1, "author": 7, "autowidthlabelsgrid": 5, "blankpanel": 3, "bondangledialog": 3, "bondlengthdialog": 3, "build": 11, "calcul": 2, "calculationpanel": 3, "constraint": 2, "content": 7, "control": 2, "controlerror": 2, "creat": 11, "crystal": 11, "datasetconfigurepanel": 3, "datasetconstraintpanel": 3, "datasetpanel": 3, "datasetresultspanel": 3, "debugopt": 3, "design": 4, "diffpi": [0, 1, 2, 3, 4, 5, 6, 7], "document": 7, "dopingseriespanel": 3, "errorreportdialog": 3, "errorreportdialog_control_fix": 3, "errorwrapp": 3, "extendedplotfram": 3, "fit": [2, 11], "fitdataset": 2, "fitnotebookpanel": 3, "fitstructur": 2, "fittre": 3, "gui": [3, 4, 5], "icon": 6, "indic": 7, "insertrowsdialog": 3, "instal": 7, "journalpanel": 3, "lesson": 11, "licens": 8, "listctrl": 5, "main": 3, "mainfram": 3, "manual": 9, "model": 11, "modul": [0, 1, 2, 3, 5], "multi": 11, "ni": 11, "note": 10, "organ": 2, "outputpanel": 3, "packag": [0, 1, 2, 3, 4, 5, 6], "paneldialog": 5, "paneltest": 3, "paramet": 2, "parameterspanel": 3, "pdf": 11, "pdfcompon": 2, "pdfdataset": 2, "pdfgui": [0, 1, 2, 3, 4, 5, 6, 7], "pdfguicontrol": 2, "pdfguiglob": 3, "pdfguimacro": 2, "pdflist": 2, "pdfpanel": 3, "pdfstructur": 2, "phaseconfigurepanel": 3, "phaseconstraintspanel": 3, "phasenotebookpanel": 3, "phasepanelutil": 3, "phaseresultspanel": 3, "plotpanel": 3, "plotter": 2, "preferencespanel": 3, "refer": [7, 11], "releas": 10, "resourc": 9, "resultspanel": 3, "rseriespanel": 3, "sgconstraindialog": 3, "sgstructuredialog": 3, "simpl": 11, "stage": 11, "structur": 11, "structureview": 2, "submodul": [0, 1, 2, 3, 5], "subpackag": [0, 3], "supercelldialog": 3, "symmetri": 11, "tabl": 7, "temperatureseriespanel": 3, "textctrlutil": 5, "tooltip": 3, "tui": 0, "tutori": [7, 11], "us": [9, 11], "util": 0, "v3": 10, "valid": 5, "version": 10, "welcomepanel": 3, "windowperspect": 3, "wxextens": 5}}) \ No newline at end of file diff --git a/src/diffpy/__init__.py b/src/diffpy/__init__.py deleted file mode 100644 index 5adbcb4b..00000000 --- a/src/diffpy/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# (c) 2024 The Trustees of Columbia University in the City of New York. -# All rights reserved. -# -# File coded by: Billinge Group members and community contributors. -# -# See GitHub contributions for a more detailed list of contributors. -# https://github.com/diffpy/diffpy.pdfgui/graphs/contributors -# -# See LICENSE.rst for license information. -# -############################################################################## -"""Blank namespace package for module diffpy.""" - - -from pkgutil import extend_path - -__path__ = extend_path(__path__, __name__) - -# End of file diff --git a/src/diffpy/pdfgui/__init__.py b/src/diffpy/pdfgui/__init__.py deleted file mode 100644 index e94fe701..00000000 --- a/src/diffpy/pdfgui/__init__.py +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# (c) 2024 The Trustees of Columbia University in the City of New York. -# All rights reserved. -# -# File coded by: Billinge Group members and community contributors. -# -# See GitHub contributions for a more detailed list of contributors. -# https://github.com/diffpy/diffpy.pdfgui/graphs/contributors -# -# See LICENSE.rst for license information. -# -############################################################################## -"""GUI for PDF simulation and structure refinement.""" - -# package version -from diffpy.pdfgui.version import __version__ - -# silence the pyflakes syntax checker -assert __version__ or True - -# End of file diff --git a/src/diffpy/pdfgui/applications/__init__.py b/src/diffpy/pdfgui/applications/__init__.py deleted file mode 100644 index 8bdc5f5a..00000000 --- a/src/diffpy/pdfgui/applications/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# diffpy.pdfgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2009-2024 Trustees of the Columbia University -# in the City of New York. All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - - -# End of file diff --git a/src/diffpy/pdfgui/applications/pdfgui.py b/src/diffpy/pdfgui/applications/pdfgui.py deleted file mode 100755 index cb6166a2..00000000 --- a/src/diffpy/pdfgui/applications/pdfgui.py +++ /dev/null @@ -1,134 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -""" -PDFgui Graphical User Interface for Pair Distribution Function fitting -Usage: pdfgui [project.dpp] - -PDFgui is graphical user interface to PDFfit2 - a Python library for PDF -simulation and structure refinement. PDFgui has many nice features such -as control of multiple fits, integrated plotting, easy setup of sequential -refinements, and saving of entire project in a single file. - -Options: - -h, --help display this message - -V, --version show program version - -Debugging options: - --db-noed disable exceptions catching to ErrorReportDialog - --db-nocf exit without asking to save modified project - --db-pdb use Python debugger to handle error exceptions -""" - -from __future__ import print_function - -import getopt -import os -import sys - - -def usage(): - """Show usage info.""" - myname = os.path.basename(sys.argv[0]) - msg = __doc__.replace("pdfgui", myname) - print(msg) - return - - -def version(): - from diffpy.pdfgui import __version__ - - print("PDFgui", __version__) - return - - -def processArguments(argv1): - """Process command line arguments and store results in - pdfguiglobals. This method updates cmdopts, cmdargs and dbopts - attributes in the pdfguiglobals module. - - argv1 -- list of command line arguments excluding the executable - - Returns boolean flag to indicate if the execution should continue. - The flag is False, when options contain --help or --version. - Raises GetoptError for invalid options. - Raises ValueError for more than one project file arguments or - when project is not a valid file. - """ - from diffpy.pdfgui.gui import pdfguiglobals - - dbopts = pdfguiglobals.dbopts - dboptions = [("db-" + o[0]) for o in dbopts.alldebugoptions] - # default parameters - opts, args = getopt.gnu_getopt(sys.argv[1:], "hV", ["help", "version"] + dboptions) - # process options - proceed = True - for o, a in opts: - if o in ("-h", "--help"): - usage() - proceed = False - elif o in ("-V", "--version"): - version() - proceed = False - elif o.startswith("--") and o[2:] in dboptions: - # strip "--db-" - dbo = o[5:] - setattr(dbopts, dbo, True) - pdfguiglobals.cmdopts = opts - # bail-out here if options contain --help or --version - if not proceed: - return False - # otherwise continue checking arguments - if len(args) == 1 and not os.path.isfile(args[0]): - emsg = "Project file %s does not exist." % args[0] - raise ValueError(emsg) - elif len(args) > 1: - emsg = "Too many project files." - raise ValueError(emsg) - # ready to go - pdfguiglobals.cmdargs = args - return proceed - - -def main(): - """Main entry point to PDFgui.""" - # process arguments - proceed = False - try: - proceed = processArguments(sys.argv[1:]) - except (getopt.GetoptError, ValueError) as err: - print(err, file=sys.stderr) - sys.exit(1) - # bail out when no gui is needed - if not proceed: - sys.exit() - # initialize gui - import diffpy.pdfgui.gui.main as guimain - - # Catch control errors, that may happen during project - # loading, before the GUI gets running - from diffpy.pdfgui.control.controlerrors import ControlError - - try: - guimain.main() - except ControlError as err: - print(err, file=sys.stderr) - sys.exit(1) - return - - -if __name__ == "__main__": - main() - -# End of file diff --git a/src/diffpy/pdfgui/control/__init__.py b/src/diffpy/pdfgui/control/__init__.py deleted file mode 100644 index a90402c6..00000000 --- a/src/diffpy/pdfgui/control/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -# End of file diff --git a/src/diffpy/pdfgui/control/calculation.py b/src/diffpy/pdfgui/control/calculation.py deleted file mode 100644 index c8e86a44..00000000 --- a/src/diffpy/pdfgui/control/calculation.py +++ /dev/null @@ -1,376 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Pavol Juhas, Jiwu Liu -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""Class Calculation for performing PDF simulation from model -structure.""" - -import copy -import math -import pickle - -from diffpy.pdfgui.control.controlerrors import ControlConfigError, ControlKeyError, ControlValueError -from diffpy.pdfgui.control.pdfcomponent import PDFComponent -from diffpy.pdfgui.utils import safeCPickleDumps - - -class Calculation(PDFComponent): - """Perform a theoretical computation of PDF from model structure. - - Data members: - - rmin -- read-only lower boundary of rcalc, change with setRGrid() - rstep -- read-only r-grid step, use setRGrid() to change it - rmax -- read-only upper boundary of rcalc, change with setRGrid() - rlen -- read-only number of r points, set by setRGrid(). - To be used in PdfFit.alloc() - rcalc -- list of r values, this is set after calculation is finished - Gcalc -- list of calculated G values - stype -- scattering type, 'X' or 'N' - qmax -- maximum value of Q in inverse Angstroms. Termination ripples - are ignored for qmax=0. - qdamp -- specifies width of Gaussian damping factor in pdf_obs due - to imperfect Q resolution - qbroad -- quadratic peak broadening factor related to dataset - spdiameter -- particle diameter for shape damping function. - Note: this attribute has been moved to FitStructure and is - maintained only for backward compatible reading of PDFgui - project files. - dscale -- total scale factor - """ - - def __init__(self, name): - """Initialize Calculation. - - name -- calculation name - """ - PDFComponent.__init__(self, name) - - # rmin, rstep, rmax, rlen, rcalc - self.setRGrid(rmin=0.1, rstep=0.01, rmax=10.0) - self.rcalc = [] - self.Gcalc = [] - self.stype = "X" - # user must specify qmax to get termination ripples - self.qmax = 0.0 - self.qdamp = 0.001 - self.qbroad = 0.0 - self.spdiameter = None - self.dscale = 1.0 - return - - def _getStrId(self): - """Make a string identifier. - - return value: string id - """ - return "c_" + self.name - - def setRGrid(self, rmin=None, rstep=None, rmax=None): - """Change specified r-grid parameters (rmin, rstep, rmax). - Adjust rmax for integer number of steps. - - rmin -- new low rcalc boundary - rstep -- new r-grid step - rmax -- new maximum rcalc, slightly adjusted to accommodate rstep - - No return value. - Raise ControlValueError for invalid range specification. - """ - if rmin is None: - rmin = self.rmin - if rstep is None: - rstep = self.rstep - if rmax is None: - rmax = self.rmax - rstep = float(rstep) - # check if arguments are valid - if not rmin > 0: - emsg = "Low range boundary must be positive." - raise ControlValueError(emsg) - if not rmin < rmax: - emsg = "Invalid range boundaries." - raise ControlValueError(emsg) - if rstep <= 0.0: - emsg = "Invalid value of rstep, rstep must be positive." - raise ControlValueError(emsg) - # find number of r bins - nbins = int(math.ceil((rmax - rmin) / rstep)) - # check for overshot due to round-off - epsilonr = 1.0e-8 * rstep - deltarmax = abs(rmin + (nbins - 1) * rstep - rmax) - if nbins > 1 and deltarmax < epsilonr: - nbins -= 1 - # All went well, let us go ahead and set the attributes. - self.rmin = rmin - self.rstep = rstep - self.rmax = rmin + nbins * rstep - self.rlen = nbins + 1 - return - - def start(self): - """Entry function for calculation.""" - from diffpy.pdfgui.control.fitting import getEngineExceptions, handleEngineException - - try: - self.calculate() - except getEngineExceptions() as error: - gui = self.owner.controlCenter.gui - handleEngineException(error, gui) - - # inform gui of change ( when engine calculation fails, it will update gui as well ) - gui = self.owner.controlCenter.gui - if gui: - gui.postEvent(gui.OUTPUT, None) - gui.postEvent(gui.PLOTNOW, self) - return - - def calculate(self): - """Do the real calculation.""" - # clean up old results - self.rcalc = [] - self.Gcalc = [] - - # do the job - if len(self.owner.strucs) == 0: - raise ControlConfigError("No structure is given for calculation") - - # make sure parameters are initialized - self.owner.updateParameters() - from diffpy.pdffit2 import PdfFit - - server = PdfFit() - - # structure needs to be read before dataset allocation - for struc in self.owner.strucs: - server.read_struct_string(struc.writeStr("pdffit")) - for key, var in struc.constraints.items(): - server.constrain(key, var.formula) - - # set up dataset - server.alloc(self.stype, self.qmax, self.qdamp, self.rmin, self.rmax, self.rlen) - server.setvar("qbroad", self.qbroad) - server.setvar("dscale", self.dscale) - - # phase related variables - # pair selection applies to current dataset, - # therefore it has to be done after alloc - for phaseidx0, struc in enumerate(self.owner.strucs): - phaseidx1 = phaseidx0 + 1 - server.setphase(phaseidx1) - server.setvar("pscale", struc.getvar("pscale")) - server.setvar("spdiameter", struc.getvar("spdiameter")) - struc.applyPairSelection(server, phaseidx1) - - # set up parameters - for index, par in self.owner.parameters.items(): - server.setpar(index, par.initialValue()) # info[0] = init value - # fix if fixed. Note: all parameters are free after server.reset(). - if par.fixed: - server.fixpar(index) - - # all ready here - server.calc() - - # get results - self.rcalc = server.getR() - self.Gcalc = server.getpdf_fit() - - def write(self, filename): - """Write this calculated PDF to a file. - - filename -- name of file to write to - - No return value. - """ - txt = self.writeStr() - f = open(filename, "w") - f.write(txt) - f.close() - return - - def writeStr(self): - """String representation of calculated PDF. - - Returns data string - """ - import time - from getpass import getuser - - lines = [] - # write metadata - lines.extend( - [ - "History written: " + time.ctime(), - "produced by " + getuser(), - "##### PDFgui calculation", - ] - ) - # stype - if self.stype == "X": - lines.append("stype=X x-ray scattering") - elif self.stype == "N": - lines.append("stype=N neutron scattering") - # dscale - if self.dscale: - lines.append("dscale=%g" % self.dscale) - # qmax - if self.qmax == 0: - qmax_line = "qmax=0 correction not applied" - else: - qmax_line = "qmax=%.2f" % self.qmax - lines.append(qmax_line) - # qdamp - if isinstance(self.qdamp, float): - lines.append("qdamp=%g" % self.qdamp) - # qbroad - if self.qbroad: - lines.append("qbroad=%g" % self.qbroad) - # write data: - lines.append("##### start data") - lines.append("#L r(A) G(r)") - for i in range(len(self.rcalc)): - lines.append("%g %g" % (self.rcalc[i], self.Gcalc[i])) - # lines are ready here - datastring = "\n".join(lines) + "\n" - return datastring - - def load(self, z, subpath): - """Load data from a zipped project file. - - z -- zipped project file - subpath -- path to its own storage within project file - - returns a tree of internal hierarchy - """ - config = pickle.loads(z.read(subpath + "config"), encoding="latin1") - self.rmin = config["rmin"] - self.rstep = config["rstep"] - self.rmax = config["rmax"] - self.rlen = config["rlen"] - self.rcalc = config["rcalc"] - self.Gcalc = config["Gcalc"] - self.stype = config["stype"] - self.qmax = config["qmax"] - self.qdamp = config.get("qdamp", config.get("qsig")) - self.qbroad = config.get("qbroad", config.get("qalp", 0.0)) - self.spdiameter = config.get("spdiameter") - self.dscale = config["dscale"] - return - - def save(self, z, subpath): - """Save data from a zipped project file. - - z -- zipped project file - subpath -- path to its own storage within project file - """ - config = { - "rmin": self.rmin, - "rstep": self.rstep, - "rmax": self.rmax, - "rlen": self.rlen, - "rcalc": self.rcalc, - "Gcalc": self.Gcalc, - "stype": self.stype, - "qmax": self.qmax, - "qdamp": self.qdamp, - "qbroad": self.qbroad, - "dscale": self.dscale, - } - z.writestr(subpath + "config", safeCPickleDumps(config)) - return - - def copy(self, other=None): - """Copy self to other. if other is None, create new instance. - - other -- reference to other object - - returns reference to copied object - """ - if other is None: - other = Calculation(self.name) - - # rcalc and Gcalc may be assigned, they get replaced by new lists - # after every calculation - assign_attributes = ( - "rmin", - "rstep", - "rmax", - "rlen", - "rcalc", - "Gcalc", - "stype", - "qmax", - "qdamp", - "qbroad", - "dscale", - ) - copy_attributes = () - for a in assign_attributes: - setattr(other, a, getattr(self, a)) - for a in copy_attributes: - setattr(other, a, copy.copy(getattr(self, a))) - return other - - def getYNames(self): - """Get names of data item which can be plotted as y. - - returns a name str list - """ - return [ - "Gcalc", - ] - - def getXNames(self): - """Get names of data item which can be plotted as x. - - returns a name str list - """ - return [ - "r", - ] - - def getData(self, dataname, step=None): - """Get Calculation data member. - - name -- data item name - step -- ignored, just for compatibility with Organizer.getData() - - returns data object, be it a single number, a list, or a list of list - """ - if dataname not in ["rcalc", "Gcalc"]: - emsg = "%s is not valid dataname" % dataname - raise ControlKeyError(emsg) - return self.__dict__[dataname] - - def getMetaDataNames(self): - """Return all applicable meta data names.""" - # FIXME: Currently we haven't thought about this - return [] - - def getMetaData(self, name): - """Get meta data value. - - name -- meta data name - returns meta data value - """ - return None - - -# End of class Calculation - -# simple test code -if __name__ == "__main__": - Calculation("name") - -# End of file diff --git a/src/diffpy/pdfgui/control/constraint.py b/src/diffpy/pdfgui/control/constraint.py deleted file mode 100644 index 54a5daa4..00000000 --- a/src/diffpy/pdfgui/control/constraint.py +++ /dev/null @@ -1,148 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""Class Constraint for storage of a single constraint equation -constraints will be stored in { variable : constraint } dictionary.""" - -import math -import re - -from diffpy.pdfgui.control.controlerrors import ControlSyntaxError - - -class Constraint: - """Constraint --> storage and check of a single constraint equation. - - Data members: - formula -- right-side of constraint equation (string). When - assigned it is checked for math correctness and updates - the parguess dictionary - parguess -- read-only dictionary of parameter indices and their - estimated initial values. Values are None if they - cannot be estimated. - - Private members: - __lhs -- last value of constrained variable passed to guess() - """ - - def __init__(self, formula, value=None): - """Initialize the Constraint. - - formula -- (string) right-side of constraint equation - value -- (optional) current value of the variable - - __init__ raises ControlSyntaxError when formula is incorrect - """ - # initialize private members firsts - self.__lhs = None - self.parguess = {} - # initialize formula member avoid __setattr__ - self.__dict__["formula"] = "None" - # formula should be assigned as a last one - self.formula = formula - if value is not None: - self.guess(value) - return - - def evalFormula(self, parvalues): - """Evaluate constraint formula. - - parvalues -- dictionary of int parameter indices and float values. - - returns formula result - """ - fncp = self.lambdaFormula() - result = fncp(parvalues) - return result - - def lambdaFormula(self): - """Build lambda function from constraint formula. Lambda - function expects dictionary argument. - - returns lambda function - """ - expr = re.sub(r"@(\d*)", r"p[\1]", self.formula) - f = eval("lambda p:" + expr, vars(math)) - return f - - def guess(self, value): - """Guess the initial values of parameters contained in parguess. - - value -- current value of the constrained variable - - The keys of self.parguess are indices of parameters used in formula, - and the values are suggested parameter values (None if they cannot - be estimated). - - returns a copy of self.parguess - """ - self.__lhs = float(value) - for k in self.parguess: - self.parguess[k] = None - # solve linear formulas of one variable - if len(self.parguess) == 1: - fncp = self.lambdaFormula() - # check if fncp is linear with eps precision - try: - eps = 1.0e-8 - lo, hi = 1.0 - eps, 1.0 + eps - (k,) = self.parguess.keys() - y = [fncp({k: 0.25}), fncp({k: 0.5}), fncp({k: 0.75})] - dy = [y[1] - y[0], y[2] - y[1]] - ady = [abs(z) for z in dy] - if lo * ady[0] <= ady[1] <= hi * ady[0] and dy[0] != 0.0: - a = 4 * dy[0] - b = y[1] - 0.5 * a - self.parguess[k] = (value - b) / a - except (ValueError, ZeroDivisionError): - pass - return dict(self.parguess) - - def __setattr__(self, name, value): - """Check math and update parguess when formula is assigned.""" - if name != "formula": - self.__dict__[name] = value - return - # here we are assigning to formula - # first we need to check it it is valid - newformula = value - pars = re.findall(r"@\d+", newformula) - # require at least one parameter in the formula - if len(pars) == 0: - message = "No parameter in formula '%s'" % newformula - raise ControlSyntaxError(message) - try: - # this raises ControlSyntaxError if newformula is invalid - # define fncx in math module namespace - fncx = eval("lambda x:" + re.sub(r"@\d+", "x", newformula), vars(math)) - # check if fncx(0.25) is float - fncx(0.25) + 0.0 - except (ValueError, SyntaxError, TypeError, NameError): - message = "invalid constraint formula '%s'" % newformula - raise ControlSyntaxError(message) - # few more checks of the formula: - if newformula.find("**") != -1: - emsg = ("invalid constraint formula '{}', " "operator '**' not supported.").format(newformula) - raise ControlSyntaxError(emsg) - # checks checked - self.__dict__["formula"] = newformula - self.parguess = dict.fromkeys([int(p[1:]) for p in pars]) - if self.__lhs is not None: - self.guess(self.__lhs) - return - - -# End of class Constraint - -# End of file diff --git a/src/diffpy/pdfgui/control/controlerrors.py b/src/diffpy/pdfgui/control/controlerrors.py deleted file mode 100644 index b7fd47d3..00000000 --- a/src/diffpy/pdfgui/control/controlerrors.py +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Jiwu Liu -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - - -class ControlError(Exception): - """Basic PDFGuiControl exception class.""" - - def __init__(self, info): - """initialize. - - info -- description string - """ - Exception.__init__(self) - self.info = info - - def __str__(self): - return self.info - - -class ControlConfigError(ControlError): - """PDFGuiControl exception class -- object config is invalid.""" - - pass - - -class ControlFileError(ControlError): - """PDFGuiControl exception class -- object config is invalid.""" - - pass - - -class ControlKeyError(ControlError): - """PDFGuiControl exception class -- requested object can't be - found.""" - - pass - - -class ControlValueError(ControlError): - """PDFGuiControl exception class -- Invalid value.""" - - pass - - -class ControlTypeError(ControlError): - """PDFGuiControl exception class -- Type mismatch.""" - - pass - - -class ControlStatusError(ControlError): - """PDFGuiControl exception class -- Fitting status doesn't match.""" - - pass - - -class ControlRuntimeError(ControlError): - """PDFGuiControl exception class -- various irrecoverable runtime - error.""" - - pass - - -class ControlIndexError(ControlError): - """PDFGuiControl exception class -- index out of bound.""" - - pass - - -class ControlSyntaxError(ControlError): - """PDFGuiControl exception class -- invalid syntax of constraint - formula.""" - - pass - - -class TempControlSelectError(ControlError): - """Temporary define this error to identify the select-control error - in python3.""" - - pass - - -# End of file diff --git a/src/diffpy/pdfgui/control/fitdataset.py b/src/diffpy/pdfgui/control/fitdataset.py deleted file mode 100644 index a9147658..00000000 --- a/src/diffpy/pdfgui/control/fitdataset.py +++ /dev/null @@ -1,869 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""Class FitDataSet for experimental PDF data and related fitting -parameters.""" - -import copy - -import numpy - -from diffpy.pdfgui.control.controlerrors import ControlStatusError -from diffpy.pdfgui.control.parameter import Parameter -from diffpy.pdfgui.control.pdfdataset import PDFDataSet -from diffpy.utils.resampler import wsinterp - - -class FitDataSet(PDFDataSet): - """FitDataSet stores experimental and calculated PDF data and - related fitting parameters. Inherited from PDFDataSet. - - Data members (in addition to those in PDFDataSet): - - fitrmin -- lower boundary for data fitting, property - fitrmax -- upper boundary for data fitting, property - fitrstep -- r-step used for fitted data, property - constraints -- dictionary of { var_string : Constraint_instance } - initial -- dictionary of initial values of refinable variables - refined -- dictionary of refined values of refinable variables - - Calculated members: - - rcalc -- list of r points where Gcalc is calculated, cached property - Gcalc -- list of calculated G values, cached property - dGcalc -- list of standard deviations of Gcalc, cached property - Gtrunc -- Gobs resampled to rcalc grid, cached property - dGtrunc -- dGobs resampled to rcalc grid, cached property - Gdiff -- difference curve, Gdiff = Gtrunc - Gcalc, property - crw -- cumulative rw of the fit - - The data in rcalc, Gcalc, dGcalc, Gtrunc, dGtrunc are recalculated - and cached when r-sampling changes. Any change to fitrmin, - fitrmax and fitrstep sets the _rcalc_changed flag. - - Refinable variables: qdamp, qbroad, dscale - Note: self.refvar is the same as self.initial[refvar]. - - Class data: - - persistentItems -- list of attributes saved in project file - """ - - persistentItems = [ - "rcalc", - "Gcalc", - "dGcalc", - "fitrmin", - "fitrmax", - "fitrstep", - "initial", - "refined", - ] - - def __init__(self, name): - """Initialize FitDataSet. - - name -- name of the data set. It must be a unique identifier. - """ - self.initial = {} - self.refined = {} - PDFDataSet.__init__(self, name) - self.clear() - return - - def __setattr__(self, name, value): - """Assign refinable variables to self.initial.""" - if name in PDFDataSet.refinableVars: - self.initial[name] = value - else: - PDFDataSet.__setattr__(self, name, value) - return - - def __getattr__(self, name): - """Obtain refinable variables from self.initial. - - This is called only when normal attribute lookup fails. - """ - if name in PDFDataSet.refinableVars: - value = self.initial[name] - else: - emsg = "A instance has no attribute '%s'" % name - raise AttributeError(emsg) - return value - - def _getStrId(self): - """Make a string identifier. - - return value: string id - """ - return "d_" + self.name - - def getYNames(self): - """Get names of data item which can be plotted as y. - - returns list of strings - """ - ynames = ["Gobs", "Gcalc", "Gdiff", "Gtrunc", "dGcalc", "crw"] + list(self.constraints.keys()) - return ynames - - def getXNames(self): - """Get names of data item which can be plotted as x. - - returns list of strings - """ - return [ - "r", - ] - - def getData(self, name, step=-1): - """Get self's data member. - - name -- data item name - step -- step info, it can be: - (1) a number ( -1 means latest step ): for single step - (2) a list of numbers: for multiple steps - (3) None: for all steps - - returns data object, be it a single number, a list, or a list of list - """ - # FIXME: for next plot interface, we need find how many steps the - # plotter is requiring for and make exact same number of copies of - # data in below - if name in self.metadata: - return self.metadata[name] - elif name in ("Gobs", "Gcalc", "Gtrunc", "Gdiff", "crw", "robs", "rcalc"): - d = getattr(self, name) - - # for Gtrunc and rcalc, we can use Gobs and robs instead when they - # are not ready. - if not d: - if name == "Gtrunc": - return getattr(self, "Gobs") - if name == "rcalc": - return getattr(self, "robs") - - return d - - # otherwise fitting's repository is preferred - return self.owner._getData(self, name, step) - - def clear(self): - """Reset all data members to initial empty values.""" - PDFDataSet.clear(self) - self._rcalc_changed = True - self._rcalc = [] - self._Gcalc = [] - self._dGcalc = [] - self._Gtrunc = [] - self._dGtrunc = [] - self._crw = [] - self._fitrmin = 0.5 - self._fitrmax = None - self._fitrstep = None - self.constraints = {} - self.refined = {} - return - - def clearRefined(self): - """Clear all refinement results.""" - self.Gcalc = [] - self.dGcalc = [] - self.crw = [] - self.refined = {} - return - - def obtainRefined(self, server, idataset): - """Upload refined datataset from PdfFit server instance. - - server -- instance of PdfFit server - idataset -- index of this dataset in server - """ - server.setdata(idataset) - # obtain Gcalc, dGcalc and crw from the server - self.Gcalc = server.getpdf_fit() - self.dGcalc = server.getpdf_diff() - self.crw = server.getcrw() - # get variables from the server - for var in PDFDataSet.refinableVars: - self.refined[var] = server.getvar(var) - return - - def read(self, filename): - """Same as readObs().""" - return self.readObs(filename) - - def _updateRcalcRange(self): - """Helper method for updating fitrmin, fitrmax and fitrstep just - after reading observed values. - - No return value. - """ - frmin = self.fitrmin or self.rmin - self.fitrmin = max(frmin, self.rmin) - frmax = self.fitrmax or self.rmax - self.fitrmax = min(frmax, self.rmax) - self.fitrstep = self.fitrstep or self.getObsSampling() - return - - def readObs(self, filename): - """Load experimental PDF data from PDFGetX2 or PDFGetN gr file. - - filename -- file to read from - - returns self - """ - PDFDataSet.read(self, filename) - self._updateRcalcRange() - return self - - def readStr(self, datastring): - """Same as readObsStr().""" - return self.readObsStr(datastring) - - def readObsStr(self, datastring): - """Read experimental PDF data from a string. - - datastring -- string of raw data - - returns self - """ - PDFDataSet.readStr(self, datastring) - self._updateRcalcRange() - return self - - def write(self, filename): - """Same as writeCalc(). Use writeObs() to save experimental PDF - data. - - filename -- name of file to write to - - No return value. - """ - self.writeCalc(filename) - return - - def writeCalc(self, filename): - """Write calculated PDF data to a file. - - filename -- name of file to write to - - No return value. - """ - txt = self.writeCalcStr() - f = open(filename, "w") - f.write(txt) - f.close() - return - - def writeStr(self): - """Same as writeCalcStr. Use writeObsStr() for experimental - PDF. - - Return data string. - """ - return self.writeCalcStr() - - def writeCalcStr(self): - """String representation of calculated PDF data. - - Return data string. - """ - if self.Gcalc == []: - raise ControlStatusError("Gcalc not available") - import time - from getpass import getuser - - lines = [] - # write metadata - lines.extend( - [ - "History written: " + time.ctime(), - "produced by " + getuser(), - "##### PDFgui fit", - ] - ) - # stype - if self.stype == "X": - lines.append("stype=X x-ray scattering") - elif self.stype == "N": - lines.append("stype=N neutron scattering") - # qmax - if self.qmax: - lines.append("qmax=%.2f" % self.qmax) - # qdamp - lines.append("qdamp=%g" % self.refined["qdamp"]) - # qbroad - lines.append("qbroad=%g" % self.refined["qbroad"]) - # dscale - lines.append("dscale=%g" % self.refined["dscale"]) - # fitrmin, fitrmax - if self.fitrmin is not None and self.fitrmax is not None: - lines.append("fitrmin=%g" % self.fitrmin) - lines.append("fitrmax=%g" % self.fitrmax) - # metadata - if len(self.metadata) > 0: - lines.append("# metadata") - for k, v in self.metadata.items(): - lines.append("%s=%s" % (k, v)) - # write data: - lines.append("##### start data") - lines.append("#L r(A) G(r) d_r d_Gr Gdiff") - # cache Gdiff here so it is not calculated many times - Gdiff = self.Gdiff - drcalc = 0.0 - for i in range(len(self.rcalc)): - lines.append("%g %g %.1f %g %g" % (self.rcalc[i], self.Gcalc[i], drcalc, self.dGcalc[i], Gdiff[i])) - # lines are ready here - datastring = "\n".join(lines) + "\n" - return datastring - - def writeObs(self, filename): - """Write observed PDF data to a file. - - filename -- name of file to write to - - No return value. - """ - PDFDataSet.write(self, filename) - return - - def writeObsStr(self): - """String representation of observed PDF data. - - Return data string. - """ - return PDFDataSet.writeStr(self) - - def _resampledPDFDataSet(self): - """Return instance of PDFDataSet with resampled observed data. - - Helper method for writeResampledObs and writeResampledObsStr. - """ - resampled = PDFDataSet(self.name) - self.copy(resampled) - resampled.robs = self.rcalc - resampled.drobs = len(self.rcalc) * [0.0] - resampled.Gobs = self.Gtrunc - resampled.dGobs = self.dGtrunc - return resampled - - def writeResampledObs(self, filename): - """Write resampled PDF data in Gtrunc to a file. - - filename -- name of the file to write to - - No return value. - """ - resampled = self._resampledPDFDataSet() - resampled.write(filename) - return - - def writeResampledObsStr(self): - """String representation of resampled PDF data in Gtrunc. - - Return data string. - """ - resampled = self._resampledPDFDataSet() - s = resampled.writeStr() - return s - - def findParameters(self): - """Obtain dictionary of parameters used by self.constraints. The - keys of returned dictionary are integer parameter indices, and - their values Parameter instances, with guessed initial values. - - returns dictionary of indices and Parameter instances - """ - foundpars = {} - for var, con in self.constraints.items(): - con.guess(self.getvar(var)) - for pidx, pguess in con.parguess.items(): - # skip if already found - if pidx in foundpars: - continue - # insert to foundpars otherwise - if pguess is not None: - foundpars[pidx] = Parameter(pidx, initial=pguess) - else: - foundpars[pidx] = Parameter(pidx, initial=0.0) - return foundpars - - def applyParameters(self, parameters): - """Evaluate constraint formulas and adjust self.initial. - - parameters -- dictionary of parameter indices with Parameter instances. - Dictionary may also have float-type values. - """ - # convert values to floats - parvalues = {} - for pidx, par in parameters.items(): - if isinstance(par, Parameter): - parvalues[pidx] = par.initialValue() - else: - parvalues[pidx] = float(par) - # evaluate constraints - for var, con in self.constraints.items(): - # __setattr__ assigns var in self.initial - self.setvar(var, con.evalFormula(parvalues)) - return - - def changeParameterIndex(self, oldidx, newidx): - """Change a parameter index to a new value. - - This will replace all instances of one parameter name with - another in this fit. - """ - import re - - for var in self.constraints: - formula = self.constraints[var].formula - pat = r"@%i\b" % oldidx - newformula = re.sub(pat, "@%i" % newidx, formula) - self.constraints[var].formula = newformula - return - - def copy(self, other=None): - """Copy self to other. if other is None, create new instance. - - other -- ref to other object - - returns reference to copied object - """ - # check arguments - if other is None: - other = FitDataSet(self.name) - PDFDataSet.copy(self, other) - if isinstance(other, FitDataSet): - # assigned attributes - other._fitrmin = self._fitrmin - other._fitrmax = self._fitrmax - other._fitrstep = self._fitrstep - other._rcalc_changed = self._rcalc_changed - # copied attributes - other.constraints = copy.deepcopy(self.constraints) - other.initial = copy.deepcopy(self.initial) - other.refined = copy.deepcopy(self.refined) - # must also update the sampling on the new object - st = self.getFitSamplingType() - other.setFitSamplingType(st, self.fitrstep) - return other - - def load(self, z, subpath): - """Load data from a zipped project file. - - z -- zipped project file - subpath -- path to its own storage within project file - """ - import pickle - - from diffpy.pdfgui.utils import asunicode - - self.clear() - subs = subpath.split("/") - rootDict = z.fileTree[subs[0]][subs[1]][subs[2]][subs[3]] - # raw data - obsdata = asunicode(z.read(subpath + "obs")) - self.readObsStr(obsdata) - - # data from calculation - content = pickle.loads(z.read(subpath + "calc"), encoding="latin1") - for item in FitDataSet.persistentItems: - # skip items which are not in the project file - if item not in content: - continue - # update dictionaries so that old project files load fine - if item == "initial": - self.initial.update(content[item]) - elif item == "refined": - self.refined.update(content[item]) - else: - setattr(self, item, content[item]) - self._updateRcalcRange() - - # constraints - if "constraints" in rootDict: - from diffpy.pdfgui.control.pdfguicontrol import CtrlUnpickler - - self.constraints = CtrlUnpickler.loads(z.read(subpath + "constraints")) - # handle renamed variable from old project files - translate = {"qsig": "qdamp", "qalp": "qbroad"} - for old, new in translate.items(): - if old in self.constraints: - self.constraints[new] = self.constraints.pop(old) - - return - - def save(self, z, subpath): - """Save data to a zipped project file. - - z -- zipped project file - subpath -- path to its own storage within project file - """ - from diffpy.pdfgui.utils import safeCPickleDumps - - # write raw data - z.writestr(subpath + "obs", self.writeObsStr()) - content = {} - for item in FitDataSet.persistentItems: - content[item] = getattr(self, item, None) - spkl = safeCPickleDumps(content) - z.writestr(subpath + "calc", spkl) - - # make a picklable dictionary of constraints - if self.constraints: - spkl = safeCPickleDumps(self.constraints) - z.writestr(subpath + "constraints", spkl) - return - - # interface for data sampling - - def getFitSamplingType(self): - """Description of r-sampling used in the fit. This method - compares self.fitrstep with r-sampling in the observed data and - with Nyquist r step. - - Return a string, possible values are "data", "Nyquist" or - "custom". - """ - eps = 1e-8 - if abs(self.fitrstep - self.getObsSampling()) < eps: - rv = "data" - elif abs(self.fitrstep - self.getNyquistSampling()) < eps: - rv = "Nyquist" - else: - rv = "custom" - return rv - - def setFitSamplingType(self, tp, value=None): - """GUI interface to set fitrstep, i.e., r-grid for fitting. - - tp -- description of fit sampling type. Possible values are - "data" ... same as used in experimental PDF - "Nyquist" ... sampling at Nyquist spacing - "custom" ... user specified value - value -- new value of fitrstep, only used when tp is "custom". - - No return value. - - Raises ValueError for unknown tp string. - """ - if tp == "data": - self.fitrstep = self.getObsSampling() - elif tp == "Nyquist": - self.fitrstep = self.getNyquistSampling() - elif tp == "custom": - self.fitrstep = max(value, self.getObsSampling()) - else: - emsg = "Invalid value for fit sampling type." - raise ValueError(emsg) - return - - def getObsSampling(self): - """Return the average r-step used in robs or zero when not - defined.""" - n = len(self.robs) - if n > 1: - rv = (self.robs[-1] - self.robs[0]) / (n - 1.0) - else: - rv = 0.0 - return rv - - def getNyquistSampling(self): - """Return r-step corresponding to Nyquist sampling at the qmax - value. - - When qmax is zero, return r-step in the observed data. - """ - if self.qmax > 0.0: - rv = numpy.pi / self.qmax - else: - rv = self.getObsSampling() - return rv - - # Property Attributes - - def _updateRcalcSampling(self): - """Helper method for resampling rcalc and interpolating related - data. This method interpolates Gcalc, dGcalc, Gtrunc, dGtrunc, - crw to new r grid. - - No return value. - """ - if not self._rcalc_changed: - return - frmin, frmax = self.fitrmin, self.fitrmax - frstep = float(self.fitrstep) - # new rcalc must cover the whole [fitrmin, fitrmax] interval - # otherwise pdffit2 would complain - robs_below = [ri for ri in self.robs if ri < frmin] - if robs_below: - rcalcfirst = robs_below[-1] - else: - rcalcfirst = self.robs[0] - nrcalc = numpy.round(1.0 * (frmax - rcalcfirst) / frstep) - if frmax - (rcalcfirst + nrcalc * frstep) > frstep * 1e-8: - nrcalc += 1 - newrcalc = rcalcfirst + frstep * numpy.arange(nrcalc + 1) - tp = self.getFitSamplingType() - # Gcalc: - if len(self._Gcalc) > 0: - newGcalc = grid_interpolation(self._rcalc, self._Gcalc, newrcalc, tp=tp) - self._Gcalc = list(newGcalc) - # dGcalc - if len(self._dGcalc) > 0: - newdGcalc = grid_interpolation(self._rcalc, self._dGcalc, newrcalc, tp=tp) - self._dGcalc = list(newdGcalc) - # invalidate Gtrunc and dGtrunc - self._Gtrunc = [] - self._dGtrunc = [] - # everything has been interpolated here, we can overwrite _rcalc - self._rcalc = list(newrcalc) - # and finally set flag for up to date cache - self._rcalc_changed = False - return - - # fitrmin - - def _get_fitrmin(self): - return self._fitrmin - - def _set_fitrmin(self, value): - self._rcalc_changed = True - self._fitrmin = float(value) - return - - fitrmin = property(_get_fitrmin, _set_fitrmin, doc="Lower boundary for simulated PDF curve.") - - # fitrmax - - def _get_fitrmax(self): - return self._fitrmax - - def _set_fitrmax(self, value): - self._rcalc_changed = True - self._fitrmax = float(value) - return - - fitrmax = property(_get_fitrmax, _set_fitrmax, doc="Upper boundary for simulated PDF curve.") - - # fitrstep - - def _get_fitrstep(self): - return self._fitrstep - - def _set_fitrstep(self, value): - self._rcalc_changed = True - self._fitrstep = float(value) - return - - fitrstep = property(_get_fitrstep, _set_fitrstep, doc="R-step used for simulated PDF curve.") - - # rcalc - - def _get_rcalc(self): - self._updateRcalcSampling() - return self._rcalc - - def _set_rcalc(self, value): - self._rcalc = value - return - - rcalc = property( - _get_rcalc, - _set_rcalc, - doc="""R-grid for refined data, read-only. - Use fitrmin, fitrmax, fitrstep to change it""", - ) - - # Gcalc - - def _get_Gcalc(self): - self._updateRcalcSampling() - return self._Gcalc - - def _set_Gcalc(self, value): - self._Gcalc = value - return - - Gcalc = property(_get_Gcalc, _set_Gcalc, doc="List of calculate G values.") - - # dGcalc - - def _get_dGcalc(self): - self._updateRcalcSampling() - return self._dGcalc - - def _set_dGcalc(self, value): - self._dGcalc = value - return - - dGcalc = property(_get_dGcalc, _set_dGcalc, doc="List of standard deviations of Gcalc.") - - # Gtrunc - - def _get_Gtrunc(self): - self._updateRcalcSampling() - if not self._Gtrunc: - tp = self.getFitSamplingType() - newGtrunc = grid_interpolation(self.robs, self.Gobs, self.rcalc, tp=tp) - self._Gtrunc = list(newGtrunc) - return self._Gtrunc - - def _set_Gtrunc(self, value): - self._Gtrunc = value - return - - Gtrunc = property(_get_Gtrunc, _set_Gtrunc, doc="Gobs resampled to rcalc grid.") - - # dGtrunc - - def _get_dGtrunc(self): - self._updateRcalcSampling() - if not self._dGtrunc: - tp = self.getFitSamplingType() - # use sum to avoid index error for empty arrays - newdGtrunc = grid_interpolation( - self.robs, - self.dGobs, - self.rcalc, - left=sum(self.dGobs[:1]), - right=sum(self.dGobs[-1:]), - tp=tp, - ) - self._dGtrunc = list(newdGtrunc) - return self._dGtrunc - - def _set_dGtrunc(self, value): - self._dGtrunc = value - return - - dGtrunc = property(_get_dGtrunc, _set_dGtrunc, doc="dGobs resampled to rcalc grid.") - - # Gdiff - - def _get_Gdiff(self): - if len(self.Gcalc): - rv = [(yo - yc) for yo, yc in zip(self.Gtrunc, self.Gcalc)] - else: - rv = [] - return rv - - Gdiff = property(_get_Gdiff, doc="Difference between observed and calculated PDF on rcalc grid.") - - # crw - def _get_crw(self): - # crw comes from the engine, so it doesn't need rescaling - return self._crw - - def _set_crw(self, value): - if len(value) != len(self.rcalc): - self._crw = [0.0] * len(self.rcalc) - else: - self._crw = value[:] - return - - crw = property(_get_crw, _set_crw, doc="cumulative rw on rcalc grid") - - # End of Property Attributes - - -# End of class FitDataSet - - -############################################################################## -# helper functions -############################################################################## -def _linear_interpolation(x0, y0, x1, youtleft, youtright): - - x0 = numpy.asarray(x0, copy=None, dtype=float) - y0 = numpy.asarray(y0, copy=None, dtype=float) - n0 = len(x0) - x1 = numpy.asarray(x1, copy=None, dtype=float) - n1 = len(x1) - y1 = youtright * numpy.ones(n1, dtype=float) - if n0: - y1[x1 < x0.min()] = youtleft - # take care of special n0 lengths - if n0 == 0: - return y1 - elif n0 == 1: - y1[x1 == x0[0]] = y0[0] - return y1 - # here n0 > 1 so we can safely calculate dx0 - dx0 = (x0[-1] - x0[0]) / (n0 - 1.0) - epsx = dx0 * 1e-8 - # find covered values in x1 - (m1,) = numpy.where(numpy.logical_and(x0[0] - epsx < x1, x1 < x0[-1] + epsx)) - ilo0 = numpy.floor((x1[m1] - x0[0]) / dx0) - ilo0 = numpy.array(ilo0, dtype=int) - # ilo0 may be out of bounds for x1 close to the edge - ilo0[ilo0 < 0] = 0 - ilo0[ilo0 > n0 - 2] = n0 - 2 - ihi0 = ilo0 + 1 - # make sure hi indices remain valid - w0hi = (x1[m1] - x0[ilo0]) / dx0 - w0lo = 1.0 - w0hi - y1[m1] = w0lo * y0[ilo0] + w0hi * y0[ihi0] - return y1 - - -def grid_interpolation(x0, y0, x1, left=None, right=None, tp=None): - """Interpolate values from one grid onto another using either linear - or Whittaker–Shannon interpolation. - - Parameters - ---------- - x0 : array_like - Original x-grid, must be equally spaced. - y0 : array_like - Original values defined on x0. - x1 : array_like - New x-grid upon which to interpolate. - tp : {'data', 'Nyquist', 'custom'}, optional - Corresponding fit sampling type. Use Whittaker–Shannon interpolation - for Nyquist resampling and linear interpolation otherwise. - If not provided, linear interpolation is used. - left : float, optional - Value for interpolated y1 for x1 below the x0 range. - Default: if tp='Nyquist' then y1[0] is used. Otherwise 0.0 is used. - right : float, optional - Value for interpolated y1 for x1 above the x0 range. - Default: if tp='Nyquist' then y1[-1] is used. Otherwise 0.0 is used. - - Returns - ------- - numpy.ndarray - Array of interpolated values on the new grid x1. - - Notes - ----- - When tp='Nyquist', the function calls :func:`wsinterp` to perform Whittaker–Shannon interpolation. - Otherwise it uses the internal :func:`_linear_interpolation` routine. - """ - if tp == "Nyquist": - x0 = numpy.asarray(x0) - x1 = numpy.asarray(x1) - y0 = numpy.asarray(y0) - return wsinterp(x1, x0, y0, left, right) - else: - left = 0.0 if left is None else left - right = 0.0 if right is None else right - return _linear_interpolation(x0, y0, x1, left, right) - - -# simple test code -if __name__ == "__main__": - FitDataSet("name") - -# End of file diff --git a/src/diffpy/pdfgui/control/fitstructure.py b/src/diffpy/pdfgui/control/fitstructure.py deleted file mode 100644 index d4141c56..00000000 --- a/src/diffpy/pdfgui/control/fitstructure.py +++ /dev/null @@ -1,901 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""Class FitStructure for storage of one phase and related fitting -parameters.""" - -import copy -import re - -import numpy - -from diffpy.pdfgui.control.constraint import Constraint -from diffpy.pdfgui.control.controlerrors import ControlTypeError, ControlValueError -from diffpy.pdfgui.control.parameter import Parameter -from diffpy.pdfgui.control.pdfstructure import PDFStructure -from diffpy.structure import Atom - - -class FitStructure(PDFStructure): - """FitStructure holds initial and refined structure and related fit - parameters. Inherited from PDFStructure. - - Class data members: - symposeps -- tolerance for recognizing site as symmetry position - - Data members (in addition to those in PDFStructure): - owner -- instance of parent Fitting (set in Organizer.add()) - initial -- initial structure, same as self - refined -- refined structure when available or None - constraints -- dictionary of { refvar_string : Constraint_instance } - selected_pairs -- string of selected pairs, by default "all-all". - Use setSelectedPairs() and getSelectedPairs() methods - to access its value. - custom_spacegroup -- instance of SpaceGroup which has no equivalent - in diffpy.structure.spacegroups module. This can happen - after reading from a CIF file. When equivalent space - group exists, custom_spacegroup is None. - - Refinable variables: pscale, spdiameter, delta1, delta2, sratio, lat(n), - where n=1..6, x(i), y(i), z(i), occ(i), u11(i), u22(i), u33(i), - u12(i), u13(i), u23(i), where i=1..Natoms - - Non-refinable variable: rcut, stepcut - """ - - # class data members: - symposeps = 0.001 - # evaluation of sorted_standard_space_groups deferred when necessary - sorted_standard_space_groups = [] - - def __init__(self, name, *args, **kwargs): - """Initialize FitDataSet. - - name -- name of the data set. The same name is used for - self.initial and self.final. - args, kwargs -- optional arguments passed to parent PDFStructure - """ - PDFStructure.__init__(self, name) - self.owner = None - # self.initial deliberately not assigned, - # it gets mapped to self by __getattr__ - self.refined = None - self.constraints = {} - self.selected_pairs = "all-all" - self.initial.pdffit["sgoffset"] = [0.0, 0.0, 0.0] - self.custom_spacegroup = None - return - - def _update_custom_spacegroup(self, parser): - """Helper method for read() and readStr(), which takes care of - setting custom_spacegroup after successful reading. - - parser -- instance of StructureParser used in reading. - - No return value. - """ - self.custom_spacegroup = None - self.initial.pdffit["sgoffset"] = [0.0, 0.0, 0.0] - if hasattr(parser, "spacegroup"): - sg = parser.spacegroup - # when sg.number is None or 0, we have a custom spacegroup - if not sg.number: - # overwrite sg.number with 0, an identifier for custom SG - sg.number = 0 - self.custom_spacegroup = sg - # here sg.number is 0 or positive integer - self.initial.pdffit["spcgr"] = sg.short_name - return - - def read(self, filename, format="auto"): - """Load structure from a file, raise ControlFileError for - invalid or unknown structure format. Overloads - PDFStructure.read() to handle custom_spacegroup attribute. - - filename -- file to be loaded - format -- structure format such as 'pdffit', 'pdb', 'xyz'. When - 'auto' all available formats are tried in a row. - - Return instance of StructureParser used to load the data. - See Structure.read() for more info. - """ - p = PDFStructure.read(self, filename, format) - # update data only after successful reading - self._update_custom_spacegroup(p) - # FIXME Temporary workaround to prevent forced isotropy of the Uij - # values. To be removed and handled by atom isotropy column. - self.anisotropy = True - return p - - def readStr(self, s, format="auto"): - """Same as PDFStructure.readStr, but handle the - custom_spacegroup data. - - Return instance of StructureParser used to load the data. See - Structure.readStr() for more info. - """ - p = PDFStructure.readStr(self, s, format) - # update data only after successful reading - self._update_custom_spacegroup(p) - # FIXME Temporary workaround to prevent forced isotropy of the Uij - # values. To be removed and handled by atom isotropy column. - self.anisotropy = True - return p - - def __getattr__(self, name): - """Map self.initial to self. - - This is called only when normal attribute lookup fails. - """ - if name == "initial": - value = self - else: - emsg = "A instance has no attribute '%s'" % name - raise AttributeError(emsg) - return value - - def _getStrId(self): - """Make a string identifier. - - return value: string id - """ - return "p_" + self.name - - def clearRefined(self): - """Clear all refinement results.""" - self.refined = None - return - - def obtainRefined(self, server, iphase): - """Upload refined phase from PdfFit server instance. - - server -- instance of PdfFit server - iphase -- index of this phase in server - """ - server.setphase(iphase) - if self.refined is None: - self.refined = PDFStructure(self.name) - self.refined.readStr(server.save_struct_string(iphase), "pdffit") - return - - def findParameters(self): - """Obtain dictionary of parameters used by self.constraints. The - keys of returned dictionary are integer parameter indices, and - the values are Parameter instances, with guessed initial values. - - returns dictionary of indices and Parameter instances - """ - foundpars = {} - for var, con in self.constraints.items(): - con.guess(self.initial.getvar(var)) - for pidx, pguess in con.parguess.items(): - # skip if already found - if pidx in foundpars: - continue - # insert to foundpars otherwise - if pguess is not None: - foundpars[pidx] = Parameter(pidx, initial=pguess) - else: - foundpars[pidx] = Parameter(pidx, initial=0.0) - return foundpars - - def applyParameters(self, parameters): - """Evaluate constraint formulas and adjust initial PDFStructure. - - parameters -- dictionary of parameter indices with Parameter - instance values. Values may also be float type. - """ - # convert values to floats - parvalues = {} - for pidx, par in parameters.items(): - if isinstance(par, Parameter): - parvalues[pidx] = par.initialValue() - else: - parvalues[pidx] = float(par) - # evaluate constraints - for var, con in self.constraints.items(): - self.initial.setvar(var, con.evalFormula(parvalues)) - return - - def changeParameterIndex(self, oldidx, newidx): - """Change a parameter index to a new value. - - This will replace all instances of one parameter name with - another in this fit. - """ - for var in self.constraints: - formula = self.constraints[var].formula - pat = r"@%i\b" % oldidx - newformula = re.sub(pat, "@%i" % newidx, formula) - self.constraints[var].formula = newformula - return - - def _popAtomConstraints(self): - """Take out atom-related items from the constraints dictionary. - - This is useful when atom indices are going to change due to - insertion or removal of atoms. See also _restoreAtomConstraints(). - - Return a dictionary of atom instances vs dictionary of related - refinable variables (stripped of "(siteindex)") and Constraint - instances - for example {atom : {'u13' : constraint}}. - """ - rv = {} - # atom variable pattern - avpat = re.compile(r"^([xyz]|occ|u11|u22|u33|u12|u13|u23)\((\d+)\)") - for var in list(self.constraints.keys()): - m = avpat.match(var) - if not m: - continue - barevar = m.group(1) - atomidx = int(m.group(2)) - 1 - cnts = rv.setdefault(self.initial[atomidx], {}) - cnts[barevar] = self.constraints.pop(var) - return rv - - def _restoreAtomConstraints(self, acd): - """Restore self.constraints from atom constraints dictionary. - This is useful for getting correct atom indices into refvar - strings. See also _popAtomConstraints() - - acd -- dictionary obtained from _popAtomConstraints() - """ - for i, a in enumerate(self.initial): - if a not in acd: - continue - # there are some constraints for atom a - siteindex = i + 1 - cnts = acd[a] - for barevar, con in cnts.items(): - var = barevar + "(%i)" % siteindex - self.constraints[var] = con - return - - def insertAtoms(self, index, atomlist): - """Insert list of atoms before index and adjust - self.constraints. - - index -- position in the initial structure, atoms are appended - when larger than len(self.initial). - atomlist -- list of atom instances. - """ - acd = self._popAtomConstraints() - # FIXME Temporary workaround to prevent forced isotropy of the Uij - # values. To be removed and handled by atom isotropy column. - for a in atomlist: - a.anisotropy = True - # workaround ends here. - self.initial[index:index] = atomlist - self._restoreAtomConstraints(acd) - return - - def deleteAtoms(self, indices): - """Removed atoms at given indices and adjust self.constraints. - - indices -- list of integer indices of atoms to be deleted - """ - acd = self._popAtomConstraints() - # get unique, reverse sorted indices - ruindices = sorted(set(indices), reverse=True) - for i in ruindices: - self.initial.pop(i) - self._restoreAtomConstraints(acd) - return - - def expandSuperCell(self, mno): - """Perform supercell expansion for this structure and adjust - constraints for positions and lattice parameters. New lattice - parameters are multiplied and fractional coordinates divided by - corresponding multiplier. New atoms are grouped with their - source in the original cell. - - mno -- tuple or list of three positive integer cell multipliers along - the a, b, c axis - """ - # check argument - if tuple(mno) == (1, 1, 1): - return - if min(mno) < 1: - raise ControlValueError("mno must contain 3 positive integers") - # back to business - acd = self._popAtomConstraints() - mnofloats = numpy.array(mno[:3], dtype=float) - ijklist = [(i, j, k) for i in range(mno[0]) for j in range(mno[1]) for k in range(mno[2])] - # build a list of new atoms - newatoms = [] - for a in self.initial: - for ijk in ijklist: - adup = Atom(a) - adup.xyz = (a.xyz + ijk) / mnofloats - newatoms.append(adup) - # does atom a have any constraint? - if a not in acd: - continue - # add empty constraint dictionary for duplicate atom - acd[adup] = {} - for barevar, con in acd[a].items(): - formula = con.formula - if barevar in ("x", "y", "z"): - symidx = "xyz".index(barevar) - if ijk[symidx] != 0: - formula += " + %i" % ijk[symidx] - if mno[symidx] > 1: - formula = "(%s)/%.1f" % (formula, mno[symidx]) - formula = re.sub(r"\((@\d+)\)", r"\1", formula) - # keep other formulas intact and add constraint - # for barevar of the duplicate atom - acd[adup][barevar] = Constraint(formula) - # replace original atoms with newatoms - self.initial[:] = newatoms - for ai, an in zip(self.initial, newatoms): - if an in acd: - acd[ai] = acd[an] - # and rebuild their constraints - self._restoreAtomConstraints(acd) - # take care of lattice parameters - self.initial.lattice.setLatPar( - a=mno[0] * self.initial.lattice.a, - b=mno[1] * self.initial.lattice.b, - c=mno[2] * self.initial.lattice.c, - ) - # adjust lattice constraints if present - latvars = ("lat(1)", "lat(2)", "lat(3)") - for var, multiplier in zip(latvars, mno): - if var in self.constraints and multiplier > 1: - con = self.constraints[var] - formula = "%.0f*(%s)" % (multiplier, con.formula) - formula = re.sub(r"\((@\d+)\)", r"\1", formula) - con.formula = formula - return - - def isSpaceGroupPossible(self, spacegroup): - """Check if space group is consistent with lattice parameters. - - spacegroup -- instance of SpaceGroup - - Return bool. - """ - from diffpy.structure.symmetryutilities import isSpaceGroupLatPar - - return isSpaceGroupLatPar(spacegroup, *self.initial.lattice.abcABG()) - - def getSpaceGroupList(self): - """Return a list of SpaceGroup instances sorted by International - Tables number. - - When custom_spacegroup is defined, the list starts with - custom_spacegroup. - """ - if not FitStructure.sorted_standard_space_groups: - import diffpy.structure.spacegroups as SG - - existing_names = {} - unique_named_list = [] - for sg in SG.SpaceGroupList: - if sg.short_name not in existing_names: - unique_named_list.append(sg) - existing_names[sg.short_name] = True - # sort by International Tables number, stay compatible with 2.3 - n_sg = [(sg.number % 1000, sg) for sg in unique_named_list] - n_sg = sorted(n_sg, key=lambda x: x[0]) # sort by the first element of tuple. - FitStructure.sorted_standard_space_groups = [sg for n, sg in n_sg] - sglist = list(FitStructure.sorted_standard_space_groups) - if self.custom_spacegroup: - sglist.insert(0, self.custom_spacegroup) - return sglist - - def getSpaceGroup(self, sgname): - """Find space group in getSpaceGroupList() by short_name or - number. sgname can be non-standard in case of CIF file defined - space group. - - Return instance of SpaceGroup. Raise ValueError if sgname cannot - be found or when it is not present in getSpaceGroupList(). - """ - import diffpy.structure.spacegroups as SG - - # this should match the "CIF data" sgname - sgmatch = [sg for sg in self.getSpaceGroupList() if sg.short_name == sgname] - # use standard lookup function when not matched by short_name - if not sgmatch: - sgmatch.append(SG.GetSpaceGroup(sgname)) - if not sgmatch: - emsg = "Unknown space group %r" % sgname - raise ValueError(emsg) - sgfound = sgmatch[0] - return sgfound - - def expandAsymmetricUnit(self, spacegroup, indices, sgoffset=[0, 0, 0]): - """Perform symmetry expansion for atoms at given indices. - Temperature factors may be corrected to reflect the symmetry. - All constraints for expanded atoms are erased with the exception - of the occupancy("occ". Constraints of unaffected atoms are - adjusted for new positions self.initial. - - spacegroup -- instance of SpaceGroup from diffpy.structure - indices -- list of integer indices of atoms to be expanded - sgoffset -- optional offset of space group origin [0,0,0] - """ - from diffpy.structure.symmetryutilities import ExpandAsymmetricUnit - - acd = self._popAtomConstraints() - # get unique, reverse sorted indices - ruindices = sorted(set(indices), reverse=True) - coreatoms = [self.initial[i] for i in ruindices] - corepos = [a.xyz for a in coreatoms] - coreUijs = [a.U for a in coreatoms] - eau = ExpandAsymmetricUnit(spacegroup, corepos, coreUijs, sgoffset=sgoffset, eps=self.symposeps) - # build a nested list of new atoms: - newatoms = [] - for i in range(len(coreatoms)): - ca = coreatoms[i] - caocc_con = None - if ca in acd and "occ" in acd[ca]: - caocc_con = acd[ca]["occ"] - eca = [] # expanded core atom - for j in range(eau.multiplicity[i]): - a = Atom(ca) - a.xyz = eau.expandedpos[i][j] - a.U = eau.expandedUijs[i][j] - eca.append(a) - if caocc_con is None: - continue - # make a copy of occupancy constraint - acd[a] = {"occ": copy.copy(caocc_con)} - newatoms.append(eca) - # insert new atoms where they belong - for i, atomlist in zip(ruindices, newatoms): - self.initial[i : i + 1] = atomlist - # remember this spacegroup as the last one used - self.initial.pdffit["spcgr"] = spacegroup.short_name - self.initial.pdffit["sgoffset"] = list(sgoffset) - # tidy constraints - self._restoreAtomConstraints(acd) - return - - def applySymmetryConstraints(self, spacegroup, indices, posflag, Uijflag, sgoffset=[0, 0, 0]): - """Generate symmetry constraints for positions and thermal - factors. Both positions and thermal factors may get corrected to - reflect space group symmetry. Old positional and thermal - constraints get erased. New parameter indices start at fist - decade after the last used parameter. - - spacegroup -- instance of SpaceGroup from diffpy.structure - indices -- list of integer indices of atoms to be expanded - posflag -- required bool flag for constraining positions - Uijflag -- required bool flag for Uij constrainment - sgoffset -- optional offset of space group origin [0,0,0] - """ - if not posflag and not Uijflag: - return - # need to do something - from diffpy.structure.symmetryutilities import SymmetryConstraints - - # get unique sorted indices - tobeconstrained = dict.fromkeys(indices) - uindices = sorted(tobeconstrained.keys()) - # remove old constraints - pospat = re.compile(r"^([xyz])\((\d+)\)") - Uijpat = re.compile(r"^(u11|u22|u33|u12|u13|u23)\((\d+)\)") - for var in list(self.constraints.keys()): - mpos = posflag and pospat.match(var) - mUij = Uijflag and Uijpat.match(var) - if mpos and (int(mpos.group(2)) - 1) in tobeconstrained: - del self.constraints[var] - elif mUij and (int(mUij.group(2)) - 1) in tobeconstrained: - del self.constraints[var] - # find the largest used parameter index; pidxused must have an element - pidxused = [i for i in self.owner.updateParameters()] + [0] - # new parameters will start at the next decade - parzeroidx = 10 * (int(max(pidxused) / 10)) + 10 - # dictionary of parameter indices and their values - newparvalues = {} - selatoms = [self.initial[i] for i in uindices] - selpos = [a.xyz for a in selatoms] - selUijs = [a.U for a in selatoms] - symcon = SymmetryConstraints(spacegroup, selpos, selUijs, sgoffset=sgoffset, eps=self.symposeps) - # deal with positions - if posflag: - # fix positions: - for a, xyz in zip(selatoms, symcon.positions): - a.xyz = xyz - possymbols, parvalues = _makeParNames(symcon.pospars, parzeroidx) - newparvalues.update(parvalues) - eqns = symcon.positionFormulasPruned(possymbols) - for aidx, eq in zip(uindices, eqns): - siteidx = aidx + 1 - for barevar, formula in eq.items(): - var = barevar + "(%i)" % siteidx - self.constraints[var] = Constraint(formula) - # deal with temperature factors - if Uijflag: - # fix thermals - for a, Uij in zip(selatoms, symcon.Uijs): - a.U = Uij - Usymbols, parvalues = _makeParNames(symcon.Upars, parzeroidx) - newparvalues.update(parvalues) - eqns = symcon.UFormulasPruned(Usymbols) - for aidx, eq in zip(uindices, eqns): - siteidx = aidx + 1 - for barevar, formula in eq.items(): - # keys in formula dictionary are uppercase - var = barevar.lower() + "(%i)" % siteidx - self.constraints[var] = Constraint(formula) - # update parameter values in parent Fitting - self.owner.updateParameters() - for pidx, pvalue in newparvalues.items(): - parobj = self.owner.parameters[pidx] - parobj.setInitial(pvalue) - # and finally remember this space group - self.initial.pdffit["spcgr"] = spacegroup.short_name - self.initial.pdffit["sgoffset"] = list(sgoffset) - return - - def setSelectedPairs(self, s): - """Set the value of selected_pairs to s, raise ControlValueError - when s has invalid syntax. The selected_pairs is a comma - separated list of words formatted as. - - [!]{element|indexOrRange|all}-[!]{element|indexOrRange|all} - - where '!' excludes the given atoms from first or second pair. - - Examples: - - all-all all possible pairs - Na-Na only Na-Na pairs - all-all, !Na- all pairs except Na-Na (first index skips Na) - all-all, -!Na same as previous (second index skips Na) - Na-1:4 pairs of Na and first 4 atoms - all-all, !Cl-!Cl exclude any pairs containing Cl - all-all, !Cl-, -!Cl same as previous - 1-all only pairs including the first atom - - Use getPairSelectionFlags() method to get a list of included values - for first and second pair index. - """ - # check syntax of s - psf = self.getPairSelectionFlags(s) - self.selected_pairs = psf["fixed_pair_string"] - return - - def getSelectedPairs(self): - return self.selected_pairs - - def getPairSelectionFlags(self, s=None): - """Translate string s to a list of allowed values for first and - second pair index. Raise ControlValueError for invalid syntax - of s. See setSelectedPairs() docstring for a definition of pair - selection syntax. - - s -- string describing selected pairs (default: self.selected_pairs) - - Return a dictionary with following keys: - - firstflags -- list of selection flags for first indices - secondflags -- list of selection flags for second indices - fixed_pair_string -- argument corrected to standard syntax - """ - if s is None: - s = self.selected_pairs - Natoms = len(self.initial) - # sets of first and second indices - firstflags = Natoms * [False] - secondflags = Natoms * [False] - # words of fixed_pair_string - words_fixed = [] - s1 = s.strip(" \t,") - words = re.split(r" *, *", s1) - for w in words: - wparts = w.split("-") - if len(wparts) != 2: - emsg = "Selection word '%s' must contain one dash '-'." % w - raise ControlValueError(emsg) - sel0 = self._parseAtomSelectionString(wparts[0]) - sel1 = self._parseAtomSelectionString(wparts[1]) - wfixed = sel0["fixedstring"] + "-" + sel1["fixedstring"] - words_fixed.append(wfixed) - for idx, flg in sel0["flags"].items(): - firstflags[idx] = flg - for idx, flg in sel1["flags"].items(): - secondflags[idx] = flg - # build returned dictionary - rv = { - "firstflags": firstflags, - "secondflags": secondflags, - "fixed_pair_string": ", ".join(words_fixed), - } - return rv - - def applyPairSelection(self, server, phaseidx): - """Apply pair selection for calculations of partial PDF. - - server -- instance of PdfFit engine - phaseidx -- phase index in PdfFit engine starting from 1 - """ - psf = self.getPairSelectionFlags() - idx = 0 - for iflag, jflag in zip(psf["firstflags"], psf["secondflags"]): - idx += 1 - server.selectAtomIndex(phaseidx, "i", idx, iflag) - server.selectAtomIndex(phaseidx, "j", idx, jflag) - return - - def getSelectedIndices(self, s): - """Indices of the atoms that match the specified selection - string. - - s -- selection string consisting of one or more atom selection - words formatted as [!]{element|indexOrRange|all} - Example: "1:4, 7, Cl". - - Return a list of integers. - Raise ControlValueError for invalid selection string format. - """ - s1 = "".join(c for c in s if not c.isspace()) - words = s1.split(",") - indices = set() - for w in words: - asd = self._parseAtomSelectionString(w) - for idx, flg in asd["flags"].items(): - if flg: - indices.add(idx) - else: - indices.discard(idx) - rv = sorted(indices) - return rv - - # Regular expression object for matching atom selection strings. - # Will be assign with the first call to _parseAtomSelectionString. - _rxatomselection = None - - def _parseAtomSelectionString(self, s): - """Process string that describes a set of atoms in the - structure. - - s -- selection string formatted as [!]{element|indexOrRange|all} - "!" negates the selection, indexOrRange can be 1, 1:4, - where atom indices starts from 1, and "all" matches all atoms. - - Return a dictionary with following keys: - 'fixedstring' -- selection string adjusted to standard formatting - 'flags' -- dictionary of atom indices and boolean flags for - normal or negated selection. - Raise ControlValueError for invalid string format. - """ - # delayed initialization of the class variable - if self._rxatomselection is None: - FitStructure._rxatomselection = re.compile( - r""" - (?P!?) # exclamation point - (?:(?P[a-zA-Z]+)$| # element|all or - (?P\d+)(?P:\d+)?$ # number range - )""", - re.VERBOSE, - ) - assert self._rxatomselection - Natoms = len(self.initial) - flags = {} - rv = {"fixedstring": "", "flags": flags} - # allow empty string and return an empty flags dictionary - s1 = s.replace(" ", "") - if not s1: - return rv - mx = self._rxatomselection.match(s1) - if not mx: - emsg = "Invalid selection syntax in '%s'" % s - raise ControlValueError(emsg) - if mx.group("negate"): - rv["fixedstring"] = "!" - flg = not mx.group("negate") - # process atom type - if mx.group("element"): - elfixed = mx.group("element") - elfixed = elfixed[0:1].upper() + elfixed[1:].lower() - if elfixed == "All": - flags.update(dict.fromkeys(range(Natoms), flg)) - rv["fixedstring"] += elfixed.lower() - else: - for idx in range(Natoms): - if self.initial[idx].element == elfixed: - flags[idx] = flg - rv["fixedstring"] += elfixed - # process range - else: - lo = max(int(mx.group("start")) - 1, 0) - rv["fixedstring"] += mx.group("start") - hi = lo + 1 - if mx.group("stop"): - hi = int(mx.group("stop")[1:]) - rv["fixedstring"] += mx.group("stop") - hi = min(hi, Natoms) - flags.update(dict.fromkeys(range(lo, hi), flg)) - return rv - - def copy(self, other=None): - """Copy self to other. if other is None, create new instance. - - other -- reference to other object - - returns reference to copied object - """ - # check arguments - if other is None: - other = FitStructure(self.name) - elif not isinstance(other, PDFStructure): - emsg = "other must be PDFStructure or FitStructure" - raise ControlTypeError(emsg) - # copy initial structure (self) to other - PDFStructure.copy(self, other) - # copy refined structure to other when it is FitStructure - if isinstance(other, FitStructure): - if self.refined is None: - other.refined = None - else: - other.refined = self.refined.copy(other.refined) - # copy constraints - other.constraints = copy.deepcopy(self.constraints) - other.selected_pairs = self.selected_pairs - return other - - def load(self, z, subpath): - """Load structure from a zipped project file. - - z -- zipped project file - subpath -- path to its own storage within project file - """ - # subpath = projname/fitname/structure/myname/ - from diffpy.pdfgui.control.pdfguicontrol import CtrlUnpickler - from diffpy.pdfgui.utils import asunicode - - subs = subpath.split("/") - rootDict = z.fileTree[subs[0]][subs[1]][subs[2]][subs[3]] - strudata = asunicode(z.read(subpath + "initial")) - self.initial.readStr(strudata, "pdffit") - # refined - if "refined" in rootDict: - self.refined = PDFStructure(self.name) - refdata = asunicode(z.read(subpath + "refined")) - self.refined.readStr(refdata, "pdffit") - # constraints - if "constraints" in rootDict: - self.constraints = CtrlUnpickler.loads(z.read(subpath + "constraints")) - translate = {"gamma": "delta1", "delta": "delta2", "srat": "sratio"} - for old, new in translate.items(): - if old in self.constraints: - self.constraints[new] = self.constraints.pop(old) - # selected_pairs - if "selected_pairs" in rootDict: - self.selected_pairs = asunicode(z.read(subpath + "selected_pairs")) - # sgoffset - if "sgoffset" in rootDict: - sgoffsetstr = asunicode(z.read(subpath + "sgoffset")) - sgoffset = [float(w) for w in sgoffsetstr.split()] - self.initial.pdffit["sgoffset"] = sgoffset - # custom_spacegroup - if "custom_spacegroup" in rootDict: - spkl = z.read(subpath + "custom_spacegroup") - self.custom_spacegroup = CtrlUnpickler.loads(spkl) - return - - def save(self, z, subpath): - """Save structure to a zipped project file. - - z -- zipped project file - subpath -- path to its own storage within project file - """ - from diffpy.pdfgui.utils import safeCPickleDumps - - z.writestr(subpath + "initial", self.initial.writeStr("pdffit")) - if self.refined: - z.writestr(subpath + "refined", self.refined.writeStr("pdffit")) - if self.constraints: - spkl = safeCPickleDumps(self.constraints) - z.writestr(subpath + "constraints", spkl) - z.writestr(subpath + "selected_pairs", self.selected_pairs) - # sgoffset - sgoffset = self.initial.pdffit.get("sgoffset", [0.0, 0.0, 0.0]) - sgoffsetstr = "%g %g %g" % tuple(sgoffset) - z.writestr(subpath + "sgoffset", sgoffsetstr) - if self.custom_spacegroup: - spkl = safeCPickleDumps(self.custom_spacegroup) - z.writestr(subpath + "custom_spacegroup", spkl) - return - - def getYNames(self): - """Get names of data item which can be plotted as y. - - returns a name str list - """ - return list(self.constraints.keys()) - - def getXNames(self): - """Get names of data item which can be plotted as x. - - returns a name str list - """ - # in fact nothing - return [] - - def getData(self, name, step=-1): - """Get self's data member. - - name -- data item name - step -- step info, it can be: - (1) a number ( -1 means latest step ): for single step - (2) a list of numbers: for multiple steps - (3) None: for all steps - - returns data object, be it a single number, a list, or a list of list - """ - # FIXME: for next plot interface, we need find how many steps the - # plotter is requiring for and make exact same number of copies of - # data by name - data = self.owner.getMetaData(name) - if data is not None: - return data - return self.owner._getData(self, name, step) - - -# End of class FitStructure - -# Local helper functions ----------------------------------------------------- - - -def _makeParNames(sympars, parzeroindex): - """Return a tuple of (symbols, parvalues), where symbols is a list - of unique PDFFit parameter strings in "@%i" format and parvalues is - a dictionary of parameter indices and their values. The symbols have - indices 10n + (1, 2, 3) when referring to x, y, z, or 10n + (4, 5, - 6, 7, 8, 9) when referring to Uij. - - sympars -- pospars or Upars attribute of a SymmetryConstraints object - Must be a sequence of symbols and values. - parzeroindex -- the offset of all parameter indices. - Must be a multiple of 10. - - Return a tuple of (possymbols, Usymbols, parvalues). - This function is only used in FitStructure.applySymmetryConstraints method. - """ - if parzeroindex % 10: - raise ValueError("parzeroindex must be a multiple of 10.") - smbindex = { - "x": 1, - "y": 2, - "z": 3, - "U11": 4, - "U22": 5, - "U33": 6, - "U12": 7, - "U13": 8, - "U23": 9, - } - symbols = [] - parvalues = {} - for smb, value in sympars: - if smb[:1] == "U": - nsite = 10 * int(smb[3:]) - nvar = smbindex[smb[:3]] - else: - nsite = 10 * int(smb[1:]) - nvar = smbindex[smb[:1]] - pidx = parzeroindex + nsite + nvar - symbols.append("@%i" % pidx) - parvalues[pidx] = value - assert len(symbols) == len(parvalues) - rv = (symbols, parvalues) - return rv - - -# End of file diff --git a/src/diffpy/pdfgui/control/fitting.py b/src/diffpy/pdfgui/control/fitting.py deleted file mode 100644 index d6b7dc6a..00000000 --- a/src/diffpy/pdfgui/control/fitting.py +++ /dev/null @@ -1,823 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Jiwu Liu -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -from __future__ import print_function - -import pickle -import threading -import time - -from diffpy.pdfgui.control.controlerrors import ControlError, ControlStatusError, ControlValueError -from diffpy.pdfgui.control.organizer import Organizer -from diffpy.pdfgui.utils import safeCPickleDumps - -# helper routines to deal with PDFfit2 exceptions - - -def getEngineExceptions(): - """Return a tuple of possible exceptions from - diffpy.pdffit2.pdffit2.""" - from diffpy.pdffit2.pdffit2 import ( - calculationError, - constraintError, - dataError, - structureError, - unassignedError, - ) - - engine_exceptions = ( - dataError, - unassignedError, - constraintError, - structureError, - calculationError, - ) - return engine_exceptions - - -def handleEngineException(error, gui=None): - """Common handler of PDFfit2 engine exceptions. - - error -- instance of PDFfit2 exception - gui -- reference to GUI when active - """ - errorInfo = "(%s)\n%s" % (error.__class__.__name__, str(error)) - # be more verbose for Singular matrix exception - if "singular matrix" in errorInfo.lower(): - errorInfo += ( - "\n\n" - "Common reasons are degeneracy in fit parameters,\n" - "zero thermal factors or fit range starting at zero." - ) - if gui: - gui.postEvent(gui.ERROR, " %s" % errorInfo) - else: - print(" %s" % errorInfo) - return - - -############################################################################## -class Fitting(Organizer): - """Fitting is the class to control a PdfFit process running locally. - Fitting will start a new thread to interact with the PdfFit server. - - rw: fitness parameter - tolerancy: accuracy requirement - step: current refinement step - res: fitting result string - parameters: parameter dictionary - """ - - # Fit status -- mask 0xff - INITIALIZED = 1 - CONNECTED = 1 << 1 - CONFIGURED = 1 << 2 - DONE = 1 << 3 - - # JOB Status -- mask 0xff00 - VOID = 1 << 8 - QUEUED = 1 << 9 - RUNNING = 1 << 10 - PAUSED = 1 << 11 - - class Worker(threading.Thread): - """Worker is the daemon thread of fitting.""" - - def __init__(self, fitting): - """Worker ( self, fitting) --> initialize. - - fitting -- fitting object - """ - threading.Thread.__init__(self) - self.fitting = fitting - - def run(self): - """Overload function from Thread.""" - try: - self.fitting.run() - except ControlError as error: - gui = self.fitting.controlCenter.gui - if gui: - gui.postEvent(gui.ERROR, " %s" % error.info) - else: - print(" %s" % error.info) - except getEngineExceptions() as error: - gui = self.fitting.controlCenter.gui - handleEngineException(error, gui) - return - - def __init__(self, name): - """initialize. - - name -- name of this fitting - """ - Organizer.__init__(self, name) - - # Thread, status, and control variables - self.thread = None - self.pauseEvent = threading.Event() - self.fitStatus = Fitting.INITIALIZED - self.jobStatus = Fitting.VOID - self.stopped = False - self.paused = False - - # the PDFfit2 server instance. - self.server = None - - # public data members - self.step = 0 - self.parameters = {} - self.rw = 1.0 - self.tolerancy = 0.001 - self.res = "" - self.snapshots = [] - self.res = "" - - # All the calculated data are to be stored in a list. - # Such flat storage require unique index for each data item - # self.dataNameDict translate named data to an index - self.dataNameDict = {} - self.itemIndex = 0 - - def __changeStatus(self, fitStatus=None, jobStatus=None): - """Change current status of fitting. - - fitStatus -- new fitting status - jobStatus -- new thread status - """ - self.fitStatus = fitStatus or self.fitStatus - self.jobStatus = jobStatus or self.jobStatus - if fitStatus or jobStatus: # either of them is not None - gui = self.controlCenter.gui - if gui: - gui.postEvent(gui.UPDATE, self) - gui.postEvent(gui.OUTPUT, None) - - def _release(self): - """Release resources.""" - if self.server: # server has been allocated, we need free the memory - self.server.reset() - - def _getStrId(self): - """Make a string identifier. - - return value: string id - """ - return "f_" + self.name - - def copy(self, other=None): - """Copy self to other. if other is None, create an instance. - - other -- ref to other object - return value: reference to copied object - """ - if other is None: - other = Fitting(self.name) - import copy - - Organizer.copy(self, other) - other.parameters = copy.deepcopy(self.parameters) - other.snapshots = copy.deepcopy(self.snapshots) - other.res = copy.deepcopy(self.res) - other.dataNameDict = copy.deepcopy(self.dataNameDict) - other.itemIndex = self.itemIndex - return other - - def load(self, z, subpath): - """Load data from a zipped project file. - - z -- zipped project file - subpath -- path to its own storage within project file - - returns a tree of internal hierarchy - """ - # subpath = projName/fitName/ - subs = subpath.split("/") - rootDict = z.fileTree[subs[0]][subs[1]] - - if "parameters" in rootDict: - from diffpy.pdfgui.control.pdfguicontrol import CtrlUnpickler - - self.parameters = CtrlUnpickler.loads(z.read(subpath + "parameters")) - if "steps" in rootDict: - self.itemIndex, self.dataNameDict, self.snapshots = pickle.loads( - z.read(subpath + "steps"), encoding="latin1" - ) - if "result" in rootDict: - self.rw, self.res = pickle.loads(z.read(subpath + "result"), encoding="latin1") - - return Organizer.load(self, z, subpath) - - def save(self, z, subpath): - """Save data from a zipped project file. - - z -- zipped project file - subpath -- path to its own storage within project file - """ - if self.parameters: - spkl = safeCPickleDumps(self.parameters) - z.writestr(subpath + "parameters", spkl) - if self.res: - spkl = safeCPickleDumps((self.rw, self.res)) - z.writestr(subpath + "result", spkl) - if self.snapshots: - spkl = safeCPickleDumps((self.itemIndex, self.dataNameDict, self.snapshots)) - z.writestr(subpath + "steps", spkl) - Organizer.save(self, z, subpath) - return - - def stripped(self): - """Make a copy stripped of all unpickleable data members. - The copy should be suitable for pickling and has the - following data members removed: - controlCenter, lock, pauseEvent, thread - - returns reference to stripped copy - """ - unpickleables = ("controlCenter", "lock", "pauseEvent", "thread") - naked = self.copy() - for a in unpickleables: - if a in self.__dict__: - delattr(naked, a) - return naked - - def updateParameters(self): - """Update parameters dictionary from active constraints. - - returns self.parameters - """ - # create dictionary of parameters used in constraints - cpars = {} - for struc in self.strucs: - for idx, par in struc.findParameters().items(): - if idx not in cpars: - cpars[idx] = par - for dataset in self.datasets: - for idx, par in dataset.findParameters().items(): - if idx not in cpars: - cpars[idx] = par - # add new parameters - for idx, par in cpars.items(): - if idx not in self.parameters: - self.parameters[idx] = par - # remove unused parameters - unused = [idx for idx in self.parameters if idx not in cpars] - for idx in unused: - del self.parameters[idx] - return self.parameters - - def applyParameters(self): - """Evaluate all constrained variables using current - parameters.""" - for struc in self.strucs: - struc.applyParameters(self.parameters) - for dataset in self.datasets: - dataset.applyParameters(self.parameters) - return - - def changeParameterIndex(self, oldidx, newidx): - """Change a parameter index to a new value. - - This will replace all instances of one parameter name with - another in the containing fit. - """ - # Change the index in the current structure - for struc in self.strucs: - struc.changeParameterIndex(oldidx, newidx) - for dataset in self.datasets: - dataset.changeParameterIndex(oldidx, newidx) - - # Change the index if appears in linking equation initial values, e.g. - # '=thisfitname:oldidx' -> '=thisfitname:newidx' - fiteq = "=%s:%i" % (self.name, oldidx) - newfiteq = "=%s:%i" % (self.name, newidx) - - from diffpy.pdfgui.control.pdfguicontrol import pdfguicontrol - - fits = pdfguicontrol().fits - for fit in fits: - parameters = fit.parameters - for par in parameters.values(): - if par.initialStr() == fiteq: - par.setInitial(newfiteq) - - return - - def queue(self, enter=True): - """Queue or dequeue self. - - enter -- True to queue, False to dequeue - """ - if enter: - if self.jobStatus == Fitting.VOID: - self.__changeStatus(jobStatus=Fitting.QUEUED) - else: - if self.jobStatus == Fitting.QUEUED: - self.__changeStatus(jobStatus=Fitting.VOID) - - def getServer(self): - """Get a PDFfit2 instance either locally or remotely.""" - if self.fitStatus != Fitting.INITIALIZED: - return - # create a new instance of calculation server - from diffpy.pdffit2 import PdfFit - - self.server = PdfFit() - self.__changeStatus(fitStatus=Fitting.CONNECTED) - - def configure(self): - """Configure fitting.""" - if self.fitStatus != Fitting.CONNECTED: - return - - # make sure parameters are initialized - self.updateParameters() - self.server.reset() - for struc in self.strucs: - struc.clearRefined() - self.server.read_struct_string(struc.initial.writeStr("pdffit")) - for key, var in struc.constraints.items(): - self.server.constrain(key, var.formula) - - # phase parameters configured - - for dataset in self.datasets: - dataset.clearRefined() - self.server.read_data_string( - dataset.writeResampledObsStr(), - dataset.stype, - dataset.qmax, - dataset.qdamp, - ) - self.server.setvar("qbroad", dataset.qbroad) - for key, var in dataset.constraints.items(): - self.server.constrain(key, var.formula) - # Removed call to pdfrange call, because data were already - # resampled to at fit range. - # - # Pair selection applies only to the current dataset, - # therefore it has to be done here. - nstrucs = len(self.strucs) - for phaseidx, struc in zip(range(1, nstrucs + 1), self.strucs): - struc.applyPairSelection(self.server, phaseidx) - - for index, par in self.parameters.items(): - # clean any refined value - par.refined = None - self.server.setpar(index, par.initialValue()) # info[0] = init value - # fix if fixed. Note: all parameters are free after self.server.reset(). - if par.fixed: - self.server.fixpar(index) - - # build name dict - self.buildNameDict() - - self.__changeStatus(fitStatus=Fitting.CONFIGURED) - return - - def resetStatus(self): - """Reset status back to initialized.""" - self.snapshots = [] - self.step = 0 - if self.fitStatus == Fitting.INITIALIZED: - return # already reset - - # This status will mandate allocation of a new PdfFit instance - self.__changeStatus(fitStatus=Fitting.INITIALIZED) - - def run(self): - """Function to be run in daemon thread.""" - # Begin - self.__changeStatus(jobStatus=Fitting.RUNNING) - try: - for calc in self.calcs: - calc.start() - - while not self.stopped and self.datasets: - if not self.paused: - # quick check to make sure status is right - # will do nothing if status is CONFIGURED - self.getServer() - self.configure() - - # if self.refine_step return True, fitting is finished - if self.refine_step(): - break - else: - # Wait on an event, pause for a while - self.__changeStatus(jobStatus=Fitting.PAUSED) - self.pauseEvent.wait() - - # Recover from pause now - self.__changeStatus(jobStatus=Fitting.RUNNING) - - finally: - # whatever happened, resource should be released. - self._release() - - # job status should be changed because of thread exit - self.__changeStatus(jobStatus=Fitting.VOID) - return - - def _configureBondCalculation(self, struc): - """Prepare server for bond angle or bond length calculation. - - struc -- instance of PDFStructure - - No return value. - """ - # struc can be handle to FitStructure.initial - # let's make sure it is synchronized with current parameters - self.applyParameters() - self.getServer() - self.server.reset() - strucstr = struc.writeStr("pdffit") - self.server.read_struct_string(strucstr) - return - - def outputBondAngle(self, struc, i, j, k): - """Output bond angle defined by atoms i, j, k. The angle is - calculated using the shortest lengths ji and jk with respect to - periodic boundary conditions. - - struc -- instance of PDFStructure - i, j, k -- atom indices starting at 1 - - No return value. The result should be automatically added to - the Output Window, because all server output is sent there. - - Raise ControlValueError for invalid indices i, j, k. - """ - try: - self._configureBondCalculation(struc) - self.server.bang(i, j, k) - self._release() - except getEngineExceptions() as error: - gui = self.controlCenter.gui - handleEngineException(error, gui) - except ValueError as error: - raise ControlValueError(str(error)) - return - - def outputBondLengthAtoms(self, struc, i, j): - """Output shortest bond between atoms i, j. Periodic boundary - conditions are applied to find the shortest bond. - - struc -- instance of PDFStructure - i, j -- atom indices starting at 1 - - No return value. The result should be automatically added to - the Output Window, because all server output is sent there. - - Raise ControlValueError for invalid indices i, j. - """ - try: - self._configureBondCalculation(struc) - self.server.blen(i, j) - self._release() - except getEngineExceptions() as error: - gui = self.controlCenter.gui - handleEngineException(error, gui) - except ValueError as error: - raise ControlValueError(str(error)) - return - - def outputBondLengthTypes(self, struc, a1, a2, lb, ub): - """Output all a1-a2 bond lengths within specified range. - - struc -- instance of PDFStructure - a1 -- symbol of the first element in pair or "ALL" - a2 -- symbol of the second element in pair or "ALL" - lb -- lower bond length boundary - ub -- upper bond length boundary - - No return value. The result should be automatically added to - the Output Window, because all server output is sent there. - - Raise ControlValueError for invalid element symbols. - """ - try: - self._configureBondCalculation(struc) - self.server.blen(a1, a2, lb, ub) - self._release() - except getEngineExceptions() as error: - gui = self.controlCenter.gui - handleEngineException(error, gui) - except ValueError as error: - raise ControlValueError(str(error)) - return - - def pause(self, bPause=None): - """Pause ( self, bPause = None ) --> pause a fitting process. - - bPause -- True to pause, False to restart. If None, it will figure out - by itself. - """ - if bPause is None: - bPause = self.jobStatus == Fitting.RUNNING - - if bPause: - self.paused = True - else: - self.paused = False - self.pauseEvent.set() - - def start(self): - """Start fitting.""" - # check if paused - if self.jobStatus == Fitting.PAUSED: - self.pause(False) - return - - # clean up control variable - self.stopped = False - self.paused = False - self.resetStatus() - - # Restart fitting require another thread instance. - self.thread = Fitting.Worker(self) - self.thread.start() - - def stop(self): - """Stop the fitting.""" - self.stopped = True - - # wake up daemon thread if it is paused - if self.jobStatus == Fitting.PAUSED: - self.pause(False) - - def isThreadRunning(self): - """Check if fitting thread is running. - - return: True if running, False otherwise - """ - return self.thread is not None and self.thread.is_alive() - - def join(self): - """Wait for current fitting to finish.""" - if self.thread: - self.thread.join() - self.thread = None - - def close(self, force=False): - """Close up the fitting in order to exit. - - force -- if force to exit - """ - if force: - if self.isThreadRunning(): - self.stop() - # NOTE: Not waiting for thread to stop. There's no graceful - # way while user choose to stop forcefully - else: - if self.isThreadRunning(): - raise ControlStatusError("Fitting: Fitting %s is still running" % self.name) - if self.thread is not None: - self.thread.join() - - def buildNameDict(self): - """Build up a data name dictionary, which will map data name to - a unique index. - - The private dataNameDict has such structure: - { 'd_data1':{'Gobs':12, 'Gcalc':11, ....}, - 'd_data2':{'Gobs':10, 'Gcalc':9, ....}, - ... - 'p_ph1':{'lat(1)':1,'lat(2)':2, .....}, - 'p_ph1':{'lat(1)':3,'lat(2)':4, .....}, - ... - 'f_fit':{'rw':100, 1:101, 2:102} - } - - The value of each sub-dict is the corresponding index of this data - item in the snapshot. - The prefix d_ p_ f_ make dataset,struc,fitname unique within the - shared name space of dictionary - """ - self.itemIndex = 0 - dataNameDict = {} - - # dataNameDict for datasets - for dataset in self.datasets: - id = dataset._getStrId() - dataNameDict[id] = {} - for itemName in list(dataset.constraints.keys()) + ["Gcalc", "crw"]: - dataNameDict[id][itemName] = self.itemIndex - self.itemIndex += 1 - - # dataNameDict for strucs - for struc in self.strucs: - id = struc._getStrId() - dataNameDict[id] = {} - for itemName in struc.constraints.keys(): - dataNameDict[id][itemName] = self.itemIndex - self.itemIndex += 1 - - # dataNameDict for self - id = self._getStrId() - dataNameDict[id] = {} - dataNameDict[id]["rw"] = self.itemIndex - self.itemIndex += 1 - for parameter in self.parameters.keys(): - dataNameDict[id][parameter] = self.itemIndex - self.itemIndex += 1 - - # assign to self - self.dataNameDict = dataNameDict - - def appendStep(self, source): - """After a refinement step is done, append all data from self to - the historical storage, i.e., self.snapshots. - - source -- where to get the fitted data, in deed it's a PdfFit2 instance - """ - # self.itemIndex should store total number of items - snapshot = [None] * self.itemIndex - - # update datasets - seq = 1 - for dataset in self.datasets: - id = dataset._getStrId() - # set current dataset - source.setdata(seq) - # use nameDict for current dataset - nameDict = self.dataNameDict[id] - # get values for constrained variables - for name in dataset.constraints.keys(): - snapshot[nameDict[name]] = source.getvar(name) - - snapshot[nameDict["Gcalc"]] = dataset.Gcalc - snapshot[nameDict["crw"]] = dataset.crw - seq += 1 - - # update strucs - seq = 1 - for struc in self.strucs: - id = struc._getStrId() - # set current struc - source.setphase(seq) - # use nameDict for current struc - nameDict = self.dataNameDict[id] - # get values for constrained variables - for name in struc.constraints.keys(): - snapshot[nameDict[name]] = source.getvar(name) - seq += 1 - - # update global data - id = self._getStrId() - nameDict = self.dataNameDict[id] - snapshot[nameDict["rw"]] = self.rw - for parameter in self.parameters.keys(): - snapshot[nameDict[parameter]] = source.getpar(parameter) - - self.snapshots.append(snapshot) - - def refine_step(self): - """Run a single step of the fit. - - return value: True if refinement is finished, otherwise False - """ - if self.fitStatus == Fitting.DONE: - # do nothing but return finished - return True - - finished = self.server.refine_step(self.tolerancy) - - # get fitted data - idataset = 1 - for dataset in self.datasets: - dataset.obtainRefined(self.server, idataset) - idataset += 1 - - # get refined structure - istruc = 1 - for struc in self.strucs: - struc.obtainRefined(self.server, istruc) - istruc += 1 - - # update parameters - for idx, par in self.parameters.items(): - par.refined = self.server.getpar(idx) - - self.rw = self.server.getrw() - - self.step += 1 - self.appendStep(self.server) - - # update plots and structure renderer - gui = self.controlCenter.gui - if gui: - gui.postEvent(gui.OUTPUT, None) - gui.postEvent(gui.PLOTNOW, self) - - if finished: - self.res = "* %s\n\n" % time.ctime() + self.server.save_res_string() - self.__changeStatus(fitStatus=Fitting.DONE) - - return finished - - def getYNames(self): - """Get names of data item which can be plotted as y. - - returns a name str list - """ - names = list(self.parameters.keys()) - names.append("rw") - return names - - def getXNames(self): - """Get names of data item which can be plotted as x. - - returns a name str list - """ - return [] - - def getData(self, name, step=-1): - """Get self's data member. - - name -- data item name - step -- step info, it can be: - (1) a number ( -1 means latest step ): for single step - (2) a list of numbers: for multiple steps - (3) None: for all steps - - returns data object, be it a single number, a list, or a list of list - """ - # FIXME: for next plot interface, we need find how many steps the - # plotter is requiring for and make exact same number of copies of - # data by name - data = self.getMetaData(name) - if data is not None: - return data - - return self._getData(self, name, step) - - def getMetaDataNames(self): - """Return all applicable meta data names.""" - names = [] - for dataset in self.datasets: - # build up the name list - if not names: - names = list(dataset.metadata.keys()) - else: - for name in names[:]: - if name not in dataset.metadata: - names.remove(name) - return names - - def getMetaData(self, name): - """Get meta data value. - - name -- meta data name - returns meta data value - """ - try: - return self.datasets[0].metadata[name] - except (KeyError, IndexError): - return None - - def _getData(self, id, name, step=-1): - """Get any data member from snapshots. - - id -- reference to a Fitting/Calculation/Phase/DataSet object - name -- data item name - step -- step info, it can be: - (1) a number ( -1 means latest step ): for single step - (2) a list of numbers: for multiple steps - (3) None: for all steps - - returns data object, be it a single number, a list, or a list of list - """ - # find the unique index - if len(self.snapshots) == 0: - return None - try: - # if it is a 'int', it must be parameter. So only fitting has its value. - if isinstance(name, int): - id = self - nameDict = self.dataNameDict[id._getStrId()] - index = nameDict[name] - except KeyError: - return None # data is not ready - - if step is None: - return [snapshot[index] for snapshot in self.snapshots] - elif isinstance(step, list): - return [self.snapshots[i][index] for i in step] - else: - return self.snapshots[step][index] - - -# End of file diff --git a/src/diffpy/pdfgui/control/organizer.py b/src/diffpy/pdfgui/control/organizer.py deleted file mode 100644 index adadf6cd..00000000 --- a/src/diffpy/pdfgui/control/organizer.py +++ /dev/null @@ -1,288 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Jiwu Liu -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -from diffpy.pdfgui.control.calculation import Calculation -from diffpy.pdfgui.control.controlerrors import ControlTypeError -from diffpy.pdfgui.control.fitdataset import FitDataSet -from diffpy.pdfgui.control.fitstructure import FitStructure -from diffpy.pdfgui.control.pdfcomponent import PDFComponent - - -# Search datasets for spdiameter and its constraints -def spd_assigned(ds): - return bool(ds.spdiameter) - - -def spd_constrained(ds): - return "spdiameter" in ds.constraints - - -class Organizer(PDFComponent): - """Base class for Fitting. It holds separate lists of datasets, - strucs and calculations. - - datasets: dataset list - strucs: structure list - calcs: calculation list - """ - - def __init__(self, name): - """initialize. - - name -- component name - """ - from diffpy.pdfgui.control.pdflist import PDFList - - PDFComponent.__init__(self, name) - - self.datasets = PDFList() - self.strucs = PDFList() - self.calcs = PDFList() - - # self.metadata is created but not pickled only for the purpose - # of plotting. It holds common metadata from all its datasets - self.metadata = {} - - # controlCenter is the reference to global PDFGuiControl object - from diffpy.pdfgui.control.pdfguicontrol import pdfguicontrol - - self.controlCenter = pdfguicontrol() - - def __findList(self, id): - if isinstance(id, FitDataSet): - return self.datasets - elif isinstance(id, FitStructure): - return self.strucs - elif isinstance(id, Calculation): - return self.calcs - else: - emsg = "Unknown type object '%s'" % id.name - raise ControlTypeError(emsg) - - def add(self, id, position=None): - """Add structure/dataset/calculation. - - id -- reference to structure/dataset/calculation - position -- position to insert, by default the last one - """ - objList = self.__findList(id) - if position is None: - position = len(objList) - objList.insert(position, id) - - # successfully added, set the object owner - id.owner = self - - def remove(self, id): - """Remove structure/dataset/calculation. - - id -- reference to structure/dataset/calculation - """ - objList = self.__findList(id) - objList.remove(id) - return id - - def rename(self, id, newname): - """Rename structure/dataset/calculation. - - id -- reference to structure/dataset/calculation - newname -- new name to be given - """ - objList = self.__findList(id) - objList.rename(id.name, newname) - - def index(self, id): - """Find the position of item in the list. - - id -- id of object - return : object position - """ - objList = self.__findList(id) - return objList.index(id.name) - - def hasStructures(self): - """Check to see if there are structures.""" - return len(self.strucs) > 0 - - def getStructure(self, pos): - """Get structure by position. - - pos -- the position of structure in the list - """ - # The function can only be called by gui code. So don't catch IndexError - # Any IndexError is a program bug thus should be propagated as is. - return self.strucs[pos] - - def hasDataSets(self): - """Check to see if there are datasets.""" - return len(self.datasets) > 0 - - def getDataSet(self, pos): - """Get dataset by position. - - pos -- the position of dataset in the list - """ - # The function can only be called by gui code. So don't catch IndexError - # Any IndexError is a program bug thus should be propagated as is. - return self.datasets[pos] - - def hasCalculations(self): - """Check to see if there are calculations.""" - return len(self.calcs) > 0 - - def getCalculation(self, pos): - """Get calculation by position. - - pos -- the position of calculation in the list - """ - # The function can only be called by gui code. So don't catch IndexError - # Any IndexError is a program bug thus should be propagated as is. - return self.calcs[pos] - - def load(self, z, subpath): - """Load data from a zipped project file. - - z -- zipped project file - subpath -- path to its own storage within project file - - returns a tree of internal hierarchy - """ - # subpath = projName/myName/ - from urllib.parse import unquote_plus - - subs = subpath.split("/") - rootDict = z.fileTree[subs[0]][subs[1]] - if "structure" in rootDict: - for strucName in rootDict["structure"].keys(): - struc = FitStructure(unquote_plus(strucName)) - struc.load(z, subpath + "structure/" + strucName + "/") - self.add(struc) - - if "dataset" in rootDict: - for datasetName in rootDict["dataset"].keys(): - dataset = FitDataSet(unquote_plus(datasetName)) - dataset.load(z, subpath + "dataset/" + datasetName + "/") - self.add(dataset) - - if "calculation" in rootDict: - for calcName in rootDict["calculation"].keys(): - calc = Calculation(unquote_plus(calcName)) - calc.load(z, subpath + "calculation/" + calcName + "/") - self.add(calc) - - self.__forward_spdiameter() - - return self.organization() - - def save(self, z, subpath): - """Save data from a zipped project file. - - z -- zipped project file - subpath -- path to its own storage within project file - """ - # strucs and datasets - from urllib.parse import quote_plus - - for struc in self.strucs: - struc.save(z, subpath + "structure/" + quote_plus(struc.name) + "/") - for dataset in self.datasets: - dataset.save(z, subpath + "dataset/" + quote_plus(dataset.name) + "/") - for calc in self.calcs: - calc.save(z, subpath + "calculation/" + quote_plus(calc.name) + "/") - return - - def copy(self, other=None): - """Copy self to other. if other is None, create an instance. - - other -- ref to other object - returns reference to copied object - """ - if other is None: - other = Organizer(self.name) - - for dataset in self.datasets: - other.add(dataset.copy()) - for struc in self.strucs: - other.add(struc.copy()) - for calc in self.calcs: - other.add(calc.copy()) - return other - - def organization(self): - """Get internal organization. - - returns a tree of internal hierarchy - """ - org = [None] * 4 - org[0] = self - org[1] = [] - for dataset in self.datasets: - org[1].append((dataset.name, dataset)) - org[2] = [] - for struc in self.strucs: - org[2].append((struc.name, struc)) - org[3] = [] - for calc in self.calcs: - org[3].append((calc.name, calc)) - - return org - - def __forward_spdiameter(self): - """Copy spdiameter value loaded from fit or calculation to - phase. - - This method takes care of loading old PDFgui projects where - spdiameter belonged to FitDataSet or Calculation classes. It - should be called only from the Organizer.load method. - """ - # Jump out if any of structures has spdiameter set - for stru in self.strucs: - if stru.getvar("spdiameter"): - return - - # Figure out the value and constraint for spdiameter. - # The highest priority is for a dataset with constrained spdiameter, - # then for dataset with assigned spdiameter and finally from - # a calculation. - spd_val = spd_cns = None - constrained_datas = list(filter(spd_constrained, self.datasets)) - assigned_datas = list(filter(spd_assigned, self.datasets)) - assigned_calcs = list(filter(spd_assigned, self.calcs)) - if constrained_datas: - spd_val = constrained_datas[0].spdiameter - spd_cns = constrained_datas[0].constraints["spdiameter"] - elif assigned_datas: - spd_val = assigned_datas[0].spdiameter - elif assigned_calcs: - spd_val = assigned_calcs[0].spdiameter - # assign spd_val to all structures that don't have it set - for stru in self.strucs: - if spd_val and not stru.getvar("spdiameter"): - stru.setvar("spdiameter", spd_val) - if spd_cns: - stru.constraints.setdefault("spdiameter", spd_cns) - # finally remove any spdiameter constraints from all datasets - for ds in self.datasets: - ds.constraints.pop("spdiameter", None) - return - - -# End of class Organizer - -# simple test code -if __name__ == "__main__": - Organizer("name") - -# End of file diff --git a/src/diffpy/pdfgui/control/parameter.py b/src/diffpy/pdfgui/control/parameter.py deleted file mode 100644 index b366c856..00000000 --- a/src/diffpy/pdfgui/control/parameter.py +++ /dev/null @@ -1,194 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""Class Parameter for handling one refined parameter To be stored in -Fitting.parameters { idx : parameter } dictionary.""" - -from diffpy.pdfgui.control.controlerrors import ( - ControlError, - ControlKeyError, - ControlRuntimeError, - ControlTypeError, -) - - -class Parameter: - """Parameter is class for value and properties of refined parameter. - Because the initial value of Parameter may come from another - Fitting, it is accessed by setInitial(), initialStr() and - initialValue() methods. - - Data members: - idx -- integer identifier of this parameter in PdfFit - name -- optional description - refined -- refined value of the parameter, float or None. - fixed -- flag for fixing the parameter in refinement [False] - - Private members: - __initial -- stores the initial value, float, or "=fitname:idx" string - __fitrepr -- None or string representation of Fitting instance - """ - - # fits should reference PDFGuiControl.fits - - def __init__(self, idx, initial=0.0): - """Initialize new parameter. - - idx -- idx of this parameter in PdfFit - initial -- optional initial value of the parameter. - It can be float, Fitting, "=fitname" or "=fitname:idx" string. - """ - self.idx = idx - self.name = "" - self.refined = None - self.fixed = False - self.__initial = None - self.__fitrepr = None - self.setInitial(initial) - return - - def setInitial(self, initial): - """Set initial value to float or refined value from another - Fitting. - - initial -- initial value, it can be something convertible to float, - Fitting reference or string in "=fitname" or - "=fitname:idx" format. - """ - self.__fitrepr = None - from diffpy.pdfgui.control.fitting import Fitting - - try: - self.__initial = float(initial) - return - except (ValueError, TypeError): - pass - if isinstance(initial, Fitting): - self.__initial = "=" + initial.name - self.__fitrepr = repr(initial) - elif isinstance(initial, str) and initial[:1] == "=": - self.__initial = initial - self.__findLinkedFitting() - else: - raise ControlTypeError("invalid type of Parameter initial value") - return - - def initialStr(self): - """Convert initial value to string. - - returns string in "=fitname:idx" or "%f" format - """ - if isinstance(self.__initial, float): - s = str(self.__initial) - else: - self.__findLinkedFitting() - s = self.__initial - return s - - def initialValue(self): - """Convert initial value to float. - For linked parameters it may raise: - ControlKeyError if source Fitting does not exist - KeyError when parameter does not exist - ControlRunTimeError for self-dependent parameters - - returns the initial value - """ - if isinstance(self.__initial, float): - value = self.__initial - else: - try: - value = self.__getLinkedValue() - except RuntimeError as v: - # we will catch only recursion RuntimeError - if "maximum recursion" in str(v): - raise ControlRuntimeError("self-dependent parameter") - # other RuntimeError should be left alone - else: - raise - return float(value) - - def __getLinkedValue(self): - """Private retrieval of parameter value from linked Fitting.""" - # Check to see if the fit name has a ':' in it - isplit = self.__initial.split(":") - # Who needs regular expressions? - try: - if len(isplit) == 1: - srcidx = self.idx - fitname = self.__initial[1:] - else: - srcidx = int(isplit[-1]) - fitname = (":".join(isplit[:-1]))[1:] - except ValueError: - # __initial should be in the form "=fitname[:srcidx]" - raise ControlError("Malformed linked parameter %s" % self.__initial) - srcfit = self.__findLinkedFitting() - if srcfit is None: - raise ControlKeyError("Fitting '%s' does not exist" % fitname) - # Check to see if srcfit has parameter srcidx - try: - srcpar = srcfit.parameters[srcidx] - except KeyError: - raise ControlKeyError("Fitting '%s' has no parameter %s" % (fitname, srcidx)) - - if srcpar.refined is not None: - value = srcpar.refined - elif isinstance(srcpar.__initial, float): - value = srcpar.__initial - else: - value = srcpar.__getLinkedValue() - return value - - def __findLinkedFitting(self): - """Private search for linked Fitting by name and by - representation. Should be called only when initial value is - linked to another Fitting. Updates self.__initial and - self.__fitrepr. - - returns reference to Fitting when found or None - """ - # Check to see if the fit name has a ':' in it - isplit = self.__initial.split(":") - try: - srcidx = int(isplit[-1]) - fitname = (":".join(isplit[:-1]))[1:] - except ValueError: - fitname = self.__initial[1:] - srcidx = self.idx - self.__initial += ":%i" % srcidx - from diffpy.pdfgui.control.pdfguicontrol import pdfguicontrol - - fits = pdfguicontrol().fits - fitnames = [f.name for f in fits] - fitrepres = [repr(f) for f in fits] - # first find linked fitting by name - if fitname in fitnames: - idx = fitnames.index(fitname) - self.__fitrepr = fitrepres[idx] - ref = fits[idx] - # if not found by name, look up by representation - elif self.__fitrepr in fitrepres: - idx = fitrepres.index(self.__fitrepr) - self.__initial = "=%s:%i" % (fitnames[idx], srcidx) - ref = fits[idx] - # here self.__initial was not found, but let it pass - # maybe the linked fitting will be defined later - else: - self.__fitrepr = None - ref = None - return ref - - -# End of class Parameter diff --git a/src/diffpy/pdfgui/control/pdfcomponent.py b/src/diffpy/pdfgui/control/pdfcomponent.py deleted file mode 100644 index 2dc0a393..00000000 --- a/src/diffpy/pdfgui/control/pdfcomponent.py +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Jiwu Liu -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - - -class PDFComponent(object): - """Common base class.""" - - def __init__(self, name): - """initialize. - - name -- object name - """ - self.name = name - - def close(self, force=False): - """Close myself. - - force -- if forcibly (no wait) - """ - pass - - -# End of file diff --git a/src/diffpy/pdfgui/control/pdfdataset.py b/src/diffpy/pdfgui/control/pdfdataset.py deleted file mode 100644 index 34b6efba..00000000 --- a/src/diffpy/pdfgui/control/pdfdataset.py +++ /dev/null @@ -1,380 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""Class PDFDataSet for experimental PDF data.""" - -import copy -import os.path -import re -import time -from getpass import getuser - -from diffpy.pdfgui.control.controlerrors import ControlFileError, ControlKeyError -from diffpy.pdfgui.control.pdfcomponent import PDFComponent - - -class PDFDataSet(PDFComponent): - """PDFDataSet is a class for experimental PDF data. - - Data members: - robs -- list of observed r points - Gobs -- list of observed G values - drobs -- list of standard deviations of robs - dGobs -- list of standard deviations of Gobs - stype -- scattering type, 'X' or 'N' - qmax -- maximum value of Q in inverse Angstroms. Termination - ripples are neglected for qmax=0. - qdamp -- specifies width of Gaussian damping factor in pdf_obs due - to imperfect Q resolution - qbroad -- quadratic peak broadening factor related to dataset - spdiameter -- particle diameter for shape damping function - Note: This attribute was moved to PDFStructure. - It is kept for backward compatibility when reading - PDFgui project files. - dscale -- scale factor of this dataset - rmin -- same as robs[0] - rmax -- same as robs[-1] - filename -- set to absolute path after reading from file - metadata -- dictionary for other experimental conditions, such as - temperature or doping - - Global member: - persistentItems -- list of attributes saved in project file - refinableVars -- set (dict) of refinable variable names. - """ - - persistentItems = [ - "robs", - "Gobs", - "drobs", - "dGobs", - "stype", - "qmax", - "qdamp", - "qbroad", - "dscale", - "rmin", - "rmax", - "metadata", - ] - refinableVars = dict.fromkeys(("qdamp", "qbroad", "dscale")) - - def __init__(self, name): - """Initialize. - - name -- name of the data set. It must be a unique identifier. - """ - PDFComponent.__init__(self, name) - self.clear() - return - - def clear(self): - """Reset all data members to initial empty values.""" - self.robs = [] - self.Gobs = [] - self.drobs = [] - self.dGobs = [] - self.stype = "X" - # user must specify qmax to get termination ripples - self.qmax = 0.0 - self.qdamp = 0.001 - self.qbroad = 0.0 - self.spdiameter = None - self.dscale = 1.0 - self.rmin = None - self.rmax = None - self.filename = None - self.metadata = {} - return - - def setvar(self, var, value): - """Assign data member using PdfFit-style variable. Used by - applyParameters(). - - var -- string representation of dataset PdfFit variable. - Possible values: qdamp, qbroad, dscale - value -- new value of the variable - """ - barevar = var.strip() - fvalue = float(value) - if barevar in PDFDataSet.refinableVars: - setattr(self, barevar, fvalue) - else: - emsg = "Invalid PdfFit dataset variable %r" % barevar - raise ControlKeyError(emsg) - return - - def getvar(self, var): - """Obtain value corresponding to PdfFit dataset variable. Used - by findParameters(). - - var -- string representation of dataset PdfFit variable. - Possible values: qdamp, qbroad, dscale - - returns value of var - """ - barevar = var.strip() - if barevar in PDFDataSet.refinableVars: - value = getattr(self, barevar) - else: - emsg = "Invalid PdfFit dataset variable %r" % barevar - raise ControlKeyError(emsg) - return value - - def read(self, filename): - """Load data from PDFGetX2 or PDFGetN gr file. - - filename -- file to read from - - returns self - """ - try: - with open(filename) as fp: - self.readStr(fp.read()) - except PDFDataFormatError as err: - basename = os.path.basename(filename) - emsg = ("Could not open '%s' due to unsupported file format " + "or corrupted data. [%s]") % ( - basename, - err, - ) - raise ControlFileError(emsg) - self.filename = os.path.abspath(filename) - return self - - def readStr(self, datastring): - """Read experimental PDF data from a string. - - datastring -- string of raw data - - returns self - """ - self.clear() - # useful regex patterns: - rx = {"f": r"[-+]?(\d+(\.\d*)?|\d*\.\d+)([eE][-+]?\d+)?"} - # find where does the data start - res = re.search(r"^#+ start data\s*(?:#.*\s+)*", datastring, re.M) - # start_data is position where the first data line starts - if res: - start_data = res.end() - else: - # find line that starts with a floating point number - regexp = r"^\s*%(f)s" % rx - res = re.search(regexp, datastring, re.M) - if res: - start_data = res.start() - else: - start_data = 0 - header = datastring[:start_data] - databody = datastring[start_data:].strip() - - # find where the metadata starts - metadata = "" - res = re.search(r"^#+\ +metadata\b\n", header, re.M) - if res: - metadata = header[res.end() :] - header = header[: res.start()] - - # parse header - # stype - if re.search("(x-?ray|PDFgetX)", header, re.I): - self.stype = "X" - elif re.search("(neutron|PDFgetN)", header, re.I): - self.stype = "N" - # qmax - regexp = r"\bqmax *= *(%(f)s)\b" % rx - res = re.search(regexp, header, re.I) - if res: - self.qmax = float(res.groups()[0]) - # qdamp - regexp = r"\b(?:qdamp|qsig) *= *(%(f)s)\b" % rx - res = re.search(regexp, header, re.I) - if res: - self.qdamp = float(res.groups()[0]) - # qbroad - regexp = r"\b(?:qbroad|qalp) *= *(%(f)s)\b" % rx - res = re.search(regexp, header, re.I) - if res: - self.qbroad = float(res.groups()[0]) - # spdiameter - regexp = r"\bspdiameter *= *(%(f)s)\b" % rx - res = re.search(regexp, header, re.I) - if res: - self.spdiameter = float(res.groups()[0]) - # dscale - regexp = r"\bdscale *= *(%(f)s)\b" % rx - res = re.search(regexp, header, re.I) - if res: - self.dscale = float(res.groups()[0]) - # temperature - regexp = r"\b(?:temp|temperature|T)\ *=\ *(%(f)s)\b" % rx - res = re.search(regexp, header) - if res: - self.metadata["temperature"] = float(res.groups()[0]) - # doping - regexp = r"\b(?:x|doping)\ *=\ *(%(f)s)\b" % rx - res = re.search(regexp, header) - if res: - self.metadata["doping"] = float(res.groups()[0]) - - # parsing general metadata - if metadata: - regexp = r"\b(\w+)\ *=\ *(%(f)s)\b" % rx - while True: - res = re.search(regexp, metadata, re.M) - if res: - self.metadata[res.groups()[0]] = float(res.groups()[1]) - metadata = metadata[res.end() :] - else: - break - - # read actual data - robs, Gobs, drobs, dGobs - inf_or_nan = re.compile("(?i)^[+-]?(NaN|Inf)\\b") - has_drobs = True - has_dGobs = True - # raise PDFDataFormatError if something goes wrong - try: - for line in databody.split("\n"): - v = line.split() - # there should be at least 2 value in the line - self.robs.append(float(v[0])) - self.Gobs.append(float(v[1])) - # drobs is valid if all values are defined and positive - has_drobs = has_drobs and len(v) > 2 and not inf_or_nan.match(v[2]) - if has_drobs: - v2 = float(v[2]) - has_drobs = v2 > 0.0 - self.drobs.append(v2) - # dGobs is valid if all values are defined and positive - has_dGobs = has_dGobs and len(v) > 3 and not inf_or_nan.match(v[3]) - if has_dGobs: - v3 = float(v[3]) - has_dGobs = v3 > 0.0 - self.dGobs.append(v3) - if not has_drobs: - self.drobs = len(self.robs) * [0.0] - if not has_dGobs: - self.dGobs = len(self.robs) * [0.0] - except (ValueError, IndexError) as err: - raise PDFDataFormatError(err) - self.rmin = self.robs[0] - self.rmax = self.robs[-1] - if not has_drobs: - self.drobs = len(self.robs) * [0.0] - if not has_dGobs: - self.dGobs = len(self.robs) * [0.0] - return self - - def write(self, filename): - """Write experimental PDF data to a file. - - filename -- name of file to write to - - No return value. - """ - txt = self.writeStr() - f = open(filename, "w") - f.write(txt) - f.close() - return - - def writeStr(self): - """String representation of experimental PDF data. - - Return data string. - """ - lines = [] - # write metadata - lines.extend( - [ - "History written: " + time.ctime(), - "produced by " + getuser(), - "##### PDFgui", - ] - ) - # stype - if self.stype == "X": - lines.append("stype=X x-ray scattering") - elif self.stype == "N": - lines.append("stype=N neutron scattering") - # qmax - if self.qmax == 0: - qmax_line = "qmax=0 correction not applied" - else: - qmax_line = "qmax=%.2f" % self.qmax - lines.append(qmax_line) - # qdamp - lines.append("qdamp=%g" % self.qdamp) - # qbroad - lines.append("qbroad=%g" % self.qbroad) - # dscale - lines.append("dscale=%g" % self.dscale) - # metadata - if len(self.metadata) > 0: - lines.append("# metadata") - for k, v in self.metadata.items(): - lines.append("%s=%s" % (k, v)) - # write data: - lines.append("##### start data") - lines.append("#L r(A) G(r) d_r d_Gr") - for i in range(len(self.robs)): - lines.append("%g %g %g %g" % (self.robs[i], self.Gobs[i], self.drobs[i], self.dGobs[i])) - # that should be it - datastring = "\n".join(lines) + "\n" - return datastring - - def copy(self, other=None): - """Copy self to other. if other is None, create new instance. - - other -- ref to other object - returns reference to copied object - """ - if other is None: - other = PDFDataSet(self.name) - elif isinstance(other, PDFDataSet): - other.clear() - # some attributes can be assigned, e.g., robs, Gobs, drobs, dGobs are - # constant so they can be shared between copies. - assign_attributes = ( - "robs", - "Gobs", - "drobs", - "dGobs", - "stype", - "qmax", - "qdamp", - "qbroad", - "dscale", - "rmin", - "rmax", - "filename", - ) - # for others we will assign a copy - copy_attributes = ("metadata",) - for a in assign_attributes: - setattr(other, a, getattr(self, a)) - for a in copy_attributes: - setattr(other, a, copy.deepcopy(getattr(self, a))) - return other - - -# End of class PDFDataSet - - -class PDFDataFormatError(Exception): - """Exception class marking failure to process PDF data string.""" - - pass - - -# End of file diff --git a/src/diffpy/pdfgui/control/pdfguicontrol.py b/src/diffpy/pdfgui/control/pdfguicontrol.py deleted file mode 100644 index 695a15ac..00000000 --- a/src/diffpy/pdfgui/control/pdfguicontrol.py +++ /dev/null @@ -1,583 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Jiwu Liu -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -from __future__ import print_function - -import io -import os -import pickle -import sys -import threading -import time -from urllib.parse import quote_plus - -from diffpy.pdfgui.control.calculation import Calculation -from diffpy.pdfgui.control.controlerrors import ControlError, ControlFileError, ControlTypeError -from diffpy.pdfgui.control.fitdataset import FitDataSet -from diffpy.pdfgui.control.fitstructure import FitStructure -from diffpy.pdfgui.control.fitting import Fitting -from diffpy.pdfgui.control.organizer import Organizer -from diffpy.pdfgui.control.pdflist import PDFList -from diffpy.pdfgui.utils import asunicode - - -class PDFGuiControl: - """PDFGuiControl holds all the data GUI needs to access or change It - has a container of Calculation and Fitting instances. - - Each Calculation and Fitting has a unique name. - """ - - def __init__(self, gui=None): - """initialize. - - gui: main panel of GUI - """ - self.lock = threading.RLock() - self.gui = gui - - # clean up local data - self.reset() - - # Queue stuff - self.fittingQueue = [] - self.currentFitting = None - self.queueManager = PDFGuiControl.QueueManager(self) - # self.startQueue() - - def reset(self): - """Clean up for a new project.""" - self.fits = PDFList() - self.plots = PDFList() - self.journal = "" - - self.projfile = None - # self.saved = False - - # a simple thread to handle fitting queue - class QueueManager(threading.Thread): - def __init__(self, control): - threading.Thread.__init__(self) - self.control = control - self.running = True - - def run(self): - while self.running: - try: - self.control.checkQueue() - except ControlError as error: - gui = self.control.gui - if gui: - gui.postEvent(gui.ERROR, " %s" % error.info) - else: - print(" %s" % error.info) - # another check before go to sleep - if not self.running: - break - time.sleep(1) - - def startQueue(self): - """Start queue manager.""" - self.queueManager.daemon = True - self.queueManager.start() - - def checkQueue(self): - """Find next fitting in the queue and start it.""" - if self.currentFitting: - # wait for currentFitting - self.currentFitting.join() - - # No fitting in the queue is running. - try: - self.lock.acquire() - if len(self.fittingQueue) > 0: - self.currentFitting = self.fittingQueue.pop(0) - else: - self.currentFitting = None - return - finally: - self.lock.release() - - self.currentFitting.start() - - def enqueue(self, fits, enter=True): - """Enqueue or dequeue fittings. - - fits -- list of fittings to be queued/dequeued - enter -- True to queue, False to dequeue - """ - try: - self.lock.acquire() - for fit in fits: - if enter: - try: - self.fittingQueue.index(fit) - # if no exception, then it already in the queue, - # continue to next - continue - except ValueError: - # not in the queue - self.fittingQueue.append(fit) - else: - try: - # try to remove even if it may not be in the queue - self.fittingQueue.remove(fit) - except ValueError: - # do nothing if it's not in the queue, continue to next. - continue - - # When this is called, GUI lock is in possess for sure, so - # no dead lock can happen. - fit.queue(enter) - finally: - self.lock.release() - - def close(self, force=True): - """Close a project. - - force -- if exit forciably - """ - self.stop() - for plot in self.plots: - plot.close(force) - for fit in self.fits: - fit.close(force) - - self.reset() - - def exit(self): - """Exit when program finished.""" - self.close() - if self.queueManager.is_alive(): - self.queueManager.running = False - - def newFitting(self, name, position=None): - """Insert a new instance of Fitting. - - name -- unique name for this Fitting - position -- where Fitting is inserted, default is last place - - return: Fitting reference - """ - fitting = Fitting(name) - self.add(fitting, position) - return fitting - - def newCalculation(self, targetID, name, position=None): - """Insert a new instance of Calculation to a Fitting. - - targetID -- reference to Fitting - name -- unique name for this Calculation - position -- where Calculation is inserted, default is last place - - return: Calculation reference - """ - calculation = Calculation(name) - targetID.add(calculation, position) - - return calculation - - def newStructure(self, targetID, name, position=None): - """Add blank structure to a Fitting. - - targetID -- reference to Fitting - name -- name of the new Structure - position -- where the structure is to be inserted, default is last - - return: Structure reference - """ - self.__validateType(targetID) - - # insert to target - struct = FitStructure(name) - targetID.add(struct, position) - return struct - - def loadStructure(self, targetID, filename, name=None, position=None): - """Add blank structure to a Fitting. - - targetID -- reference to Fitting - name -- name of the new Structure, default is file basename - - return: Structure reference - """ - self.__validateType(targetID) - if name is None: - name = os.path.basename(filename) - - # insert to target - struct = FitStructure(name) - struct.initial.read(filename) - targetID.add(struct, position) - return struct - - def loadDataset(self, targetID, filename, name=None, position=None): - """Load Dataset from a file to a Fitting. - - targetID -- reference to Fitting - name -- name of the new Dataset, default is file basename - position -- where the dataset is to be inserted, default is last - - return: Dataset reference - """ - self.__validateType(targetID) - - if name is None: - name = os.path.basename(filename) - - # insert to target - dataset = FitDataSet(name) - dataset.readObs(filename) - targetID.add(dataset, position) - return dataset - - def add(self, ID, position=None): - """Add fitting/calculation to internal list. - - Id -- reference to the object to be inserted - position -- where the object is to be inserted, default is last - """ - if not isinstance(ID, Fitting) and not isinstance(ID, Calculation): - raise ControlTypeError("Can't add %s to list" % self.__class__.__name__) - if position is not None: - self.fits.insert(position, ID) - else: - self.fits.append(ID) - # added successfully - ID.owner = self - return ID - - def __findOwner(self, ID): - """Find where the ID belongs. - - ID -- object which can be Fitting,Calculation,FitDataSet or FitStructure - return: a PDFList holding that object - """ - if isinstance(ID, Organizer): - return self.fits - else: - try: - return ID.owner - except AttributeError: - raise ControlTypeError("Object %s doesn't exit in the list" % ID.name) - - def rename(self, ID, new_name): - """Rename Fitting, Calculation, Dataset or Structure identified - by ID. - - ID: reference to the object to be renamed - new_name: new name to be given to the object - """ - container = self.__findOwner(ID) - container.rename(ID, new_name) - - def remove(self, ID): - """Remove Fitting, Calculation, Dataset or Structure identified - by ID. - - ID: reference to the object to be removed - return: removed object - """ - container = self.__findOwner(ID) - container.remove(ID) - return ID - - def index(self, ID): - """Return position index of an object in its owner list. - - ID -- ID of object - return: index - """ - container = self.__findOwner(ID) - return container.index(ID) - - def copy(self, src): - """Copy src object. - - src -- reference to the source object - return: reference to the copy - """ - newObject = src.copy() - return newObject - - def paste(self, dup, target=None, new_name=None, position=None): - """Paste copied object to target under new_name, the default - new_name will be name of src. - - dup -- reference to the copied object - target -- target object where the copy should be inserted - new_name -- new name to be given to the copy - position -- where in the target object should the copy be inserted - - return: reference to the pasted object - """ - if target is None: - target = self - else: - self.__validateType(target) - - o = dup.copy() - if new_name is not None: - o.name = new_name - target.add(o, position) - return o - - def load(self, projfile): - """Load project from projfile. - - projfile -- a zip file of everything - """ - - def _nameParser(namelist): - """Parse the zipfile name list to get a file tree.""" - fileTree = {} - for name in namelist: - subs = name.split("/") - pathDict = fileTree - for x in subs[:-1]: - # if no node has been created - if x not in pathDict: - pathDict[x] = {} - pathDict = pathDict[x] - - # check if the entry is a leaf(file, not folder) - if subs[-1] != "": - pathDict[subs[-1]] = None - return fileTree - - self.projfile = projfile - organizations = [] - import zipfile - - # IOError can be raised when reading invalid zipfile - # check for file existence here. - if not os.path.isfile(projfile): - emsg = "Project file %s does not exist." % projfile - raise ControlFileError(emsg) - - emsg_invalid_file = "Invalid or corrupted project %s." % projfile - z = None - try: - z = zipfile.ZipFile(projfile, "r") - z.fileTree = _nameParser(z.namelist()) - - if len(z.fileTree) == 0: - raise ControlFileError(emsg_invalid_file) - # The first layer has only one folder - rootDict = next(iter(z.fileTree.values())) - projName = next(iter(z.fileTree.keys())) - - if "journal" in rootDict: - self.journal = asunicode(z.read(projName + "/journal")) - - # all the fitting and calculations - # NOTE: It doesn't hurt to keep backward compatibility - # old test project may not have file 'fits' - if "fits" in rootDict: - ftxt = asunicode(z.read(projName + "/fits")) - fitnames = ftxt.splitlines() - else: - fitnames = [x for x in rootDict.keys() if rootDict[x] is not None] - - for name in fitnames: - if not name: # empty string - continue - fit = Fitting(name) - # fitting name stored in rootDict should be quoted - rdname = quote_plus(name) - # but let's also handle old project files - if rdname not in rootDict: - rdname = name - if rdname in rootDict: - org = fit.load(z, projName + "/" + rdname + "/") - else: - # it's simply a blank fitting, has no info in proj file yet - org = fit.organization() - organizations.append(org) - self.add(fit) - - except (IOError, zipfile.error, pickle.PickleError): - raise ControlFileError(emsg_invalid_file) - - # close input file if opened - finally: - if z: - z.close() - - return organizations - - def save(self, projfile=None): - """Save project to projfile, default projfile is self.projfile. - - This method first writes to a temporary file and only when - successful, it overwrites projfile with the temporary file - content. These steps prevent corruption of existing projects - should something go wrong in the middle of save. As an added - benefit, all permissions and ownership flags in an existing - projfile are preserved. - """ - if projfile is not None: - self.projfile = projfile - - # self.projfile is unset here only due to a bug. - assert self.projfile is not None - - import shutil - import tempfile - import zipfile - - projbase = os.path.basename(self.projfile) - projName = os.path.splitext(projbase)[0] - # prepare to write - fitnames = [] - z = None - tmpfilename = None - try: - tmpfd, tmpfilename = tempfile.mkstemp() - os.close(tmpfd) - z = zipfile.ZipFile(tmpfilename, "w", zipfile.ZIP_DEFLATED) - # fits also contain calculations - for fit in self.fits: - name = fit.name - fit.save(z, projName + "/" + quote_plus(fit.name) + "/") - fitnames.append(name) - if self.journal: - z.writestr(projName + "/journal", asunicode(self.journal)) - ftxt = "\n".join(fitnames) - z.writestr(projName + "/fits", asunicode(ftxt)) - z.close() - shutil.copyfile(tmpfilename, self.projfile) - - except (IOError, pickle.PickleError): - emsg = "Error when writing to %s" % self.projfile - raise ControlFileError(emsg) - - finally: - if z is not None: - z.close() - if tmpfilename is not None: - os.remove(tmpfilename) - - return - - def plot(self, xItem, yItems, Ids, shift=1.0, dry=False): - """Make a 2D plot. - - xItem -- x data item name - yItems -- list of y data item names - Ids -- Objects where y data items are taken from - shift -- y displacement for each curve - dry -- not a real plot, only check if plot is valid - """ - from diffpy.pdfgui.control.plotter import Plotter - - plotter = Plotter() - plotter.plot(xItem, yItems, Ids, shift, dry) - self.plots.append(plotter) - - def start(self, IDlist): - """Execute Calculations and Fittings in IDlist.""" - self.redirectStdout() - fits = [ID for ID in IDlist if isinstance(ID, Fitting)] - # only add calcs which is not in fits, because fits will automatically run calcs under it anyway - calcs = [ID for ID in IDlist if isinstance(ID, Calculation) and ID.owner not in fits] - for calc in calcs: - calc.start() - self.enqueue(fits) - - def stop(self): - """Stop all Fittings.""" - self.enqueue(self.fits, False) - for id in self.fits: - if isinstance(id, Fitting): - id.stop() - - def __validateType(self, targetID): - """Check if targetID is a Fitting class.""" - if not isinstance(targetID, Organizer): - raise ControlTypeError("Can't insert to %s" % self.__class__.__name__) - - def redirectStdout(self): - """Redirect standard out. - - This redirect engine output to StringIO if not done yet. - """ - from diffpy.pdffit2 import output, redirect_stdout - - if output.stdout is sys.stdout: - redirect_stdout(io.StringIO()) - return - - def getEngineOutput(self): - """Get the output from the engine.""" - from diffpy.pdffit2 import output, redirect_stdout - - txt = output.stdout.getvalue() - output.stdout.close() - redirect_stdout(io.StringIO()) - return txt - - -_pdfguicontrol = None - - -def pdfguicontrol(*args, **kwargs): - """This function will return the single instance of class - PDFGuiControl.""" - global _pdfguicontrol - if _pdfguicontrol is None: - _pdfguicontrol = PDFGuiControl(*args, **kwargs) - return _pdfguicontrol - - -def _importByName(mname, name): - try: - module = __import__(mname, globals(), locals(), [name]) - except ImportError: - return None - return getattr(module, name) - - -def _find_global(moduleName, clsName): - # from diffpy.pdfgui.control.parameter import Parameter - moduleName = "diffpy.pdfgui.control." + moduleName.split(".")[-1] - m = _importByName(moduleName, clsName) - return m - - -class CtrlUnpickler: - """Occasionally the project file may be generated on a platform - where PYTHONPATH is not correctly set up. - - CtrlUnpickler will transform the module path in the project file to - be relative to diffpy so that it can be safely loaded. Only - constraints and parameters need this class to un- pickle. - """ - - @staticmethod - def loads(s): - try: - return pickle.loads(s) - except ImportError as err: - missedModule = str(err).split(" ")[-1] - if missedModule.find("pdfgui.control") == -1: - raise err - f = io.StringIO(s) - unpickler = pickle.Unpickler(f) - unpickler.find_global = _find_global - return unpickler.load() - - -# End of file diff --git a/src/diffpy/pdfgui/control/pdfguimacros.py b/src/diffpy/pdfgui/control/pdfguimacros.py deleted file mode 100644 index 02eb5a81..00000000 --- a/src/diffpy/pdfgui/control/pdfguimacros.py +++ /dev/null @@ -1,388 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""Methods for macros used in pdfgui.""" - -from __future__ import print_function - -import copy -import os - -from diffpy.pdfgui.control.controlerrors import ControlValueError -from diffpy.pdfgui.control.fitdataset import FitDataSet - - -def makeRSeries( - control, - fit, - maxfirst=None, - maxlast=None, - maxstep=None, - minfirst=None, - minlast=None, - minstep=None, -): - """Make an series of fits with an increasing r-range. - - The new fits are appended to the end of any current fits in the control. - - control -- The control object that will contain the fits - fit -- The prototype fit - maxfirst -- The first value of the maximum of the fit range - maxlast -- The last value of the maximum of the fit range - maxstep -- The step size of the maximum of the fit range - minfirst -- The first value of the minimum of the fit range - minlast -- The last value of the minimum of the fit range - minstep -- The step size of the minimum of the fit range - - returns a list of the new fit organization objects - """ - # Check to see if the input values are correct. - - # MIN-MIN: FIRST < LAST - if minfirst is not None and minlast is not None and not minfirst < minlast: - message = ( - "The first value of the minimum (%.2f)\ - \nmust be less than the last value of the\ - \nminimum (%.2f)" - % (minfirst, minlast) - ) - raise ControlValueError(message) - - # MAX-MAX: FIRST < LAST - if maxfirst is not None and maxlast is not None and not maxfirst < maxlast: - message = ( - "The first value of the maximum (%.2f)\ - \nmust be less than the last value of the\ - \nmaximum (%.2f)" - % (maxfirst, maxlast) - ) - raise ControlValueError(message) - - # MAX > MIN: FIRST-FIRST - if maxfirst is not None and minfirst is not None and not maxfirst > minfirst: - message = ( - "The first value of the fit maximum (%.2f)\ - \nmust be greater than first value of the fit\ - \nminimum (%.2f)." - % (maxfirst, minfirst) - ) - raise ControlValueError(message) - - # MAX > MIN: LAST-LAST - if maxlast is not None and minlast is not None and not maxlast > minlast: - message = ( - "The last value of the fit maximum (%.2f)\ - \nmust be greater than last value of the fit\ - \nminimum (%.2f)." - % (maxlast, minlast) - ) - raise ControlValueError(message) - - # STEP > 0 - message = "Step size (%.2f) must be greater than 0." - if maxstep is not None and not maxstep > 0: - raise ControlValueError(message % maxstep) - if minstep is not None and not minstep > 0: - raise ControlValueError(message % minstep) - - # Check to see that either max or min is fully specified - maxlist = [maxfirst, maxlast] - minlist = [minfirst, minlast] - if maxlist.count(None) == 1 or minlist.count(None) == 1: - raise ControlValueError("First and last values are partially specified") - if maxstep is None and minstep is None: - raise ControlValueError("Either minstep or maxstep must be specified.") - - maxlist = [] - minlist = [] - if maxfirst is not None: - if maxstep is None: - maxstep = minstep - maxrange = int((maxlast - maxfirst) / (1.0 * maxstep) + 1) - maxlist = [maxfirst + i * maxstep for i in range(maxrange)] - if minfirst is not None: - if minstep is None: - minstep = maxstep - minrange = int((minlast - minfirst) / (1.0 * minstep) + 1) - minlist = [minfirst + i * minstep for i in range(minrange)] - - # Resize the lists to the length of the shortest - serieslen = min(len(maxlist), len(minlist)) - if serieslen != 0: - maxlist = maxlist[:serieslen] - minlist = minlist[:serieslen] - else: - serieslen = max(len(maxlist), len(minlist)) - - basename = fit.name - fits = [] - - newname = "" - lastname = "" - fitcopy = control.copy(fit) - # Duplicate the original fit and change the appropriate parameters. - for i in range(serieslen): - lastname = newname - - # Loop over datasets - for ds in fitcopy.datasets: - - if minlist: - fitrmin = minlist[i] - else: - fitrmin = ds.fitrmin - if maxlist: - fitrmax = maxlist[i] - else: - fitrmax = ds.fitrmax - - # Check to see that the values are in bounds and sensical - if fitrmin < ds.rmin or fitrmin >= ds.rmax: - message = ( - "Fit minimum (%.2f) is outside the data range\ - \n[%.2f, %.2f].\ - \nAdjust the range of the series." - % (fitrmin, ds.rmin, ds.rmax) - ) - raise ControlValueError(message) - if fitrmax <= ds.rmin or fitrmax > ds.rmax: - message = ( - "Fit maximum (%.2f) is outside the data range\ - \n[%.2f, %.2f].\ - \nAdjust the range of the series." - % (fitrmax, ds.rmin, ds.rmax) - ) - raise ControlValueError(message) - if fitrmin >= fitrmax: - message = ( - "Fit minimum (%.2f) is greater than the\ - \nmaximum (%.2f).\ - \nIncrease maxstep or reduce minstep." - % (fitrmin, fitrmax) - ) - raise ControlValueError(message) - - # Set the values if all is well - if minlist: - ds.fitrmin = fitrmin - if maxlist: - ds.fitrmax = fitrmax - - # Set the parameters to the previous fit's name, if one exists. - if lastname: - parval = "=%s" % lastname - for par in fitcopy.parameters.values(): - par.setInitial(parval) - - # Now paste the copy into the control. - newname = "%s-(%.2f,%.2f)" % (basename, fitrmin, fitrmax) - o = control.paste(fitcopy, new_name=newname) - fits.append(o) - - return [f.organization() for f in fits] - - -# Temperature Series -def makeTemperatureSeries(control, fit, paths, temperatures): - """Make a temperature series. - - control -- pdguicontrol instance - fit -- The template fit - paths -- list of path names of new datasets - temperatures -- list of temperatures corresponding to the datasets - - returns a list of the new fit organization objects - """ - - if len(fit.datasets) != 1: - message = "Can't apply macro to fits with multiple datasets." - raise ControlValueError(message) - - fits = [] - # holds all of the other information about the dataset - fitbasename = fit.name - fitnewname = fit.name - fitlastname = fit.name - dataset = fit.datasets[0] - for i in range(len(paths)): - filename = paths[i] - fitlastname = fitnewname - - fitcopy = control.copy(fit) - - # Get rid of the old dataset - temp = fitcopy.datasets[0] - fitcopy.remove(temp) - - # Configure the new dataset - dsname = os.path.basename(filename) - newdataset = FitDataSet(dsname) - newdataset.readObs(filename) - - newdataset.qdamp = dataset.qdamp - newdataset.qbroad = dataset.qbroad - newdataset.dscale = dataset.dscale - newdataset.fitrmin = dataset.fitrmin - newdataset.fitrmax = dataset.fitrmax - rstep = dataset.fitrstep - st = dataset.getFitSamplingType() - newdataset.setFitSamplingType(st, rstep) - doping = dataset.metadata.get("doping") - if doping is None: - doping = 0.0 - newdataset.metadata["doping"] = doping - newdataset.constraints = copy.deepcopy(dataset.constraints) - - # Set the chosen temperature - newdataset.metadata["temperature"] = temperatures[i] - - # Add the dataset to the fitcopy - fitcopy.add(newdataset, None) - - # Set the parameters to the previous fit's name, if one exists. - if fitlastname: - parval = "=%s" % fitlastname - for par in fitcopy.parameters.values(): - par.setInitial(parval) - - # Now paste the copy into the control. - fitnewname = "%s-T%i=%g" % (fitbasename, i + 1, temperatures[i]) - o = control.paste(fitcopy, new_name=fitnewname) - fits.append(o) - - return [f.organization() for f in fits] - - -# Doping Series -def makeDopingSeries(control, fit, base, dopant, paths, doping): - """Make a temperature series. - - control -- pdguicontrol instance - fit -- The template fit - base -- Name of the base element - dopant -- Name of the dopant element - paths -- list of path names of new datasets - doping -- list of doping values corresponding to the datasets - - returns a list of the new fit organization objects - """ - from diffpy.pdffit2 import is_element - - # Make sure that base and dopant are elements - base = base.title() - dopant = dopant.title() - if not is_element(base): - raise ControlValueError("'%s' is not an element!" % base) - if not is_element(dopant): - raise ControlValueError("'%s' is not an element!" % dopant) - - # Make sure that base and dopant are in the structure file(s) - hasBase = False - hasDopant = False - for S in fit.strucs: - for atom in S: - if atom.element == base: - hasBase = True - if atom.element == dopant: - hasDopant = True - if hasBase and hasDopant: - break - - if not hasBase: - message = "The template structure does not contain the base atom." - raise ControlValueError(message) - - if not hasDopant: - message = "The template structure does not contain the dopant atom." - raise ControlValueError(message) - - # Make sure we're only replacing a single dataset - if len(fit.datasets) != 1: - message = "Can't apply macro to fits with multiple datasets." - raise ControlValueError(message) - - fits = [] - # holds all of the other information about the dataset - fitbasename = fit.name - fitnewname = fit.name - fitlastname = fit.name - dataset = fit.datasets[0] - for i in range(len(paths)): - filename = paths[i] - fitlastname = fitnewname - - fitcopy = control.copy(fit) - - # Get rid of the old dataset - temp = fitcopy.datasets[0] - fitcopy.remove(temp) - - # Configure the new dataset - dsname = os.path.basename(filename) - newdataset = FitDataSet(dsname) - newdataset.readObs(filename) - - newdataset.qdamp = dataset.qdamp - newdataset.qbroad = dataset.qbroad - newdataset.dscale = dataset.dscale - newdataset.fitrmin = dataset.fitrmin - newdataset.fitrmax = dataset.fitrmax - rstep = dataset.fitrstep - st = dataset.getFitSamplingType() - newdataset.setFitSamplingType(st, rstep) - temperature = dataset.metadata.get("temperature") - if temperature is None: - temperature = 300.0 - newdataset.metadata["temperature"] = temperature - newdataset.constraints = copy.deepcopy(dataset.constraints) - - # Set the chosen temperature - newdataset.metadata["doping"] = doping[i] - - # Add the dataset to the fitcopy - fitcopy.add(newdataset, None) - - # Update the doping information in the structures - for S in fitcopy.strucs: - for A in S: - if A.element == dopant: - A.occupancy = doping[i] - if A.element == base: - A.occupancy = 1 - doping[i] - - # Set the parameters to the previous fit's name, if one exists. - if fitlastname: - parval = "=%s" % fitlastname - for par in fitcopy.parameters.values(): - par.setInitial(parval) - - # Now paste the copy into the control. - fitnewname = "%s-%1.4f" % (fitbasename, doping[i]) - o = control.paste(fitcopy, new_name=fitnewname) - fits.append(o) - - return [f.organization() for f in fits] - - -if __name__ == "__main__": - from diffpy.pdfgui.control.pdfguicontrol import PDFGuiControl - - control = PDFGuiControl() - control.load("../../tests/testdata/ni.ddp") - fit = control.fits[0] - olist = makeRSeries(control, fit, 5, 20, 5) - print("\n".join(f[0].name for f in olist)) - -# End of file diff --git a/src/diffpy/pdfgui/control/pdflist.py b/src/diffpy/pdfgui/control/pdflist.py deleted file mode 100644 index 344c1155..00000000 --- a/src/diffpy/pdfgui/control/pdflist.py +++ /dev/null @@ -1,114 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Jiwu Liu -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -from diffpy.pdfgui.control.controlerrors import ControlKeyError - - -class PDFList(list): - """List class of PDFComponent, which can be accessed through index - or a name string.""" - - def __init__(self, *args): - """Initialize. - - args -- argument list - """ - list.__init__(self, args) - return - - def __getitem__(self, idnm): - """Get the item by idnm. - - idnm -- The index or name of the item - return: The requested object - """ - try: - return list.__getitem__(self, idnm) - except TypeError: - for item in self: - if item.name == idnm: - return item - else: - raise ControlKeyError("'%s' does not exist" % idnm) - - def __setitem__(self, idnm, obj): - """Set the item by idnm. - - idnm -- The index or name of the item - obj -- The object to be inserted - """ - if obj.name in self.keys(): - raise ControlKeyError("'%s' already exists" % obj.name) - try: - list.__setitem__(self, idnm, obj) - return - except TypeError: - self.append(obj) - return - - def __delitem__(self, idnm): - """Delete the item by idnm. - - idnm -- The index or name of the item - """ - try: - list.__delitem__(self, idnm) - return - except TypeError: - try: - index = self.keys.index(idnm) - list.__delitem__(self, index) - except IndexError: - raise ControlKeyError("'%s' does not exist" % idnm) - - def rename(self, idnmrf, newname): - """Rename an item. - - idnmrf -- index,name or reference to the object - newname -- new name - """ - if newname in self.keys(): - raise ControlKeyError("'%s' already exists" % newname) - try: - self.index(idnmrf) - # if no exception, it is a object in the list. - idnmrf.name = newname - except ValueError: - self[idnmrf].name = newname - return - - def keys(self): - """Get the names of the held objects. - - return: list of names - """ - return [x.name for x in self] - - def values(self): - """Get all held objects. - - return: list of objects - """ - return self[:] - - def items(self): - """Get name-object pairs. - - return: a list of tuple ( name, object) - """ - return [(x.name, x) for x in self] - - -# End of file diff --git a/src/diffpy/pdfgui/control/pdfstructure.py b/src/diffpy/pdfgui/control/pdfstructure.py deleted file mode 100644 index 6dd095ff..00000000 --- a/src/diffpy/pdfgui/control/pdfstructure.py +++ /dev/null @@ -1,189 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -import copy -import re - -from diffpy.pdfgui.control.controlerrors import ControlFileError, ControlKeyError -from diffpy.pdfgui.control.pdfcomponent import PDFComponent -from diffpy.structure import PDFFitStructure - - -class PDFStructure(PDFComponent, PDFFitStructure): - """PDFStructure contains structure information, which can be used - for 3D rendering as well as structure refinement.""" - - def __init__(self, name, *args, **kwargs): - """Initialize PDFStructure. - - name -- name of this PDFStructure. - args, kwargs -- optional arguments passed to parent Structure class - """ - PDFComponent.__init__(self, name) - PDFFitStructure.__init__(self, *args, **kwargs) - return - - def read(self, filename, format="auto"): - """Load structure from a file, raise ControlFileError for - invalid or unknown structure format. - - filename -- file to be loaded - format -- structure format such as 'pdffit', 'pdb', 'xyz'. When - 'auto' all available formats are tried in a row. - - Return instance of StructureParser used to load the data. - See Structure.read() for more info. - """ - from diffpy.structure import StructureFormatError - - try: - p = PDFFitStructure.read(self, filename, format) - except StructureFormatError as err: - import os.path - - emsg = "Unable to read file '%s'\n%s." % (os.path.basename(filename), err) - raise ControlFileError(emsg) - return p - - def copy(self, other=None): - """Copy self to other. if other is None, create an instance. - - other -- ref to other object - - returns reference to copied object - """ - if other is None: - other = PDFStructure(self.name) - for a in PDFFitStructure().__dict__: - setattr(other, a, copy.deepcopy(getattr(self, a))) - other[:] = copy.deepcopy(self[:]) - return other - - # dictionary of allowed keys from self.pdffit dictionary, - # that can be used in setvar and getvar methods. - _allowed_pdffit_vars = dict.fromkeys(("spdiameter", "stepcut", "delta1", "delta2", "sratio", "rcut")) - - def setvar(self, var, value): - """Assign to data member using PdfFit-style variable This can be - used when applying constraint equations with particular - parameter values. - - var -- string representation of PdfFit variable. Possible values: - pscale, spdiameter, stepcut, delta1, delta2, sratio, rcut, - lat(n), where n=1..6, x(i), y(i), z(i), occ(i), u11(i), - u22(i), u33(i), u12(i), u13(i), u23(i), where i=1..Natoms - value -- new value of the variable - """ - barevar = var.strip() - fvalue = float(value) - parenthesis = re.match(r"^(\w+)\((\d+)\)$", barevar) - # common error message - emsg = "Invalid PdfFit phase variable %r" % barevar - if barevar in ("pscale"): - self.pdffit["scale"] = fvalue - elif barevar in PDFStructure._allowed_pdffit_vars: - self.pdffit[barevar] = fvalue - elif barevar == "lat(1)": - self.lattice.setLatPar(a=fvalue) - elif barevar == "lat(2)": - self.lattice.setLatPar(b=fvalue) - elif barevar == "lat(3)": - self.lattice.setLatPar(c=fvalue) - elif barevar == "lat(4)": - self.lattice.setLatPar(alpha=fvalue) - elif barevar == "lat(5)": - self.lattice.setLatPar(beta=fvalue) - elif barevar == "lat(6)": - self.lattice.setLatPar(gamma=fvalue) - elif parenthesis: - pvar = parenthesis.group(1) - idx = int(parenthesis.group(2)) - atom = self[idx - 1] - if pvar == "x": - atom.xyz[0] = fvalue - elif pvar == "y": - atom.xyz[1] = fvalue - elif pvar == "z": - atom.xyz[2] = fvalue - elif pvar == "occ": - atom.occupancy = fvalue - elif pvar in ("u11", "u22", "u33", "u12", "u13", "u23"): - i, j = int(pvar[1]) - 1, int(pvar[2]) - 1 - atom.U[i, j], atom.U[j, i] = fvalue, fvalue - else: - raise ControlKeyError(emsg) - else: - raise ControlKeyError(emsg) - return - - def getvar(self, var): - """Obtain value corresponding to PdfFit phase variable var This - can be used when guessing Parameter values from constraints - dictionary. - - var -- string representation of PdfFit variable. Possible values: - pscale, spdiameter, stepcut, delta1, delta2, sratio, rcut, - lat(n), where n = 1..6, x(i), y(i), z(i), occ(i), u11(i), - u22(i), u33(i), u12(i), u13(i), u23(i), where i=1..Natoms - - returns value of var - """ - barevar = var.strip() - parenthesis = re.match(r"^(\w+)\((\d+)\)$", barevar) - # common error message - emsg = "Invalid PdfFit phase variable %r" % barevar - if barevar in ("pscale"): - value = self.pdffit["scale"] - elif barevar in PDFStructure._allowed_pdffit_vars: - value = self.pdffit[barevar] - elif barevar == "lat(1)": - value = self.lattice.a - elif barevar == "lat(2)": - value = self.lattice.b - elif barevar == "lat(3)": - value = self.lattice.c - elif barevar == "lat(4)": - value = self.lattice.alpha - elif barevar == "lat(5)": - value = self.lattice.beta - elif barevar == "lat(6)": - value = self.lattice.gamma - elif parenthesis: - pvar = parenthesis.group(1) - idx = int(parenthesis.group(2)) - atom = self[idx - 1] - if pvar == "x": - value = atom.xyz[0] - elif pvar == "y": - value = atom.xyz[1] - elif pvar == "z": - value = atom.xyz[2] - elif pvar == "occ": - value = atom.occupancy - elif pvar in ("u11", "u22", "u33", "u12", "u13", "u23"): - i, j = int(pvar[1]) - 1, int(pvar[2]) - 1 - value = atom.U[i, j] - else: - raise ControlKeyError(emsg) - else: - raise ControlKeyError(emsg) - # all should be fine here, but value may be NumPy.float64scalar type - value = float(value) - return value - - -# End of class PDFStructure - -# End of file diff --git a/src/diffpy/pdfgui/control/plotter.py b/src/diffpy/pdfgui/control/plotter.py deleted file mode 100644 index b272d4f6..00000000 --- a/src/diffpy/pdfgui/control/plotter.py +++ /dev/null @@ -1,698 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Jiwu Liu -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -from diffpy.pdfgui.control.controlerrors import ControlConfigError, ControlStatusError -from diffpy.pdfgui.control.pdfcomponent import PDFComponent -from diffpy.pdfgui.gui.extendedplotframe import ExtendedPlotFrame - -# Preset plotting style -colors = ( - "red", - "blue", - "magenta", - "cyan", - "green", - "yellow", # "black", - "darkRed", - "darkBlue", - "darkMagenta", - "darkCyan", - "darkGreen", - "darkYellow", -) -lines = ("solid", "dash", "dot", "dashDot") -symbols = ("circle", "square", "triangle", "diamond") # ,"cross","xCross") - -# this is to map 'r' to what it is supposed to be. For example, when user asks -# for plotting 'Gobs' against 'r', the real data objects are 'Gobs' and 'robs' -transdict = { - "Gobs": "robs", - "Gcalc": "rcalc", - "Gdiff": "rcalc", - "Gtrunc": "rcalc", - "crw": "rcalc", -} -baselineStyle = { - "with": "lines", - "line": "solid", - "color": "black", - "width": 1, - "legend": "_nolegend_", -} - - -def _transName(name): - """Translate name of y object. - - This is mainly for plotting of parameters. GUI will pass in a integer to - indicate which parameter to be plotted. However, in data storage the - parameter is denoted as '@n' - - name -- name of data item - """ - if isinstance(name, int): - rv = "@" + str(name) - else: - rv = str(name) - return rv - - -def _fullName(dataId): - """Construct full name.""" - from diffpy.pdfgui.control.fitting import Fitting - - if hasattr(dataId, "owner") and isinstance(dataId.owner, Fitting): - return _fullName(dataId.owner) + "/" + dataId.name - else: - return dataId.name - - -def _buildStyle(plotter, name, group, yNames): - """Trying to figure out a good style. - - 1. generally we want line style for Gcalc, Gdiff, crw, symbol style for Gobs, - and line-symbol style for the rest - 2. there is a preferred style for plotting a single PDF curve - - plotter -- A plotter instance - name -- what is to be plotted (y name) - group -- which group the curve is in (group = -1 means it is the only group) - yNames -- all y to be plotted - return: style dictionary - """ - if name in ("Gcalc", "Gdiff", "crw"): - style = plotter.buildLineStyle() - style["line"] = "solid" - elif name in ("Gobs", "Gtrunc"): - style = plotter.buildSymbolStyle() - - # Use open circle always - style["symbolColor"] = "white" - style["symbol"] = "circle" - style["symbolSize"] = 6 - else: - style = plotter.buildLineSymbolStyle() - style["line"] = "dash" - style["symbol"] = "circle" - style["symbolSize"] = 8 - - # We only care about how to arrange Gdiff Gobs Gcalc Gtrunc crw nicely - if group < 0: - # use fixed style for single PDFFit picture - if name == "Gcalc": - style["color"] = "red" - elif name in ("Gobs", "Gtrunc"): - style["color"] = "blue" - elif name in ("Gdiff", "crw"): - style["color"] = "green" - else: - # make sure Gdiff, Gtrunc, Gobs, crw are having same color - if name in ("Gobs", "Gtrunc", "Gdiff", "Gcalc", "crw"): - style["color"] = colors[group % len(colors)] - if name == "Gcalc": - # for visual effect, change Gcalc to black if it's going to be plotted against Gobs/Gtrunc - if "Gobs" in yNames or "Gtrunc" in yNames: - style["color"] = "black" - - return style - - -def deblank(s): - """Remove all whitespace from the given string.""" - return "".join(s.split()) - - -class Plotter(PDFComponent): - """Plots a single graph. - - It can have multiple curves. - """ - - __plotWindowNumber = 1 - - class Curve: - """Curve stores the information for a curve in the plot. - - There are three ways of forming x and y data lists. - (1) r and g(r) from a single refinement are vectors by themselves - (2) A scalar data item (any item other than r and g(r)) can form a - vector if multiple timeSteps (refinement steps) are specified. - (3) A scalar data item (any item other than r and g(r)) can form a - vector if multiple refinement (multiple ids) are specified - - name -- The curve name - plotwnd -- The window where the curve is drawn - xStr -- Data name (string) for x axis - yStr -- Data name (string) for y axis - steps -- refinement step list - ids -- The list of object ids that the curve is related to - offset -- curve displacement in y direction - style --The drawing style of the curve - xData, yData -- data to be plotted - x, y -- original data for exporting (curve could be shifted) - bMultiData -- if the curve data comes from multiple data objects - bMultiStep -- if the curve data comes from multiple refinement step - ref -- reference of curve in the plot window - initialized -- if curve has been inserted - dataChanged -- if curve data has changed - """ - - def __init__(self, name, plotwnd, xStr, yStr, steps, ids, offset, style): - """initialize. - - name -- The curve name - plotwnd -- The window where the curve is drawn - xStr -- Data name (string) for x axis - yStr -- Data name (string) for y axis - steps -- refinement step list - ids -- The list of object ids that the curve is related to - offset -- curve displacement in y direction - style --The drawing style of the curve - """ - self.name = name - self.plotwnd = plotwnd - self.ids = ids - self.steps = steps - self.xStr = xStr - self.yStr = yStr - self.offset = offset - self.style = style - - self.bMultiData = len(self.ids) > 1 - self.bMultiStep = False - if self.steps is None or isinstance(self.steps, list): - self.bMultiStep = True - - self.xData = None - self.yData = None - self.x = None - self.y = None - - # Reference to the curve object in the underlying plotting library - self.ref = None - self.initialized = False - self.dataChanged = False - - # validate user's choice - self.validate() - - def validate(self): - """Validate(self) --> check if the curve is valid. - - Validity - is broken: - (1) when xStr or yStr doesn't refer to a legal vector - (2) when sizes of xStr and yStr don't match - """ - bItemIsVector = False - if self.xStr in ("r", "rcalc", "robs"): - if self.yStr not in ("Gobs", "Gcalc", "Gdiff", "Gtrunc", "crw"): - emsg = "x={}, y={} don't match".format(self.xStr, self.yStr) - raise ControlConfigError(emsg) - bItemIsVector = True - elif self.xStr in ("Gobs", "Gcalc", "Gdiff", "Gtrunc", "crw"): - raise ControlConfigError("%s can't be x axis" % self.xStr) - elif self.yStr in ("Gobs", "Gcalc", "Gdiff", "Gtrunc", "crw"): - # Get called when x is not r but y is not Gobs, Gtrunc Gdiff... - raise ControlConfigError("%s can only be plotted against r" % self.yStr) - - # There are three booleans - # (1) bItemIsVector - # (2) self.ids has only one element - # (3) self.allSteps - # The logic below make sure only one of them can be true. - if bItemIsVector: - if self.bMultiData or self.bMultiStep: - emsg = ("({}, {}) can't be plotted with multiple " "refinements/steps").format( - self.xStr, self.yStr - ) - raise ControlConfigError(emsg) - else: - if not self.bMultiData and not self.bMultiStep: - raise ControlConfigError("(%s, %s) is a single point" % (self.xStr, self.yStr)) - elif self.bMultiData and self.bMultiStep: - emsg = ( - "({}, {}) can't be plotted with both multiple " "refinements and multiple steps" - ).format(self.xStr, self.yStr) - raise ControlConfigError(emsg) - - def notify(self, changedIds=None, plotwnd=None): - """Notify Curve object certain data is updated. - - changedIds -- objects to which changed data is associated with - """ - if plotwnd: - self.plotwnd = plotwnd - - # in the case when changedIds are given explicitly, use it. - if changedIds: - affectedIds = [] - for id in self.ids: - for changedId in changedIds: - if id is changedId or id.owner is changedId: - affectedIds.append(id) - break - - # If the change doesn't affect any id, do nothing - if not affectedIds: - return False - else: - affectedIds = self.ids - - # translation may be required - xStr = self.xStr - if xStr == "r": - xStr = transdict.get(self.yStr, xStr) - - if self.bMultiData: - # Local list is maintained here - if self.xData is None: - self.xData = [None] * len(self.ids) - if self.yData is None: - self.yData = [None] * len(self.ids) - for id in affectedIds: - i = self.ids.index(id) - self.yData[i] = id.getData(self.yStr, -1) - if xStr == "step": - raise AssertionError("Can not plot against step") - elif xStr == "index": - self.xData[i] = i - else: - self.xData[i] = id.getData(xStr, -1) - else: - # affectedIds has only one member - if self.bMultiStep: - steps = None # None to get the whole steps - else: - steps = -1 # - - # plot multiple refinement steps for a single dataId - # in deed, the reference is not gonna change - self.yData = affectedIds[0].getData(self.yStr, steps) - if xStr == "step": - if self.yData is None: - self.xData = None - else: - self.xData = list(range(len(self.yData))) - else: - self.xData = affectedIds[0].getData(xStr, steps) - - self.x = self.xData - self.y = self.yData - - def _shift(y): - return y + self.offset - - if self.yData and self.offset: # not zero - self.yData = [_shift(yi) for yi in self.yData] - - if self.xData and self.yData: # not empty or None - return self.draw() - else: - return False - - def draw(self): - """Draw the curve in the graph. - - It will make sure the data is OK, and plot to the screen. - """ - if self.bMultiData: - # xs and ys initialize here. They are actual data object to be - # used for plotting - xs = [] - ys = [] - plotData = sorted(zip(self.xData, self.yData)) - for x, y in plotData: - if x is not None and y is not None: - xs.append(x) - ys.append(y) - self.x = xs - self.y = ys - else: - xs = self.xData - ys = self.yData - - if not xs or not ys: - return False - - # If it can get here, data is ready now. - if self.ref is None: - self.ref = self.plotwnd.insertCurve(xs, ys, self.style) - if self.yStr == "Gdiff": - # add a baseline for any Gdiff - rs = self.ids[0].rcalc - if not rs: - rs = self.ids[0].robs - hMin = min(rs) - hMax = max(rs) - - self.plotwnd.insertCurve([hMin, hMax], [self.offset, self.offset], baselineStyle) - else: - # update only - self.plotwnd.updateData(self.ref, xs, ys) - - return True - - def __init__(self, name=None): - """initialize. - - name -- name of plot - """ - if name is None: - name = "Plot [%i]" % Plotter.__plotWindowNumber - - PDFComponent.__init__(self, name) - import threading - - self.lock = threading.RLock() - self.curves = [] - self.window = None - self.isShown = False - from diffpy.pdfgui.control.pdfguicontrol import pdfguicontrol - - self.controlCenter = pdfguicontrol() - - # add some flavor by starting with random style - import random - - self.symbolStyleIndex = random.randint(0, 100) - self.lineStyleIndex = random.randint(0, 100) - return - - def close(self, force=True): - """Close up the plot. - - force -- if True, close forcibly - """ - if self.window is not None: - # self.window.Close(True) - self.window.Destroy() - self.window = None - - def onWindowClose(self): - """Get called when self.window is closed by user.""" - self.window = None - try: - self.controlCenter.plots.remove(self) - except ValueError: - # if controlCenter doesn't know me, I'm just fine to bail out - pass - - def buildSymbolStyle(self, index=-1): - """Generate a symbol style. - - index -- plotting style index - """ - # To build different symbol style, we first change color then the symbol - i = index - if i == -1: - i = self.symbolStyleIndex - self.symbolStyleIndex += 1 - - symbolIndex = i % len(symbols) - colorIndex = i % len(colors) - return { - "with": "points", - "color": colors[colorIndex], - "symbolColor": colors[colorIndex], - "symbol": symbols[symbolIndex], - "symbolSize": 3, - } - - def buildLineStyle(self, index=-1): - """Generate a line style. - - index -- plotting style index - """ - # To build different line style, we first change color then the line - i = index - if i == -1: - i = self.lineStyleIndex - self.lineStyleIndex += 1 - - lineIndex = i % len(lines) - colorIndex = i % len(colors) - return { - "with": "lines", - "color": colors[colorIndex], - "line": lines[lineIndex], - "width": 2, - } - - def buildLineSymbolStyle(self, index=-1): - """Generate a linesymbol style. - - index -- plotting style index - """ - style = self.buildLineStyle(index) - style.update(self.buildSymbolStyle(index)) - style["with"] = "linespoints" - return style - - def plot(self, xName, yNames, ids, shift, dry): - """Make a 2D plot. - - xName -- x data item name - yNames -- list of y data item names - ids -- Objects where y data items are taken from - shift -- y spacing for different ids - dry -- dry run - """ - - def _addCurve(dataIds): - # Identify the plot type. This is used to automatically modify - # 'Gdiff' and 'crw' in certain types of plots. - yset = set(yNames) - if "Gdiff" in yset: - yset.remove("Gdiff") - if "crw" in yset: - yset.remove("crw") - - # add yNames one by one for given dataIds - for y in yNames: - _offset = offset - legend = None - style = None - if not dry: - if len(dataIds) == 1 and group != -1: - # legend = dataIds[0].name + ": " + _transName(y) - legend = _fullName(dataIds[0]) + ": " + _transName(y) - else: - # 1.Group = -1, multiple ids give a single curve - # 2.there is only one dataId so that prefix unneeded - legend = _transName(y) - - style = _buildStyle(self, y, group, yNames) - style["legend"] = legend - - # automatically apply offset if we're plotting more than - # just 'Gdiff' and 'crw' - if y in ("Gdiff", "crw") and group == -1 and len(yset) > 0: - _offset = shift - # Create curve, get data for it and update it in the plot - curve = Plotter.Curve(legend, self.window, xName, y, step, dataIds, _offset, style) - self.curves.append(curve) - return - - if not ids: # empty - raise ControlConfigError("Plotter: No data is selected") - if not yNames: - raise ControlConfigError("Plotter: No y item is selected") - - # bSeparateID indicates if we want data from different ID to be - # plotted in different curve or not - bSeparateID = False - if len(ids) > 1 and xName in ("r", "rcalc", "step"): - # multi ID and within each ID we wants a vector, so curve can - # only be plotted separately. - bSeparateID = True - - # set up the step - if xName == "step": - step = None - else: - step = -1 - - self.curves = [] - - if "Gcalc" in yNames: - yNames.remove("Gcalc") - yNames.append("Gcalc") - - # default is no shift, single group. - offset = 0.0 - group = -1 - if bSeparateID: - for id in ids: - group += 1 - _addCurve( - [ - id, - ] - ) - offset += shift - else: - _addCurve(ids) - - # clean up, it's only a dry run - if dry: - self.curves = [] - return - - # Real plot starts - if self.window is None: - # plotWindown may either not be ready or it has been closed - self.window = ExtendedPlotFrame(self.controlCenter.gui) - Plotter.__plotWindowNumber += 1 - self.window.plotter = self - else: - self.window.clear() - - for curve in self.curves: - # Initial notification, don't plot immediately, wait for last line to be added - # This is to optimize plotting multiple curves. - curve.notify(plotwnd=self.window) - - # make the graph title, x, y label - yStrs = [_transName(yName) for yName in yNames] - if yStrs[0].startswith("G"): - # then all are Gs - yLabel = "G" - else: - yLabel = ",".join(yStrs) - title = "" - if len(ids) == 1: - title = ids[0].name + ": " - title += yLabel - self.window.setTitle(self.name + " " + title, title) - self.window.setXLabel(_transName(xName)) - self.window.setYLabel(yLabel) - - # show the graph - self.window.replot() - self.show(True) - - def show(self, bShow=None): - """Show the plot on screen. - - bShow -- True to show, False to Hide. None to toggle - return value: current status of window - """ - if self.window is None: - raise ControlStatusError("Plot: %s has no window" % self.name) - if bShow is None: - bShow = not self.isShown - self.window.Show(bShow) - if bShow: # True - # further bring it to top - self.window.Raise() - self.isShown = bShow - return self.isShown - - def notify(self, data): - """Change of the data is notified. - - data -- data object that has changed - """ - if not self.curves or self.window is None: - return - ret = False - for curve in self.curves: - ret |= curve.notify( - changedIds=[ - data, - ] - ) - if ret: - self.window.replot() - - def export(self, filename): - """Export current data to external file. - - filename -- the name of the file to save data - """ - # Check if any curve - if len(self.curves) == 0: - return - import getpass - import time - - outfile = open(filename, "w") - header = "# Generated on %s by %s.\n" % (time.ctime(), getpass.getuser()) - header += "# This file was created by PDFgui.\n" - outfile.write(header) - xylist = [(c.x, c.y) for c in self.curves] - xynames = [(_transName(c.xStr), deblank(c.name)) for c in self.curves] - _exportCompactData(outfile, xylist, xynames) - outfile.close() - return - - -# End of class Plotter - - -def _exportCompactData(fp, xylist, xynames=None): - """Write the xylist data in a text format to the file object fp. - The curves with the same x are grouped in the same datasets. - The datasets are marked with "#S 1", "#S 2", etc. labels according - to the spec format http://www.certif.com/cplot_manual/ch0c_C_11_3.html - - fp -- file type object that is writable - xylist -- list of (x, y) tuples of x and y arrays. Items with - empty x or empty y are ignored. - xynames -- list of tuples of (xname, yname) strings. These are - used as a header in the dataset blocks. - - No return value. - """ - dataformat = "%g" - # build the default xynames: - if xynames is None: - xynames = [("x%i" % i, "y%i" % i) for i in range(len(xylist))] - datasets = [] - datanames = [] - xt2idx = {} - for (x, y), (xn, yn) in zip(xylist, xynames): - if x is None or not len(x): - continue - if y is None or not len(y): - continue - xt = tuple(x) - i = xt2idx.setdefault(xt, len(xt2idx)) - if not i < len(datasets): - datasets.append([]) - datanames.append([]) - ds = datasets[i] - dn = datanames[i] - if not ds: - ds.append(x) - dn.append(xn) - ds.append(y) - dn.append(yn) - for i, (ds, dn) in enumerate(zip(datasets, datanames)): - # separate datasets with a blank line: - if i > 0: - fp.write("\n") - fp.write("#S %i\n" % (i + 1)) - fp.write("#L %s\n" % (" ".join(dn))) - ncols = len(ds) - fmt = " ".join(ncols * [dataformat]) + "\n" - for cols in zip(*ds): - line = fmt % cols - fp.write(line) - return - - -# End of file diff --git a/src/diffpy/pdfgui/control/structureviewer.py b/src/diffpy/pdfgui/control/structureviewer.py deleted file mode 100644 index ad46d5f2..00000000 --- a/src/diffpy/pdfgui/control/structureviewer.py +++ /dev/null @@ -1,238 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# diffpy.pdfgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2009-2024 Trustees of the Columbia University -# in the City of New York. All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""Structure plotting in an external viewer process.""" - -from __future__ import print_function - -import os.path -import shutil -import sys -import tempfile - -from diffpy.pdfgui.control.controlerrors import ControlConfigError - - -def getStructureViewer(): - """Factory returning singleton instance of the StructureViewer - class.""" - global _struviewer - if _struviewer is None: - _struviewer = StructureViewer() - return _struviewer - - -_struviewer = None - - -class StructureViewer(object): - """Class for plotting structure in general structure viewer. It - takes care of creating temporary structure file in a desired format - and launching structure viewer as a background process. The - temporary files are removed when StructureViewer instance goes out - of scope. - - Data attributes: - - executable -- full path to the structure viewer executable or an executable - that can be found in system PATH. By default '' (not set). - argstr -- argument string for the viewer program, it can use shell - quoting. Instances of '%s' in the string are replaced with - temporary structure file. By default '%s' - fileformat -- structure format that can be loaded by the viewer. - Must be one of output formats supported by diffpy.structure - package. By default 'pdb'. - _tmpdir -- Temporary directory for structure files opened by the viewer. - tmpdir is None before the first call to plot. The directory - and everything inside is removed when StructureViewer goes - out of the scope. - _plotcount -- Number of plots created by this viewer. - """ - - def __init__(self, executable=None, argstr=None, fileformat=None): - """Create StructureViewer instance. All arguments are optional, - they override defaults described in class docstring. The - configuration can be changed later using setConfig method. - - executable -- path to the structure viewer executable - argstr -- argument string for the viewer program, it can use - shell quoting. Instances of '%s' are replaced with - temporary structure file. - fileformat -- structure format supported by diffpy.structure package. - """ - # declare instance data - self.executable = "" - self.argstr = "%s" - self.fileformat = "pdb" - self._tmpdir = None - self._plotcount = 0 - # process arguments: - if executable is not None: - self.executable = executable - if argstr is not None: - self.argstr = argstr - if fileformat is not None: - self.fileformat = fileformat - # finish every method with return - return - - def getConfig(self): - """Return current configuration of StructureViewer instance. - - Returns new dictionary with the following keys: - ('executable', 'argstr', 'fileformat') - """ - cfgkeys = ("executable", "argstr", "fileformat") - kv = [(k, getattr(self, k)) for k in cfgkeys] - rv = dict(kv) - return rv - - def setConfig(self, cfg): - """Configure StructureViewer instance using values in a - dictionary. - - cfg -- configuration dictionary, with the same keys as returned - by getConfig(). Any other keys are ignored. - - No return value. - """ - # iterate over keys from getConfig dictionary - for k in self.getConfig(): - if k in cfg: - setattr(self, k, cfg[k]) - return - - def getFileFormats(): - """Return list of valid values for the fileformat attribute.""" - from diffpy.structure.parsers import outputFormats - - return outputFormats() - - getFileFormats = staticmethod(getFileFormats) - - def plot(self, stru): - """Launch new structure viewer and open a temporary copy of - stru. - - stru -- instance of Structure class from diffpy.structure - - No return value. - Raise ControlConfigError if structure viewer could not be launched. - """ - import subprocess - - # check if executable has been set - if not self.executable: - emsg = "StructureViewer program has not been set." - raise ControlConfigError(emsg) - # create temporary structure file - strupath = self._writeTemporaryStructure(stru) - args = [self.executable] + self._getArgumentList(strupath) - try: - subprocess.Popen(args) - except OSError as err: - emsg = "Error executing StructureViewer %s: %s" % (self.executable, err) - raise ControlConfigError(emsg) - return - - def __del__(self): - """Remove temporary files created by this instance of - StructureViewer.""" - # short circuit if nothing has been created - if self._tmpdir is None: - return - - # Function for showing unremovable files - def onerror(fnc, path, error): - print(("Cannot remove %s - %s" % (path, error)), file=sys.stderr) - return - - # For safety remove _tmpdir subdirectories by their names - for i in range(self._plotcount): - di = os.path.join(self._tmpdir, "%04i" % i) - shutil.rmtree(di, True, onerror) - # finally remove _tmpdir, which should now be empty - try: - os.rmdir(self._tmpdir) - except OSError as err: - onerror(None, self._tmpdir, err) - pass - return - - def _getArgumentList(self, strupath): - """Convert self.argstr to a list of string arguments. - - strupath -- path to temporary structure file. Replaces every - instance of '%s' in self.argstr. - - Return list of arguments (not including the viewer executable). - """ - import re - import shlex - - # make sure shlex.split is not called with None, because - # it would read standard input - s = self.argstr and self.argstr or "" - args = shlex.split(s) - # substitute strupath in args using % operator - pat = re.compile(r"(? - launchBrowser("https://www.nsf.gov") - event.Skip() - - def onDanseLogo(self, event): # wxGlade: DialogAbout. - launchBrowser("https://www.its.caltech.edu/~matsci/btf/DANSE_web_page.html") - event.Skip() - - def onMsuLogo(self, event): # wxGlade: DialogAbout. - launchBrowser("https://www.msu.edu") - event.Skip() - - def onColumbiaLogo(self, event): # wxGlade: DialogAbout. - launchBrowser("https://www.columbia.edu") - event.Skip() - - -# end of class DialogAbout - -# testing code ########################################################### - -if __name__ == "__main__": - app = wx.App() - dialog = DialogAbout(None, -1, "") - dialog.ShowModal() diff --git a/src/diffpy/pdfgui/gui/adddatapanel.py b/src/diffpy/pdfgui/gui/adddatapanel.py deleted file mode 100644 index bf703bbd..00000000 --- a/src/diffpy/pdfgui/gui/adddatapanel.py +++ /dev/null @@ -1,225 +0,0 @@ -#!/usr/bin/env python -# -*- coding: ISO-8859-1 -*- -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# (c) 2024 trustees of the Columbia University in the City -# All rights reserved. -# -# File coded by: Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -# generated by wxGlade 0.9.3 on Fri Jul 19 15:56:56 2019 - -import wx - -from diffpy.pdfgui.gui.fittree import incrementName -from diffpy.pdfgui.gui.pdfpanel import PDFPanel - - -class AddDataPanel(wx.Panel, PDFPanel): - """Panel for adding or changing data. - - Data members: - Several items must be known to this panel so it knows where to try to insert - the dataset. - entrypoint -- The FitTree item id from which we entered this panel. - entryfit -- The parent of the new dataset. - entryset -- The dataset below which to place the new set. This can be - None, which means the new dataset is appended to the end of - the entryfit. - """ - - def __init__(self, *args, **kwds): - PDFPanel.__init__(self) - # begin wxGlade: AddDataPanel.__init__ - kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL - wx.Panel.__init__(self, *args, **kwds) - - sizer_1 = wx.BoxSizer(wx.VERTICAL) - - sizer_4 = wx.BoxSizer(wx.HORIZONTAL) - sizer_1.Add(sizer_4, 0, wx.BOTTOM | wx.EXPAND | wx.TOP, 5) - - self.textLoadData = wx.StaticText(self, wx.ID_ANY, "Load a data set from file.") - self.textLoadData.SetFont( - wx.Font( - 12, - wx.FONTFAMILY_DEFAULT, - wx.FONTSTYLE_NORMAL, - wx.FONTWEIGHT_NORMAL, - 0, - "Sans", - ) - ) - sizer_4.Add(self.textLoadData, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) - - self.buttonOpen = wx.Button(self, wx.ID_OPEN, "Open") - sizer_4.Add(self.buttonOpen, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) - - self.static_line_2 = wx.StaticLine(self, wx.ID_ANY) - sizer_1.Add(self.static_line_2, 0, wx.BOTTOM | wx.EXPAND, 10) - - self.buttonCancel = wx.Button(self, wx.ID_CANCEL, "Cancel") - sizer_1.Add(self.buttonCancel, 0, wx.ALIGN_RIGHT | wx.ALL, 5) - - sizer_1.Add((450, 0), 0, 0, 0) - - self.SetSizer(sizer_1) - sizer_1.Fit(self) - - self.Layout() - - self.Bind(wx.EVT_BUTTON, self.onOpen, self.buttonOpen) - self.Bind(wx.EVT_BUTTON, self.onCancel, self.buttonCancel) - # end wxGlade - self.__customProperties() - - # UTILITY FUNCTIONS #### - - def __customProperties(self): - """Custom Properties go here.""" - self.entrypoint = None # The entrypoint on the tree - self.entryfit = None # The fit under which to insert an item - self.entryset = None # The dataset in which to insert an item - self.fullpath = "" # The last loaded dataset - return - - def readConfiguration(self): - """Read the 'DATASET' configuration. - - In the 'DATASET' section of the project ConfigurationParser the - following is set by this panel. - - 'last' -- The last dataset file added to the project. This is - stored in the class variable fullpath. - """ - remember = False - if self.cP.has_option("DATASET", "remember"): - remember = self.cP.getboolean("DATASET", "remember") - - if remember: - if self.cP.has_option("DATASET", "last"): - self.fullpath = self.cP.get("DATASET", "last") - import os.path - - if not os.path.exists(self.fullpath): - self.fullpath = "" - else: - self.fullpath = "" - return - - def updateConfiguration(self): - """Update the configuration for the 'DATASET'.""" - if not self.cP.has_section("DATASET"): - self.cP.add_section("DATASET") - self.cP.set("DATASET", "last", self.fullpath) - return - - # EVENT CODE #### - - def onOpen(self, event): # wxGlade: AddDataPanel. - """Add a dataset to the tree from a file.""" - import os.path - - newnode = None - dir, filename = os.path.split(self.fullpath) - if not dir: - dir = self.mainFrame.workpath - matchstring = "|".join( - ( - "PDF files", - "*.gr;*.fgr;*.fit;*.cgr;*.calc", - "PDF data files (*.gr)", - "*.gr", - "PDF fit files (*.fgr)", - "*.fgr", - "PDF fit files (*.fit)", - "*.fit", - "PDF calculation files (*.cgr)", - "*.cgr", - "PDF calculation files (*.calc)", - "*.calc", - "All Files", - "*", - ) - ) - d = wx.FileDialog(None, "Choose a file", dir, "", matchstring) - if d.ShowModal() == wx.ID_OK: - self.fullpath = d.GetPath() - self.mainFrame.workpath = os.path.dirname(self.fullpath) - - # Update the configuration - self.updateConfiguration() - - # Add the item to the tree. - name = os.path.basename(self.fullpath) - - # Check the name and alter it if necessary - siblings = self.treeCtrlMain.GetChildren(self.entryfit) - names = [self.treeCtrlMain.GetItemText(i) for i in siblings] - name = incrementName(name, names) - newnode = self.treeCtrlMain.AddDataSet( - self.entryfit, name, insertafter=self.entryset, filename=self.fullpath - ) - - self.mainFrame.setMode("fitting") - self.treeCtrlMain.SetItemBold(self.entrypoint, False) - self.treeCtrlMain.UnselectAll() - self.mainFrame.makeTreeSelection(newnode) - d.Destroy() - return - - def onCancel(self, event): # wxGlade: AddDataPanel. - """Cancel this addition. - - Go back to the last panel. - """ - if self.entrypoint is None: - return - self.mainFrame.setMode("fitting") - self.treeCtrlMain.SetItemBold(self.entrypoint, False) - self.treeCtrlMain.UnselectAll() - self.mainFrame.makeTreeSelection(self.entrypoint) - return - - # Methods overloaded from PDFPanel - def refresh(self): - """Check the necessary tree nodes and bold text the entry point. - - Update the configuration - """ - self.readConfiguration() - - selections = self.treeCtrlMain.GetSelections() - entrypoint = selections[0] - entryset = entrypoint - entryfit = self.treeCtrlMain.GetFitRoot(entrypoint) - - # Check on the entryset and entryfit. Data sets can only be - # inserted from datasets or fits. If the entry is on a dataset, the - # entryset is the id of that dataset. Otherwise it is None. If the - # entry is on a fit, this is the entryfit. If the entry is on a - # dataset, the entryfit is its parent. - entrytype = self.treeCtrlMain.GetNodeType(entrypoint) - if entrytype != "dataset": - entryset = None - - # Prepare the window - self.entrypoint = entrypoint - self.entryset = entryset - self.entryfit = entryfit - - # Let's see it! - self.treeCtrlMain.SetItemBold(entrypoint) - self.treeCtrlMain.UnselectAll() - return - - -# end of class AddDataPanel diff --git a/src/diffpy/pdfgui/gui/addphasepanel.py b/src/diffpy/pdfgui/gui/addphasepanel.py deleted file mode 100644 index 21e1e358..00000000 --- a/src/diffpy/pdfgui/gui/addphasepanel.py +++ /dev/null @@ -1,278 +0,0 @@ -#!/usr/bin/env python -# -*- coding: ISO-8859-1 -*- -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -# generated by wxGlade 0.9.3 on Fri Jul 19 15:59:31 2019 - -import wx - -from diffpy.pdfgui.gui.fittree import incrementName -from diffpy.pdfgui.gui.pdfpanel import PDFPanel - - -class AddPhasePanel(wx.Panel, PDFPanel): - """Panel for adding a phase. - - Several items must know to this panel so it knows where to try to insert the - phase. - entrypoint -- The FitTree item id from which we entered this panel. - dataset or a calculation item. - entryfit -- The parent of the new dataset. - entryphase -- The phase below which to place the new phase. This can be - None, which means the new phase is appended to the end of - the phase section of the entryfit. - """ - - def __init__(self, *args, **kwds): - PDFPanel.__init__(self) - # begin wxGlade: AddPhasePanel.__init__ - kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL - wx.Panel.__init__(self, *args, **kwds) - - sizer_1 = wx.BoxSizer(wx.VERTICAL) - - sizer_4 = wx.BoxSizer(wx.HORIZONTAL) - sizer_1.Add(sizer_4, 0, wx.BOTTOM | wx.EXPAND | wx.TOP, 5) - - self.labelOpenPhase = wx.StaticText(self, wx.ID_ANY, "Load a structure from file.") - self.labelOpenPhase.SetFont( - wx.Font( - 12, - wx.FONTFAMILY_DEFAULT, - wx.FONTSTYLE_NORMAL, - wx.FONTWEIGHT_NORMAL, - 0, - "Sans", - ) - ) - sizer_4.Add(self.labelOpenPhase, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) - - self.buttonOpen = wx.Button(self, wx.ID_OPEN, "Open") - sizer_4.Add(self.buttonOpen, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) - - self.static_line_5 = wx.StaticLine(self, wx.ID_ANY) - sizer_1.Add(self.static_line_5, 0, wx.EXPAND, 0) - - sizer_5 = wx.BoxSizer(wx.HORIZONTAL) - sizer_1.Add(sizer_5, 0, wx.BOTTOM | wx.EXPAND | wx.TOP, 5) - - self.labelCreatePhase = wx.StaticText(self, wx.ID_ANY, "Create a structure from scratch.") - self.labelCreatePhase.SetFont( - wx.Font( - 12, - wx.FONTFAMILY_DEFAULT, - wx.FONTSTYLE_NORMAL, - wx.FONTWEIGHT_NORMAL, - 0, - "Sans", - ) - ) - sizer_5.Add(self.labelCreatePhase, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) - - self.buttonNew = wx.Button(self, wx.ID_NEW, "New") - sizer_5.Add(self.buttonNew, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) - - self.static_line_6 = wx.StaticLine(self, wx.ID_ANY) - sizer_1.Add(self.static_line_6, 0, wx.BOTTOM | wx.EXPAND, 10) - - self.buttonCancel = wx.Button(self, wx.ID_CANCEL, "Cancel") - sizer_1.Add(self.buttonCancel, 0, wx.ALIGN_RIGHT | wx.ALL, 5) - - sizer_1.Add((450, 10), 0, 0, 0) - - self.SetSizer(sizer_1) - sizer_1.Fit(self) - - self.Layout() - - self.Bind(wx.EVT_BUTTON, self.onOpen, self.buttonOpen) - self.Bind(wx.EVT_BUTTON, self.onNew, self.buttonNew) - self.Bind(wx.EVT_BUTTON, self.onCancel, self.buttonCancel) - # end wxGlade - self.__customProperties() - - # UTILITY FUNCTIONS #### - - def __customProperties(self): - """Custom Properties go here.""" - self.entrypoint = None # The entrypoint on the tree - self.entryfit = None # The fit in which to insert an item - self.entryphase = None # The phase under which to insert an item - self.fullpath = "" # The last loaded structure - return - - def readConfiguration(self): - """Read the 'PHASE' configuration. - - In the 'PHASE' section of the project ConfigurationParser the - following is set by this panel. - - 'last' -- The last structure file added to the project. This is - stored in the class variable fullpath. - """ - remember = False - if self.cP.has_option("PHASE", "remember"): - remember = self.cP.getboolean("PHASE", "remember") - - if remember: - if self.cP.has_option("PHASE", "last"): - self.fullpath = self.cP.get("PHASE", "last") - import os.path - - if not os.path.exists(self.fullpath): - self.fullpath = "" - else: - self.fullpath = "" - return - - def updateConfiguration(self): - """Update the configuration for the 'DATASET'.""" - if not self.cP.has_section("PHASE"): - self.cP.add_section("PHASE") - self.cP.set("PHASE", "last", self.fullpath) - return - - # EVENT CODE #### - - def onOpen(self, event): # wxGlade: AddPhasePanel. - """Add a the new phase to the tree. - - The phase is added as a child of entryfit, right after the - entryphase, if it exists. If entryphase is None, the new phase - is appended to the end of the children of entryfit. - """ - import os.path - - newnode = None - dir, filename = os.path.split(self.fullpath) - if not dir: - dir = self.mainFrame.workpath - matchstring = "|".join( - ( - "Structure file", - "*.cif;*CIF;*.stru;*.STRU;*.pdb;*.PDB;*.xyz;*.XYZ", - "Crystallographic Information File (*.cif)", - "*.cif;*.CIF", - "PDFfit structure files (*.stru)", - "*.stru;*.STRU", - "Protein Data Bank files (*.pdb)", - "*.pdb;*.PDB", - "Coordinate files (*.xyz)", - "*.xyz;*.XYZ", - "All Files", - "*", - ) - ) - d = wx.FileDialog(None, "Choose a file", dir, "", matchstring) - if d.ShowModal() == wx.ID_OK: - self.fullpath = d.GetPath() - self.mainFrame.workpath = os.path.dirname(self.fullpath) - - # Update the configuration - self.updateConfiguration() - - # Add the item to the tree. - name = os.path.basename(self.fullpath) - - # Check the name and alter it if necessary - siblings = self.treeCtrlMain.GetChildren(self.entryfit) - names = [self.treeCtrlMain.GetItemText(i) for i in siblings] - name = incrementName(name, names) - - newnode = self.treeCtrlMain.AddPhase( - self.entryfit, name, insertafter=self.entryphase, filename=self.fullpath - ) - - self.mainFrame.setMode("fitting") - self.treeCtrlMain.SetItemBold(self.entrypoint, False) - self.treeCtrlMain.UnselectAll() - self.mainFrame.makeTreeSelection(newnode) - self.validateStructure(newnode) - d.Destroy() - return - - def onNew(self, event): # wxGlade: AddPhasePanel. - """Add a new item to be created from scratch.""" - # Set the name of the new phase - siblings = self.treeCtrlMain.GetChildren(self.entryfit) - names = [self.treeCtrlMain.GetItemText(i) for i in siblings] - label = "New Phase" - label = incrementName(label, names) - - # Create the phase - newnode = self.treeCtrlMain.AddPhase(self.entryfit, label, insertafter=self.entryphase) - - # Go to the new node - self.mainFrame.setMode("fitting") - self.treeCtrlMain.SetItemBold(self.entrypoint, False) - self.treeCtrlMain.UnselectAll() - self.mainFrame.makeTreeSelection(newnode) - self.treeCtrlMain.EditLabel(newnode) - return - - def onCancel(self, event): # wxGlade: AddPhasePanel. - """Cancel this addition. - - Go back to the last panel. - """ - self.mainFrame.setMode("fitting") - self.treeCtrlMain.SetItemBold(self.entrypoint, False) - self.treeCtrlMain.UnselectAll() - self.mainFrame.makeTreeSelection(self.entrypoint) - return - - def validateStructure(self, node): - """Make sure that the structure is valid.""" - from diffpy.pdfgui.control.controlerrors import ControlError - - dataobject = self.treeCtrlMain.GetControlData(node) - stru = dataobject.initial - for a in stru: - nonzero = 0 - for row in a.U: - nonzero += row.any() - if not nonzero: - raise ControlError("Structure has atoms with all zero ADP values.") - return - - # Methods overloaded from PDFPanel - def refresh(self): - """Bold text the entrypoint on the tree. - - This also reads the configuration. - """ - self.readConfiguration() - - selections = self.treeCtrlMain.GetSelections() - entrypoint = selections[0] - entryphase = entrypoint - entryfit = self.treeCtrlMain.GetFitRoot(entrypoint) - - entrytype = self.treeCtrlMain.GetNodeType(entryphase) - if entrytype != "phase": - entryphase = None - - # Prepare the window - self.entrypoint = entrypoint - self.entryphase = entryphase - self.entryfit = entryfit - - # Make the entry point bold. - self.treeCtrlMain.SetItemBold(self.entrypoint) - self.treeCtrlMain.UnselectAll() - return - - -# end of class AddPhasePanel diff --git a/src/diffpy/pdfgui/gui/blankpanel.py b/src/diffpy/pdfgui/gui/blankpanel.py deleted file mode 100644 index d989e94b..00000000 --- a/src/diffpy/pdfgui/gui/blankpanel.py +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""This module contains the BlankPanel class.""" - -import wx - -from diffpy.pdfgui.gui.pdfpanel import PDFPanel - - -class BlankPanel(wx.Panel, PDFPanel): - """A blank panel needed as a right panel in mainframe.py.""" - - def __init__(self, *args, **kwds): - PDFPanel.__init__(self) - wx.Panel.__init__(self, *args, **kwds) - - def refresh(self): - return - - -# end of class BlankPanel diff --git a/src/diffpy/pdfgui/gui/bondangledialog.py b/src/diffpy/pdfgui/gui/bondangledialog.py deleted file mode 100644 index 0ae91afa..00000000 --- a/src/diffpy/pdfgui/gui/bondangledialog.py +++ /dev/null @@ -1,167 +0,0 @@ -#!/usr/bin/env python -# -*- coding: ISO-8859-1 -*- -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - - -import wx - -from diffpy.pdfgui.gui.pdfpanel import PDFPanel - - -class BondAngleDialog(wx.Dialog, PDFPanel): - def __init__(self, *args, **kwds): - PDFPanel.__init__(self) - kwds["style"] = wx.DEFAULT_DIALOG_STYLE - wx.Dialog.__init__(self, *args, **kwds) - self.sizer_2_staticbox = wx.StaticBox(self, -1, "Bond Angle Calculation") - self.instructionsLabel = wx.StaticText(self, -1, "Calculate the angle defined by three atoms.") - self.atomsLabel = wx.StaticText(self, -1, "Atom Indices") - self.aSpinCtrl = wx.SpinCtrl(self, -1, "1", min=1, max=1) - self.bSpinCtrl = wx.SpinCtrl(self, -1, "1", min=1, max=1) - self.cSpinCtrl = wx.SpinCtrl(self, -1, "1", min=1, max=1) - self.static_line_1 = wx.StaticLine(self, -1) - self.cancelButton = wx.Button(self, wx.ID_CANCEL, "Cancel") - self.okButton = wx.Button(self, wx.ID_OK, "OK") - - self.__set_properties() - self.__do_layout() - - self.Bind(wx.EVT_BUTTON, self.onCancel, id=wx.ID_CANCEL) - self.Bind(wx.EVT_BUTTON, self.onOk, id=wx.ID_OK) - self.Bind(wx.EVT_SPINCTRL, self.onSpin, self.aSpinCtrl) - self.Bind(wx.EVT_SPINCTRL, self.onSpin, self.bSpinCtrl) - self.Bind(wx.EVT_SPINCTRL, self.onSpin, self.cSpinCtrl) - self.__customProperties() - - def __set_properties(self): - self.SetTitle("Calculate Bond Angles") - # end wxGlade - - def __do_layout(self): - # begin wxGlade: SGStructureDialog.__do_layout - sizer_2 = wx.StaticBoxSizer(self.sizer_2_staticbox, wx.VERTICAL) - sizer_4_copy = wx.BoxSizer(wx.HORIZONTAL) - sizer_4 = wx.BoxSizer(wx.HORIZONTAL) - sizer_3 = wx.BoxSizer(wx.HORIZONTAL) - sizer_2.Add( - self.instructionsLabel, - 0, - wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.ADJUST_MINSIZE, - 5, - ) - sizer_2.Add(sizer_3, 0, wx.EXPAND, 0) - sizer_4.Add(self.atomsLabel, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.ADJUST_MINSIZE, 5) - sizer_4.Add(self.aSpinCtrl, 0, wx.ALL | wx.ADJUST_MINSIZE, 5) - sizer_4.Add(self.bSpinCtrl, 0, wx.ALL | wx.ADJUST_MINSIZE, 5) - sizer_4.Add(self.cSpinCtrl, 0, wx.ALL | wx.ADJUST_MINSIZE, 5) - sizer_2.Add(sizer_4, 0, wx.EXPAND, 0) - sizer_2.Add(self.static_line_1, 0, wx.EXPAND, 0) - sizer_4_copy.Add((0, 0), 1, wx.EXPAND | wx.ADJUST_MINSIZE, 0) - sizer_4_copy.Add(self.cancelButton, 0, wx.ALL | wx.ADJUST_MINSIZE, 5) - sizer_4_copy.Add(self.okButton, 0, wx.ALL | wx.ADJUST_MINSIZE, 5) - sizer_2.Add(sizer_4_copy, 0, wx.EXPAND, 0) - self.SetAutoLayout(True) - self.SetSizer(sizer_2) - sizer_2.Fit(self) - sizer_2.SetSizeHints(self) - self.Layout() - # end wxGlade - - # ######################################################################### - - def __customProperties(self): - """Set the custom properties.""" - self.a = 1 - self.b = 2 - self.c = 3 - return - - def setStructure(self, structure): - """Set the structure and update the widgets. - - This must be called before the spin control boxes will be - settable to anything other than 1. - """ - natoms = len(structure) - self.aSpinCtrl.SetRange(1, natoms) - self.bSpinCtrl.SetRange(1, natoms) - self.cSpinCtrl.SetRange(1, natoms) - self.aSpinCtrl.SetValue(min(1, natoms)) - self.bSpinCtrl.SetValue(min(2, natoms)) - self.cSpinCtrl.SetValue(min(3, natoms)) - self.okButton.Enable(True) - if natoms < 3: - self.okButton.Enable(False) - return - - def getCtrlLetter(self, ctrl): - """Get the letter associated with the control.""" - if ctrl is self.aSpinCtrl: - return "a" - if ctrl is self.bSpinCtrl: - return "b" - return "c" - - def onSpin(self, event): - """Handle atom selection events. - - This makes sure that no two controls can have the same value. - """ - letters = ["a", "b", "c"] - ctrl = event.GetEventObject() - val = event.GetSelection() - - atomLetter = self.getCtrlLetter(ctrl) - - # Check to see if the value is increasing or decreasing - increasing = True - oldval = getattr(self, atomLetter) - if val < oldval: - increasing = False - - # Check to see if the value is equal to another. If so, move it along in - # the direction it was going. - letters.remove(atomLetter) - newval = val - loop = True - while loop: - loop = False - for letter in letters: - if newval == getattr(self, letter): - loop = True - if increasing: - newval += 1 - else: - newval -= 1 - - # Set the new value, depending on what it is. - if newval > 0 and newval <= ctrl.GetMax(): - setattr(self, atomLetter, newval) - wx.CallAfter(ctrl.SetValue, newval) - else: - setattr(self, atomLetter, oldval) - wx.CallAfter(ctrl.SetValue, oldval) - return - - def onOk(self, event): - event.Skip() - return - - def onCancel(self, event): # wxGlade: SGStructureDialog. - event.Skip() - return - - -# end of class SGStructureDialog diff --git a/src/diffpy/pdfgui/gui/bondlengthdialog.py b/src/diffpy/pdfgui/gui/bondlengthdialog.py deleted file mode 100644 index 67a141bc..00000000 --- a/src/diffpy/pdfgui/gui/bondlengthdialog.py +++ /dev/null @@ -1,256 +0,0 @@ -#!/usr/bin/env python -# -*- coding: ISO-8859-1 -*- -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2007 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -# generated by wxGlade 0.9.3 on Fri Jul 19 16:00:05 2019 - -import wx - -from diffpy.pdfgui.gui.wxextensions.validators import FLOAT_ONLY, TextValidator - -# begin wxGlade: extracode -# end wxGlade - - -class BondLengthDialog(wx.Dialog): - def __init__(self, *args, **kwds): - # begin wxGlade: BondLengthDialog.__init__ - kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_DIALOG_STYLE - wx.Dialog.__init__(self, *args, **kwds) - self.SetTitle("Calculate Bond Lengths") - - sizer_2 = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.VERTICAL) - - self.instructionsLabel = wx.StaticText(self, wx.ID_ANY, "Enter the indices of two atoms.") - sizer_2.Add(self.instructionsLabel, 0, wx.ALL, 5) - - sizer_3 = wx.BoxSizer(wx.HORIZONTAL) - sizer_2.Add(sizer_3, 0, wx.EXPAND, 0) - - self.indicesLabel = wx.StaticText(self, wx.ID_ANY, "Atom Indices") - sizer_3.Add(self.indicesLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) - - self.aSpinCtrl = wx.SpinCtrl(self, wx.ID_ANY, "", min=0, max=100, style=0) - self.aSpinCtrl.SetMinSize((80, 27)) - sizer_3.Add(self.aSpinCtrl, 0, wx.ALL, 5) - - self.bSpinCtrl = wx.SpinCtrl(self, wx.ID_ANY, "", min=0, max=100, style=0) - self.bSpinCtrl.SetMinSize((80, 27)) - sizer_3.Add(self.bSpinCtrl, 0, wx.ALL, 5) - - self.static_line_2 = wx.StaticLine(self, wx.ID_ANY) - sizer_2.Add(self.static_line_2, 0, wx.BOTTOM | wx.EXPAND, 5) - - self.instructionsLabel2 = wx.StaticText( - self, - wx.ID_ANY, - "Or enter the elemental symbols of two atoms and\nthe range over which to calculate the bond lengths.", - ) - sizer_2.Add(self.instructionsLabel2, 0, wx.ALL, 5) - - sizer_4 = wx.BoxSizer(wx.HORIZONTAL) - sizer_2.Add(sizer_4, 0, wx.EXPAND, 0) - - self.elementLabel = wx.StaticText(self, wx.ID_ANY, "Elements") - sizer_4.Add(self.elementLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) - - self.aComboBox = wx.ComboBox(self, wx.ID_ANY, choices=[], style=0) - self.aComboBox.SetMinSize((80, 27)) - sizer_4.Add(self.aComboBox, 0, wx.ALL, 5) - - self.bComboBox = wx.ComboBox(self, wx.ID_ANY, choices=[], style=0) - self.bComboBox.SetMinSize((80, 27)) - sizer_4.Add(self.bComboBox, 0, wx.ALL, 5) - - sizer_4_copy_1 = wx.BoxSizer(wx.HORIZONTAL) - sizer_2.Add(sizer_4_copy_1, 0, wx.EXPAND, 0) - - self.rangeLabel = wx.StaticText(self, wx.ID_ANY, "Range") - sizer_4_copy_1.Add(self.rangeLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) - - self.lbTextCtrl = wx.TextCtrl(self, wx.ID_ANY, "") - self.lbTextCtrl.SetMinSize((80, 27)) - sizer_4_copy_1.Add(self.lbTextCtrl, 0, wx.ALL, 5) - - self.toLabel = wx.StaticText(self, wx.ID_ANY, "to") - sizer_4_copy_1.Add(self.toLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) - - self.ubTextCtrl = wx.TextCtrl(self, wx.ID_ANY, "") - self.ubTextCtrl.SetMinSize((80, 27)) - sizer_4_copy_1.Add(self.ubTextCtrl, 0, wx.ALL, 5) - - self.static_line_1 = wx.StaticLine(self, wx.ID_ANY) - sizer_2.Add(self.static_line_1, 0, wx.EXPAND, 0) - - sizer_4_copy = wx.BoxSizer(wx.HORIZONTAL) - sizer_2.Add(sizer_4_copy, 0, wx.EXPAND, 0) - - sizer_4_copy.Add((0, 0), 1, wx.EXPAND, 0) - - self.cancelButton = wx.Button(self, wx.ID_CANCEL, "Cancel") - sizer_4_copy.Add(self.cancelButton, 0, wx.ALL, 5) - - self.okButton = wx.Button(self, wx.ID_OK, "OK") - sizer_4_copy.Add(self.okButton, 0, wx.ALL, 5) - - self.SetSizer(sizer_2) - sizer_2.Fit(self) - - self.Layout() - - self.Bind(wx.EVT_SPINCTRL, self.onSpin, self.aSpinCtrl) - self.Bind(wx.EVT_SPINCTRL, self.onSpin, self.bSpinCtrl) - self.Bind(wx.EVT_BUTTON, self.onCancel, self.cancelButton) - self.Bind(wx.EVT_BUTTON, self.onOk, self.okButton) - # end wxGlade - self.__customProperties() - - def __customProperties(self): - """Set the custom properties.""" - self.a = 1 - self.b = 2 - self.ea = "ALL" - self.eb = "ALL" - self.lb = 0 - self.ub = 0 - - # Set the textCtrl validators and focus events - textCtrls = [self.lbTextCtrl, self.ubTextCtrl] - for ctrl in textCtrls: - ctrl.SetValidator(TextValidator(FLOAT_ONLY)) - ctrl.Bind(wx.EVT_KILL_FOCUS, self.onTextKillFocus) - - self.comboBoxes = [self.aComboBox, self.bComboBox] - for cbox in self.comboBoxes: - cbox.Bind(wx.EVT_KILL_FOCUS, self.onComboKillFocus) - cbox.Bind(wx.EVT_COMBOBOX, self.onComboKillFocus) - return - - def setStructure(self, structure): - """Set the structure and update the widgets. - - This must be called before the spin control boxes will be - settable to anything other than 1. - """ - self.okButton.Enable(True) - - natoms = len(structure) - if natoms < 2: - self.okButton.Enable(False) - return - - # Fill the spin controls - self.aSpinCtrl.SetRange(1, natoms) - self.bSpinCtrl.SetRange(1, natoms) - self.aSpinCtrl.SetValue(min(1, natoms)) - self.bSpinCtrl.SetValue(min(2, natoms)) - - # Fill the combo boxes - self.eList = sorted(set(a.element for a in structure)) - self.eList.insert(0, "All") - - self.aComboBox.Clear() - self.bComboBox.Clear() - for el in self.eList: - self.aComboBox.Append(el) - self.bComboBox.Append(el) - self.aComboBox.SetValue("All") - self.bComboBox.SetValue("All") - - self.lbTextCtrl.SetValue("0.0") - self.ubTextCtrl.SetValue("0.0") - return - - def onTextKillFocus(self, event): - self.lb = float(self.lbTextCtrl.GetValue()) - self.ub = float(self.ubTextCtrl.GetValue()) - event.Skip() - return - - def onComboKillFocus(self, event): - - # Verify that the combo boxes are valid - for cbox in self.comboBoxes: - val = cbox.GetValue() - if val not in self.eList: - val = "All" - cbox.SetValue(val) - - self.ea = self.aComboBox.GetValue() - self.eb = self.bComboBox.GetValue() - event.Skip() - return - - def getCtrlLetter(self, ctrl): - """Get the letter associated with the control.""" - if ctrl is self.aSpinCtrl: - return "a" - return "b" - - def onSpin(self, event): # wxGlade: BondLengthDialog. - letters = ["a", "b"] - ctrl = event.GetEventObject() - val = event.GetSelection() - - atomLetter = self.getCtrlLetter(ctrl) - - # Check to see if the value is increasing or decreasing - increasing = True - oldval = getattr(self, atomLetter) - if val < oldval: - increasing = False - - # Check to see if the value is equal to another. If so, move it along in - # the direction it was going. - letters.remove(atomLetter) - newval = val - loop = True - while loop: - loop = False - for letter in letters: - if newval == getattr(self, letter): - loop = True - if increasing: - newval += 1 - else: - newval -= 1 - - # Set the new value, depending on what it is. - if newval > 0 and newval <= ctrl.GetMax(): - setattr(self, atomLetter, newval) - wx.CallAfter(ctrl.SetValue, newval) - else: - setattr(self, atomLetter, oldval) - wx.CallAfter(ctrl.SetValue, oldval) - return - - def onCancel(self, event): # wxGlade: BondLengthDialog. - event.Skip() - - def onOk(self, event): # wxGlade: BondLengthDialog. - self.onTextKillFocus(event) - self.onComboKillFocus(event) - event.Skip() - - -# end of class BondLengthDialog - - -if __name__ == "__main__": - app = wx.PySimpleApp(0) - blenDialog = BondLengthDialog(None, -1, "") - app.SetTopWindow(blenDialog) - blenDialog.Show() - app.MainLoop() diff --git a/src/diffpy/pdfgui/gui/calculationpanel.py b/src/diffpy/pdfgui/gui/calculationpanel.py deleted file mode 100644 index 70b3ae1a..00000000 --- a/src/diffpy/pdfgui/gui/calculationpanel.py +++ /dev/null @@ -1,297 +0,0 @@ -#!/usr/bin/env python -# -*- coding: UTF-8 -*- -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -# generated by wxGlade 0.9.3 on Fri Jul 19 16:00:20 2019 - -import wx - -from diffpy.pdfgui.gui.pdfpanel import PDFPanel -from diffpy.pdfgui.gui.wxextensions.textctrlutils import textCtrlAsGridCell -from diffpy.pdfgui.gui.wxextensions.validators import FLOAT_ONLY, TextValidator - - -class CalculationPanel(wx.Panel, PDFPanel): - def __init__(self, *args, **kwds): - PDFPanel.__init__(self) - # begin wxGlade: CalculationPanel.__init__ - kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL - wx.Panel.__init__(self, *args, **kwds) - - sizer_1 = wx.BoxSizer(wx.HORIZONTAL) - - outerSizer = wx.BoxSizer(wx.VERTICAL) - sizer_1.Add(outerSizer, 1, wx.EXPAND, 0) - - sizer_panelname = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.HORIZONTAL) - outerSizer.Add(sizer_panelname, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) - - self.panelNameLabel = wx.StaticText(self, wx.ID_ANY, "Calculation Configuration") - self.panelNameLabel.SetFont( - wx.Font( - 18, - wx.FONTFAMILY_DEFAULT, - wx.FONTSTYLE_NORMAL, - wx.FONTWEIGHT_BOLD, - 0, - "", - ) - ) - sizer_panelname.Add(self.panelNameLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT, 5) - - outerSizer.Add((450, 5), 0, 0, 0) - - self.radioBoxStype = wx.RadioBox( - self, - wx.ID_ANY, - "Scatterer Type", - choices=["Neutron", "X-ray"], - majorDimension=2, - style=wx.RA_SPECIFY_COLS, - ) - self.radioBoxStype.SetMinSize((330, 43)) - self.radioBoxStype.SetSelection(0) - outerSizer.Add(self.radioBoxStype, 0, wx.ALL, 5) - - grid_sizer_1 = wx.FlexGridSizer(4, 6, 5, 10) - outerSizer.Add(grid_sizer_1, 0, wx.ALL | wx.EXPAND, 5) - - self.labelCalcRange = wx.StaticText(self, wx.ID_ANY, "Range", style=wx.ALIGN_RIGHT) - grid_sizer_1.Add( - self.labelCalcRange, - 0, - wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, - 5, - ) - - self.textCtrlCalcFrom = wx.TextCtrl(self, wx.ID_ANY, "1.0") - grid_sizer_1.Add(self.textCtrlCalcFrom, 0, wx.ALIGN_CENTER_VERTICAL, 0) - - self.labelTo = wx.StaticText(self, wx.ID_ANY, "to", style=wx.ALIGN_RIGHT) - grid_sizer_1.Add(self.labelTo, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, 20) - - self.textCtrlCalcTo = wx.TextCtrl(self, wx.ID_ANY, "10.0") - grid_sizer_1.Add(self.textCtrlCalcTo, 0, wx.ALIGN_CENTER_VERTICAL, 0) - - self.labelRStep = wx.StaticText(self, wx.ID_ANY, "spacing", style=wx.ALIGN_RIGHT) - grid_sizer_1.Add(self.labelRStep, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, 5) - - self.textCtrlRStep = wx.TextCtrl(self, wx.ID_ANY, "0.01") - grid_sizer_1.Add(self.textCtrlRStep, 0, wx.ALIGN_CENTER_VERTICAL, 0) - - self.labelScaleFactor = wx.StaticText(self, wx.ID_ANY, "Scale Factor", style=wx.ALIGN_RIGHT) - grid_sizer_1.Add( - self.labelScaleFactor, - 0, - wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, - 5, - ) - - self.textCtrlScaleFactor = wx.TextCtrl(self, wx.ID_ANY, "1.0") - grid_sizer_1.Add(self.textCtrlScaleFactor, 0, wx.ALIGN_CENTER_VERTICAL, 0) - - self.labelQmax = wx.StaticText(self, wx.ID_ANY, "Qmax", style=wx.ALIGN_RIGHT) - grid_sizer_1.Add(self.labelQmax, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, 20) - - self.textCtrlQmax = wx.TextCtrl(self, wx.ID_ANY, "25.0") - grid_sizer_1.Add(self.textCtrlQmax, 0, wx.ALIGN_CENTER_VERTICAL, 0) - - self.label_1 = wx.StaticText(self, wx.ID_ANY, "") - grid_sizer_1.Add(self.label_1, 0, 0, 0) - - self.label_1_copy = wx.StaticText(self, wx.ID_ANY, "") - grid_sizer_1.Add(self.label_1_copy, 0, 0, 0) - - self.labelQdamp = wx.StaticText(self, wx.ID_ANY, "Qdamp", style=wx.ALIGN_RIGHT) - grid_sizer_1.Add(self.labelQdamp, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, 5) - - self.textCtrlQdamp = wx.TextCtrl(self, wx.ID_ANY, "0.0") - grid_sizer_1.Add(self.textCtrlQdamp, 0, wx.ALIGN_CENTER_VERTICAL, 0) - - self.labelQbroad = wx.StaticText(self, wx.ID_ANY, "Qbroad", style=wx.ALIGN_RIGHT) - grid_sizer_1.Add(self.labelQbroad, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, 5) - - self.textCtrlQbroad = wx.TextCtrl(self, wx.ID_ANY, "0.0") - grid_sizer_1.Add(self.textCtrlQbroad, 0, wx.ALIGN_CENTER_VERTICAL, 0) - - self.label_1_copy_2 = wx.StaticText(self, wx.ID_ANY, "") - grid_sizer_1.Add(self.label_1_copy_2, 0, 0, 0) - - self.label_1_copy_1 = wx.StaticText(self, wx.ID_ANY, "") - grid_sizer_1.Add(self.label_1_copy_1, 0, 0, 0) - - self.label_1_copy_6 = wx.StaticText(self, wx.ID_ANY, "") - grid_sizer_1.Add(self.label_1_copy_6, 0, 0, 0) - - self.label_1_copy_5 = wx.StaticText(self, wx.ID_ANY, "") - grid_sizer_1.Add(self.label_1_copy_5, 0, 0, 0) - - self.label_1_copy_3 = wx.StaticText(self, wx.ID_ANY, "") - grid_sizer_1.Add(self.label_1_copy_3, 0, 0, 0) - - self.label_1_copy_4 = wx.StaticText(self, wx.ID_ANY, "") - grid_sizer_1.Add(self.label_1_copy_4, 0, 0, 0) - - self.SetSizer(sizer_1) - sizer_1.Fit(self) - - self.Layout() - - self.Bind(wx.EVT_RADIOBOX, self.onStype, self.radioBoxStype) - # end wxGlade - self.__customProperties() - - # USER CONFIGURATION CODE ################################################# - - def __customProperties(self): - """Set up the custom properties.""" - self._focusedText = None - self.calculation = None - self.stypeMap = {0: "N", 1: "X"} - - self.ctrlMap = { - "rmin": "textCtrlCalcFrom", - "rmax": "textCtrlCalcTo", - "qmax": "textCtrlQmax", - "qdamp": "textCtrlQdamp", - "qbroad": "textCtrlQbroad", - "rstep": "textCtrlRStep", - "dscale": "textCtrlScaleFactor", - } - - # Give each textCtrl a name that can be referenced and setup the - # validator - for key, value in self.ctrlMap.items(): - textCtrl = getattr(self, value) - textCtrl.SetName(key) - textCtrl.SetValidator(TextValidator(FLOAT_ONLY)) - - # Create specific bindings for the textCtrls - self.textCtrlCalcFrom.Bind(wx.EVT_KILL_FOCUS, self.onCalcRange) - self.textCtrlCalcTo.Bind(wx.EVT_KILL_FOCUS, self.onCalcRange) - self.textCtrlQmax.Bind(wx.EVT_KILL_FOCUS, self.onKillFocus) - self.textCtrlQdamp.Bind(wx.EVT_KILL_FOCUS, self.onKillFocus) - self.textCtrlQbroad.Bind(wx.EVT_KILL_FOCUS, self.onKillFocus) - self.textCtrlScaleFactor.Bind(wx.EVT_KILL_FOCUS, self.onKillFocus) - self.textCtrlRStep.Bind(wx.EVT_KILL_FOCUS, self.onCalcRange) - - # Bind the focus and key events - for key, value in self.ctrlMap.items(): - textCtrl = getattr(self, value) - textCtrl.Bind(wx.EVT_SET_FOCUS, self.onSetFocus) - textCtrl.Bind(wx.EVT_KEY_DOWN, self.onTextCtrlKey) - - return - - # Create the onTextCtrlKey event handler from textCtrlAsGridCell from - # wxextensions.textctrlutils - onTextCtrlKey = textCtrlAsGridCell - - def setConfigurationData(self): - """Set the data in the panel.""" - if self.calculation: - stype = self.calculation.stype - - if stype == "N": - self.radioBoxStype.SetSelection(0) - elif stype == "X": - self.radioBoxStype.SetSelection(1) - - for key, value in self.ctrlMap.items(): - textCtrl = getattr(self, value) - - value = getattr(self.calculation, key) - - if value is not None: - textCtrl.SetValue(str(value)) - else: - textCtrl.SetValue("0.0") - return - - def __coerseText(self, value): - if not value: - value = "0" - if value[-1].lower() in ("-", "e"): - value += "0" - return float(value) - - # EVENT CODE ############################################################# - - def onStype(self, event): # wxGlade: CalculationPanel. - value = event.GetInt() - self.calculation.stype = self.stypeMap[value] - self.mainFrame.needsSave() - return - - def onCalcRange(self, event): # wxGlade: CalculationPanel. - event.Skip() - if self.calculation is None: - return - from diffpy.pdfgui.control.controlerrors import ControlValueError - - # Since calculation.rmax gets adjusted by setRGrid, - # always obtain all range parameters. - rminvalue = self.textCtrlCalcFrom.GetValue() - rstepvalue = self.textCtrlRStep.GetValue() - rmaxvalue = self.textCtrlCalcTo.GetValue() - rmin = self.__coerseText(rminvalue) - rstep = self.__coerseText(rstepvalue) - rmax = self.__coerseText(rmaxvalue) - oldrmin = self.calculation.rmin - oldrstep = self.calculation.rstep - oldrmax = self.calculation.rmax - if oldrmin == rmin and oldrstep == rstep and oldrmax == rmax: - return - - try: - self.calculation.setRGrid(rmin, rstep, rmax) - except ControlValueError: - pass - # Make sure the panels and the control are consistent - self.textCtrlCalcFrom.SetValue(str(self.calculation.rmin)) - self.textCtrlRStep.SetValue(str(self.calculation.rstep)) - self.textCtrlCalcTo.SetValue(str(self.calculation.rmax)) - self.mainFrame.needsSave() - return - - def onSetFocus(self, event): - """Saves a TextCtrl value, to be used later.""" - self._focusedText = event.GetEventObject().GetValue() - event.Skip() - return - - def onKillFocus(self, event): - textCtrl = event.GetEventObject() - value = textCtrl.GetValue() - value = self.__coerseText(value) - name = textCtrl.GetName() - oldval = getattr(self.calculation, name) - if oldval != value: - setattr(self.calculation, name, value) - self.mainFrame.needsSave() - event.Skip() - return - - def onExport(self, event): # wxGlade: CalculationPanel. - event.Skip() - - # Methods overloaded from PDFPanel - def refresh(self): - """Refresh the panel.""" - self.setConfigurationData() - return - - -# end of class CalculationPanel diff --git a/src/diffpy/pdfgui/gui/datasetconfigurepanel.py b/src/diffpy/pdfgui/gui/datasetconfigurepanel.py deleted file mode 100644 index 55c693a3..00000000 --- a/src/diffpy/pdfgui/gui/datasetconfigurepanel.py +++ /dev/null @@ -1,472 +0,0 @@ -#!/usr/bin/env python -# -*- coding: UTF-8 -*- -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -# generated by wxGlade 0.9.3 on Fri Jul 19 16:00:35 2019 - -import wx - -from diffpy.pdfgui.gui import tooltips -from diffpy.pdfgui.gui.pdfpanel import PDFPanel -from diffpy.pdfgui.gui.wxextensions.textctrlutils import textCtrlAsGridCell -from diffpy.pdfgui.gui.wxextensions.validators import FLOAT_ONLY, TextValidator - - -class DataSetConfigurePanel(wx.Panel, PDFPanel): - def __init__(self, *args, **kwds): - PDFPanel.__init__(self) - # begin wxGlade: DataSetConfigurePanel.__init__ - kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL - wx.Panel.__init__(self, *args, **kwds) - - sizer_1 = wx.BoxSizer(wx.HORIZONTAL) - - outerSizer = wx.BoxSizer(wx.VERTICAL) - sizer_1.Add(outerSizer, 1, wx.EXPAND, 0) - - sizer_panelname = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.HORIZONTAL) - outerSizer.Add(sizer_panelname, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) - - self.panelNameLabel = wx.StaticText(self, wx.ID_ANY, "Data Set Configuration") - self.panelNameLabel.SetFont( - wx.Font( - 18, - wx.FONTFAMILY_DEFAULT, - wx.FONTSTYLE_NORMAL, - wx.FONTWEIGHT_BOLD, - 0, - "", - ) - ) - sizer_panelname.Add(self.panelNameLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT, 5) - - outerSizer.Add((450, 5), 0, 0, 0) - - self.radioBoxStype = wx.RadioBox( - self, - wx.ID_ANY, - "Scatterer Type", - choices=["Neutron", "X-ray"], - majorDimension=2, - style=wx.RA_SPECIFY_COLS, - ) - self.radioBoxStype.SetMinSize((330, 43)) - self.radioBoxStype.SetSelection(0) - outerSizer.Add(self.radioBoxStype, 0, wx.ALL, 5) - - self.radioBoxSampling = wx.RadioBox( - self, - wx.ID_ANY, - "Data Sampling", - choices=["Data", "Nyquist", "Custom"], - majorDimension=3, - style=wx.RA_SPECIFY_COLS, - ) - self.radioBoxSampling.SetMinSize((232, 44)) - self.radioBoxSampling.SetSelection(0) - outerSizer.Add(self.radioBoxSampling, 0, wx.ALL, 5) - - grid_sizer_1 = wx.FlexGridSizer(5, 6, 5, 10) - outerSizer.Add(grid_sizer_1, 0, wx.ALL | wx.EXPAND, 5) - - self.labelDataRange = wx.StaticText(self, wx.ID_ANY, "Data Range") - grid_sizer_1.Add( - self.labelDataRange, - 0, - wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, - 5, - ) - - self.textCtrlDataFrom = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) - self.textCtrlDataFrom.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT)) - grid_sizer_1.Add(self.textCtrlDataFrom, 0, 0, 0) - - self.labelDataTo = wx.StaticText(self, wx.ID_ANY, "to") - grid_sizer_1.Add(self.labelDataTo, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, 20) - - self.textCtrlDataTo = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) - self.textCtrlDataTo.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT)) - grid_sizer_1.Add(self.textCtrlDataTo, 0, 0, 0) - - self.labelDataStep = wx.StaticText(self, wx.ID_ANY, "spacing") - grid_sizer_1.Add( - self.labelDataStep, - 0, - wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, - 20, - ) - - self.textCtrlDataStep = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) - self.textCtrlDataStep.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT)) - grid_sizer_1.Add(self.textCtrlDataStep, 0, 0, 0) - - self.labelFitRange = wx.StaticText(self, wx.ID_ANY, "Fit Range", style=wx.ALIGN_RIGHT) - grid_sizer_1.Add( - self.labelFitRange, - 0, - wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, - 5, - ) - - self.textCtrlFitFrom = wx.TextCtrl(self, wx.ID_ANY, "1.0") - grid_sizer_1.Add(self.textCtrlFitFrom, 0, wx.ALIGN_CENTER_VERTICAL, 0) - - self.labelFitTo = wx.StaticText(self, wx.ID_ANY, "to", style=wx.ALIGN_RIGHT) - grid_sizer_1.Add(self.labelFitTo, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, 20) - - self.textCtrlFitTo = wx.TextCtrl(self, wx.ID_ANY, "10.0") - grid_sizer_1.Add(self.textCtrlFitTo, 0, wx.ALIGN_CENTER_VERTICAL, 0) - - self.labelFitStep = wx.StaticText(self, wx.ID_ANY, "spacing") - grid_sizer_1.Add( - self.labelFitStep, - 0, - wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, - 20, - ) - - self.textCtrlFitStep = wx.TextCtrl(self, wx.ID_ANY, "0") - grid_sizer_1.Add(self.textCtrlFitStep, 0, wx.ALIGN_CENTER_VERTICAL, 0) - - self.labelScaleFactor = wx.StaticText(self, wx.ID_ANY, "Scale Factor", style=wx.ALIGN_RIGHT) - grid_sizer_1.Add( - self.labelScaleFactor, - 0, - wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, - 5, - ) - - self.textCtrlScaleFactor = wx.TextCtrl(self, wx.ID_ANY, "1.0") - grid_sizer_1.Add(self.textCtrlScaleFactor, 0, wx.ALIGN_CENTER_VERTICAL, 0) - - self.labelQmax = wx.StaticText(self, wx.ID_ANY, "Qmax", style=wx.ALIGN_RIGHT) - grid_sizer_1.Add(self.labelQmax, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, 20) - - self.textCtrlQmax = wx.TextCtrl(self, wx.ID_ANY, "25.0") - grid_sizer_1.Add(self.textCtrlQmax, 0, wx.ALIGN_CENTER_VERTICAL, 0) - - self.blank1_copy = wx.StaticText(self, wx.ID_ANY, "") - grid_sizer_1.Add(self.blank1_copy, 0, 0, 0) - - self.blank1_copy_4 = wx.StaticText(self, wx.ID_ANY, "") - grid_sizer_1.Add(self.blank1_copy_4, 0, 0, 0) - - self.labelQdamp = wx.StaticText(self, wx.ID_ANY, "Qdamp", style=wx.ALIGN_RIGHT) - grid_sizer_1.Add(self.labelQdamp, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, 5) - - self.textCtrlQdamp = wx.TextCtrl(self, wx.ID_ANY, "0.0") - grid_sizer_1.Add(self.textCtrlQdamp, 0, wx.ALIGN_CENTER_VERTICAL, 0) - - self.labelQbroad = wx.StaticText(self, wx.ID_ANY, "Qbroad", style=wx.ALIGN_RIGHT) - grid_sizer_1.Add(self.labelQbroad, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, 20) - - self.textCtrlQbroad = wx.TextCtrl(self, wx.ID_ANY, "0.0") - grid_sizer_1.Add(self.textCtrlQbroad, 0, wx.ALIGN_CENTER_VERTICAL, 0) - - self.blank1_copy_1 = wx.StaticText(self, wx.ID_ANY, "") - grid_sizer_1.Add(self.blank1_copy_1, 0, 0, 0) - - self.blank1_copy_5 = wx.StaticText(self, wx.ID_ANY, "") - grid_sizer_1.Add(self.blank1_copy_5, 0, 0, 0) - - self.labelTemperature = wx.StaticText(self, wx.ID_ANY, "Temperature", style=wx.ALIGN_RIGHT) - grid_sizer_1.Add( - self.labelTemperature, - 0, - wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, - 5, - ) - - self.textCtrlTemperature = wx.TextCtrl(self, wx.ID_ANY, "300.0") - grid_sizer_1.Add(self.textCtrlTemperature, 0, wx.ALIGN_CENTER_VERTICAL, 0) - - self.labelDoping = wx.StaticText(self, wx.ID_ANY, "Doping", style=wx.ALIGN_RIGHT) - grid_sizer_1.Add(self.labelDoping, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, 20) - - self.textCtrlDoping = wx.TextCtrl(self, wx.ID_ANY, "1.0") - grid_sizer_1.Add(self.textCtrlDoping, 0, wx.ALIGN_CENTER_VERTICAL, 0) - - self.blank1_copy_3 = wx.StaticText(self, wx.ID_ANY, "") - grid_sizer_1.Add(self.blank1_copy_3, 0, 0, 0) - - self.blank1_copy_7 = wx.StaticText(self, wx.ID_ANY, "") - grid_sizer_1.Add(self.blank1_copy_7, 0, 0, 0) - - self.SetSizer(sizer_1) - sizer_1.Fit(self) - - self.Layout() - - self.Bind(wx.EVT_RADIOBOX, self.onStype, self.radioBoxStype) - self.Bind(wx.EVT_RADIOBOX, self.onSampling, self.radioBoxSampling) - # end wxGlade - self.__customProperties() - - # USER CONFIGURATION CODE ################################################# - - def __customProperties(self): - # Set some reasonable defaults - self.configuration = None - self.constraints = {} - self.stypeMap = {0: "N", 1: "X"} - self.metaNames = ["doping", "temperature"] - self.constrainables = ["dscale", "qdamp", "qbroad"] - self.sampList = ["data", "Nyquist", "custom"] - self._focusedText = None - - # Note that the rstep and fitrstep attributes are special cases, so they - # are handled separately. Qmax is also handled with these. - self.ctrlMap = { - "fitrmin": "textCtrlFitFrom", - "fitrmax": "textCtrlFitTo", - "rmin": "textCtrlDataFrom", - "rmax": "textCtrlDataTo", - "dscale": "textCtrlScaleFactor", - "qdamp": "textCtrlQdamp", - "qbroad": "textCtrlQbroad", - "temperature": "textCtrlTemperature", - "doping": "textCtrlDoping", - } - - # Give each textCtrl a name that can be referenced and setup the - # validator - for key, value in self.ctrlMap.items(): - textCtrl = getattr(self, value) - textCtrl.SetName(key) - textCtrl.SetValidator(TextValidator(FLOAT_ONLY)) - self.textCtrlFitStep.SetValidator(TextValidator(FLOAT_ONLY)) - - # Setup the event code. - for ctrlName in self.ctrlMap.values(): - textCtrl = getattr(self, ctrlName) - textCtrl.Bind(wx.EVT_SET_FOCUS, self.onSetFocus) - textCtrl.Bind(wx.EVT_KILL_FOCUS, self.onLoseFocus) - textCtrl.Bind(wx.EVT_KEY_DOWN, self.onTextCtrlKey) - - self.textCtrlFitStep.Bind(wx.EVT_KILL_FOCUS, self.onSampling) - self.textCtrlQmax.Bind(wx.EVT_KILL_FOCUS, self.onSampling) - self.textCtrlFitStep.Bind(wx.EVT_KEY_DOWN, self.onTextCtrlKey) - self.textCtrlQmax.Bind(wx.EVT_KEY_DOWN, self.onTextCtrlKey) - - # define tooltips - self.setToolTips(tooltips.datasetconfigurepanel) - # make sure tooltips exist for all controls in `constrainables` as - # this is later assumed in restrictConstrainedParameters code - for tname in map(self.ctrlMap.get, self.constrainables): - assert getattr(self, tname).GetToolTip() is not None - - # For blocked text controls. - self.message = "This variable is constrained. Edit the associated parameter." - return - - # Create the onTextCtrlKey event handler from textCtrlAsGridCell from - # wxextensions.textctrlutils - onTextCtrlKey = textCtrlAsGridCell - - def setConfigurationData(self): - """Set the values in the configuration panel. - - The values come from the configuration member dictionary. - stype -- 'N' or 'X' - dscale -- float - qmax -- float - qdamp -- float - rmin -- float - rmax -- float - fitrmin -- float - fitrmax -- float - temperature -- float - doping -- float - """ - if not self.configuration: - return - - stype = self.configuration.stype - - if stype == "N": - self.radioBoxStype.SetSelection(0) - elif stype == "X": - self.radioBoxStype.SetSelection(1) - else: - self.configuration.stype = "N" - self.radioBoxStype.SetSelection(0) - - # iterate over all configurable items - for key, value in self.ctrlMap.items(): - textCtrl = getattr(self, value) - - if key in self.metaNames: - value = self.configuration.metadata.get(key) - else: - value = getattr(self.configuration, key) - - if value is not None: - textCtrl.SetValue(str(value)) - else: - textCtrl.SetValue("0.0") - - # Set qmax - val = self.configuration.qmax - self.textCtrlQmax.SetValue(str(val)) - - # Set the data step - val = self.configuration.getObsSampling() - self.textCtrlDataStep.SetValue(str(val)) - - # Set up the sampling type and fit step type - st = self.configuration.getFitSamplingType() - si = self.sampList.index(st) - self.radioBoxSampling.SetSelection(si) - val = self.configuration.fitrstep - self.textCtrlFitStep.SetValue(str(val)) - - # Make sure the sampling info is consistent - self.onSampling(None) - return - - def restrictConstrainedParameters(self): - """Set 'read-only' boxes that correspond to constrained - parameters.""" - if not self.configuration: - return - - self.setToolTips(tooltips.datasetconfigurepanel) - txtbg = self.textCtrlScaleFactor.DefaultStyle.BackgroundColour - - for key in self.constrainables: - value = self.ctrlMap[key] - textCtrl = getattr(self, value) - if key in self.constraints: - textCtrl.SetEditable(False) - textCtrl.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT)) - tt = textCtrl.GetToolTip() - tt.SetTip(self.constraints[key].formula) - else: - textCtrl.SetEditable(True) - textCtrl.SetBackgroundColour(txtbg) - - return - - def __coerseText(self, value): - """Turn the text representation of a float into a float.""" - if not value: - value = "0" - if value[-1].lower() in ("-", "e"): - value += "0" - return float(value) - - def __adjustFitRange(self, name, value): - """Check the fit range values. - - The fit range values are set to their defaults (the data range) - when the fit range is nonsensical. - """ - if name == "fitrmin": - if value < self.configuration.rmin or value >= self.configuration.fitrmax: - value = self.configuration.rmin - self.textCtrlFitFrom.SetValue(str(value)) - elif name == "fitrmax": - if value < self.configuration.fitrmin or value >= self.configuration.rmax: - value = self.configuration.rmax - self.textCtrlFitTo.SetValue(str(value)) - return value - - # EVENT CODE ############################################################# - - def onStype(self, event): # wxGlade: DataSetConfigurePanel. - """Record the user's selection for stype.""" - value = event.GetInt() - self.configuration.stype = self.stypeMap[value] - self.mainFrame.needsSave() - return - - def onSampling(self, event): # wxGlade: DataSetConfigurePanel. - """Record how the data is to be sampled during the fit. - - This does not use the event argument, so feel free to call this - method programmatically. - """ - si = self.radioBoxSampling.GetSelection() - oldsampling = self.configuration.getFitSamplingType() - sampling = self.sampList[si] - oldstep = self.configuration.fitrstep - # Get the value of the custom sampling and enable/disable status - if sampling == "custom": # "custom" - txtbg = self.textCtrlFitStep.DefaultStyle.BackgroundColour - step = self.__coerseText(self.textCtrlFitStep.GetValue()) - self.textCtrlFitStep.SetEditable(True) - self.textCtrlFitStep.SetBackgroundColour(txtbg) - else: - step = None - self.textCtrlFitStep.SetEditable(False) - self.textCtrlFitStep.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT)) - - # Set the value of qmax - val = self.__coerseText(self.textCtrlQmax.GetValue()) - oldqmax = self.configuration.qmax - if oldqmax != val: - self.configuration.qmax = val - self.mainFrame.needsSave() - - # Set the configured value - if oldsampling != sampling or (sampling == "custom" and oldstep != step): - self.configuration.setFitSamplingType(sampling, step) - self.mainFrame.needsSave() - # Update the text control - self.textCtrlFitStep.SetValue(str(self.configuration.fitrstep)) - - if event is not None: - event.Skip() - return - - def onSetFocus(self, event): - """Saves a TextCtrl value, to be used later.""" - self._focusedText = event.GetEventObject().GetValue() - event.Skip() - return - - def onLoseFocus(self, event): - """Record the user's selection for the text ctrl data.""" - event.Skip() - if not self.configuration: - return - textCtrl = event.GetEventObject() - value = textCtrl.GetValue() - value = self.__coerseText(value) - name = textCtrl.GetName() - # Check the fit range - value = self.__adjustFitRange(name, value) - if name in self.metaNames: - temp = self.configuration.metadata.get(name) - if temp != value: - self.configuration.metadata[name] = value - self.mainFrame.needsSave() - else: - temp = getattr(self.configuration, name) - if temp != value: - setattr(self.configuration, name, value) - self.mainFrame.needsSave() - return - - # Methods overloaded from PDFPanel - - def refresh(self): - """Refresh the panel.""" - self.setConfigurationData() - self.restrictConstrainedParameters() - return - - -# end of class DataSetConfigurePanel diff --git a/src/diffpy/pdfgui/gui/datasetconstraintpanel.py b/src/diffpy/pdfgui/gui/datasetconstraintpanel.py deleted file mode 100644 index c585b579..00000000 --- a/src/diffpy/pdfgui/gui/datasetconstraintpanel.py +++ /dev/null @@ -1,176 +0,0 @@ -#!/usr/bin/env python -# -*- coding: UTF-8 -*- -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -# generated by wxGlade 0.9.3 on Fri Jul 19 16:01:02 2019 - -import wx - -from diffpy.pdfgui.control.constraint import Constraint -from diffpy.pdfgui.gui import tooltips -from diffpy.pdfgui.gui.pdfpanel import PDFPanel -from diffpy.pdfgui.gui.wxextensions.textctrlutils import textCtrlAsGridCell - - -class DataSetConstraintPanel(wx.Panel, PDFPanel): - def __init__(self, *args, **kwds): - PDFPanel.__init__(self) - # begin wxGlade: DataSetConstraintPanel.__init__ - kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL - wx.Panel.__init__(self, *args, **kwds) - self.panelNameLabel = wx.StaticText(self, wx.ID_ANY, "Data Set Constraints") - self.labelScaleFactor = wx.StaticText(self, wx.ID_ANY, "Scale Factor") - self.textCtrlScaleFactor = wx.TextCtrl(self, wx.ID_ANY, "") - self.labelQdamp = wx.StaticText(self, wx.ID_ANY, "Qdamp") - self.textCtrlQdamp = wx.TextCtrl(self, wx.ID_ANY, "") - self.labelQbroad = wx.StaticText(self, wx.ID_ANY, "Qbroad") - self.textCtrlQbroad = wx.TextCtrl(self, wx.ID_ANY, "") - - self.__set_properties() - self.__do_layout() - # end wxGlade - self.__customProperties() - - def __set_properties(self): - # begin wxGlade: DataSetConstraintPanel.__set_properties - self.panelNameLabel.SetFont( - wx.Font( - 18, - wx.FONTFAMILY_DEFAULT, - wx.FONTSTYLE_NORMAL, - wx.FONTWEIGHT_BOLD, - 0, - "", - ) - ) - # end wxGlade - - def __do_layout(self): - # begin wxGlade: DataSetConstraintPanel.__do_layout - sizer_1 = wx.BoxSizer(wx.VERTICAL) - grid_sizer_1 = wx.FlexGridSizer(3, 2, 5, 10) - sizer_panelname = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.HORIZONTAL) - sizer_panelname.Add(self.panelNameLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT, 5) - sizer_1.Add(sizer_panelname, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) - grid_sizer_1.Add( - self.labelScaleFactor, - 0, - wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, - 5, - ) - grid_sizer_1.Add(self.textCtrlScaleFactor, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - grid_sizer_1.Add(self.labelQdamp, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, 5) - grid_sizer_1.Add(self.textCtrlQdamp, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - grid_sizer_1.Add(self.labelQbroad, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, 5) - grid_sizer_1.Add(self.textCtrlQbroad, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - sizer_1.Add(grid_sizer_1, 0, wx.ALL | wx.EXPAND, 5) - self.SetSizer(sizer_1) - sizer_1.Fit(self) - self.Layout() - # end wxGlade - - # USER CONFIGURATION CODE ################################################# - - def __customProperties(self): - self._focusedText = None - self.constraints = {} - self.ctrlMap = { - "dscale": "textCtrlScaleFactor", - "qdamp": "textCtrlQdamp", - "qbroad": "textCtrlQbroad", - } - - # Give each textCtrl a name that can be referenced - for key, value in self.ctrlMap.items(): - textCtrl = getattr(self, value) - textCtrl.SetName(key) - - # Setup the event code. - for ctrlName in self.ctrlMap.values(): - textCtrl = getattr(self, ctrlName) - textCtrl.Bind(wx.EVT_SET_FOCUS, self.onSetFocus) - textCtrl.Bind(wx.EVT_KILL_FOCUS, self.onLoseFocus) - textCtrl.Bind(wx.EVT_KEY_DOWN, self.onTextCtrlKey) - - # Define tooltips. - self.setToolTips(tooltips.datasetconstraintpanel) - return - - # Create the onTextCtrlKey event handler from textCtrlAsGridCell from - # wxextensions.textctrlutils - onTextCtrlKey = textCtrlAsGridCell - - def setConstraintsData(self): - """Set the values in the constraints panel. - - The values come from the constraints member dictionary. dscale - qdamp qbroad - """ - for par, ctrlName in self.ctrlMap.items(): - textCtrl = getattr(self, ctrlName) - if par in self.constraints: - val = self.constraints[par].formula - textCtrl.SetValue(val) - else: - textCtrl.SetValue("") - return - - def processFormula(self, value, parname): - """Process a formula that was entered into a textCtrl.""" - formula = value.strip() - oldconst = self.constraints.get(parname) - oldformula = "" - if oldconst: - oldformula = oldconst.formula - if formula == "": - self.constraints.pop(parname, None) - elif oldformula != formula: - # Let the PDFGui error handler take care of this - self.constraints[parname] = Constraint(formula) - self.mainFrame.needsSave() - - return - - # EVENT CODE ############################################################# - def onSetFocus(self, event): - """Saves a TextCtrl value, to be compared in onKillFocus - later.""" - self._focusedText = event.GetEventObject().GetValue() - event.Skip() - return - - def onLoseFocus(self, event): - """Record the user's selection for the text ctrl data.""" - textCtrl = event.GetEventObject() - value = textCtrl.GetValue() - par = textCtrl.GetName() - self.processFormula(value, par) - if par in self.constraints: - val = self.constraints[par].formula - textCtrl.SetValue(val) - else: - textCtrl.SetValue("") - event.Skip() - return - - # Methods overloaded from PDFPanel - def refresh(self): - """Refresh the panel.""" - # Set the constraints data - self.setConstraintsData() - return - - -# end of class DataSetConstraintPanel diff --git a/src/diffpy/pdfgui/gui/datasetpanel.py b/src/diffpy/pdfgui/gui/datasetpanel.py deleted file mode 100644 index d49fcf7d..00000000 --- a/src/diffpy/pdfgui/gui/datasetpanel.py +++ /dev/null @@ -1,129 +0,0 @@ -#!/usr/bin/env python -# -*- coding: UTF-8 -*- -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -# generated by wxGlade 0.9.3 on Fri Jul 19 16:01:11 2019 - -import wx - -from diffpy.pdfgui.gui.datasetconfigurepanel import DataSetConfigurePanel -from diffpy.pdfgui.gui.datasetconstraintpanel import DataSetConstraintPanel -from diffpy.pdfgui.gui.datasetresultspanel import DataSetResultsPanel -from diffpy.pdfgui.gui.pdfpanel import PDFPanel - - -class DataSetPanel(wx.Panel, PDFPanel): - def __init__(self, *args, **kwds): - PDFPanel.__init__(self) - # begin wxGlade: DataSetPanel.__init__ - kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL - wx.Panel.__init__(self, *args, **kwds) - self.dataSetNotebook = wx.Notebook(self, wx.ID_ANY, style=0) - self.configurePage = wx.Panel(self.dataSetNotebook, wx.ID_ANY) - self.configurePanel = DataSetConfigurePanel(self.configurePage, wx.ID_ANY) - self.constraintsPage = wx.Panel(self.dataSetNotebook, wx.ID_ANY) - self.constraintPanel = DataSetConstraintPanel(self.constraintsPage, wx.ID_ANY) - self.resultsPage = wx.Panel(self.dataSetNotebook, wx.ID_ANY) - self.resultsPanel = DataSetResultsPanel(self.resultsPage, wx.ID_ANY) - - self.__set_properties() - self.__do_layout() - - self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.onNotebookChanged, self.dataSetNotebook) - # end wxGlade - self.__customProperties() - - def __set_properties(self): - # begin wxGlade: DataSetPanel.__set_properties - pass - # end wxGlade - - def __do_layout(self): - # begin wxGlade: DataSetPanel.__do_layout - sizer_3 = wx.BoxSizer(wx.VERTICAL) - sizer_7 = wx.BoxSizer(wx.HORIZONTAL) - sizer_6 = wx.BoxSizer(wx.HORIZONTAL) - sizer_1 = wx.BoxSizer(wx.HORIZONTAL) - sizer_1.Add(self.configurePanel, 1, wx.EXPAND, 0) - self.configurePage.SetSizer(sizer_1) - sizer_6.Add(self.constraintPanel, 1, wx.EXPAND, 0) - self.constraintsPage.SetSizer(sizer_6) - sizer_7.Add(self.resultsPanel, 1, wx.EXPAND, 0) - self.resultsPage.SetSizer(sizer_7) - self.dataSetNotebook.AddPage(self.configurePage, "Configure") - self.dataSetNotebook.AddPage(self.constraintsPage, "Constraints") - self.dataSetNotebook.AddPage(self.resultsPage, "Results") - sizer_3.Add(self.dataSetNotebook, 1, wx.EXPAND, 0) - self.SetSizer(sizer_3) - sizer_3.Fit(self) - self.Layout() - # end wxGlade - - # USER CONFIGURATION CODE ################################################# - - def __customProperties(self): - self.configuration = {} - self.constraints = {} - self.results = {} - - # Methods overloaded from PDFPanel - def refresh(self): - self.configurePanel.treeCtrlMain = self.treeCtrlMain - self.constraintPanel.treeCtrlMain = self.treeCtrlMain - self.resultsPanel.treeCtrlMain = self.treeCtrlMain - self.configurePanel.mainFrame = self.mainFrame - self.constraintPanel.mainFrame = self.mainFrame - self.resultsPanel.mainFrame = self.mainFrame - self.configurePanel.configuration = self.configuration - self.configurePanel.constraints = self.constraints - self.constraintPanel.constraints = self.constraints - self.resultsPanel.results = self.results - - # Refresh the visible panel - self.refreshSelectedPage() - return - - def refreshSelectedPage(self): - """Refresh the panel corresponding to the currently selected - page.""" - # self.configurePanel.refresh() - # self.constraintPanel.refresh() - # self.resultsPanel.refresh() - id = self.dataSetNotebook.GetCurrentPage().GetId() - if id == self.configurePage.GetId(): - self.configurePanel.refresh() - elif id == self.constraintsPage.GetId(): - self.constraintPanel.refresh() - elif id == self.resultsPage.GetId(): - self.resultsPanel.refresh() - return id - - # EVENT CODE ############################################################# - - def onNotebookChanged(self, event): # wxGlade: DataSetPanel. - """Refresh the selected panel.""" - self.refreshSelectedPage() - return - - # Overloaded from Panel. - def Enable(self, enable=True): - """Keep the notebook enabled, just not the panels.""" - self.configurePanel.Enable(enable) - self.constraintPanel.Enable(enable) - self.resultsPanel.Enable(enable) - return - - -# end of class DataSetPanel diff --git a/src/diffpy/pdfgui/gui/datasetresultspanel.py b/src/diffpy/pdfgui/gui/datasetresultspanel.py deleted file mode 100644 index e3670afc..00000000 --- a/src/diffpy/pdfgui/gui/datasetresultspanel.py +++ /dev/null @@ -1,135 +0,0 @@ -#!/usr/bin/env python -# -*- coding: UTF-8 -*- -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -# generated by wxGlade 0.9.3 on Fri Jul 19 16:01:22 2019 - -from __future__ import print_function - -import wx - -from diffpy.pdfgui.gui import tooltips -from diffpy.pdfgui.gui.pdfpanel import PDFPanel - - -class DataSetResultsPanel(wx.Panel, PDFPanel): - def __init__(self, *args, **kwds): - # begin wxGlade: DataSetResultsPanel.__init__ - kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL - wx.Panel.__init__(self, *args, **kwds) - - sizer_7 = wx.BoxSizer(wx.VERTICAL) - - sizer_panelname = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.HORIZONTAL) - sizer_7.Add(sizer_panelname, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) - - self.panelNameLabel = wx.StaticText(self, wx.ID_ANY, "Data Set Results") - self.panelNameLabel.SetFont( - wx.Font( - 18, - wx.FONTFAMILY_DEFAULT, - wx.FONTSTYLE_NORMAL, - wx.FONTWEIGHT_BOLD, - 0, - "", - ) - ) - sizer_panelname.Add(self.panelNameLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT, 5) - - grid_sizer_1 = wx.FlexGridSizer(3, 2, 5, 10) - sizer_7.Add(grid_sizer_1, 0, wx.ALL | wx.EXPAND, 5) - - self.labelScaleFactor = wx.StaticText(self, wx.ID_ANY, "Scale Factor") - grid_sizer_1.Add( - self.labelScaleFactor, - 0, - wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, - 5, - ) - - self.textCtrlScaleFactor = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) - grid_sizer_1.Add(self.textCtrlScaleFactor, 0, wx.ALIGN_CENTER_VERTICAL, 20) - - self.labelQdamp = wx.StaticText(self, wx.ID_ANY, "Qdamp") - grid_sizer_1.Add(self.labelQdamp, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, 5) - - self.textCtrlQdamp = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) - grid_sizer_1.Add(self.textCtrlQdamp, 0, wx.ALIGN_CENTER_VERTICAL, 20) - - self.labelQbroad = wx.StaticText(self, wx.ID_ANY, "Qbroad") - grid_sizer_1.Add(self.labelQbroad, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT, 5) - - self.textCtrlQbroad = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) - grid_sizer_1.Add(self.textCtrlQbroad, 0, wx.ALIGN_CENTER_VERTICAL, 20) - - self.buttonExport = wx.Button(self, wx.ID_OPEN, "Export PDF") - self.buttonExport.Hide() - sizer_7.Add(self.buttonExport, 0, wx.ALIGN_RIGHT | wx.ALL, 5) - - self.SetSizer(sizer_7) - sizer_7.Fit(self) - - self.Layout() - - self.Bind(wx.EVT_BUTTON, self.onExport, self.buttonExport) - # end wxGlade - self.__customProperties() - - # USER CONFIGURATION CODE ################################################# - - def __customProperties(self): - self.results = {} - self.ctrlMap = { - "dscale": "textCtrlScaleFactor", - "qdamp": "textCtrlQdamp", - "qbroad": "textCtrlQbroad", - } - # Define tooltips. - self.setToolTips(tooltips.datasetresultspanel) - return - - def setResultsData(self): - """Set the values in the results panel. - - The values are taken from the results member dictionary. - dscale -- float - qdamp -- float - qbroad -- float - """ - for name in self.ctrlMap: - value = self.results.get(name, None) - ctrlName = self.ctrlMap[name] - textCtrl = getattr(self, ctrlName) - if value is not None: - textCtrl.SetValue(str(value)) - else: - textCtrl.SetValue("") - return - - # EVENT CODE ############################################################# - - def onExport(self, event): # wxGlade: DataSetResultsPanel. - print("Event handler `onExport' not implemented") - event.Skip() - - # Methods overloaded from PDFPanel - def refresh(self): - """Refresh the panel.""" - # Set the results data - self.setResultsData() - return - - -# end of class DataSetResultsPanel diff --git a/src/diffpy/pdfgui/gui/debugoptions.py b/src/diffpy/pdfgui/gui/debugoptions.py deleted file mode 100644 index 3b5af79e..00000000 --- a/src/diffpy/pdfgui/gui/debugoptions.py +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""DebugOptions class for storing guess three time what. - -There should be exactly one instance of DebugOptions in pdfguiglobals -module. -""" - - -class DebugOptions: - """DebugOptions is a place to store various debugging options. There - should be just one instance defined in pdfguiglobals module. It - would be nice to have a simple way of setting them on command line. - - Options in short and long forms: - noed, noerrordialog -- [False], disable exceptions catching and - display in ErrorReportDialog - nocf, noconfirm -- boolean (default False), exit without asking to - save modified project file - pdb, pythondebugger -- use python debugger to handle error exceptions - instead of ErrorReportDialog - """ - - # global list of all options - alldebugoptions = ( - ("noed", "noerrordialog"), - ("nocf", "noconfirm"), - ("pdb", "pythondebugger"), - ) - # global dictionary for converting long options to short - short2long = dict(alldebugoptions) - - def __init__(self): - """Initialize DebugOptions, by default all of them are off.""" - self.noerrordialog = False - self.noconfirm = False - self.pythondebugger = False - return - - def __setattr__(self, name, value): - """Map short options to their long equivalents.""" - if name in DebugOptions.short2long: - longname = DebugOptions.short2long[name] - else: - longname = name - self.__dict__[longname] = value - return - - def __getattr__(self, name): - """Resolve values of short options. This is called only when - normal lookup fails. - - returns value of short debug option - """ - if name in DebugOptions.short2long: - longname = DebugOptions.short2long[name] - value = getattr(self, longname) - else: - raise AttributeError("An instance has no attribute %r" % name) - return value - - -# End of class DebugOptions - -# End of file diff --git a/src/diffpy/pdfgui/gui/design/__init__.py b/src/diffpy/pdfgui/gui/design/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/src/diffpy/pdfgui/gui/design/aboutdialog.wxg b/src/diffpy/pdfgui/gui/design/aboutdialog.wxg deleted file mode 100644 index 049d8f97..00000000 --- a/src/diffpy/pdfgui/gui/design/aboutdialog.wxg +++ /dev/null @@ -1,303 +0,0 @@ - - - - - - 600, 595 - About - - 1 - - wxVERTICAL - - - 3 - wxBOTTOM|wxEXPAND - - wxHORIZONTAL - - - 0 - wxEXPAND - - - $parent - $id - wx.Bitmap(iconpath("logo.png")) - - - - - - 0 - wxEXPAND - - wxVERTICAL - - - 0 - wxEXPAND - - wxHORIZONTAL - - - 10 - wxLEFT|wxTOP|wxEXPAND - - - 26 - default - - bold - 0 - - - - 1 - - - - - 0 - wxEXPAND - - 20 - 20 - - - - - 10 - wxRIGHT|wxALIGN_BOTTOM - - - 26 - default - - normal - 0 - - - 1 - - - - - - - 5 - wxTOP|wxEXPAND - - wxHORIZONTAL - - - 10 - wxLEFT|wxRIGHT - - - 1 - - - - - 0 - - 1 - - - - - - - 10 - wxLEFT|wxRIGHT|wxTOP - - 1 - - - - - 10 - wxLEFT|wxRIGHT - - - 1 - - - - - 10 - wxLEFT|wxRIGHT - - - $parent - $id - _homepage - URL=_homepage - - - - - - 0 - - 20 - 20 - - - - - 10 - wxLEFT|wxRIGHT - - 1 - 1 - - $parent - $id - _license - URL=_license - - - - - - - - - - 0 - wxEXPAND - - - 1 - - - - - 7 - wxLEFT|wxTOP|wxBOTTOM - - 1 - - - - - 7 - wxLEFT|wxTOP|wxBOTTOM - - - $parent - $id - _paper - URL=_paper - - - - - - 0 - wxEXPAND - - - 1 - - - - - 0 - wxEXPAND - - wxHORIZONTAL - - - 2 - wxLEFT - - - onNsfLogo - - - - - - - 2 - wxLEFT - - - onDanseLogo - - - - - - - 2 - wxLEFT - - - onMsuLogo - - - - - - - 2 - wxLEFT - - - onColumbiaLogo - - - - - - - 0 - - 50 - 50 - - - - - - - 0 - wxEXPAND - - - 1 - - - - - 0 - wxEXPAND - - wxHORIZONTAL - - - 0 - wxEXPAND - - 20 - 20 - - - - - 10 - wxRIGHT - - wx.ID_OK - - - - - - - - diff --git a/src/diffpy/pdfgui/gui/design/adddatapanel.wxg b/src/diffpy/pdfgui/gui/design/adddatapanel.wxg deleted file mode 100644 index 1c06e666..00000000 --- a/src/diffpy/pdfgui/gui/design/adddatapanel.wxg +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - wxVERTICAL - - - 5 - wxTOP|wxBOTTOM|wxEXPAND - - wxHORIZONTAL - - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - - - 12 - default - - normal - 0 - Sans - - - 1 - - - - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - - - onOpen - - wx.ID_OPEN - - - - - - - - 10 - wxBOTTOM|wxEXPAND - - - 1 - - - - - 5 - wxALL|wxALIGN_RIGHT - - - onCancel - - wx.ID_CANCEL - - - - - - 0 - - 450 - 0 - - - - - diff --git a/src/diffpy/pdfgui/gui/design/addphasepanel.wxg b/src/diffpy/pdfgui/gui/design/addphasepanel.wxg deleted file mode 100644 index c2345a8a..00000000 --- a/src/diffpy/pdfgui/gui/design/addphasepanel.wxg +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - wxVERTICAL - - - 5 - wxTOP|wxBOTTOM|wxEXPAND - - wxHORIZONTAL - - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - - - 12 - default - - normal - 0 - Sans - - - 1 - - - - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - - - onOpen - - wx.ID_OPEN - - - - - - - - 0 - wxEXPAND - - - 1 - - - - - 5 - wxTOP|wxBOTTOM|wxEXPAND - - wxHORIZONTAL - - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - - - 12 - default - - normal - 0 - Sans - - - 1 - - - - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - - - onNew - - wx.ID_NEW - - - - - - - - 10 - wxBOTTOM|wxEXPAND - - - 1 - - - - - 5 - wxALL|wxALIGN_RIGHT - - - onCancel - - wx.ID_CANCEL - - - - - - 0 - - 450 - 10 - - - - - diff --git a/src/diffpy/pdfgui/gui/design/bondlengthdialog.wxg b/src/diffpy/pdfgui/gui/design/bondlengthdialog.wxg deleted file mode 100644 index 6d80666e..00000000 --- a/src/diffpy/pdfgui/gui/design/bondlengthdialog.wxg +++ /dev/null @@ -1,211 +0,0 @@ - - - - - - Calculate Bond Lengths - - - wxVERTICAL - - - 5 - wxALL - - - 1 - - - - - 0 - wxEXPAND - - wxHORIZONTAL - - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 5 - wxALL - - - onSpin - - 80, 27 - 0, 100 - - - - - 5 - wxALL - - - onSpin - - 80, 27 - 0, 100 - - - - - - - 5 - wxBOTTOM|wxEXPAND - - - 1 - - - - - 5 - wxALL - - - 1 - - - - - 0 - wxEXPAND - - wxHORIZONTAL - - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 5 - wxALL - - 80, 27 - -1 - - - - - - - 5 - wxALL - - 80, 27 - -1 - - - - - - - - - 0 - wxEXPAND - - wxHORIZONTAL - - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 5 - wxALL - - 80, 27 - - - - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 5 - wxALL - - 80, 27 - - - - - - - 0 - wxEXPAND - - - 1 - - - - - 0 - wxEXPAND - - wxHORIZONTAL - - - 0 - wxEXPAND - - 0 - 0 - - - - - 5 - wxALL - - - onCancel - - wx.ID_CANCEL - - - - - - 5 - wxALL - - - onOk - - wx.ID_OK - - - - - - - - diff --git a/src/diffpy/pdfgui/gui/design/calculationpanel.wxg b/src/diffpy/pdfgui/gui/design/calculationpanel.wxg deleted file mode 100644 index 54a24565..00000000 --- a/src/diffpy/pdfgui/gui/design/calculationpanel.wxg +++ /dev/null @@ -1,264 +0,0 @@ - - - - - - - - wxHORIZONTAL - - - 0 - wxEXPAND - - wxVERTICAL - - - 5 - wxLEFT|wxRIGHT|wxEXPAND - - wxHORIZONTAL - - - 5 - wxLEFT|wxRIGHT|wxALIGN_CENTER_VERTICAL - - - 18 - default - - bold - 0 - - - - 1 - - - - - - - 0 - - 450 - 5 - - - - - 5 - wxALL - - - onStype - - 330, 43 - - 2 - 0 - - Neutron - X-ray - - - - - - - 5 - wxALL|wxEXPAND - - 4 - 6 - 5 - 10 - - - 5 - wxLEFT|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - - 1 - - - - - 0 - wxALIGN_CENTER_VERTICAL - - 1.0 - - - - - 20 - wxLEFT|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - - 1 - - - - - 0 - wxALIGN_CENTER_VERTICAL - - 10.0 - - - - - 5 - wxLEFT|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - - 1 - - - - - 0 - wxALIGN_CENTER_VERTICAL - - 0.01 - - - - - 5 - wxLEFT|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - - 1 - - - - - 0 - wxALIGN_CENTER_VERTICAL - - 1.0 - - - - - 20 - wxLEFT|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - - 1 - - - - - 0 - wxALIGN_CENTER_VERTICAL - - 25.0 - - - - - 0 - - 1 - - - - - 0 - - 1 - - - - - 5 - wxLEFT|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - - 1 - - - - - 0 - wxALIGN_CENTER_VERTICAL - - 0.0 - - - - - 5 - wxLEFT|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - - 1 - - - - - 0 - wxALIGN_CENTER_VERTICAL - - 0.0 - - - - - 0 - - 1 - - - - - 0 - - 1 - - - - - 0 - - 1 - - - - - 0 - - 1 - - - - - 0 - - 1 - - - - - 0 - - 1 - - - - - - - - - diff --git a/src/diffpy/pdfgui/gui/design/datasetconfigurepanel.wxg b/src/diffpy/pdfgui/gui/design/datasetconfigurepanel.wxg deleted file mode 100644 index 4bf7c968..00000000 --- a/src/diffpy/pdfgui/gui/design/datasetconfigurepanel.wxg +++ /dev/null @@ -1,356 +0,0 @@ - - - - - - - - wxHORIZONTAL - - - 0 - wxEXPAND - - wxVERTICAL - - - 5 - wxLEFT|wxRIGHT|wxEXPAND - - wxHORIZONTAL - - - 5 - wxLEFT|wxRIGHT|wxALIGN_CENTER_VERTICAL - - - 18 - default - - bold - 0 - - - - 1 - - - - - - - 0 - - 450 - 5 - - - - - 5 - wxALL - - - onStype - - 330, 43 - - 2 - 0 - - Neutron - X-ray - - - - - - - 5 - wxALL - - - onSampling - - 232, 44 - - 3 - 0 - - Data - Nyquist - Custom - - - - - - - 5 - wxALL|wxEXPAND - - 5 - 6 - 5 - 10 - - - 5 - wxLEFT|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - - wxSYS_COLOUR_GRAYTEXT - - - - - - 20 - wxLEFT|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - - wxSYS_COLOUR_GRAYTEXT - - - - - - 20 - wxLEFT|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - - wxSYS_COLOUR_GRAYTEXT - - - - - - 5 - wxLEFT|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - - 1 - - - - - 0 - wxALIGN_CENTER_VERTICAL - - 1.0 - - - - - 20 - wxLEFT|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - - 1 - - - - - 0 - wxALIGN_CENTER_VERTICAL - - 10.0 - - - - - 20 - wxLEFT|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALIGN_CENTER_VERTICAL - - 0 - - - - - 5 - wxLEFT|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - - 1 - - - - - 0 - wxALIGN_CENTER_VERTICAL - - 1.0 - - - - - 20 - wxLEFT|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - - 1 - - - - - 0 - wxALIGN_CENTER_VERTICAL - - 25.0 - - - - - 0 - - 1 - - - - - 0 - - 1 - - - - - 5 - wxLEFT|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - - 1 - - - - - 0 - wxALIGN_CENTER_VERTICAL - - 0.0 - - - - - 20 - wxLEFT|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - - 1 - - - - - 0 - wxALIGN_CENTER_VERTICAL - - 0.0 - - - - - 0 - - 1 - - - - - 0 - - 1 - - - - - 5 - wxLEFT|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - - 1 - - - - - 0 - wxALIGN_CENTER_VERTICAL - - 300.0 - - - - - 20 - wxLEFT|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - - 1 - - - - - 0 - wxALIGN_CENTER_VERTICAL - - 1.0 - - - - - 0 - - 1 - - - - - 0 - - 1 - - - - - - - - - diff --git a/src/diffpy/pdfgui/gui/design/datasetconstraintpanel.wxg b/src/diffpy/pdfgui/gui/design/datasetconstraintpanel.wxg deleted file mode 100644 index 341c1dc3..00000000 --- a/src/diffpy/pdfgui/gui/design/datasetconstraintpanel.wxg +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - - wxVERTICAL - - - 5 - wxLEFT|wxRIGHT|wxEXPAND - - wxHORIZONTAL - - - 5 - wxLEFT|wxRIGHT|wxALIGN_CENTER_VERTICAL - - - 18 - default - - bold - 0 - - - - 1 - - - - - - - 5 - wxALL|wxEXPAND - - 3 - 2 - 5 - 10 - - - 5 - wxLEFT|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - 5 - wxLEFT|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - 5 - wxLEFT|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - - diff --git a/src/diffpy/pdfgui/gui/design/datasetpanel.wxg b/src/diffpy/pdfgui/gui/design/datasetpanel.wxg deleted file mode 100644 index d2ff8c16..00000000 --- a/src/diffpy/pdfgui/gui/design/datasetpanel.wxg +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - wxVERTICAL - - - 0 - wxEXPAND - - - onNotebookChanged - - - Configure - Constraints - Results - - - - - wxHORIZONTAL - - - 0 - wxEXPAND - - - $parent - $id - - - - - - - - - wxHORIZONTAL - - - 0 - wxEXPAND - - - $parent - $id - - - - - - - - - wxHORIZONTAL - - - 0 - wxEXPAND - - - $parent - $id - - - - - - - - - - diff --git a/src/diffpy/pdfgui/gui/design/datasetresultspanel.wxg b/src/diffpy/pdfgui/gui/design/datasetresultspanel.wxg deleted file mode 100644 index 70fb6f67..00000000 --- a/src/diffpy/pdfgui/gui/design/datasetresultspanel.wxg +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - - - wxVERTICAL - - - 5 - wxLEFT|wxRIGHT|wxEXPAND - - wxHORIZONTAL - - - 5 - wxLEFT|wxRIGHT|wxALIGN_CENTER_VERTICAL - - - 18 - default - - bold - 0 - - - - 1 - - - - - - - 5 - wxALL|wxEXPAND - - 3 - 2 - 5 - 10 - - - 5 - wxLEFT|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 20 - wxALIGN_CENTER_VERTICAL - - - - - - - 5 - wxLEFT|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 20 - wxALIGN_CENTER_VERTICAL - - - - - - - 5 - wxLEFT|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 20 - wxALIGN_CENTER_VERTICAL - - - - - - - - - 5 - wxALL|wxALIGN_RIGHT - - - onExport - - wx.ID_OPEN - 1 - - - - - - diff --git a/src/diffpy/pdfgui/gui/design/dopingseriespanel.wxg b/src/diffpy/pdfgui/gui/design/dopingseriespanel.wxg deleted file mode 100644 index d43421f6..00000000 --- a/src/diffpy/pdfgui/gui/design/dopingseriespanel.wxg +++ /dev/null @@ -1,225 +0,0 @@ - - - - - - - - wxVERTICAL - - - 5 - wxALL|wxEXPAND - - - 10 - default - - normal - 0 - Sans - - - 1 - - - - - 0 - wxEXPAND - - wxHORIZONTAL - - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 5 - wxALL - - - - - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 5 - wxALL - - - - - - - - 0 - wxEXPAND - - wxVERTICAL - - - 0 - wxEXPAND - - wxHORIZONTAL - - - 5 - wxALL|wxEXPAND - - - onColClick - onEndLabelEdit - - - - - - - 0 - wxEXPAND - - wxVERTICAL - - - 0 - - 0 - 0 - - - - - 5 - wxALL - - - onUp - - - - - - - 5 - wxALL - - - onDown - - - - - - - 0 - - 0 - 0 - - - - - - - - - - - 5 - wxALL - - 1 - 2 - 10 - 10 - - - 0 - - - onAdd - - wx.ID_ADD - - - - - - 0 - - - onDelete - - wx.ID_DELETE - - - - - - - - 0 - wxEXPAND - - - 1 - - - - - 0 - wxEXPAND - - wxHORIZONTAL - - - 0 - wxEXPAND - - 20 - 20 - - - - - 5 - wxALL - - - onOK - - wx.ID_OK - - - - - - 5 - wxALL - - - onCancel - - wx.ID_CANCEL - - - - - - - - diff --git a/src/diffpy/pdfgui/gui/design/errorreportdialog.wxg b/src/diffpy/pdfgui/gui/design/errorreportdialog.wxg deleted file mode 100644 index fde229dd..00000000 --- a/src/diffpy/pdfgui/gui/design/errorreportdialog.wxg +++ /dev/null @@ -1,113 +0,0 @@ - - - - - - 540, 600 - Problem Report for PDFgui - - - wxVERTICAL - - - 5 - wxALL|wxEXPAND - - wxHORIZONTAL - - - 5 - wxEXPAND - - - $parent - $id - - - - - - - - 10 - wxLEFT|wxRIGHT|wxTOP|wxEXPAND - - wxVERTICAL - - - 5 - wxLEFT|wxRIGHT|wxTOP|wxEXPAND - - - 1 - - - - - 5 - wxLEFT|wxRIGHT|wxEXPAND - - - - - - - - - 5 - wxLEFT|wxRIGHT|wxTOP|wxEXPAND - - - 1 - - - - - 0 - wxEXPAND - - wxHORIZONTAL - - - 0 - - 20 - 20 - - - - - 5 - wxALL - - - onGoogle - - - - - - - 5 - wxALL - - - onCopyErrorLog - - - - - - - 5 - wxALL - - wx.ID_CANCEL - - - - - - - - diff --git a/src/diffpy/pdfgui/gui/design/fitnotebookpanel.wxg b/src/diffpy/pdfgui/gui/design/fitnotebookpanel.wxg deleted file mode 100644 index f818926b..00000000 --- a/src/diffpy/pdfgui/gui/design/fitnotebookpanel.wxg +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - wxHORIZONTAL - - - 0 - wxEXPAND - - - onPageChanged - onPageChanging - - - Parameters - Results - - - - 1 - - - - 1 - - - - - - diff --git a/src/diffpy/pdfgui/gui/design/insertrowsdialog.wxg b/src/diffpy/pdfgui/gui/design/insertrowsdialog.wxg deleted file mode 100644 index 2da55483..00000000 --- a/src/diffpy/pdfgui/gui/design/insertrowsdialog.wxg +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - InsertRows - - - wxHORIZONTAL - - - 0 - wxEXPAND - - wxVERTICAL - - - 0 - wxEXPAND - - wxHORIZONTAL - - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - - 0, 100 - 1 - - - - - - - 5 - wxALL|wxEXPAND - - 2 - 1 - - Above - Below - - - - - - - - - 0 - wxEXPAND - - wxVERTICAL - - - 5 - wxALL - - wx.ID_OK - - - - - - 5 - wxALL - - wx.ID_CANCEL - - - - - - - - diff --git a/src/diffpy/pdfgui/gui/design/journalpanel.wxg b/src/diffpy/pdfgui/gui/design/journalpanel.wxg deleted file mode 100644 index 871bf8e3..00000000 --- a/src/diffpy/pdfgui/gui/design/journalpanel.wxg +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - wxVERTICAL - - - 0 - wxEXPAND - - - onText - - - - - - - 0 - wxEXPAND - - wxHORIZONTAL - - - 0 - - 1 - 1 - - - - - 5 - wxALL - - - onExport - - - - - - - 5 - wxALL - - - onClose - - wx.ID_CLOSE - - - - - - - diff --git a/src/diffpy/pdfgui/gui/design/outputpanel.wxg b/src/diffpy/pdfgui/gui/design/outputpanel.wxg deleted file mode 100644 index fa536dfa..00000000 --- a/src/diffpy/pdfgui/gui/design/outputpanel.wxg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - wxVERTICAL - - - 0 - wxALL|wxEXPAND - - - - - - - diff --git a/src/diffpy/pdfgui/gui/design/parameterspanel.wxg b/src/diffpy/pdfgui/gui/design/parameterspanel.wxg deleted file mode 100644 index d9c7a82b..00000000 --- a/src/diffpy/pdfgui/gui/design/parameterspanel.wxg +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - wxVERTICAL - - - 0 - wxEXPAND - - - onCellChange - onCellLeftClick - onCellRightClick - onEditorShown - onGridRangeSelect - - 1 - - Initial - Fixed - Refined - - 0 - 1 - 1 - 1 - 0 - 1 - wxGrid.wxGridSelectCells - - - - - 0 - wxEXPAND - - wxHORIZONTAL - - - 0 - - 20 - 20 - - - - - 5 - wxALL - - - onApplyParameters - - - - - - - - - diff --git a/src/diffpy/pdfgui/gui/design/phaseconfigurepanel.wxg b/src/diffpy/pdfgui/gui/design/phaseconfigurepanel.wxg deleted file mode 100644 index 07af80c8..00000000 --- a/src/diffpy/pdfgui/gui/design/phaseconfigurepanel.wxg +++ /dev/null @@ -1,396 +0,0 @@ - - - - - - 1 - - - wxVERTICAL - - - 5 - wxLEFT|wxRIGHT|wxEXPAND - - wxHORIZONTAL - - - 5 - wxLEFT|wxRIGHT|wxALIGN_CENTER_VERTICAL - - - 18 - default - - bold - 0 - - - - 1 - - - - - - - 5 - wxLEFT|wxRIGHT|wxEXPAND - - wxHORIZONTAL - - - 0 - wxEXPAND - - 2 - 6 - 0 - 0 - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - - - - - 5 - wxLEFT|wxRIGHT|wxEXPAND - - wxHORIZONTAL - - - 0 - wxEXPAND - - 3 - 6 - 0 - 0 - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - 0 - - 20 - 10 - - - - - 0 - - 20 - 10 - - - - - 0 - - 20 - 10 - - - - - 0 - - 20 - 10 - - - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - - - - - 5 - wxLEFT|wxRIGHT|wxEXPAND - - wxVERTICAL - - - 0 - wxEXPAND - - wxHORIZONTAL - - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 5 - wxALL - - 240, 25 - all-all - - - - - - - 0 - wxEXPAND - - - onCellChange - onCellRightClick - onEditorShown - onLabelRightClick - - 1 - - elem - x - y - z - u11 - u22 - u33 - u12 - u13 - u23 - occ - - 0 - 1 - 1 - 1 - 0 - 1 - wxGrid.wxGridSelectCells - - - - - - - diff --git a/src/diffpy/pdfgui/gui/design/phaseconstraintspanel.wxg b/src/diffpy/pdfgui/gui/design/phaseconstraintspanel.wxg deleted file mode 100644 index 2695d6b1..00000000 --- a/src/diffpy/pdfgui/gui/design/phaseconstraintspanel.wxg +++ /dev/null @@ -1,396 +0,0 @@ - - - - - - - - wxVERTICAL - - - 5 - wxLEFT|wxRIGHT|wxEXPAND - - wxHORIZONTAL - - - 5 - wxLEFT|wxRIGHT|wxALIGN_CENTER_VERTICAL - - - 18 - default - - bold - 0 - - - - 1 - - - - - - - 5 - wxLEFT|wxRIGHT|wxEXPAND - - wxHORIZONTAL - - - 0 - wxEXPAND - - 2 - 6 - 0 - 0 - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - - - - - 5 - wxLEFT|wxRIGHT|wxEXPAND - - wxHORIZONTAL - - - 0 - wxEXPAND - - 3 - 6 - 0 - 0 - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - 0 - - 20 - 10 - - - - - 0 - - 20 - 10 - - - - - 0 - - 20 - 10 - - - - - 0 - - 20 - 10 - - - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - - - - - 5 - wxLEFT|wxRIGHT|wxEXPAND - - wxVERTICAL - - - 0 - wxEXPAND - - wxHORIZONTAL - - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 5 - wxALL - - 240, 25 - - all-all - - - - - - - 0 - wxEXPAND - - - onCellChange - onCellRightClick - onEditorShown - onLabelRightClick - - 1 - - elem - x - y - z - u11 - u22 - u33 - u12 - u13 - u23 - occ - - 0 - 1 - 1 - 1 - 0 - 1 - wxGrid.wxGridSelectCells - - - - - - - diff --git a/src/diffpy/pdfgui/gui/design/phaseresultspanel.wxg b/src/diffpy/pdfgui/gui/design/phaseresultspanel.wxg deleted file mode 100644 index f0b546b7..00000000 --- a/src/diffpy/pdfgui/gui/design/phaseresultspanel.wxg +++ /dev/null @@ -1,390 +0,0 @@ - - - - - - - - wxVERTICAL - - - 5 - wxLEFT|wxRIGHT|wxEXPAND - - wxHORIZONTAL - - - 5 - wxLEFT|wxRIGHT|wxALIGN_CENTER_VERTICAL - - - 18 - default - - bold - 0 - - - - 1 - - - - - - - 5 - wxLEFT|wxRIGHT|wxEXPAND - - wxHORIZONTAL - - - 0 - wxEXPAND - - 2 - 6 - 0 - 0 - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - - - - - 5 - wxLEFT|wxRIGHT|wxEXPAND - - wxHORIZONTAL - - - 0 - wxEXPAND - - 3 - 6 - 0 - 0 - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - 0 - - 20 - 10 - - - - - 0 - - 20 - 10 - - - - - 0 - - 20 - 10 - - - - - 0 - - 20 - 10 - - - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - 5 - wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxALL|wxALIGN_CENTER_VERTICAL - - - - - - - - - - - 5 - wxLEFT|wxRIGHT|wxEXPAND - - wxVERTICAL - - - 0 - wxEXPAND - - wxHORIZONTAL - - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 5 - wxALL - - 240, 25 - - all-all - - - - - - - 0 - wxEXPAND - - 1 - - elem - x - y - z - u11 - u22 - u33 - u12 - u13 - u23 - occ - - 0 - 0 - 1 - 1 - 0 - 1 - wxGrid.wxGridSelectCells - - - - - - - diff --git a/src/diffpy/pdfgui/gui/design/plotpanel.wxg b/src/diffpy/pdfgui/gui/design/plotpanel.wxg deleted file mode 100644 index da3370cf..00000000 --- a/src/diffpy/pdfgui/gui/design/plotpanel.wxg +++ /dev/null @@ -1,118 +0,0 @@ - - - - - - 456, 659 - - - wxVERTICAL - - - 0 - wxEXPAND - - wxHORIZONTAL - - - - 5 - wxALL - - - -1 - - - - - - - - - 0 - wxEXPAND - - wxHORIZONTAL - - - - 5 - wxALL|wxEXPAND - - - - - - - - - 0 - wxEXPAND - - wxHORIZONTAL - - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - - - - 1 - - - - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - - - onEnter - - - -5 - - - - - - - 5 - wxTOP|wxBOTTOM|wxEXPAND - - - 1 - - - - - 0 - wxEXPAND - - wxHORIZONTAL - - - 5 - wxALL - - - onPlot - - - - - - - 5 - wxALL - - - onReset - - - - - - - - - diff --git a/src/diffpy/pdfgui/gui/design/preferencespanel.wxg b/src/diffpy/pdfgui/gui/design/preferencespanel.wxg deleted file mode 100644 index 6825722f..00000000 --- a/src/diffpy/pdfgui/gui/design/preferencespanel.wxg +++ /dev/null @@ -1,198 +0,0 @@ - - - - - - - - wxVERTICAL - - - 5 - wxLEFT|wxRIGHT|wxEXPAND - - wxHORIZONTAL - - - 5 - wxLEFT|wxRIGHT|wxEXPAND - - - 18 - default - - bold - 0 - Bitstream Vera Sans - - - 1 - - - - - - - 5 - wxALL - - 3 - 3 - 10 - 10 - - - 0 - wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxEXPAND - - - - - - 0 - - - onBrowse - - - - - - - 0 - wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxEXPAND - - - - - - 0 - - 20 - 20 - - - - - 0 - wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 0 - wxEXPAND - - -1 - - - - - - - 0 - - 20 - 20 - - - - - - - 5 - wxALL - - - - - - - 5 - wxALL - - - - - - - 0 - wxEXPAND - - 0 - 0 - - - - - 5 - wxLEFT|wxRIGHT|wxEXPAND - - - 1 - - - - - 0 - wxEXPAND - - wxHORIZONTAL - - - 0 - - 0 - 0 - - - - - 5 - wxALL - - - onOK - - wx.ID_OK - - - - - - 5 - wxALL - - - onCancel - - wx.ID_CANCEL - - - - - - - - diff --git a/src/diffpy/pdfgui/gui/design/resultspanel.wxg b/src/diffpy/pdfgui/gui/design/resultspanel.wxg deleted file mode 100644 index 7e1d833a..00000000 --- a/src/diffpy/pdfgui/gui/design/resultspanel.wxg +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - wxVERTICAL - - - 5 - wxALL|wxEXPAND - - wxHORIZONTAL - - - 5 - wxALL - - - 18 - default - - bold - 0 - - - - 1 - - - - - - - 5 - wxALL|wxEXPAND - - - Fit results will display here once the fit is complete. - - - - - diff --git a/src/diffpy/pdfgui/gui/design/rseriespanel.wxg b/src/diffpy/pdfgui/gui/design/rseriespanel.wxg deleted file mode 100644 index ee0bde33..00000000 --- a/src/diffpy/pdfgui/gui/design/rseriespanel.wxg +++ /dev/null @@ -1,183 +0,0 @@ - - - - - - - - wxVERTICAL - - - 5 - wxALL|wxEXPAND - - - 10 - default - - normal - 0 - Sans - - - 1 - - - - - 5 - wxALL|wxEXPAND - - wxHORIZONTAL - - - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 5 - wxALL - - - - - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 5 - wxALL - - - - - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 5 - wxALL - - - - - - - - 5 - wxALL|wxEXPAND - - wxHORIZONTAL - - - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 5 - wxALL - - - - - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 5 - wxALL - - - - - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 5 - wxALL - - - - - - - - 0 - wxEXPAND - - wxHORIZONTAL - - - 0 - wxEXPAND - - 20 - 20 - - - - - 5 - wxALL - - - onOK - - wx.ID_OK - - - - - - 5 - wxALL - - - onCancel - - wx.ID_CANCEL - - - - - - - - diff --git a/src/diffpy/pdfgui/gui/design/sgconstraindialog.wxg b/src/diffpy/pdfgui/gui/design/sgconstraindialog.wxg deleted file mode 100644 index 18dd199d..00000000 --- a/src/diffpy/pdfgui/gui/design/sgconstraindialog.wxg +++ /dev/null @@ -1,177 +0,0 @@ - - - - - - Space Group Constraints - - - wxVERTICAL - - - - 5 - wxALL|wxALIGN_CENTER_HORIZONTAL - - 1 - - - - - 0 - wxEXPAND - - wxHORIZONTAL - - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 5 - wxALL - - - onSGSelect - onSGTextEnter - - 0 - - P1 - - - - - - - - 0 - wxEXPAND - - wxHORIZONTAL - - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 5 - wxALL - - - onOXTextEnter - - 0 - - - - - 5 - wxALL - - - onOYTextEnter - - 0 - - - - - 5 - wxALL - - - onOZTextEnter - - 0 - - - - - - - 5 - wxALL - - - onPosFlag - - - 1 - - - - - 5 - wxALL - - - onTempFlag - - - 1 - - - - - 0 - wxEXPAND - - - 1 - - - - - 0 - wxEXPAND - - wxHORIZONTAL - - - 0 - wxEXPAND - - 0 - 0 - - - - - 5 - wxALL - - - onCancel - - wx.ID_CANCEL - - - - - - 5 - wxALL - - - onOk - - wx.ID_OK - - - - - - - - diff --git a/src/diffpy/pdfgui/gui/design/sgstructuredialog.wxg b/src/diffpy/pdfgui/gui/design/sgstructuredialog.wxg deleted file mode 100644 index 411cefb2..00000000 --- a/src/diffpy/pdfgui/gui/design/sgstructuredialog.wxg +++ /dev/null @@ -1,156 +0,0 @@ - - - - - - Space Group Expansion - - - wxVERTICAL - - - - 5 - wxALL - - 1 - - - - - 0 - wxEXPAND - - wxHORIZONTAL - - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 5 - wxALL - - - onSGSelect - onSGTextEnter - - 0 - - P1 - - - - - - - - 0 - wxEXPAND - - wxHORIZONTAL - - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 5 - wxALL - - - onOXTextEnter - - - 0 - - - - - 5 - wxALL - - - onOYTextEnter - - - 0 - - - - - 5 - wxALL - - - onOZTextEnter - - - 0 - - - - - - - 0 - wxEXPAND - - - 1 - - - - - 0 - wxEXPAND - - wxHORIZONTAL - - - 0 - wxEXPAND - - 0 - 0 - - - - - 5 - wxALL - - - onCancel - - wx.ID_CANCEL - - - - - - 5 - wxALL - - - onOk - - wx.ID_OK - - - - - - - - diff --git a/src/diffpy/pdfgui/gui/design/supercelldialog.wxg b/src/diffpy/pdfgui/gui/design/supercelldialog.wxg deleted file mode 100644 index fd8690c5..00000000 --- a/src/diffpy/pdfgui/gui/design/supercelldialog.wxg +++ /dev/null @@ -1,140 +0,0 @@ - - - - - - Supercell Expansion - - - wxVERTICAL - - - - 0 - wxEXPAND - - wxHORIZONTAL - - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 5 - wxALL - - 1, 10 - 1 - - - - - - - 0 - wxEXPAND - - wxHORIZONTAL - - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 5 - wxALL - - 1, 10 - 1 - - - - - - - 0 - wxEXPAND - - wxHORIZONTAL - - - 5 - wxALL|wxALIGN_CENTER_VERTICAL - - - 1 - - - - - 5 - wxALL - - 1, 10 - 1 - - - - - - - 0 - wxEXPAND - - wxHORIZONTAL - - - 5 - wxTOP|wxBOTTOM|wxEXPAND - - - 1 - - - - - - - 0 - wxEXPAND - - wxHORIZONTAL - - - 5 - wxALL - - - onCancel - - wx.ID_CANCEL - - - - - - 5 - wxALL - - - onOk - - wx.ID_OK - - - - - - - - diff --git a/src/diffpy/pdfgui/gui/design/temperatureseriespanel.wxg b/src/diffpy/pdfgui/gui/design/temperatureseriespanel.wxg deleted file mode 100644 index 623abcd8..00000000 --- a/src/diffpy/pdfgui/gui/design/temperatureseriespanel.wxg +++ /dev/null @@ -1,185 +0,0 @@ - - - - - - - - wxVERTICAL - - - 5 - wxALL|wxEXPAND - - - 10 - default - - normal - 0 - Sans - - - 1 - - - - - 0 - wxEXPAND - - wxVERTICAL - - - 0 - wxEXPAND - - wxHORIZONTAL - - - 5 - wxALL|wxEXPAND - - - onColClick - onEndLabelEdit - - - - - - - 0 - wxEXPAND - - wxVERTICAL - - - 0 - - 0 - 0 - - - - - 5 - wxALL - - - onUp - - - - - - - 5 - wxALL - - - onDown - - - - - - - 0 - - 0 - 0 - - - - - - - - - - - 5 - wxALL - - 1 - 2 - 10 - 10 - - - 0 - - - onAdd - - wx.ID_ADD - - - - - - 0 - - - onDelete - - wx.ID_DELETE - - - - - - - - 0 - wxEXPAND - - - 1 - - - - - 0 - wxEXPAND - - wxHORIZONTAL - - - 0 - wxEXPAND - - 20 - 20 - - - - - 5 - wxALL - - - onOK - - wx.ID_OK - - - - - - 5 - wxALL - - - onCancel - - wx.ID_CANCEL - - - - - - - - diff --git a/src/diffpy/pdfgui/gui/dopingseriespanel.py b/src/diffpy/pdfgui/gui/dopingseriespanel.py deleted file mode 100644 index fd60c1bf..00000000 --- a/src/diffpy/pdfgui/gui/dopingseriespanel.py +++ /dev/null @@ -1,380 +0,0 @@ -#!/usr/bin/env python -# -*- coding: ISO-8859-1 -*- -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -# generated by wxGlade 0.9.3 on Fri Jul 19 16:14:31 2019 - -import os.path -import re - -import wx - -from diffpy.pdfgui.control.pdfguimacros import makeDopingSeries -from diffpy.pdfgui.gui import tooltips -from diffpy.pdfgui.gui.pdfpanel import PDFPanel -from diffpy.pdfgui.gui.wxextensions.listctrls import AutoWidthListCtrl -from diffpy.pdfgui.gui.wxextensions.validators import ALPHA_ONLY, TextValidator - - -class DopingSeriesPanel(wx.Panel, PDFPanel): - def __init__(self, *args, **kwds): - PDFPanel.__init__(self) - # begin wxGlade: DopingSeriesPanel.__init__ - kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL - wx.Panel.__init__(self, *args, **kwds) - - sizer_1 = wx.BoxSizer(wx.VERTICAL) - - self.instructionsLabel = wx.StaticText( - self, - wx.ID_ANY, - "Select a fit from the tree on the left then add datasets and " - + "assign\ndoping elements and values below. " - + "If you have not set up a fit to be\nthe template for the series, " - + "hit cancel and rerun this macro once a\nfit has been created.", - ) - self.instructionsLabel.SetFont( - wx.Font( - 10, - wx.FONTFAMILY_DEFAULT, - wx.FONTSTYLE_NORMAL, - wx.FONTWEIGHT_NORMAL, - 0, - "Sans", - ) - ) - sizer_1.Add(self.instructionsLabel, 0, wx.ALL | wx.EXPAND, 5) - - sizer_6 = wx.BoxSizer(wx.HORIZONTAL) - sizer_1.Add(sizer_6, 0, wx.EXPAND, 0) - - self.labelBaseElement = wx.StaticText(self, wx.ID_ANY, "Base element") - sizer_6.Add(self.labelBaseElement, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) - - self.textCtrlBaseElement = wx.TextCtrl(self, wx.ID_ANY, "") - sizer_6.Add(self.textCtrlBaseElement, 0, wx.ALL, 5) - - self.labelDopant = wx.StaticText(self, wx.ID_ANY, "Dopant") - sizer_6.Add(self.labelDopant, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) - - self.textCtrlDopant = wx.TextCtrl(self, wx.ID_ANY, "") - sizer_6.Add(self.textCtrlDopant, 0, wx.ALL, 5) - - sizer_2 = wx.BoxSizer(wx.VERTICAL) - sizer_1.Add(sizer_2, 1, wx.EXPAND, 0) - - sizer_4 = wx.BoxSizer(wx.HORIZONTAL) - sizer_2.Add(sizer_4, 1, wx.EXPAND, 0) - - self.listCtrlFiles = AutoWidthListCtrl( - self, wx.ID_ANY, style=wx.BORDER_SUNKEN | wx.LC_EDIT_LABELS | wx.LC_REPORT - ) - sizer_4.Add(self.listCtrlFiles, 1, wx.ALL | wx.EXPAND, 5) - - sizer_5 = wx.BoxSizer(wx.VERTICAL) - sizer_4.Add(sizer_5, 0, wx.EXPAND, 0) - - sizer_5.Add((0, 0), 1, 0, 0) - - self.buttonUp = wx.BitmapButton(self, wx.ID_ANY, wx.NullBitmap) - self.buttonUp.SetSize(self.buttonUp.GetBestSize()) - sizer_5.Add(self.buttonUp, 0, wx.ALL, 5) - - self.buttonDown = wx.BitmapButton(self, wx.ID_ANY, wx.NullBitmap) - self.buttonDown.SetSize(self.buttonDown.GetBestSize()) - sizer_5.Add(self.buttonDown, 0, wx.ALL, 5) - - sizer_5.Add((0, 0), 1, 0, 0) - - grid_sizer_1 = wx.GridSizer(1, 2, 10, 10) - sizer_1.Add(grid_sizer_1, 0, wx.ALL, 5) - - self.buttonAdd = wx.Button(self, wx.ID_ADD, "Add") - grid_sizer_1.Add(self.buttonAdd, 0, 0, 0) - - self.buttonDelete = wx.Button(self, wx.ID_DELETE, "Delete") - grid_sizer_1.Add(self.buttonDelete, 0, 0, 0) - - self.static_line_1 = wx.StaticLine(self, wx.ID_ANY) - sizer_1.Add(self.static_line_1, 0, wx.EXPAND, 0) - - sizer_3 = wx.BoxSizer(wx.HORIZONTAL) - sizer_1.Add(sizer_3, 0, wx.EXPAND, 0) - - sizer_3.Add((20, 20), 1, wx.EXPAND, 0) - - self.goButton = wx.Button(self, wx.ID_OK, "OK") - sizer_3.Add(self.goButton, 0, wx.ALL, 5) - - self.cancelButton = wx.Button(self, wx.ID_CANCEL, "Cancel") - sizer_3.Add(self.cancelButton, 0, wx.ALL, 5) - - self.SetSizer(sizer_1) - sizer_1.Fit(self) - - self.Layout() - - self.Bind(wx.EVT_LIST_COL_CLICK, self.onColClick, self.listCtrlFiles) - self.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.onEndLabelEdit, self.listCtrlFiles) - self.Bind(wx.EVT_BUTTON, self.onUp, self.buttonUp) - self.Bind(wx.EVT_BUTTON, self.onDown, self.buttonDown) - self.Bind(wx.EVT_BUTTON, self.onAdd, self.buttonAdd) - self.Bind(wx.EVT_BUTTON, self.onDelete, self.buttonDelete) - self.Bind(wx.EVT_BUTTON, self.onOK, self.goButton) - self.Bind(wx.EVT_BUTTON, self.onCancel, self.cancelButton) - # end wxGlade - self.__customProperties() - - def __customProperties(self): - """Set the custom properties.""" - self.fit = None - self.reverse = False # Reverse the sort? - self.fullpath = "" - self.datasets = [] # Contains (doping, filename) tuples - # doping comes first for easy sorting - - self.listCtrlFiles.InsertColumn(0, "Doping") - self.listCtrlFiles.InsertColumn(1, "Data Set") - self.listCtrlFiles.SetColumnWidth(0, -2) - - # Set the validators - self.textCtrlBaseElement.SetValidator(TextValidator(ALPHA_ONLY)) - self.textCtrlDopant.SetValidator(TextValidator(ALPHA_ONLY)) - - # Define tooltips. - self.setToolTips(tooltips.dopingseriespanel) - return - - def onColClick(self, event): # wxGlade: DopingSeriesPanel. - """Sort by doping.""" - self.datasets.sort() - if self.reverse: - self.datasets.reverse() - self.reverse = not self.reverse - self.fillList() - return - - def onEndLabelEdit(self, event): # wxGlade: DopingSeriesPanel. - """Update the doping in the datasets.""" - index = event.GetIndex() - text = event.GetText() - doping = 0.0 - try: - doping = float(text) - except ValueError: - event.Veto() - return - if doping < 0 or doping > 1: - event.Veto() - return - # update the internal information - self.datasets[index][0] = doping - self.reverse = False - return - - def onUp(self, event): # wxGlade: DopingSeriesPanel. - """Move an item in the list up.""" - index = self.listCtrlFiles.GetFirstSelected() - if index > 0: - temp = self.datasets[index] - self.datasets[index] = self.datasets[index - 1] - self.datasets[index - 1] = temp - self.fillList() - self.listCtrlFiles.Select(index - 1) - return - - def onDown(self, event): # wxGlade: DopingSeriesPanel. - """Move an item in the list down.""" - index = self.listCtrlFiles.GetFirstSelected() - if index > -1 and index != len(self.datasets) - 1: - temp = self.datasets[index] - self.datasets[index] = self.datasets[index + 1] - self.datasets[index + 1] = temp - self.fillList() - self.listCtrlFiles.Select(index + 1) - return - - def onAdd(self, event): # wxGlade: DopingSeriesPanel. - """Append files to the list.""" - dir, filename = os.path.split(self.fullpath) - if not dir: - dir = self.mainFrame.workpath - - matchstring = ( - "PDF data files (*.gr)|*.gr|PDF fit files (*.fgr)|*.fgr|PDF fit files (*.fit)|" - "*.fit|PDF calculation files (*.cgr)|*.cgr|PDF calculation files (*.calc)|*.calc|" - "All Files|*" - ) - d = wx.FileDialog( - None, - "Choose files", - dir, - "", - matchstring, - wx.FD_OPEN | wx.FD_FILE_MUST_EXIST | wx.FD_MULTIPLE, - ) - paths = [] - if d.ShowModal() == wx.ID_OK: - paths = d.GetPaths() - d.Destroy() - - # Assign the doping. Default to 0.0 - newdatasets = [] - for path in paths: - self.fullpath = path - self.mainFrame.workpath = os.path.dirname(self.fullpath) - - # Look for the doping in the filename - doping = 0.0 - rx = {"f": r"(?:\d+(?:\.\d*)?|\d*\.\d+)"} - # Search for x123, X123, doping123, Doping123. - # Is there a better regexp? Probably... - regexp = r"(?:X|x|Doping|doping)(%(f)s)" % rx - res = re.search(regexp, os.path.basename(path)) - if res: - doping = float(res.groups()[0]) - else: - # Look in the file - infile = open(path, "r") - datastring = infile.read() - infile.close() - # Look for it first in the file - res = re.search(r"^#+ start data\s*(?:#.*\s+)*", datastring, re.M) - # start_data is position where the first data line starts - if res: - start_data = res.end() - else: - res = re.search(r"^[^#]", datastring, re.M) - if res: - start_data = res.start() - else: - start_data = 0 - header = datastring[:start_data] - # parse header to get doping - regexp = r"\b(?:x|doping)\ *=\ *(%(f)s)\b" % rx - res = re.search(regexp, header) - if res: - doping = float(res.groups()[0]) - # Add the new path - if doping < 0: - doping = 0.0 - newdatasets.append([doping, path]) - - self.datasets.extend(newdatasets) - self.fillList() - return - - def onDelete(self, event): # wxGlade: DopingSeriesPanel. - """Delete selected files from the list.""" - idxlist = [] - item = self.listCtrlFiles.GetFirstSelected() - while item != -1: - idxlist.append(item) - item = self.listCtrlFiles.GetNextSelected(item) - - idxlist.reverse() - for item in idxlist: - del self.datasets[item] - self.fillList() - return - - def onOK(self, event): # wxGlade: DopingSeriesPanel. - """Let's go!""" - dvals = [tp[0] for tp in self.datasets] - paths = [tp[1] for tp in self.datasets] - base = self.textCtrlBaseElement.GetValue() - dopant = self.textCtrlDopant.GetValue() - # Value checks will take place in makeDopingSeries - org = makeDopingSeries(self.mainFrame.control, self.fit, base, dopant, paths, dvals) - self.treeCtrlMain.ExtendProjectTree(org, clear=False) - self.mainFrame.needsSave() - self.onCancel(event) - return - - def onCancel(self, event): # wxGlade: DopingSeriesPanel. - """Let's go, but not actually do anything.""" - self.mainFrame.setMode("fitting") - self.treeCtrlMain.UnselectAll() - self.mainFrame.switchRightPanel("blank") - return - - # Utility functions - def checkConfiguration(self): - """Verify that the dopant and base are elements. - - More detailed checking is done in the control method. - """ - from diffpy.pdffit2 import is_element - from diffpy.pdfgui.control.controlerrors import ControlValueError - - base = self.textCtrlBaseElement.GetValue() - dopant = self.textCtrlDopant.GetValue() - # Make sure that the base and dopant are actual elements - base = base.title() - dopant = dopant.title() - if not is_element(base): - raise ControlValueError("'%s' is not an element!" % base) - if not is_element(dopant): - raise ControlValueError("'%s' is not an element!" % dopant) - return - - def fillList(self): - """Fill the list with the datasets.""" - self.listCtrlFiles.DeleteAllItems() - names = [pair[1] for pair in self.datasets] - cp = os.path.commonprefix(names) - # We want to break at the last path/separator in the common prefix - idx = cp.rfind(os.path.sep) - if idx == -1: - idx = len(cp) - for doping, filename in self.datasets: - shortname = "..." + filename[idx:] - # index = self.listCtrlFiles.InsertItem(sys.maxsize, str(doping)) #doesn't work for windows - index = self.listCtrlFiles.InsertItem(100000, str(doping)) # doesn't work for windows - self.listCtrlFiles.SetItem(index, 1, shortname) - return - - # Needed by mainframe - def treeSelectionUpdate(self, node): - """Set the current fit when the tree selection changes.""" - nodetype = self.treeCtrlMain.GetNodeType(node) - if nodetype == "fit": - self.fit = self.treeCtrlMain.GetControlData(node) - self.refresh() - return - - # Required by PDFPanel - def refresh(self): - """Block out OK button if there is no fit. - - This also blocks OK if the fit has no datasets or structures. - """ - # We can't rely on Veto to block unwanted tree selections on windows. - # So, we have to check for errors here. - node = None - nodetype = None - selections = self.treeCtrlMain.GetSelections() - if selections: - node = selections[0] - nodetype = self.treeCtrlMain.GetNodeType(node) - - if node and nodetype == "fit" and self.fit and self.fit.hasDataSets() and self.fit.hasStructures(): - self.goButton.Enable() - else: - self.goButton.Enable(False) - return - - -# end of class DopingSeriesPanel diff --git a/src/diffpy/pdfgui/gui/errorreportdialog.py b/src/diffpy/pdfgui/gui/errorreportdialog.py deleted file mode 100644 index f4de87aa..00000000 --- a/src/diffpy/pdfgui/gui/errorreportdialog.py +++ /dev/null @@ -1,246 +0,0 @@ -#!/usr/bin/env python -# -*- coding: UTF-8 -*- -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Dmitriy Bryndin -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -# generated by wxGlade 0.9.3 on Fri Jul 19 16:01:37 2019 - -import re -import webbrowser - -# -# "Bug report" Dialog -# -import wx -import wx.html - -# Constants ------------------------------------------------------------------ - -ISSUESTRACKER = "https://github.com/diffpy/diffpy.pdfgui/issues" -USERSMAILINGLIST = "https://groups.google.com/d/forum/diffpy-users" -_WEBSEARCHURL = "https://www.google.com/search?q={query}" - -_MSG_TRAILER = """ -

-You can view current bug reports and feature requests at -{issues}. -

-Discuss PDFgui and learn about new developments and features at -{mlist}. -

-""".format( - issues=ISSUESTRACKER, mlist=USERSMAILINGLIST -) - -_MSG_FEATURE_REQUEST = ( - """ -

-Share you thoughts about PDFgui! -

-""" - + _MSG_TRAILER -) - -_MSG_ERROR_REPORT = ( - """ -

-PDFgui has encountered a problem. We are sorry for the inconvenience. -

-""" - + _MSG_TRAILER -) - -# ---------------------------------------------------------------------------- - - -class ErrorReportDialog(wx.Dialog): - def __init__(self, *args, **kwds): - # begin wxGlade: ErrorReportDialog.__init__ - kwds["style"] = ( - kwds.get("style", 0) | wx.DEFAULT_DIALOG_STYLE | wx.MAXIMIZE_BOX | wx.MINIMIZE_BOX | wx.RESIZE_BORDER - ) - wx.Dialog.__init__(self, *args, **kwds) - self.SetSize((540, 600)) - self.label_header = wx.html.HtmlWindow(self, wx.ID_ANY) - self.label_log = wx.StaticText(self, wx.ID_ANY, "Error Log:") - self.text_ctrl_log = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_MULTILINE | wx.TE_READONLY) - self.static_line_1 = wx.StaticLine(self, wx.ID_ANY) - self.button_google = wx.Button(self, wx.ID_ANY, "Google This Error") - self.button_copyErrorLog = wx.Button(self, wx.ID_ANY, "Copy Error Log") - self.button_close = wx.Button(self, wx.ID_CANCEL, "Close") - - self.__set_properties() - self.__do_layout() - - self.Bind(wx.EVT_BUTTON, self.onGoogle, self.button_google) - self.Bind(wx.EVT_BUTTON, self.onCopyErrorLog, self.button_copyErrorLog) - # end wxGlade - self.__customProperties() - return - - def __set_properties(self): - # begin wxGlade: ErrorReportDialog.__set_properties - self.SetTitle("Problem Report for PDFgui") - self.SetSize((540, 600)) - # end wxGlade - - def __do_layout(self): - # begin wxGlade: ErrorReportDialog.__do_layout - sizer_main = wx.BoxSizer(wx.VERTICAL) - sizer_buttons = wx.BoxSizer(wx.HORIZONTAL) - sizer_log = wx.BoxSizer(wx.VERTICAL) - sizer_label = wx.BoxSizer(wx.HORIZONTAL) - sizer_label.Add(self.label_header, 1, wx.EXPAND, 5) - sizer_main.Add(sizer_label, 1, wx.ALL | wx.EXPAND, 5) - sizer_log.Add(self.label_log, 0, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, 5) - sizer_log.Add(self.text_ctrl_log, 1, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) - sizer_main.Add(sizer_log, 3, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, 10) - sizer_main.Add(self.static_line_1, 0, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, 5) - sizer_buttons.Add((20, 20), 1, 0, 0) - sizer_buttons.Add(self.button_google, 0, wx.ALL, 5) - sizer_buttons.Add(self.button_copyErrorLog, 0, wx.ALL, 5) - sizer_buttons.Add(self.button_close, 0, wx.ALL, 5) - sizer_main.Add(sizer_buttons, 0, wx.EXPAND, 0) - self.SetSizer(sizer_main) - self.Layout() - # end wxGlade - - def __customProperties(self): - """Set custom properties.""" - # Events - self.errorReport = True - self.label_header.Bind(wx.html.EVT_HTML_LINK_CLICKED, self.onURL) - return - - def ShowModal(self): - # there are 2 modes: error report and feature request - if self.text_ctrl_log.GetValue().strip() == "": - self.SetTitle("Feature Request / Bug Report") - self.label_header.SetPage(_MSG_FEATURE_REQUEST) - self.label_header.SetBackgroundColour("") - self.label_log.Hide() - self.text_ctrl_log.Hide() - self.button_google.Hide() - self.button_copyErrorLog.Hide() - self.SetSize((540, 200)) - self.errorReport = False - else: - self.SetTitle("Problem Report for PDFgui") - self.label_header.SetPage(_MSG_ERROR_REPORT) - self.label_header.SetBackgroundColour("") - self.text_ctrl_log.Show() - self.errorReport = True - - wx.Dialog.ShowModal(self) - - def onGoogle(self, event): # wxGlade: ErrorReportDialog. - """Handle the "Google This Error" button. - - Search for path-independent module and function names and for - error message extracted from exception traceback. - """ - from urllib.parse import quote_plus - - traceback = self.text_ctrl_log.GetValue() - terms = _extractSearchTerms(traceback) - str_to_search = " ".join(terms) if terms else traceback.strip() - query = quote_plus(str_to_search) - url = _WEBSEARCHURL.format(query=query) - webbrowser.open(url) - event.Skip() - return - - def onCopyErrorLog(self, event): # wxGlade: ErrorReportDialog. - # copy the traceback enclosed in GitHub block quotations so it is easier to paste into GitHub issue. - traceback = self.text_ctrl_log.GetValue() - clipdata = wx.TextDataObject() - clipdata.SetText("```\n" + traceback.strip() + "\n```\n") - wx.TheClipboard.Open() - wx.TheClipboard.SetData(clipdata) - wx.TheClipboard.Close() - event.Skip() - return - - def onURL(self, event): # wxGlade: ErrorReportDialog. - # click on the URL link in dialog, it will open the URL in web browser. - link = event.GetLinkInfo() - webbrowser.open(link.GetHref()) - - -# end of class ErrorReportDialog - -# Helper functions ----------------------------------------------------------- - - -def _extractSearchTerms(tbtext): - """Extract search words from a Python exception traceback. - - Parameters - ---------- - tbtext : str - Python exception traceback converted to a string. - - Returns - ------- - searchterms : list - List of search terms to be used for Google search. - """ - # extract module names and function names from a traceback - modfncpairs = re.findall(r"File.*?([^/\\]*[.]py).*?, line \d+, in (\w+)", tbtext, re.MULTILINE) - modfnc = list(sum(modfncpairs, ())) - # find the last line starting with "SomeError: ...". - lasterr = re.findall(r"^\w+Error:.*", tbtext, re.MULTILINE) - rv = modfnc + lasterr[-1:] - return rv - - -# testing code ############################################################ - -_EXAMPLE_TRACEBACK = r""" -Traceback (most recent call last): - File "C:\DiffPy\Python25\lib\site-packages\diffpy.pdfgui-1.0_r3067_20090410-py2.5.egg\ -diffpy\pdfgui\gui\errorwrapper.py", line 60, in _f - return func(*args, **kwargs) - File "C:\DiffPy\Python25\lib\site-packages\diffpy.pdfgui-1.0_r3067_20090410-py2.5.egg\ -diffpy\pdfgui\gui\mainframe.py", line 2176, in onSave - self.control.save(self.fullpath) - File "C:\DiffPy\Python25\lib\site-packages\diffpy.pdfgui-1.0_r3067_20090410-py2.5.egg\ -diffpy\pdfgui\control\pdfguicontrol.py", line 507, in save - self.projfile = projfile.encode('ascii') -UnicodeDecodeError: 'ascii' codec can't decode byte 0xb0 in position 115: ordinal not in range(128) -""".strip() - - -class MyApp(wx.App): - def OnInit(self): - self.dialog = ErrorReportDialog(None, -1, "") - self.SetTopWindow(self.dialog) - self.test() - self.dialog.ShowModal() - self.dialog.Destroy() - return True - - def test(self): - """Testing code goes here.""" - self.dialog.text_ctrl_log.SetValue(_EXAMPLE_TRACEBACK) - return - - -# end of class MyApp - -if __name__ == "__main__": - app = MyApp(0) - app.MainLoop() - -# end of testing code ##################################################### diff --git a/src/diffpy/pdfgui/gui/errorreportdialog_control_fix.py b/src/diffpy/pdfgui/gui/errorreportdialog_control_fix.py deleted file mode 100644 index 38050c98..00000000 --- a/src/diffpy/pdfgui/gui/errorreportdialog_control_fix.py +++ /dev/null @@ -1,183 +0,0 @@ -#!/usr/bin/env python -# -*- coding: UTF-8 -*- -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Dmitriy Bryndin -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -# generated by wxGlade 0.9.3 on Fri Jul 19 16:01:37 2019 - -import re - -# -# "Bug report" Dialog -# -import wx -import wx.html - -from .errorreportdialog import ErrorReportDialog - -# Constants ------------------------------------------------------------------ - -ISSUESTRACKER = "https://github.com/diffpy/diffpy.pdfgui/issues" -USERSMAILINGLIST = "https://groups.google.com/d/forum/diffpy-users" -_WEBSEARCHURL = "https://www.google.com/search?q={query}" - - -_MSG_ERROR_REPORT = """ -

-Currently the control-select is not supported in Python3 PDFgui. We will fix this issue in a future version. -Please use shift-select for multiple cells instead. -

-""" - -# ---------------------------------------------------------------------------- - - -class ErrorReportDialogControlFix(wx.Dialog): - def __init__(self, *args, **kwds): - # begin wxGlade: ErrorReportDialog.__init__ - kwds["style"] = ( - kwds.get("style", 0) | wx.DEFAULT_DIALOG_STYLE | wx.MAXIMIZE_BOX | wx.MINIMIZE_BOX | wx.RESIZE_BORDER - ) - wx.Dialog.__init__(self, *args, **kwds) - self.SetSize((540, 200)) - self.label_header = wx.html.HtmlWindow(self, wx.ID_ANY) - # self.label_log = wx.StaticText(self, wx.ID_ANY, "Error Log:") - # self.text_ctrl_log = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_MULTILINE | wx.TE_READONLY) - # self.static_line_1 = wx.StaticLine(self, wx.ID_ANY) - # self.button_google = wx.Button(self, wx.ID_ANY, "Google This Error") - # self.button_copyErrorLog = wx.Button(self, wx.ID_ANY, "Copy Error Log") - self.button_close = wx.Button(self, wx.ID_CANCEL, "Close") - - self.__set_properties() - self.__do_layout() - - # self.Bind(wx.EVT_BUTTON, self.onGoogle, self.button_google) - # self.Bind(wx.EVT_BUTTON, self.onCopyErrorLog, self.button_copyErrorLog) - # end wxGlade - self.__customProperties() - return - - def __set_properties(self): - # begin wxGlade: ErrorReportDialog.__set_properties - self.SetTitle("Problem Report for PDFgui") - self.SetSize((540, 200)) - # end wxGlade - - def __do_layout(self): - # begin wxGlade: ErrorReportDialog.__do_layout - sizer_main = wx.BoxSizer(wx.VERTICAL) - sizer_buttons = wx.BoxSizer(wx.HORIZONTAL) - # sizer_log = wx.BoxSizer(wx.VERTICAL) - sizer_label = wx.BoxSizer(wx.HORIZONTAL) - sizer_label.Add(self.label_header, 1, wx.EXPAND, 5) - sizer_main.Add(sizer_label, 1, wx.ALL | wx.EXPAND, 5) - # sizer_log.Add(self.label_log, 0, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, 5) - # sizer_log.Add(self.text_ctrl_log, 1, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) - # sizer_main.Add(sizer_log, 3, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, 10) - # sizer_main.Add(self.static_line_1, 0, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, 5) - # sizer_buttons.Add((20, 20), 1, 0, 0) - # sizer_buttons.Add(self.button_google, 0, wx.ALL, 5) - # sizer_buttons.Add(self.button_copyErrorLog, 0, wx.ALL, 5) - sizer_buttons.Add(self.button_close, 0, wx.ALL, 5) - sizer_main.Add(sizer_buttons, 0, wx.EXPAND, 0) - self.SetSizer(sizer_main) - self.Layout() - # end wxGlade - - def __customProperties(self): - """Set custom properties.""" - # Events - self.errorReport = True - # self.label_header.Bind(wx.html.EVT_HTML_LINK_CLICKED, self.onURL) - return - - def ShowModal(self): - # there are 2 modes: error report and feature request - - self.SetTitle("Problem Report for PDFgui") - self.label_header.SetPage(_MSG_ERROR_REPORT) - self.label_header.SetBackgroundColour("") - # self.text_ctrl_log.Show() - self.errorReport = True - - wx.Dialog.ShowModal(self) - - -# end of class ErrorReportDialog - -# Helper functions ----------------------------------------------------------- - - -def _extractSearchTerms(tbtext): - """Extract search words from a Python exception traceback. - - Parameters - ---------- - tbtext : str - Python exception traceback converted to a string. - - Returns - ------- - searchterms : list - List of search terms to be used for Google search. - """ - # extract module names and function names from a traceback - modfncpairs = re.findall(r"File.*?([^/\\]*[.]py).*?, line \d+, in (\w+)", tbtext, re.MULTILINE) - modfnc = list(sum(modfncpairs, ())) - # find the last line starting with "SomeError: ...". - lasterr = re.findall(r"^\w+Error:.*", tbtext, re.MULTILINE) - rv = modfnc + lasterr[-1:] - return rv - - -# testing code ############################################################ - -_EXAMPLE_TRACEBACK = r""" -Traceback (most recent call last): - File "C:\DiffPy\Python25\lib\site-packages\diffpy.pdfgui-1.0_r3067_20090410-py2.5.egg\ -\diffpy\pdfgui\gui\errorwrapper.py", line 60, in _f - return func(*args, **kwargs) - File "C:\DiffPy\Python25\lib\site-packages\diffpy.pdfgui-1.0_r3067_20090410-py2.5.egg\ -\diffpy\pdfgui\gui\mainframe.py", line 2176, in onSave - self.control.save(self.fullpath) - File "C:\DiffPy\Python25\lib\site-packages\diffpy.pdfgui-1.0_r3067_20090410-py2.5.egg\ -\diffpy\pdfgui\control\pdfguicontrol.py", line 507, in save - self.projfile = projfile.encode('ascii') -UnicodeDecodeError: 'ascii' codec can't decode byte 0xb0 in position 115: \ -ordinal not in range(128) -""".strip() - - -class MyApp(wx.App): - def OnInit(self): - self.dialog = ErrorReportDialog(None, -1, "") - self.SetTopWindow(self.dialog) - self.test() - self.dialog.ShowModal() - self.dialog.Destroy() - return True - - def test(self): - """Testing code goes here.""" - # self.dialog.text_ctrl_log.SetValue(_EXAMPLE_TRACEBACK) - return - - -# end of class MyApp - -if __name__ == "__main__": - app = MyApp(0) - app.MainLoop() - -# end of testing code ##################################################### diff --git a/src/diffpy/pdfgui/gui/errorwrapper.py b/src/diffpy/pdfgui/gui/errorwrapper.py deleted file mode 100644 index 78e0f1cb..00000000 --- a/src/diffpy/pdfgui/gui/errorwrapper.py +++ /dev/null @@ -1,133 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2008 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""This module contains a function wrapper and an object wrapper that -catch control errors and shows them in an error report dialog. - -This is used by PDFPanel and MainFrame. -""" - -import sys -import traceback - -import wx - -from diffpy.pdfgui.control.controlerrors import ControlError, TempControlSelectError -from diffpy.pdfgui.gui import pdfguiglobals -from diffpy.pdfgui.gui.errorreportdialog import ErrorReportDialog -from diffpy.pdfgui.gui.errorreportdialog_control_fix import ErrorReportDialogControlFix - -# these methods will not be wrapped in catchFunctionErrors -_EXCLUDED_METHODS = dict.fromkeys(dir(wx.Panel) + dir(wx.Dialog)) - - -def catchFunctionErrors(obj, funcName): - """Wrap a function so its errors get transferred to a dialog. - - obj -- Object containing the function. It is assumed that the - object has an attribute named 'mainFrame', which is a - reference to the MainFrame instance, which contains - information about how and when to display errors. - funcName -- Name of a function to wrap. - - Returns the wrapped function - """ - func = getattr(obj, funcName) - - # do not catch anything when requested in pdfguigloabals.dbopts - if pdfguiglobals.dbopts.noerrordialog: - return func - - # default return value when exception is skipped: - rvpass = wx.ID_CANCEL - - # otherwise wrap func within exceptions handler - def _f(*args, **kwargs): - - hasmf = hasattr(obj, "mainFrame") and obj.mainFrame is not None - - try: - return func(*args, **kwargs) - - # to be deleted. temporarily used for show the select-control error. - except TempControlSelectError: - dlg = ErrorReportDialogControlFix(obj.mainFrame) - dlg.ShowModal() - dlg.Destroy() - - # Display ControlError error messages in a dialog. - except ControlError as e: - if not hasmf: - raise - message = str(e) - obj.mainFrame.showMessage(message, "Oops!") - return rvpass - - # Everything else - except Exception: - if pdfguiglobals.dbopts.pythondebugger: - import pdb - - tb = sys.exc_info()[2] - pdb.post_mortem(tb) - return rvpass - if not hasmf: - raise - msglines = traceback.format_exception(*sys.exc_info()) - message = "".join(msglines) - if obj.mainFrame.quitting: - sys.stderr.write(message) - sys.stderr.write("\n") - else: - dlg = ErrorReportDialog(obj.mainFrame) - dlg.text_ctrl_log.SetValue(message) - dlg.ShowModal() - dlg.Destroy() - return rvpass - - # we should never get here - pass - - return _f - - -def catchObjectErrors(obj, exclude=None): - """Wrap all functions of an object so that the exceptions are - caught. - - obj -- Object containing the function. It is assumed that the object has an - attribute named 'mainFrame', which is a reference to the MainFrame - instance, which contains information about how and when to display - errors. - exclude -- An iterable of additional function names to exclude. These are - excluded in addition to names in _EXCLUDED_METHODS defined above. - - All functions starting with '_' are excluded. - """ - if exclude: - extra_excludes = dict.fromkeys(exclude) - else: - extra_excludes = {} - - funcNames = [ - item - for item in dir(obj) - if not item.startswith("_") and item not in _EXCLUDED_METHODS and item not in extra_excludes - ] - - for name in funcNames: - if hasattr(getattr(obj, name), "__call__"): - setattr(obj, name, catchFunctionErrors(obj, name)) - - return diff --git a/src/diffpy/pdfgui/gui/extendedplotframe.py b/src/diffpy/pdfgui/gui/extendedplotframe.py deleted file mode 100644 index 9e41fd5e..00000000 --- a/src/diffpy/pdfgui/gui/extendedplotframe.py +++ /dev/null @@ -1,427 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Jiwu Liu, Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""The module contains extensions for GUI plot frame.""" - -import os.path - -import matplotlib -import wx -from matplotlib.artist import setp -from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas -from matplotlib.backends.backend_wxagg import NavigationToolbar2WxAgg as NavToolbar -from matplotlib.figure import Figure -from matplotlib.font_manager import FontProperties - -from diffpy.pdfgui.gui.pdfguiglobals import iconpath - -matplotlib.use("WXAgg") - -DATA_SAVE_ID = wx.NewIdRef() - - -class ExtendedToolbar(NavToolbar): - """An extended plotting toolbar with a save and close button.""" - - # override NavToolbar.toolitems to exclude the subplots tool. - toolitems = tuple(el for el in NavToolbar.toolitems if el[0] != "Subplots") - - def __init__(self, canvas): - NavToolbar.__init__(self, canvas) - # Load customized icon image - save_icon_fp = iconpath("exportplotdata.png") - save_icon = wx.Bitmap(save_icon_fp) - # Add new buttons - self.AddTool(DATA_SAVE_ID, "Export data", save_icon, shortHelp="Export plot data to file") - return - - -# End class ExtendedToolbar - - -class ExtendedPlotFrame(wx.Frame): - """An extended plotting frame with a save and close button. - - The class has a matplotlib.figure.Figure data member named 'figure'. - It also has a matplotlib.axes.Axes data member named 'axes'. The - normal matplotlib plot manipulations can be performed with these two - data members. See the matplotlib API at: - http://matplotlib.sourceforge.net/classdocs.html - """ - - # keyboard shortcut(s) for closing plot window - close_keys = set(matplotlib.rcParamsDefault["keymap.quit"]) - - def __init__(self, parent=None, *args, **kwargs): - """Initialize the CanvasFrame. - - The frame uses ExtendedToolbar as a toolbar, which has a save data - button and a close button on the toolbar in addition to the normal - buttons. - - args -- argument list - kwargs -- keyword argument list - """ - wx.Frame.__init__(self, parent, -1, "ExtendedPlotFrame", size=(550, 350)) - - # figsize in inches - self.figure = Figure(figsize=(0.5, 0.5), dpi=72) - - # we will manage view scale ourselves - self.subplot = self.figure.add_subplot(111, autoscale_on=False) - self.canvas = FigureCanvas(self, -1, self.figure) - - # Introspection data - self.dirname = "" - self.filename = "" - - self.sizer = wx.BoxSizer(wx.VERTICAL) - self.sizer.Add(self.canvas, 1, wx.TOP | wx.LEFT | wx.EXPAND) - self.toolbar = ExtendedToolbar(self.canvas) - self.toolbar.Realize() - - self.coordLabel = wx.StaticText(self, -1, style=wx.ALIGN_RIGHT | wx.NO_BORDER) - # Place coordinates textbox in a horizontal sizer next to the toolbar. - barSizer = wx.BoxSizer(wx.HORIZONTAL) - self.sizer.Add(barSizer, 0, wx.EXPAND | wx.CENTER) - barSizer.Add(self.toolbar, 0, wx.CENTER) - barSizer.Add((20, 10), 0) - barSizer.Add(self.coordLabel, 0, wx.CENTER) - - # update the axes menu on the toolbar - self.toolbar.update() - self.SetSizer(self.sizer) - self.Fit() - self.SetSize((600, 400)) - # Use toolbar's color for coordinates label background. - self.SetBackgroundColour(self.toolbar.GetBackgroundColour()) - # FIXME -- toolbar background color does not match on Mac OS X. - # Use GIMP - picked color until a proper way is found. - if wx.Platform == "__WXMAC__": - self.SetBackgroundColour((200, 200, 200, 255)) - self.canvas.mpl_connect("motion_notify_event", self.UpdateStatusBar) - self.canvas.mpl_connect("key_press_event", self.mplKeyPress) - self.Bind(wx.EVT_PAINT, self.OnPaint) - self.Bind(wx.EVT_TOOL, self.savePlotData, id=DATA_SAVE_ID) - self.Bind(wx.EVT_CLOSE, self.onClose) - - self.datalims = {} - - # CUSTOM METHODS ######################################################## - - # EVENT CODE ############################################################# - def onClose(self, evt): - """Close the frame.""" - if hasattr(self, "plotter"): - self.plotter.onWindowClose() - self.Destroy() - return - - def OnPaint(self, event): - self.canvas.draw() - event.Skip() - - def savePlotData(self, evt): - """Save the data in the plot in columns.""" - d = wx.FileDialog( - None, - "Save as...", - self.dirname, - self.filename, - "(*.dat)|*.dat|(*.txt)|*.txt|(*)|*", - wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT, - ) - if d.ShowModal() == wx.ID_OK: - fullname = d.GetPath() - self.dirname = os.path.dirname(fullname) - self.filename = os.path.basename(fullname) - self.plotter.export(fullname) - - d.Destroy() - return - - def UpdateStatusBar(self, event): - if event.inaxes: - x, y = event.xdata, event.ydata - xystr = "x = %g, y = %g" % (x, y) - self.coordLabel.SetLabel(xystr) - - def mplKeyPress(self, event): - """Process keyboard input in matplotlib plot window. - - This implements a standard close-window shortcut key. - """ - if event.key in self.close_keys: - self.Close() - return - - def replot(self): - """Officially call function in matplotlib to do drawing.""" - self.canvas.draw() - - def insertCurve(self, xData, yData, style): - """Insert a new curve to the plot. - - xData, yData -- x, y data to used for the curve - style -- the way curve should be plotted - return: internal reference to the newly added curve - """ - _, properties = self.__translateStyles(style) - curveRef = self.subplot.plot(xData, yData, **properties)[0] - if "legend" in style: - self.subplot.legend(**legendBoxProperties()) - try: - self.datalims[curveRef] = (min(xData), max(xData), min(yData), max(yData)) - except ValueError: - self.datalims[curveRef] = (0, 0, 0, 0) - self.__updateViewLimits() - return curveRef - - def updateData(self, curveRef, xData, yData): - """Update data for a existing curve. - - curveRef -- internal reference to a curve - xData, yData -- x, y data to used for the curve - """ - curveRef.set_data(xData, yData) - try: - self.datalims[curveRef] = (min(xData), max(xData), min(yData), max(yData)) - except ValueError: - self.datalims[curveRef] = (0, 0, 0, 0) - self.__updateViewLimits() - - def changeStyle(self, curveRef, style): - """Change curve style. - - curveRef -- internal reference to curves - style -- style dictionary - """ - stylestr, properties = self.__translateStyles(style) - # FIXME: we discard stylestr because it seems there's no way - # it can be changed afterwards. - setp((curveRef,), **properties) - self.subplot.legend(**legendBoxProperties()) - - def removeCurve(self, curveRef): - """Remove curve from plot. - - curveRef -- internal reference to curves - """ - del self.datalims[curveRef] - self.figure.gca().lines.remove(curveRef) - self.subplot.legend(**legendBoxProperties()) - self.__updateViewLimits() - - def __updateViewLimits(self): - """Adjust the subplot range in order to show all curves - correctly.""" - # NOTE: - # we need to adjust view limits by ourselves because Matplotlib can't - # set the legend nicely when there are multiple curves in the plot. - # Beside, autoscale can not automatically respond to data change. - if len(self.datalims) == 0: - return - # ignore previous range - self.subplot.dataLim.ignore(True) - bounds = list(self.datalims.values()) - xmin = min([b[0] for b in bounds]) - xmax = max([b[1] for b in bounds]) - ymin = min([b[2] for b in bounds]) - ymax = max([b[3] for b in bounds]) - - # If multiple curve, we need calculate new x limits because legend box - # take up some space - # NOTE: 3 and 0.33 is our best estimation for a good view - # 2007-10-25 PJ: it is better to use full plot area - # if len(self.datalims) > 3: - # # leave extra room for legend by shift the upper bound for x axis - # xmax += (xmax-xmin)*0.33 - if xmax > xmin: - self.subplot.set_xlim(xmin, xmax) - if ymax > ymin: - self.subplot.set_ylim(ymin, ymax) - - def __translateStyles(self, style): - """Private function to translate general probabilities to - Matplotlib specific ones. - - style -- general curve style dictionary (defined in demoplot) - """ - # Translation dictionary - lineStyleDict = {"solid": "-", "dash": "--", "dot": ":", "dashDot": "-."} - symbolDict = { - "diamond": "d", - "square": "s", - "circle": "o", - "cross": "+", - "xCross": "x", - "triangle": "^", - } - colorDict = { - "blue": "#0B3C5D", - "green": "#1C6B0A", - "red": "#B82601", - "cyan": "c", - "magenta": "m", - "yellow": "y", - "black": "k", - "white": "w", - "darkRed": "#8B0000", - "darkGreen": "#006400", - "darkCyan": "#008B8B", - "darkYellow": "#FFD700", - "darkBlue": "#00008B", - "darkMagenta": "#8B008B", - } - - properties = {} - - # NOTE: matplotlib takes additional string for plotting. It's - # purpose is like 'with' in Gnuplot - stylestr = "" - # color is universal for either lines, points or linepoints - color = colorDict.get(style["color"], "k") - - if style["with"] in ("points", "linespoints"): - # require symbol properties - stylestr = "." - symbol = symbolDict.get(style["symbol"], "s") # prefer square - symbolSize = style["symbolSize"] - symbolColor = colorDict.get(style["symbolColor"], "k") - properties.update( - { # 'linewidth':0.0, # doesn't affect any - "markerfacecolor": symbolColor, - "markeredgecolor": color, - "marker": symbol, - "markersize": symbolSize, - } - ) - if style["with"] != "points": - # not 'points', so line properties are required as well - lineStyle = lineStyleDict.get(style["line"], "-") # prefer solid - lineWidth = style["width"] - stylestr += lineStyle - properties.update({"color": color, "linestyle": lineStyle, "linewidth": lineWidth}) - - if "legend" in style: - properties["label"] = style["legend"] - return stylestr, properties - - def setTitle(self, wt, gt): - """Set graph labels. - - wt -- window title - gt -- graph title - """ - self.SetTitle(wt) - self.figure.gca().set_title(gt) - - def setXLabel(self, x): - """Set label for x axis. - - x -- x label - """ - self.figure.gca().set_xlabel(x) - - def setYLabel(self, y): - """Set label for y axis. - - y -- y label - """ - self.figure.gca().set_ylabel(y) - - def clear(self): - """Erase all curves.""" - self.subplot.clear() - self.curverefs = [] - self.replot() - - -# End class ExtendedPlotFrame - - -def legendBoxProperties(): - """Legend properties dictionary with keys consistent with MPL - version. - - The argument names have changed in matplotlib 0.98.5. Old arguments - do not work with later versions of matplotlib. - - Return dictionary of legend properties. - """ - global _lbp - # return immediately if properties have already been cached - if len(_lbp) > 0: - return _lbp - # figure out matplotlib version and appropriate names - from matplotlib import __version__ as mplver - from packaging.version import parse - - if parse(mplver) >= parse("0.98.5"): - _lbp = { - "loc": "upper right", - "numpoints": 3, # number of points in the legend line - "borderpad": 0.25, # whitespace in the legend border - "labelspacing": 0, # space between legend entries - "handlelength": 1.5, # the length of the legend lines - "handletextpad": 0.5, # separation between line and text - "prop": FontProperties(size="medium"), - } - else: - _lbp = { - "loc": "upper right", - "numpoints": 3, # number of points in the legend line - "pad": 0.20, # whitespace in the legend border - "labelsep": 0.005, # space between legend entries - "handlelen": 0.03, # the length of the legend lines - "handletextsep": 0.02, # separation between line and text - "prop": FontProperties(size="medium"), - } - return _lbp - - -_lbp = {} - -# End of legendBoxProperties - - -if __name__ == "__main__": - - class MyApp(wx.App): - def OnInit(self): - from numpy import arange, cos, pi, sin - - "Create the main window and insert the custom frame" - x = arange(0.0, 3.0, 0.01) - s = sin(2 * pi * x) - c = cos(2 * pi * x) - t = sin(2 * pi * x) + cos(2 * pi * x) - frame = ExtendedPlotFrame(None) - style = {"with": "lines", "color": "blue", "line": "solid", "width": 2} - style["legend"] = "sin(x)" - frame.insertCurve(x, s, style) - style = {"with": "lines", "color": "red", "line": "solid", "width": 2} - style["legend"] = "cos(x)" - frame.insertCurve(x, c, style) - style = {"with": "lines", "color": "black", "line": "solid", "width": 2} - # style['legend'] = 'sin(x)+cos(x)' - frame.insertCurve(x, t, style) - frame.Show(True) - return True - - app = MyApp(0) - app.MainLoop() - - -# End of file diff --git a/src/diffpy/pdfgui/gui/fitnotebookpanel.py b/src/diffpy/pdfgui/gui/fitnotebookpanel.py deleted file mode 100644 index c35656b8..00000000 --- a/src/diffpy/pdfgui/gui/fitnotebookpanel.py +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/env python -# -*- coding: ISO-8859-1 -*- -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -# generated by wxGlade 0.9.3 on Fri Jul 19 17:16:20 2019 - -import wx - -from diffpy.pdfgui.gui.parameterspanel import ParametersPanel -from diffpy.pdfgui.gui.pdfpanel import PDFPanel -from diffpy.pdfgui.gui.resultspanel import ResultsPanel - - -class FitNotebookPanel(wx.Panel, PDFPanel): - def __init__(self, *args, **kwds): - # begin wxGlade: FitNotebookPanel.__init__ - kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL - wx.Panel.__init__(self, *args, **kwds) - self.fitnotebook = wx.Notebook(self, wx.ID_ANY, style=0) - self.parametersPanel = ParametersPanel(self.fitnotebook, wx.ID_ANY) - self.resultsPanel = ResultsPanel(self.fitnotebook, wx.ID_ANY) - - self.__set_properties() - self.__do_layout() - - self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.onPageChanged, self.fitnotebook) - self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGING, self.onPageChanging, self.fitnotebook) - # end wxGlade - self.__customProperties() - - def __set_properties(self): - # begin wxGlade: FitNotebookPanel.__set_properties - pass - # end wxGlade - - def __do_layout(self): - # begin wxGlade: FitNotebookPanel.__do_layout - sizer_1 = wx.BoxSizer(wx.HORIZONTAL) - self.fitnotebook.AddPage(self.parametersPanel, "Parameters") - self.fitnotebook.AddPage(self.resultsPanel, "Results") - sizer_1.Add(self.fitnotebook, 1, wx.EXPAND, 0) - self.SetSizer(sizer_1) - sizer_1.Fit(self) - self.Layout() - # end wxGlade - - def __customProperties(self): - """Set the custom properties.""" - self.fit = None - self.mainFrame = None - return - - def onPageChanged(self, event): # wxGlade: FitNotebookPanel. - """Refresh the panel visible panel.""" - self.refresh() - return - - def onPageChanging(self, event): # wxGlade: FitNotebookPanel. - event.Skip() - - def refresh(self): - """Refresh the panels.""" - if not self.fit: - return - panel = self.fitnotebook.GetCurrentPage() - panel.mainFrame = self.mainFrame - panel.refresh() - panel.fit = self.fit - panel.parameters = self.fit.parameters - panel.refresh() - - # Overloaded from Panel. - def Enable(self, enable=True): - """Keep the notebook enabled, just not the panels. - - outputPanel is immune from this, since it needs to be interacted - with. - """ - self.parametersPanel.Enable(enable) - return - - -# end of class FitNotebookPanel diff --git a/src/diffpy/pdfgui/gui/fittree.py b/src/diffpy/pdfgui/gui/fittree.py deleted file mode 100644 index fd6b5590..00000000 --- a/src/diffpy/pdfgui/gui/fittree.py +++ /dev/null @@ -1,929 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""This module contains the FitTree object designed for use in PDFgui. - -Classes: - FitTree -- A tree specific to orgainizing data for pdffit - -Exceptions: - FitTreeError -- Exception for errors with FitTree operations. -""" - -import base64 -import pickle -import re - -import wx - -from diffpy.pdfgui.control.controlerrors import ControlError -from diffpy.pdfgui.control.fitting import Fitting -from diffpy.pdfgui.gui.pdfguiglobals import iconpath -from diffpy.pdfgui.utils import safeCPickleDumps - - -class FitTree(wx.TreeCtrl): - """TreeCtrl designed to organize pdffit fits. - - The root of the tree is hidden. Below that there are several levels - which are diagrammed below. - - _ fit (*) - | - |____ phase (5) - |____ dataset (*) - |____ calculation (*) - - Fits are at the top level. Under fits there are phases, datasets, and - calculations (in that order). - - It is required that the data for each node is a dictionary. In the 'type' - entry of this dictionary is the node type (fit, phase, dataset, - calculation). Fit items also have a 'cdata' entry in their tree item - dictionary. This is the control center data associated with this node's - branch. - - Data members: - control -- The pdfguicontrol object that interfaces between the tree - and the pdffit2 engine. The tree is a mirror of the internal - structure of the control. - """ - - def __init__( - self, - parent, - id=-1, - pos=wx.DefaultPosition, - size=wx.DefaultSize, - style=wx.TR_HAS_BUTTONS | wx.TR_HIDE_ROOT | wx.TR_MULTIPLE, - validator=wx.DefaultValidator, - name="FitTree", - ): - wx.TreeCtrl.__init__(self, parent, id, pos, size, style) - - # Define the control - # This is set by the mainFrame - # self.control = pdfguicontrol() - - # Define bitmaps - datasetbmp = wx.Bitmap(iconpath("datasetitem.png")) - phasebmp = wx.Bitmap(iconpath("phaseitem.png")) - fitbmp = wx.Bitmap(iconpath("fititem.png")) - calcbmp = wx.Bitmap(iconpath("calculationitem.png")) - isz = (16, 16) - il = wx.ImageList(isz[0], isz[1]) - self.fitbmid = il.Add(fitbmp) - self.dtsbmid = il.Add(datasetbmp) - self.phabmid = il.Add(phasebmp) - self.clcbmid = il.Add(calcbmp) - self.SetImageList(il) - self.treeImageList = il - - return - - def InitializeTree(self): - """This initializes the tree by adding a root node.""" - self.root = self.AddRoot("The Root Item") - self.SetNodeType(self.root, "root") - # Testing code - # fit1 = self.AddFit() - # self.AddPhase(fit1, "Phase 1") - # self.AddPhase(fit1, "Phase 2") - # self.AddDataSet(fit1, "Data 1") - # self.AddCalc(fit1, "Calc 1") - # self.Expand(fit1) - return - - def GetTreeItemDict(self, node): - """Get the data dictionary of the node.""" - return self.GetItemData(node) - - def GetFitRoot(self, node): - """Return the id of the fit in which the passed node resides.""" - if not node: - return - fitId = node - nextId = self.GetItemParent(node) - while nextId != self.root: - fitId = nextId - nextId = self.GetItemParent(nextId) - return fitId - - def GetChildren(self, node): - """Get the ids of the children of a given node.""" - cookie = 0 - ids = [] - (child, cookie) = self.GetFirstChild(node) - while child.IsOk(): - ids.append(child) - (child, cookie) = self.GetNextChild(node, cookie) - - return ids - - def GetSiblings(self, node): - """Get the ids of the siblings of a given node.""" - parent = self.GetItemParent(node) - ids = self.GetChildren(parent) - ids.remove(node) - return ids - - def GetAllType(self, node): - """Get the id of each item in the tree of the same type as - node.""" - nodetype = self.GetNodeType(node) - fits = self.GetChildren(self.root) - if nodetype == "fit": - return fits - else: - sametype = [] - for fit in fits: - children = self.GetChildren(fit) - sametype.extend([child for child in children if self.GetNodeType(child) == nodetype]) - return sametype - - def GetPhases(self, node): - """Get a list of phase in branch. - - node is either the fit-root or a node in the fit-branch of - interest. - """ - nodes = self.GetChildren(self.GetFitRoot(node)) - ids = [id for id in nodes if self.GetNodeType(id) == "phase"] - return ids - - def GetDataSets(self, node): - """Get a list of datasets in branch. - - node is either the fit-root or a node in the fit-branch of - interest. - """ - nodes = self.GetChildren(self.GetFitRoot(node)) - ids = [id for id in nodes if self.GetNodeType(id) == "dataset"] - return ids - - def GetCalculations(self, node): - """Get a list of calculations in branch. - - node is either the fit-root or a node in the fit-branch of - interest. - """ - nodes = self.GetChildren(self.GetFitRoot(node)) - ids = [id for id in nodes if self.GetNodeType(id) == "calculation"] - return ids - - def GetNodeType(self, node): - """Get the node type. - - This is the "type" entry in the data dictionary of the node. - """ - if not node: - return None - datadict = self.GetTreeItemDict(node) - if datadict is None: - return None - return datadict["type"] - - def SetNodeType(self, node, tp): - """Set the node type of a node.""" - if not node: - return - datadict = self.GetTreeItemDict(node) - if datadict is None: - datadict = {} - self.SetItemData(node, datadict) - datadict["type"] = tp - return - - def GetBranchName(self, node): - """Get the name of the branch in which node resides.""" - fp = self.GetFitRoot(node) - return self.GetItemText(fp) - - def GetLastPhase(self, node): - """Get the last phase child of the parent node. - - This method is helpful in placing datasets and phases into the - fit tree. This method depends on the fact that phases are placed - before datasets in the fit tree. - """ - siblings = self.GetChildren(node) - lastphase = None - for sib in siblings: - if self.GetNodeType(sib) == "dataset": - break - elif self.GetNodeType(sib) == "calculation": - break - else: - lastphase = sib - return lastphase - - def GetLastDataSet(self, node): - """Get the last dataset child of the fit node. - - If there is no last dataset node, this may return the last phase - node. The purpose of getting this node is to know where to place - another node, so the actual node type is not important. - """ - siblings = self.GetChildren(node) - lastdata = None - for sib in siblings: - if self.GetNodeType(sib) == "calculation": - break - else: - lastdata = sib - return lastdata - - def GetNumPhases(self, node): - """Get the number of phases in a branch. - - node -- A node in the branch, or the root of the branch. - """ - parent = self.GetFitRoot(node) - family = self.GetChildren(parent) - phases = [item for item in family if self.GetNodeType(item) == "phase"] - return len(phases) - - def GetNumDataSets(self, node): - """Get the number of datasets in a branch. - - node -- A node in the branch, or the root of the branch. - """ - parent = self.GetFitRoot(node) - family = self.GetChildren(parent) - phases = [item for item in family if self.GetNodeType(item) == "dataset"] - return len(phases) - - def GetPositionInSubtree(self, node): - """Get the index if the node in its subtree. - - For fits the position is absolute within the tree. For phases, - datasets, and calculations, the location is taken to be in - reference to the other nodes of its type. This is designed to be - compatible with the control center. - """ - parent = self.GetItemParent(node) - brood = self.GetChildren(parent) - pos = 0 - for sib in brood: - if sib == node: - break - else: - pos += 1 - nodetype = self.GetNodeType(node) - if nodetype == "dataset": - pos -= self.GetNumPhases(node) - if nodetype == "calculation": - pos -= self.GetNumPhases(node) + self.GetNumDataSets(node) - return pos - - def SetControlData(self, node, data): - """Set the control center data associated with the node. - - This need only be called for 'fit' nodes. This is the "cdata" - entry in the data dictionary of the node. It holds the object - with which the right panel interfaces. For example, for a - 'phase' node, it contains a Structure object. - """ - nodetype = self.GetNodeType(node) - if nodetype != "fit": - message = "Node type %s does not hold its own data" % nodetype - raise FitTreeError(message) - - self.GetTreeItemDict(node)["cdata"] = data - return - - def GetControlData(self, node): - """Get the control center data associated with a node. - - NOTE: The fit-root of a node holds this data. This method makes it - convenient to retrieve it. - """ - nodetype = self.GetNodeType(node) - parent = self.GetFitRoot(node) - pdata = self.GetTreeItemDict(parent)["cdata"] - if nodetype == "fit": - return pdata - elif nodetype == "phase": - pos = self.GetPositionInSubtree(node) - return pdata.getStructure(pos) - elif nodetype == "dataset": - pos = self.GetPositionInSubtree(node) - return pdata.getDataSet(pos) - elif nodetype == "calculation": - pos = self.GetPositionInSubtree(node) - return pdata.getCalculation(pos) - else: - message = "Node of type %s does not exist" % nodetype - raise FitTreeError(message) - return - - def AddFit(self, fitname="Fit 1", cdata=None, paste=False): - """Append a new fit tree to the end of the current fits. - - fitname -- The name of the fit. This is incremented if it already - exists. - cdata -- Control data for the node. If cdata is None (default), - then the control is asked to create new data. - paste -- Whether or not the cdata is being pasted from another - node (default False). - - Returns the id of the new node. - """ - # Name the fit, but check to not duplicate names. - fits = self.GetChildren(self.root) - names = [self.GetItemText(f) for f in fits] - fitname = incrementName(fitname, names) - - newfit = self.AppendItem(self.root, fitname) - self.SetNodeType(newfit, "fit") - self.SetItemImage(newfit, self.fitbmid, wx.TreeItemIcon_Normal) - pos = self.GetPositionInSubtree(newfit) - - try: - # Set the node data for the new node - if cdata is None: - cdata = self.control.newFitting(fitname, pos) - elif paste: - cdata = self.control.paste(cdata, None, fitname, pos) - self.SetControlData(newfit, cdata) - return newfit - except Exception: - self.Delete(newfit) - raise - return - - def AddPhase(self, node, label, insertafter=None, filename=None, makedata=True, cdata=None): - """Add a new blank Phase to the tree as a child of node. - - node -- The parent 'fit' node. - label -- The name of the new node. - insertafter -- The node after which to insert the new phase. If - insertafter is None (default) the new phase is - appended to the end of the phases in the subtree of - the parent node. - filename -- The file from which to load the structure. If this is - None (default), a new structure is created. - makedata -- Tells whether the control needs to make data for the - node (default True). - cdata -- Control data for the node. If cdata is None (default), - then it is assumed that the node already has data in the - control. See ExtendProjectTree and __InsertBranch for - examples of how this is used. - - Phases are always placed before DataSets. - - Raises: - FitTreeError if node is not a "fit" node. - FitTreeError if insertafter is not a "phase" node. - - Returns the id of the new node. - """ - # Check to make sure the new phase is a child of a fit or calculation - nodetype = self.GetNodeType(node) - if nodetype != "fit": - message = "Can only add a phase as a child of a fit." - raise FitTreeError(message) - - if insertafter is not None: - afttype = self.GetNodeType(insertafter) - if afttype != "phase": - insertafter = None - - if insertafter: - newphase = self.InsertItem(node, insertafter, label) - else: - lastphase = self.GetLastPhase(node) - if lastphase: - # Put the new phase after the last - newphase = self.InsertItem(node, lastphase, label) - else: - newphase = self.PrependItem(node, label) - - self.SetNodeType(newphase, "phase") - self.SetItemImage(newphase, self.phabmid, wx.TreeItemIcon_Normal) - - # Set the control data to the new phase - pdata = self.GetControlData(node) - pos = self.GetPositionInSubtree(newphase) - - # Try to get/make the node data from the control. If it doesn't work, - # then delete the new node. - try: - if makedata: - if filename is None: - self.control.newStructure(pdata, label, pos) - else: - self.control.loadStructure(pdata, filename, label, pos) - - elif cdata is not None: - self.control.paste(cdata, pdata, label, pos) - return newphase - except Exception: - self.Delete(newphase) - raise - return - - def AddDataSet(self, node, label, insertafter=None, filename=None, makedata=True, cdata=None): - """Add a new DataSet to the tree as a child of fit. - - node -- The parent node of the dataset. Must be 'fit' type. - label -- The label of the new node. - insertafter -- The node after which to insert the new dataset. If - insertafter is None (default) the new dataset is - appended to the end of the datasets in the subtree of - the parent node. - filename -- The name of the file from which to load the data. - makedata -- Tells whether the control needs to make data for the - node (default True). If True, cdata is ignored. - cdata -- Control data for the node. If False cdata is None - (default), then it is assumed that the node already has - data in the control. See ExtendProjectTree and - __InsertBranch for examples of how this is used. - - DataSets are always placed after Phases. - - Raises: - FitTreeError if node is not a "fit" node. - FitTreeError if insertafter is not a "dataset" node. - - Returns the id of the new node. - """ - # Check to make sure the new dataset is a child of a fit - nodetype = self.GetNodeType(node) - if nodetype != "fit": - message = "Can only add a data set as a child of a fit." - raise FitTreeError(message) - - if insertafter is not None: - afttype = self.GetNodeType(node) - if afttype != "dataset": - insertafter = None - - if insertafter: - newset = self.InsertItem(node, insertafter, label) - else: - lastset = self.GetLastDataSet(node) - if lastset: - newset = self.InsertItem(node, lastset, label) - else: - newset = self.PrependItem(node, label) - - self.SetNodeType(newset, "dataset") - self.SetItemImage(newset, self.dtsbmid, wx.TreeItemIcon_Normal) - # Attach the control center data to the new dataset - pos = self.GetPositionInSubtree(newset) - pdata = self.GetControlData(node) - - try: - if makedata: - if filename is not None: - self.control.loadDataset(pdata, filename, label, pos) - else: - raise FitTreeError("Cannot load a dataset without a name!") - elif cdata is not None: - self.control.paste(cdata, pdata, label, pos) - return newset - except Exception: - self.Delete(newset) - raise - return - - def AddCalc(self, node, label, insertafter=None, makedata=True, cdata=None): - """Add a new DataSet to the tree as a child of fit. - - node -- The parent node of the calculation. Must be 'fit' type. - label -- The label of the new node. - insertafter -- The node after which to insert the new calculation. If - insertafter is None (default) the new calculation is - appended to the end of the calculation in the subtree of - the parent node. - makedata -- Tells whether the control needs to make data for the - node (default True). If True, cdata is ignored. - cdata -- Control data for the node. If False cdata is None - (default), then it is assumed that the node already has - data in the control. See ExtendProjectTree and - __InsertBranch for examples of how this is used. - - Calculations are always placed after datasets. - - Raises: - FitTreeError if node is not a "fit" node. - FitTreeError if insertafter is not a "calculation" node. - - Returns the id of the new node. - """ - # Check to make sure the new calculation is a child of a fit - nodetype = self.GetNodeType(node) - if nodetype != "fit": - message = "Can only add a calculation as a child of a fit." - raise FitTreeError(message) - - if insertafter is not None: - afttype = self.GetNodeType(node) - if afttype != "calculation": - insertafter = None - - sibs = self.GetCalculations(node) - names = [self.GetItemText(sb) for sb in sibs] - label = incrementName(label, names) - - if insertafter: - newcalc = self.InsertItem(node, insertafter, label) - else: - newcalc = self.AppendItem(node, label) - - self.SetNodeType(newcalc, "calculation") - self.SetItemImage(newcalc, self.clcbmid, wx.TreeItemIcon_Normal) - # Attach the control center data to the new datacalc - pos = self.GetPositionInSubtree(newcalc) - pdata = self.GetControlData(node) - - try: - if makedata: - self.control.newCalculation(pdata, label, pos) - elif cdata is not None: - self.control.paste(cdata, pdata, label, pos) - return newcalc - except Exception: - self.Delete(newcalc) - raise - return - - def CopyBranch(self, startnode): - """Make a copy of a tree branch. - - The branch is held in the system clipboard so it can be used in - another instance of the fittree. - """ - nodetype = self.GetNodeType(startnode) - cdata = self.control.copy(self.GetControlData(startnode)) - if isinstance(cdata, Fitting): - cdata = cdata.stripped() - cdata.type = nodetype - cdatabytes = safeCPickleDumps(cdata) - cdatabytes = "pdfgui_cliboard=".encode() + cdatabytes - # wxpython only accepts str, use base64 to convert bytes to str - cdatastring = base64.b64encode(cdatabytes) - textdata = wx.TextDataObject(cdatastring) - if not wx.TheClipboard.IsOpened(): - opened = wx.TheClipboard.Open() - if not opened: - raise FitTreeError("Cannot open the clipboard.") - wx.TheClipboard.SetData(textdata) - wx.TheClipboard.Close() - return - - def GetClipboard(self): - """Get the clipboard data. - - Returns the controldata in the clipboard, or None if the - clipboard is empty or contains the wrong type of data. - """ - # Check to see if data is present - if not wx.TheClipboard.IsSupported(wx.DataFormat(wx.DF_TEXT)): - return None - - textdata = wx.TextDataObject() - if not wx.TheClipboard.IsOpened(): - opened = wx.TheClipboard.Open() - if not opened: - return None - success = wx.TheClipboard.GetData(textdata) - wx.TheClipboard.Close() - if not success: - return None - cdatastring = textdata.GetText() - - cdata = None - # use base64 to convert str back to bytes - try: - cdatabytes = base64.b64decode(cdatastring.encode()) - - if cdatabytes[:16] == "pdfgui_cliboard=".encode(): - cdatabytes = cdatabytes[16:] - cdata = pickle.loads(cdatabytes, encoding="latin1") - except Exception: - pass - return cdata - - def PasteBranch(self, entrypoint=None): - """Paste the branch from the clipboard into tree at the given - node. - - A certain type of branch can only be copied to specific places. - - fit - A fit can be pasted to anywhere. This does not overwrite - an existing node, but simply inserts the fit into the - last available slot. - phase - A phase can be pasted from anywhere. If pasted from a - fit, it is placed at the end of the phase section of - that node. If inserted from a dataset or a calculation, - it is placed at the end of the phase section. - dataset - A dataset can be pasted from anywhere. If pasted from a - fit, the dataset is appended at the end of the other - datasets. If pasted from a dataset, the pasted set is - inserted right after that one. If pasted from a phase, - it is placed at the beginning of the dataset section. If - pasted from a calculation, it is placed at the end of - the dataset section. - calculation - A calculation can be pasted to anywhere, but it appears - at the end of the calculation section of the tree. If - pasted from a calculation node, it is inserted after - that node. - - Raises: - FitTreeError if the entrypoint and branch type are incompatible. - """ - cdata = self.GetClipboard() - if cdata is None: - message = "There is no branch to paste!" - raise FitTreeError(message) - - # Now we have the cdata, we must put it into the tree - branchtype = cdata.type - insertafter = None - prepend = False - entrytype = None - if entrypoint: - entrytype = self.GetNodeType(entrypoint) - # Check to see what we are trying to paste, and where. - - if branchtype == "fit": - # Paste after the selected fit containing the selection, or - # after the last fit if a calculation is selected. If nothing is - # selected, just paste it! - - entrytype = None - if entrypoint: - entrypoint = self.GetFitRoot(entrypoint) - entrytype = self.GetNodeType(entrypoint) - - if entrytype is None: - entrypoint = self.root - insertafter = None - elif entrytype == "fit": - insertafter = entrypoint - entrypoint = self.root - else: # Just in case - raise FitTreeError("Cannot paste a fit branch here.") - - if branchtype == "phase": - # Paste after selected phase, or append to the end of the phase - # section of a fit. - - if entrytype == "phase": - # The entry is to be a sibling. - insertafter = entrypoint - entrypoint = self.GetItemParent(entrypoint) - elif entrytype in ("dataset", "calculation"): - # Paste to the end of the phases, if they exist. - entrypoint = self.GetItemParent(entrypoint) - insertafter = self.GetLastPhase(entrypoint) - if not insertafter: - # Put the branch at the beginning of the phases - prepend = True - elif entrytype == "fit": - # Get the last phase in the phase section, which may not - # exist. - insertafter = self.GetLastPhase(entrypoint) - if not insertafter: - # Put the branch at the beginning of the phases - prepend = True - else: # Just in case - raise FitTreeError("Cannot paste a phase branch here.") - - if branchtype == "dataset": - # Paste after a selected dataset, or into a selected fit. - - if entrytype == "dataset": - # The entry is to be a sibling. - insertafter = entrypoint - entrypoint = self.GetItemParent(entrypoint) - elif entrytype == "phase": - # The entry goes to the end of the phases, which must exist. - entrypoint = self.GetItemParent(entrypoint) - insertafter = self.GetLastPhase(entrypoint) - elif entrytype == "calculation": - # The entry goes to the end of the datasets. - entrypoint = self.GetItemParent(entrypoint) - insertafter = self.GetLastDataSet(entrypoint) - elif entrytype == "fit": - insertafter = self.GetLastDataSet(entrypoint) - # The entrypoint is ok. The branch is appended to the end of - # the calculations. - pass - else: - raise FitTreeError("Cannot paste a data set branch here.") - - if branchtype == "calculation": - # Paste after the selected calculation or after the calculations. - - if entrytype == "calculation": - # The entry is to be a sibling. - insertafter = entrypoint - entrypoint = self.GetItemParent(entrypoint) - elif entrytype in ("phase", "dataset"): - entrypoint = self.GetItemParent(entrypoint) - insertafter = self.GetLastDataSet(entrypoint) - elif entrytype == "fit": - insertafter = self.GetLastDataSet(entrypoint) - else: # Just in case - raise FitTreeError("Cannot paste a calculation branch here.") - - # Now set the name of the item to be inserted. - label = self.__copyLabel(cdata.name, entrypoint) - - # Now we have a label. We must insert the item into the tree. - newnode = self.__InsertBranch(cdata, entrypoint, label, insertafter, prepend) - - return newnode - - def __copyLabel(self, oldlabel, entrypoint): - """Make a new label that is appropriate for a new node.""" - # Append "_copy" to the end of the label, unless it already has that. - # In that case, just add a number to indicate which copy it is. - siblings = self.GetChildren(entrypoint) - labels = [self.GetItemText(sb) for sb in siblings] - match = r"_copy\d*$" - label = re.sub(match, "", oldlabel) - label += "_copy" - label = incrementName(label, labels) - return label - - def __InsertBranch(self, cdata, entrypoint, label, insertafter=None, prepend=False): - """Insert control data into the tree. - - cdata -- The control data that goes with the branch - entrypoint -- The subbranch (fit root) to paste into - label -- The label of the new node - insertafter -- A node after which to insert. If insertafter is None - (default), then the new node will be pasted after the - last node of the same type. - prepend -- Prepend to the beginning of the node group (default - False). insertafter takes prescedent over prepend. - - Returns the newly inserted node. - """ - if cdata is None: - message = "There is no branch to paste!" - raise FitTreeError(message) - - branchtype = cdata.type - # cdata.name = label - if branchtype == "fit": - cdata.name = label - newnode = self.ExtendProjectTree([cdata.organization()], clear=False, paste=True) - elif branchtype == "phase": - newnode = self.AddPhase(entrypoint, label, insertafter=insertafter, makedata=False, cdata=cdata) - elif branchtype == "dataset": - newnode = self.AddDataSet(entrypoint, label, insertafter=insertafter, makedata=False, cdata=cdata) - elif branchtype == "calculation": - newnode = self.AddCalc(entrypoint, label, insertafter=insertafter, makedata=False, cdata=cdata) - else: - raise FitTreeError("Unrecognized node type: %s" % branchtype) - - return newnode - - def DeleteBranches(self, selections): - """Remove the subtree starting from the selected node(s).""" - # Get a list of branch heads - branchset = [node for node in selections if self.GetNodeType(node) == "fit"] - - # Get their children - childset = [] - for node in branchset: - childset.extend(self.GetChildren(node)) - - # Collect all nodes, removing any children of branch nodes. - nodeset = [node for node in selections if node not in childset] - - for node in nodeset: - cdata = self.GetControlData(node) - self.control.remove(cdata) - self.Delete(node) - return nodeset - - def SelectAll(self): - """Select all nodes.""" - self.UnselectAll() - fits = self.GetChildren(self.root) - for fit in fits: - children = self.GetChildren(fit) - self.SelectItem(fit) - for child in children: - self.SelectItem(child) - return - - def SelectAllType(self, node=None): - """Select all nodes of same type as passed node. - - node -- Node whose type to select. If node is None (default), then - all fit nodes will be selected. - """ - self.UnselectAll() - if node is None: - # Get the first fit node - fits = self.GetChildren(self.root) - if not fits: - return - node = fits[0] - typelist = self.GetAllType(node) - for item in typelist: - self.SelectItem(item) - return - - def ExtendProjectTree(self, treelist, clear=True, paste=False): - """Extend the project tree from the treelist. - - treelist -- A list of control data returned by - Oraganizer.organization() - clear -- Clear the tree before adding new nodes (default True) - paste -- Whether or not the cdata is being pasted from another - node (default False). - - The treelist here is of the type returned from pdfguicontrol.load. - It is a list of fit lists with the following format. - node[0] -- fit object - node[1] -- list of (name, dataset) tuples - node[2] -- list of (name, phase) tuples - node[3] -- list of (name, calculation) tuples - - Note that node[1] should be empty if the node is a calculation. - - Returns the last inserted fit or calculation node - """ - # Clean slate - if clear: - self.DeleteAllItems() - self.InitializeTree() - roots = [] - - # Return if the treelist is empty - if not treelist: - return - - # Build the tree - for item in treelist: - broot = item[0] - name = broot.name - node = self.AddFit(name, cdata=broot, paste=paste) - - if node is None: - message = "Cannot insert data. Malformed tree list." - raise FitTreeError(message) - - roots.append(node) - # Build the rest of the tree. Note that we don't want to create new - # data, but we don't pass the cdata since it is already included in - # the fit root. - phases = item[2] - for name, phase in phases: - self.AddPhase(node, name, makedata=False) - dsets = item[1] - for name, set in dsets: - self.AddDataSet(node, name, makedata=False) - calcs = item[3] - for name, calc in calcs: - self.AddCalc(node, name, makedata=False) - - for item in roots: - self.Expand(item) - return node - - -# End class FitTree - - -# Exceptions -class FitTreeError(ControlError): - def __init__(self, *args): - ControlError.__init__(self, *args) - return - - -# End class FitTreeError - - -# Utility functions -def incrementName(name, namelist, start=1): - """Increment the name by assigning the lowest number to the end such - that the name does not appear in the namelist.""" - newname = name - match = r"\d+$" - counter = start - while newname in namelist: - newname = re.sub(match, "", name) - counter += 1 - newname = "%s%i" % (newname, counter) - return newname diff --git a/src/diffpy/pdfgui/gui/gui_organization.txt b/src/diffpy/pdfgui/gui/gui_organization.txt deleted file mode 100644 index 8bc18cdb..00000000 --- a/src/diffpy/pdfgui/gui/gui_organization.txt +++ /dev/null @@ -1,62 +0,0 @@ -This document explains the basic organization and control of the PDFgui gui. - -The control panel of the gui is MainPanel in mainwindow.py. Among other things, -MainPanel contains a FitTree object (from fittree.py) and a dynamic panel. The -dynamic panel changes to depending upon the need of the user. (The data set and -structure panels are both be dynamic panels.) The current dynamic panel visible -in the gui is referred to the rightPanel (so named because the dynamic panel -appears to the right of the main window). - -Each dynamic panel must be derived from both wx.Panel and PDFPanel (from -pdfpanel.py). PDFPanel is a 'mix-in' class that contains variables and methods -needed by dynamic panels. The most important of these is the refresh() method. -The dynamic panel's refresh() method is called by MainPanel whenever a given -dynamic panel is made visible (it becomes the rightPanel). refresh() must be -redefined in a subclass of PDFPanel otherwise a NotImplementedError will be -thrown whenever refresh() is called. MainPanel only calls refresh() for the -rightPanel, not any of its children. It is up to a dynamic panel to take care of -its children. - -All dynamic panels, with the exception of informational ones, need access to -data and other information. A dynamic panel is provided with this information -when it becomes the rightPanel. - -All dynamic panels are assigned the member variables: -mainPanel - A reference to the MainPanel object. This can be used to change - some property of the MainPanel, such as its mode or to assign a - different rightPanel. Read the documentation in mainpanel.py to - get a better understanding of how MainPanel works. See - adddatapanel.py for an example for how these references are - used. -treeCtrlMain - A reference to the TreeCtrl of the gui. Panels may call upon - treeCtrlMain in order to change some property of the tree. Most - panels will not need this reference. See the wx.TreeCtrl API and - the documentation in fittree.py for more on this. See - adddatapanel.py for an example for how these references are - used. - -It is important to note again, if the children of a dynamic panel needs to know -what the mainPanel or treeCtrlMain are, it is the responsibility of the parent -to tell them. A dynamic panel knows what mainPanel and treeCtrlMain right after -it is initialized. - -Some dynamic panels may need to get or set data from PDFGuiControl. In most -circumstances, a reference to this information will be provided by the -MainPanel when the dynamic panel becomes the rightPanel. This allows, for -example, the phase set-up panel to display the information for the currently -selected phase in the FitTree. The information must be shared with the -children by rightPanel (perhaps as part of the refresh() method.) - -Objects given to the rightPanel in these cases is as follows. -_configuration - The configuration data for the panel. This is either a - dictionary or other object that tells how to set up the - configuration window. -_constraints - The constraints data for the panel. -_results - The fitting results to be displayed in the panel. - -Panels that need this information should initialize it to None. Future panels -may need to get bits of information from PDFGuiControl. Most cases will be -handled in the same way; data will be provided by the MainPanel to the dynamic -panel when it is needed. This allows these panels to be developed -independently from the MainPanel and allow them to be converged later. This, -hopefully, leads to easier and more rapid development. diff --git a/src/diffpy/pdfgui/gui/insertrowsdialog.py b/src/diffpy/pdfgui/gui/insertrowsdialog.py deleted file mode 100644 index 6f9389ae..00000000 --- a/src/diffpy/pdfgui/gui/insertrowsdialog.py +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env python -# -*- coding: UTF-8 -*- -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Dmitriy Bryndin -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -# generated by wxGlade 0.9.3 on Fri Jul 19 16:08:52 2019 - -import wx - - -class InsertRowsDialog(wx.Dialog): - def __init__(self, *args, **kwds): - # begin wxGlade: InsertRowsDialog.__init__ - kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_DIALOG_STYLE - wx.Dialog.__init__(self, *args, **kwds) - self.Rows = wx.StaticText(self, wx.ID_ANY, "Rows:") - self.spin_ctrl_Rows = wx.SpinCtrl(self, wx.ID_ANY, "1", min=0, max=100, style=0) - self.radio_box_where = wx.RadioBox( - self, - wx.ID_ANY, - "", - choices=["Above", "Below"], - majorDimension=2, - style=wx.RA_SPECIFY_ROWS, - ) - self.button_OK = wx.Button(self, wx.ID_OK, "OK") - self.button_Cancel = wx.Button(self, wx.ID_CANCEL, "Cancel") - - self.__set_properties() - self.__do_layout() - # end wxGlade - - def __set_properties(self): - # begin wxGlade: InsertRowsDialog.__set_properties - self.SetTitle("InsertRows") - self.radio_box_where.SetSelection(1) - # end wxGlade - - def __do_layout(self): - # begin wxGlade: InsertRowsDialog.__do_layout - sizer_horiz = wx.BoxSizer(wx.HORIZONTAL) - sizer_right_vert = wx.BoxSizer(wx.VERTICAL) - sizer_left_vert = wx.BoxSizer(wx.VERTICAL) - sizer_4 = wx.BoxSizer(wx.HORIZONTAL) - sizer_4.Add(self.Rows, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) - sizer_4.Add(self.spin_ctrl_Rows, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) - sizer_left_vert.Add(sizer_4, 0, wx.EXPAND, 0) - sizer_left_vert.Add(self.radio_box_where, 0, wx.ALL | wx.EXPAND, 5) - sizer_horiz.Add(sizer_left_vert, 0, wx.EXPAND, 0) - sizer_right_vert.Add(self.button_OK, 0, wx.ALL, 5) - sizer_right_vert.Add(self.button_Cancel, 0, wx.ALL, 5) - sizer_horiz.Add(sizer_right_vert, 0, wx.EXPAND, 0) - self.SetSizer(sizer_horiz) - sizer_horiz.Fit(self) - self.Layout() - # end wxGlade - - -# end of class InsertRowsDialog diff --git a/src/diffpy/pdfgui/gui/journalpanel.py b/src/diffpy/pdfgui/gui/journalpanel.py deleted file mode 100644 index 1a38c2a5..00000000 --- a/src/diffpy/pdfgui/gui/journalpanel.py +++ /dev/null @@ -1,134 +0,0 @@ -#!/usr/bin/env python -# -*- coding: UTF-8 -*- -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -# generated by wxGlade 0.9.3 on Fri Jul 19 16:03:01 2019 - -import os.path - -import wx - -from diffpy.pdfgui.gui.pdfpanel import PDFPanel - - -class JournalPanel(wx.Panel, PDFPanel): - def __init__(self, *args, **kwds): - PDFPanel.__init__(self) - # begin wxGlade: JournalPanel.__init__ - kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL - wx.Panel.__init__(self, *args, **kwds) - self.textCtrlJournal = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_MULTILINE) - self.exportButton = wx.Button(self, wx.ID_ANY, "Export") - self.closeButton = wx.Button(self, wx.ID_CLOSE, "") - - self.__set_properties() - self.__do_layout() - - self.Bind(wx.EVT_TEXT, self.onText, self.textCtrlJournal) - self.Bind(wx.EVT_BUTTON, self.onExport, self.exportButton) - self.Bind(wx.EVT_BUTTON, self.onClose, self.closeButton) - # end wxGlade - self.__customProperties() - - def __set_properties(self): - # begin wxGlade: JournalPanel.__set_properties - pass - # end wxGlade - - def __do_layout(self): - # begin wxGlade: JournalPanel.__do_layout - sizer_1 = wx.BoxSizer(wx.VERTICAL) - sizer_2 = wx.BoxSizer(wx.HORIZONTAL) - sizer_1.Add(self.textCtrlJournal, 1, wx.EXPAND, 0) - sizer_2.Add((1, 1), 1, 0, 0) - sizer_2.Add(self.exportButton, 0, wx.ALL, 5) - sizer_2.Add(self.closeButton, 0, wx.ALL, 5) - sizer_1.Add(sizer_2, 0, wx.EXPAND, 0) - self.SetSizer(sizer_1) - sizer_1.Fit(self) - self.Layout() - # end wxGlade - - def __customProperties(self): - """Custom Properties go here.""" - self.fullpath = "" - - # Bind the focus loss of the text control - self.textCtrlJournal.Bind(wx.EVT_KEY_DOWN, self.onKey) - return - - def onText(self, event): # wxGlade: JournalPanel. - """Record anything that is written into the journal.""" - text = self.textCtrlJournal.GetValue() - if text != self.mainFrame.control.journal: - self.mainFrame.control.journal = text - self.mainFrame.needsSave() - return - - def onExport(self, event): # wxGlade: JournalPanel. - """Export the journal to an external file.""" - matchstring = "Text files (*.txt)|*.txt|All Files|*" - dir, filename = os.path.split(self.fullpath) - if not dir: - dir = self.mainFrame.workpath - d = wx.FileDialog( - None, - "Export to...", - dir, - filename, - matchstring, - wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT, - ) - - if d.ShowModal() == wx.ID_OK: - self.fullpath = d.GetPath() - self.mainFrame.workpath = os.path.dirname(self.fullpath) - outfile = open(self.fullpath, "w") - outfile.write(self.mainFrame.control.journal) - outfile.close() - d.Destroy() - return - - def onClose(self, event): # wxGlade: JournalPanel. - self._close() - return - - def _close(self): - self.mainFrame.onShowJournal(None) - return - - def onKey(self, event): - """Catch Ctrl+J to close the journal.""" - # Ctrl J - key = event.GetKeyCode() - if event.ControlDown() and key == 74: - self._close() - event.Skip() - return - - # Methods overloaded from PDFPanel - def refresh(self): - """Fill the jounalTextCtrl with the journal.""" - # This will make sure that the scroll position does not change. - text = self.textCtrlJournal.GetValue() - if text != self.mainFrame.control.journal: - self.textCtrlJournal.ChangeValue(self.mainFrame.control.journal) - self.textCtrlJournal.SetInsertionPointEnd() - pos = self.textCtrlJournal.GetInsertionPoint() - self.textCtrlJournal.ShowPosition(pos) - return - - -# end of class JournalPanel diff --git a/src/diffpy/pdfgui/gui/main.py b/src/diffpy/pdfgui/gui/main.py deleted file mode 100644 index 8c580b06..00000000 --- a/src/diffpy/pdfgui/gui/main.py +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env python -# -*- coding: ISO-8859-1 -*- -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -# generated by wxGlade 0.4 on Tue Feb 21 12:00:30 2006 - -import wx - - -class PDFGuiApp(wx.App): - def OnInit(self): - from diffpy.pdfgui.gui.mainframe import MainFrame - - self.frame = MainFrame(None, -1, "") - self.SetTopWindow(self.frame) - self.frame.Show() - return True - - -# end of class PDFGuiApp - - -def main(): - """Kick starter for the PDFgui graphical user interface. - - This function is normally called from a light-weight console starter - diffpy.pdfgui.applications.pdfgui. Command line options and - arguments can be passed via cmdopts and cmdargs variables of the - pdfguiglobals module. - """ - app = PDFGuiApp(0) - app.MainLoop() - return - - -if __name__ == "__main__": - main() diff --git a/src/diffpy/pdfgui/gui/mainframe.py b/src/diffpy/pdfgui/gui/mainframe.py deleted file mode 100644 index ab2acbd4..00000000 --- a/src/diffpy/pdfgui/gui/mainframe.py +++ /dev/null @@ -1,2648 +0,0 @@ -#!/usr/bin/env python -# -*- coding: ISO-8859-1 -*- -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -# generated by wxGlade 0.4 on Thu Feb 23 15:06:06 2006 -"""This module contains the main window of PDFgui.""" - -import os.path -from configparser import ConfigParser - -import wx -import wx.aui -import wx.lib.newevent - -from diffpy.pdfgui.control import structureviewer -from diffpy.pdfgui.control.controlerrors import ControlError, ControlFileError -from diffpy.pdfgui.control.pdfguicontrol import pdfguicontrol -from diffpy.pdfgui.gui import pdfguiglobals -from diffpy.pdfgui.gui.aboutdialog import DialogAbout -from diffpy.pdfgui.gui.adddatapanel import AddDataPanel -from diffpy.pdfgui.gui.addphasepanel import AddPhasePanel -from diffpy.pdfgui.gui.blankpanel import BlankPanel -from diffpy.pdfgui.gui.calculationpanel import CalculationPanel -from diffpy.pdfgui.gui.datasetpanel import DataSetPanel -from diffpy.pdfgui.gui.dopingseriespanel import DopingSeriesPanel -from diffpy.pdfgui.gui.errorreportdialog import USERSMAILINGLIST, ErrorReportDialog -from diffpy.pdfgui.gui.errorwrapper import catchObjectErrors -from diffpy.pdfgui.gui.fitnotebookpanel import FitNotebookPanel -from diffpy.pdfgui.gui.fittree import FitTree, FitTreeError -from diffpy.pdfgui.gui.journalpanel import JournalPanel -from diffpy.pdfgui.gui.outputpanel import OutputPanel -from diffpy.pdfgui.gui.pdfguiglobals import docMainFile, iconpath -from diffpy.pdfgui.gui.phasenotebookpanel import PhaseNotebookPanel -from diffpy.pdfgui.gui.plotpanel import PlotPanel -from diffpy.pdfgui.gui.preferencespanel import PreferencesPanel -from diffpy.pdfgui.gui.rseriespanel import RSeriesPanel -from diffpy.pdfgui.gui.temperatureseriespanel import TemperatureSeriesPanel -from diffpy.pdfgui.gui.welcomepanel import WelcomePanel - -(PDFCustomEvent, EVT_PDFCUSTOM) = wx.lib.newevent.NewEvent() - -# WARNING - This file cannot be maintained with wxglade any longer. Do not make -# modifications with wxglade!!! - -# README - Note that wx.TreeCtrl.GetSelections works differently in MSW than it -# does in GTK. In GTK, it returns a list of nodes as they appear in the tree. -# In MSW, it returns the list of nodes in some other order. This can lead to -# trouble if the order of selected nodes is important to a method. -# wx.TreeControl does not create an event in windows. Node deselection does -# not create an event on windows. There is no workaround for this. Node -# selection vetoing does not work on windows. Finally, changing the tree -# selection sends two selection events on windows. One for an empty selection -# and one with the new selections. - - -class MainFrame(wx.Frame): - """The left pane is a FitTree (from fittree.py), the right is a - dynamic panel, accessed via the data member rightPanel, which can - hold one of any number of panels. The panels that can appear in the - right pane must be derived from PDFPanel (in pdfpanel.py) and are - defined in the dynamicPanels dictionary, which is defined in - __customProperties. A panel is placed in the right pane by passing - its dynamicPanels dictionary key to the switchRightPanel method. - This method takes care of displaying the panel, giving the data it - needs, and calling its refresh() method. - - ** NODE TYPES ** - The FitTree is essential to the functionality of the Gui. - The tree contains one of five types of items: - "fit" -- This represents a fit that is to be run by pdffit. - "dataset" -- This represents a data for a fit. - "phase" -- This represents the theoretical phases needed for a - dataset or a calculation. - "calculation" -- This represents a calculation which is to be made from - using a configured fit. - - Depending upon what type of item is selected in the tree, the right pane - will display the properties and configuration of that item (if in "fitting - mode", see below.) More on these item types is given in the documentation - for the FitTree in fittree.py. See r - - ** MODES ** - The program has various modes of operation. - "fitting" -- In this mode the right pane changes depending upon what - type of item is selected in the FitTree. When the - fitting button is pressed, the program is in "fitting" - mode. - "addingdata" -- This mode is for adding data. - "addingphase" -- This mode is for adding the phase - "config" -- This mode is used for preferences and structure viewer - configuration. - "rseries" -- The mode used when configuring an r-series macro. - "tseries" -- The mode used when configuring a temperature series - macro. - "dseries" -- The mode used when configuring a doping series macro. - - The mode determines how the tree and other widgets react to user - interaction. The mode of the program is changed with the method setMode. - This method outright enables or disables certain widgets that should not be - used when in certain modes. - - ** DATA MEMBERS ** - dynamicPanels -- The dictionary of right panels. This is used to change the - right panel in the method switchRightPanel. The panels held - by the dynamicPanels dictionary are listed below by their - dictionary keys: - - * Miscellaneous panels: - "blank" -- A blank panel - "rseries" -- The r-series macro panel - "tseries" -- The temperature series macro panel - "dseries" -- The doping series macro panel - "welcome" -- A welcome panel - - * 'fitting' mode panels - "fit" -- The panel for 'fit' nodes - "phase" -- The panel for 'phase' nodes - "dataset" -- The panel for 'dataset' nodes - "calculation" -- The panel for 'calculation' nodes - - * Panels specific to other program modes - "adddata" -- The panel used in 'addingdata' mode - "addphase" -- The panel used in 'addingphase' mode - - * Panels for future implementation - "configuration" -- Another 'config' mode panel - - rightPanel -- The current right panel. - fullpath -- The full path to the most recently accessed project file. - workpath -- The full path to the working directory. This is modified - whenever something is loaded or saved to file. It is - preserved in the current session and across new projects. - cP -- A python SafeConfigurationParser object. This is in charge - of storing configuration information about the most recently - used files list. It is also used by addphasepanel and - adddatapanel to store their respective fullpath variables. - The code that handles the MRU files interacts directly - with cP. - mode -- The current mode of the program. This is modified using the - setMode method. See the MODES section above. - name -- The name of the program as defined in pdfguiglobals. - control -- The pdfguicontrol object needed for interfacing with the - engine pdffit2 code. - isAltered -- A Boolean flag that indicates when the program has been - altered. This should be changed with the method needsSave so - that the save menu item and toolbar button can be updated - accordingly. - runningDict -- A dictionary of running fits and calculations indexed by - name. This dictionary is used to change the status colors of - running fits and to keep the user from editing a running - fit. - quitting -- A boolean that is set when the program is quitting. This - flag tells the error handlers to ignore any errors that take - place during shutdown. - """ - - def __init__(self, *args, **kwds): - kwds["style"] = wx.DEFAULT_FRAME_STYLE - - wx.Frame.__init__(self, *args, **kwds) - - self.SetMinSize((700, 500)) - self.auiManager = wx.aui.AuiManager(self) - - self.treeCtrlMain = FitTree( - self, - -1, - style=wx.TR_HAS_BUTTONS - | wx.TR_NO_LINES - | wx.TR_EDIT_LABELS - | wx.TR_MULTIPLE - | wx.TR_HIDE_ROOT - | wx.TR_MULTIPLE - | wx.TR_DEFAULT_STYLE - | wx.SUNKEN_BORDER, - ) - self.plotPanel = PlotPanel(self, -1) - self.outputPanel = OutputPanel(self, -1) - self.journalPanel = JournalPanel(self, -1) - self.panelDynamic = BlankPanel(self, -1) - - self.__customProperties() - - self.Bind(wx.EVT_TREE_SEL_CHANGING, self.onTreeSelChanging, self.treeCtrlMain) - self.Bind(wx.EVT_TREE_SEL_CHANGED, self.onTreeSelChanged, self.treeCtrlMain) - self.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.onEndLabelEdit, self.treeCtrlMain) - self.Bind(wx.EVT_TREE_BEGIN_LABEL_EDIT, self.onBeginLabelEdit, self.treeCtrlMain) - self.__customBindings() - self.__cmdLineLoad() - self.updateTitle() - - self.auiManager.Update() - self.switchRightPanel("welcome") - return - - # USER CONFIGURATION CODE ################################################# - - def __cmdLineLoad(self): - """Open file loaded from the command line. - - This opens a file without any checking for existing projects. - This should only be called after all initializations. It will - open a file whose name is specified in pdfguiglobals.cmdargs. - """ - if pdfguiglobals.cmdargs: - filename = pdfguiglobals.cmdargs[0] - fullpath = os.path.abspath(filename) - treelist = self.control.load(fullpath) - self.treeCtrlMain.ExtendProjectTree(treelist) - self.fullpath = fullpath - self.workpath = os.path.dirname(fullpath) - self.fileHistory.AddFileToHistory(fullpath) - self.plotPanel.refresh() - return - - def __defineLocalIds(self): - """Several user functions are duplicated many times throughout - the gui. - - This occurs mostly between the main menu, the right-click menu, - and the many buttons in the gui. This method defines local Ids - that can be used for all of these. - """ - # Functions that modify the tree. - # These are used in the fitting right-click menu and the main menu. - self.newFitId = wx.NewIdRef() # New Fit - self.newCalcId = wx.NewIdRef() # New Calculation - self.newPhaseId = wx.NewIdRef() # New Phase - self.newDataId = wx.NewIdRef() # New Data Set - self.deleteId = wx.ID_DELETE # Delete tree item - self.copyId = wx.ID_COPY # Copy a tree item - self.pasteId = wx.ID_PASTE # Paste a tree item into tree - self.pasteLinkId = wx.NewIdRef() # Paste and link a fit node - - # Misc. functions, these are exclusive to the main menu. - self.newId = wx.ID_NEW # Start a new Project - self.openId = wx.ID_OPEN # Open a project - self.recentId = None # Open a recent project (set later) - self.saveId = wx.ID_SAVE # Save the project - self.saveAsId = wx.ID_SAVEAS # Save the project as... - self.quitId = wx.ID_CLOSE # Quit the program - self.runFitId = wx.NewIdRef() # Run a fit - self.stopFitId = wx.NewIdRef() # Stop a fit - self.quickPlotId = wx.NewIdRef() # Quick plot a fit - self.exportFitPDFId = wx.NewIdRef() # Save a fit PDF - self.exportFitStruId = wx.NewIdRef() # Save a fit structure - self.exportNewStruId = wx.NewIdRef() # Export a 'new' structure - self.plotIStructId = wx.NewIdRef() # Plot initial structure - self.plotFStructId = wx.NewIdRef() # Plot final structure - self.printBLId = wx.NewIdRef() # Print the bond lengths of a structure - self.printBAId = wx.NewIdRef() # Print the bond angles of a structure - self.exportResId = wx.NewIdRef() # Save the results file - self.runCalcId = wx.NewIdRef() # Run a calculation - self.exportCalcPDFId = wx.NewIdRef() # Save a calculated PDF - return - - def __customProperties(self): - """Custom Properties go here.""" - # Set some visual stuff - icon = wx.Icon(iconpath("pdfgui.ico"), wx.BITMAP_TYPE_ANY) - self.SetIcon(icon) - - # The panel should know its name - self.name = pdfguiglobals.name - - # The fit tree needs a copy of the control, as - # most interactions with the control happen there. - self.control = pdfguicontrol(self) - self.control.startQueue() - self.treeCtrlMain.control = self.control - - # Constants needed for communication with the control - self.ERROR = 1 - self.UPDATE = 1 << 1 - self.OUTPUT = 1 << 2 - self.PLOTNOW = 1 << 3 - - # Needed for the error checker so it doesn't throw errors at quit time - self.quitting = False - - # Wrap the events to use an event handler - self.mainFrame = self # needed by error wrapper - catchObjectErrors(self) - - # Needed for loading and saving - self.fullpath = "" - self.workpath = os.path.abspath(".") - - # The dictionary of running fits/calculations - self.runningDict = {} - - # The configuration parser for getting configuration data. - # self.cP = Configparser() - # Long try this to avoid DuplicateSectionError and ParsingError - self.cP = ConfigParser(strict=False, allow_no_value=True, interpolation=None) - - # Set the program mode - self.mode = "fitting" - - # This is the dictionary of right panels. For simplicity the five panels - # corresponding to the five tree item types are given the name of the - # data type (fit, dataset, phase, calculation). This allows for - # automatic switching of panels. - self.dynamicPanels = { - "blank": self.panelDynamic, - "welcome": WelcomePanel(self, -1), - "fit": FitNotebookPanel(self, -1), - "phase": PhaseNotebookPanel(self, -1), - "dataset": DataSetPanel(self, -1), - "calculation": CalculationPanel(self, -1), - "adddata": AddDataPanel(self, -1), - "addphase": AddPhasePanel(self, -1), - "preferences": PreferencesPanel(self, -1), - "rseries": RSeriesPanel(self, -1), - "tseries": TemperatureSeriesPanel(self, -1), - "dseries": DopingSeriesPanel(self, -1), - } - - # Prepare the right pane. Display the welcome screen. - self.rightPanel = self.panelDynamic - for key in self.dynamicPanels: - self.auiManager.AddPane( - self.dynamicPanels[key], - wx.aui.AuiPaneInfo() - .Name(key) - .CenterPane() - .BestSize(wx.Size(400, 380)) - .MinSize(wx.Size(190, 200)) - .Hide(), - ) - self.dynamicPanels[key].mainFrame = self - self.dynamicPanels[key].treeCtrlMain = self.treeCtrlMain - self.dynamicPanels[key].cP = self.cP - self.dynamicPanels[key].key = key - self.dynamicPanels[key].Enable(False) - - # Do the same for the plotPanel and journalPanel - self.plotPanel.mainFrame = self - self.plotPanel.treeCtrlMain = self.treeCtrlMain - self.plotPanel.cP = self.cP - self.plotPanel.Enable(False) - - self.journalPanel.mainFrame = self - self.journalPanel.treeCtrlMain = self.treeCtrlMain - self.journalPanel.cP = self.cP - - # Position other panels. Note that currently MinimizeButton does not do - # anything. It is to be implemented in future versions of wx.aui - self.auiManager.AddPane( - self.outputPanel, - wx.aui.AuiPaneInfo() - .Name("outputPanel") - .Caption("PDFfit2 Output") - .Bottom() - .TopDockable() - .BottomDockable() - .LeftDockable() - .RightDockable() - .MinimizeButton() - .BestSize(wx.Size(400, 40)) - .MinSize(wx.Size(200, 40)), - ) - self.auiManager.AddPane( - self.treeCtrlMain, - wx.aui.AuiPaneInfo() - .Name("treeCtrlMain") - .Caption("Fit Tree") - .Left() - .TopDockable() - .BottomDockable() - .LeftDockable() - .RightDockable() - .MinimizeButton() - .BestSize(wx.Size(200, 100)) - .MinSize(wx.Size(200, 40)), - ) - self.auiManager.AddPane( - self.plotPanel, - wx.aui.AuiPaneInfo() - .Name("plotPanel") - .Caption("Plot Control") - .Left() - .TopDockable() - .BottomDockable() - .LeftDockable() - .RightDockable() - .MinimizeButton() - .BestSize(wx.Size(200, 250)) - .MinSize(wx.Size(200, 150)), - ) - self.auiManager.AddPane( - self.journalPanel, - wx.aui.AuiPaneInfo() - .Name("journalPanel") - .Caption("Project Journal") - .TopDockable() - .BottomDockable() - .LeftDockable() - .RightDockable() - .MinimizeButton() - .Hide() - .BestSize(wx.Size(450, 450)) - .MinSize(wx.Size(200, 200)) - .FloatingSize(wx.Size(450, 450)) - .Float(), - ) - - # Continue with initialization - self.__defineLocalIds() # Ids for menu items - self.__setupMainMenu() # Make the main menu - self.__setupToolBar() # Make the toolbar - self.treeCtrlMain.InitializeTree() # Initialize the tree - - # Load the configuration - self.loadConfiguration() - - # Set the state of the program - self.needsSave(False) - - return - - def __setupMainMenu(self): - """This sets up the menu in the main frame.""" - self.menulength = 8 - - self.menuBar = wx.MenuBar() - self.SetMenuBar(self.menuBar) - - # File Menu - self.fileMenu = wx.Menu() - self.newItem = wx.MenuItem(self.fileMenu, self.newId, "&New Project\tCtrl+n", "", wx.ITEM_NORMAL) - self.fileMenu.Append(self.newItem) - self.openItem = wx.MenuItem(self.fileMenu, self.openId, "&Open Project\tCtrl+o", "", wx.ITEM_NORMAL) - self.fileMenu.Append(self.openItem) - self.recentMenu = wx.Menu() - msub = self.fileMenu.AppendSubMenu(self.recentMenu, "&Recent Files") - self.recentId = msub.Id - self.fileMenu.AppendSeparator() - self.saveItem = wx.MenuItem(self.fileMenu, self.saveId, "&Save Project\tCtrl+s", "", wx.ITEM_NORMAL) - self.fileMenu.Append(self.saveItem) - self.saveAsItem = wx.MenuItem( - self.fileMenu, - self.saveAsId, - "Save Project &as\tCtrl+Shift+s", - "", - wx.ITEM_NORMAL, - ) - self.fileMenu.Append(self.saveAsItem) - self.fileMenu.AppendSeparator() - self.quitItem = wx.MenuItem(self.fileMenu, self.quitId, "&Quit\tCtrl+q", "", wx.ITEM_NORMAL) - self.fileMenu.Append(self.quitItem) - self.menuBar.Append(self.fileMenu, "&File") - # End File Menu - - # Edit Menu - self.editMenu = wx.Menu() - self.delItem = wx.MenuItem(self.editMenu, self.deleteId, "&Delete Item(s)\tCtrl+X", "", wx.ITEM_NORMAL) - self.editMenu.Append(self.delItem) - self.copyItem = wx.MenuItem(self.editMenu, self.copyId, "&Copy Item\tCtrl+C", "", wx.ITEM_NORMAL) - self.editMenu.Append(self.copyItem) - self.pasteItem = wx.MenuItem(self.editMenu, self.pasteId, "&Paste Item\tCtrl+V", "", wx.ITEM_NORMAL) - self.editMenu.Append(self.pasteItem) - self.pasteLinkItem = wx.MenuItem(self.editMenu, self.pasteLinkId, "Paste &Linked Fit", "", wx.ITEM_NORMAL) - self.editMenu.Append(self.pasteLinkItem) - self.editMenu.AppendSeparator() - self.prefItem = wx.MenuItem(self.editMenu, wx.NewIdRef(), "&Preferences", "", wx.ITEM_NORMAL) - self.editMenu.Append(self.prefItem) - self.menuBar.Append(self.editMenu, "&Edit") - # End Edit Menu - - # View Menu - self.viewMenu = wx.Menu() - self.defaultLayoutItem = wx.MenuItem( - self.editMenu, wx.NewIdRef(), "Default Window Layout", "", wx.ITEM_NORMAL - ) - self.viewMenu.Append(self.defaultLayoutItem) - self.viewMenu.AppendSeparator() - # These items are context sensitive. - self.showFitItem = wx.MenuItem(self.viewMenu, wx.NewIdRef(), "Show Fit Tree", "", wx.ITEM_NORMAL) - self.viewMenu.Append(self.showFitItem) - self.showPlotItem = wx.MenuItem(self.viewMenu, wx.NewIdRef(), "Show Plot Control", "", wx.ITEM_NORMAL) - self.viewMenu.Append(self.showPlotItem) - self.showOutputItem = wx.MenuItem(self.viewMenu, wx.NewIdRef(), "Show Output", "", wx.ITEM_NORMAL) - self.viewMenu.Append(self.showOutputItem) - self.showJournalItem = wx.MenuItem( - self.viewMenu, wx.NewIdRef(), "Show Journal\tCtrl+j", "", wx.ITEM_NORMAL - ) - self.viewMenu.Append(self.showJournalItem) - self.menuBar.Append(self.viewMenu, "&View") - - # Fits Menu - self.fitsMenu = wx.Menu() - self.newFitItem = wx.MenuItem(self.fitsMenu, self.newFitId, "&New Fit\tCtrl+t", "", wx.ITEM_NORMAL) - self.fitsMenu.Append(self.newFitItem) - self.fitsMenu.AppendSeparator() - self.runFitItem = wx.MenuItem(self.fitsMenu, self.runFitId, "&Run Selected Fits", "", wx.ITEM_NORMAL) - self.fitsMenu.Append(self.runFitItem) - self.stopFitItem = wx.MenuItem(self.fitsMenu, self.stopFitId, "&Stop Fitting", "", wx.ITEM_NORMAL) - self.fitsMenu.Append(self.stopFitItem) - self.fitsMenu.AppendSeparator() - self.expResItem = wx.MenuItem(self.fitsMenu, self.exportResId, "Export Resu<s File", "", wx.ITEM_NORMAL) - self.fitsMenu.Append(self.expResItem) - self.fitsMenu.AppendSeparator() - # Macros sub-menu - self.macrosMenu = wx.Menu() - self.rseriesItem = wx.MenuItem(self.macrosMenu, wx.NewIdRef(), "r-Series", "", wx.ITEM_NORMAL) - self.macrosMenu.Append(self.rseriesItem) - self.tseriesItem = wx.MenuItem(self.macrosMenu, wx.NewIdRef(), "Temperature Series", "", wx.ITEM_NORMAL) - self.macrosMenu.Append(self.tseriesItem) - self.dseriesItem = wx.MenuItem(self.macrosMenu, wx.NewIdRef(), "Doping Series", "", wx.ITEM_NORMAL) - self.macrosMenu.Append(self.dseriesItem) - self.fitsMenu.AppendSubMenu(self.macrosMenu, "Macros") - self.menuBar.Append(self.fitsMenu, "Fi&ts") - # End Fits Menu - - # Phases Menu - self.phasesMenu = wx.Menu() - self.newPhaseItem = wx.MenuItem(self.phasesMenu, self.newPhaseId, "&New Phase\tCtrl+p", "", wx.ITEM_NORMAL) - self.phasesMenu.Append(self.newPhaseItem) - self.phasesMenu.AppendSeparator() - self.printBLItem = wx.MenuItem( - self.phasesMenu, - self.printBLId, - "Calculate bond lengths", - "", - wx.ITEM_NORMAL, - ) - self.phasesMenu.Append(self.printBLItem) - self.printBAItem = wx.MenuItem( - self.phasesMenu, self.printBAId, "Calculate bond angles", "", wx.ITEM_NORMAL - ) - self.phasesMenu.Append(self.printBAItem) - self.phasesMenu.AppendSeparator() - self.expNewPhaseItem = wx.MenuItem( - self.phasesMenu, - self.exportNewStruId, - "Export &Selected Phase", - "", - wx.ITEM_NORMAL, - ) - self.phasesMenu.Append(self.expNewPhaseItem) - self.expStruItem = wx.MenuItem( - self.fitsMenu, - self.exportFitStruId, - "&Export Fit Structure", - "", - wx.ITEM_NORMAL, - ) - self.phasesMenu.Append(self.expStruItem) - self.phasesMenu.AppendSeparator() - self.plotIStructItem = wx.MenuItem( - self.phasesMenu, - self.plotIStructId, - "&Plot Initial Structure", - "", - wx.ITEM_NORMAL, - ) - self.phasesMenu.Append(self.plotIStructItem) - self.plotFStructItem = wx.MenuItem( - self.phasesMenu, - self.plotFStructId, - "&Plot Final Structure", - "", - wx.ITEM_NORMAL, - ) - self.phasesMenu.Append(self.plotFStructItem) - - self.menuBar.Append(self.phasesMenu, "&Phases") - # End Phases Menu - - # Data Menu - self.dataMenu = wx.Menu() - self.newDataItem = wx.MenuItem(self.dataMenu, self.newDataId, "&New Data Set\tCtrl+d", "", wx.ITEM_NORMAL) - self.dataMenu.Append(self.newDataItem) - self.dataMenu.AppendSeparator() - self.expFitPDFItem = wx.MenuItem(self.fitsMenu, self.exportFitPDFId, "&Export Fit PDF", "", wx.ITEM_NORMAL) - self.dataMenu.Append(self.expFitPDFItem) - self.menuBar.Append(self.dataMenu, "&Data") - # End Data Menu - - # Calculations Menu - self.calcMenu = wx.Menu() - self.newCalcItem = wx.MenuItem( - self.calcMenu, - self.newCalcId, - "&New Calculation\tCtrl+l", - "", - wx.ITEM_NORMAL, - ) - self.calcMenu.Append(self.newCalcItem) - self.calcMenu.AppendSeparator() - self.runCalcItem = wx.MenuItem( - self.calcMenu, - self.runCalcId, - "&Run Selected Calculation", - "", - wx.ITEM_NORMAL, - ) - self.calcMenu.Append(self.runCalcItem) - self.calcMenu.AppendSeparator() - self.expCalcPDFItem = wx.MenuItem( - self.calcMenu, - self.exportCalcPDFId, - "&Export Selected Calculation", - "", - wx.ITEM_NORMAL, - ) - self.calcMenu.Append(self.expCalcPDFItem) - self.menuBar.Append(self.calcMenu, "Ca&lculations") - # End Calculations Menu - - # Help Menu - self.helpMenu = wx.Menu() - self.docItem = wx.MenuItem(self.helpMenu, wx.NewIdRef(), "&Documentation\tF1", "", wx.ITEM_NORMAL) - self.helpMenu.Append(self.docItem) - self.requestItem = wx.MenuItem( - self.helpMenu, - wx.NewIdRef(), - "Request a Feature / Report a Bug", - "", - wx.ITEM_NORMAL, - ) - self.helpMenu.Append(self.requestItem) - self.communityItem = wx.MenuItem(self.helpMenu, wx.NewIdRef(), "PDFgui Community", "", wx.ITEM_NORMAL) - self.helpMenu.Append(self.communityItem) - self.aboutItem = wx.MenuItem(self.helpMenu, wx.NewIdRef(), "&About", "", wx.ITEM_NORMAL) - self.helpMenu.Append(self.aboutItem) - self.menuBar.Append(self.helpMenu, "&Help") - # End Help Menu - - # For managing MRUs - self.fileHistory = wx.FileHistory(pdfguiglobals.MAXMRU) - self.fileHistory.UseMenu(self.recentMenu) - - return - - def __setupToolBar(self): - """This sets up the tool bar in the parent window.""" - self.toolBar = self.CreateToolBar() - size = (16, 16) - bitmap = wx.ArtProvider.GetBitmap(wx.ART_NEW, wx.ART_TOOLBAR, size) - self.toolBar.AddTool( - self.newId, - "New Project", - bitmap, - wx.NullBitmap, - wx.ITEM_NORMAL, - "Start a new project", - ) - bitmap = wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN, wx.ART_TOOLBAR, size) - self.toolBar.AddTool( - self.openId, - "Open Project", - bitmap, - wx.NullBitmap, - wx.ITEM_NORMAL, - "Open an existing project", - ) - bitmap = wx.ArtProvider.GetBitmap(wx.ART_FILE_SAVE, wx.ART_TOOLBAR, size) - self.toolBar.AddTool( - self.saveId, - "Save Project", - bitmap, - wx.NullBitmap, - wx.ITEM_NORMAL, - "Save this project", - ) - self.toolBar.AddSeparator() - # This fixes the shadowing problem on Windows. - # The bitmap has a white transparency color (mask) - maskcolor = wx.Colour(red=255, green=255, blue=255) - bitmap = wx.Bitmap(iconpath("run.png")) - bitmap.SetSize(size) - mask = wx.Mask(bitmap, maskcolor) - bitmap.SetMask(mask) - self.toolBar.AddTool( - self.runFitId, - "Start", - bitmap, - wx.NullBitmap, - wx.ITEM_NORMAL, - "Start a fit or calculation", - ) - bitmap = wx.Bitmap(iconpath("stop.png")) - bitmap.SetSize(size) - mask = wx.Mask(bitmap, maskcolor) - bitmap.SetMask(mask) - self.toolBar.AddTool( - self.stopFitId, - "Stop", - bitmap, - wx.NullBitmap, - wx.ITEM_NORMAL, - "Stop running fits or calculations", - ) - self.toolBar.AddSeparator() - bitmap = wx.Bitmap(iconpath("datasetitem.png")) - bitmap.SetSize(size) - self.toolBar.AddTool( - self.quickPlotId, - "Quick plot", - bitmap, - wx.NullBitmap, - wx.ITEM_NORMAL, - "Plot PDF or structure", - ) - self.toolBar.Realize() - return - - def __customBindings(self): - """Custom user bindings go here. - - These bindings are not present in wxglade. - """ - # Allow a general right-click to work on the tree - self.treeCtrlMain.Bind(wx.EVT_RIGHT_DOWN, self.onRightClick) - # Double-click select all type on tree - # FIXME - this doesn't work, I suspect the problem is with the tree - # selection code. - # self.treeCtrlMain.Bind(wx.EVT_LEFT_DCLICK, self.onDoubleClick2) - # self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.onDoubleClick, self.treeCtrlMain) - # Middle-click quickplot - self.Bind(wx.EVT_TREE_ITEM_MIDDLE_CLICK, self.onMiddleClick, self.treeCtrlMain) - # Catch key events for the tree - self.treeCtrlMain.Bind(wx.EVT_KEY_DOWN, self.onKey) - # Catch the close event - self.Bind(wx.EVT_CLOSE, self.onQuit) - # Use the custom event to pop up error messages - self.Bind(EVT_PDFCUSTOM, self.onCustom) - # Do bindings for menu items - self.__menuBindings() - self.__fittingRightMenuBindings() - return - - def __menuBindings(self): - """Setup bindings for the main menu and toolbar. - - Since all toolbar functions use the same Ids as main menu items, - the toolbar events do not need their own bindings. - """ - # File Menu - self.Bind(wx.EVT_MENU, self.onNew, id=self.newId) - self.Bind(wx.EVT_MENU, self.onOpen, id=self.openId) - self.Bind(wx.EVT_MENU, self.onSave, id=self.saveId) - self.Bind(wx.EVT_MENU, self.onSaveAs, id=self.saveAsId) - self.Bind(wx.EVT_MENU, self.onQuit, id=self.quitId) - # For recent items - self.Bind(wx.EVT_MENU_RANGE, self.onMRUFile, id=wx.ID_FILE1, id2=wx.ID_FILE5) - - # Edit Menu - self.Bind(wx.EVT_MENU, self.onDelete, id=self.deleteId) - self.Bind(wx.EVT_MENU, self.onCopy, id=self.copyId) - self.Bind(wx.EVT_MENU, self.onPaste, id=self.pasteId) - self.Bind(wx.EVT_MENU, self.onPasteLink, id=self.pasteLinkId) - self.Bind(wx.EVT_MENU, self.onPreferences, self.prefItem) - - # View menu - self.Bind(wx.EVT_MENU, self.onDefaultLayout, self.defaultLayoutItem) - self.Bind(wx.EVT_MENU, self.onShowFit, self.showFitItem) - self.Bind(wx.EVT_MENU, self.onShowPlot, self.showPlotItem) - self.Bind(wx.EVT_MENU, self.onShowOutput, self.showOutputItem) - self.Bind(wx.EVT_MENU, self.onShowJournal, self.showJournalItem) - - # Fits Menu - self.Bind(wx.EVT_MENU, self.onNewFit, id=self.newFitId) - self.Bind(wx.EVT_MENU, self.onRun, id=self.runFitId) - self.Bind(wx.EVT_MENU, self.onStop, id=self.stopFitId) - self.Bind(wx.EVT_MENU, self.onExportRes, id=self.exportResId) - self.Bind(wx.EVT_MENU, self.onRSeries, self.rseriesItem) - self.Bind(wx.EVT_MENU, self.onTSeries, self.tseriesItem) - self.Bind(wx.EVT_MENU, self.onDSeries, self.dseriesItem) - # Macros are inserted individually - - # Phases Menu - self.Bind(wx.EVT_MENU, self.onInsPhase, id=self.newPhaseId) - self.Bind(wx.EVT_MENU, self.onPrintBL, id=self.printBLId) - self.Bind(wx.EVT_MENU, self.onPrintBA, id=self.printBAId) - self.Bind(wx.EVT_MENU, self.onExportNewStruct, id=self.exportNewStruId) - self.Bind(wx.EVT_MENU, self.onExportStruct, id=self.exportFitStruId) - self.Bind(wx.EVT_MENU, self.onPlotIStruct, id=self.plotIStructId) - self.Bind(wx.EVT_MENU, self.onPlotFStruct, id=self.plotFStructId) - - # Data Menu - self.Bind(wx.EVT_MENU, self.onInsData, id=self.newDataId) - self.Bind(wx.EVT_MENU, self.onExportPDF, id=self.exportFitPDFId) - - # Calculations Menu - self.Bind(wx.EVT_MENU, self.onInsCalc, id=self.newCalcId) - self.Bind(wx.EVT_MENU, self.onRun, id=self.runCalcId) - self.Bind(wx.EVT_MENU, self.onSaveCalc, id=self.exportCalcPDFId) - - # Help Menu - self.Bind(wx.EVT_MENU, self.onDocumentation, self.docItem) - self.Bind(wx.EVT_MENU, self.onAbout, self.aboutItem) - self.Bind(wx.EVT_MENU, self.onRequest, self.requestItem) - self.Bind(wx.EVT_MENU, self.onCommunity, self.communityItem) - - # The generic menu-check. - self.Bind(wx.EVT_MENU_OPEN, self.onMainMenu) - - # Toolbar events that have no menu item - self.Bind(wx.EVT_MENU, self.onQuickPlot, id=self.quickPlotId) - return - - def __fittingRightMenuBindings(self): - """Bindings for the fitting-mode right-click menu.""" - self.Bind(wx.EVT_MENU, self.onNewFit, id=self.newFitId) - self.Bind(wx.EVT_MENU, self.onCopy, id=self.copyId) - self.Bind(wx.EVT_MENU, self.onPaste, id=self.pasteId) - self.Bind(wx.EVT_MENU, self.onPasteLink, id=self.pasteLinkId) - self.Bind(wx.EVT_MENU, self.onInsPhase, id=self.newPhaseId) - self.Bind(wx.EVT_MENU, self.onInsData, id=self.newDataId) - self.Bind(wx.EVT_MENU, self.onInsCalc, id=self.newCalcId) - self.Bind(wx.EVT_MENU, self.onDelete, id=self.deleteId) - return - - # UTILITY FUNCTIONS ###################################################### - - def switchRightPanel(self, paneltype): - """Switch the panel which is visible in the right hand side. - - This sets any panel-specific data and calls the refresh() method of the - new rightPanel. All right panels must be derived from wxPanel and - PDFPanel (in pdfpanel module). - - Inputs: - paneltype -- The code used in self.dynamicPanels that indicates the - panel to be displayed. If paneltype is None, the blank - panel is displayed. - """ - self.rightPanel.Enable(False) - self.plotPanel.Enable(False) - for key in self.dynamicPanels: - self.auiManager.GetPane(key).Hide() - - # Why doesn't this work? - # key = self.rightPanel.key - # self.auiManager.GetPane(key).Hide() - - if paneltype is None: - paneltype = "blank" - - self.rightPanel = self.dynamicPanels[paneltype] - self.rightPanel.Enable(True) - self.setPanelSpecificData(paneltype) - self.rightPanel.refresh() - paneinfo = self.auiManager.GetPane(paneltype) - paneinfo.Show() - self.auiManager.Update() - - selections = self.treeCtrlMain.GetSelections() - if len(selections) == 1: - self.plotPanel.Enable(True) - - return - - def setPanelSpecificData(self, paneltype): - """This method sets the panel specific data for the right panel. - - This method gets panel-specific data and sends it to the rightPanel. The - different types of data assignment are listed below. - - "fit" type: - * Give the fit object to the panel - - "phase" type: - * initialize constraints dictionary and configuration and results - * Structure objects. - - "dataset" type: - * initialize configuration, constraints, and results objects - - "calculation" type: - * Give the calculation object to the panel - - "rseries" type: - * Give the fit object to the panel - - "tseries" type: - * Give the fit object to the panel - - "dseries" type: - * Give the fit object to the panel - """ - selections = self.treeCtrlMain.GetSelections() - if len(selections) == 1: - node = selections[0] - dataobject = self.treeCtrlMain.GetControlData(node) - - if paneltype == "phase": - self.rightPanel.configuration = dataobject.initial - self.rightPanel.constraints = dataobject.constraints - self.rightPanel.results = dataobject.refined - elif paneltype == "dataset": - self.rightPanel.configuration = dataobject - self.rightPanel.constraints = dataobject.constraints - self.rightPanel.results = dataobject.refined - elif paneltype == "fit": - dataobject.updateParameters() - self.rightPanel.fit = dataobject - elif paneltype == "calculation": - self.rightPanel.calculation = dataobject - elif paneltype == "rseries": - self.rightPanel.fit = dataobject - elif paneltype == "tseries": - self.rightPanel.fit = dataobject - elif paneltype == "dseries": - self.rightPanel.fit = dataobject - - return - - def setMode(self, mode): - """Set the mode of the program. - - This method takes care of any widget properties that must change when - the mode is changed. If the mode is changing due to the change in the - right panel, always call setMode before switchRightPanel. - - "fitting" mode: - * treeCtrlMain is enabled - * plotPanel panel is enabled - * toolBar is enabled - * menuBar is enabled - - "addingdata" mode: - "addingphase" mode: - "config" mode: - * treeCtrlMain is disabled - * plotPanel panel is disabled - * toolBar is disabled - * menuBar is disabled - - "rseries" mode: - "tseries" mode: - "dseries" mode: - * treeCtrlMain is enabled - * plotPanel panel is disabled - * toolBar is disabled - * menuBar is disabled - """ - self.mode = mode - if mode == "fitting": - self.treeCtrlMain.Enable(True) - self.plotPanel.Enable(True) - self.toolBar.Enable(True) - for i in range(self.menulength): - self.menuBar.EnableTop(i, True) - elif mode in ["addingdata", "addingphase", "config"]: - self.treeCtrlMain.Enable(False) - self.plotPanel.Enable(False) - self.toolBar.Enable(False) - for i in range(self.menulength): - self.menuBar.EnableTop(i, False) - elif mode in ["rseries", "tseries", "dseries"]: - self.treeCtrlMain.Enable(True) - self.plotPanel.Enable(False) - self.toolBar.Enable(False) - for i in range(self.menulength): - self.menuBar.EnableTop(i, False) - return - - def loadConfiguration(self): - """Load the configuration from file. - - The MRU list is handled by the local member fileHistory, which - is a wxFileHistory object. - """ - - # Get MRU information - localpath = os.path.expanduser(pdfguiglobals.configfilename) - if os.path.exists(localpath): - self.cP.read(localpath) - for i in range(pdfguiglobals.MAXMRU, 0, -1): - if self.cP.has_option("MRU", str(i)): - filename = self.cP.get("MRU", str(i)) - if filename: - self.fileHistory.AddFileToHistory(filename) - - # Import perspective from last session - if self.cP.has_section("PERSPECTIVE"): - if self.cP.has_option("PERSPECTIVE", "last"): - perspective = self.cP.get("PERSPECTIVE", "last") - self.auiManager.LoadPerspective(perspective) - else: - from diffpy.pdfgui.gui.windowperspective import default - - self.auiManager.LoadPerspective(default) - - # Load the window dimensions - w = 800 - h = 600 - if self.cP.has_option("SIZE", "width"): - w = self.cP.get("SIZE", "width") - w = int(w) - if self.cP.has_option("SIZE", "height"): - h = self.cP.get("SIZE", "height") - h = int(h) - self.SetSize((w, h)) - - # Load structure viewer information and put this in the configure panel - viewerconfig = {} - if self.cP.has_section("STRUCTUREVIEWER"): - viewerconfig = dict(self.cP.items("STRUCTUREVIEWER")) - viewer = structureviewer.getStructureViewer() - viewer.setConfig(viewerconfig) - - return - - def updateConfiguration(self): - """Update the configuration information. - - This updates the 'MRU' section of the configuration. - """ - # Most recently used list - if not self.cP.has_section("MRU"): - self.cP.add_section("MRU") - - for i in range(self.fileHistory.GetCount()): - item = self.fileHistory.GetHistoryFile(i) - self.cP.set("MRU", str(i + 1), item) - - # Window size - if not self.cP.has_section("SIZE"): - self.cP.add_section("SIZE") - - w, h = self.GetSize() - self.cP.set("SIZE", "width", str(w)) - self.cP.set("SIZE", "height", str(h)) - - # Frame layout - if not self.cP.has_section("PERSPECTIVE"): - self.cP.add_section("PERSPECTIVE") - - perspective = self.auiManager.SavePerspective() - self.cP.set("PERSPECTIVE", "last", perspective) - - # Set the structure viewer information - if not self.cP.has_section("STRUCTUREVIEWER"): - self.cP.add_section("STRUCTUREVIEWER") - viewer = structureviewer.getStructureViewer() - viewerconfig = viewer.getConfig() - for key, value in viewerconfig.items(): - self.cP.set("STRUCTUREVIEWER", key, value) - - return - - def writeConfiguration(self): - """Write the program configuration to file.""" - filename = os.path.expanduser(pdfguiglobals.configfilename) - oflags = os.O_CREAT | os.O_WRONLY - try: - with os.fdopen(os.open(filename, oflags, 0o600), "w") as outfile: - self.cP.write(outfile) - except IOError: - emsg = "Cannot write configuration file %r" % filename - raise ControlFileError(emsg) - return - - def checkForSave(self): - """Pop up a dialog if the project needs to be saved. - - returns: - wx.ID_YES if the user chose to save the project. - wx.ID_NO if the user chose not to save the project. - wx.ID_CANCEL if they changed their mind about their action. - """ - code = wx.ID_NO - # disable when requested in dbopts - if pdfguiglobals.dbopts.noconfirm: - return code - if pdfguiglobals.isAltered: - d = wx.MessageDialog( - self, - "Would you like to save this session?", - "Save?", - wx.YES_NO | wx.CANCEL, - ) - code = d.ShowModal() - if code == wx.ID_YES: - code = self.onSave(None) - d.Destroy() - return code - - def updateTitle(self): - """Update the title according to the name of the current - file.""" - shorttitle = os.path.basename(self.fullpath) - udirnamed = "~" + os.path.sep - udir = os.path.expanduser(udirnamed) - if shorttitle: - namedpath = self.fullpath - if namedpath.startswith(udir): - namedpath = namedpath.replace(udir, udirnamed) - fulltitle = "%s (%s) - %s" % (shorttitle, namedpath, self.name) - else: - fulltitle = self.name - self.SetTitle(fulltitle) - return - - # MAIN PANEL EVENT CODE ####################################################### - - def onMainMenu(self, event): - """Prepare the main menu whenever it is activated.""" - self.disableMainMenuItems() - return - - def makeTreeSelection(self, node): - """Manually select a node of the tree and update according to - selection. - - This makes sure that the node is visible after selection. - - If node is None, this does nothing. - """ - if node is None: - return - - self.treeCtrlMain.SelectItem(node) - - # Make sure that the node is visible. - self.treeCtrlMain.SetFocus() - self.treeCtrlMain.EnsureVisible(node) - self.treeCtrlMain.ScrollTo(node) - - self.treeSelectionUpdate(node) - - # The right-panel probably stole focus, but we want it back. - self.treeCtrlMain.SetFocus() - return - - def treeSelectionUpdate(self, node): - """Update the widgets based on a tree selection. - - "fitting" mode: - * Right panel changes depending upon the type of item selected from the - tree. - - "rseries", "tseries", "dseries" mode: - * The behavior is defined in the associated panel - """ - selections = self.treeCtrlMain.GetSelections() - - # "fitting" mode - if self.mode == "fitting": - # This doesn't work on Windows. - self.plotPanel.Enable(True) - if len(selections) == 0: - self.switchRightPanel("blank") - self.plotPanel.Enable(False) - # return - elif len(selections) == 1: - self.rightPanel.Enable() - selectiontype = self.treeCtrlMain.GetNodeType(selections[0]) - self.switchRightPanel(selectiontype) - else: - self.rightPanel.Enable(False) - self.plotPanel.Enable(True) - - # Don't let the user edit the right panel of a running fit. - fp = self.treeCtrlMain.GetFitRoot(node) - if fp: - name = self.treeCtrlMain.GetItemText(fp) - if name in self.runningDict: - self.rightPanel.Enable(False) - - elif self.mode in ["rseries", "tseries", "dseries"]: - self.rightPanel.treeSelectionUpdate(node) - - # Update the plotPanel - self.plotPanel.refresh() - - # update the toolbar and menu - self.updateToolbar() - if self.runningDict: - self.disableMainMenuItems() - return - - def onTreeSelChanged(self, event): - """Set the click behavior for each mode.""" - node = event.GetItem() - self.treeSelectionUpdate(node) - return - - def onTreeSelChanging(self, event): # wxGlade: MainPanel. - """Set the click behavior for each mode. - - Note that this doesn't work on Windows. Be sure to build in redundancy - so that the program behaves as if this does not even get called. If the - Windows bug does not get fixed, this method will probably be - eliminated. - - "addingdata" mode: - * can select nothing - - "addingphase" mode: - * can select nothing - - "config" mode: - * can select nothing - - "rseries" mode: - * can only select fit items - - "tseries" mode: - * can only select fit items - - "dseries" mode: - * can only select fit items - """ - # THIS DOESN'T WORK ON WINDOWS! - node = event.GetItem() - if not node: - return - if self.mode in ["addingdata", "addingphase", "config"]: - event.Veto() - elif self.mode in ["rseries", "tseries", "dseries"]: - nodetype = self.treeCtrlMain.GetNodeType(node) - if nodetype != "fit": - event.Veto() - - return - - def onBeginLabelEdit(self, event): # wxGlade: MainPanel. - """Veto editing of some items and in some modes. - - The following editing attempts are Veto()'d - * Editing any item in "addingdata", "addingphase", or "config" mode. - """ - nodetype = self.treeCtrlMain.GetNodeType(event.GetItem()) - # silence the pyflakes syntax checker - assert nodetype or True - if self.mode != "fitting": - event.Veto() - return - - def onEndLabelEdit(self, event): # wxGlade: MainPanel. - """Allow only certain types of renaming. - - The following rename attempts are Veto()'d - * Giving a node the same name as a sibling. Cousins can share names. - * Giving a node the name ''. Everything needs a name. - """ - label = event.GetLabel() - - # No '' - if label.strip() == "": - event.Veto() - return - - # No sibling's sharing the same name. (Sorry, George Foreman.) - node = event.GetItem() - siblings = [self.treeCtrlMain.GetItemText(id) for id in self.treeCtrlMain.GetSiblings(node)] - if label in siblings: - event.Veto() - return - - # Notify the control of the rename - cdata = self.treeCtrlMain.GetControlData(node) - self.control.rename(cdata, label) - self.needsSave() - return - - def onRightClick(self, event): # wxGlade: MainPanel. - """Bring up the right-click menu. - - This menu can give a different menu depending upon which mode the - program is in. It can even give a different menu depending upon what - part of the tree is selected. - - "fitting" mode - The menu appears for right-clicks both on and off of tree items. - The menu has the following items: - "New Fit" -- Append a new fit from anywhere on the tree. - "Copy" -- Copy a fit, phase, dataset, or calc branch - "Paste" -- Paste a copied branch into the tree. Branches - of a given type can only be pasted in certain - places. - "Delete" -- Delete a branch from the tree. - "Insert Phase" -- Insert a phase in the phase section of a fit or - calculation branch. - "Insert Data Set" -- Insert a dataset in the dataset section of a fit - branch. - "Insert Calculation"-- Insert a calculation in the calculation section - of a fit. - - The menu appears for right-clicks both on and off of tree items. - The menu has the following items: - "Select All" -- The tree automatically selects all items of the - type the user clicked on. - """ - # This menu is disabled the if item is part of a running fit. - selections = self.treeCtrlMain.GetSelections() - if selections: - node = self.treeCtrlMain.GetFitRoot(selections[0]) - nodetype = self.treeCtrlMain.GetNodeType(node) - # silence the pyflakes syntax checker - assert nodetype or True - if node in self.runningDict.values(): - return - - if self.mode == "fitting": - - # The menu Ids are defined in __defineLocalIds. - menu = wx.Menu() - menu.Append(self.newFitId, "New Fit") - menu.AppendSeparator() - menu.Append(self.copyId, "Copy") - menu.Append(self.pasteId, "Paste") - menu.Append(self.pasteLinkId, "Paste Linked Fit") - menu.Append(self.deleteId, "Delete") - menu.AppendSeparator() - menu.Append(self.newPhaseId, "Insert Phase") - menu.Append(self.newDataId, "Insert Data Set") - menu.Append(self.newCalcId, "Insert Calculation") - - # Get the item we've right clicked on - itemtype = None - x = event.GetX() - y = event.GetY() - node, flags = self.treeCtrlMain.HitTest((x, y)) - - if flags in [ - wx.TREE_HITTEST_ABOVE, - wx.TREE_HITTEST_BELOW, - wx.TREE_HITTEST_NOWHERE, - ]: - # The hit is not on an item. - self.treeCtrlMain.UnselectAll() - self.switchRightPanel("blank") - selections = [] - # Select the item with a right click, but don't add it to an - # existing selection. - elif node not in selections: - self.treeCtrlMain.UnselectAll() - self.treeCtrlMain.SelectItem(node) - selections = [node] - itemtype = self.treeCtrlMain.GetNodeType(node) - # silence the pyflakes syntax checker - assert itemtype or True - # Enable/Disable certain entries based upon where we clicked. - self.disableSharedMenuItems(menu) - - else: - return - - # Bring up the popup menu. Must have the coordinates of the right-click - # event that summoned the menu. - - # This is to position the menu correctly on a floating frame. - # wx.treeCtrlMain.GetPosition() will return (0,0) if the frame is - # not docked. This is a bit of a hack, since pane.floating_pos is not - # designed to be a public attribute. - pane = self.auiManager.GetPane("treeCtrlMain") - (x0, y0) = self.treeCtrlMain.GetPosition() - if pane.IsFloating(): - (x0, y0) = self.ScreenToClient(pane.floating_pos) - self.PopupMenu(menu, (x0 + x, y0 + y)) - menu.Destroy() - return - - def onMiddleClick(self, event): - """Quickplot on item middle click.""" - node = event.GetItem() - self.treeCtrlMain.UnselectAll() - self.treeCtrlMain.SelectItem(node) - self.onQuickPlot(None) - return - - def onDoubleClick2(self, event): - """Select-all type on item double click.""" - x = event.GetX() - y = event.GetY() - node, flags = self.treeCtrlMain.HitTest((x, y)) - - if flags not in [ - wx.TREE_HITTEST_ABOVE, - wx.TREE_HITTEST_BELOW, - wx.TREE_HITTEST_NOWHERE, - ]: - if self.mode == "fitting": - wx.CallAfter(self.treeCtrlMain.SelectAllType, node) - wx.CallAfter(self.treeSelectionUpdate, node) - return - - def onDoubleClick(self, event): - """Select-all type on item double click.""" - node = event.GetItem() - if self.mode == "fitting": - wx.CallAfter(self.treeCtrlMain.SelectAllType, node) - wx.CallAfter(self.treeSelectionUpdate, node) - return - - def onKey(self, event): - """Catch key events in the panel.""" - # See if the tree is in focus. If not, pass the event on - key = event.GetKeyCode() - - selections = self.treeCtrlMain.GetSelections() - node = None - if selections: - node = selections[0] - - # Shift+Ctrl+A - # "fitting" mode -- Select all nodes of a given type - if event.ShiftDown() and event.ControlDown() and key == 65: - if self.mode == "fitting": - self.treeCtrlMain.SelectAllType(node) - self.treeSelectionUpdate(node) - - # Ctrl+A - # "fitting" mode -- Select all nodes - elif event.ControlDown() and key == 65: - if self.mode == "fitting": - self.treeCtrlMain.SelectAll() - self.treeSelectionUpdate(node) - - # XXX - removed - Without undo functionality, this is too dangerous. - # Delete - # "fitting" mode -- Delete selected noded - # elif key == 127: - # if self.mode == "fitting": - # self.onDelete(None) - - # Tab - # Move to the right panel - elif key == 9: - self.rightPanel.SetFocus() - - else: - event.Skip() - - return - - # MENU RELATED FUNCTIONS ################################################## - - def updateToolbar(self): - """Update the toolbar based upon the status of the program.""" - self.toolBar.EnableTool(self.saveId, (pdfguiglobals.isAltered and self.runningDict == {})) - - itemtype = None - selections = self.treeCtrlMain.GetSelections() - if selections: - itemtype = self.treeCtrlMain.GetNodeType(selections[0]) - - # This is redundant, but easy to maintain - if self.mode == "fitting": - - # Quickplot - if len(selections) == 1 and itemtype and itemtype != "fit": - self.toolBar.EnableTool(self.quickPlotId, True) - else: - self.toolBar.EnableTool(self.quickPlotId, False) - - # Fit run/stop - if not self.runningDict: - # No fit is running - self.toolBar.EnableTool(self.stopFitId, False) - # We can run a fit if there are any selections - if selections: - self.toolBar.EnableTool(self.runFitId, True) - else: - self.toolBar.EnableTool(self.runFitId, False) - - else: - self.toolBar.EnableTool(self.stopFitId, True) - self.toolBar.EnableTool(self.runFitId, False) - - else: - # Quickplot - self.toolBar.EnableTool(self.quickPlotId, False) - - # Fit run/stop - self.toolBar.EnableTool(self.stopFitId, False) - self.toolBar.EnableTool(self.runFitId, False) - - return - - def needsSave(self, altered=True): - """Tell the gui that the program needs to be saved. - - This changes the state of the save menu and tool bar items. - - altered -- Whether or not the program needs saving (default True). - """ - if not self.quitting: - pdfguiglobals.isAltered = altered - self.updateToolbar() - return - - def disableSharedMenuItems(self, menu): - """Disable some menu items based upon what is selected in the - tree. - - menu -- The menu which to apply the changes. - - Note that this method is meant to disable only the shared menu items, - that is, those that use the same menu item Ids. These are defined in the - top part of __defineLocalIds(). Putting this logic into a single method - makes it easier to make changes with the menus. If a specific menu needs - additional logic, put that in a separate method. - """ - # Start by refreshing the shared items. We don't need things to become - # perpetually disabled. All things are enabled by default. It is up to - # the logic below to disable them. - menu.Enable(self.newFitId, True) - menu.Enable(self.newPhaseId, True) - menu.Enable(self.newDataId, True) - menu.Enable(self.newCalcId, True) - menu.Enable(self.deleteId, True) - menu.Enable(self.copyId, True) - menu.Enable(self.pasteId, True) - menu.Enable(self.pasteLinkId, True) - - # Get the selections off the tree - selections = self.treeCtrlMain.GetSelections() - node = None - if selections: - node = selections[0] - - noPhases = False - if node: - phases = self.treeCtrlMain.GetPhases(node) - # No insert calculation if there are no phases - if len(phases) == 0: - noPhases = True - - # No insert calculation if there are no phases - if noPhases: - menu.Enable(self.newCalcId, False) - - # Change the paste text and enable or disable the paste function - # based upon where we are in the tree or whether or not we have - # something in the clipboard - pastename = "" - clipbranchtype = None - cdata = self.treeCtrlMain.GetClipboard() - - # No paste if nothing in the clipboard - if cdata is None: - menu.Enable(self.pasteId, False) - menu.Enable(self.pasteLinkId, False) - else: - clipbranchtype = cdata.type - if clipbranchtype == "fit": - pastename = "Fit" - # Check to see if the linking fit is still in the tree. If it is - # not, we disable pasteLink - fitname = cdata.name - fits = self.treeCtrlMain.GetChildren(self.treeCtrlMain.root) - fitnames = set(map(self.treeCtrlMain.GetItemText, fits)) - if fitname not in fitnames: - menu.Enable(self.pasteLinkId, False) - # pasteLink only if there's a fit in the clipboard - elif clipbranchtype == "phase": - pastename = "Phase" - menu.Enable(self.pasteLinkId, False) - elif clipbranchtype == "dataset": - pastename = "Data Set" - menu.Enable(self.pasteLinkId, False) - elif clipbranchtype == "calculation": - pastename = "Calculation" - menu.Enable(self.pasteLinkId, False) - pastetext = "&Paste %s\tCtrl+V" % pastename - menu.SetLabel(self.pasteId, pastetext) - - # Disable certain entries based upon where we clicked. - # No copy, paste, or insert on multiple items. - if len(selections) > 1: - menu.Enable(self.copyId, False) - menu.Enable(self.pasteId, False) - menu.Enable(self.pasteLinkId, False) - menu.Enable(self.newDataId, False) - menu.Enable(self.newPhaseId, False) - menu.Enable(self.newCalcId, False) - # Disallow paste of fit if no items selected - elif not selections: - menu.Enable(self.copyId, False) - menu.Enable(self.deleteId, False) - menu.Enable(self.newDataId, False) - menu.Enable(self.newPhaseId, False) - menu.Enable(self.newCalcId, False) - if clipbranchtype != "fit": - menu.Enable(self.pasteId, False) - menu.Enable(self.pasteLinkId, False) - - return - - def disableMainMenuItems(self): - """Disable main menu items.""" - - menu = self.menuBar - # First disable the shared items - - self.disableSharedMenuItems(menu) - - # Enable everything that can be disabled - # Menus - menu.EnableTop(1, True) - menu.EnableTop(2, True) - menu.EnableTop(3, True) - menu.EnableTop(4, True) - menu.EnableTop(5, True) - menu.EnableTop(6, True) - menu.EnableTop(7, True) - # Menu Items - menu.Enable(self.runFitId, True) - menu.Enable(self.stopFitId, True) - menu.Enable(self.exportFitPDFId, True) - menu.Enable(self.exportFitStruId, True) - menu.Enable(self.exportResId, True) - menu.Enable(self.runCalcId, True) - menu.Enable(self.exportCalcPDFId, True) - menu.Enable(self.printBLId, True) - menu.Enable(self.printBAId, True) - menu.Enable(self.exportNewStruId, True) - menu.Enable(self.plotIStructId, True) - menu.Enable(self.plotFStructId, True) - menu.Enable(self.aboutItem.GetId(), True) - - # Reset the save menus so that they can be disabled if a fit is running. - menu.Enable(self.saveId, pdfguiglobals.isAltered) - menu.Enable(self.saveAsId, True) - menu.Enable(self.openId, True) - menu.Enable(self.recentId, True) - - # Now disable the non-shared menu items - selections = self.treeCtrlMain.GetSelections() - numsel = len(selections) - node = None - if selections: - node = selections[0] - itemtype = self.treeCtrlMain.GetNodeType(node) - else: - itemtype = None - - # MODE - if self.mode != "fitting": - menu.Enable(self.deleteId, False) - menu.Enable(self.copyId, False) - menu.Enable(self.pasteId, False) - menu.Enable(self.runFitId, False) - menu.Enable(self.runCalcId, False) - menu.Enable(self.newFitId, False) - menu.Enable(self.newCalcId, False) - menu.Enable(self.newPhaseId, False) - menu.Enable(self.newDataId, False) - - # FIT - if itemtype != "fit": - menu.Enable(self.runFitId, False) - menu.Enable(self.exportResId, False) - elif numsel > 1: - menu.Enable(self.exportResId, False) - else: - cdata = self.treeCtrlMain.GetControlData(node) - if not cdata.res: - menu.Enable(self.exportResId, False) - - # CALCULATION - if itemtype != "calculation": - menu.Enable(self.runCalcId, False) - menu.Enable(self.exportCalcPDFId, False) - elif numsel > 1: - menu.Enable(self.exportCalcPDFId, False) - else: - cdata = self.treeCtrlMain.GetControlData(node) - if not cdata.Gcalc: - menu.Enable(self.exportCalcPDFId, False) - - # PHASE - if itemtype != "phase": - menu.Enable(self.exportNewStruId, False) - menu.Enable(self.exportFitStruId, False) - menu.Enable(self.printBLId, False) - menu.Enable(self.printBAId, False) - menu.Enable(self.plotIStructId, False) - menu.Enable(self.plotFStructId, False) - elif numsel > 1: - menu.Enable(self.plotIStructId, False) - menu.Enable(self.plotFStructId, False) - menu.Enable(self.printBLId, False) - menu.Enable(self.printBAId, False) - menu.Enable(self.exportFitStruId, False) - menu.Enable(self.exportNewStruId, False) - else: - menu.Enable(self.plotIStructId, True) - cdata = self.treeCtrlMain.GetControlData(node) - if not cdata.refined: - menu.Enable(self.exportFitStruId, False) - menu.Enable(self.plotFStructId, False) - - # DATASET - if itemtype != "dataset": - menu.Enable(self.exportFitPDFId, False) - elif numsel > 1: - menu.Enable(self.exportFitPDFId, False) - else: - cdata = self.treeCtrlMain.GetControlData(node) - if not cdata.Gcalc: - menu.Enable(self.exportFitPDFId, False) - - # Check the run/stop status. - if self.runningDict: - menu.Enable(self.newId, False) - menu.Enable(self.runCalcId, False) - menu.Enable(self.runFitId, False) - menu.Enable(self.saveAsId, False) - menu.Enable(self.saveId, False) - menu.Enable(self.openId, False) - menu.Enable(self.recentId, False) - - # Disallow certain things during a running fit - pnode = self.treeCtrlMain.GetFitRoot(node) - if pnode in self.runningDict.values(): - menu.EnableTop(1, False) - menu.EnableTop(3, False) - menu.EnableTop(4, False) - menu.EnableTop(5, False) - menu.EnableTop(6, False) - else: - menu.Enable(self.stopFitId, False) - - # Show/Hide fitTree - if self.auiManager.GetPane("treeCtrlMain").IsShown(): - self.showFitItem.SetItemLabel("Hide Fit Tree") - else: - self.showFitItem.SetItemLabel("Show Fit Tree") - - # Show/Hide plotPanel - if self.auiManager.GetPane("plotPanel").IsShown(): - self.showPlotItem.SetItemLabel("Hide Plot Control") - else: - self.showPlotItem.SetItemLabel("Show Plot Control") - - # Show/Hide outputPanel - if self.auiManager.GetPane("outputPanel").IsShown(): - self.showOutputItem.SetItemLabel("Hide Output") - else: - self.showOutputItem.SetItemLabel("Show Output") - - # Show/Hide journalPanel - if self.auiManager.GetPane("journalPanel").IsShown(): - self.showJournalItem.SetItemLabel("Hide Journal\tCtrl+j") - else: - self.showJournalItem.SetItemLabel("Show Journal\tCtrl+j") - - return - - # Shared menu items - # The bulk of the code for these methods is in the FitTree class. - def onNewFit(self, event): - """Start a new fit tree. - - A fit is given the name "Fit n", where n is the smallest - positive integer such that the name is not already taken. - """ - newfit = self.treeCtrlMain.AddFit() - # Select the fit item so that the name can be edited - self.treeCtrlMain.Expand(newfit) - self.treeCtrlMain.EditLabel(newfit) - self.treeCtrlMain.SelectItem(newfit) - self.treeCtrlMain.EnsureVisible(newfit) - self.needsSave() - return - - def onCopy(self, event): - """Copy the subtree of the current selected item into the - clipboard.""" - selections = self.treeCtrlMain.GetSelections() - if len(selections) == 1: - self.treeCtrlMain.CopyBranch(selections[0]) - return - - def onPaste(self, event): - """Paste the subtree from the clipboard into the tree.""" - selections = self.treeCtrlMain.GetSelections() - ep = None - if selections: - ep = selections[0] - try: - newnode = self.treeCtrlMain.PasteBranch(ep) - except FitTreeError: - return - self.treeCtrlMain.Expand(newnode) - self.treeCtrlMain.EditLabel(newnode) - self.treeCtrlMain.SelectItem(newnode) - self.treeCtrlMain.EnsureVisible(newnode) - self.needsSave() - return - - def onPasteLink(self, event): - """Paste a copied fit and link it to the original. - - This should only be called on a 'fit' node, and only if the - original 'fit' node, or at least one with the same name as the - original still exists in the tree. - """ - selections = self.treeCtrlMain.GetSelections() - cdata = self.treeCtrlMain.GetClipboard() - fitname = cdata.name - fits = self.treeCtrlMain.GetChildren(self.treeCtrlMain.root) - fitnames = set(map(self.treeCtrlMain.GetItemText, fits)) - if fitname not in fitnames: - return - - ep = None - if selections: - ep = selections[0] - - newnode = self.treeCtrlMain.PasteBranch(ep) - # Now link the fit - newfit = self.treeCtrlMain.GetControlData(newnode) - oldparnames = set(cdata.parameters.keys()) - for parname, par in newfit.parameters.items(): - if parname in oldparnames: - parval = "=%s:%s" % (fitname, parname) - par.setInitial(parval) - - # Make the node ready for editing - self.treeCtrlMain.Expand(newnode) - self.treeCtrlMain.EditLabel(newnode) - self.treeCtrlMain.SelectItem(newnode) - self.treeCtrlMain.EnsureVisible(newnode) - self.needsSave() - return - - def onInsData(self, event): - """Insert a new dataset item. - - This opens up the new data set panel from adddatapanel.py. That - panel is in charge of inserting a new phase. See the module for - details. - """ - selections = self.treeCtrlMain.GetSelections() - if len(selections) == 1: - self.setMode("addingdata") - self.switchRightPanel("adddata") - self.needsSave() - return - - def onInsPhase(self, event): - """Insert a new phase item. - - This opens up the new phase panel from addphasepanel.py. That - panel is in charge of inserting a new phase. See the module for - details. - """ - selections = self.treeCtrlMain.GetSelections() - if len(selections) == 1: - self.setMode("addingphase") - self.switchRightPanel("addphase") - self.needsSave() - return - - def onInsCalc(self, event): - """Insert a new calculation item. - - A calculation is given the name "Calculation n", where n is the - smallest positive integer such that the name is not already - taken. - """ - selections = self.treeCtrlMain.GetSelections() - if len(selections) == 1: - node = selections[0] - fitroot = self.treeCtrlMain.GetFitRoot(node) - newcalc = self.treeCtrlMain.AddCalc(fitroot, "Calculation 1", insertafter=node) - # Select the calculation item so that the name can be edited - self.treeCtrlMain.UnselectAll() - self.treeCtrlMain.EditLabel(newcalc) - self.treeCtrlMain.SelectItem(newcalc) - self.treeCtrlMain.EnsureVisible(newcalc) - self.needsSave() - return - - def onDelete(self, event): - """Remove the subtrees starting from the selected nodes.""" - selections = self.treeCtrlMain.GetSelections() - - # find a node to choose after deletion - fitroot = None - roots = self.treeCtrlMain.GetChildren(self.treeCtrlMain.root) - delroots = list(map(self.treeCtrlMain.GetFitRoot, selections)) - # Find the fit node above the first removed node. - for root in roots: - if root in selections: - break - - fitroot = root - if root in delroots: - break - - # Delete! - if selections: - self.treeCtrlMain.DeleteBranches(selections) - self.needsSave() - - # Select the fit root it it exists. If not, select the first fit node. - # If that does not exist, then go blank. - if fitroot: - self.treeCtrlMain.SelectItem(fitroot) - else: - fits = self.treeCtrlMain.GetChildren(self.treeCtrlMain.root) - if fits: - self.treeCtrlMain.SelectItem(fits[0]) - else: - self.switchRightPanel("blank") - return - - # Main menu items - - def onRun(self, event): - """Run the selected fits/calculations and disable their tree - entries. - - This also runs calculations that are children of a running fit. - """ - # Make sure that the tree is focused. This will trigger the KILL_FOCUS - # events of the other panels. - self.treeCtrlMain.SetFocus() - - selections = self.treeCtrlMain.GetSelections() - # Get the calculation nodes and fit parent nodes from the selections. - nodes = [ - self.treeCtrlMain.GetFitRoot(sel) - for sel in selections - if self.treeCtrlMain.GetNodeType(sel) != "calculation" - ] - nodes.extend([sel for sel in selections if self.treeCtrlMain.GetNodeType(sel) == "calculation"]) - - # Add calculation nodes that are children of fit nodes, and order them - # as if walking down the fit tree - allnodes = [] - for node in nodes: - if node not in allnodes: - allnodes.append(node) - if self.treeCtrlMain.GetNodeType(node) == "fit": - allnodes.extend(self.treeCtrlMain.GetChildren(node)) - - # Disable the current panel - if self.rightPanel.key != "calculation": - self.rightPanel.Enable(False) - - # Change the color of the fitting nodes depending upon their status. See - # updateFittingStatus for the color scheme. Create a dictionary of fits - # for ease of use. - for sel in allnodes: - if self.treeCtrlMain.GetNodeType(sel) == "fit": - self.treeCtrlMain.SetItemBackgroundColour(sel, wx.LIGHT_GREY) - name = self.treeCtrlMain.GetItemText(sel) - self.runningDict[name] = sel - self.needsSave() - - IDlist = list(map(self.treeCtrlMain.GetControlData, allnodes)) - self.control.start(IDlist) - return - - def onStop(self, event): - """Stop all fits. - - This removes all items from the runningDict and changes the - status colors back to wxWHITE. - """ - self.control.stop() - self.needsSave() - return - - def onPreferences(self, event): - """Switch the right panel to the 'preferences' panel. - - The 'preferences' panel uses the 'config' mode. - """ - self.setMode("config") - self.switchRightPanel("preferences") - return - - def onDefaultLayout(self, event): - """Place the fit tree and plot panel in default locations.""" - from diffpy.pdfgui.gui.windowperspective import default - - self.auiManager.LoadPerspective(default) - self.auiManager.Update() - return - - def onShowFit(self, event): - """Make sure the fit tree is visible.""" - if self.auiManager.GetPane("treeCtrlMain").IsShown(): - self.auiManager.GetPane("treeCtrlMain").Hide() - else: - self.auiManager.GetPane("treeCtrlMain").Show() - self.auiManager.Update() - return - - def onShowPlot(self, event): - """Make sure the plot panel is visible.""" - if self.auiManager.GetPane("plotPanel").IsShown(): - self.auiManager.GetPane("plotPanel").Hide() - else: - self.auiManager.GetPane("plotPanel").Show() - self.auiManager.Update() - return - - def onShowOutput(self, event): - """Make sure the output panel is visible.""" - if self.auiManager.GetPane("outputPanel").IsShown(): - self.auiManager.GetPane("outputPanel").Hide() - else: - self.auiManager.GetPane("outputPanel").Show() - self.auiManager.Update() - return - - def onShowJournal(self, event): - """Bring up or hide the journal window.""" - if self.auiManager.GetPane("journalPanel").IsShown(): - self.auiManager.GetPane("journalPanel").Hide() - else: - self.auiManager.GetPane("journalPanel").Show() - self.journalPanel.refresh() - self.journalPanel.SetFocus() - self.auiManager.Update() - return - - def onPlotIStruct(self, event): - """Plots the phase structure. - - Opens Atomeye and plots the structure. - """ - return self._plotStruct("initial") - - def onPlotFStruct(self, event): - """Plots the phase structure. - - Opens Atomeye and plots the structure. - """ - return self._plotStruct("refined") - - def _plotStruct(self, stype): - """Helper for onPlotFStruct and onPlotIStruct.""" - selections = self.treeCtrlMain.GetSelections() - if selections: - node = selections[0] - itemtype = self.treeCtrlMain.GetNodeType(node) - if itemtype == "phase": - # panel = self.dynamicPanels['phase'] - cdata = self.treeCtrlMain.GetControlData(node) - stru = getattr(cdata, stype) - viewer = structureviewer.getStructureViewer() - viewer.plot(stru) - return - - def onPrintBL(self, event): - """Print the bond lengths of a selected structure to the output - panel.""" - from diffpy.pdfgui.gui.bondlengthdialog import BondLengthDialog - - selections = self.treeCtrlMain.GetSelections() - if selections: - node = selections[0] - itemtype = self.treeCtrlMain.GetNodeType(node) - if itemtype == "phase": - # panel = self.dynamicPanels['phase'] - cdata = self.treeCtrlMain.GetControlData(node) - S = cdata.refined - if not S: - S = cdata.initial - - dlg = BondLengthDialog(self) - dlg.setStructure(S) - - if dlg.ShowModal() == wx.ID_OK: - fitroot = self.treeCtrlMain.GetFitRoot(node) - fitting = self.treeCtrlMain.GetControlData(fitroot) - - self.control.redirectStdout() - - # Figure out what to calculate. If the upper and lower bound - # is too small, it is assumed that a single distance is - # intended to be calculated. - a = dlg.a - b = dlg.b - ea = dlg.ea - eb = dlg.eb - lb = min(dlg.lb, dlg.ub) - ub = max(dlg.lb, dlg.ub) - - if lb == ub == 0: - fitting.outputBondLengthAtoms(S, a, b) - else: - fitting.outputBondLengthTypes(S, ea, eb, lb, ub) - - self.updateOutput() - dlg.Destroy() - return - - def onPrintBA(self, event): - """Print the bond angles of a selected structure to the output - panel.""" - from diffpy.pdfgui.gui.bondangledialog import BondAngleDialog - - selections = self.treeCtrlMain.GetSelections() - if selections: - node = selections[0] - itemtype = self.treeCtrlMain.GetNodeType(node) - if itemtype == "phase": - # panel = self.dynamicPanels['phase'] - cdata = self.treeCtrlMain.GetControlData(node) - S = cdata.refined - if not S: - S = cdata.initial - - dlg = BondAngleDialog(self) - dlg.setStructure(S) - - if dlg.ShowModal() == wx.ID_OK: - fitroot = self.treeCtrlMain.GetFitRoot(node) - fitting = self.treeCtrlMain.GetControlData(fitroot) - self.control.redirectStdout() - fitting.outputBondAngle(S, dlg.a, dlg.b, dlg.c) - self.updateOutput() - dlg.Destroy() - - def onQuickPlot(self, event): - """Quickly plot information for the selected node.""" - selections = self.treeCtrlMain.GetSelections() - if len(selections) != 1: - return - node = selections[0] - refs = [self.treeCtrlMain.GetControlData(node)] - nodetype = self.treeCtrlMain.GetNodeType(selections[0]) - if nodetype == "dataset": - xval = "r" - # For quick plotting, keep this order. Gdiff must be the last. - yvals = ["Gtrunc", "Gcalc", "Gdiff"] - soffset = self.plotPanel.offsetTextCtrl.GetValue() - offset = 0 - if soffset: - offset = float(self.plotPanel.offsetTextCtrl.GetValue()) - self.control.plot(xval, yvals, refs, shift=offset) - elif nodetype == "calculation": - xval = "r" - yvals = ["Gcalc"] - self.control.plot(xval, yvals, refs, shift=0) - elif nodetype == "phase": - cdata = self.treeCtrlMain.GetControlData(node) - if cdata.refined: - self.onPlotFStruct(event) - else: - self.onPlotIStruct(event) - return - - def onAbout(self, event): - dlg = DialogAbout(self) - # dlg.CenterOnScreen() - dlg.ShowModal() - dlg.Destroy() - return - - def onRequest(self, event): - dlg = ErrorReportDialog(self) - # dlg.errorReport = True - dlg.ShowModal() - dlg.Destroy() - return - - def onCommunity(self, event): - """Open the browser and go to the diffpy-users Google Group.""" - import webbrowser - - try: - webbrowser.open(USERSMAILINGLIST) - except Exception as e: - errorinfo = 'Failed to open "%s"' % e - raise ControlError(errorinfo) - return - - def onNew(self, event): - """Create a new project.""" - retval = self.checkForSave() - if retval != wx.ID_CANCEL: - self.control.stop() - self.control.close() - self.treeCtrlMain.DeleteAllItems() - self.treeCtrlMain.InitializeTree() - self.switchRightPanel("welcome") - self.plotPanel.refresh() - self.needsSave(False) - self.fullpath = "" - self.outputPanel.clearText() - self.journalPanel.refresh() - self.updateTitle() - return - - def onOpen(self, event): - """Open a file dialog so an existing project can be opened.""" - retval = self.checkForSave() - if retval != wx.ID_CANCEL: - dir, filename = os.path.split(self.fullpath) - if not dir: - dir = self.workpath - matchstring = "PDFgui project files (*.ddp)|*.ddp;*.ddp3" - d = wx.FileDialog(None, "Choose a file", dir, "", matchstring) - if d.ShowModal() == wx.ID_OK: - fullpath = d.GetPath() - # Load this file into the control center. - self.control.stop() - self.control.close() - treelist = self.control.load(fullpath) - self.treeCtrlMain.ExtendProjectTree(treelist) - self.setMode("fitting") - self.switchRightPanel("welcome") - - self.fullpath = fullpath - self.workpath = os.path.dirname(fullpath) - self.fileHistory.AddFileToHistory(fullpath) - self.needsSave(False) - - self.outputPanel.clearText() - self.journalPanel.refresh() - self.updateTitle() - d.Destroy() - return - - def onSave(self, event): - """Save the project to a predetermined location.""" - # Make sure that the tree is focused. This will trigger the KILL_FOCUS - # events of the other panels. - self.treeCtrlMain.SetFocus() - - code = wx.ID_OK - if self.fullpath: - self.control.save(self.fullpath) - self.fileHistory.AddFileToHistory(self.fullpath) - self.needsSave(False) - pass - else: - code = self.onSaveAs(event) - return code - - def onSaveAs(self, event): - """Open a save dialog so the current project can be saved.""" - # Make sure that the tree is focused. This will trigger the KILL_FOCUS - # events of the other panels. - self.treeCtrlMain.SetFocus() - - matchstring = "PDFgui project files (*.ddp3)|*.ddp3|All Files|*" - dir, filename = os.path.split(self.fullpath) - if not dir: - dir = self.workpath - d = wx.FileDialog( - None, - "Save as...", - dir, - filename or "project.ddp3", - matchstring, - wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT, - ) - code = d.ShowModal() - if code == wx.ID_OK: - self.fullpath = d.GetPath() - if len(self.fullpath) < 5 or self.fullpath[-5:] != ".ddp3": - self.fullpath += ".ddp3" - self.workpath = os.path.dirname(self.fullpath) - self.fileHistory.AddFileToHistory(self.fullpath) - # Save the file - self.control.save(self.fullpath) - self.needsSave(False) - self.updateTitle() - d.Destroy() - return code - - def onQuit(self, event): - """Shut down gracefully.""" - # Make sure that we have focus. - self.SetFocus() - retval = self.checkForSave() - if retval != wx.ID_CANCEL: - self.quitting = True - self.updateConfiguration() - self.writeConfiguration() - self.control.exit() - self.auiManager.UnInit() - self.Destroy() - return - - def onMRUFile(self, event): - """Open a recently used file.""" - index = event.GetId() - wx.ID_FILE1 - filename = self.fileHistory.GetHistoryFile(index) - retval = self.checkForSave() - if retval != wx.ID_CANCEL: - self.control.stop() - self.control.close() - try: - treelist = self.control.load(filename) - self.treeCtrlMain.ExtendProjectTree(treelist) - self.setMode("fitting") - self.switchRightPanel("welcome") - self.needsSave(False) - self.outputPanel.clearText() - self.journalPanel.refresh() - self.fullpath = filename - self.workpath = os.path.dirname(self.fullpath) - self.fileHistory.AddFileToHistory(self.fullpath) - self.updateTitle() - except ControlError as e: - self.fileHistory.RemoveFileFromHistory(index) - self.updateConfiguration() - self.writeConfiguration() - raise e - return - - def onExportRes(self, event): - """Export the results file for the selected calculation.""" - selections = self.treeCtrlMain.GetSelections() - if not selections: - return - node = selections[0] - nodetype = self.treeCtrlMain.GetNodeType(node) - if nodetype != "fit": - return - cdata = self.treeCtrlMain.GetControlData(node) - name = self.treeCtrlMain.GetItemText(node) - basename = ".".join(name.split(".")[:-1]) or name - matchstring = "PDFgui results files (*.res)|*.res|All Files|*" - d = wx.FileDialog( - None, - "Save as...", - self.workpath, - basename, - matchstring, - wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT, - ) - if d.ShowModal() == wx.ID_OK: - path = d.GetPath() - self.workpath, savename = os.path.split(path) - # Add the right extension if it doesn't already have it. - if len(savename) < 3 or savename[-3:] != "res": - savename += ".res" - path = os.path.join(self.workpath, savename) - outfile = open(path, "w") - outfile.write(cdata.res) - outfile.close() - d.Destroy() - return - - def onRSeries(self, event): - """Open up the r-series panel.""" - self.setMode("rseries") - self.switchRightPanel("rseries") - return - - def onTSeries(self, event): - """Open up the temperature series panel.""" - self.setMode("tseries") - self.switchRightPanel("tseries") - return - - def onDSeries(self, event): - """Open up the doping series panel.""" - self.setMode("dseries") - self.switchRightPanel("dseries") - return - - def onExportNewStruct(self, event): - """Export a structure that was created from scratch.""" - extlist = ["stru", "cif", "pdb", "xyz", "xyz", ""] - fmtlist = ["pdffit", "cif", "pdb", "xyz", "rawxyz", "xcfg"] - selections = self.treeCtrlMain.GetSelections() - if not selections: - return - node = selections[0] - nodetype = self.treeCtrlMain.GetNodeType(node) - if nodetype != "phase": - return - cdata = self.treeCtrlMain.GetControlData(node) - # branchname = self.treeCtrlMain.GetBranchName(node) - name = self.treeCtrlMain.GetItemText(node) - basename = ".".join(name.split(".")[:-1]) or name - matchstring = ( - "PDFfit structure file (*.stru)|*.stru|" - "Crystallographic Information File (*.cif)|*.cif|" - "Protein Data Bank file (*.pdb)|*.pdb|" - "Labeled coordinate file (*.xyz)|*.xyz|" - "Raw coordinate file (*.xyz)|*.xyz|" - "AtomEye configuration file|*" - ) - d = wx.FileDialog( - None, - "Save as...", - self.workpath, - basename, - matchstring, - wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT, - ) - if d.ShowModal() == wx.ID_OK: - i = d.GetFilterIndex() - path = d.GetPath() - self.workpath, savename = os.path.split(path) - # Add the right extension if the file needs it. - if len(savename) < 3 or (extlist[i] and savename[-3:] != extlist[i][-3:]): - savename += ".%s" % extlist[i] - path = os.path.join(self.workpath, savename) - text = cdata.initial.writeStr(fmtlist[i]) - outfile = open(path, "w") - outfile.write(text) - outfile.close() - d.Destroy() - return - - def onExportStruct(self, event): - """Export a fit structure.""" - extlist = ["stru", "cif", "pdb", "xyz", "xyz", ""] - fmtlist = ["pdffit", "cif", "pdb", "xyz", "rawxyz", "xcfg"] - selections = self.treeCtrlMain.GetSelections() - if not selections: - return - node = selections[0] - nodetype = self.treeCtrlMain.GetNodeType(node) - if nodetype != "phase": - return - cdata = self.treeCtrlMain.GetControlData(node) - # branchname = self.treeCtrlMain.GetBranchName(node) - name = self.treeCtrlMain.GetItemText(node) - basename = ".".join(name.split(".")[:-1]) or name - matchstring = ( - "PDFfit structure file (*.stru)|*.stru|" - "Crystallographic Information File (*.cif)|*.cif|" - "Protein Data Bank file (*.pdb)|*.pdb|" - "Labeled coordinate file (*.xyz)|*.xyz|" - "Raw coordinate file (*.xyz)|*.xyz|" - "AtomEye configuration file|*" - ) - d = wx.FileDialog( - None, - "Save as...", - self.workpath, - basename, - matchstring, - wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT, - ) - if d.ShowModal() == wx.ID_OK: - i = d.GetFilterIndex() - path = d.GetPath() - self.workpath, savename = os.path.split(path) - # Add the right extension if the file needs it. - if len(savename) < 3 or (extlist[i] and savename[-3:] != extlist[i][-3:]): - savename += ".%s" % extlist[i] - path = os.path.join(self.workpath, savename) - text = cdata.refined.writeStr(fmtlist[i]) - outfile = open(path, "w") - outfile.write(text) - outfile.close() - d.Destroy() - return - - def onExportPDF(self, event): - """Export a fit PDF.""" - selections = self.treeCtrlMain.GetSelections() - if not selections: - return - node = selections[0] - nodetype = self.treeCtrlMain.GetNodeType(node) - if nodetype != "dataset": - return - cdata = self.treeCtrlMain.GetControlData(node) - # branchname = self.treeCtrlMain.GetBranchName(node) - name = self.treeCtrlMain.GetItemText(node) - basename = ".".join(name.split(".")[:-1]) or name - matchstring = "PDF fit data file (*.fgr)|*.fgr|All Files|*" - d = wx.FileDialog( - None, - "Save as...", - self.workpath, - basename, - matchstring, - wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT, - ) - if d.ShowModal() == wx.ID_OK: - path = d.GetPath() - self.workpath, savename = os.path.split(path) - # Add the right extension if it doesn't already have it. - if len(savename) < 3 or savename[-3:] != "fgr": - savename += ".fgr" - path = os.path.join(self.workpath, savename) - cdata.writeCalc(path) - d.Destroy() - return - - def onSaveCalc(self, event): - """Export a calculated PDF.""" - selections = self.treeCtrlMain.GetSelections() - if not selections: - return - node = selections[0] - nodetype = self.treeCtrlMain.GetNodeType(node) - if nodetype != "calculation": - return - cdata = self.treeCtrlMain.GetControlData(node) - name = self.treeCtrlMain.GetItemText(node) - basename = ".".join(name.split(".")[:-1]) or name - matchstring = "PDF calculated data file (*.cgr)|*.cgr|All Files|*" - d = wx.FileDialog( - None, - "Save as...", - self.workpath, - basename, - matchstring, - wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT, - ) - if d.ShowModal() == wx.ID_OK: - path = d.GetPath() - self.workpath, savename = os.path.split(path) - # Add the right extension if it doesn't already have it. - if len(savename) < 3 or savename[-3:] != "cgr": - savename += ".cgr" - path = os.path.join(self.workpath, savename) - cdata.write(path) - d.Destroy() - return - - def onDocumentation(self, event): - """Show information about the documentation.""" - import webbrowser - - webbrowser.open(docMainFile) - return - - # MISC INTERACTION ITEMS - def showMessage(self, info, title="PDF Control Error"): - """ShowMessage(self, info) --> tell user about an exception and - so on. - - title -- window title - info -- message - """ - dlg = wx.MessageDialog(self, info, title, wx.OK | wx.ICON_ERROR) - dlg.ShowModal() - dlg.Destroy() - return - - # control items - def lock(self): - if not wx.IsMainThread(): - wx.MutexGuiEnter() - - def unlock(self): - if not wx.IsMainThread(): - wx.MutexGuiLeave() - - def postEvent(self, type, info): - """This method is called by the control. - - Whenever the control needs to communicate directly with the gui - it can call this method. The event is processed by onCustom and - then handled by the gui on its own terms. - """ - event = PDFCustomEvent() - event.type = type - event.info = info - wx.PostEvent(self, event) - return - - def onCustom(self, event): - """This handles the custom events sent by the control.""" - if event.type == self.ERROR: - self.showMessage(event.info) - elif event.type == self.UPDATE: - # job is a fitting or a calculation - job = event.info - self.updateFittingStatus(job) - elif event.type == self.OUTPUT: - self.updateOutput() - elif event.type == self.PLOTNOW: - # job is a fitting or a calculation with a new data to plot. - job = event.info - for plot in self.control.plots: - plot.notify(job) - return - - def updateFittingStatus(self, job): - """Update the fitting status. - - This will alter the local member runningDict so that the running items - cannot be altered. The following status ids are defined in the fitting - module. Some are given a color which gives the user an indication of the - fit status. job is actually a fitting or a calculation object. - - Fit status - INITIALIZED -- 'LIGHT GRAY' - CONNECTED -- 'GREEN' - CONFIGURED -- 'GREEN' - DONE -- 'WHITE' - - JOB Status - VOID - QUEUED - RUNNING - PAUSED - """ - from diffpy.pdfgui.control.fitting import Fitting - - if isinstance(job, Fitting): - name = job.name - fitStatus = job.fitStatus - jobStatus = job.jobStatus - try: - node = self.runningDict[name] - except KeyError: - return - if jobStatus == Fitting.RUNNING: - if fitStatus == Fitting.INITIALIZED: - self.treeCtrlMain.SetItemBackgroundColour(node, wx.LIGHT_GREY) - elif fitStatus in (Fitting.CONNECTED, Fitting.CONFIGURED): - self.treeCtrlMain.SetItemBackgroundColour(node, wx.GREEN) - elif jobStatus == Fitting.VOID: - self.treeCtrlMain.SetItemBackgroundColour(node, wx.WHITE) - selections = self.treeCtrlMain.GetSelections() - if len(selections) == 1: - # Enable whatever panel is currently being viewed. - self.rightPanel.Enable() - if node == selections[0]: - self.rightPanel.refresh() - self.runningDict.pop(name, None) - self.needsSave() - - # Update the menus and toolbars whenever an event is posted. - self.disableMainMenuItems() - self.updateToolbar() - return - - def updateOutput(self): - """Update text in outputPanel with text in stdout.""" - self.outputPanel.updateText(self.control.getEngineOutput()) - return - - -# end of class MainPanel diff --git a/src/diffpy/pdfgui/gui/menuitems.txt b/src/diffpy/pdfgui/gui/menuitems.txt deleted file mode 100644 index a5cacb18..00000000 --- a/src/diffpy/pdfgui/gui/menuitems.txt +++ /dev/null @@ -1,89 +0,0 @@ -Menus for PDFgui - -File - _____________________________ - Open Project Ctrl-o - Recent Files > -- Contains list of recent projects - ----------------------------- - Save Project Ctrl-s - Save Project as - ----------------------------- - Close Project Ctrl-x - Quit Ctrl-q - _____________________________ - - -Edit - _____________________________ - Journal Ctrl-j - ----------------------------- - Preferences -- Contains structure viewer configuration - _____________________________ - - -Fits - _____________________________ - New Fit - Delete Fit -- Only when fit is selected - Duplicate Fit -- Only when fit is selected - Move Fit -- Only when fit is selected - ----------------------------- - Run Selected Fits -- Only when fit is selected - Stop Fitting - ----------------------------- - Save Fit PDF(s) -- Brings up selection dialog - Save Fit Structure(s) -- Brings up selection dialog - Save Results - ----------------------------- - Paste Copied Data - ----------------------------- - Macros > -- Temperature and doping series macros - _____________________________ - - -Calculations - _____________________________ - New Calculation - Delete Calculation -- Only when calculation is selected - Duplicate Calculation -- Only when calculation is selected - Move Calculation -- Only when calculation is selected - ----------------------------- - Run Selected Calculations -- Only when fit is selected - ----------------------------- - Save Calculated PDF - ----------------------------- - Paste Copied Structure - _____________________________ - - -Data - _____________________________ - Import PDF Data - Export PDF Data -- Only when data is selected - ----------------------------- - Copy PDF Data -- Only when data is selected - Delete PDF Data -- Only when data is selected - ----------------------------- - Select Duplicate Data -- Only when data is selected - ----------------------------- - Paste Copied Phase - _____________________________ - - -Structures - _____________________________ - Import Structure - Export Structure - ----------------------------- - Select Duplicate Phases -- Only when structure is selected - ----------------------------- - Copy Phase -- Only when structure is selected - Delete Phase -- Only when structure is selected - _____________________________ - - -Help - _____________________________ - Documentation - About - _____________________________ diff --git a/src/diffpy/pdfgui/gui/outputpanel.py b/src/diffpy/pdfgui/gui/outputpanel.py deleted file mode 100644 index 17e1c253..00000000 --- a/src/diffpy/pdfgui/gui/outputpanel.py +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env python -# -*- coding: UTF-8 -*- -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2007 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Jiwu Liu, Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -# generated by wxGlade 0.9.3 on Fri Jul 19 16:04:33 2019 - -import wx - -from diffpy.pdfgui.gui.pdfpanel import PDFPanel - - -class OutputPanel(wx.Panel, PDFPanel): - def __init__(self, *args, **kwds): - # begin wxGlade: OutputPanel.__init__ - kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL - wx.Panel.__init__(self, *args, **kwds) - self.outputTextCtrl = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.HSCROLL | wx.TE_MULTILINE | wx.TE_READONLY) - - self.__set_properties() - self.__do_layout() - # end wxGlade - self.__customProperties() - - def __set_properties(self): - # begin wxGlade: OutputPanel.__set_properties - pass - # end wxGlade - return - - def __do_layout(self): - # begin wxGlade: OutputPanel.__do_layout - sizer_1 = wx.BoxSizer(wx.VERTICAL) - sizer_1.Add(self.outputTextCtrl, 1, wx.ALL | wx.EXPAND, 0) - self.SetSizer(sizer_1) - sizer_1.Fit(self) - self.Layout() - # end wxGlade - - def __customProperties(self): - """Set the custom properties.""" - # Set the font to monospace - ftxt = self.outputTextCtrl.GetFont() - font = wx.Font( - ftxt.GetPointSize(), - wx.FONTFAMILY_TELETYPE, - ftxt.GetStyle(), - ftxt.GetWeight(), - ) - self.outputTextCtrl.SetFont(font) - return - - def clearText(self): - """Clear the text from the output control.""" - self.outputTextCtrl.Clear() - return - - def updateText(self, text): - """Update the text in the window.""" - self.outputTextCtrl.AppendText(text) - return - - def refresh(self): - pass - - -# end of class OutputPanel diff --git a/src/diffpy/pdfgui/gui/paneltest.py b/src/diffpy/pdfgui/gui/paneltest.py deleted file mode 100644 index 5adda3b9..00000000 --- a/src/diffpy/pdfgui/gui/paneltest.py +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env python -# -*- coding: ISO-8859-1 -*- -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -# generated by wxGlade 0.4 on Tue Feb 21 12:00:30 2006 - -import wx - -# from diffpy.pdfgui.gui.mainframe import MainPanel -# from diffpy.pdfgui.gui.journalpanel import JournalPanel -# from diffpy.pdfgui.gui.datasetconfigurepanel import DataSetConfigurePanel -# from diffpy.pdfgui.gui.fitnotebookpanel import FitNotebookPanel -# from diffpy.pdfgui.gui.rseriespanel import RSeriesPanel -from diffpy.pdfgui.gui.temperatureseriespanel import TemperatureSeriesPanel - - -class MyFrame(wx.Frame): - def __init__(self, *args, **kwds): - # begin wxGlade: MyFrame.__init__ - kwds["style"] = wx.DEFAULT_FRAME_STYLE - wx.Frame.__init__(self, *args, **kwds) - # self.window_1 = MainPanel(self, -1) - # self.window_1 = JournalPanel(self, -1) - # self.window_1 = DataSetConfigurePanel(self, -1) - # self.window_1 = FitNotebookPanel(self, -1) - # self.window_1 = RSeriesPanel(self, -1) - self.window_1 = TemperatureSeriesPanel(self, -1) - - self.__set_properties() - self.__do_layout() - # end wxGlade - - def __set_properties(self): - # begin wxGlade: MyFrame.__set_properties - self.SetTitle("panel test") - # end wxGlade - - def __do_layout(self): - # begin wxGlade: MyFrame.__do_layout - sizer_3 = wx.BoxSizer(wx.VERTICAL) - sizer_3.Add(self.window_1, 1, wx.EXPAND, 0) - self.SetAutoLayout(True) - self.SetSizer(sizer_3) - sizer_3.Fit(self) - sizer_3.SetSizeHints(self) - self.Layout() - # end wxGlade - self.SetSize((700, 120)) - - -# end of class MyFrame - - -class MyApp(wx.App): - def OnInit(self): - frame_1 = MyFrame(None, -1, "") - self.SetTopWindow(frame_1) - frame_1.Show() - return True - - -# end of class MyApp - -if __name__ == "__main__": - app = MyApp(0) - app.MainLoop() diff --git a/src/diffpy/pdfgui/gui/parameterspanel.py b/src/diffpy/pdfgui/gui/parameterspanel.py deleted file mode 100644 index 6a300f7a..00000000 --- a/src/diffpy/pdfgui/gui/parameterspanel.py +++ /dev/null @@ -1,482 +0,0 @@ -#!/usr/bin/env python -# -*- coding: UTF-8 -*- -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Dmitriy Bryndin, Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - - -# Parameters panel -# Dmitriy Bryndin - - -# generated by wxGlade 0.9.3 on Fri Jul 19 16:04:38 2019 - -import wx.grid - -from diffpy.pdfgui.gui.pdfpanel import PDFPanel -from diffpy.pdfgui.gui.wxextensions.autowidthlabelsgrid import AutoWidthLabelsGrid -from diffpy.utils.wx import gridutils - - -class ParametersPanel(wx.Panel, PDFPanel): - """GUI Panel, parameters viewer/editor. - - Data members: - parameters -- parameters dictionary - _focusedText -- value of a cell before it changes - """ - - def __init__(self, *args, **kwds): - PDFPanel.__init__(self) - # begin wxGlade: ParametersPanel.__init__ - kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL - wx.Panel.__init__(self, *args, **kwds) - self.grid_parameters = AutoWidthLabelsGrid(self, wx.ID_ANY, size=(1, 1)) - self.button_applyparameters = wx.Button(self, wx.ID_ANY, "Apply parameters") - - self.__set_properties() - self.__do_layout() - - self.Bind(wx.grid.EVT_GRID_CMD_CELL_CHANGED, self.onCellChange, self.grid_parameters) - self.Bind( - wx.grid.EVT_GRID_CMD_CELL_LEFT_CLICK, - self.onCellLeftClick, - self.grid_parameters, - ) - self.Bind( - wx.grid.EVT_GRID_CMD_CELL_RIGHT_CLICK, - self.onCellRightClick, - self.grid_parameters, - ) - self.Bind(wx.grid.EVT_GRID_CMD_EDITOR_SHOWN, self.onEditorShown, self.grid_parameters) - self.Bind( - wx.grid.EVT_GRID_CMD_RANGE_SELECT, - self.onGridRangeSelect, - self.grid_parameters, - ) - self.Bind(wx.EVT_BUTTON, self.onApplyParameters, self.button_applyparameters) - # end wxGlade - self.__customProperties() - return - - def __set_properties(self): - # begin wxGlade: ParametersPanel.__set_properties - self.grid_parameters.CreateGrid(0, 3) - self.grid_parameters.EnableDragRowSize(0) - self.grid_parameters.SetColLabelValue(0, "Initial") - self.grid_parameters.SetColLabelValue(1, "Fixed") - self.grid_parameters.SetColLabelValue(2, "Refined") - # end wxGlade - - # set the second column to display boolean values - attr = wx.grid.GridCellAttr() - attr.SetEditor(wx.grid.GridCellBoolEditor()) - attr.SetRenderer(wx.grid.GridCellBoolRenderer()) - self.grid_parameters.SetColAttr(1, attr) - - def __do_layout(self): - # begin wxGlade: ParametersPanel.__do_layout - sizer_1 = wx.BoxSizer(wx.VERTICAL) - sizer_buttons = wx.BoxSizer(wx.HORIZONTAL) - sizer_1.Add(self.grid_parameters, 1, wx.EXPAND, 0) - sizer_buttons.Add((20, 20), 1, 0, 0) - sizer_buttons.Add(self.button_applyparameters, 0, wx.ALL, 5) - sizer_1.Add(sizer_buttons, 0, wx.EXPAND, 0) - self.SetSizer(sizer_1) - sizer_1.Fit(self) - self.Layout() - # end wxGlade - - # ######################################################################## - # Misc Methods - - def __customProperties(self): - """Custom properties for the panel.""" - self._focusedText = None - self._selectedCells = [] - self.parameters = {} - self.fit = None - return - - def refresh(self): - """Refreshes wigets on the panel.""" - # # Update the parameters dictionary - # self.fitting.updateParameters() - - nRows = len(self.parameters) - - # update the grid - # remove all rows and create new ones - self.grid_parameters.BeginBatch() - gridrows = self.grid_parameters.GetNumberRows() - if gridrows != 0: - self.grid_parameters.DeleteRows(numRows=gridrows) - self.grid_parameters.InsertRows(numRows=nRows) - # self.grid_parameters.SetColFormatBool(1) - - i = 0 - keys = sorted(self.parameters.keys()) - for key in keys: - # parameter index - self.grid_parameters.SetRowLabelValue(i, str(self.parameters[key].idx)) - # initial value - self.grid_parameters.SetCellValue(i, 0, str(self.parameters[key].initialStr())) - # flag "fixed" - # NOTE: for bool type of cells use '0' or '1' as False and True - self.grid_parameters.SetCellValue(i, 1, str(int(self.parameters[key].fixed))) - # refined value - self.grid_parameters.SetReadOnly(i, 2) - if self.parameters[key].refined is None: - self.grid_parameters.SetCellValue(i, 2, "") - else: - self.grid_parameters.SetCellValue(i, 2, str(self.parameters[key].refined)) - i += 1 - - self.grid_parameters.AutosizeLabels() - self.grid_parameters.AutoSizeColumns() - self.grid_parameters.EndBatch() - - def onCellLeftClick(self, event): # wxGlade: ParametersPanel. - """Toggle a fix/free cell when clicked.""" - r = event.GetRow() - c = event.GetCol() - # Only proceed if there is no selection and - # this click has no keyboard modifiers. - ignorethis = c != 1 or self.grid_parameters.IsSelection() or event.ShiftDown() or event.ControlDown() - if ignorethis: - # do standard click event handling - event.Skip() - return - # We consume the event here. This prevents focusing the clicked - # cell after a click, but that is not necessary for a checkbox. - state = int(self.grid_parameters.GetCellValue(r, c) or 0) - self.applyCellChange(r, c, not state) - return - - def onGridRangeSelect(self, event): # wxGlade: ParametersPanel. - """Handle range selections. - - This is needed to properly handle simple left-clicking of - fix/free cells. It serves no other purpose. - """ - event.Skip() - return - - def onCellRightClick(self, event): # wxGlade: ParametersPanel. - # Popup the menu. If an item is selected then its handler - # will be called before PopupMenu returns. - r = event.GetRow() - c = event.GetCol() - # If the right-clicked node is not part of a group, then make sure that - # it is the only selected cell. - append = False - if self.grid_parameters.IsInSelection(r, c): - append = True - self.grid_parameters.SelectBlock(r, c, r, c, append) - self.popupMenu(self.grid_parameters, event.GetPosition().x, event.GetPosition().y) - event.Skip() - return - - def onEditorShown(self, event): # wxGlade: ParametersPanel. - i = event.GetRow() - j = event.GetCol() - self._focusedText = self.grid_parameters.GetCellValue(i, j) - self._selectedCells = gridutils.getSelectedCells(self.grid_parameters) - event.Skip() - return - - def onCellChange(self, event): # wxGlade: ParametersPanel. - # NOTE: be careful with refresh() => recursion! operations on grid will - # call onCellChange - # Note that this method does not get called when a fix/free cell is - # selected. - i = event.GetRow() - j = event.GetCol() - - if self._focusedText is None: - return - self._focusedText = None - - value = self.grid_parameters.GetCellValue(i, j) - # Verify the value. This is done here since if it is allowed to be done - # in fillCells, then an error dialog will be thrown for each point - # in the loop. - try: - # Check that the value is valid - if j == 0: - converted = value - try: - converted = int(value) - except ValueError: - pass - key = int(self.grid_parameters.GetRowLabelValue(i)) - temp = self.parameters[key].initialValue() - if temp != converted: - self.parameters[key].setInitial(converted) - self.mainFrame.needsSave() - - # If we made it this far, then we can continue. - self.fillCells(self._selectedCells, value) - self.grid_parameters.AutoSizeColumns(0) - finally: - # self.refresh() - event.Skip() - - return - - def applyCellChange(self, row, col, value): - """Update parameters dictionary according to a change in a cell. - - This also updates the cell, if possible, but not the grid. Changes to - the cell that may affect the grid, such as inserting text that is wider - than the column width, must be handled elsewhere. - - row -- row - col -- column - value -- new value - """ - key = int(self.grid_parameters.GetRowLabelValue(row)) - if col == 0: # initial value - temp = self.parameters[key].initialValue() - if temp != value: - self.parameters[key].setInitial(value) - self.grid_parameters.SetCellValue(row, 0, str(float(value))) - self.mainFrame.needsSave() - - elif col == 1: # flag "fixed" - temp = bool(self.parameters[key].fixed) - value = bool(int(value)) - if temp is not value: - self.parameters[key].fixed = value - self.grid_parameters.SetCellValue(row, 1, str(int(value))) - self.mainFrame.needsSave() - - return - - def popupMenu(self, window, x, y): - """Opens a popup menu. - - window -- window, where to popup a menu - x -- x coordinate - y -- y coordinate - """ - # only do this part the first time so the events are only bound once - if not hasattr(self, "did_popupIDs"): - self.did_popupIDs = True - self.popupID1 = wx.NewIdRef() - self.popupID2 = wx.NewIdRef() - self.popupID3 = wx.NewIdRef() - - self.Bind(wx.EVT_MENU, self.onPopupFixFree, id=self.popupID1) - self.Bind(wx.EVT_MENU, self.onPopupCopyRefinedToInitial, id=self.popupID2) - self.Bind(wx.EVT_MENU, self.onPopupRenameParameters, id=self.popupID3) - - # make a menu - menu = wx.Menu() - - # add some other items - menu.Append(self.popupID1, "Fix / Free") - menu.Append(self.popupID2, "Copy Refined To Initial") - menu.Append(self.popupID3, "Rename Parameters") - - # Popup the menu. If an item is selected then its handler - # will be called before PopupMenu returns. - window.PopupMenu(menu, wx.Point(x, y)) - menu.Destroy() - return - - # Popup menu events ################################################## - def onPopupFill(self, event): - """Fills cells selected in the grid with a new value.""" - - # NOTE: GetSelectedCells returns only SINGLE selected cells, not blocks or row/columns ! - if self.grid_parameters.IsSelection(): - dlg = wx.TextEntryDialog(self, "New value:", "Fill Selected Cells", "") - - if dlg.ShowModal() == wx.ID_OK: - value = dlg.GetValue() - - rows = self.grid_parameters.GetNumberRows() - cols = self.grid_parameters.GetNumberCols() - - for i in range(rows): - for j in range(cols): - inSelection = self.grid_parameters.IsInSelection(i, j) - valueChanged = value != self.grid_parameters.GetCellValue(i, j) - if inSelection and valueChanged: - self.applyCellChange(i, j, value) - - # self.refresh() - - dlg.Destroy() - event.Skip() - - def onPopupFixFree(self, event): - """Fixes parameters with selected cells.""" - # NOTE: GetSelectedCells returns only SINGLE selected cells, not blocks - # or row/columns ! - seldict = {} - if self.grid_parameters.IsSelection(): - - indices = self.getSelectedParameters() - for row in indices: - state = self.grid_parameters.GetCellValue(row, 1) - state = bool(int(state.strip() or "0")) - seldict[row] = state - - # Find the majority state - nfixed = sum(1 for st in seldict.values() if st) - nfree = len(seldict) - nfixed - newstate = True # fixed - if nfree < nfixed: - # free all parameters - newstate = False - - for row in seldict: - self.applyCellChange(row, 1, newstate) - event.Skip() - return - - def onPopupCopyRefinedToInitial(self, event): - """Copy refined parameter to initial value.""" - if not self.grid_parameters.IsSelection(): - event.Skip() - return - for row in self.getSelectedParameters(): - refined = self.grid_parameters.GetCellValue(row, 2) - if refined == "": - continue - self.applyCellChange(row, 0, refined) - # Resize the first column - self.grid_parameters.AutoSizeColumn(0) - event.Skip() - return - - def onPopupRenameParameters(self, event): - """Rename parameters.""" - - if self.grid_parameters.IsSelection(): - dlg = wx.TextEntryDialog(self, "New index:", "Rename Selected Parameters", "") - - value = None - if dlg.ShowModal() == wx.ID_OK: - value = dlg.GetValue() - dlg.Destroy() - try: - value = int(value) - except (ValueError, TypeError): - return - - rows = self.grid_parameters.GetNumberRows() - cols = self.grid_parameters.GetNumberCols() - - selpars = [] - # Get the selected parameters - for i in range(rows): - key = int(self.grid_parameters.GetRowLabelValue(i)) - for j in range(cols): - if self.grid_parameters.IsInSelection(i, j): - selpars.append(key) - break - - for key in selpars: - if key != value: - self.fit.changeParameterIndex(key, value) - self.mainFrame.needsSave() - - self.fit.updateParameters() - self.refresh() - - event.Skip() - return - - # end of Popup menu events ########################################### - - def onApplyParameters(self, event): # wxGlade: ParametersPanel. - self.fit.applyParameters() - self.mainFrame.needsSave() - event.Skip() - - # Required by event handlers - - def getSelectedParameters(self): - """Get list of row values of selected cells.""" - rows = self.grid_parameters.GetNumberRows() - cols = self.grid_parameters.GetNumberCols() - selection = [] - - for i in range(rows): - for j in range(cols): - if self.grid_parameters.IsInSelection(i, j): - selection.append(i) - break - - return selection - - def fillCells(self, indices, value): - """Fill cells with a given value. - - indices -- list of (i,j) tuples representing cell coordinates - value -- string value to place into cells - """ - for i, j in indices: - if j != 1 and not self.grid_parameters.IsReadOnly(i, j): - self.applyCellChange(i, j, value) - return - - -# end of class ParametersPanel - -# testing code ############################################################ -if __name__ == "__main__": - - class MyFrame(wx.Frame): - def __init__(self, *args, **kwds): - kwds["style"] = wx.DEFAULT_FRAME_STYLE - wx.Frame.__init__(self, *args, **kwds) - self.window = ParametersPanel(self, -1) - self.SetTitle("testing") - # choke, mainframe.needsSave() emulation - self.window.mainFrame = self.window - self.window.mainFrame.needsSave = self.dummy - - self.test() - - def dummy(self): - pass - - def test(self): - """Testing code goes here.""" - from diffpy.pdfgui.control.parameter import Parameter - - self.window.parameters = { - 3: Parameter(3), - 17: Parameter(17), - 11: Parameter(11), - } - self.window.parameters[3].setInitial(1) - self.window.parameters[17].setInitial(0.55) - self.window.parameters[11].setInitial(5.532) - - self.window.refresh() - - class MyApp(wx.App): - def onInit(self): - frame_1 = MyFrame(None, -1, "") - self.SetTopWindow(frame_1) - frame_1.Show() - return 1 - - app = MyApp(0) - app.MainLoop() -# end of testing code ##################################################### diff --git a/src/diffpy/pdfgui/gui/pdfguiglobals.py b/src/diffpy/pdfgui/gui/pdfguiglobals.py deleted file mode 100644 index 5580dca5..00000000 --- a/src/diffpy/pdfgui/gui/pdfguiglobals.py +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""This module contains global parameters needed by PDFgui.""" - -import os.path -from importlib.resources import files - -from diffpy.pdfgui.gui import debugoptions - -# Name of the program -name = "PDFgui" -# Maximum number of files to be remembered -MAXMRU = 5 -# The location of the configuration file -configfilename = os.path.expanduser("~/.pdfgui_py3.cfg") -# Project modification flag -isAltered = False - -# Resolve APPDATADIR base path to application data files. -try: - _mydir = os.path.abspath(str(files(__name__))) -except TypeError: # For Python < 3.12 - _mydir = os.path.abspath(os.path.dirname(__file__)) - -_upbasedir = os.path.normpath(_mydir + "/../../..") -_development_mode = os.path.basename(_upbasedir) == "src" and os.path.isfile( - os.path.join(_upbasedir, "../pyproject.toml") -) - -# Requirement must have egg-info. Do not use in _development_mode. -_req = "diffpy.pdfgui" - -# pavol -# APPDATADIR = (os.path.dirname(_upbasedir) if _development_mode -# else str(files(_req))) -# long -if _development_mode: - APPDATADIR = os.path.dirname(_mydir) -else: - APPDATADIR = str(files(_req)) - -APPDATADIR = os.path.abspath(APPDATADIR) - -# Location of the HTML manual -docMainFile = "https://diffpy.github.io/diffpy.pdfgui/manual.html" - -del _upbasedir -del _development_mode -del _req - - -def iconpath(iconfilename): - """Full path to the icon file in pdfgui installation. This function - should be used whenever GUI needs access to custom icons. - - iconfilename -- icon file name without any path - - Return string. - """ - rv = os.path.join(APPDATADIR, "icons", iconfilename) - assert os.path.isfile(rv), "icon file does not exist" - return rv - - -# options and arguments passed on command line -cmdopts = [] -cmdargs = [] - -# debugging options: - -dbopts = debugoptions.DebugOptions() - -# End of file diff --git a/src/diffpy/pdfgui/gui/pdfpanel.py b/src/diffpy/pdfgui/gui/pdfpanel.py deleted file mode 100644 index 718292f1..00000000 --- a/src/diffpy/pdfgui/gui/pdfpanel.py +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Chris Farrow, Dmitriy Bryndin -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -import wx - -from diffpy.pdfgui.gui.errorwrapper import catchObjectErrors - - -class PDFPanel(object): - """Mix-in class for all PDF gui panels. - - This method is meant to be a secondary parent class for classed - derived from wx.Panel. It defines methods and member variables - necessary to all panels in the PDFgui. - """ - - def __init__(self, *args, **kwds): - self.mainFrame = None - self.treeCtrlMain = None - # The configuration parser for reading and writing to the - # configuration file - self.cP = None - # key is used to determine the node type associated with the given panel. - self.key = "" - # Wrap all events so that the exceptions get handled. - catchObjectErrors(self) - return - - def refresh(self): - """Refreshes wigets of the panel. - - This method must be overloaded in the derived class or else a - NotImplementedError will be raised when this method is called. - """ - raise NotImplementedError("refresh() must be implemented in subclass") - - def setToolTips(self, toolTips): - """Sets tooltips for controls. - - @param toolTips: dictionary of the form {'controlname' : - 'tooltip'} - """ - for controlName, tooltip in toolTips.items(): - control = getattr(self, controlName) - if control.GetToolTip() is None: - control.SetToolTip(wx.ToolTip("")) - tt = control.GetToolTip() - tt.SetTip(tooltip) - return diff --git a/src/diffpy/pdfgui/gui/phaseconfigurepanel.py b/src/diffpy/pdfgui/gui/phaseconfigurepanel.py deleted file mode 100644 index db269589..00000000 --- a/src/diffpy/pdfgui/gui/phaseconfigurepanel.py +++ /dev/null @@ -1,795 +0,0 @@ -#!/usr/bin/env python -# -*- coding: UTF-8 -*- -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Chris Farrow, Dmitriy Bryndin -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -# generated by wxGlade 0.9.3 on Fri Jul 19 16:04:47 2019 - -import wx -import wx.grid - -from diffpy.pdffit2 import is_element -from diffpy.pdfgui.control.controlerrors import TempControlSelectError -from diffpy.pdfgui.gui import phasepanelutils, tooltips -from diffpy.pdfgui.gui.insertrowsdialog import InsertRowsDialog -from diffpy.pdfgui.gui.pdfpanel import PDFPanel -from diffpy.pdfgui.gui.wxextensions.autowidthlabelsgrid import AutoWidthLabelsGrid -from diffpy.pdfgui.gui.wxextensions.textctrlutils import textCtrlAsGridCell -from diffpy.pdfgui.gui.wxextensions.validators import FLOAT_ONLY, TextValidator -from diffpy.structure import Atom -from diffpy.utils.wx import gridutils - - -class PhaseConfigurePanel(wx.Panel, PDFPanel): - """Panel for configuring a phase. - - Data members: - structure -- reference to PDFStructure - _focusedText -- value of a cell or textctrl before it changes - lConstraintsMap -- map of TextCtrl name to parameter name - _row -- row, where rightclick occurred - _col -- column, where rightclick occurred - """ - - def __init__(self, *args, **kwds): - PDFPanel.__init__(self) - # begin wxGlade: PhaseConfigurePanel.__init__ - kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL - wx.Panel.__init__(self, *args, **kwds) - self.SetFocus() - - sizerMain = wx.BoxSizer(wx.VERTICAL) - - sizerPanelName = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.HORIZONTAL) - sizerMain.Add(sizerPanelName, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) - - self.labelPanelName = wx.StaticText(self, wx.ID_ANY, "Phase Configuration") - self.labelPanelName.SetFont( - wx.Font( - 18, - wx.FONTFAMILY_DEFAULT, - wx.FONTSTYLE_NORMAL, - wx.FONTWEIGHT_BOLD, - 0, - "", - ) - ) - sizerPanelName.Add(self.labelPanelName, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT, 5) - - sizerLatticeParameters = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.HORIZONTAL) - sizerMain.Add(sizerLatticeParameters, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) - - grid_sizer_3 = wx.FlexGridSizer(2, 6, 0, 0) - sizerLatticeParameters.Add(grid_sizer_3, 1, wx.EXPAND, 0) - - self.labelA = wx.StaticText(self, wx.ID_ANY, "a") - grid_sizer_3.Add(self.labelA, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) - - self.textCtrlA = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) - grid_sizer_3.Add(self.textCtrlA, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - self.labelB = wx.StaticText(self, wx.ID_ANY, "b") - grid_sizer_3.Add(self.labelB, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) - - self.textCtrlB = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) - grid_sizer_3.Add(self.textCtrlB, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - self.labelC = wx.StaticText(self, wx.ID_ANY, "c") - grid_sizer_3.Add(self.labelC, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) - - self.textCtrlC = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) - grid_sizer_3.Add(self.textCtrlC, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - self.labelAlpha = wx.StaticText(self, wx.ID_ANY, "alpha") - grid_sizer_3.Add(self.labelAlpha, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) - - self.textCtrlAlpha = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) - grid_sizer_3.Add(self.textCtrlAlpha, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - self.labelBeta = wx.StaticText(self, wx.ID_ANY, "beta") - grid_sizer_3.Add(self.labelBeta, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) - - self.textCtrlBeta = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) - grid_sizer_3.Add(self.textCtrlBeta, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - self.labelGamma = wx.StaticText(self, wx.ID_ANY, "gamma") - grid_sizer_3.Add(self.labelGamma, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) - - self.textCtrlGamma = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) - grid_sizer_3.Add(self.textCtrlGamma, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - sizerAdditionalParameters = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.HORIZONTAL) - sizerMain.Add(sizerAdditionalParameters, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) - - grid_sizer_4 = wx.FlexGridSizer(3, 6, 0, 0) - sizerAdditionalParameters.Add(grid_sizer_4, 1, wx.EXPAND, 0) - - self.labelScaleFactor = wx.StaticText(self, wx.ID_ANY, "Scale Factor") - grid_sizer_4.Add( - self.labelScaleFactor, - 0, - wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, - 5, - ) - - self.textCtrlScaleFactor = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) - grid_sizer_4.Add(self.textCtrlScaleFactor, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - grid_sizer_4.Add((20, 10), 0, 0, 0) - - grid_sizer_4.Add((20, 10), 0, 0, 0) - - grid_sizer_4.Add((20, 10), 0, 0, 0) - - grid_sizer_4.Add((20, 10), 0, 0, 0) - - self.labelDelta1 = wx.StaticText(self, wx.ID_ANY, "delta1") - grid_sizer_4.Add(self.labelDelta1, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) - - self.textCtrlDelta1 = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) - grid_sizer_4.Add(self.textCtrlDelta1, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - self.labelDelta2 = wx.StaticText(self, wx.ID_ANY, "delta2") - grid_sizer_4.Add(self.labelDelta2, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) - - self.textCtrlDelta2 = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) - grid_sizer_4.Add(self.textCtrlDelta2, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - self.labelSpdiameter = wx.StaticText(self, wx.ID_ANY, "spdiameter") - grid_sizer_4.Add( - self.labelSpdiameter, - 0, - wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, - 5, - ) - - self.textCtrlSpdiameter = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) - grid_sizer_4.Add(self.textCtrlSpdiameter, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - self.labelSratio = wx.StaticText(self, wx.ID_ANY, "sratio") - grid_sizer_4.Add(self.labelSratio, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) - - self.textCtrlSratio = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) - grid_sizer_4.Add(self.textCtrlSratio, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - self.labelRcut = wx.StaticText(self, wx.ID_ANY, "rcut") - grid_sizer_4.Add(self.labelRcut, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) - - self.textCtrlRcut = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) - grid_sizer_4.Add(self.textCtrlRcut, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - self.labelStepcut = wx.StaticText(self, wx.ID_ANY, "stepcut") - grid_sizer_4.Add(self.labelStepcut, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) - - self.textCtrlStepcut = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) - grid_sizer_4.Add(self.textCtrlStepcut, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - sizerAtoms = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.VERTICAL) - sizerMain.Add(sizerAtoms, 1, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) - - sizer_1 = wx.BoxSizer(wx.HORIZONTAL) - sizerAtoms.Add(sizer_1, 0, wx.EXPAND, 0) - - self.labelIncludedPairs = wx.StaticText(self, wx.ID_ANY, "Included Pairs") - sizer_1.Add(self.labelIncludedPairs, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) - - self.textCtrlIncludedPairs = wx.TextCtrl(self, wx.ID_ANY, "all-all") - self.textCtrlIncludedPairs.SetMinSize((240, 25)) - sizer_1.Add(self.textCtrlIncludedPairs, 0, wx.ALL, 5) - - self.gridAtoms = AutoWidthLabelsGrid(self, wx.ID_ANY, size=(1, 1)) - self.gridAtoms.CreateGrid(0, 11) - self.gridAtoms.EnableDragRowSize(0) - self.gridAtoms.SetColLabelValue(0, "elem") - self.gridAtoms.SetColLabelValue(1, "x") - self.gridAtoms.SetColLabelValue(2, "y") - self.gridAtoms.SetColLabelValue(3, "z") - self.gridAtoms.SetColLabelValue(4, "u11") - self.gridAtoms.SetColLabelValue(5, "u22") - self.gridAtoms.SetColLabelValue(6, "u33") - self.gridAtoms.SetColLabelValue(7, "u12") - self.gridAtoms.SetColLabelValue(8, "u13") - self.gridAtoms.SetColLabelValue(9, "u23") - self.gridAtoms.SetColLabelValue(10, "occ") - sizerAtoms.Add(self.gridAtoms, 1, wx.EXPAND, 0) - - self.SetSizer(sizerMain) - sizerMain.Fit(self) - - self.Layout() - - self.Bind(wx.grid.EVT_GRID_CMD_CELL_CHANGED, self.onCellChange, self.gridAtoms) - self.Bind(wx.grid.EVT_GRID_CMD_CELL_RIGHT_CLICK, self.onCellRightClick, self.gridAtoms) - self.Bind(wx.grid.EVT_GRID_CMD_EDITOR_SHOWN, self.onEditorShown, self.gridAtoms) - self.Bind( - wx.grid.EVT_GRID_CMD_LABEL_RIGHT_CLICK, - self.onLabelRightClick, - self.gridAtoms, - ) - # end wxGlade - self.__customProperties() - - # ######################################################################## - # Misc Methods - - def __customProperties(self): - """Custom properties for the panel.""" - self.structure = None - self.constraints = {} - self.results = None - self._row = 0 - self._col = 0 - self._focusedText = None - self._selectedCells = [] - - self.lAtomConstraints = [ - "x", - "y", - "z", - "u11", - "u22", - "u33", - "u12", - "u13", - "u23", - "occ", - ] - # pdffit internal naming - self.lConstraintsMap = { - "textCtrlA": "lat(1)", - "textCtrlB": "lat(2)", - "textCtrlC": "lat(3)", - "textCtrlAlpha": "lat(4)", - "textCtrlBeta": "lat(5)", - "textCtrlGamma": "lat(6)", - "textCtrlScaleFactor": "pscale", - "textCtrlDelta1": "delta1", - "textCtrlDelta2": "delta2", - "textCtrlSratio": "sratio", - "textCtrlRcut": "rcut", - "textCtrlStepcut": "stepcut", - "textCtrlSpdiameter": "spdiameter", - } - - # bind onSetFocus onKillFocus events to text controls - for tname in self.lConstraintsMap: - self.__dict__[tname].Bind(wx.EVT_SET_FOCUS, self.onSetFocus) - self.__dict__[tname].Bind(wx.EVT_KILL_FOCUS, self.onKillFocus) - self.__dict__[tname].SetValidator(TextValidator(FLOAT_ONLY)) - self.__dict__[tname].Bind(wx.EVT_KEY_DOWN, self.onTextCtrlKey) - - self.textCtrlIncludedPairs.Bind(wx.EVT_SET_FOCUS, self.onSetFocus) - self.textCtrlIncludedPairs.Bind(wx.EVT_KILL_FOCUS, self.onSelectedPairs) - self.textCtrlIncludedPairs.Bind(wx.EVT_KEY_DOWN, self.onTextCtrlKey) - - # define tooltips - self.setToolTips(tooltips.phasepanel) - # make sure tooltips exist for all lConstraintsMap controls as - # this is later assumed in restrictConstrainedParameters code - for tname in self.lConstraintsMap: - assert getattr(self, tname).GetToolTip() is not None - - # catch key events and apply them to the grid - self.Bind(wx.EVT_KEY_DOWN, self.onKey) - return - - # Create the onTextCtrlKey event handler from textCtrlAsGridCell from - # wxextensions.textctrlutils - onTextCtrlKey = textCtrlAsGridCell - - def _cache(self): - """Cache the current structure and constraints for future - comparison.""" - pass - - __this_is_first_refresh = True - - def refresh(self): - """Refreshes widgets on the panel.""" - phasepanelutils.refreshTextCtrls(self) - pairs = self.structure.getSelectedPairs() - self.textCtrlIncludedPairs.SetValue(pairs) - phasepanelutils.refreshGrid(self) - self.restrictConstrainedParameters() - # wxpython 3.0 on Windows 7 prevents textCtrlA from receiving - # left-click input focus and can be only focused with a Tab key. - # This only happens for the first input, the text control behaves - # normally after receiving focus once. - # Workaround: do explicit focus here for the first rendering. - if self.__this_is_first_refresh: - self.__this_is_first_refresh = False - focusowner = self.textCtrlA.FindFocus() - wx.CallAfter(self.textCtrlA.SetFocus) - if focusowner is not None: - wx.CallAfter(focusowner.SetFocus) - return - - def restrictConstrainedParameters(self): - """Set 'read-only' boxes that correspond to constrained - parameters.""" - - self.setToolTips(tooltips.phasepanel) - self.textCtrlA.DefaultStyle.BackgroundColour - txtbg = self.textCtrlScaleFactor.DefaultStyle.BackgroundColour - - # First the TextCtrls - for key, var in self.lConstraintsMap.items(): - textCtrl = getattr(self, key) - if var in self.constraints: - textCtrl.SetEditable(False) - textCtrl.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT)) - tt = textCtrl.GetToolTip() - tt.SetTip(self.constraints[var].formula) - else: - textCtrl.SetEditable(True) - textCtrl.SetBackgroundColour(txtbg) - - # Now the grid - rows = self.gridAtoms.GetNumberRows() - cols = self.gridAtoms.GetNumberCols() - - for i in range(rows): - for j in range(1, cols): - var = self.lAtomConstraints[j - 1] - var += "(%i)" % (i + 1) - if var in self.constraints: - self.gridAtoms.SetReadOnly(i, j, True) - self.gridAtoms.SetCellBackgroundColour( - i, j, wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT) - ) - else: - self.gridAtoms.SetReadOnly(i, j, False) - self.gridAtoms.SetCellBackgroundColour(i, j, wx.NullColour) - - return - - def applyTextCtrlChange(self, id, value): - """Update a structure according to a change in a TextCtrl. - - id -- textctrl id - value -- new value - """ - if self.structure is None: - return - - try: - value = float(value) - if id == self.textCtrlA.GetId(): - self.structure.lattice.setLatPar(a=value) - elif id == self.textCtrlB.GetId(): - self.structure.lattice.setLatPar(b=value) - elif id == self.textCtrlC.GetId(): - self.structure.lattice.setLatPar(c=value) - elif id == self.textCtrlAlpha.GetId(): - self.structure.lattice.setLatPar(alpha=value) - elif id == self.textCtrlBeta.GetId(): - self.structure.lattice.setLatPar(beta=value) - elif id == self.textCtrlGamma.GetId(): - self.structure.lattice.setLatPar(gamma=value) - elif id == self.textCtrlScaleFactor.GetId(): - self.structure.pdffit["scale"] = value - elif id == self.textCtrlDelta1.GetId(): - self.structure.pdffit["delta1"] = value - elif id == self.textCtrlDelta2.GetId(): - self.structure.pdffit["delta2"] = value - elif id == self.textCtrlSratio.GetId(): - self.structure.pdffit["sratio"] = value - elif id == self.textCtrlRcut.GetId(): - self.structure.pdffit["rcut"] = value - elif id == self.textCtrlStepcut.GetId(): - self.structure.pdffit["stepcut"] = value - elif id == self.textCtrlSpdiameter.GetId(): - self.structure.pdffit["spdiameter"] = value - - return value - - except Exception: - return None - - def applyCellChange(self, i, j, value): - """Update an atom according to a change in a cell. - - i -- cell position - j -- cell position - value -- new value - """ - if not self.mainFrame or self.structure is None: - return - - # The element name - if j == 0: - value = value.title() - if not is_element(value): - return - self.structure[i].element = value # element - return value - - # Other entries - # ignore the change if the value is not valid - try: - value = float(value) - if value == "": - value = 0.0 - if j == 1: - self.structure[i].xyz[0] = value # x - elif j == 2: - self.structure[i].xyz[1] = value # y - elif j == 3: - self.structure[i].xyz[2] = value # z - elif j == 4: - self.structure[i].U[0, 0] = value # U(1,1) - elif j == 5: - self.structure[i].U[1, 1] = value # U(2,2) - elif j == 6: - self.structure[i].U[2, 2] = value # U(3,3) - elif j == 7: - self.structure[i].U[0, 1] = self.structure[i].U[1, 0] = value # U(1,2) - elif j == 8: - self.structure[i].U[0, 2] = self.structure[i].U[2, 0] = value # U(1,3) - elif j == 9: - self.structure[i].U[1, 2] = self.structure[i].U[2, 1] = value # U(2,3) - elif j == 10: - self.structure[i].occupancy = value # occupancy - - self.mainFrame.needsSave() - return value - - except ValueError: - return - - # ######################################################################## - # Event Handlers - - # TextCtrl Events - def onSetFocus(self, event): - """Saves a TextCtrl value, to be compared in onKillFocus - later.""" - self._focusedText = event.GetEventObject().GetValue() - event.Skip() - return - - def onKillFocus(self, event): - """Check value of TextCtrl and update structure if necessary.""" - if not self.mainFrame: - return - textctrl = event.GetEventObject() - value = textctrl.GetValue() - if value != self._focusedText: - self.applyTextCtrlChange(textctrl.GetId(), value) - phasepanelutils.refreshTextCtrls(self) - self.mainFrame.needsSave() - self._focusedText = None - event.Skip() - return - - def onSelectedPairs(self, event): - """Check to see if the value of the selected pairs is valid.""" - if not self.mainFrame: - return - value = self.textCtrlIncludedPairs.GetValue() - self.structure.setSelectedPairs(value) - value = self.structure.getSelectedPairs() - self.textCtrlIncludedPairs.SetValue(value) - event.Skip() - return - - # Grid Events - def onLabelRightClick(self, event): # wxGlade: PhaseConfigurePanel. - """Bring up right-click menu.""" - if self.structure is not None: - dx = dy = 0 - if event.GetRow() == -1: - dy = self.gridAtoms.GetGridCornerLabelWindow().GetSize().y - if event.GetCol() == -1: - dx = self.gridAtoms.GetGridCornerLabelWindow().GetSize().x - - # do not popup menu if the whole grid is set to read only - if len(self.structure) == 0: - self.popupMenu( - self.gridAtoms, - event.GetPosition().x - dx, - event.GetPosition().y - dy, - ) - event.Skip() - return - - def onCellRightClick(self, event): # wxGlade: PhaseConfigurePanel. - """Bring up right-click menu.""" - self._row = event.GetRow() - self._col = event.GetCol() - - # If the right-clicked node is not part of a group, then make sure that - # it is the only selected cell. - append = False - r = self._row - c = self._col - if self.gridAtoms.IsInSelection(r, c): - append = True - self.gridAtoms.SelectBlock(r, c, r, c, append) - - self.popupMenu(self.gridAtoms, event.GetPosition().x, event.GetPosition().y) - event.Skip() - return - - def onEditorShown(self, event): # wxGlade: PhaseConfigurePanel. - """Capture the focused text when the grid editor is shown.""" - i = event.GetRow() - j = event.GetCol() - self._focusedText = self.gridAtoms.GetCellValue(i, j) - # self._selectedCells = gridutils.getSelectedCells(self.gridAtoms) - # TODO: temporary show the error message for control-select. - try: - self._selectedCells = gridutils.getSelectedCells(self.gridAtoms) - except TypeError: - raise TempControlSelectError("controlselecterror") - return - - def onCellChange(self, event): # wxGlade: PhaseConfigurePanel. - """Update focused and selected text when a cell changes.""" - # NOTE: be careful with refresh(). It calls Grid.AutoSizeColumns, which - # creates a EVT_GRID_CMD_CELL_CHANGED event, which causes a recursion - # loop. - i = event.GetRow() - j = event.GetCol() - - value = self.gridAtoms.GetCellValue(i, j) - while (i, j) in self._selectedCells: - self._selectedCells.remove((i, j)) - # We need the edited cell to be at the front of the list - self._selectedCells.insert(0, (i, j)) - self.fillCells(value) - self._focusedText = None - return - - def fillCells(self, value): - """Fill cells with a given value. - - value -- string value to place into cells - - This uses the member variable _selectedCells, a list of (i,j) tuples for - the selected cells. - """ - for i, j in self._selectedCells: - if not self.gridAtoms.IsReadOnly(i, j): - # Get the last valid text from the cell. For the cell that triggered - # this method, that is the _focusedText, for other cells it is the - # value returned by GetCellValue - oldvalue = self._focusedText or self.gridAtoms.GetCellValue(i, j) - self._focusedText = None - newvalue = self.applyCellChange(i, j, value) - # print i, j, value, oldvalue, newvalue - if newvalue is None: - newvalue = oldvalue - self.gridAtoms.SetCellValue(i, j, str(newvalue)) - - gridutils.quickResizeColumns(self.gridAtoms, self._selectedCells) - return - - def onKey(self, event): - """Catch key events in the panel.""" - key = event.GetKeyCode() - - # Select All - # Ctrl A - if event.ControlDown() and key == 65: - rows = self.gridAtoms.GetNumberRows() - cols = self.gridAtoms.GetNumberCols() - self.gridAtoms.SelectBlock(0, 0, rows, cols) - - # context menu key - elif key == wx.WXK_MENU: - self.popupMenu(self.gridAtoms, event.GetPosition().x, event.GetPosition().y) - - # Vim-like search for atom selection - elif key == 47: - self.onPopupSelect(event) - - # Delete an atom - # Delete - elif key == 127: - selected = self.gridAtoms.GetSelectedRows() - if selected: - self.structure.deleteAtoms(selected) - self.refresh() - self.mainFrame.needsSave() - - # Ctrl - - elif event.ControlDown() and key == 45: - indices = gridutils.getSelectionRows(self.gridAtoms) - self.structure.deleteAtoms(indices) - self.refresh() - self.mainFrame.needsSave() - - # Append an atom - # Ctrl + or Ctrl = - elif event.ControlDown() and (key == 61 or key == 43): - indices = gridutils.getSelectionRows(self.gridAtoms) - pos = 0 - if indices: - pos = 1 + indices[-1] - elif self.structure: - pos = len(self.structure) - # insert "rows" atoms into the structure - atoms = [_defaultNewAtom()] - self.structure.insertAtoms(pos, atoms) - self.refresh() - self.mainFrame.needsSave() - - else: - event.Skip() - - return - - # ######################################################################## - # Grid popup menu and handlers - - def popupMenu(self, window, x, y): - """Creates the popup menu. - - window -- window, where to popup a menu - x -- x coordinate - y -- y coordinate - """ - # only do this part the first time so the events are only bound once - if not hasattr(self, "insertID"): - self.insertID = wx.NewIdRef() - self.deleteID = wx.NewIdRef() - self.selectID = wx.NewIdRef() - self.copyID = wx.NewIdRef() - self.pasteID = wx.NewIdRef() - self.supercellID = wx.NewIdRef() - self.spaceGroupID = wx.NewIdRef() - - self.Bind(wx.EVT_MENU, self.onPopupInsert, id=self.insertID) - self.Bind(wx.EVT_MENU, self.onPopupDelete, id=self.deleteID) - self.Bind(wx.EVT_MENU, self.onPopupSelect, id=self.selectID) - self.Bind(wx.EVT_MENU, self.onPopupCopy, id=self.copyID) - self.Bind(wx.EVT_MENU, self.onPopupPaste, id=self.pasteID) - self.Bind(wx.EVT_MENU, self.onPopupSupercell, id=self.supercellID) - self.Bind(wx.EVT_MENU, self.onPopupSpaceGroup, id=self.spaceGroupID) - - # make a menu - menu = wx.Menu() - - # add some other items - menu.Append(self.insertID, "&Insert atoms...") - menu.Append(self.deleteID, "&Delete atoms") - menu.AppendSeparator() - menu.Append(self.selectID, "Select &atoms...") - menu.Append(self.copyID, "&Copy") - menu.Append(self.pasteID, "&Paste") - menu.AppendSeparator() - menu.Append(self.supercellID, "Create supercell...") - menu.Append(self.spaceGroupID, "Expand space group...") - - # Disable some items if there are no atoms selected - indices = gridutils.getSelectionRows(self.gridAtoms) - if not indices: - menu.Enable(self.deleteID, False) - menu.Enable(self.spaceGroupID, False) - - # Disable some items if there is no structure - if self.structure is None or len(self.structure) == 0: - menu.Enable(self.deleteID, False) - menu.Enable(self.supercellID, False) - menu.Enable(self.spaceGroupID, False) - - # Check for copy/paste - if not phasepanelutils.canCopySelectedCells(self): - menu.Enable(self.copyID, False) - if not phasepanelutils.canPasteIntoCells(self): - menu.Enable(self.pasteID, False) - - # Popup the menu. If an item is selected then its handler - # will be called before PopupMenu returns. - window.PopupMenu(menu, wx.Point(x, y)) - menu.Destroy() - return - - def onPopupInsert(self, event): - """Adds rows to the grid.""" - if self.structure is not None: - dlg = InsertRowsDialog(self) - if dlg.ShowModal() == wx.ID_OK: - rows = dlg.spin_ctrl_Rows.GetValue() - - if len(self.structure) == 0: - self._row = 0 - elif dlg.radio_box_where.GetSelection() == 1: # if selected "below" - self._row += 1 - - # insert "rows" atoms into the structure - atoms = [_defaultNewAtom() for i in range(rows)] - self.structure.insertAtoms(self._row, atoms) - self.refresh() - self.mainFrame.needsSave() - - # Highlight the elements of the new rows so that they can be - # changed by the user. - self.gridAtoms.SetFocus() - self.gridAtoms.SelectBlock(self._row, 0, self._row + len(atoms) - 1, 0) - self.gridAtoms.SetGridCursor(self._row, 0) - - dlg.Destroy() - return - - def onPopupDelete(self, event): - """Deletes the row under mouse pointer from the grid.""" - if self.structure is not None: - indices = gridutils.getSelectionRows(self.gridAtoms) - self.structure.deleteAtoms(indices) - self.refresh() - self.mainFrame.needsSave() - return - - def onPopupSelect(self, event): - """Limit cell selection to specified atom selection string.""" - phasepanelutils.showSelectAtomsDialog(self) - return - - def onPopupCopy(self, event): - """Copy selected cells.""" - phasepanelutils.copySelectedCells(self) - return - - def onPopupPaste(self, event): - """Paste previously copied cells.""" - phasepanelutils.pasteIntoCells(self) - return - - def onPopupSupercell(self, event): - """Create a supercell with the supercell dialog.""" - from diffpy.pdfgui.gui.supercelldialog import SupercellDialog - - if self.structure is not None: - dlg = SupercellDialog(self) - if dlg.ShowModal() == wx.ID_OK: - mno = dlg.getMNO() - self.structure.expandSuperCell(mno) - self.refresh() - self.mainFrame.needsSave() - dlg.Destroy() - return - - def onPopupSpaceGroup(self, event): - """Create a supercell with the supercell dialog.""" - from diffpy.pdfgui.gui.sgstructuredialog import SGStructureDialog - - if self.structure is not None: - - indices = gridutils.getSelectionRows(self.gridAtoms) - dlg = SGStructureDialog(self) - dlg.mainFrame = self.mainFrame - dlg.indices = indices - dlg.setStructure(self.structure) - if dlg.ShowModal() == wx.ID_OK: - spcgrp = dlg.getSpaceGroup() - offset = dlg.getOffset() - self.structure.expandAsymmetricUnit(spcgrp, indices, offset) - self.refresh() - self.mainFrame.needsSave() - dlg.Destroy() - return - - -# end of class PhaseConfigurePanel - -# Local helpers -------------------------------------------------------------- - - -def _defaultNewAtom(): - """Create new atom instance with non-zero initial U.""" - uii = 0.003 - rv = Atom("C", [0.0, 0.0, 0.0], U=[[uii, 0, 0], [0, uii, 0], [0, 0, uii]]) - return rv diff --git a/src/diffpy/pdfgui/gui/phaseconstraintspanel.py b/src/diffpy/pdfgui/gui/phaseconstraintspanel.py deleted file mode 100644 index e27ec9b0..00000000 --- a/src/diffpy/pdfgui/gui/phaseconstraintspanel.py +++ /dev/null @@ -1,659 +0,0 @@ -#!/usr/bin/env python -# -*- coding: UTF-8 -*- -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Chris Farrow, Dmitriy Bryndin -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -# generated by wxGlade 0.9.3 on Fri Jul 19 16:05:04 2019 - -import re - -import wx -import wx.grid - -from diffpy.pdfgui.control.constraint import Constraint -from diffpy.pdfgui.control.controlerrors import ControlValueError -from diffpy.pdfgui.gui import phasepanelutils, tooltips -from diffpy.pdfgui.gui.pdfpanel import PDFPanel -from diffpy.pdfgui.gui.sgconstraindialog import SGConstrainDialog -from diffpy.pdfgui.gui.wxextensions.autowidthlabelsgrid import AutoWidthLabelsGrid -from diffpy.pdfgui.gui.wxextensions.textctrlutils import textCtrlAsGridCell -from diffpy.utils.wx import gridutils - - -class PhaseConstraintsPanel(wx.Panel, PDFPanel): - def __init__(self, *args, **kwds): - PDFPanel.__init__(self) - # begin wxGlade: PhaseConstraintsPanel.__init__ - kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL - wx.Panel.__init__(self, *args, **kwds) - - sizerMain = wx.BoxSizer(wx.VERTICAL) - - sizerPanelName = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.HORIZONTAL) - sizerMain.Add(sizerPanelName, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) - - self.labelPanelName = wx.StaticText(self, wx.ID_ANY, "Phase Constraints") - self.labelPanelName.SetFont( - wx.Font( - 18, - wx.FONTFAMILY_DEFAULT, - wx.FONTSTYLE_NORMAL, - wx.FONTWEIGHT_BOLD, - 0, - "", - ) - ) - sizerPanelName.Add(self.labelPanelName, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT, 5) - - sizerLatticeParameters = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.HORIZONTAL) - sizerMain.Add(sizerLatticeParameters, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) - - grid_sizer_3 = wx.FlexGridSizer(2, 6, 0, 0) - sizerLatticeParameters.Add(grid_sizer_3, 1, wx.EXPAND, 0) - - self.labelA = wx.StaticText(self, wx.ID_ANY, "a") - grid_sizer_3.Add(self.labelA, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) - - self.textCtrlA = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) - grid_sizer_3.Add(self.textCtrlA, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - self.labelB = wx.StaticText(self, wx.ID_ANY, "b") - grid_sizer_3.Add(self.labelB, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) - - self.textCtrlB = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) - grid_sizer_3.Add(self.textCtrlB, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - self.labelC = wx.StaticText(self, wx.ID_ANY, "c") - grid_sizer_3.Add(self.labelC, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) - - self.textCtrlC = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) - grid_sizer_3.Add(self.textCtrlC, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - self.labelAlpha = wx.StaticText(self, wx.ID_ANY, "alpha") - grid_sizer_3.Add(self.labelAlpha, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) - - self.textCtrlAlpha = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) - grid_sizer_3.Add(self.textCtrlAlpha, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - self.labelBeta = wx.StaticText(self, wx.ID_ANY, "beta") - grid_sizer_3.Add(self.labelBeta, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) - - self.textCtrlBeta = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) - grid_sizer_3.Add(self.textCtrlBeta, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - self.labelGamma = wx.StaticText(self, wx.ID_ANY, "gamma") - grid_sizer_3.Add(self.labelGamma, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) - - self.textCtrlGamma = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) - grid_sizer_3.Add(self.textCtrlGamma, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - sizerAdditionalParameters = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.HORIZONTAL) - sizerMain.Add(sizerAdditionalParameters, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) - - grid_sizer_4 = wx.FlexGridSizer(3, 6, 0, 0) - sizerAdditionalParameters.Add(grid_sizer_4, 1, wx.EXPAND, 0) - - self.labelScaleFactor = wx.StaticText(self, wx.ID_ANY, "Scale Factor") - grid_sizer_4.Add( - self.labelScaleFactor, - 0, - wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, - 5, - ) - - self.textCtrlScaleFactor = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) - grid_sizer_4.Add(self.textCtrlScaleFactor, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - grid_sizer_4.Add((20, 10), 0, 0, 0) - - grid_sizer_4.Add((20, 10), 0, 0, 0) - - grid_sizer_4.Add((20, 10), 0, 0, 0) - - grid_sizer_4.Add((20, 10), 0, 0, 0) - - self.labelDelta1 = wx.StaticText(self, wx.ID_ANY, "delta1") - grid_sizer_4.Add(self.labelDelta1, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) - - self.textCtrlDelta1 = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) - grid_sizer_4.Add(self.textCtrlDelta1, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - self.labelDelta2 = wx.StaticText(self, wx.ID_ANY, "delta2") - grid_sizer_4.Add(self.labelDelta2, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) - - self.textCtrlDelta2 = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) - grid_sizer_4.Add(self.textCtrlDelta2, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - self.labelSpdiameter = wx.StaticText(self, wx.ID_ANY, "spdiameter") - grid_sizer_4.Add( - self.labelSpdiameter, - 0, - wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, - 5, - ) - - self.textCtrlSpdiameter = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) - grid_sizer_4.Add(self.textCtrlSpdiameter, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - self.labelSratio = wx.StaticText(self, wx.ID_ANY, "sratio") - grid_sizer_4.Add(self.labelSratio, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) - - self.textCtrlSratio = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) - grid_sizer_4.Add(self.textCtrlSratio, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - self.labelRcut = wx.StaticText(self, wx.ID_ANY, "rcut") - grid_sizer_4.Add(self.labelRcut, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) - - self.textCtrlRcut = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER | wx.TE_READONLY) - grid_sizer_4.Add(self.textCtrlRcut, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - self.labelStepcut = wx.StaticText(self, wx.ID_ANY, "stepcut") - grid_sizer_4.Add(self.labelStepcut, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) - - self.textCtrlStepcut = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER | wx.TE_READONLY) - grid_sizer_4.Add(self.textCtrlStepcut, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - sizerAtoms = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.VERTICAL) - sizerMain.Add(sizerAtoms, 1, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) - - sizer_1 = wx.BoxSizer(wx.HORIZONTAL) - sizerAtoms.Add(sizer_1, 0, wx.EXPAND, 0) - - self.labelIncludedPairs = wx.StaticText(self, wx.ID_ANY, "Included Pairs") - sizer_1.Add(self.labelIncludedPairs, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) - - self.textCtrlIncludedPairs = wx.TextCtrl(self, wx.ID_ANY, "all-all", style=wx.TE_READONLY) - self.textCtrlIncludedPairs.SetMinSize((240, 25)) - sizer_1.Add(self.textCtrlIncludedPairs, 0, wx.ALL, 5) - - self.gridAtoms = AutoWidthLabelsGrid(self, wx.ID_ANY, size=(1, 1)) - self.gridAtoms.CreateGrid(0, 11) - self.gridAtoms.EnableDragRowSize(0) - self.gridAtoms.SetColLabelValue(0, "elem") - self.gridAtoms.SetColLabelValue(1, "x") - self.gridAtoms.SetColLabelValue(2, "y") - self.gridAtoms.SetColLabelValue(3, "z") - self.gridAtoms.SetColLabelValue(4, "u11") - self.gridAtoms.SetColLabelValue(5, "u22") - self.gridAtoms.SetColLabelValue(6, "u33") - self.gridAtoms.SetColLabelValue(7, "u12") - self.gridAtoms.SetColLabelValue(8, "u13") - self.gridAtoms.SetColLabelValue(9, "u23") - self.gridAtoms.SetColLabelValue(10, "occ") - sizerAtoms.Add(self.gridAtoms, 1, wx.EXPAND, 0) - - self.SetSizer(sizerMain) - sizerMain.Fit(self) - - self.Layout() - - self.Bind(wx.grid.EVT_GRID_CMD_CELL_CHANGED, self.onCellChange, self.gridAtoms) - self.Bind(wx.grid.EVT_GRID_CMD_CELL_RIGHT_CLICK, self.onCellRightClick, self.gridAtoms) - self.Bind(wx.grid.EVT_GRID_CMD_EDITOR_SHOWN, self.onEditorShown, self.gridAtoms) - self.Bind( - wx.grid.EVT_GRID_CMD_LABEL_RIGHT_CLICK, - self.onLabelRightClick, - self.gridAtoms, - ) - # end wxGlade - self.__customProperties() - - # ######################################################################## - # Misc Methods - - def __customProperties(self): - """Custom properties for the panel.""" - self.structure = None - self.constraints = {} - self.results = None - self._textctrls = [ - "textCtrlA", - "textCtrlB", - "textCtrlC", - "textCtrlAlpha", - "textCtrlBeta", - "textCtrlGamma", - "textCtrlScaleFactor", - "textCtrlDelta1", - "textCtrlDelta2", - "textCtrlSratio", - "textCtrlSpdiameter", - ] - self._row = 0 - self._col = 0 - self._focusedText = None - self._selectedCells = [] - # bind onSetFocus onKillFocus events to text controls - for widget in self._textctrls: - self.__dict__[widget].Bind(wx.EVT_SET_FOCUS, self.onSetFocus) - self.__dict__[widget].Bind(wx.EVT_KILL_FOCUS, self.onKillFocus) - self.__dict__[widget].Bind(wx.EVT_KEY_DOWN, self.onTextCtrlKey) - - # set up grid - self.lAtomConstraints = [ - "x", - "y", - "z", - "u11", - "u22", - "u33", - "u12", - "u13", - "u23", - "occ", - ] - # pdffit internal naming - self.lConstraints = [ - "lat(1)", - "lat(2)", - "lat(3)", - "lat(4)", - "lat(5)", - "lat(6)", - "pscale", - "delta1", - "delta2", - "sratio", - "spdiameter", - ] - textCtrlIds = [getattr(self, n).GetId() for n in self._textctrls] - self._id2varname = dict(zip(textCtrlIds, self.lConstraints)) - - # Define tooltips. - self.setToolTips(tooltips.phasepanel) - - # NOTE: GridCellAttr is reference counted. - # Each call of SetX(attr) decreases its reference count. - # We need to call attr.IncRef before each SetX(attr) - # https://github.com/wxWidgets/Phoenix/issues/627#issuecomment-354219493 - - # set 'elem' abd 'name' columns to read-only - attr = wx.grid.GridCellAttr() - attr.SetReadOnly(True) - attr.IncRef() - self.gridAtoms.SetColAttr(0, attr) - attr.IncRef() - self.gridAtoms.SetColAttr(11, attr) - # drop local reference to `attr` as it was constructed here. - attr.DecRef() - - # catch key events and apply them to the grid - self.Bind(wx.EVT_KEY_DOWN, self.onKey) - - # Hide some stuff - self.labelRcut.Hide() - self.textCtrlRcut.Hide() - self.labelStepcut.Hide() - self.textCtrlStepcut.Hide() - return - - # Create the onTextCtrlKey event handler from textCtrlAsGridCell from - # wxextensions.textctrlutils - onTextCtrlKey = textCtrlAsGridCell - - def _cache(self): - """Cache the current structure and constraints for future - comparison.""" - pass - - def refresh(self): - """Refresh wigets on the panel.""" - if self.structure is None: - raise ValueError("structure is not defined.") - - self.refreshTextCtrls() - - # # update the grid ### - natoms = len(self.structure) - nrows = self.gridAtoms.GetNumberRows() - self.gridAtoms.BeginBatch() - # make sure grid has correct number of rows - if natoms > nrows: - self.gridAtoms.InsertRows(numRows=natoms - nrows) - elif natoms < nrows: - self.gridAtoms.DeleteRows(numRows=nrows - natoms) - - # start with clean grid - self.gridAtoms.ClearGrid() - - # fill the first 'elem' column with element symbols - for row, atom in zip(range(natoms), self.structure): - self.gridAtoms.SetCellValue(row, 0, atom.element) - - # update constraints - bareAtomVarColumn = dict(zip(self.lAtomConstraints, range(1, 1 + len(self.lAtomConstraints)))) - avpat = re.compile(r"(\w+)\((\d+)\)$") - for var, con in self.constraints.items(): - m = avpat.match(var) - if not m: - continue - barevar = m.group(1) - if barevar not in bareAtomVarColumn: - continue - column = bareAtomVarColumn[barevar] - row = int(m.group(2)) - 1 - if not 0 <= row < natoms: - emsg = "Invalid variable index for %r" % var - raise ControlValueError(emsg) - self.gridAtoms.SetCellValue(row, column, con.formula) - barevar = re.sub(r"\(\d+\)$", "", var) - if barevar not in bareAtomVarColumn: - continue - - self.gridAtoms.AutosizeLabels() - self.gridAtoms.AutoSizeColumns() - self.gridAtoms.EndBatch() - - self.gridAtoms.AdjustScrollbars() - self.gridAtoms.ForceRefresh() - return - - def refreshTextCtrls(self): - """Refreshes the TextCtrls.""" - - for widget, var in zip(self._textctrls, self.lConstraints): - wobj = getattr(self, widget) - if var in self.constraints: - s = self.constraints[var].formula - else: - s = "" - wobj.SetValue(s) - - pairs = self.structure.getSelectedPairs() - self.textCtrlIncludedPairs.SetValue(pairs) - return - - def applyTextCtrlChange(self, id, value): - """Update a structure according to a change in a TextCtrl. - - id -- textctrl id - value -- new value - """ - self.mainFrame.needsSave() - var = self._id2varname[id] - formula = value.strip() - if formula != "": - self.constraints[var] = Constraint(formula) - return self.constraints[var].formula - else: - self.constraints.pop(var, None) - return "" - - def applyCellChange(self, i, j, value): - """Update an atom according to a change in a cell. - - i -- cell position - j -- cell position - value -- new value - - returns the new value stored in the data object, or None if value is - somehow invalid. - """ - self.mainFrame.needsSave() - key = self.lAtomConstraints[j - 1] + "({})".format(i + 1) - formula = value.strip() - if formula != "": - self.constraints[key] = Constraint(formula) - return self.constraints[key].formula - else: - self.constraints.pop(key, None) - return "" - return - - # ######################################################################## - # Event Handlers - - # TextCtrl Events - def onSetFocus(self, event): - """Saves a TextCtrl value, to be compared in onKillFocuse - later.""" - self._focusedText = event.GetEventObject().GetValue() - event.Skip() - return - - def onKillFocus(self, event): - """Check value of TextCtrl and update structure if necessary.""" - event.Skip() - if not self.mainFrame: - return - textctrl = event.GetEventObject() - value = textctrl.GetValue() - if value != self._focusedText: - self.applyTextCtrlChange(textctrl.GetId(), value) - self.refreshTextCtrls() - self.mainFrame.needsSave() - self._focusedText = None - return - - # Grid Events - def onLabelRightClick(self, event): # wxGlade: PhaseConstraintsPanel. - """Bring up right-click menu.""" - if self.structure is not None: - dx = dy = 0 - if event.GetRow() == -1: - dy = self.gridAtoms.GetGridCornerLabelWindow().GetSize().y - if event.GetCol() == -1: - dx = self.gridAtoms.GetGridCornerLabelWindow().GetSize().x - - # do not popup menu if the whole grid is set to read only - if len(self.structure) == 0: - self.popupMenu( - self.gridAtoms, - event.GetPosition().x - dx, - event.GetPosition().y - dy, - ) - event.Skip() - return - - def onCellRightClick(self, event): # wxGlade: PhaseConstraintsPanel. - """Bring up right-click menu.""" - self._row = event.GetRow() - self._col = event.GetCol() - - # If the right-clicked node is not part of a group, then make sure that - # it is the only selected cell. - append = False - r = self._row - c = self._col - if self.gridAtoms.IsInSelection(r, c): - append = True - self.gridAtoms.SelectBlock(r, c, r, c, append) - - self.popupMenu(self.gridAtoms, event.GetPosition().x, event.GetPosition().y) - event.Skip() - return - - def onEditorShown(self, event): # wxGlade: PhaseConstraintsPanel. - """Capture the focused text when the grid editor is shown.""" - i = event.GetRow() - j = event.GetCol() - self._focusedText = self.gridAtoms.GetCellValue(i, j) - self._selectedCells = gridutils.getSelectedCells(self.gridAtoms) - return - - def onCellChange(self, event): # wxGlade: PhaseConstraintsPanel. - """Update focused and selected text when a cell changes.""" - # NOTE: be careful with refresh(). It calls Grid.AutoSizeColumns, which - # creates a EVT_GRID_CMD_CELL_CHANGED event, which causes a recursion - # loop. - i = event.GetRow() - j = event.GetCol() - - value = self.gridAtoms.GetCellValue(i, j) - while (i, j) in self._selectedCells: - self._selectedCells.remove((i, j)) - # We need the edited cell to be at the front of the list - self._selectedCells.insert(0, (i, j)) - self.fillCells(value) - self._focusedText = None - return - - def fillCells(self, value): - """Fill cells with a given value. - - value -- string value to place into cells - - This uses the member variable _selectedCells, a list of (i,j) tuples for - the selected cells. - """ - for i, j in self._selectedCells: - if not self.gridAtoms.IsReadOnly(i, j): - # Get the last valid text from the cell. For the cell that triggered - # this method, that is the _focusedText, for other cells it is the - # value returned by GetCellValue - oldvalue = self._focusedText - if oldvalue is None: - oldvalue = self.gridAtoms.GetCellValue(i, j) - self._focusedText = None - newvalue = self.applyCellChange(i, j, value) - # print i, j, value, oldvalue, newvalue - if newvalue is None: - # Get out of here. If the value is invalid, it won't be valid - # for any cells. - newvalue = oldvalue - self.gridAtoms.SetCellValue(i, j, str(newvalue)) - break - else: - self.gridAtoms.SetCellValue(i, j, str(newvalue)) - - gridutils.quickResizeColumns(self.gridAtoms, self._selectedCells) - return - - def onKey(self, event): - """Catch key events in the panel.""" - key = event.GetKeyCode() - - # Select All - Ctrl+A - if event.ControlDown() and key == 65: - rows = self.gridAtoms.GetNumberRows() - cols = self.gridAtoms.GetNumberCols() - self.gridAtoms.SelectBlock(0, 0, rows, cols) - - # context menu key - elif key == wx.WXK_MENU: - self.popupMenu(self.gridAtoms, event.GetPosition().x, event.GetPosition().y) - - # Vim-like search for atom selection - elif key == 47: - self.onPopupSelect(event) - - # Delete - elif key == 127: - self._selectedCells = gridutils.getSelectedCells(self.gridAtoms) - self.fillCells("") - self.mainFrame.needsSave() - - # Can't get these to work. Maybe later. - # Copy - Ctrl+C / Ctrl+Insert - # if event.ControlDown() and (key == 67 or key == wx.WXK_INSERT): - # if phasepanelutils.canCopySelectedCells(self): - # phasepanelutils.copySelectedCells(self) - - # Paste - Ctrl+V / Shift+Insert - # if (event.ControlDown() and key == 86) or\ - # (event.ShiftDown() and key == wx.WXK_INSERT): - # if phasepanelutils.canPasteIntoCells(self): - # phasepanelutils.pasteIntoCells(self) - - else: - event.Skip() - return - - # ######################################################################## - # Grid popup menu and handlers - - def popupMenu(self, window, x, y): - """Creates the popup menu. - - window -- window, where to popup a menu - x -- x coordinate - y -- y coordinate - """ - # only do this part the first time so the events are only bound once - if not hasattr(self, "spaceGroupID"): - self.spaceGroupID = wx.NewIdRef() - self.selectID = wx.NewIdRef() - self.copyID = wx.NewIdRef() - self.pasteID = wx.NewIdRef() - - self.Bind(wx.EVT_MENU, self.onPopupSpaceGroup, id=self.spaceGroupID) - self.Bind(wx.EVT_MENU, self.onPopupSelect, id=self.selectID) - self.Bind(wx.EVT_MENU, self.onPopupCopy, id=self.copyID) - self.Bind(wx.EVT_MENU, self.onPopupPaste, id=self.pasteID) - - # make a menu - menu = wx.Menu() - - # add some other items - menu.Append(self.spaceGroupID, "&Symmetry constraints...") - menu.AppendSeparator() - menu.Append(self.selectID, "Select &atoms...") - menu.Append(self.copyID, "&Copy") - menu.Append(self.pasteID, "&Paste") - - # Disable some items if there are no atoms selected - indices = gridutils.getSelectionRows(self.gridAtoms) - if not indices: - menu.Enable(self.spaceGroupID, False) - - # Check for copy/paste - if not phasepanelutils.canCopySelectedCells(self): - menu.Enable(self.copyID, False) - if not phasepanelutils.canPasteIntoCells(self): - menu.Enable(self.pasteID, False) - - # Popup the menu. If an item is selected then its handler - # will be called before PopupMenu returns. - window.PopupMenu(menu, wx.Point(x, y)) - menu.Destroy() - return - - def onPopupSpaceGroup(self, event): - """Create a supercell with the supercell dialog.""" - if self.structure is not None: - - indices = gridutils.getSelectionRows(self.gridAtoms) - dlg = SGConstrainDialog(self) - dlg.mainFrame = self.mainFrame - dlg.indices = indices - dlg.setStructure(self.structure) - dlg.updateWidgets() - if dlg.ShowModal() == wx.ID_OK: - spcgrp = dlg.getSpaceGroup() - offset = dlg.getOffset() - posflag = dlg.getPosFlag() - tempflag = dlg.getTempFlag() - self.structure.applySymmetryConstraints(spcgrp, indices, posflag, tempflag, offset) - self.refresh() - dlg.Destroy() - self.mainFrame.needsSave() - return - - def onPopupSelect(self, event): - """Limit cell selection to specified atom selection string.""" - phasepanelutils.showSelectAtomsDialog(self) - return - - def onPopupCopy(self, event): - """Copy selected cells.""" - phasepanelutils.copySelectedCells(self) - return - - def onPopupPaste(self, event): - """Paste previously copied cells.""" - phasepanelutils.pasteIntoCells(self) - return - - -# end of class PhaseConstraintsPanel diff --git a/src/diffpy/pdfgui/gui/phasenotebookpanel.py b/src/diffpy/pdfgui/gui/phasenotebookpanel.py deleted file mode 100644 index 43fa886a..00000000 --- a/src/diffpy/pdfgui/gui/phasenotebookpanel.py +++ /dev/null @@ -1,112 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Dmitriy Bryndin -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -# -# Phase notebook panel -# -# Just a notebook, holds three panels: "Configure", "Constraints", "Results" -# -# Dmitriy Bryndin - - -import wx - -from diffpy.pdfgui.gui.pdfpanel import PDFPanel -from diffpy.pdfgui.gui.phaseconfigurepanel import PhaseConfigurePanel -from diffpy.pdfgui.gui.phaseconstraintspanel import PhaseConstraintsPanel -from diffpy.pdfgui.gui.phaseresultspanel import PhaseResultsPanel - - -class PhaseNotebookPanel(wx.Panel, PDFPanel): - def __init__(self, *args, **kwds): - PDFPanel.__init__(self) - kwds["style"] = wx.TAB_TRAVERSAL - wx.Panel.__init__(self, *args, **kwds) - self.notebook_phase = wx.Notebook(self, -1, style=0) - self.notebook_phase_pane_Configure = PhaseConfigurePanel(self.notebook_phase, -1) - self.notebook_phase_pane_Constraints = PhaseConstraintsPanel(self.notebook_phase, -1) - self.notebook_phase_pane_Results = PhaseResultsPanel(self.notebook_phase, -1) - - self.__set_properties() - self.__do_layout() - - self.notebook_phase.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.onNotebookPageChanged) - self.notebook_phase.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGING, self.onNotebookPageChanging) - - self.configuration = None - self.constraints = {} - self.results = None - self.mainFrame = None - self.focusedId = 0 - - def __set_properties(self): - pass - - def __do_layout(self): - sizer_1 = wx.BoxSizer(wx.HORIZONTAL) - self.notebook_phase.AddPage(self.notebook_phase_pane_Configure, "Configure") - self.notebook_phase.AddPage(self.notebook_phase_pane_Constraints, "Constraints") - self.notebook_phase.AddPage(self.notebook_phase_pane_Results, "Results") - sizer_1.Add(self.notebook_phase, 1, wx.EXPAND, 0) - self.SetAutoLayout(True) - self.SetSizer(sizer_1) - sizer_1.Fit(self) - sizer_1.SetSizeHints(self) - - def refresh(self): - """Refreshes the currently shown panel.""" - if self.mainFrame.quitting: - return - if self.focusedId == -1: - return - - panel = self.notebook_phase.GetPage(self.focusedId) - - panel.structure = self.configuration - panel.constraints = self.constraints - panel.results = self.results - - # This has to be done here, because this panel does not know who it - # belongs to until after it is instantiated. - panel.mainFrame = self.mainFrame - panel.refresh() - return - - def onNotebookPageChanging(self, event): - """Called during the page selection change.""" - # focusedId = event.GetOldSelection() - panel = self.notebook_phase.GetPage(self.focusedId) - panel._cache() - return - - def onNotebookPageChanged(self, event): - """Called after the page selection is changed.""" - self.focusedId = event.GetSelection() - self.refresh() - event.Skip() - return - - # Overloaded from Panel. - def Enable(self, enable=True): - """Keep the notebook enabled, just not the panels.""" - self.notebook_phase_pane_Configure.Enable(enable) - self.notebook_phase_pane_Constraints.Enable(enable) - self.notebook_phase_pane_Results.Enable(enable) - return - - -# end of class PhaseNotebookPanel - -# End of file diff --git a/src/diffpy/pdfgui/gui/phasepanelutils.py b/src/diffpy/pdfgui/gui/phasepanelutils.py deleted file mode 100644 index b74f73f9..00000000 --- a/src/diffpy/pdfgui/gui/phasepanelutils.py +++ /dev/null @@ -1,340 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""Common methods used in the phase panels.""" - -import wx - -from diffpy.utils.wx import gridutils - -# List of row entries taken from the clipboard -clipcells = [] - -# String describing what atoms should be selected. -selected_atoms = "" - - -def float2str(x): - """Compact string representation of float.""" - s = "%g" % x - if s.find(".") == -1 and s.find("e") == -1: - s = s + ".0" - return s - - -def refreshTextCtrls(panel): - """Refreshes the TextCtrls on the panel. - - This is used by phaseconfigurepanel and phaseresultspanel. - - This method updates the following TextCtrls with with contents of - the structure member variable of the panel. textCtrlA textCtrlB - textCtrlC textCtrlAlpha textCtrlBeta textCtrlGamma - textCtrlScaleFactor textCtrlDelta1 textCtrlDelta2 textCtrlSratio - textCtrlRcut textCtrlStepcut textCtrlSpdiameter - """ - if panel.structure is None: - # clear textcontrols - panel.textCtrlA.SetValue("") - panel.textCtrlB.SetValue("") - panel.textCtrlC.SetValue("") - panel.textCtrlAlpha.SetValue("") - panel.textCtrlBeta.SetValue("") - panel.textCtrlGamma.SetValue("") - panel.textCtrlScaleFactor.SetValue("") - panel.textCtrlDelta1.SetValue("") - panel.textCtrlDelta2.SetValue("") - panel.textCtrlSratio.SetValue("") - panel.textCtrlRcut.SetValue("") - panel.textCtrlStepcut.SetValue("") - panel.textCtrlSpdiameter.SetValue("") - - else: - # update panel with values from panel.structure - # update textctrls - panel.textCtrlA.SetValue(float2str(panel.structure.lattice.a)) - panel.textCtrlB.SetValue(float2str(panel.structure.lattice.b)) - panel.textCtrlC.SetValue(float2str(panel.structure.lattice.c)) - panel.textCtrlAlpha.SetValue(float2str(panel.structure.lattice.alpha)) - panel.textCtrlBeta.SetValue(float2str(panel.structure.lattice.beta)) - panel.textCtrlGamma.SetValue(float2str(panel.structure.lattice.gamma)) - panel.textCtrlScaleFactor.SetValue(float2str(panel.structure.pdffit["scale"])) - panel.textCtrlDelta1.SetValue(float2str(panel.structure.pdffit["delta1"])) - panel.textCtrlDelta2.SetValue(float2str(panel.structure.pdffit["delta2"])) - panel.textCtrlSratio.SetValue(float2str(panel.structure.pdffit["sratio"])) - panel.textCtrlRcut.SetValue(float2str(panel.structure.pdffit["rcut"])) - panel.textCtrlStepcut.SetValue(float2str(panel.structure.pdffit["stepcut"])) - panel.textCtrlSpdiameter.SetValue(float2str(panel.structure.pdffit["spdiameter"])) - return - - -def refreshGrid(panel): - """Refreshes grid on the panel. - - This is used by phaseconfigurepanel and phaseresultspanel. - - This method fills the grid with the contents of the structure member - variable of the panel. It is expected that the grid is named - 'gridAtoms'. - """ - if panel.structure is None: - # remove all rows from grid - panel.gridAtoms.BeginBatch() - if panel.gridAtoms.GetNumberRows() != 0: - panel.gridAtoms.DeleteRows(numRows=panel.gridAtoms.GetNumberRows()) - panel.gridAtoms.EndBatch() - - else: - # update the grid with atoms - panel.gridAtoms.BeginBatch() - - # set column labels - panel.gridAtoms.SetColLabelValue(0, "elem") - panel.gridAtoms.SetColLabelValue(1, "x") - panel.gridAtoms.SetColLabelValue(2, "y") - panel.gridAtoms.SetColLabelValue(3, "z") - panel.gridAtoms.SetColLabelValue(4, "u11") - panel.gridAtoms.SetColLabelValue(5, "u22") - panel.gridAtoms.SetColLabelValue(6, "u33") - panel.gridAtoms.SetColLabelValue(7, "u12") - panel.gridAtoms.SetColLabelValue(8, "u13") - panel.gridAtoms.SetColLabelValue(9, "u23") - panel.gridAtoms.SetColLabelValue(10, "occ") - - # make sure grid has correct number of rows and blank it - natoms = len(panel.structure) - nrows = panel.gridAtoms.GetNumberRows() - if natoms > nrows: - panel.gridAtoms.InsertRows(numRows=natoms - nrows) - elif natoms < nrows: - panel.gridAtoms.DeleteRows(numRows=nrows - natoms) - panel.gridAtoms.ClearGrid() - for i, atom in enumerate(panel.structure): - panel.gridAtoms.SetCellValue(i, 0, str(atom.element)) # element - panel.gridAtoms.SetCellValue(i, 1, float2str(atom.xyz[0])) # x - panel.gridAtoms.SetCellValue(i, 2, float2str(atom.xyz[1])) # y - panel.gridAtoms.SetCellValue(i, 3, float2str(atom.xyz[2])) # z - panel.gridAtoms.SetCellValue(i, 4, float2str(atom.U[0, 0])) # U(1,1) - panel.gridAtoms.SetCellValue(i, 5, float2str(atom.U[1, 1])) # U(2,2) - panel.gridAtoms.SetCellValue(i, 6, float2str(atom.U[2, 2])) # U(3,3) - panel.gridAtoms.SetCellValue(i, 7, float2str(atom.U[0, 1])) # U(1,2) - panel.gridAtoms.SetCellValue(i, 8, float2str(atom.U[0, 2])) # U(1,3) - panel.gridAtoms.SetCellValue(i, 9, float2str(atom.U[1, 2])) # U(2,3) - panel.gridAtoms.SetCellValue(i, 10, float2str(atom.occupancy)) # occupancy - - panel.gridAtoms.AutosizeLabels() - panel.gridAtoms.AutoSizeColumns() - panel.gridAtoms.EndBatch() - - panel.gridAtoms.AdjustScrollbars() - return - - -# Utility functions - - -def showSelectAtomsDialog(panel): - """Extend or limit selection to a string atom selection. - - panel -- instance of PhaseConfigurePanel or PhaseConstraintsPanel - - No return value. - """ - # do nothing for non-existent or empty structure - if not panel.structure: - return - msg = "\n".join( - [ - 'Specify index, symbol or "all", use "!" to subtract selection.', - 'Examples: "Na", "1:4, 6, 9:10", "all, !Na".', - ] - ) - global selected_atoms - dlg = wx.TextEntryDialog(panel, msg, "Select Atoms", selected_atoms) - if dlg.ShowModal() == wx.ID_OK: - s1 = dlg.GetValue().strip() - rows = panel.structure.getSelectedIndices(s1) - selected_atoms = s1 - if s1: - gridutils.limitSelectionToRows(panel.gridAtoms, rows) - dlg.Destroy() - return - - -def canCopySelectedCells(panel): - """Check to see if we can copy selected cells. - - To be copyable, the cells must exist in a single block or there must - be a single cell selected. Note that a block that is selected by - individual cells is considered a collection of individual atoms, not - a block. This is default wxPython behavior. - """ - grid = panel.gridAtoms - - topleft = grid.GetSelectionBlockTopLeft() - individuals = grid.GetSelectedCells() - numsel = len(topleft) + len(individuals) - return numsel == 1 - - -def canPasteIntoCells(panel): - """Check if clipboard contents are formatted for grid insertion. - - This also checks to see if the cell selection is appropriate for - pasting. - """ - grid = panel.gridAtoms - - individuals = grid.GetSelectedCells() - topleft = grid.GetSelectionBlockTopLeft() - if len(individuals) + len(topleft) != 1: - return False - - # Get the text - if not wx.TheClipboard.IsSupported(wx.DataFormat(wx.DF_TEXT)): - return False - - textdata = wx.TextDataObject() - if not wx.TheClipboard.IsOpened(): - opened = wx.TheClipboard.Open() - if not opened: - return False - success = wx.TheClipboard.GetData(textdata) - wx.TheClipboard.Close() - if not success: - return False - copytext = textdata.GetText() - - # Remove any trailing newline - copytext = copytext.rstrip("\n") - - # Make sure it is of the appropriate format - try: - rowlist = copytext.split("\n") - # Strip any trailing tabs - rowlist = [r.rstrip("\t") for r in rowlist] - celllist = [r.split("\t") for r in rowlist] - except wx.PyDeadObjectError: - return False - - if len(celllist) == 0: - return False - ncol = len(celllist[0]) - for row in celllist: - if len(row) != ncol: - return False - if ncol == 0: - return False - - global clipcells - clipcells = celllist - return True - - -def copySelectedCells(panel): - """Copy block of selected cells or individual cell into clipboard. - - This stores the cells as a plain text grid so that it can be copied - to and from other applications. Columns are delimited by tabs '\t'. - Rows are delimited by newlines '\n'. - """ - grid = panel.gridAtoms - copytext = "" - - # Get the cells - individuals = grid.GetSelectedCells() - topleft = grid.GetSelectionBlockTopLeft() - bottomright = grid.GetSelectionBlockBottomRight() - - if len(individuals) == 1: - copytext = str(grid.GetCellValue(individuals[0])) - - elif len(topleft) == 1: - # Format the block of cells - rtl = topleft[0][0] - ctl = topleft[0][1] - rbr = bottomright[0][0] - cbr = bottomright[0][1] - - for row in range(rtl, rbr + 1): - for col in range(ctl, cbr + 1): - copytext += str(grid.GetCellValue(row, col)) - copytext += "\t" - copytext += "\n" - - # Place the copytext into the clipboard - if not wx.TheClipboard.IsOpened(): - opened = wx.TheClipboard.Open() - if not opened: - raise IOError("Cannot open the clipboard.") - textdata = wx.TextDataObject(copytext) - wx.TheClipboard.SetData(textdata) - wx.TheClipboard.Close() - return - - -def pasteIntoCells(panel): - """Paste clipboard contents into cells. - - canPasteIntoCells must be called before this method in order to - format clipboard text for pasting. - """ - # Double check the clipcells - if len(clipcells) == 0: - return - if len(clipcells[0]) == 0: - return - - grid = panel.gridAtoms - individuals = grid.GetSelectedCells() - topleft = grid.GetSelectionBlockTopLeft() - if len(individuals) > 0: - tl = individuals[0] - elif len(topleft) > 0: - tl = topleft[0] - else: - return - rtl = tl[0] - ctl = tl[1] - - nrows = grid.GetNumberRows() - ncols = grid.GetNumberCols() - - rbr = min(nrows, rtl + len(clipcells)) - 1 - cbr = min(ncols, ctl + len(clipcells[0])) - 1 - - selections = [] - for row in range(rtl, rbr + 1): - for col in range(ctl, cbr + 1): - if not grid.IsReadOnly(row, col): - oldvalue = panel.gridAtoms.GetCellValue(row, col) - newvalue = panel.applyCellChange(row, col, clipcells[row - rtl][col - ctl]) - if newvalue is None: - newvalue = oldvalue - panel.gridAtoms.SetCellValue(row, col, str(newvalue)) - selections.append((row, col)) - - gridutils.quickResizeColumns(panel.gridAtoms, selections) - - # Clear the grid and select the inserted entries - grid.ClearSelection() - # panel.refresh() - for row in range(rtl, rbr + 1): - for col in range(ctl, cbr + 1): - if not grid.IsReadOnly(row, col): - grid.SelectBlock(row, col, row, col, True) - return - - -# End of file diff --git a/src/diffpy/pdfgui/gui/phaseresultspanel.py b/src/diffpy/pdfgui/gui/phaseresultspanel.py deleted file mode 100644 index 17268f3b..00000000 --- a/src/diffpy/pdfgui/gui/phaseresultspanel.py +++ /dev/null @@ -1,231 +0,0 @@ -#!/usr/bin/env python -# -*- coding: UTF-8 -*- -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Chris Farrow, Dmitriy Bryndin -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -# generated by wxGlade 0.9.3 on Fri Jul 19 16:05:14 2019 - - -import wx -import wx.grid - -from diffpy.pdfgui.gui import phasepanelutils, tooltips -from diffpy.pdfgui.gui.pdfpanel import PDFPanel -from diffpy.pdfgui.gui.wxextensions.autowidthlabelsgrid import AutoWidthLabelsGrid - - -class PhaseResultsPanel(wx.Panel, PDFPanel): - """GUI Panel, holds phase (structure) related constraints.""" - - def __init__(self, *args, **kwds): - PDFPanel.__init__(self) - # begin wxGlade: PhaseResultsPanel.__init__ - kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL - wx.Panel.__init__(self, *args, **kwds) - - sizerMain = wx.BoxSizer(wx.VERTICAL) - - sizerPanelName = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.HORIZONTAL) - sizerMain.Add(sizerPanelName, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) - - self.labelPanelName = wx.StaticText(self, wx.ID_ANY, "Phase Results") - self.labelPanelName.SetFont( - wx.Font( - 18, - wx.FONTFAMILY_DEFAULT, - wx.FONTSTYLE_NORMAL, - wx.FONTWEIGHT_BOLD, - 0, - "", - ) - ) - sizerPanelName.Add(self.labelPanelName, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT, 5) - - sizerLatticeParameters = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.HORIZONTAL) - sizerMain.Add(sizerLatticeParameters, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) - - grid_sizer_3 = wx.FlexGridSizer(2, 6, 0, 0) - sizerLatticeParameters.Add(grid_sizer_3, 1, wx.EXPAND, 0) - - self.labelA = wx.StaticText(self, wx.ID_ANY, "a") - grid_sizer_3.Add(self.labelA, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) - - self.textCtrlA = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) - grid_sizer_3.Add(self.textCtrlA, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - self.labelB = wx.StaticText(self, wx.ID_ANY, "b") - grid_sizer_3.Add(self.labelB, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) - - self.textCtrlB = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) - grid_sizer_3.Add(self.textCtrlB, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - self.labelC = wx.StaticText(self, wx.ID_ANY, "c") - grid_sizer_3.Add(self.labelC, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) - - self.textCtrlC = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) - grid_sizer_3.Add(self.textCtrlC, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - self.labelAlpha = wx.StaticText(self, wx.ID_ANY, "alpha") - grid_sizer_3.Add(self.labelAlpha, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) - - self.textCtrlAlpha = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) - grid_sizer_3.Add(self.textCtrlAlpha, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - self.labelBeta = wx.StaticText(self, wx.ID_ANY, "beta") - grid_sizer_3.Add(self.labelBeta, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) - - self.textCtrlBeta = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) - grid_sizer_3.Add(self.textCtrlBeta, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - self.labelGamma = wx.StaticText(self, wx.ID_ANY, "gamma") - grid_sizer_3.Add(self.labelGamma, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) - - self.textCtrlGamma = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) - grid_sizer_3.Add(self.textCtrlGamma, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - sizerAdditionalParameters = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.HORIZONTAL) - sizerMain.Add(sizerAdditionalParameters, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) - - grid_sizer_4 = wx.FlexGridSizer(3, 6, 0, 0) - sizerAdditionalParameters.Add(grid_sizer_4, 1, wx.EXPAND, 0) - - self.labelScaleFactor = wx.StaticText(self, wx.ID_ANY, "Scale Factor") - grid_sizer_4.Add( - self.labelScaleFactor, - 0, - wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, - 5, - ) - - self.textCtrlScaleFactor = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) - grid_sizer_4.Add(self.textCtrlScaleFactor, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - grid_sizer_4.Add((20, 10), 0, 0, 0) - - grid_sizer_4.Add((20, 10), 0, 0, 0) - - grid_sizer_4.Add((20, 10), 0, 0, 0) - - grid_sizer_4.Add((20, 10), 0, 0, 0) - - self.labelDelta1 = wx.StaticText(self, wx.ID_ANY, "delta1") - grid_sizer_4.Add(self.labelDelta1, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) - - self.textCtrlDelta1 = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) - grid_sizer_4.Add(self.textCtrlDelta1, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - self.labelDelta2 = wx.StaticText(self, wx.ID_ANY, "delta2") - grid_sizer_4.Add(self.labelDelta2, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) - - self.textCtrlDelta2 = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) - grid_sizer_4.Add(self.textCtrlDelta2, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - self.labelSpdiameter = wx.StaticText(self, wx.ID_ANY, "spdiameter") - grid_sizer_4.Add( - self.labelSpdiameter, - 0, - wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, - 5, - ) - - self.textCtrlSpdiameter = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) - grid_sizer_4.Add(self.textCtrlSpdiameter, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - self.labelSratio = wx.StaticText(self, wx.ID_ANY, "sratio") - grid_sizer_4.Add(self.labelSratio, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) - - self.textCtrlSratio = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) - grid_sizer_4.Add(self.textCtrlSratio, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - self.labelRcut = wx.StaticText(self, wx.ID_ANY, "rcut") - grid_sizer_4.Add(self.labelRcut, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) - - self.textCtrlRcut = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) - grid_sizer_4.Add(self.textCtrlRcut, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - self.labelStepcut = wx.StaticText(self, wx.ID_ANY, "stepcut") - grid_sizer_4.Add(self.labelStepcut, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) - - self.textCtrlStepcut = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY) - grid_sizer_4.Add(self.textCtrlStepcut, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) - - sizerAtoms = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.VERTICAL) - sizerMain.Add(sizerAtoms, 1, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) - - sizer_1 = wx.BoxSizer(wx.HORIZONTAL) - sizerAtoms.Add(sizer_1, 0, wx.EXPAND, 0) - - self.labelIncludedPairs = wx.StaticText(self, wx.ID_ANY, "Included Pairs") - sizer_1.Add(self.labelIncludedPairs, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) - - self.textCtrlIncludedPairs = wx.TextCtrl(self, wx.ID_ANY, "all-all", style=wx.TE_READONLY) - self.textCtrlIncludedPairs.SetMinSize((240, 25)) - sizer_1.Add(self.textCtrlIncludedPairs, 0, wx.ALL, 5) - - self.gridAtoms = AutoWidthLabelsGrid(self, wx.ID_ANY, size=(1, 1)) - self.gridAtoms.CreateGrid(0, 11) - self.gridAtoms.EnableEditing(0) - self.gridAtoms.EnableDragRowSize(0) - self.gridAtoms.SetColLabelValue(0, "elem") - self.gridAtoms.SetColLabelValue(1, "x") - self.gridAtoms.SetColLabelValue(2, "y") - self.gridAtoms.SetColLabelValue(3, "z") - self.gridAtoms.SetColLabelValue(4, "u11") - self.gridAtoms.SetColLabelValue(5, "u22") - self.gridAtoms.SetColLabelValue(6, "u33") - self.gridAtoms.SetColLabelValue(7, "u12") - self.gridAtoms.SetColLabelValue(8, "u13") - self.gridAtoms.SetColLabelValue(9, "u23") - self.gridAtoms.SetColLabelValue(10, "occ") - sizerAtoms.Add(self.gridAtoms, 1, wx.EXPAND, 0) - - self.SetSizer(sizerMain) - sizerMain.Fit(self) - - self.Layout() - # end wxGlade - self.__customProperties() - return - - # ######################################################################## - # Misc Methods - - def __customProperties(self): - """Custom properties for the panel.""" - # The resulting structure - self.structure = None - self.constraints = {} - self.results = None - # Define tooltips. - self.setToolTips(tooltips.phasepanel) - return - - def _cache(self): - """Cache the current structure and constraints for future - comparison.""" - pass - - def refresh(self): - """Refreshes wigets on the panel.""" - # This makes the right thing happen in phasepanelutils. It saves a lot - # of coding. - pairs = self.structure.getSelectedPairs() - self.textCtrlIncludedPairs.SetValue(pairs) - self.structure = self.results - phasepanelutils.refreshTextCtrls(self) - phasepanelutils.refreshGrid(self) - return - - -# end of class PhaseResultsPanel diff --git a/src/diffpy/pdfgui/gui/plotpanel.py b/src/diffpy/pdfgui/gui/plotpanel.py deleted file mode 100644 index c36db091..00000000 --- a/src/diffpy/pdfgui/gui/plotpanel.py +++ /dev/null @@ -1,276 +0,0 @@ -#!/usr/bin/env python -# -*- coding: ISO-8859-1 -*- -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -# generated by wxGlade 0.9.3 on Fri Jul 19 16:05:24 2019 - - -import wx - -from diffpy.pdfgui.control.controlerrors import ControlConfigError -from diffpy.pdfgui.gui import tooltips -from diffpy.pdfgui.gui.pdfpanel import PDFPanel -from diffpy.pdfgui.gui.wxextensions.listctrls import KeyEventsListCtrl -from diffpy.pdfgui.gui.wxextensions.validators import FLOAT_ONLY, TextValidator -from diffpy.pdfgui.utils import numericStringSort - - -class PlotPanel(wx.Panel, PDFPanel): - def __init__(self, *args, **kwds): - PDFPanel.__init__(self) - # begin wxGlade: PlotPanel.__init__ - kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL - wx.Panel.__init__(self, *args, **kwds) - self.SetSize((456, 659)) - - sizer_1 = wx.BoxSizer(wx.VERTICAL) - - sizer_3 = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, "X"), wx.HORIZONTAL) - sizer_1.Add(sizer_3, 0, wx.EXPAND, 0) - - self.xDataCombo = wx.ComboBox(self, wx.ID_ANY, choices=[], style=wx.CB_READONLY) - sizer_3.Add(self.xDataCombo, 1, wx.ALL, 5) - - sizer_4 = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, "Y"), wx.HORIZONTAL) - sizer_1.Add(sizer_4, 1, wx.EXPAND, 0) - - self.yDataList = KeyEventsListCtrl( - self, wx.ID_ANY, style=wx.BORDER_SUNKEN | wx.LC_NO_HEADER | wx.LC_REPORT - ) - sizer_4.Add(self.yDataList, 1, wx.ALL | wx.EXPAND, 5) - - sizer_6 = wx.BoxSizer(wx.HORIZONTAL) - sizer_1.Add(sizer_6, 0, wx.EXPAND, 0) - - self.offsetLabel = wx.StaticText(self, wx.ID_ANY, "offset", style=wx.ALIGN_RIGHT) - sizer_6.Add(self.offsetLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) - - self.offsetTextCtrl = wx.TextCtrl(self, wx.ID_ANY, "-5", style=wx.TE_PROCESS_ENTER) - sizer_6.Add(self.offsetTextCtrl, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) - - self.static_line_1 = wx.StaticLine(self, wx.ID_ANY) - sizer_1.Add(self.static_line_1, 0, wx.BOTTOM | wx.EXPAND | wx.TOP, 5) - - sizer_2 = wx.BoxSizer(wx.HORIZONTAL) - sizer_1.Add(sizer_2, 0, wx.EXPAND, 0) - - self.plotButton = wx.Button(self, wx.ID_ANY, "Plot") - sizer_2.Add(self.plotButton, 0, wx.ALL, 5) - - self.resetButton = wx.Button(self, wx.ID_ANY, "Reset") - sizer_2.Add(self.resetButton, 0, wx.ALL, 5) - - self.SetSizer(sizer_1) - - self.Layout() - - self.Bind(wx.EVT_TEXT_ENTER, self.onEnter, self.offsetTextCtrl) - self.Bind(wx.EVT_BUTTON, self.onPlot, self.plotButton) - self.Bind(wx.EVT_BUTTON, self.onReset, self.resetButton) - # end wxGlade - self.Bind(wx.EVT_COMBOBOX, self._check, self.xDataCombo) - self.Bind(wx.EVT_LIST_ITEM_SELECTED, self._check, self.yDataList) - self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self._check, self.yDataList) - self.__customProperties() - - # USER CONFIGURATION CODE ################################################# - def __customProperties(self): - """Custom Properties go here.""" - self.yDataList.InsertColumn(0, "Y data") - self.offsetTextCtrl.SetValidator(TextValidator(FLOAT_ONLY, allowNeg=True)) - - # Define tooltips. - self.setToolTips(tooltips.plotpanel) - - # Testing Code. Comment or delete this block when finished. - # self.yDataList.InsertStringItem(sys.maxint, "y1") - # self.yDataList.InsertStringItem(sys.maxint, "y2") - # self.yDataList.InsertStringItem(sys.maxint, "y3") - # self.yDataList.InsertStringItem(sys.maxint, "y4") - # self.yDataList.InsertStringItem(sys.maxint, "y5") - # Initialize the sorter. - # self.yDataList.makeIDM() - # self.yDataList.initializeSorter() - - return - - def enableWidgets(self, on=True): - """Enable or disable the widgets.""" - self.xDataCombo.Enable(on) - self.yDataList.Enable(on) - self.offsetTextCtrl.Enable(on) - self.resetButton.Enable(on) - self.plotButton.Enable(on) - return - - def updateWidgets(self): - """Enable or disable certain widgets depending upon what is - selected in the tree and in the plotting widgets.""" - # selections: selected nodes in treeCtrl - # fits: only different fittings - # refs: data item ids ( can be calculation, fit, structure and dataset - selections = self.treeCtrlMain.GetSelections() - # Only proceed if we have compatible items selected from the tree. - if not selections: - self.enableWidgets(False) - return - self.enableWidgets(True) - fits = dict.fromkeys( - [self.treeCtrlMain.GetControlData(self.treeCtrlMain.GetFitRoot(sel)) for sel in selections] - ) - refs = [self.treeCtrlMain.GetControlData(sel) for sel in selections] - - xdata = [] - # step is added if selections include type other than calculation - for type in [self.treeCtrlMain.GetNodeType(sel) for sel in selections]: - if type != "calculation": - xdata.append("step") - break - - # index is added if multiple selections are chosen from different fits - if len(fits) > 1: - xdata.append("index") - - for ref in refs: - xdata.extend(ref.getXNames()) - - for fit in fits: - xdata.extend(fit.getMetaDataNames()) - # also can plot y against y so add yNames as well - xdata.extend(fit.getYNames()) - - # reduce - xdata = list(set(xdata)) - - # Make the parameter entries a bit more presentable. - def _represent(mixedNames): - vals = ["@%i" % item for item in mixedNames if isinstance(item, int)] - others = [item for item in mixedNames if not isinstance(item, int)] - vals.extend(others) - numericStringSort(vals) - return vals - - xvals = _represent(xdata) - try: - xvals.remove("rw") - except ValueError: - pass - numericStringSort(xvals) - - # Fill the xDataCombo - if self.xDataCombo.GetCount(): - current = self.xDataCombo.GetValue() - else: - current = None - self.xDataCombo.Clear() - for item in xvals: - self.xDataCombo.Append(item) - - # Set default value for xDataCombo - # Either keep the current plot value selected, select 'r', or the - # first in the list. - defaultOrders = ["r", "step", "index"] - if current: - defaultOrders.insert(0, current) - for item in defaultOrders: - if item in xvals: - self.xDataCombo.SetValue(item) - break - else: - self.xDataCombo.SetSelection(0) - - # Y-DATA is the common subset of all data id - ydata = refs[0].getYNames() - for ref in refs[1:]: - for name in ydata[:]: - if name not in ref.getYNames(): - ydata.remove(name) - - yvals = _represent(ydata) - - # Fill the List - self.yDataList.DeleteAllItems() - for val in yvals: - # self.yDataList.InsertItem(sys.maxsize, str(val)) #doesn't work for windows - self.yDataList.InsertItem(100000, str(val)) - self.yDataList.makeIDM() - self.yDataList.initializeSorter() - if yvals: - self.yDataList.Select(0) - - # self.prevSelectionType = selectiontype - self._check(None) - - return - - def getSelectedYVals(self): - """Get the y-values selected in the y-value ListCtrl.""" - yvals = [] - item = self.yDataList.GetFirstSelected() - while item != -1: - name = self.yDataList.GetItemText(item) - yvals.append(name) - item = self.yDataList.GetNextSelected(item) - return yvals - - # EVENT CODE ############################################################# - def onPlot(self, event): # wxGlade: PlotPanel. - """Plot some stuff.""" - self._plot(event) - return - - def _plot(self, event): - """This function is not wrapped.""" - selections = self.treeCtrlMain.GetSelections() - refs = [self.treeCtrlMain.GetControlData(node) for node in selections] - xval = self.xDataCombo.GetValue() - if xval[0] == "@": - xval = int(xval[1:]) - temp = self.getSelectedYVals() - # Clean up some formatting so the control can understand this. - yvals = [int(par[1:]) for par in temp if par[0] == "@"] - yvals.extend([val for val in temp if val[0] != "@"]) - offset = self.offsetTextCtrl.GetValue() - try: - offset = float(offset) - except ValueError: # offset can be empty string - offset = 0.0 - - self.mainFrame.control.plot(xval, yvals, refs, shift=offset, dry=(event is None)) - return - - def onEnter(self, event): - """Reset plot.""" - self.onPlot(event) - return - - def onReset(self, event): # wxGlade: PlotPanel. - """Reset everything.""" - self.offsetTextCtrl.SetValue("-5") - self.refresh() - return - - # Methods overloaded from PDFPanel - def refresh(self): - """Refresh this panel.""" - self.updateWidgets() - return - - def _check(self, event): - try: - self._plot(None) - self.plotButton.Enable() - except ControlConfigError: - self.plotButton.Disable() diff --git a/src/diffpy/pdfgui/gui/preferencespanel.py b/src/diffpy/pdfgui/gui/preferencespanel.py deleted file mode 100644 index f586bc7c..00000000 --- a/src/diffpy/pdfgui/gui/preferencespanel.py +++ /dev/null @@ -1,209 +0,0 @@ -#!/usr/bin/env python -# -*- coding: UTF-8 -*- -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2007 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -# generated by wxGlade 0.9.3 on Fri Jul 19 16:05:32 2019 - -import wx -import wx.lib.filebrowsebutton - -from diffpy.pdfgui.control import structureviewer -from diffpy.pdfgui.gui import tooltips -from diffpy.pdfgui.gui.pdfpanel import PDFPanel - - -class PreferencesPanel(wx.Panel, PDFPanel): - def __init__(self, *args, **kwds): - PDFPanel.__init__(self) - # begin wxGlade: PreferencesPanel.__init__ - kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL - wx.Panel.__init__(self, *args, **kwds) - - sizer_1 = wx.BoxSizer(wx.VERTICAL) - - sizerPanelName = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.HORIZONTAL) - sizer_1.Add(sizerPanelName, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) - - self.labelPanelName = wx.StaticText(self, wx.ID_ANY, "Preferences") - self.labelPanelName.SetFont( - wx.Font( - 18, - wx.FONTFAMILY_DEFAULT, - wx.FONTSTYLE_NORMAL, - wx.FONTWEIGHT_BOLD, - 0, - "Bitstream Vera Sans", - ) - ) - sizerPanelName.Add(self.labelPanelName, 1, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) - - grid_sizer_1 = wx.GridSizer(3, 3, 10, 10) - sizer_1.Add(grid_sizer_1, 0, wx.ALL, 5) - - self.labelViewer = wx.StaticText(self, wx.ID_ANY, "Structure viewer executable") - grid_sizer_1.Add(self.labelViewer, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT, 0) - - self.textCtrlViewer = wx.TextCtrl(self, wx.ID_ANY, "") - grid_sizer_1.Add(self.textCtrlViewer, 0, wx.EXPAND, 0) - - self.buttonViewerBrowse = wx.Button(self, wx.ID_ANY, "Browse") - grid_sizer_1.Add(self.buttonViewerBrowse, 0, 0, 0) - - self.labelArgStr = wx.StaticText(self, wx.ID_ANY, "Argument string") - grid_sizer_1.Add(self.labelArgStr, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT, 0) - - self.textCtrlArgument = wx.TextCtrl(self, wx.ID_ANY, "") - grid_sizer_1.Add(self.textCtrlArgument, 0, wx.EXPAND, 0) - - grid_sizer_1.Add((20, 20), 0, 0, 0) - - self.labelFormat = wx.StaticText(self, wx.ID_ANY, "Structure format") - grid_sizer_1.Add(self.labelFormat, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT, 0) - - self.choiceFormat = wx.Choice(self, wx.ID_ANY, choices=[]) - grid_sizer_1.Add(self.choiceFormat, 0, wx.EXPAND, 0) - - grid_sizer_1.Add((20, 20), 0, 0, 0) - - self.structureDirCheckBox = wx.CheckBox(self, wx.ID_ANY, "Remember path to structure files") - sizer_1.Add(self.structureDirCheckBox, 0, wx.ALL, 5) - - self.dataDirCheckBox = wx.CheckBox(self, wx.ID_ANY, "Remember path to data sets") - sizer_1.Add(self.dataDirCheckBox, 0, wx.ALL, 5) - - sizer_1.Add((0, 0), 1, wx.EXPAND, 0) - - self.static_line_1 = wx.StaticLine(self, wx.ID_ANY) - sizer_1.Add(self.static_line_1, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) - - sizer_3 = wx.BoxSizer(wx.HORIZONTAL) - sizer_1.Add(sizer_3, 0, wx.EXPAND, 0) - - sizer_3.Add((0, 0), 1, 0, 0) - - self.okButton = wx.Button(self, wx.ID_OK, "OK") - sizer_3.Add(self.okButton, 0, wx.ALL, 5) - - self.cancelButton = wx.Button(self, wx.ID_CANCEL, "Cancel") - sizer_3.Add(self.cancelButton, 0, wx.ALL, 5) - - self.SetSizer(sizer_1) - sizer_1.Fit(self) - - self.Layout() - - self.Bind(wx.EVT_BUTTON, self.onBrowse, self.buttonViewerBrowse) - self.Bind(wx.EVT_BUTTON, self.onOK, self.okButton) - self.Bind(wx.EVT_BUTTON, self.onCancel, self.cancelButton) - # end wxGlade - self.__customProperties() - - def __customProperties(self): - """Set the custom properties.""" - - # Fill the options in the format choice - viewer = structureviewer.getStructureViewer() - formats = viewer.getFileFormats() - formats.sort() - for fmt in formats: - self.choiceFormat.Append(fmt) - - self.setToolTips(tooltips.preferencespanel) - return - - def onCancel(self, event): # wxGlade: PreferencesPanel. - """Cancel the changes. - - Go back to the last panel. - """ - selections = self.treeCtrlMain.GetSelections() - if selections: - node = selections[0] - entrytype = self.treeCtrlMain.GetNodeType(node) - else: - entrytype = None - self.mainFrame.setMode("fitting") - self.mainFrame.switchRightPanel(entrytype) - return - - def onOK(self, event): # wxGlade: PreferencesPanel. - """Record all of the preferences and return to fitting mode.""" - - # Record structure viewer stuff - executable = str(self.textCtrlViewer.GetValue()).strip() - argstr = str(self.textCtrlArgument.GetValue()).strip() - fileformat = str(self.choiceFormat.GetStringSelection()) - config = { - "executable": executable, - "argstr": argstr, - "fileformat": fileformat, - } - - viewer = structureviewer.getStructureViewer() - viewer.setConfig(config) - - # Structures path - remember = bool(self.structureDirCheckBox.GetValue()) - if not self.cP.has_section("PHASE"): - self.cP.add_section("PHASE") - self.cP.set("PHASE", "remember", str(remember)) - - # Data set path - remember = bool(self.dataDirCheckBox.GetValue()) - if not self.cP.has_section("DATASET"): - self.cP.add_section("DATASET") - self.cP.set("DATASET", "remember", str(remember)) - - # Get out of here - self.onCancel(event) - return - - def refresh(self): - """Refresh the panel.""" - - # Structure viewer stuff - viewer = structureviewer.getStructureViewer() - config = viewer.getConfig() - self.textCtrlViewer.SetValue(config["executable"]) - self.textCtrlArgument.SetValue(config["argstr"]) - self.choiceFormat.SetStringSelection(config["fileformat"]) - - remember = False - if self.cP.has_option("DATASET", "remember"): - remember = self.cP.getboolean("DATASET", "remember") - self.dataDirCheckBox.SetValue(remember) - - remember = False - if self.cP.has_option("PHASE", "remember"): - remember = self.cP.getboolean("PHASE", "remember") - self.structureDirCheckBox.SetValue(remember) - return - - def onBrowse(self, event): # wxGlade: PreferencesPanel. - d = wx.FileDialog( - None, - "Choose structure viewer", - ".", - "", - "All Files|*", - wx.FD_OPEN | wx.FD_FILE_MUST_EXIST, - ) - if d.ShowModal() == wx.ID_OK: - fullpath = d.GetPath() - self.textCtrlViewer.SetValue(fullpath) - return - - -# end of class PreferencesPanel diff --git a/src/diffpy/pdfgui/gui/resultspanel.py b/src/diffpy/pdfgui/gui/resultspanel.py deleted file mode 100644 index a63256d6..00000000 --- a/src/diffpy/pdfgui/gui/resultspanel.py +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/env python -# -*- coding: UTF-8 -*- -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -# generated by wxGlade 0.9.3 on Fri Jul 19 16:05:44 2019 - -import wx - -from diffpy.pdfgui.gui.pdfpanel import PDFPanel - - -class ResultsPanel(wx.Panel, PDFPanel): - def __init__(self, *args, **kwds): - # begin wxGlade: ResultsPanel.__init__ - kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL - wx.Panel.__init__(self, *args, **kwds) - self.fitResLabel = wx.StaticText(self, wx.ID_ANY, "Fit Summary") - self.resultsTextCtrl = wx.TextCtrl( - self, - wx.ID_ANY, - "Fit results will display here once the fit is complete.", - style=wx.HSCROLL | wx.TE_MULTILINE | wx.TE_READONLY, - ) - - self.__set_properties() - self.__do_layout() - # end wxGlade - self.__customProperties() - - def __set_properties(self): - # begin wxGlade: ResultsPanel.__set_properties - self.fitResLabel.SetFont( - wx.Font( - 18, - wx.FONTFAMILY_DEFAULT, - wx.FONTSTYLE_NORMAL, - wx.FONTWEIGHT_BOLD, - 0, - "", - ) - ) - # end wxGlade - - def __do_layout(self): - # begin wxGlade: ResultsPanel.__do_layout - sizer_1 = wx.BoxSizer(wx.VERTICAL) - sizer_2 = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.HORIZONTAL) - sizer_2.Add(self.fitResLabel, 0, wx.ALL, 5) - sizer_1.Add(sizer_2, 0, wx.ALL | wx.EXPAND, 5) - sizer_1.Add(self.resultsTextCtrl, 1, wx.ALL | wx.EXPAND, 5) - self.SetSizer(sizer_1) - sizer_1.Fit(self) - self.Layout() - # end wxGlade - - # UTILITY METHODS ################################# - def __customProperties(self): - """Set the custom properties.""" - self.fit = None - self.defres = "Fit results will display here once the fit is complete." - self.results = self.defres - - # Set the font to monospace - ftxt = self.resultsTextCtrl.GetFont() - font = wx.Font( - ftxt.GetPointSize(), - wx.FONTFAMILY_TELETYPE, - ftxt.GetStyle(), - ftxt.GetWeight(), - ) - self.resultsTextCtrl.SetFont(font) - return - - # Methods overloaded from PDFPanel - def refresh(self): - """Fill in the resultsTextCtrl with the fit results if they - exist.""" - if self.fit: - self.results = self.fit.res - else: - self.results = "" - if not self.results: - self.results = self.defres - displayed = self.resultsTextCtrl.GetValue() - if displayed != self.results: - lastpos = self.resultsTextCtrl.GetLastPosition() - self.resultsTextCtrl.Replace(0, lastpos, self.results) - return - - -# end of class ResultsPanel diff --git a/src/diffpy/pdfgui/gui/rseriespanel.py b/src/diffpy/pdfgui/gui/rseriespanel.py deleted file mode 100644 index 5c733d2c..00000000 --- a/src/diffpy/pdfgui/gui/rseriespanel.py +++ /dev/null @@ -1,187 +0,0 @@ -#!/usr/bin/env python -# -*- coding: ISO-8859-1 -*- -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -# generated by wxGlade 0.9.3 on Fri Jul 19 16:05:55 2019 - -import wx - -from diffpy.pdfgui.control.pdfguimacros import makeRSeries -from diffpy.pdfgui.gui.pdfpanel import PDFPanel -from diffpy.pdfgui.gui.wxextensions.validators import FLOAT_ONLY, TextValidator - - -class RSeriesPanel(wx.Panel, PDFPanel): - def __init__(self, *args, **kwds): - PDFPanel.__init__(self) - # begin wxGlade: RSeriesPanel.__init__ - kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL - wx.Panel.__init__(self, *args, **kwds) - self.instructionsLabel = wx.StaticText( - self, - wx.ID_ANY, - "Select a fit from the tree on the left and set the first value, last value, \nand the step size of the maximum and/or minimum of the fit range\nbelow. If you have not set up a fit to be the template for the series, hit\ncancel and rerun this macro once a fit has been created.", # noqa: E501 - ) - self.maxFirstLabel = wx.StaticText(self, wx.ID_ANY, "first") - self.maxFirstTextCtrl = wx.TextCtrl(self, wx.ID_ANY, "") - self.maxLastLabel = wx.StaticText(self, wx.ID_ANY, "last") - self.maxLastTextCtrl = wx.TextCtrl(self, wx.ID_ANY, "") - self.maxStepLabel = wx.StaticText(self, wx.ID_ANY, "step") - self.maxStepTextCtrl = wx.TextCtrl(self, wx.ID_ANY, "") - self.minFirstLabel = wx.StaticText(self, wx.ID_ANY, "first") - self.minFirstTextCtrl = wx.TextCtrl(self, wx.ID_ANY, "") - self.minLastLabel = wx.StaticText(self, wx.ID_ANY, "last") - self.minLastTextCtrl = wx.TextCtrl(self, wx.ID_ANY, "") - self.minStepLabel = wx.StaticText(self, wx.ID_ANY, "step") - self.minStepTextCtrl = wx.TextCtrl(self, wx.ID_ANY, "") - self.goButton = wx.Button(self, wx.ID_OK, "OK") - self.cancelButton = wx.Button(self, wx.ID_CANCEL, "Cancel") - - self.__set_properties() - self.__do_layout() - - self.Bind(wx.EVT_BUTTON, self.onOK, self.goButton) - self.Bind(wx.EVT_BUTTON, self.onCancel, self.cancelButton) - # end wxGlade - self.__customProperties() - - def __set_properties(self): - # begin wxGlade: RSeriesPanel.__set_properties - self.instructionsLabel.SetFont( - wx.Font( - 10, - wx.FONTFAMILY_DEFAULT, - wx.FONTSTYLE_NORMAL, - wx.FONTWEIGHT_NORMAL, - 0, - "Sans", - ) - ) - # end wxGlade - - def __do_layout(self): - # begin wxGlade: RSeriesPanel.__do_layout - sizer_1 = wx.BoxSizer(wx.VERTICAL) - sizer_3 = wx.BoxSizer(wx.HORIZONTAL) - sizer_4_copy = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, "fit minimum"), wx.HORIZONTAL) - sizer_4 = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, "fit maximum"), wx.HORIZONTAL) - sizer_1.Add(self.instructionsLabel, 0, wx.ALL | wx.EXPAND, 5) - sizer_4.Add(self.maxFirstLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) - sizer_4.Add(self.maxFirstTextCtrl, 0, wx.ALL, 5) - sizer_4.Add(self.maxLastLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) - sizer_4.Add(self.maxLastTextCtrl, 0, wx.ALL, 5) - sizer_4.Add(self.maxStepLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) - sizer_4.Add(self.maxStepTextCtrl, 0, wx.ALL, 5) - sizer_1.Add(sizer_4, 0, wx.ALL | wx.EXPAND, 5) - sizer_4_copy.Add(self.minFirstLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) - sizer_4_copy.Add(self.minFirstTextCtrl, 0, wx.ALL, 5) - sizer_4_copy.Add(self.minLastLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) - sizer_4_copy.Add(self.minLastTextCtrl, 0, wx.ALL, 5) - sizer_4_copy.Add(self.minStepLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) - sizer_4_copy.Add(self.minStepTextCtrl, 0, wx.ALL, 5) - sizer_1.Add(sizer_4_copy, 0, wx.ALL | wx.EXPAND, 5) - sizer_3.Add((20, 20), 1, wx.EXPAND, 0) - sizer_3.Add(self.goButton, 0, wx.ALL, 5) - sizer_3.Add(self.cancelButton, 0, wx.ALL, 5) - sizer_1.Add(sizer_3, 0, wx.EXPAND, 0) - self.SetSizer(sizer_1) - sizer_1.Fit(self) - self.Layout() - # end wxGlade - - # ################################################ - def __customProperties(self): - """Set the custom properties of this panel.""" - self.fit = None - self.ctrlMap = { - "maxfirst": "maxFirstTextCtrl", - "maxlast": "maxLastTextCtrl", - "maxstep": "maxStepTextCtrl", - "minfirst": "minFirstTextCtrl", - "minlast": "minLastTextCtrl", - "minstep": "minStepTextCtrl", - } - - for var in self.ctrlMap: - setattr(self, var, None) - - for ctrlname in self.ctrlMap.values(): - textCtrl = getattr(self, ctrlname) - textCtrl.SetValidator(TextValidator(FLOAT_ONLY)) - return - - def onOK(self, event): # wxGlade: RSeriesPanel. - """Add make a temperature series and add it to the project.""" - for varname, ctrlname in self.ctrlMap.items(): - textCtrl = getattr(self, ctrlname) - value = textCtrl.GetValue() - if value == "": - value = None - else: - value = float(value) - setattr(self, varname, value) - - org = makeRSeries( - self.mainFrame.control, - self.fit, - self.maxfirst, - self.maxlast, - self.maxstep, - self.minfirst, - self.minlast, - self.minstep, - ) - self.treeCtrlMain.ExtendProjectTree(org, clear=False) - self.mainFrame.needsSave() - self.onCancel(event) - return - - def onCancel(self, event): # wxGlade: RSeriesPanel. - """Return to the main panel.""" - self.mainFrame.setMode("fitting") - self.treeCtrlMain.UnselectAll() - self.mainFrame.switchRightPanel("blank") - return - - def treeSelectionUpdate(self, node): - """Set the current fit when the tree selection changes.""" - nodetype = self.treeCtrlMain.GetNodeType(node) - if nodetype == "fit": - self.fit = self.treeCtrlMain.GetControlData(node) - self.refresh() - return - - def refresh(self): - """Block out OK button if there is no fit. - - This also blocks OK if the fit has no datasets or phases. - """ - # We can't rely on Veto to block unwanted tree selections on windows. - # So, we have to check for errors here. - node = None - nodetype = None - selections = self.treeCtrlMain.GetSelections() - if selections: - node = selections[0] - nodetype = self.treeCtrlMain.GetNodeType(node) - - if node and nodetype == "fit" and self.fit and self.fit.hasDataSets() and self.fit.hasStructures(): - self.goButton.Enable() - else: - self.goButton.Enable(False) - return - - -# end of class RSeriesPanel diff --git a/src/diffpy/pdfgui/gui/sgconstraindialog.py b/src/diffpy/pdfgui/gui/sgconstraindialog.py deleted file mode 100644 index 18d6d20c..00000000 --- a/src/diffpy/pdfgui/gui/sgconstraindialog.py +++ /dev/null @@ -1,263 +0,0 @@ -#!/usr/bin/env python -# -*- coding: ISO-8859-1 -*- -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -# generated by wxGlade 0.9.3 on Fri Jul 19 16:06:06 2019 - -import math - -import wx - -from diffpy.pdfgui.control.controlerrors import ControlValueError -from diffpy.pdfgui.gui.pdfpanel import PDFPanel - - -class SGConstrainDialog(wx.Dialog, PDFPanel): - def __init__(self, *args, **kwds): - PDFPanel.__init__(self) - # begin wxGlade: SGConstrainDialog.__init__ - kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_DIALOG_STYLE - wx.Dialog.__init__(self, *args, **kwds) - self.SetTitle("Space Group Constraints") - - sizer_2 = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, "Space Group Constraints"), wx.VERTICAL) - - self.numConstrainedLabel = wx.StaticText(self, wx.ID_ANY, "") - sizer_2.Add(self.numConstrainedLabel, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 5) - - sizer_3 = wx.BoxSizer(wx.HORIZONTAL) - sizer_2.Add(sizer_3, 0, wx.EXPAND, 0) - - self.sgLabel = wx.StaticText(self, wx.ID_ANY, "Space Group") - sizer_3.Add(self.sgLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) - - self.sgComboBox = wx.ComboBox(self, wx.ID_ANY, choices=["P1"], style=0) - self.sgComboBox.SetSelection(0) - sizer_3.Add(self.sgComboBox, 0, wx.ALL, 5) - - sizer_4 = wx.BoxSizer(wx.HORIZONTAL) - sizer_2.Add(sizer_4, 0, wx.EXPAND, 0) - - self.offsetLabel = wx.StaticText(self, wx.ID_ANY, "Origin Offset") - sizer_4.Add(self.offsetLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) - - self.offsetTextCtrlX = wx.TextCtrl(self, wx.ID_ANY, "0") - sizer_4.Add(self.offsetTextCtrlX, 0, wx.ALL, 5) - - self.offsetTextCtrlY = wx.TextCtrl(self, wx.ID_ANY, "0") - sizer_4.Add(self.offsetTextCtrlY, 0, wx.ALL, 5) - - self.offsetTextCtrlZ = wx.TextCtrl(self, wx.ID_ANY, "0") - sizer_4.Add(self.offsetTextCtrlZ, 0, wx.ALL, 5) - - self.positionCheckBox = wx.CheckBox(self, wx.ID_ANY, "constrain positions") - self.positionCheckBox.SetValue(1) - sizer_2.Add(self.positionCheckBox, 0, wx.ALL, 5) - - self.tfCheckBox = wx.CheckBox(self, wx.ID_ANY, "constrain temperature factors") - self.tfCheckBox.SetValue(1) - sizer_2.Add(self.tfCheckBox, 0, wx.ALL, 5) - - self.static_line_1 = wx.StaticLine(self, wx.ID_ANY) - sizer_2.Add(self.static_line_1, 0, wx.EXPAND, 0) - - sizer_4_copy = wx.BoxSizer(wx.HORIZONTAL) - sizer_2.Add(sizer_4_copy, 0, wx.EXPAND, 0) - - sizer_4_copy.Add((0, 0), 1, wx.EXPAND, 0) - - self.cancelButton = wx.Button(self, wx.ID_CANCEL, "Cancel") - sizer_4_copy.Add(self.cancelButton, 0, wx.ALL, 5) - - self.okButton = wx.Button(self, wx.ID_OK, "OK") - sizer_4_copy.Add(self.okButton, 0, wx.ALL, 5) - - self.SetSizer(sizer_2) - sizer_2.Fit(self) - - self.Layout() - - self.Bind(wx.EVT_COMBOBOX, self.onSGSelect, self.sgComboBox) - self.Bind(wx.EVT_TEXT_ENTER, self.onSGTextEnter, self.sgComboBox) - self.Bind(wx.EVT_TEXT_ENTER, self.onOXTextEnter, self.offsetTextCtrlX) - self.Bind(wx.EVT_TEXT_ENTER, self.onOYTextEnter, self.offsetTextCtrlY) - self.Bind(wx.EVT_TEXT_ENTER, self.onOZTextEnter, self.offsetTextCtrlZ) - self.Bind(wx.EVT_CHECKBOX, self.onPosFlag, self.positionCheckBox) - self.Bind(wx.EVT_CHECKBOX, self.onTempFlag, self.tfCheckBox) - self.Bind(wx.EVT_BUTTON, self.onCancel, self.cancelButton) - self.Bind(wx.EVT_BUTTON, self.onOk, self.okButton) - # end wxGlade - self.__customProperties() - - # ######################################################################### - - def __customProperties(self): - """Set the custom properties.""" - # setting of combo box items was deferred to updateSpaceGroupList() - self.spacegroup = None - self.offset = [0.0, 0.0, 0.0] - self.posflag = True - self.tempflag = True - self.structure = None - self.indices = [] - - self.textCtrls = [ - self.offsetTextCtrlX, - self.offsetTextCtrlY, - self.offsetTextCtrlZ, - ] - - # Set the focus events. - for textctrl in self.textCtrls: - textctrl.Bind(wx.EVT_KILL_FOCUS, self.onKillFocus) - self.sgComboBox.Bind(wx.EVT_KILL_FOCUS, self.onKillFocus) - return - - def updateSpaceGroupList(self): - """Update space group choices in combobox according to - self.structure.getSpaceGroupList(). - - Requires that structure attribute is defined. - """ - self.sgComboBox.Clear() - sglist = self.structure.getSpaceGroupList() - self.spacegroup = self.structure.getSpaceGroup("P1") - for sg in sglist: - self.sgComboBox.Append(sg.short_name) - return - - def setStructure(self, structure): - """Set the structure and update the widgets.""" - self.structure = structure - self.updateSpaceGroupList() - sgname = self.structure.pdffit.get("spcgr") - offset = self.structure.pdffit.get("sgoffset") - if sgname: - self.sgComboBox.SetValue(sgname) - if offset: - self.offsetTextCtrlX.SetValue(str(offset[0])) - self.offsetTextCtrlY.SetValue(str(offset[1])) - self.offsetTextCtrlZ.SetValue(str(offset[2])) - self.updateWidgets() - return - - def getSpaceGroup(self): - """Get the current space group.""" - return self.spacegroup - - def getOffset(self): - """Get the offset.""" - return self.offset - - def getPosFlag(self): - """Get whether the positions should be constrained.""" - return self.posflag - - def getTempFlag(self): - """Get whether the positions should be constrained.""" - return self.tempflag - - def updateWidgets(self): - """Update the widgets.""" - # Update space group - sgname = self.sgComboBox.GetValue() - try: - self.spacegroup = self.structure.getSpaceGroup(sgname) - error = None - except ValueError: - error = "Space group %s does not exist." % sgname - # This changes list box value to the short_name of the new spacegroup - # or to the name of previous spacegroup when getSpaceGroup failed. - self.sgComboBox.SetValue(self.spacegroup.short_name) - # Update offset - for i in range(3): - textctrl = self.textCtrls[i] - val = textctrl.GetValue() - # make sure the value is meaningful - try: - val = float(eval("1.0*" + val, dict(math.__dict__))) - except (NameError, TypeError, SyntaxError): - val = 0 - textctrl.SetValue("%s" % val) - self.offset[i] = val - - # newatoms = len(stemp) - len(self.structure) - s = "" - if len(self.indices) != 1: - s = "s" - message = "%i atom%s selected." % (len(self.indices), s) - self.numConstrainedLabel.SetLabel(message) - - # Raise an error if we had to change the space group - if error: - raise ControlValueError(error) - return - - # # Events - - def onKillFocus(self, event): - """Check value of widgets and update the dialog message.""" - self.updateWidgets() - event.Skip() - return - - def onSGTextEnter(self, event): # wxGlade: SGConstrainDialog. - self.updateWidgets() - return - - def onOXTextEnter(self, event): # wxGlade: SGConstrainDialog. - self.updateWidgets() - return - - def onOYTextEnter(self, event): # wxGlade: SGConstrainDialog. - self.updateWidgets() - return - - def onOZTextEnter(self, event): # wxGlade: SGConstrainDialog. - self.updateWidgets() - return - - def onSGSelect(self, event): # wxGlade: SGConstrainDialog. - self.updateWidgets() - return - - def onOk(self, event): # wxGlade: SGConstrainDialog. - # check to see if the space group is consistent - if not self.structure.isSpaceGroupPossible(self.spacegroup): - message = "The chosen space group is not consistent\n" - message += "with the lattice parameters.\n" - message += "Would you like to proceed anyways?" - d = wx.MessageDialog(self, message, "Inconsistent space group", wx.YES_NO) - code = d.ShowModal() - if code == wx.ID_YES: - self.EndModal(wx.ID_OK) - else: - self.EndModal(wx.ID_OK) - return - - def onCancel(self, event): # wxGlade: SGConstrainDialog. - event.Skip() - return - - def onPosFlag(self, event): # wxGlade: SGConstrainDialog. - self.posflag = self.positionCheckBox.GetValue() - return - - def onTempFlag(self, event): # wxGlade: SGConstrainDialog. - self.tempflag = self.tfCheckBox.GetValue() - return - - -# end of class SGConstrainDialog diff --git a/src/diffpy/pdfgui/gui/sgstructuredialog.py b/src/diffpy/pdfgui/gui/sgstructuredialog.py deleted file mode 100644 index 07319930..00000000 --- a/src/diffpy/pdfgui/gui/sgstructuredialog.py +++ /dev/null @@ -1,249 +0,0 @@ -#!/usr/bin/env python -# -*- coding: ISO-8859-1 -*- -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -# generated by wxGlade 0.9.3 on Fri Jul 19 16:06:15 2019 - -import math - -import wx - -from diffpy.pdfgui.control.controlerrors import ControlValueError -from diffpy.pdfgui.gui.pdfpanel import PDFPanel - - -class SGStructureDialog(wx.Dialog, PDFPanel): - def __init__(self, *args, **kwds): - PDFPanel.__init__(self) - # begin wxGlade: SGStructureDialog.__init__ - kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_DIALOG_STYLE - wx.Dialog.__init__(self, *args, **kwds) - self.SetTitle("Space Group Expansion") - - sizer_2 = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, "Space Group Expansion"), wx.VERTICAL) - - self.numConstrainedLabel = wx.StaticText(self, wx.ID_ANY, "") - sizer_2.Add(self.numConstrainedLabel, 0, wx.ALL, 5) - - sizer_3 = wx.BoxSizer(wx.HORIZONTAL) - sizer_2.Add(sizer_3, 0, wx.EXPAND, 0) - - self.sgLabel = wx.StaticText(self, wx.ID_ANY, "Space Group") - sizer_3.Add(self.sgLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) - - self.sgComboBox = wx.ComboBox(self, wx.ID_ANY, choices=["P1"], style=0) - self.sgComboBox.SetSelection(0) - sizer_3.Add(self.sgComboBox, 0, wx.ALL, 5) - - sizer_4 = wx.BoxSizer(wx.HORIZONTAL) - sizer_2.Add(sizer_4, 0, wx.EXPAND, 0) - - self.offsetLabel = wx.StaticText(self, wx.ID_ANY, "Origin Offset") - sizer_4.Add(self.offsetLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) - - self.offsetTextCtrlX = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_PROCESS_ENTER) - sizer_4.Add(self.offsetTextCtrlX, 0, wx.ALL, 5) - - self.offsetTextCtrlY = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_PROCESS_ENTER) - sizer_4.Add(self.offsetTextCtrlY, 0, wx.ALL, 5) - - self.offsetTextCtrlZ = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_PROCESS_ENTER) - sizer_4.Add(self.offsetTextCtrlZ, 0, wx.ALL, 5) - - self.static_line_1 = wx.StaticLine(self, wx.ID_ANY) - sizer_2.Add(self.static_line_1, 0, wx.EXPAND, 0) - - sizer_4_copy = wx.BoxSizer(wx.HORIZONTAL) - sizer_2.Add(sizer_4_copy, 0, wx.EXPAND, 0) - - sizer_4_copy.Add((0, 0), 1, wx.EXPAND, 0) - - self.cancelButton = wx.Button(self, wx.ID_CANCEL, "Cancel") - sizer_4_copy.Add(self.cancelButton, 0, wx.ALL, 5) - - self.okButton = wx.Button(self, wx.ID_OK, "OK") - sizer_4_copy.Add(self.okButton, 0, wx.ALL, 5) - - self.SetSizer(sizer_2) - sizer_2.Fit(self) - - self.Layout() - - self.Bind(wx.EVT_COMBOBOX, self.onSGSelect, self.sgComboBox) - self.Bind(wx.EVT_TEXT_ENTER, self.onSGTextEnter, self.sgComboBox) - self.Bind(wx.EVT_TEXT_ENTER, self.onOXTextEnter, self.offsetTextCtrlX) - self.Bind(wx.EVT_TEXT_ENTER, self.onOYTextEnter, self.offsetTextCtrlY) - self.Bind(wx.EVT_TEXT_ENTER, self.onOZTextEnter, self.offsetTextCtrlZ) - self.Bind(wx.EVT_BUTTON, self.onCancel, self.cancelButton) - self.Bind(wx.EVT_BUTTON, self.onOk, self.okButton) - # end wxGlade - self.__customProperties() - - # ######################################################################### - - def __customProperties(self): - """Set the custom properties.""" - # setting of combo box items was deferred to updateSpaceGroupList() - self.spacegroup = None - self.offset = [0.0, 0.0, 0.0] - self.structure = None - self.indices = [] - - self.textCtrls = [ - self.offsetTextCtrlX, - self.offsetTextCtrlY, - self.offsetTextCtrlZ, - ] - - # Set the focus events. - for textctrl in self.textCtrls: - textctrl.Bind(wx.EVT_KILL_FOCUS, self.onKillFocus) - self.sgComboBox.Bind(wx.EVT_KILL_FOCUS, self.onKillFocus) - return - - def updateSpaceGroupList(self): - """Update space group choices in combobox according to - self.structure.getSpaceGroupList(). - - Requires that structure attribute is defined. - """ - self.sgComboBox.Clear() - sglist = self.structure.getSpaceGroupList() - self.spacegroup = self.structure.getSpaceGroup("P1") - for sg in sglist: - self.sgComboBox.Append(sg.short_name) - return - - def setStructure(self, structure): - """Set the structure and update the dialog.""" - self.structure = structure - self.updateSpaceGroupList() - sgname = self.structure.pdffit.get("spcgr") - offset = self.structure.pdffit.get("sgoffset") - if sgname: - self.sgComboBox.SetValue(sgname) - if offset: - self.offsetTextCtrlX.SetValue(str(offset[0])) - self.offsetTextCtrlY.SetValue(str(offset[1])) - self.offsetTextCtrlZ.SetValue(str(offset[2])) - self.updateWidgets() - return - - def getSpaceGroup(self): - """Get the current space group.""" - return self.spacegroup - - def getOffset(self): - """Get the offset.""" - return self.offset - - def updateWidgets(self): - """Update the widgets.""" - # Update space group - sgname = self.sgComboBox.GetValue() - try: - self.spacegroup = self.structure.getSpaceGroup(sgname) - error = None - except ValueError: - error = "Space group %s does not exist." % sgname - # This changes list box value to the short_name of the new spacegroup - # or to the name of previous spacegroup when getSpaceGroup failed. - self.sgComboBox.SetValue(self.spacegroup.short_name) - - # Update offset - for i in range(3): - textctrl = self.textCtrls[i] - val = textctrl.GetValue() - # make sure the value is meaningful - try: - val = float(eval("1.0*" + val, dict(math.__dict__))) - except (NameError, TypeError, SyntaxError): - val = 0.0 - textctrl.SetValue("%s" % val) - self.offset[i] = val - - # find how many new atoms would be generated - from diffpy.structure.symmetryutilities import ExpandAsymmetricUnit - - corepos = [self.structure[i].xyz for i in self.indices] - symposeps = self.structure.symposeps - eau = ExpandAsymmetricUnit(self.spacegroup, corepos, sgoffset=self.offset, eps=symposeps) - newsize = sum(eau.multiplicity) - s = "" - if len(self.indices) != 1: - s = "s" - message = "%i atom%s selected. Expanding to %i positions." % ( - len(self.indices), - s, - newsize, - ) - self.numConstrainedLabel.SetLabel(message) - - # Raise an error if we had to change the space group - if error: - raise ControlValueError(error) - return - - # # Events - def onKillFocus(self, event): - """Check value of widgets and update the dialog message.""" - self.updateWidgets() - event.Skip() - return - - def onSGTextEnter(self, event): # wxGlade: SGStructureDialog. - self.updateWidgets() - self.onOk(None) - return - - def onSGSelect(self, event): # wxGlade: SGStructureDialog. - self.updateWidgets() - return - - def onOXTextEnter(self, event): # wxGlade: SGStructureDialog. - self.updateWidgets() - self.onOk(None) - return - - def onOYTextEnter(self, event): # wxGlade: SGStructureDialog. - self.updateWidgets() - self.onOk(None) - return - - def onOZTextEnter(self, event): # wxGlade: SGStructureDialog. - self.updateWidgets() - self.onOk(None) - return - - def onOk(self, event): # wxGlade: SGStructureDialog. - # check to see if the space group is consistent - if not self.structure.isSpaceGroupPossible(self.spacegroup): - message = "The chosen space group is not consistent\n" - message += "with the lattice parameters.\n" - message += "Would you like to proceed anyways?" - d = wx.MessageDialog(self, message, "Inconsistent space group", wx.YES_NO) - code = d.ShowModal() - if code == wx.ID_YES: - self.EndModal(wx.ID_OK) - else: - self.EndModal(wx.ID_OK) - return - - def onCancel(self, event): # wxGlade: SGStructureDialog. - event.Skip() - return - - -# end of class SGStructureDialog diff --git a/src/diffpy/pdfgui/gui/supercelldialog.py b/src/diffpy/pdfgui/gui/supercelldialog.py deleted file mode 100644 index 2e34b2c7..00000000 --- a/src/diffpy/pdfgui/gui/supercelldialog.py +++ /dev/null @@ -1,105 +0,0 @@ -#!/usr/bin/env python -# -*- coding: ISO-8859-1 -*- -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -# generated by wxGlade 0.9.3 on Fri Jul 19 16:06:24 2019 - -import wx - - -class SupercellDialog(wx.Dialog): - def __init__(self, *args, **kwds): - # begin wxGlade: SupercellDialog.__init__ - kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_DIALOG_STYLE - wx.Dialog.__init__(self, *args, **kwds) - self.aLabel = wx.StaticText(self, wx.ID_ANY, "a multiplier") - self.aSpinCtrl = wx.SpinCtrl(self, wx.ID_ANY, "1", min=1, max=10, style=0) - self.bLabel = wx.StaticText(self, wx.ID_ANY, "b multiplier") - self.bSpinCtrl = wx.SpinCtrl(self, wx.ID_ANY, "1", min=1, max=10, style=0) - self.cLabel = wx.StaticText(self, wx.ID_ANY, "c multiplier") - self.cSpinCtrl = wx.SpinCtrl(self, wx.ID_ANY, "1", min=1, max=10, style=0) - self.static_line_1 = wx.StaticLine(self, wx.ID_ANY) - self.cancelButton = wx.Button(self, wx.ID_CANCEL, "Cancel") - self.okButton = wx.Button(self, wx.ID_OK, "OK") - - self.__set_properties() - self.__do_layout() - - self.Bind(wx.EVT_BUTTON, self.onCancel, self.cancelButton) - self.Bind(wx.EVT_BUTTON, self.onOk, self.okButton) - # end wxGlade - self.__customProperties() - - def __set_properties(self): - # begin wxGlade: SupercellDialog.__set_properties - self.SetTitle("Supercell Expansion") - # end wxGlade - - def __do_layout(self): - # begin wxGlade: SupercellDialog.__do_layout - sizer_1 = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, "Supercell Expansion"), wx.VERTICAL) - sizer_4 = wx.BoxSizer(wx.HORIZONTAL) - sizer_3 = wx.BoxSizer(wx.HORIZONTAL) - sizer_2_copy_1 = wx.BoxSizer(wx.HORIZONTAL) - sizer_2_copy = wx.BoxSizer(wx.HORIZONTAL) - sizer_2 = wx.BoxSizer(wx.HORIZONTAL) - sizer_2.Add(self.aLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) - sizer_2.Add(self.aSpinCtrl, 0, wx.ALL, 5) - sizer_1.Add(sizer_2, 0, wx.EXPAND, 0) - sizer_2_copy.Add(self.bLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) - sizer_2_copy.Add(self.bSpinCtrl, 0, wx.ALL, 5) - sizer_1.Add(sizer_2_copy, 0, wx.EXPAND, 0) - sizer_2_copy_1.Add(self.cLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) - sizer_2_copy_1.Add(self.cSpinCtrl, 0, wx.ALL, 5) - sizer_1.Add(sizer_2_copy_1, 0, wx.EXPAND, 0) - sizer_3.Add(self.static_line_1, 1, wx.BOTTOM | wx.EXPAND | wx.TOP, 5) - sizer_1.Add(sizer_3, 0, wx.EXPAND, 0) - sizer_4.Add(self.cancelButton, 0, wx.ALL, 5) - sizer_4.Add(self.okButton, 0, wx.ALL, 5) - sizer_1.Add(sizer_4, 1, wx.EXPAND, 0) - self.SetSizer(sizer_1) - sizer_1.Fit(self) - self.Layout() - # end wxGlade - - # ########################################################################## - - def __customProperties(self): - """Set custom properties.""" - # Set the text validators - self.m = 1 - self.n = 1 - self.o = 1 - return - - def getMNO(self): - """Get the [m, n, o] expansion parameters from the dialog.""" - return [self.m, self.n, self.o] - - def onOk(self, event): # wxGlade: SupercellDialog. - """Accept the expansion.""" - self.m = self.aSpinCtrl.GetValue() - self.n = self.bSpinCtrl.GetValue() - self.o = self.cSpinCtrl.GetValue() - event.Skip() - return - - def onCancel(self, event): # wxGlade: SupercellDialog. - """Get out of here.""" - event.Skip() - return - - -# end of class SupercellDialog diff --git a/src/diffpy/pdfgui/gui/temperatureseriespanel.py b/src/diffpy/pdfgui/gui/temperatureseriespanel.py deleted file mode 100644 index 14d9ce31..00000000 --- a/src/diffpy/pdfgui/gui/temperatureseriespanel.py +++ /dev/null @@ -1,358 +0,0 @@ -#!/usr/bin/env python -# -*- coding: ISO-8859-1 -*- -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -# generated by wxGlade 0.9.3 on Fri Jul 19 16:06:35 2019 - -import os.path -import re - -import wx - -from diffpy.pdfgui.control.pdfguimacros import makeTemperatureSeries -from diffpy.pdfgui.gui import tooltips -from diffpy.pdfgui.gui.pdfpanel import PDFPanel -from diffpy.pdfgui.gui.wxextensions.listctrls import AutoWidthListCtrl -from diffpy.pdfgui.utils import numericStringSort - - -class TemperatureSeriesPanel(wx.Panel, PDFPanel): - def __init__(self, *args, **kwds): - PDFPanel.__init__(self) - # begin wxGlade: TemperatureSeriesPanel.__init__ - kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL - wx.Panel.__init__(self, *args, **kwds) - - sizer_1 = wx.BoxSizer(wx.VERTICAL) - - self.instructionsLabel = wx.StaticText( - self, - wx.ID_ANY, - "Select a fit from the tree on the left then add datasets and assign\ntemperatues below. If you have not set up a fit to be the template\nfor the series, hit cancel and rerun this macro once a fit has been\ncreated.", # noqa: E501 - ) - self.instructionsLabel.SetFont( - wx.Font( - 10, - wx.FONTFAMILY_DEFAULT, - wx.FONTSTYLE_NORMAL, - wx.FONTWEIGHT_NORMAL, - 0, - "Sans", - ) - ) - sizer_1.Add(self.instructionsLabel, 0, wx.ALL | wx.EXPAND, 5) - - sizer_2 = wx.BoxSizer(wx.VERTICAL) - sizer_1.Add(sizer_2, 1, wx.EXPAND, 0) - - sizer_4 = wx.BoxSizer(wx.HORIZONTAL) - sizer_2.Add(sizer_4, 1, wx.EXPAND, 0) - - self.listCtrlFiles = AutoWidthListCtrl( - self, wx.ID_ANY, style=wx.BORDER_SUNKEN | wx.LC_EDIT_LABELS | wx.LC_REPORT - ) - sizer_4.Add(self.listCtrlFiles, 1, wx.ALL | wx.EXPAND, 5) - - sizer_5 = wx.BoxSizer(wx.VERTICAL) - sizer_4.Add(sizer_5, 0, wx.EXPAND, 0) - - sizer_5.Add((0, 0), 1, 0, 0) - - self.buttonUp = wx.BitmapButton(self, wx.ID_ANY, wx.NullBitmap) - self.buttonUp.SetSize(self.buttonUp.GetBestSize()) - sizer_5.Add(self.buttonUp, 0, wx.ALL, 5) - - self.buttonDown = wx.BitmapButton(self, wx.ID_ANY, wx.NullBitmap) - self.buttonDown.SetSize(self.buttonDown.GetBestSize()) - sizer_5.Add(self.buttonDown, 0, wx.ALL, 5) - - sizer_5.Add((0, 0), 1, 0, 0) - - grid_sizer_1 = wx.GridSizer(1, 2, 10, 10) - sizer_1.Add(grid_sizer_1, 0, wx.ALL, 5) - - self.buttonAdd = wx.Button(self, wx.ID_ADD, "Add") - grid_sizer_1.Add(self.buttonAdd, 0, 0, 0) - - self.buttonDelete = wx.Button(self, wx.ID_DELETE, "Delete") - grid_sizer_1.Add(self.buttonDelete, 0, 0, 0) - - self.static_line_1 = wx.StaticLine(self, wx.ID_ANY) - sizer_1.Add(self.static_line_1, 0, wx.EXPAND, 0) - - sizer_3 = wx.BoxSizer(wx.HORIZONTAL) - sizer_1.Add(sizer_3, 0, wx.EXPAND, 0) - - sizer_3.Add((20, 20), 1, wx.EXPAND, 0) - - self.goButton = wx.Button(self, wx.ID_OK, "OK") - sizer_3.Add(self.goButton, 0, wx.ALL, 5) - - self.cancelButton = wx.Button(self, wx.ID_CANCEL, "Cancel") - sizer_3.Add(self.cancelButton, 0, wx.ALL, 5) - - self.SetSizer(sizer_1) - sizer_1.Fit(self) - - self.Layout() - - self.Bind(wx.EVT_LIST_COL_CLICK, self.onColClick, self.listCtrlFiles) - self.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.onEndLabelEdit, self.listCtrlFiles) - self.Bind(wx.EVT_BUTTON, self.onUp, self.buttonUp) - self.Bind(wx.EVT_BUTTON, self.onDown, self.buttonDown) - self.Bind(wx.EVT_BUTTON, self.onAdd, self.buttonAdd) - self.Bind(wx.EVT_BUTTON, self.onDelete, self.buttonDelete) - self.Bind(wx.EVT_BUTTON, self.onOK, self.goButton) - self.Bind(wx.EVT_BUTTON, self.onCancel, self.cancelButton) - # end wxGlade - self.buttonUp.SetBitmapLabel(wx.ArtProvider.GetBitmap(wx.ART_GO_UP)) - self.buttonDown.SetBitmapLabel(wx.ArtProvider.GetBitmap(wx.ART_GO_DOWN)) - self.__customProperties() - - def __customProperties(self): - """Set the custom properties.""" - self.fit = None - self.reverse = False # Reverse the sort? - self.fullpath = "." - self.datasets = [] # Contains (temperature, filename) tuples - # temperature is a float and comes first for easy sorting - - self.listCtrlFiles.InsertColumn(0, "Temperature") - self.listCtrlFiles.InsertColumn(1, "Data Set") - self.listCtrlFiles.SetColumnWidth(0, -2) - - # Define tooltips. - self.setToolTips(tooltips.temperatureseriespanel) - return - - def onEndLabelEdit(self, event): # wxGlade: TemperatureSeriesPanel. - """Update the temperature in the datasets.""" - index = event.GetIndex() - text = event.GetText() - temperature = 300.0 - try: - temperature = float(text) - except ValueError: - event.Veto() - return - if temperature <= 0: - event.Veto() - return - # update the internal information - self.datasets[index][0] = temperature - self.reverse = False - return - - def onOK(self, event): # wxGlade: TemperatureSeriesPanel. - """Let's go!""" - paths = [tp[1] for tp in self.datasets] - temperatures = [tp[0] for tp in self.datasets] - org = makeTemperatureSeries(self.mainFrame.control, self.fit, paths, temperatures) - self.treeCtrlMain.ExtendProjectTree(org, clear=False) - self.mainFrame.needsSave() - self.onCancel(event) - return - - def onCancel(self, event): # wxGlade: TemperatureSeriesPanel. - """Let's go, but not actually do anything.""" - self.mainFrame.setMode("fitting") - self.treeCtrlMain.UnselectAll() - self.mainFrame.switchRightPanel("blank") - return - - def onUp(self, event): # wxGlade: TemperatureSeriesPanel. - """Move an item in the list up.""" - index = self.listCtrlFiles.GetFirstSelected() - if index > 0: - temp = self.datasets[index] - self.datasets[index] = self.datasets[index - 1] - self.datasets[index - 1] = temp - self.fillList() - self.listCtrlFiles.Select(index - 1) - return - - def onDown(self, event): # wxGlade: TemperatureSeriesPanel. - """Move an item in the list down.""" - index = self.listCtrlFiles.GetFirstSelected() - if index > -1 and index != len(self.datasets) - 1: - temp = self.datasets[index] - self.datasets[index] = self.datasets[index + 1] - self.datasets[index + 1] = temp - self.fillList() - self.listCtrlFiles.Select(index + 1) - return - - def onAdd(self, event): # wxGlade: TemperatureSeriesPanel. - """Append files to the list.""" - dir, filename = os.path.split(self.fullpath) - if not dir: - dir = self.mainFrame.workpath - - matchstring = "PDF data files (*.gr)|*.gr|PDF fit files (*.fgr)|*.fgr|PDF fit files (*.fit)|*.fit|PDF calculation files (*.cgr)|*.cgr|PDF calculation files (*.calc)|*.calc|All Files|*" # noqa: E501 - d = wx.FileDialog( - None, - "Choose files", - dir, - "", - matchstring, - wx.FD_OPEN | wx.FD_FILE_MUST_EXIST | wx.FD_MULTIPLE, - ) - paths = [] - if d.ShowModal() == wx.ID_OK: - paths = d.GetPaths() - d.Destroy() - - # Assign the temperatures. Default to 300.0 - newdatasets = [] - for path in paths: - self.fullpath = path - self.mainFrame.workpath = os.path.dirname(path) - - # Look for the temperature in the filename - temperature = 300.0 - rx = {"f": r"(?:\d+(?:\.\d*)?|\d*\.\d+)"} - # Search for T123, t123, Temp123, temp123, 123k, 123K. - # Some filenames fool this, e.g. "test1.dat" will match '1' since it - # is preceded by a 't'. - # Is there a better regexp? Probably... - regexp = ( - r"""(?:[Tt](?:emp(?:erature)?)?(%(f)s))| - (?:(? - """Delete selected files from the list.""" - idxlist = [] - item = self.listCtrlFiles.GetFirstSelected() - while item != -1: - idxlist.append(item) - item = self.listCtrlFiles.GetNextSelected(item) - - idxlist.reverse() - for item in idxlist: - del self.datasets[item] - self.fillList() - return - - def onColClick(self, event): # wxGlade: TemperatureSeriesPanel. - """Sort by temperature.""" - column = event.GetColumn() - # sort by temperature - if column == 0: - sortkey = lambda tf: float(tf[0]) # noqa: E731 - # sort by filename with numerical comparison of digits - elif column == 1: - filenames = [f for t, f in self.datasets] - numericStringSort(filenames) - order = dict(zip(filenames, range(len(filenames)))) - sortkey = lambda tf: order[tf[1]] # noqa: E731 - # ignore unhandled columns - else: - return - self.datasets.sort(key=sortkey, reverse=self.reverse) - self.reverse = not self.reverse - self.fillList() - return - - # Utility functions - def fillList(self): - """Fill the list with the datasets.""" - self.listCtrlFiles.DeleteAllItems() - names = [pair[1] for pair in self.datasets] - cp = os.path.commonprefix(names) - # We want to break at the last path/separator in the common prefix - idx = cp.rfind(os.path.sep) - if idx == -1: - idx = len(cp) - for temperature, filename in self.datasets: - shortname = "..." + filename[idx:] - # index = self.listCtrlFiles.InsertItem(sys.maxsize, str(temperature)) #doesn't work for windows - index = self.listCtrlFiles.InsertItem(100000, str(temperature)) - self.listCtrlFiles.SetItem(index, 1, shortname) - return - - # Needed by mainframe - def treeSelectionUpdate(self, node): - """Set the current fit when the tree selection changes.""" - nodetype = self.treeCtrlMain.GetNodeType(node) - if nodetype == "fit": - self.fit = self.treeCtrlMain.GetControlData(node) - self.refresh() - return - - # Required by PDFPanel - def refresh(self): - """Block out OK button if there is no fit. - - This also blocks OK if the fit has no datasets or structures. - """ - # We can't rely on Veto to block unwanted tree selections on windows. - # So, we have to check for errors here. - node = None - nodetype = None - selections = self.treeCtrlMain.GetSelections() - if selections: - node = selections[0] - nodetype = self.treeCtrlMain.GetNodeType(node) - - if node and nodetype == "fit" and self.fit and self.fit.hasDataSets() and self.fit.hasStructures(): - self.goButton.Enable() - else: - self.goButton.Enable(False) - return - - -# end of class TemperatureSeriesPanel diff --git a/src/diffpy/pdfgui/gui/tooltips.py b/src/diffpy/pdfgui/gui/tooltips.py deleted file mode 100644 index 3d7fdedd..00000000 --- a/src/diffpy/pdfgui/gui/tooltips.py +++ /dev/null @@ -1,192 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2007 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Dmitriy Bryndin -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""Tooltips for pdfgui panels.""" - - -def isalias(s): - return s[1:-1] and s[:: len(s) - 1] == "{}" and s[1:-1].replace("_", "").isalnum() - - -def _expand_tooltip_aliases(ttps): - "Replace aliased equivalent values {other} in tooltip strings." - for n, t in list(ttps.items()): - if not isalias(t): - continue - t1 = t.format(**ttps) - assert not isalias(t1), "chained tooltip alias is not allowed" - ttps[n] = t1 - return ttps - - -datasetconfigurepanel = { - # 'panelNameLabel' : '', # StaticText "Data Set Configuration" - "radioBoxStype": "Radiation type", # RadioBox "Scatterer Type", choices=["Neutron", "X-ray"] - "radioBoxSampling": "Fit sampling type", # RadioBox "Scatterer Type", choices=["Default", "Nyquist", "Custom"] - # 'labelDataRange' : '', # StaticText "Data Range" - "textCtrlDataFrom": "Data r_min", # TextCtrl - # 'labelDataTo' : '', # StaticText "to" - "textCtrlDataTo": "Data r_max", # TextCtrl - # 'labelFitRange' : '', # StaticText "Fit Range" - "textCtrlDataStep": "Step size in the data", # TextCtrl - "textCtrlFitFrom": "Fit r_min", # TextCtrl - # 'labelFitTo' : '', # StaticText "to" - "textCtrlFitTo": "Fit r_max", # TextCtrl - "textCtrlFitStep": "Step size in the fit", # TextCtrl - # 'labelScaleFactor' : '', # StaticText "Scale Factor" - "textCtrlScaleFactor": "Data scale factor", # TextCtrl - # 'labelQmax' : '', # StaticText "Qmax" - "textCtrlQmax": "Upper limit used for Fourier transform to obtain data PDF", # TextCtrl - # 'labelQdamp' : '', # StaticText "Qdamp" - "textCtrlQdamp": "Resolution dampening factor", # TextCtrl - # 'labelQbroad' : '', # StaticText "Qbroad" - "textCtrlQbroad": "Resolution peak broadening factor", # TextCtrl - # 'labelTemperature' : '', # StaticText "Temperature" - "textCtrlTemperature": "Temperature at which the data were collected", # TextCtrl - # 'labelDoping' : '', # StaticText "Doping" - "textCtrlDoping": "Sample characteristic doping level (if applicable)", # TextCtrl -} - -datasetconstraintpanel = { - "panelNameLabel": "", # StaticText "Data Set Constraints" - "labelScaleFactor": "", # StaticText "Scale Factor" - "textCtrlScaleFactor": "Data scale factor", # TextCtrl - "labelQdamp": "", # StaticText "Qdamp" - "textCtrlQdamp": "Resolution dampening factor", # TextCtrl - "labelQbroad": "", # StaticText "Qbroad" - "textCtrlQbroad": "Resolution peak broadening factor", # TextCtrl -} - -datasetresultspanel = { - "panelNameLabel": "", # StaticText "Data Set Results" - "labelScaleFactor": "", # StaticText "Scale Factor" - "textCtrlScaleFactor": "Data scale factor", # TextCtrl - "labelQdamp": "", # StaticText "Qdamp" - "textCtrlQdamp": "Resolution dampening factor", # TextCtrl - "labelQbroad": "", # StaticText "Qbroad" - "textCtrlQbroad": "Resolution peak broadening factor", # TextCtrl -} - - -dopingseriespanel = { - # 'instructionsLabel' : '', # StaticText "Select a fit from the tree on the left then add - # datasets and assign\ndoping elements and values below. If you - # have not set up a fit to be\nthe template for the series, hit - # cancel and rerun this macro once a\nfit has been created." - # 'labelBaseElement' : '', # StaticText "Base element" - # 'textCtrlBaseElement' : '', # TextCtrl - # 'labelDopant' : '', # StaticText "Dopant" - # 'textCtrlDopant' : '', # TextCtrl - "listCtrlFiles": "Click header to sort by doping", # AutoWidthListCtrl - # 'buttonUp' : '', # BitmapButton - # 'buttonDown' : '', # BitmapButton - # 'buttonAdd' : '', # Button "Add" - # 'buttonDelete' : '', # Button "Delete" - # 'goButton' : '', # Button "OK" - # 'cancelButton' : '', # Button "Cancel" -} - -phasepanel = _expand_tooltip_aliases( - { - # 'sizerLatticeParameters_staticbox' : '', # StaticBox - # 'sizerAdditionalParameters_staticbox' : '', # StaticBox - # 'sizerAtoms_staticbox' : '', # StaticBox - # 'sizerPanelName_staticbox' : '', # StaticBox - # 'labelPanelName' : '', # StaticText "Phase Configuration" - "labelA": "{textCtrlA}", # StaticText "a" - "textCtrlA": "Lattice parameter a", # TextCtrl - "labelB": "{textCtrlB}", # StaticText "b" - "textCtrlB": "Lattice parameter b", # TextCtrl - "labelC": "{textCtrlC}", # StaticText "c" - "textCtrlC": "Lattice parameter c", # TextCtrl - "labelAlpha": "{textCtrlAlpha}", # StaticText "alpha" - "textCtrlAlpha": "Lattice angle alpha", # TextCtrl - "labelBeta": "{textCtrlBeta}", # StaticText "beta" - "textCtrlBeta": "Lattice angle beta", # TextCtrl - "labelGamma": "{textCtrlGamma}", # StaticText "gamma" - "textCtrlGamma": "Lattice angle gamma", # TextCtrl - "labelScaleFactor": "{textCtrlScaleFactor}", # StaticText "Scale Factor" - "textCtrlScaleFactor": "Phase scale factor", # TextCtrl - "labelDelta1": "{textCtrlDelta1}", # StaticText "delta1" - "textCtrlDelta1": "Linear atomic correlation factor", # TextCtrl - "labelDelta2": "{textCtrlDelta2}", # StaticText "delta2" - "textCtrlDelta2": "Quadratic atomic correlation factor", # TextCtrl - "labelSratio": "{textCtrlSratio}", # StaticText "sratio" - "textCtrlSratio": "Low r peak sharpening", # TextCtrl - "labelRcut": "{textCtrlRcut}", # StaticText "rcut" - "textCtrlRcut": "Peak sharpening cutoff", # TextCtrl - "labelStepcut": "{textCtrlStepcut}", # StaticText "stepcut" - "textCtrlStepcut": "Cutoff for profile step-function", # TextCtrl - "labelSpdiameter": "{textCtrlSpdiameter}", # StaticText "Spdiameter" - "textCtrlSpdiameter": "Spherical nanoparticle amplitude correction", - # 'labelIncludedPairs' : '', # StaticText "Included Pairs" - "textCtrlIncludedPairs": """[!]{element|indexOrRange|all}-[!]{element|indexOrRange|all} -Examples: -all-all all possible pairs -Na-Na only Na-Na pairs -all-all, !Na- all pairs except Na-Na -all-all, -!Na same as previous -Na-1:4 pairs of Na and first 4 atoms -all-all, !Cl-!Cl exclude any pairs containing Cl -all-all, !Cl-, -!Cl same as previous -1-all only pairs including the first atom""", # TextCtrl "all-all" - # 'gridAtoms' : '', # AutoWidthLabelsGrid - } -) - - -plotpanel = { - # 'xDataCombo' : '', # ComboBox - # 'yDataList' : '', # KeyEventsListCtrl - "offsetLabel": "The vertical gap between stacked plots", # StaticText "offset" - # 'offsetTextCtrl' : '', # TextCtrl - "plotButton": "Plot the selected data", # Button "Plot" - "resetButton": "Reset the plot configuration", # Button "Reset" -} - - -preferencespanel = { - "structureDirCheckBox": ( - "Remember the structures directory across sessions. " - "If unchecked, the initial structures directory will " - "default to the current path." - ), - "dataDirCheckBox": ( - "Remember the data set directory across sessions. " - "If unchecked, the initial data set directory will " - "default to the current path." - ), - "textCtrlViewer": ("The name of the structure viewer executable, " "e.g., 'atomeye' or 'pymol'."), - "textCtrlArgument": """\ -The command-line arguments to the structure viewer. -'%s' represents the file name that will be passed to the viewer. -Command-line switches placed here will be passed as well. -E. g. '%s' or '-c %s' (for pymol).\ - """, - "choiceFormat": "Choose a file format the structure viewer accepts.", -} - - -temperatureseriespanel = { - # 'instructionsLabel' : '', # StaticText "Select a fit from the tree on the left - # then add datasets and assign\ntemperatues below. If you have not set up a fit to - # be the template\nfor the series, hit cancel and rerun this macro once a fit has been\ncreated." - "listCtrlFiles": "Click header to sort by temperature", # AutoWidthListCtrl - # 'buttonUp' : '', # BitmapButton - # 'buttonDown' : '', # BitmapButton - # 'buttonAdd' : '', # Button "Add" - # 'buttonDelete' : '', # Button "Delete" - # 'goButton' : '', # Button "OK" - # 'cancelButton' : '', # Button "Cancel" -} diff --git a/src/diffpy/pdfgui/gui/welcomepanel.py b/src/diffpy/pdfgui/gui/welcomepanel.py deleted file mode 100644 index 6aee2c37..00000000 --- a/src/diffpy/pdfgui/gui/welcomepanel.py +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env python -# -*- coding: UTF-8 -*- -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## - -# generated by wxGlade 0.6.3 on Wed Mar 11 13:17:19 2009 - -import wx - -from diffpy.pdfgui.gui.pdfguiglobals import iconpath -from diffpy.pdfgui.gui.pdfpanel import PDFPanel - - -class WelcomePanel(wx.Panel, PDFPanel): - def __init__(self, *args, **kwds): - PDFPanel.__init__(self) - wx.Panel.__init__(self, *args, **kwds) - kwds["style"] = wx.TAB_TRAVERSAL - bitmap = wx.Bitmap(iconpath("titlepage.png")) - self.bitmap_1 = wx.StaticBitmap(self, -1, bitmap) - - self.__set_properties() - self.__do_layout() - return - - def __set_properties(self): - return - - def __do_layout(self): - sizer_1 = wx.BoxSizer(wx.HORIZONTAL) - sizer_2 = wx.BoxSizer(wx.VERTICAL) - sizer_2.Add(self.bitmap_1, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_CENTER_VERTICAL, 0) - sizer_1.Add(sizer_2, 1, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_CENTER_VERTICAL, 0) - self.SetSizer(sizer_1) - sizer_1.Fit(self) - return - - # Methods overloaded from PDFPanel - def refresh(self): - return - - -# end of class WelcomePanel diff --git a/src/diffpy/pdfgui/gui/windowperspective.py b/src/diffpy/pdfgui/gui/windowperspective.py deleted file mode 100644 index 8abf2726..00000000 --- a/src/diffpy/pdfgui/gui/windowperspective.py +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2007 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""This contains the default perspective for the gui window.""" - -default = "layout2|name=dseries;caption=;state=770;dir=5;layer=0;row=0;pos=0;prop=100000;bestw=400;besth=380;minw=190;minh=200;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=calculation;caption=;state=770;dir=5;layer=0;row=0;pos=0;prop=100000;bestw=400;besth=380;minw=190;minh=200;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=welcome;caption=;state=768;dir=5;layer=0;row=0;pos=0;prop=100000;bestw=400;besth=380;minw=190;minh=200;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=adddata;caption=;state=770;dir=5;layer=0;row=0;pos=0;prop=100000;bestw=400;besth=380;minw=190;minh=200;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=serverconfig;caption=;state=770;dir=5;layer=0;row=0;pos=0;prop=100000;bestw=400;besth=380;minw=190;minh=200;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=addphase;caption=;state=770;dir=5;layer=0;row=0;pos=0;prop=100000;bestw=400;besth=380;minw=190;minh=200;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=blank;caption=;state=770;dir=5;layer=0;row=0;pos=0;prop=100000;bestw=400;besth=380;minw=190;minh=200;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=phase;caption=;state=770;dir=5;layer=0;row=0;pos=0;prop=100000;bestw=400;besth=380;minw=190;minh=200;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=dataset;caption=;state=770;dir=5;layer=0;row=0;pos=0;prop=100000;bestw=400;besth=380;minw=190;minh=200;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=preferences;caption=;state=770;dir=5;layer=0;row=0;pos=0;prop=100000;bestw=400;besth=380;minw=190;minh=200;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=fit;caption=;state=770;dir=5;layer=0;row=0;pos=0;prop=100000;bestw=400;besth=380;minw=190;minh=200;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=rseries;caption=;state=770;dir=5;layer=0;row=0;pos=0;prop=100000;bestw=400;besth=380;minw=190;minh=200;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=tseries;caption=;state=770;dir=5;layer=0;row=0;pos=0;prop=100000;bestw=400;besth=380;minw=190;minh=200;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=outputPanel;caption=PDFfit2 Output;state=10487804;dir=3;layer=0;row=0;pos=0;prop=100000;bestw=400;besth=40;minw=200;minh=40;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=treeCtrlMain;caption=Fit Tree;state=10487804;dir=4;layer=0;row=0;pos=0;prop=100000;bestw=200;besth=100;minw=200;minh=40;maxw=-1;maxh=-1;floatx=471;floaty=730;floatw=208;floath=124|name=plotPanel;caption=Plot Control;state=10487804;dir=4;layer=0;row=0;pos=1;prop=100000;bestw=200;besth=250;minw=200;minh=150;maxw=-1;maxh=-1;floatx=337;floaty=393;floatw=208;floath=274|name=journalPanel;caption=Project Journal;state=10487807;dir=4;layer=0;row=0;pos=0;prop=100000;bestw=450;besth=450;minw=200;minh=200;maxw=-1;maxh=-1;floatx=393;floaty=113;floatw=450;floath=450|dock_size(3,0,0)=59|dock_size(4,0,0)=202|dock_size(5,0,0)=362|" # noqa: E501 diff --git a/src/diffpy/pdfgui/gui/wxextensions/__init__.py b/src/diffpy/pdfgui/gui/wxextensions/__init__.py deleted file mode 100644 index 28609540..00000000 --- a/src/diffpy/pdfgui/gui/wxextensions/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# wxextensions by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""Extensions to wxPython used in PDFgui.""" - -# End of file diff --git a/src/diffpy/pdfgui/gui/wxextensions/autowidthlabelsgrid.py b/src/diffpy/pdfgui/gui/wxextensions/autowidthlabelsgrid.py deleted file mode 100644 index 5afcb076..00000000 --- a/src/diffpy/pdfgui/gui/wxextensions/autowidthlabelsgrid.py +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# wxextensions by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Dmitriy Bryndin -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""This module contains AutoWidthListCtrl, a wxListCtrl object that -automatically adjusts the width of its columns.""" - - -import wx -import wx.grid - - -class AutoWidthLabelsGrid(wx.grid.Grid): - """Wx grid which allows labels auto sizing.""" - - # def __init__(self, parent, state, size): - # wx.grid.Grid.__init__(self, parent, state, size) - - def AutosizeLabels(self, rows=True, cols=False): - # Common setup. - devContext = wx.ScreenDC() - devContext.SetFont(self.GetLabelFont()) - - # First do row labels. - if rows: - maxWidth = 0 - curRow = self.GetNumberRows() - 1 - while curRow >= 0: - curWidth = devContext.GetTextExtent("M%s" % (self.GetRowLabelValue(curRow)))[0] - if curWidth > maxWidth: - maxWidth = curWidth - curRow = curRow - 1 - self.SetRowLabelSize(maxWidth) - - # Then column labels. - if cols: - maxHeight = 0 - curCol = self.GetNumberCols() - 1 - while curCol >= 0: - (w, h, d, l) = devContext.GetFullTextExtent(self.GetColLabelValue(curCol)) - curHeight = h + d + l + 4 - if curHeight > maxHeight: - maxHeight = curHeight - curCol = curCol - 1 - self.SetColLabelSize(maxHeight) - return - - -# End of class AutoWidthLabelsGrid diff --git a/src/diffpy/pdfgui/gui/wxextensions/listctrls.py b/src/diffpy/pdfgui/gui/wxextensions/listctrls.py deleted file mode 100644 index 5f693f04..00000000 --- a/src/diffpy/pdfgui/gui/wxextensions/listctrls.py +++ /dev/null @@ -1,191 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# wxextensions by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""This module contains custom wxListCtrl subclasses. -AutoWidthListCtrl - A wxListCtrl object that automatically adjusts the width of -its columns. -ColumnSortListCtrl - An AutoWidthListCtrl that sorts its entries when the column -header is clicked. -KeyEventsListCtrl - A ColumnSortListCtrl that selects and item as you type its -name. -""" - - -import wx -import wx.lib.mixins.listctrl as listmix - - -class AutoWidthListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin): - """WxListCtrl subclass that automatically adjusts its column - width.""" - - def __init__(self, parent, ID, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, *args, **kwargs): - wx.ListCtrl.__init__(self, parent, ID, pos, size, style, *args, **kwargs) - listmix.ListCtrlAutoWidthMixin.__init__(self) - - def clearSelections(self): - """Clear all selections in the list.""" - for item in range(self.GetItemCount()): - self.Select(item, on=0) - return - - def setSelection(self, itemtext=None): - """Convenience function for simple selection of a list item by - label. - - itemtext -- The label of the item to select. If itemtext is None - (default) then all items will be deselected. - """ - # Clear all selections - self.clearSelections() - - # Set the selected item - item = 0 - if itemtext: - item = self.FindItem(-1, itemtext) - self.Select(item) - self.Focus(item) - return item - - -# end AutoWidthListCtrl - - -class ColumnSortListCtrl(AutoWidthListCtrl, listmix.ColumnSorterMixin): - """AutoWidthListCtrl subclass that sorts its columns when the column - header is pressed. - - This ListCtrl requires an itemDataMap member dictionary to be - initialized before the sorting capabilities can be realized. This - dictionary simply references the ListCtrl's entries by a unique - number. This number must be stored as the ItemData (with - SetItemData) of the entry. The member data must be in the form of a - tuple, where the tuple has a number of entries as the ListCtrl has - columns. The sorting routine sorts the items in the ListCtrl by the - entries in this tuple. - """ - - def __init__(self, parent, ID, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, *args, **kwargs): - AutoWidthListCtrl.__init__(self, parent, ID, pos, size, style, *args, **kwargs) - listmix.ListCtrlAutoWidthMixin.__init__(self) - - def GetListCtrl(self): - """This method is required by the sorter mixin.""" - return self - - def initializeSorter(self): - """Initialize the column sorter mixin after the ListCtrl is - filled. - - This method must be called whenever the itemDataMap is altered. - """ - numcol = self.GetColumnCount() - listmix.ColumnSorterMixin.__init__(self, numcol) - return - - def makeIDM(self): - """This method automatically sets up the itemDataMap. - - The itemDataMap gets filled with the current ListCtrl entries. - The itemDataMap does not update automatically when the list is - changed. To update the itemDataMap this method must be called - again. initializeSorter should be called after a call to this - method. - """ - numcol = self.GetColumnCount() - numrow = self.GetItemCount() - self.itemDataMap = {} - for i in range(numrow): - infolist = [] - for j in range(numcol): - infolist.append(self.GetItem(i, j).GetText()) - self.itemDataMap[i + 1] = tuple(infolist) - self.SetItemData(i, i + 1) - return - - -# end ColumnSortListCtrl - - -class KeyEventsListCtrl(ColumnSortListCtrl): - """ColumnSortListCtrl that catches key events and selects the item - that matches. - - It only searches for items in the first column. - """ - - def __init__(self, parent, id, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, *args, **kwargs): - ColumnSortListCtrl.__init__(self, parent, id, pos, size, style, *args, **kwargs) - self.typedText = "" - self.Bind(wx.EVT_KEY_DOWN, self.OnKey) - - def findPrefix(self, prefix): - if prefix: - prefix = prefix.lower() - length = len(prefix) - - for x in range(self.GetItemCount()): - text = self.GetItemText(x) - text = text.lower() - - if text[:length] == prefix: - return x - - return -1 - - def OnKey(self, evt): - key = evt.GetKeyCode() - - # Select All - Ctrl+A - if evt.ControlDown() and key == 65: - for item in range(self.GetItemCount()): - self.Select(item) - return - - # Search for name - if key >= 32 and key <= 127: - self.typedText = self.typedText + chr(key) - item = self.findPrefix(self.typedText) - - if item != -1: - itemtext = self.GetItemText(item) - self.setSelection(itemtext) - - elif key == wx.WXK_BACK: - self.typedText = self.typedText[:-1] - - if not self.typedText: - itemtext = self.GetItemText(0) - self.setSelection(itemtext) - else: - item = self.findPrefix(self.typedText) - - if item != -1: - itemtext = self.GetItemText(item) - self.setSelection(itemtext) - - else: - self.typedText = "" - evt.Skip() - - def OnKeyDown(self, evt): - pass - - -# End of class KeyEventsListCtrl - -# verify inheritance of all ListCtrl classes -assert issubclass(AutoWidthListCtrl, wx.ListCtrl) -assert issubclass(ColumnSortListCtrl, wx.ListCtrl) -assert issubclass(KeyEventsListCtrl, wx.ListCtrl) diff --git a/src/diffpy/pdfgui/gui/wxextensions/paneldialog.py b/src/diffpy/pdfgui/gui/wxextensions/paneldialog.py deleted file mode 100644 index 4089c224..00000000 --- a/src/diffpy/pdfgui/gui/wxextensions/paneldialog.py +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env python -# -*- coding: UTF-8 -*- -# generated by wxGlade 0.4.1 on Wed Mar 29 15:15:14 2006 -############################################################################## -# -# wxextensions by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Dmitriy Bryndin -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""This module contains the PanelDialog class, a simple class that turns -any panel into a dialog.""" - - -import wx - - -class PanelDialog(wx.Dialog): - """This class will turn any panel into a dialog. - - Using this makes for quicker development and encourages the - developer to design a gui as a collection of panels, instead of a - monolithic mega-panel. - """ - - def __init__(self, *args, **kwds): - """Initialize the PanelDialog. - - This takes the same args and kwds as wxDialog. See the wxDialog - documentation for more information. - - Unless specified, style is automatically set as - wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER - - Creating a PanelDialog requires three steps. 1) Create the - PanelDialog. 2) Create the Panel, with the new PanelDialog as - the parent. 3) Call the setPanel method of the PanelDialog with - the new Panel as the the argument. - """ - if not hasattr(kwds, "style"): - kwds["style"] = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER - wx.Dialog.__init__(self, *args, **kwds) - return - - def setPanel(self, panel): - """Call this method to add the panel to the dialog.""" - self.panel = panel - self.__set_properties() - self.__do_layout() - return - - def __set_properties(self): - return - - def __do_layout(self): - sizer_1 = wx.BoxSizer(wx.HORIZONTAL) - sizer_1.Add(self.panel, 1, wx.EXPAND, 0) - self.SetAutoLayout(True) - self.SetSizer(sizer_1) - sizer_1.Fit(self) - sizer_1.SetSizeHints(self) - self.Layout() - return - - -# End of class PanelDialog diff --git a/src/diffpy/pdfgui/gui/wxextensions/textctrlutils.py b/src/diffpy/pdfgui/gui/wxextensions/textctrlutils.py deleted file mode 100644 index 35466d67..00000000 --- a/src/diffpy/pdfgui/gui/wxextensions/textctrlutils.py +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env python -# -*- coding: UTF-8 -*- -############################################################################## -# -# wxextensions by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2009-2024 trustees of Columbia University in the City of -# New York. -# All rights reserved. -# -# File coded by: Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""This module contains utilities that can be used with wxTextCtrls.""" - - -import wx - - -def textCtrlAsGridCell(panel, event): - """Process a textCtrl key event as if the textCtrl was a grid cell. - - This catches ESC and ENTER events in textCtrls and processes them as if the - textCtrl were a grid cell. This method can be bound to the wx.EVT_KEY_DOWN - event of any textCtrl. See phaseconfigurepanel.py in diffpy.pdfgui.gui for - an example. - - ESC -- Cancel the edit and highlight the text. This requires that - panel has a _focusedText attribute that stores the previous - value. - ENTER -- Confirm the edit and move to the next cell (the default TAB - behavior). - """ - key = event.GetKeyCode() - - textctrl = event.GetEventObject() - - # ESC - cancel the edit - if key == 27: - # Restore the original value - textctrl.ChangeValue(panel._focusedText) - # Now reselect the text - wx.CallAfter(textctrl.SetSelection, -1, -1) - # ENTER - Act like TAB - elif key == 13: - wx.CallAfter(textctrl.Navigate) - else: - event.Skip() - return diff --git a/src/diffpy/pdfgui/gui/wxextensions/validators.py b/src/diffpy/pdfgui/gui/wxextensions/validators.py deleted file mode 100644 index 8f39454f..00000000 --- a/src/diffpy/pdfgui/gui/wxextensions/validators.py +++ /dev/null @@ -1,134 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# wxextensions by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Chris Farrow -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -import string - -import wx - -"""This module contains TextValidator, which is an input validator for the -wxTextCtrl. See the wxPython documentation for wxTextCtrl for more about text -validators. Three constants are defined for use in TextValidator: ALPHA_ONLY, -DIGIT_ONLY, and FLOAT_ONLY. See the TextValidator class for how these are used. -""" - -ALPHA_ONLY = 1 -DIGIT_ONLY = 2 -FLOAT_ONLY = 3 - - -class TextValidator(wx.Validator): - """This validator is designed to check text input for wxTextCtrls. - - (It might have uses in other widgets.) It can validate for letters - only, digits only, floats only, and can allow for a negative at the - beginning of a digit string or a negative float. - """ - - def __init__(self, flag=DIGIT_ONLY, allowNeg=False): - """Initialize the validator. - - flag -- DIGIT_ONLY, allow only digits (default) - ALPHA_ONLY, allow only letters - FLOAT_ONLY, allow only floats - - allowNeg -- Allow a negative sign in front of DIGIT_ONLY, or - FLOAT_ONLY text. (default False) - """ - wx.Validator.__init__(self) - self.flag = flag - self.allowNeg = allowNeg - self.Bind(wx.EVT_CHAR, self.OnChar) - - def Clone(self): - return TextValidator(self.flag, self.allowNeg) - - def Validate(self, win): - tc = self.GetWindow() - val = tc.GetValue() - - if self.flag == ALPHA_ONLY: - return val.isalpha() - - elif self.flag == DIGIT_ONLY: - if self.allowNeg: - val1 = val[:1].lstrip("-") + val[1:] - else: - val1 = val - return val1.isdigit() - - elif self.flag == FLOAT_ONLY: - try: - x = float(val) - if x < 0 and not self.allowNeg: - return False - except ValueError: - return False - - return True - - def OnChar(self, event): - key = event.GetKeyCode() - - if key < wx.WXK_SPACE or key == wx.WXK_DELETE or key > 255: - event.Skip() - return - - if self.flag == ALPHA_ONLY and chr(key) in string.ascii_letters: - event.Skip() - return - - # resolve the new value here - win = self.GetWindow() - val = win.GetValue() - insertion = win.GetInsertionPoint() - first, last = win.GetSelection() - if first != last: - val = val[:first] + val[last:] - insertion = first - newval = val[:insertion] + chr(key) + val[insertion:] - - if self.flag == DIGIT_ONLY: - newval1 = newval - if self.allowNeg: - newval1 = newval[:1].lstrip("-") + newval[1:] - if newval1.isdigit(): - event.Skip() - return - - if self.flag == FLOAT_ONLY: - try: - x = float(newval + "1") # Catches "1e", a float to be - if x >= 0 or self.allowNeg: - event.Skip() - return - - except ValueError: - pass - - if not wx.Validator.IsSilent(): - wx.Bell() - - # Returning without calling even. Skip eats the event before it - # gets to the text control - return - - # These are needed so the validator can work in dialogs. - def TransferToWindow(self): - return True - - def TransferFromWindow(self): - return True - - -# End of class TextValidator diff --git a/src/diffpy/pdfgui/icons/C60-16x16.png b/src/diffpy/pdfgui/icons/C60-16x16.png deleted file mode 100644 index b690b509..00000000 Binary files a/src/diffpy/pdfgui/icons/C60-16x16.png and /dev/null differ diff --git a/src/diffpy/pdfgui/icons/C60_202x202.xcf b/src/diffpy/pdfgui/icons/C60_202x202.xcf deleted file mode 100644 index 14a692fc..00000000 Binary files a/src/diffpy/pdfgui/icons/C60_202x202.xcf and /dev/null differ diff --git a/src/diffpy/pdfgui/icons/__init__.py b/src/diffpy/pdfgui/icons/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/src/diffpy/pdfgui/icons/buckyfccicon.m b/src/diffpy/pdfgui/icons/buckyfccicon.m deleted file mode 100644 index 9257c3f4..00000000 --- a/src/diffpy/pdfgui/icons/buckyfccicon.m +++ /dev/null @@ -1,102 +0,0 @@ -function stru = c60fccstru(varargin) -% BUCKYFCCICON generate PDFFIT style stru file of C60 fcc lattice -% STRU = BUCKYFCCICON returns a string -% BUCKYFCCICON accepts optional parameter-value pairs, which may be: -% 'a' [10*sqrt(2)] lattice parameter of fcc cube in A -% 'd' [7.1] diameter of Bucky ball in A -% 'r' [] experimental coordinates of Bucky ball -% 'rot' [1] if true, apply random rotation - -% default parameters -p = struct( 'a', 10*sqrt(2), 'd', 7.1, 'r', [], ... - 'U', 0.002, 'rot', 1 ); - -% process arguments -if rem(nargin, 2) - error('number of arguments must be even') -end -for i = 1:2:nargin - n = varargin{i}; - v = varargin{i+1}; - if ~isfield(p, n) - error(sprintf('unknown parameter %s', n)) - end - p = setfield(p, n, v); -end - -% FCC fractional coordinates -xyzfcc = [ 0,0,0; 1,0,0; 1,1,0; 0,1,0; - 0,0,1; 1,0,1; 1,1,1; 0,1,1; - .5,.5,.0; .5,.0,.5; .0,.5,.5; - 1.,.5,.5; .5,1.,.5; .5,.5,1. ]; - -Nfcc = size(xyzfcc,1); - -xyzsc = xyzfcc; -Nsc = size(xyzsc,1); - -if p.rot - % generate random rotation axis and angles - phi=2*pi*rand(Nsc,1); th=acos(2*rand(Nsc,1)-1); alph=2*pi*rand(Nsc,1); - Rua = [sin(th).*cos(phi), sin(th).*sin(phi), cos(th), alph]; -else - % no rotation - Rua = [ 0, 0, 1, 0 ]; - Rua = Rua(ones(Nsc,1),:); -end - -% unit bucky ball -if ~isempty(p.r) - rC60 = p.r; - rcms = mean(rC60); - rC60 = rC60 - rcms(ones(size(rC60,1),1),:); - p.d = max(distmx(rC60,'s')); -else - [ignore, uC60] = bucky(); - rC60 = uC60 * p.d/2.0; -end -rall = []; -for i = 1:Nsc - rall = [rall; - xyzsc(i*ones(size(rC60,1),1),:)*p.a + rotateua(Rua(i,:), rC60) - ]; -end -Nall = size(rall,1); - -abc = diag([1,1,1] * p.a); -% finally build the PDFFIT stru string -stru = { - sprintf('title fcc C60, d=%g, a=%g\n', p.d, p.a) - sprintf('format pdffit\n') - sprintf('scale 1.000000\n') - sprintf('sharp 0.000000, 1.000000, 0.000000\n') - sprintf('spcgr P1\n') - sprintf('cell %10.6f,%10.6f,%10.6f,%10.6f,%10.6f,%10.6f\n', ... - diag(abc), 90, 90, 90) - sprintf('dcell %10.6f,%10.6f,%10.6f,%10.6f,%10.6f,%10.6f\n', ... - zeros(1,6)) - sprintf('ncell %8i,%8i,%8i,%8i\n', 1, 1, 1, Nall) - sprintf('atoms\n') -}; -for i = 1:Nall - stru{end+1} = sprintf( '%-4s%18.8f%18.8f%18.8f%13.4f\n', ... - 'C', rall(i,:)/abc, 1.0, '', zeros(1,3), 0.0 ); - stru{end+1} = sprintf( '%22.8f%18.8f%18.8f\n', ... - p.U(ones(1,3)), zeros(3,3) ); -end - -stru = [ stru{:} ]; - -function r1 = rotateua(ua, r0) -% hacked from ROTATE -x = ua(1); -y = ua(2); -z = ua(3); -alph = ua(4); -cosa = cos(alph); -sina = sin(alph); -vera = 1 - cosa; -rot = [cosa+x^2*vera x*y*vera-z*sina x*z*vera+y*sina; ... - x*y*vera+z*sina cosa+y^2*vera y*z*vera-x*sina; ... - x*z*vera-y*sina y*z*vera+x*sina cosa+z^2*vera]'; -r1 = r0*rot; diff --git a/src/diffpy/pdfgui/icons/calculationitem.png b/src/diffpy/pdfgui/icons/calculationitem.png deleted file mode 100644 index e2dee3a9..00000000 Binary files a/src/diffpy/pdfgui/icons/calculationitem.png and /dev/null differ diff --git a/src/diffpy/pdfgui/icons/columbia-logo.png b/src/diffpy/pdfgui/icons/columbia-logo.png deleted file mode 100644 index 2130d5dc..00000000 Binary files a/src/diffpy/pdfgui/icons/columbia-logo.png and /dev/null differ diff --git a/src/diffpy/pdfgui/icons/danse-logo.png b/src/diffpy/pdfgui/icons/danse-logo.png deleted file mode 100644 index 6f796b6e..00000000 Binary files a/src/diffpy/pdfgui/icons/danse-logo.png and /dev/null differ diff --git a/src/diffpy/pdfgui/icons/datasetitem.png b/src/diffpy/pdfgui/icons/datasetitem.png deleted file mode 100644 index a94eb68b..00000000 Binary files a/src/diffpy/pdfgui/icons/datasetitem.png and /dev/null differ diff --git a/src/diffpy/pdfgui/icons/exportplotdata.png b/src/diffpy/pdfgui/icons/exportplotdata.png deleted file mode 100644 index b88994d6..00000000 Binary files a/src/diffpy/pdfgui/icons/exportplotdata.png and /dev/null differ diff --git a/src/diffpy/pdfgui/icons/exportplotdata.xcf b/src/diffpy/pdfgui/icons/exportplotdata.xcf deleted file mode 100644 index d00e6b4b..00000000 Binary files a/src/diffpy/pdfgui/icons/exportplotdata.xcf and /dev/null differ diff --git a/src/diffpy/pdfgui/icons/fititem.png b/src/diffpy/pdfgui/icons/fititem.png deleted file mode 100644 index eecd4542..00000000 Binary files a/src/diffpy/pdfgui/icons/fititem.png and /dev/null differ diff --git a/src/diffpy/pdfgui/icons/fitting.png b/src/diffpy/pdfgui/icons/fitting.png deleted file mode 100644 index 788f0c86..00000000 Binary files a/src/diffpy/pdfgui/icons/fitting.png and /dev/null differ diff --git a/src/diffpy/pdfgui/icons/fitting.xcf b/src/diffpy/pdfgui/icons/fitting.xcf deleted file mode 100644 index 7b49fac2..00000000 Binary files a/src/diffpy/pdfgui/icons/fitting.xcf and /dev/null differ diff --git a/src/diffpy/pdfgui/icons/logo.png b/src/diffpy/pdfgui/icons/logo.png deleted file mode 100644 index 4c7123c7..00000000 Binary files a/src/diffpy/pdfgui/icons/logo.png and /dev/null differ diff --git a/src/diffpy/pdfgui/icons/logo.xcf b/src/diffpy/pdfgui/icons/logo.xcf deleted file mode 100644 index 2b9682db..00000000 Binary files a/src/diffpy/pdfgui/icons/logo.xcf and /dev/null differ diff --git a/src/diffpy/pdfgui/icons/msu-logo.png b/src/diffpy/pdfgui/icons/msu-logo.png deleted file mode 100644 index 5d7f6cd6..00000000 Binary files a/src/diffpy/pdfgui/icons/msu-logo.png and /dev/null differ diff --git a/src/diffpy/pdfgui/icons/nsf-logo.png b/src/diffpy/pdfgui/icons/nsf-logo.png deleted file mode 100644 index 9a7d3b2b..00000000 Binary files a/src/diffpy/pdfgui/icons/nsf-logo.png and /dev/null differ diff --git a/src/diffpy/pdfgui/icons/pdfgui.ico b/src/diffpy/pdfgui/icons/pdfgui.ico deleted file mode 100644 index 7c26d10c..00000000 Binary files a/src/diffpy/pdfgui/icons/pdfgui.ico and /dev/null differ diff --git a/src/diffpy/pdfgui/icons/pdfgui_512x512.xcf b/src/diffpy/pdfgui/icons/pdfgui_512x512.xcf deleted file mode 100644 index 69deb877..00000000 Binary files a/src/diffpy/pdfgui/icons/pdfgui_512x512.xcf and /dev/null differ diff --git a/src/diffpy/pdfgui/icons/phaseitem.png b/src/diffpy/pdfgui/icons/phaseitem.png deleted file mode 100644 index f942a47e..00000000 Binary files a/src/diffpy/pdfgui/icons/phaseitem.png and /dev/null differ diff --git a/src/diffpy/pdfgui/icons/plotting.png b/src/diffpy/pdfgui/icons/plotting.png deleted file mode 100644 index dd15738b..00000000 Binary files a/src/diffpy/pdfgui/icons/plotting.png and /dev/null differ diff --git a/src/diffpy/pdfgui/icons/plotting.xcf b/src/diffpy/pdfgui/icons/plotting.xcf deleted file mode 100644 index d4c7ce25..00000000 Binary files a/src/diffpy/pdfgui/icons/plotting.xcf and /dev/null differ diff --git a/src/diffpy/pdfgui/icons/run.png b/src/diffpy/pdfgui/icons/run.png deleted file mode 100644 index a2a65dae..00000000 Binary files a/src/diffpy/pdfgui/icons/run.png and /dev/null differ diff --git a/src/diffpy/pdfgui/icons/stop.png b/src/diffpy/pdfgui/icons/stop.png deleted file mode 100644 index 04790771..00000000 Binary files a/src/diffpy/pdfgui/icons/stop.png and /dev/null differ diff --git a/src/diffpy/pdfgui/icons/titlepage.png b/src/diffpy/pdfgui/icons/titlepage.png deleted file mode 100644 index 5585ed14..00000000 Binary files a/src/diffpy/pdfgui/icons/titlepage.png and /dev/null differ diff --git a/src/diffpy/pdfgui/icons/titlepage.xcf b/src/diffpy/pdfgui/icons/titlepage.xcf deleted file mode 100644 index 6372ab71..00000000 Binary files a/src/diffpy/pdfgui/icons/titlepage.xcf and /dev/null differ diff --git a/src/diffpy/pdfgui/tui.py b/src/diffpy/pdfgui/tui.py deleted file mode 100644 index 0cb5536d..00000000 --- a/src/diffpy/pdfgui/tui.py +++ /dev/null @@ -1,154 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2008 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""Text user interface - utilities for extracting data from project files. -""" - - -class LoadProject: - """Load and access data in pdfgui project file. - - Protected instance data: - - _project -- instance of PDFGuiControl with loaded project file. - """ - - # public methods - - def __init__(self, filename=None): - """Initialize LoadProject object, by reading existing project - file. - - filename -- path to PDFgui project file. - """ - from diffpy.pdfgui.control.pdfguicontrol import PDFGuiControl - - self._project = PDFGuiControl() - # business - if filename is not None: - self.load(filename) - return - - def load(self, filename): - """Load a project. - - filename -- path to PDFgui project file. - - No return value. - """ - self._project.load(filename) - return - - def save(self, filename): - """Save the project. - - filename -- path where to write the PDFgui project. - - No return value. - """ - self._project.save(filename) - return - - def getFits(self): - """Get all fits defined in the project file. - - Return list of Fitting objects. - """ - rv = self._project.fits[:] - return rv - - def getDataSets(self, fits=None): - """Return a list of all datasets contained in specified fits. - - fits -- optional list of Fitting objects that own datasets. - When not specified, get datasets from all fits defined - in the project. - - Return list of FitDataSet objects. - """ - if fits is None: - fitlist = self.getFits() - else: - fitlist = fits - rv = sum([fit.datasets for fit in fitlist], []) - return rv - - def getCalculations(self, fits=None): - """Return list of all calculations contained in specified fits. - - fits -- optional list of Fitting objects that own datasets. - When not specified, get datasets from all fits defined - in the project. - - Return list of Calculation objects. - """ - if fits is None: - fitlist = self.getFits() - else: - fitlist = fits - rv = sum([fit.calcs for fit in fitlist], []) - return rv - - def getPhases(self, fits=None): - """Collect all phases contained in specified fits. - - fits -- optional list of Fitting objects that own datasets. - When not specified, get phases from all fits defined - in the project. - - Return list of FitStructure objects. - """ - if fits is None: - fitlist = self.getFits() - else: - fitlist = fits - rv = sum([fit.strucs for fit in fitlist], []) - return rv - - def getTemperatures(self, datasets=None): - """Extract temperatures from a list of datasets. - - datasets -- optional list of FitDataSet objects. When not - specified, temperatures are extracted from all - datasets in the project. - - Return list of floating point values. The list may contain - None-s for datasets with undefined temperature. - """ - if datasets is None: - dslist = self.getDataSets() - else: - dslist = datasets - temperatures = [ds.metadata.get("temperature") for ds in dslist] - return temperatures - - def getDopings(self, datasets=None): - """Extract doping values from a list of datasets. - - datasets -- optional list of FitDataSet objects. When not - specified, doping values are extracted from all - datasets in the project. - - Return list of floating point values. The list may contain - None-s for datasets with undefined doping. - """ - if datasets is None: - dslist = self.getDataSets() - else: - dslist = datasets - dopings = [ds.metadata.get("doping") for ds in dslist] - return dopings - - -# End of class LoadProject diff --git a/src/diffpy/pdfgui/utils.py b/src/diffpy/pdfgui/utils.py deleted file mode 100644 index 33cdc256..00000000 --- a/src/diffpy/pdfgui/utils.py +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2007 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""Small shared routines: - numericStringSort -- sort list of strings according to numeric value - safeCPickleDumps -- same as pickle.dumps, but safe for NaN and Inf -""" - - -def numericStringSort(lst): - """Sort list of strings inplace according to general numeric value. - Each string gets split to string and integer segments to create keys - for comparison. Signs, decimal points and exponents are ignored. - - lst -- sorted list of strings - - No return value to highlight inplace sorting. - """ - import re - - rx = re.compile(r"(\d+)") - keys = [rx.split(s) for s in lst] - for k in keys: - k[1::2] = [int(i) for i in k[1::2]] - newlst = sorted(zip(keys, lst)) - lst[:] = [kv[1] for kv in newlst] - return - - -def safeCPickleDumps(obj): - """Get pickle representation of an object possibly containing NaN or - Inf. By default it uses pickle.HIGHEST_PROTOCOL, but falls back to - ASCII protocol 0 if there is SystemError frexp() exception. - - obj -- object to be pickled - - Return pickle string. - """ - - import pickle - - ascii_protocol = 0 - try: - s = pickle.dumps(obj, pickle.HIGHEST_PROTOCOL) - except SystemError: - s = pickle.dumps(obj, ascii_protocol) - return s - - -def asunicode(s): - """Convert string or bytes object to a text type.""" - rv = s - if not isinstance(s, str): - rv = s.decode("utf-8") - return rv - - -# End of file diff --git a/src/diffpy/pdfgui/version.py b/src/diffpy/pdfgui/version.py deleted file mode 100644 index 47c1ed6e..00000000 --- a/src/diffpy/pdfgui/version.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# (c) 2024 The Trustees of Columbia University in the City of New York. -# All rights reserved. -# -# File coded by: Billinge Group members and community contributors. -# -# See GitHub contributions for a more detailed list of contributors. -# https://github.com/diffpy/diffpy.pdfgui/graphs/contributors -# -# See LICENSE.rst for license information. -# -############################################################################## -"""Definition of __version__.""" - -# We do not use the other three variables, but can be added back if needed. -# __all__ = ["__date__", "__git_commit__", "__timestamp__", "__version__"] - -import os -import time -from importlib.metadata import distribution, version - -# obtain version information -__date__ = time.ctime(os.path.getctime(distribution("diffpy.pdfgui")._path)) -__version__ = version("diffpy.pdfgui") diff --git a/tests/conftest.py b/tests/conftest.py deleted file mode 100644 index e3b63139..00000000 --- a/tests/conftest.py +++ /dev/null @@ -1,19 +0,0 @@ -import json -from pathlib import Path - -import pytest - - -@pytest.fixture -def user_filesystem(tmp_path): - base_dir = Path(tmp_path) - home_dir = base_dir / "home_dir" - home_dir.mkdir(parents=True, exist_ok=True) - cwd_dir = base_dir / "cwd_dir" - cwd_dir.mkdir(parents=True, exist_ok=True) - - home_config_data = {"username": "home_username", "email": "home@email.com"} - with open(home_dir / "diffpyconfig.json", "w") as f: - json.dump(home_config_data, f) - - yield tmp_path diff --git a/tests/test_aboutdialog.py b/tests/test_aboutdialog.py deleted file mode 100644 index b66859e7..00000000 --- a/tests/test_aboutdialog.py +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# diffpy.pdfgui Complex Modeling Initiative -# (c) 2019 Brookhaven Science Associates, -# Brookhaven National Laboratory. -# All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""Unit tests for class DialogAbout.""" - -import unittest - -import wx -from testutils import GUITestCase, overridewebbrowser - -from diffpy.pdfgui.gui import aboutdialog - -# ---------------------------------------------------------------------------- - - -class TestDialogAbout(GUITestCase): - def setUp(self): - self.app = wx.App() - self.dialog = aboutdialog.DialogAbout(None) - return - - def tearDown(self): - self.dialog.Close() - self.app.Destroy() - return - - def _clickbutton(self, button): - e = wx.CommandEvent(wx.EVT_BUTTON.typeId, button.Id) - self.dialog.ProcessEvent(e) - return - - def set_url(self, u): - setattr(self, "url", u) - - def test_LogoClicks(self): - "Check handling of clicks on various logos" - d = self.dialog - with overridewebbrowser(self.set_url): - self._clickbutton(d.bitmap_button_nsf) - self.assertTrue(self.url.endswith("www.nsf.gov")) - self._clickbutton(d.bitmap_button_danse) - self.assertTrue(self.url.endswith("www.its.caltech.edu/~matsci/btf/DANSE_web_page.html")) - self._clickbutton(d.bitmap_button_msu) - self.assertTrue(self.url.endswith("www.msu.edu")) - self._clickbutton(d.bitmap_button_columbia) - self.assertTrue(self.url.endswith("www.columbia.edu")) - return - - -# End of class TestDialogAbout - -# ---------------------------------------------------------------------------- - -if __name__ == "__main__": - unittest.main() diff --git a/tests/test_calculation.py b/tests/test_calculation.py deleted file mode 100644 index 7bcd9d82..00000000 --- a/tests/test_calculation.py +++ /dev/null @@ -1,146 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2008 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""Unit tests for calculation.py.""" - - -import unittest - -from diffpy.pdfgui.control.calculation import Calculation -from diffpy.pdfgui.control.controlerrors import ControlValueError - - -############################################################################## -class TestCalculation(unittest.TestCase): - def setUp(self): - self.calc = Calculation("calc") - return - - def tearDown(self): - return - - # def test___init__(self): - # """check Calculation.__init__() - # """ - # return - # - # def test__getStrId(self): - # """check Calculation._getStrId() - # """ - # return - - def test_setRGrid(self): - """Check Calculation.setRGrid()""" - - # helper function - def rgriddata(calc): - rv = (calc.rmin, calc.rstep, calc.rmax, calc.rlen) - return rv - - # original data: - rgd0 = rgriddata(self.calc) - # test input argument checks - self.assertRaises(ControlValueError, self.calc.setRGrid, rmin=-1) - self.assertRaises(ControlValueError, self.calc.setRGrid, rmin=0) - self.assertRaises(ControlValueError, self.calc.setRGrid, rmin=500) - self.assertRaises(ControlValueError, self.calc.setRGrid, rstep=0) - self.assertRaises(ControlValueError, self.calc.setRGrid, rmax=1e-10) - # data should be the same - self.assertEqual(rgd0, rgriddata(self.calc)) - # check round-offs for very close values - self.calc.setRGrid(1, 0.2, 10.0 - 1e-14) - self.assertEqual(1, self.calc.rmin) - self.assertEqual(10, self.calc.rmax) - self.assertEqual(0.2, self.calc.rstep) - self.assertEqual(46, self.calc.rlen) - # range should cover the argument range. - self.calc.setRGrid(1, 0.7, 10) - self.assertEqual(1, self.calc.rmin) - self.assertTrue(10 < self.calc.rmax) - self.assertEqual(0.7, self.calc.rstep) - return - - -# def test_start(self): -# """check Calculation.start() -# """ -# return -# -# def test_calculate(self): -# """check Calculation.calculate() -# """ -# return -# -# def test_write(self): -# """check Calculation.write() -# """ -# return -# -# def test_writeStr(self): -# """check Calculation.writeStr() -# """ -# return -# -# def test_load(self): -# """check Calculation.load() -# """ -# return -# -# def test_save(self): -# """check Calculation.save() -# """ -# return -# -# def test_copy(self): -# """check Calculation.copy() -# """ -# return -# -# def test_getYNames(self): -# """check Calculation.getYNames() -# """ -# return -# -# def test_getXNames(self): -# """check Calculation.getXNames() -# """ -# return -# -# def test_getData(self): -# """check Calculation.getData() -# """ -# return -# -# def test_getMetaDataNames(self): -# """check Calculation.getMetaDataNames() -# """ -# return -# -# def test_getMetaData(self): -# """check Calculation.getMetaData() -# """ -# return -# -# def test_close(self): -# """check Calculation.close() -# """ -# return - -# End of class TestCalculation - - -if __name__ == "__main__": - unittest.main() - -# End of file diff --git a/tests/test_constraint.py b/tests/test_constraint.py deleted file mode 100644 index dfff965d..00000000 --- a/tests/test_constraint.py +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""Unit tests for constraint.py.""" - - -import unittest - -from diffpy.pdfgui.control.constraint import Constraint -from diffpy.pdfgui.control.controlerrors import ControlSyntaxError - - -############################################################################## -class TestConstraint(unittest.TestCase): - """Test methods of TestConstraint.""" - - def setUp(self): - self.c = Constraint("@1") - return - - def test___init__(self): - """Check Constraint.__init__()""" - self.assertTrue(1 in self.c.parguess) - self.assertEqual(1, len(self.c.parguess)) - c1 = Constraint("2*@2 + 3.0", 13.0) - self.assertEqual(1, len(c1.parguess)) - self.assertEqual(5.0, c1.parguess[2]) - return - - def test_guess(self): - """Check Constraint.guess()""" - self.c.guess(9) - self.assertEqual(1, len(self.c.parguess)) - self.assertEqual(9, self.c.parguess[1]) - return - - def test___setattr__(self): - """Check Constraint.__setattr__()""" - self.c.guess(9) - self.c.formula = "9*@7 +18" - self.assertEqual(1, len(self.c.parguess)) - self.assertEqual(-1.0, self.c.parguess[7]) - self.assertRaises(ControlSyntaxError, setattr, self.c, "formula", "") - self.assertRaises(ControlSyntaxError, setattr, self.c, "formula", "@@1") - self.assertRaises(ControlSyntaxError, setattr, self.c, "formula", "@1*/55") - self.assertRaises(ControlSyntaxError, setattr, self.c, "formula", "@1**3") - return - - def test_evalFormula(self): - """Check Constraint.evalFormula()""" - value = self.c.evalFormula({1: 5.0}) - self.assertEqual(5.0, value) - self.c.formula = "sin(@3)" - from math import pi, sqrt - - value = self.c.evalFormula({3: pi / 3.0}) - self.assertAlmostEqual(sqrt(0.75), value, 8) - return - - -# End of class TestConstraint - -if __name__ == "__main__": - unittest.main() - -# End of file diff --git a/tests/test_datasetpanels.py b/tests/test_datasetpanels.py deleted file mode 100644 index 5343a4e1..00000000 --- a/tests/test_datasetpanels.py +++ /dev/null @@ -1,112 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# diffpy.pdfgui Complex Modeling Initiative -# (c) 2019 Brookhaven Science Associates, -# Brookhaven National Laboratory. -# All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""Unit tests for DataSet panels.""" - -import unittest - -import wx -from testutils import GUITestCase, datafile, tooltiptext - -from diffpy.pdfgui.gui.mainframe import MainFrame - -# ---------------------------------------------------------------------------- - - -class TestDataSetPanel(GUITestCase): - @classmethod - def setUpClass(cls): - GUITestCase.setUpClass() - GUITestCase.setCmdArgs([datafile("lcmo.ddp")]) - cls.app = wx.App() - cls.frame = MainFrame(None, -1, "") - tree = cls.frame.treeCtrlMain - fits = tree.GetChildren(tree.root) - dsids = tree.GetDataSets(fits[0]) - cls.frame.makeTreeSelection(dsids[0]) - return - - @classmethod - def tearDownClass(cls): - cls.frame.Close() - cls.app.Destroy() - GUITestCase.tearDownClass() - return - - def setUp(self): - self.pconfigure = self.frame.rightPanel.configurePanel - self.pconstraints = self.frame.rightPanel.constraintPanel - self.presults = self.frame.rightPanel.resultsPanel - return - - def _selectpage(self, page): - nb = self.frame.rightPanel.dataSetNotebook - nb.SetSelection(page) - return - - def _selectsampling(self, selection): - "select specified item in sampling radio box" - rbxid = self.pconfigure.radioBoxSampling.Id - self.pconfigure.radioBoxSampling.SetSelection(selection) - e = wx.CommandEvent(wx.EVT_RADIOBOX.typeId, rbxid) - e.SetInt(selection) - self.pconfigure.ProcessEvent(e) - return - - def test_refreshSelectedPage(self): - "check DataSetPanel.refreshSelectedPage method" - # cover all if branches in refreshSelectedPage - self._selectpage(2) - return - - def test_restrictConstrainedParameters(self): - "check DataSetConfigurePanel.restrictConstrainedParameters method" - self._selectpage(0) - panel = self.pconfigure - self.assertFalse(panel.textCtrlScaleFactor.IsEditable()) - self.assertTrue(panel.textCtrlQbroad.IsEditable()) - self.assertEqual("@100", tooltiptext(panel.textCtrlScaleFactor)) - return - - def test_onSampling(self): - "check DataSetConfigurePanel.onSampling method" - self._selectpage(0) - panel = self.pconfigure - self._selectsampling(0) - self.assertEqual(0.04, panel.configuration.fitrstep) - panel.textCtrlFitStep.SetValue("0.1") - self._selectsampling(2) - self.assertEqual(0.1, panel.configuration.fitrstep) - self.assertEqual(32, panel.configuration.qmax) - panel.textCtrlQmax.SetValue("27") - e = wx.FocusEvent(wx.EVT_KILL_FOCUS.typeId, panel.textCtrlQmax.Id) - panel.textCtrlQmax.ProcessEvent(e) - self.assertEqual(27, panel.configuration.qmax) - return - - def test_setConstraintsData(self): - "check DataSetConstraintPanel.setConstraintsData method" - self._selectpage(1) - panel = self.pconstraints - self.assertEqual("@100", panel.textCtrlScaleFactor.GetValue()) - self.assertEqual("Data scale factor", tooltiptext(panel.textCtrlScaleFactor)) - return - - -# End of class TestDataSetPanel - -# ---------------------------------------------------------------------------- - -if __name__ == "__main__": - unittest.main() diff --git a/tests/test_dopingseriespanel.py b/tests/test_dopingseriespanel.py deleted file mode 100644 index 325a718d..00000000 --- a/tests/test_dopingseriespanel.py +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# diffpy.pdfgui Complex Modeling Initiative -# (c) 2019 Brookhaven Science Associates, -# Brookhaven National Laboratory. -# All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""Unit tests for the DopingSeriesPanel class.""" - -import unittest - -import wx -from testutils import GUITestCase, datafile, overridefiledialog - -from diffpy.pdfgui.gui.dopingseriespanel import DopingSeriesPanel - -# ---------------------------------------------------------------------------- - - -class TestDopingSeriesPanel(GUITestCase): - def setUp(self): - self.app = wx.App() - self.frame = wx.Frame(None) - self.panel = DopingSeriesPanel(self.frame) - self.panel.mainFrame = self._mockUpMainFrame() - self.panel.mainFrame.workpath = datafile("") - return - - def tearDown(self): - self.frame.Close() - self.app.Destroy() - return - - def test_onAdd(self): - "Check DopingSeriesPanel.onAdd" - panel = self.panel - paths = ["x000.gr", "x020.gr", "lcmo_00.gr", "lcmo_20.gr"] - paths = [datafile(p) for p in paths] - with overridefiledialog(wx.ID_OK, paths): - panel.onAdd(None) - self.assertEqual(paths[-1], panel.fullpath) - self.assertEqual([0, 20, 0, 0.2], [xf[0] for xf in panel.datasets]) - return - - -# End of class TestDopingSeriesPanel - -# ---------------------------------------------------------------------------- - -if __name__ == "__main__": - unittest.main() diff --git a/tests/test_extendedplotframe.py b/tests/test_extendedplotframe.py deleted file mode 100644 index dbe17735..00000000 --- a/tests/test_extendedplotframe.py +++ /dev/null @@ -1,75 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# diffpy.pdfgui Complex Modeling Initiative -# (c) 2019 Brookhaven Science Associates, -# Brookhaven National Laboratory. -# All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""Unit tests for the ExtendedPlotFrame class.""" - -import unittest - -import numpy -import wx -from testutils import GUITestCase, overridefiledialog - -from diffpy.pdfgui.control.plotter import Plotter -from diffpy.pdfgui.gui import extendedplotframe as epf -from diffpy.pdfgui.gui.extendedplotframe import ExtendedPlotFrame - -# ---------------------------------------------------------------------------- - - -class TestExtendedPlotFrame(GUITestCase): - def setUp(self): - self.app = wx.App() - self.frame = ExtendedPlotFrame(None) - return - - def tearDown(self): - self.frame.Close() - self.app.Destroy() - return - - def _clicktoolbar(self, tbid): - e = wx.CommandEvent(wx.EVT_TOOL.typeId, tbid) - self.frame.toolbar.ProcessEvent(e) - return - - def test_insertCurve(self): - "Check ExtendedPlotFrame.insertCurve" - x = numpy.linspace(-5, 5) - ys = numpy.sin(x) - style = {"with": "lines", "color": "blue", "line": "solid", "width": 2.3} - line = self.frame.insertCurve(x, ys, style) - self.assertEqual(2.3, line.get_linewidth()) - return - - def test_savePlotData(self): - self.frame.plotter = Plotter() - # intercept plotter.export to avoid plot setup and temporary files - self.frame.plotter.export = lambda fn: setattr(self, "spd", fn) - self.spd = "" - with overridefiledialog(wx.ID_OK, ["testfile.dat"]): - self._clicktoolbar(epf.DATA_SAVE_ID) - self.assertEqual("testfile.dat", self.spd) - self.spd = "" - with overridefiledialog(wx.ID_CANCEL, ["testfile2.dat"]): - self._clicktoolbar(epf.DATA_SAVE_ID) - self.assertEqual("", self.spd) - return - - -# End of class TestExtendedPlotFrame - -# ---------------------------------------------------------------------------- - -if __name__ == "__main__": - unittest.main() diff --git a/tests/test_fitdataset.py b/tests/test_fitdataset.py deleted file mode 100644 index 2e8c0655..00000000 --- a/tests/test_fitdataset.py +++ /dev/null @@ -1,384 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2008 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""Unit tests for fitdataset.py.""" - - -import unittest - -import numpy -from testutils import datafile - -import diffpy.pdfgui.control.fitdataset as fds -from diffpy.pdfgui.control.fitdataset import FitDataSet - -# ---------------------------------------------------------------------------- - - -class TestRoutines(unittest.TestCase): - def setUp(self): - return - - def tearDown(self): - return - - def test_grid_interpolation(self): - """Check grid_interpolation()""" - x0 = numpy.arange(-5, 5, 0.25) - y0 = numpy.sin(x0) - x1 = [-6, x0[0], -0.2, x0[-1], 37] - y1a = fds.grid_interpolation(x0, y0, x1) - y1b = fds.grid_interpolation(x0, y0, x1, left=637, right=638) - # outside values - self.assertEqual(0.0, y1a[0]) - self.assertEqual(637, y1b[0]) - self.assertEqual(0.0, y1a[-1]) - self.assertEqual(638, y1b[-1]) - # boundary values - self.assertEqual(y0[0], y1a[1]) - self.assertEqual(y0[0], y1b[1]) - self.assertEqual(y0[-1], y1a[3]) - self.assertEqual(y0[-1], y1b[3]) - # inside values - self.assertAlmostEqual(-0.197923167403618, y1a[2]) - self.assertAlmostEqual(-0.197923167403618, y1b[2]) - # interpolate to empty grid: - y2 = fds.grid_interpolation(x0, y0, []) - self.assertEqual(0, len(y2)) - # interpolate over empty grid - y3 = fds.grid_interpolation([], [], [0, 1]) - self.assertEqual(0, y3[0]) - self.assertEqual(0, y3[1]) - # interpolate over trivial grid - y4 = fds.grid_interpolation([0], [5], [-1, 0, 1]) - self.assertEqual(0, y4[0]) - self.assertEqual(5, y4[1]) - self.assertEqual(0, y4[2]) - return - - -# End of class TestRoutines - -# ---------------------------------------------------------------------------- - - -class TestFitDataSet(unittest.TestCase): - - # def setUp(self): - # return - # - # def tearDown(self): - # return - # - # def test___init__(self): - # """check FitDataSet.__init__() - # """ - # return - # - # def test___setattr__(self): - # """check FitDataSet.__setattr__() - # """ - # return - # - # def test___getattr__(self): - # """check FitDataSet.__getattr__() - # """ - # return - # - # def test__getStrId(self): - # """check FitDataSet._getStrId() - # """ - # return - # - # def test_getYNames(self): - # """check FitDataSet.getYNames() - # """ - # return - # - # def test_getXNames(self): - # """check FitDataSet.getXNames() - # """ - # return - # - # def test_getData(self): - # """check FitDataSet.getData() - # """ - # return - # - # def test_clear(self): - # """check FitDataSet.clear() - # """ - # return - # - # def test_clearRefined(self): - # """check FitDataSet.clearRefined() - # """ - # return - # - # def test_obtainRefined(self): - # """check FitDataSet.obtainRefined() - # """ - # return - # - # def test_read(self): - # """check FitDataSet.read() - # """ - # return - # - # def test__updateRcalcRange(self): - # """check FitDataSet._updateRcalcRange() - # """ - # return - # - # def test_readObs(self): - # """check FitDataSet.readObs() - # """ - # return - # - # def test_readStr(self): - # """check FitDataSet.readStr() - # """ - # return - # - # def test_readObsStr(self): - # """check FitDataSet.readObsStr() - # """ - # return - # - # def test_write(self): - # """check FitDataSet.write() - # """ - # return - # - # def test_writeCalc(self): - # """check FitDataSet.writeCalc() - # """ - # return - # - # def test_writeStr(self): - # """check FitDataSet.writeStr() - # """ - # return - # - # def test_writeCalcStr(self): - # """check FitDataSet.writeCalcStr() - # """ - # return - # - # def test_writeObs(self): - # """check FitDataSet.writeObs() - # """ - # return - # - # def test_writeObsStr(self): - # """check FitDataSet.writeObsStr() - # """ - # return - - def test__resampledPDFDataSet(self): - """Check FitDataSet._resampledPDFDataSet()""" - fNi_data = datafile("Ni_2-8.chi.gr") - fds = FitDataSet("Ni") - fds.read(fNi_data) - npts = len(fds.rcalc) - rds = fds._resampledPDFDataSet() - self.assertEqual(npts, len(rds.robs)) - self.assertEqual(npts, len(rds.drobs)) - self.assertEqual(npts, len(rds.Gobs)) - self.assertEqual(npts, len(rds.dGobs)) - # reduce fitrmax to one half - fds.fitrmax = fds.rmax / 2.0 - npts1 = len(fds.rcalc) - self.assertTrue(npts1 < npts) - rds1 = fds._resampledPDFDataSet() - self.assertEqual(npts1, len(rds1.robs)) - self.assertEqual(npts1, len(rds1.drobs)) - self.assertEqual(npts1, len(rds1.Gobs)) - self.assertEqual(npts1, len(rds1.dGobs)) - return - - -# def test_writeResampledObs(self): -# """check FitDataSet.writeResampledObs() -# """ -# return -# -# def test_writeResampledObsStr(self): -# """check FitDataSet.writeResampledObsStr() -# """ -# return -# -# def test_findParameters(self): -# """check FitDataSet.findParameters() -# """ -# return -# -# def test_applyParameters(self): -# """check FitDataSet.applyParameters() -# """ -# return -# -# def test_changeParameterIndex(self): -# """check FitDataSet.changeParameterIndex() -# """ -# return -# -# def test_copy(self): -# """check FitDataSet.copy() -# """ -# return -# -# def test_load(self): -# """check FitDataSet.load() -# """ -# return -# -# def test_save(self): -# """check FitDataSet.save() -# """ -# return -# -# def test_getFitSamplingType(self): -# """check FitDataSet.getFitSamplingType() -# """ -# return -# -# def test_setFitSamplingType(self): -# """check FitDataSet.setFitSamplingType() -# """ -# return -# -# def test_getObsSampling(self): -# """check FitDataSet.getObsSampling() -# """ -# return -# -# def test_getNyquistSampling(self): -# """check FitDataSet.getNyquistSampling() -# """ -# return -# -# def test__updateRcalcSampling(self): -# """check FitDataSet._updateRcalcSampling() -# """ -# return -# -# def test__get_fitrmin(self): -# """check FitDataSet._get_fitrmin() -# """ -# return -# -# def test__set_fitrmin(self): -# """check FitDataSet._set_fitrmin() -# """ -# return -# -# def test__get_fitrmax(self): -# """check FitDataSet._get_fitrmax() -# """ -# return -# -# def test__set_fitrmax(self): -# """check FitDataSet._set_fitrmax() -# """ -# return -# -# def test__get_fitrstep(self): -# """check FitDataSet._get_fitrstep() -# """ -# return -# -# def test__set_fitrstep(self): -# """check FitDataSet._set_fitrstep() -# """ -# return -# -# def test__get_rcalc(self): -# """check FitDataSet._get_rcalc() -# """ -# return -# -# def test__set_rcalc(self): -# """check FitDataSet._set_rcalc() -# """ -# return -# -# def test__get_Gcalc(self): -# """check FitDataSet._get_Gcalc() -# """ -# return -# -# def test__set_Gcalc(self): -# """check FitDataSet._set_Gcalc() -# """ -# return -# -# def test__get_dGcalc(self): -# """check FitDataSet._get_dGcalc() -# """ -# return -# -# def test__set_dGcalc(self): -# """check FitDataSet._set_dGcalc() -# """ -# return -# -# def test__get_Gtrunc(self): -# """check FitDataSet._get_Gtrunc() -# """ -# return -# -# def test__set_Gtrunc(self): -# """check FitDataSet._set_Gtrunc() -# """ -# return -# -# def test__get_dGtrunc(self): -# """check FitDataSet._get_dGtrunc() -# """ -# return -# -# def test__set_dGtrunc(self): -# """check FitDataSet._set_dGtrunc() -# """ -# return -# -# def test__get_Gdiff(self): -# """check FitDataSet._get_Gdiff() -# """ -# return -# -# def test_close(self): -# """check FitDataSet.close() -# """ -# return -# -# def test_getvar(self): -# """check FitDataSet.getvar() -# """ -# return -# -# def test_setvar(self): -# """check FitDataSet.setvar() -# """ -# return - -# End of class TestFitDataSet - -# ---------------------------------------------------------------------------- - -if __name__ == "__main__": - unittest.main() - -# End of file diff --git a/tests/test_fitstructure.py b/tests/test_fitstructure.py deleted file mode 100644 index c49f93f4..00000000 --- a/tests/test_fitstructure.py +++ /dev/null @@ -1,295 +0,0 @@ -#!/usr/bin/env python - -"""Unit tests for class FitStructure.""" - - -import unittest - -from testutils import datafile - -from diffpy.pdfgui.control.constraint import Constraint -from diffpy.pdfgui.control.controlerrors import ControlTypeError -from diffpy.pdfgui.control.fitstructure import FitStructure -from diffpy.pdfgui.control.pdfstructure import PDFStructure -from diffpy.structure import Structure - -# ---------------------------------------------------------------------------- - - -class TestFitStructure(unittest.TestCase): - def setUp(self): - self.stru = FitStructure("noname") - return - - def tearDown(self): - return - - def test___init__(self): - """Check FitStructure.__init__()""" - stru = self.stru - self.assertEqual("noname", stru.name) - self.assertEqual("all-all", stru.selected_pairs) - return - - # def test__update_custom_spacegroup(self): - # """check FitStructure._update_custom_spacegroup() - # """ - # return - - # def test_read(self): - # """check FitStructure.read() - # """ - # return - - # def test_readStr(self): - # """check FitStructure.readStr() - # """ - # return - - def test___getattr__(self): - """Check FitStructure.__getattr__()""" - stru = self.stru - self.assertTrue(stru is stru.initial) - self.assertRaises(AttributeError, eval, "stru.notdefined", locals()) - return - - def test__getStrId(self): - """Check FitStructure._getStrId()""" - stru = self.stru - self.assertEqual("p_noname", stru._getStrId()) - return - - # def test_clearRefined(self): - # """check FitStructure.clearRefined() - # """ - # return - - # def test_obtainRefined(self): - # """check FitStructure.obtainRefined() - # """ - # return - - def test_findParameters(self): - """Check FitStructure.findParameters()""" - stru = self.stru - stru.read(datafile("Ni.stru"), format="pdffit") - for a in stru.initial: - a.Uiso = 0.00126651 - stru.constraints["lat(4)"] = Constraint("@1") - stru.constraints["y(2)"] = Constraint("@3 + 0.4") - stru.constraints["u11(3)"] = Constraint("@7 * 3.0") - pd = stru.findParameters() - self.assertEqual([1, 3, 7], sorted(pd.keys())) - self.assertEqual(90, pd[1].initialValue()) - self.assertEqual(0.5 - 0.4, pd[3].initialValue()) - self.assertEqual(0.00126651 / 3.0, pd[7].initialValue()) - return - - def test_applyParameters(self): - """Check FitStructure.applyParameters()""" - stru = self.stru - stru.read(datafile("Ni.stru"), format="pdffit") - for a in stru.initial: - a.Uiso = 0.00126651 - stru.constraints["lat(4)"] = Constraint("@1") - stru.constraints["u11(3)"] = Constraint("@7 * 3.0") - pd = stru.findParameters() - # adjust Parameter instances in pd - pd[1].setInitial(99) - pd[7].setInitial(0.5) - stru.applyParameters(pd) - self.assertEqual(99, stru.lattice.alpha) - self.assertEqual(1.5, stru[2].U11) - # pd values can be floats - pd[1] = 89 - stru.applyParameters(pd) - self.assertEqual(89, stru.lattice.alpha) - return - - def test_changeParameterIndex(self): - """Check FitStructure.changeParameterIndex()""" - stru = self.stru - stru.constraints["pscale"] = Constraint("@7+3") - stru.changeParameterIndex(7, 13) - self.assertEqual("@13+3", stru.constraints["pscale"].formula) - stru.changeParameterIndex(2, 19) - self.assertEqual("@13+3", stru.constraints["pscale"].formula) - return - - # tested in insertAtoms and deleteAtoms - # def test__popAtomConstraints(self): - # """check FitStructure._popAtomConstraints() - # """ - # return - - # def test__restoreAtomConstraints(self): - # """check FitStructure._restoreAtomConstraints() - # """ - # return - - def test_insertAtoms(self): - """Check FitStructure.insertAtoms()""" - from diffpy.structure import Atom - - stru = self.stru - stru.read(datafile("Ni.stru"), format="pdffit") - cns = Constraint("@1") - stru.constraints["x(2)"] = cns - stru.insertAtoms(0, [Atom("Na", (0, 0, 0))]) - self.assertEqual(5, len(stru)) - self.assertEqual(1, len(stru.constraints)) - self.assertTrue(cns is stru.constraints["x(3)"]) - stru.insertAtoms(5, [Atom("Cl", (0, 0, 0))]) - self.assertTrue(["x(3)"] == list(stru.constraints.keys())) - return - - def test_deleteAtoms(self): - """Check FitStructure.deleteAtoms()""" - stru = self.stru - stru.read(datafile("Ni.stru"), format="pdffit") - cns = Constraint("@1") - stru.constraints["x(2)"] = cns - stru.deleteAtoms([3]) - self.assertEqual(["x(2)"], list(stru.constraints.keys())) - self.assertTrue(cns is next(iter(stru.constraints.values()))) - stru.deleteAtoms([0]) - self.assertEqual(["x(1)"], list(stru.constraints.keys())) - self.assertTrue(cns is next(iter(stru.constraints.values()))) - stru.deleteAtoms([0]) - self.assertEqual({}, stru.constraints) - return - - # def test_expandSuperCell(self): - # """check FitStructure.expandSuperCell() - # """ - # return - # - # - # def test_isSpaceGroupPossible(self): - # """check FitStructure.isSpaceGroupPossible() - # """ - # return - # - # - # def test_getSpaceGroupList(self): - # """check FitStructure.getSpaceGroupList() - # """ - # return - # - # - # def test_getSpaceGroup(self): - # """check FitStructure.getSpaceGroup() - # """ - # return - # - # - # def test_expandAsymmetricUnit(self): - # """check FitStructure.expandAsymmetricUnit() - # """ - # return - # - # - # def test_applySymmetryConstraints(self): - # """check FitStructure.applySymmetryConstraints() - # """ - # return - # - # - # def test_setSelectedPairs(self): - # """check FitStructure.setSelectedPairs() - # """ - # return - # - # - # def test_getSelectedPairs(self): - # """check FitStructure.getSelectedPairs() - # """ - # return - - def test_getPairSelectionFlags(self): - """Check FitStructure.getPairSelectionFlags()""" - cdse = self.stru - cdse.read(datafile("CdSe_bulk_wur.stru"), format="pdffit") - self.assertEqual("all-all", cdse.getSelectedPairs()) - psf = cdse.getPairSelectionFlags() - self.assertEqual(4 * [True], psf["firstflags"]) - self.assertEqual(4 * [True], psf["secondflags"]) - psf = cdse.getPairSelectionFlags("Cd-Cd") - self.assertEqual(2 * [True] + 2 * [False], psf["firstflags"]) - self.assertEqual(psf["firstflags"], psf["secondflags"]) - psf = cdse.getPairSelectionFlags("all-all, !Cd-") - self.assertEqual(2 * [False] + 2 * [True], psf["firstflags"]) - self.assertEqual(4 * [True], psf["secondflags"]) - psf = cdse.getPairSelectionFlags("all-all, -!Cd") - self.assertEqual(4 * [True], psf["firstflags"]) - self.assertEqual(2 * [False] + 2 * [True], psf["secondflags"]) - psf = cdse.getPairSelectionFlags("Cd-3:4") - self.assertEqual(2 * [True] + 2 * [False], psf["firstflags"]) - self.assertEqual(2 * [False] + 2 * [True], psf["secondflags"]) - psf = cdse.getPairSelectionFlags("all-all, !Se-!Se") - self.assertEqual(2 * [True] + 2 * [False], psf["firstflags"]) - self.assertEqual(2 * [True] + 2 * [False], psf["secondflags"]) - psf = cdse.getPairSelectionFlags("all-all, !Se-, -!Se") - self.assertEqual(2 * [True] + 2 * [False], psf["firstflags"]) - self.assertEqual(2 * [True] + 2 * [False], psf["secondflags"]) - psf = cdse.getPairSelectionFlags("1-all") - self.assertEqual([True] + 3 * [False], psf["firstflags"]) - self.assertEqual(4 * [True], psf["secondflags"]) - return - - # def test_applyPairSelection(self): - # """check FitStructure.applyPairSelection() - # """ - # return - - def test_copy(self): - """Check FitStructure.copy()""" - stru2 = self.stru.copy() - self.assertEqual("noname", stru2.name) - stru3 = Structure() - self.assertRaises(ControlTypeError, stru2.copy, stru3) - self.stru.refined = PDFStructure("refined-name") - stru4 = self.stru.copy() - self.assertIsNot(self.stru.refined, stru4.refined) - self.assertEqual("refined-name", stru4.refined.name) - return - - -# def test_load(self): -# """check FitStructure.load() -# """ -# return -# -# -# def test_save(self): -# """check FitStructure.save() -# """ -# return -# -# -# def test_getYNames(self): -# """check FitStructure.getYNames() -# """ -# return -# -# -# def test_getXNames(self): -# """check FitStructure.getXNames() -# """ -# return -# -# -# def test_getData(self): -# """check FitStructure.getData() -# """ -# return - - -# End of class TestFitStructure - -# ---------------------------------------------------------------------------- - -if __name__ == "__main__": - unittest.main() - -# End of file diff --git a/tests/test_insertrowsdialog.py b/tests/test_insertrowsdialog.py deleted file mode 100644 index c0a00f2e..00000000 --- a/tests/test_insertrowsdialog.py +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# diffpy.pdfgui Complex Modeling Initiative -# (c) 2019 Brookhaven Science Associates, -# Brookhaven National Laboratory. -# All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""Unit tests for class InsertRowsDialog.""" - -import unittest - -import wx -from testutils import GUITestCase - -from diffpy.pdfgui.gui.insertrowsdialog import InsertRowsDialog - -# ---------------------------------------------------------------------------- - - -class TestInsertRowsDialog(GUITestCase): - def setUp(self): - self.app = wx.App() - self.dialog = InsertRowsDialog(None) - return - - def tearDown(self): - self.dialog.Close() - self.app.Destroy() - return - - def test_spin_ctrl_rows(self): - "Check default number of rows to insert" - d = self.dialog - self.assertEqual(1, d.spin_ctrl_Rows.GetValue()) - return - - -# End of class TestInsertRowsDialog - -# ---------------------------------------------------------------------------- - -if __name__ == "__main__": - unittest.main() diff --git a/tests/test_loadproject.py b/tests/test_loadproject.py deleted file mode 100644 index 3cc965d9..00000000 --- a/tests/test_loadproject.py +++ /dev/null @@ -1,116 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2008 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""Unit tests for tui.py.""" - - -import unittest - -from testutils import GUITestCase, datafile - -from diffpy.pdfgui.control.controlerrors import ControlFileError -from diffpy.pdfgui.tui import LoadProject - -# ---------------------------------------------------------------------------- - - -class TestLoadProject(GUITestCase): - - prj_lcmo = None - prj_lcmo_full = None - prj_ni = None - - def setUp(self): - # load project files once - if TestLoadProject.prj_lcmo is None: - TestLoadProject.prj_lcmo = LoadProject(datafile("lcmo.ddp")) - TestLoadProject.prj_lcmo_full = LoadProject(datafile("lcmo_full.ddp")) - TestLoadProject.prj_ni = LoadProject(datafile("ni.ddp")) - # assign them to this instance - self.prj_lcmo = TestLoadProject.prj_lcmo - self.prj_lcmo_full = TestLoadProject.prj_lcmo_full - self.prj_ni = TestLoadProject.prj_ni - return - - def tearDown(self): - return - - def test___init__(self): - """Check LoadProject.__init__()""" - self.assertEqual(1, len(self.prj_ni.getFits())) - self.assertRaises(ControlFileError, LoadProject, "does/not/exist.ddp") - return - - def test_getFits(self): - """Check LoadProject.getFits()""" - lcmofits = self.prj_lcmo.getFits() - lcmofullfits = self.prj_lcmo_full.getFits() - self.assertEqual(1, len(lcmofits)) - self.assertEqual("fit-d300", lcmofits[0].name) - self.assertEqual(10, len(lcmofullfits)) - self.assertEqual("fit-d300", lcmofullfits[0].name) - self.assertEqual("fit-d980", lcmofullfits[-1].name) - return - - def test_getDataSets(self): - """Check LoadProject.getDataSets()""" - lcmofullfits = self.prj_lcmo_full.getFits() - datasets = self.prj_lcmo_full.getDataSets() - self.assertEqual(10, len(datasets)) - self.assertEqual("d550", datasets[1].name) - datasets5 = self.prj_lcmo_full.getDataSets(lcmofullfits[:5]) - self.assertEqual(5, len(datasets5)) - self.assertEqual("d720", datasets5[-1].name) - return - - def test_getPhases(self): - """Check LoadProject.getPhases()""" - lcmofullfits = self.prj_lcmo_full.getFits() - phases = self.prj_lcmo_full.getPhases() - self.assertAlmostEqual(5.53884, phases[0].refined.lattice.a, 4) - self.assertAlmostEqual(5.54342, phases[1].refined.lattice.a, 4) - self.assertEqual(10, len(phases)) - phases3 = self.prj_lcmo_full.getPhases(lcmofullfits[:3]) - self.assertEqual(3, len(phases3)) - return - - def test_getTemperatures(self): - """Check LoadProject.getTemperatures()""" - temps = self.prj_lcmo_full.getTemperatures() - self.assertEqual(10, len(temps)) - self.assertEqual(300, temps[0]) - self.assertEqual(980, temps[-1]) - datasets3 = self.prj_lcmo_full.getDataSets()[:3] - temps3 = self.prj_lcmo_full.getTemperatures(datasets3) - self.assertEqual(650, temps3[-1]) - return - - def test_getDopings(self): - """Check LoadProject.getDopings()""" - dopings = self.prj_lcmo_full.getDopings() - self.assertEqual(10 * [None], dopings) - datasets3 = self.prj_lcmo_full.getDataSets()[:3] - dopings3 = self.prj_lcmo_full.getDopings(datasets3) - self.assertEqual(3 * [None], dopings3) - return - - -# End of class TestLoadProject - -# ---------------------------------------------------------------------------- - -if __name__ == "__main__": - unittest.main() - -# End of file diff --git a/tests/test_mainframe.py b/tests/test_mainframe.py deleted file mode 100644 index 0a2f63ed..00000000 --- a/tests/test_mainframe.py +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# diffpy.pdfgui Complex Modeling Initiative -# (c) 2019 Brookhaven Science Associates, -# Brookhaven National Laboratory. -# All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""Unit tests for the MainFrame class.""" - -import unittest - -import wx -from testutils import GUITestCase - -from diffpy.pdfgui.gui.mainframe import MainFrame - -# ---------------------------------------------------------------------------- - - -class TestMainFrame(GUITestCase): - @classmethod - def setUpClass(cls): - GUITestCase.setUpClass() - cls.app = wx.App() - cls.frame = MainFrame(None, -1, "") - return - - @classmethod - def tearDownClass(cls): - cls.frame.Close() - cls.app.Destroy() - GUITestCase.tearDownClass() - return - - def test_onRightClick(self): - "check MainFrame.onRightClick method for context menu" - # just instantiate the context menu - # disable modal Frame.PopupMenu - self.frame.PopupMenu = lambda menu, pos: None - e = wx.MouseEvent(wx.EVT_RIGHT_DOWN.typeId) - try: - self.frame.treeCtrlMain.ProcessEvent(e) - finally: - del self.frame.PopupMenu - self.assertIsNotNone(self.frame.PopupMenu) - return - - def test_disableMainMenuItems(self): - "cover MainFrame.disableMainMenuItems method." - self.frame.disableMainMenuItems() - return - - -# End of class TestMainFrame - -# ---------------------------------------------------------------------------- - -if __name__ == "__main__": - unittest.main() diff --git a/tests/test_parameter.py b/tests/test_parameter.py deleted file mode 100644 index f711ffce..00000000 --- a/tests/test_parameter.py +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# diffpy.pdfgui Complex Modeling Initiative -# (c) 2019 Brookhaven Science Associates, -# Brookhaven National Laboratory. -# All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""Unit tests for the Parameter class.""" - -import unittest - -import wx -from testutils import GUITestCase, datafile - -from diffpy.pdfgui.control.controlerrors import ControlKeyError, ControlTypeError -from diffpy.pdfgui.control.parameter import Parameter -from diffpy.pdfgui.gui.mainframe import MainFrame - -# ---------------------------------------------------------------------------- - - -class TestParameter(GUITestCase): - @classmethod - def setUpClass(cls): - GUITestCase.setUpClass() - GUITestCase.setCmdArgs([datafile("lcmo.ddp")]) - cls.app = wx.App() - cls.frame = MainFrame(None, -1, "") - tree = cls.frame.treeCtrlMain - fits = tree.GetChildren(tree.root) - cls.frame.makeTreeSelection(fits[0]) - return - - @classmethod - def tearDownClass(cls): - cls.frame.Close() - cls.app.Destroy() - GUITestCase.tearDownClass() - return - - def setUp(self): - self.fitting = self.frame.rightPanel.fit - return - - def test___init__(self): - "check Parameter.__init__" - p = Parameter(3, 2.2) - self.assertEqual(3, p.idx) - self.assertIsNone(p.refined) - self.assertEqual(2.2, p.initialValue()) - p100 = Parameter(100, self.fitting) - self.assertAlmostEqual(0.7957747, p100.initialValue(), 6) - p102 = Parameter(102, "=fit-d300:102") - self.assertAlmostEqual(1.1811493, p102.initialValue(), 6) - self.assertRaises(ControlTypeError, Parameter, 1, None) - return - - def test_initialValue(self): - "check Parameter.initialValue" - p1 = Parameter(1, 0.25) - self.assertEqual(0.25, p1.initialValue()) - self.assertEqual("0.25", p1.initialStr()) - px = Parameter(7, "=undefined") - self.assertRaises(ControlKeyError, px.initialValue) - self.assertEqual("=undefined:7", px.initialStr()) - return - - -# End of class TestParameter - -# ---------------------------------------------------------------------------- - -if __name__ == "__main__": - unittest.main() diff --git a/tests/test_parameterspanel.py b/tests/test_parameterspanel.py deleted file mode 100644 index 3f95decc..00000000 --- a/tests/test_parameterspanel.py +++ /dev/null @@ -1,127 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# diffpy.pdfgui Complex Modeling Initiative -# (c) 2018 Brookhaven Science Associates, -# Brookhaven National Laboratory. -# All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""Unit tests for ParametersPanel class.""" - -import unittest - -import wx.grid -from testutils import GUITestCase, clickcell - -from diffpy.pdfgui.control.parameter import Parameter -from diffpy.pdfgui.gui.parameterspanel import ParametersPanel - -# ---------------------------------------------------------------------------- - - -class TestParametersPanel(GUITestCase): - def setUp(self): - self.app = wx.App() - self.frame = wx.Frame(None) - self.panel = ParametersPanel(self.frame, -1) - self.panel.parameters.update( - [ - (1, Parameter(1, 0.1)), - (5, Parameter(5, 0.5)), - ] - ) - self.panel.refresh() - self.panel.mainFrame = self._mockUpMainFrame() - self.frame.window = self.panel - return - - def tearDown(self): - self.frame.Close() - self.app.Destroy() - return - - def test_onPopupFixFree(self): - "Check ParametersPanel.onPopupFixFree" - # event is not used, we just generate and reuse dummy event. - e = wx.PyCommandEvent(wx.EVT_MENU.typeId, wx.ID_ANY) - panel = self.panel - gp = self.panel.grid_parameters - plist = list(self.panel.parameters.values()) - gp.SetCellValue(0, 1, "") - self.assertTrue(all(not p.fixed for p in plist)) - gp.SelectAll() - panel.onPopupFixFree(e) - self.assertTrue(all(p.fixed for p in plist)) - self.assertEqual("1", gp.GetCellValue(0, 1)) - panel.onPopupFixFree(e) - self.assertTrue(all(not p.fixed for p in plist)) - gp.DeselectRow(0) - panel.onPopupFixFree(e) - self.assertFalse(plist[0].fixed) - self.assertTrue(plist[1].fixed) - return - - def test_applyCellChange(self): - "Check ParametersPanel.applyCellChange" - gp = self.panel.grid_parameters - mf = self.panel.mainFrame - panel = self.panel - self.assertFalse(mf.altered) - panel.applyCellChange(0, 0, 0.1) - self.assertFalse(mf.altered) - panel.applyCellChange(0, 0, 1.5) - self.assertTrue(mf.altered) - self.assertEqual("1.5", gp.GetCellValue(0, 0)) - self.assertEqual(1.5, panel.parameters[1].initialValue()) - return - - def test_onCellLeftClick(self): - "Check click handling on the Parameters grid." - gp = self.panel.grid_parameters - p = self.panel.parameters[1] - self.assertFalse(self.panel.mainFrame.altered) - self.assertEqual("0", gp.GetCellValue(0, 1)) - self.assertFalse(p.fixed) - clickcell(gp, "left", 0, 1) - self.assertEqual("1", gp.GetCellValue(0, 1)) - self.assertTrue(p.fixed) - self.assertTrue(self.panel.mainFrame.altered) - clickcell(gp, "left", 0, 1) - self.assertEqual("0", gp.GetCellValue(0, 1)) - clickcell(gp, "left", 0, 1, controlDown=True) - self.assertEqual("0", gp.GetCellValue(0, 1)) - clickcell(gp, "left", 0, 1, shiftDown=True) - self.assertEqual("0", gp.GetCellValue(0, 1)) - gp.SelectAll() - clickcell(gp, "left", 0, 1) - self.assertEqual("0", gp.GetCellValue(0, 1)) - gp.ClearSelection() - clickcell(gp, "left", 0, 1) - self.assertEqual("1", gp.GetCellValue(0, 1)) - return - - def test_onCellRightClick(self): - "Check right-click handling on the Parameters grid." - # disable modal grid_parameters.PopupMenu - gp = self.panel.grid_parameters - gp.PopupMenu = lambda menu, pos: None - try: - clickcell(gp, "right", 0, 1) - finally: - del gp.PopupMenu - self.assertTrue(self.panel.did_popupIDs) - return - - -# End of class TestParametersPanel - -# ---------------------------------------------------------------------------- - -if __name__ == "__main__": - unittest.main() diff --git a/tests/test_pdfdataset.py b/tests/test_pdfdataset.py deleted file mode 100644 index 0b268e8c..00000000 --- a/tests/test_pdfdataset.py +++ /dev/null @@ -1,126 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2008 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""Unit tests for pdfdataset.py.""" - - -import unittest - -from testutils import datafile - -from diffpy.pdfgui.control.pdfdataset import PDFDataSet - - -############################################################################## -class TestPDFDataSet(unittest.TestCase): - def setUp(self): - self.pdfds = PDFDataSet("test data set") - return - - def tearDown(self): - self.pdfds = None - return - - # def test___init__(self): - # """check PDFDataSet.__init__() - # """ - # return - # - # def test_clear(self): - # """check PDFDataSet.clear() - # """ - # return - # - # def test_setvar(self): - # """check PDFDataSet.setvar() - # """ - # return - # - # def test_getvar(self): - # """check PDFDataSet.getvar() - # """ - # return - # - def test_read(self): - """Check PDFDataSet.read()""" - # neutron data ------------------------------------------------- - fn_550K = datafile("550K.gr") - self.pdfds.read(fn_550K) - self.assertEqual("N", self.pdfds.stype) - self.assertEqual(32.0, self.pdfds.qmax) - # there are 2000 points in the file - npts = len(self.pdfds.robs) - self.assertEqual(2000, npts) - # drobs are all zero - self.assertEqual(npts * [0.0], self.pdfds.drobs) - # dGobs should be defined - self.assertTrue(min(self.pdfds.dGobs) > 0) - # x-ray data --------------------------------------------------- - fx_Ni = datafile("Ni_2-8.chi.gr") - self.pdfds.read(fx_Ni) - self.assertEqual("X", self.pdfds.stype) - self.assertEqual(40.0, self.pdfds.qmax) - # there are 2000 points in the file - npts = len(self.pdfds.robs) - self.assertEqual(2000, npts) - # drobs are all zero - self.assertEqual(npts * [0.0], self.pdfds.drobs) - # dGobs should be defined - self.assertTrue(min(self.pdfds.dGobs) > 0) - return - - def test_readStr(self): - """Check PDFDataSet.readStr()""" - # read Ni xray data, but invalidate the last dGobs - fx_Ni = datafile("Ni_2-8.chi.gr") - with open(fx_Ni) as fp: - sNi = fp.read() - lastdGobs = sNi.rstrip().rindex(" ") - sNi_no_dGobs = sNi[:lastdGobs] + " -1.3e-3" - self.pdfds.readStr(sNi_no_dGobs) - # there are 2000 points in the file - npts = len(self.pdfds.robs) - self.assertEqual(2000, npts) - # dGobs should be all zero - self.assertEqual(npts * [0.0], self.pdfds.dGobs) - return - - -# def test_write(self): -# """check PDFDataSet.write() -# """ -# return -# -# def test_writeStr(self): -# """check PDFDataSet.writeStr() -# """ -# return -# -# def test_copy(self): -# """check PDFDataSet.copy() -# """ -# return -# -# def test_close(self): -# """check PDFDataSet.close() -# """ -# return - -# End of class TestPDFDataSet - - -if __name__ == "__main__": - unittest.main() - -# End of file diff --git a/tests/test_pdfguicontrol.py b/tests/test_pdfguicontrol.py deleted file mode 100644 index fbd656c9..00000000 --- a/tests/test_pdfguicontrol.py +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# PDFgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2006 trustees of the Michigan State University. -# All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""Unit tests for pdfgui.control.pdfguicontrol.py.""" - - -import unittest - -from diffpy.pdfgui.control.pdfguicontrol import PDFGuiControl - -# ---------------------------------------------------------------------------- - - -class TestPDFGuiControl(unittest.TestCase): - """Test methods of PDFGuiControl.""" - - def setUp(self): - self.control = PDFGuiControl() - return - - def tearDown(self): - del self.control - return - - def test___init__(self): - "check PDFGuiControl.__init__" - self.assertEqual("", self.control.journal) - self.assertIsNone(self.control.projfile) - return - - -# End of class TestPDFGuiControl - -# ---------------------------------------------------------------------------- - -if __name__ == "__main__": - unittest.main() - -# End of file diff --git a/tests/test_pdfstructure.py b/tests/test_pdfstructure.py deleted file mode 100644 index cf9e2703..00000000 --- a/tests/test_pdfstructure.py +++ /dev/null @@ -1,114 +0,0 @@ -#!/usr/bin/env python - -"""Unit tests for class PDFStructure.""" - - -import unittest - -from testutils import datafile - -from diffpy.pdfgui.control.controlerrors import ControlFileError, ControlKeyError -from diffpy.pdfgui.control.pdfstructure import PDFStructure - -# ---------------------------------------------------------------------------- - - -class TestPDFStructure(unittest.TestCase): - def setUp(self): - self.stru = PDFStructure("noname") - return - - def tearDown(self): - return - - def test___init__(self): - """Check PDFStructure.__init__()""" - self.assertEqual("noname", self.stru.name) - return - - def test_read(self): - """Check PDFStructure.read()""" - stru = self.stru - notastructurefile = datafile("300K.gr") - self.assertRaises(ControlFileError, stru.read, notastructurefile, format="pdffit") - return - - def test_copy(self): - """Check PDFStructure.copy()""" - stru2 = self.stru.copy() - self.assertEqual("noname", stru2.name) - self.assertEqual(self.stru.pdffit, stru2.pdffit) - self.assertIsNot(self.stru.pdffit["ncell"], stru2.pdffit["ncell"]) - return - - def test_setvar(self): - """Check PDFStructure.setvar()""" - stru = self.stru - stru.addNewAtom("C", [0, 0, 0], anisotropy=True) - stru.setvar("pscale", 1.5) - self.assertEqual(1.5, stru.pdffit["scale"]) - stru.setvar("lat(1)", 4) - stru.setvar("lat(2)", 5) - stru.setvar("lat(3)", 7) - self.assertEqual(4, stru.lattice.a) - self.assertEqual(5, stru.lattice.b) - self.assertEqual(7, stru.lattice.c) - stru.setvar("lat(4)", 91) - stru.setvar("lat(5)", 92) - stru.setvar("lat(6)", 93) - self.assertEqual(91, stru.lattice.alpha) - self.assertEqual(92, stru.lattice.beta) - self.assertEqual(93, stru.lattice.gamma) - stru.setvar("spdiameter", 17) - self.assertEqual(17, stru.pdffit["spdiameter"]) - stru.setvar("stepcut", 19) - self.assertEqual(19, stru.pdffit["stepcut"]) - self.assertRaises(ControlKeyError, stru.setvar, "sstepcut", 6) - stru.setvar("x(1)", 0.1) - stru.setvar("y(1)", 0.2) - stru.setvar("z(1)", 0.3) - stru.setvar("occ(1)", 0.9) - stru.setvar("u23(1)", 0.004) - self.assertEqual([0.1, 0.2, 0.3], stru[0].xyz.tolist()) - self.assertEqual(0.9, stru[0].occupancy) - self.assertEqual(0.004, stru[0].U[1, 2]) - self.assertRaises(ControlKeyError, stru.setvar, "invalid(1)", 7) - return - - def test_getvar(self): - """Check PDFStructure.getvar()""" - from diffpy.structure import Atom - - stru = self.stru - abcABG = (3.0, 4.0, 5.0, 81, 82, 83) - stru.lattice.setLatPar(*abcABG) - for i in range(6): - self.assertEqual(abcABG[i], stru.getvar("lat(%i)" % (i + 1))) - stru.append(Atom("Ni", [0.1, 0.2, 0.3])) - self.assertEqual(0.1, stru.getvar("x(1)")) - self.assertEqual(0.2, stru.getvar("y(1)")) - self.assertEqual(0.3, stru.getvar("z(1)")) - self.assertEqual(1.0, stru.getvar("occ(1)")) - # pscale - self.assertEqual(1.0, stru.getvar("pscale")) - # spdiameter - self.assertEqual(0.0, stru.getvar("spdiameter")) - stru.pdffit["spdiameter"] = 37.7 - self.assertEqual(37.7, stru.getvar("spdiameter")) - # stepcut - self.assertEqual(0.0, stru.getvar("stepcut")) - stru.pdffit["stepcut"] = 17.7 - self.assertEqual(17.7, stru.getvar("stepcut")) - self.assertRaises(ControlKeyError, stru.getvar, "invalid(1)") - self.assertRaises(ControlKeyError, stru.getvar, "invalid") - return - - -# End of class TestPDFStructure - -# ---------------------------------------------------------------------------- - -if __name__ == "__main__": - unittest.main() - -# End of file diff --git a/tests/test_phaseconfigurepanel.py b/tests/test_phaseconfigurepanel.py deleted file mode 100644 index eec00bdd..00000000 --- a/tests/test_phaseconfigurepanel.py +++ /dev/null @@ -1,83 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# diffpy.pdfgui Complex Modeling Initiative -# (c) 2019 Brookhaven Science Associates, -# Brookhaven National Laboratory. -# All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""Unit tests for PhaseConfigurePanel class.""" - -import unittest - -import wx -from testutils import GUITestCase, clickcell, datafile, overrideclipboard, tooltiptext - -from diffpy.pdfgui.gui.mainframe import MainFrame -from diffpy.pdfgui.gui.phaseconfigurepanel import PhaseConfigurePanel - -# ---------------------------------------------------------------------------- - - -class TestPhaseConfigurePanel(GUITestCase): - @classmethod - def setUpClass(cls): - GUITestCase.setUpClass() - GUITestCase.setCmdArgs([datafile("lcmo.ddp")]) - cls.app = wx.App() - cls.frame = MainFrame(None, -1, "") - tree = cls.frame.treeCtrlMain - fits = tree.GetChildren(tree.root) - phases = tree.GetPhases(fits[0]) - cls.frame.makeTreeSelection(phases[0]) - return - - @classmethod - def tearDownClass(cls): - cls.frame.Close() - cls.app.Destroy() - GUITestCase.tearDownClass() - return - - def setUp(self): - self.panel = self.frame.rightPanel.notebook_phase.GetPage(0) - assert isinstance(self.panel, PhaseConfigurePanel) - return - - def test_restrictConstrainedParameters(self): - "check restrictConstrainedParameters function" - panel = self.panel - grid = self.panel.gridAtoms - self.assertTrue(panel.textCtrlScaleFactor.IsEditable()) - self.assertFalse(panel.textCtrlDelta1.IsEditable()) - self.assertTrue(grid.IsReadOnly(0, 1)) - self.assertFalse(grid.IsReadOnly(0, 3)) - self.assertEqual("@1", tooltiptext(panel.textCtrlA)) - return - - def test_onCellRightClick(self): - "check right-click handling over the atoms grid." - # disable modal gridAtoms.PopupMenu - ga = self.panel.gridAtoms - ga.PopupMenu = lambda menu, pos: None - try: - with overrideclipboard(): - clickcell(ga, "right", 0, 1) - finally: - del ga.PopupMenu - self.assertIsNotNone(self.panel.insertID) - return - - -# End of class TestPhaseConfigurePanel - -# ---------------------------------------------------------------------------- - -if __name__ == "__main__": - unittest.main() diff --git a/tests/test_showphasenotebookpanel.py b/tests/test_showphasenotebookpanel.py deleted file mode 100644 index 93db6f8f..00000000 --- a/tests/test_showphasenotebookpanel.py +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# diffpy.pdfgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2016-2024 Trustees of the Columbia University -# in the City of New York. All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""Display the PhaseNotebookPanel.""" - - -import wx -from testutils import datafile - -from diffpy.pdfgui.gui.phasenotebookpanel import PhaseNotebookPanel -from diffpy.pdfgui.tui import LoadProject - - -class MyFrame(wx.Frame): - def __init__(self, *args, **kwds): - kwds["style"] = wx.DEFAULT_FRAME_STYLE - wx.Frame.__init__(self, *args, **kwds) - self.window = PhaseNotebookPanel(self, -1) - self.SetTitle("testing") - # choke, mainframe.needsSave() emulation - self.window.mainFrame = self.window - self.window.mainFrame.needsSave = self.dummy - - # choke, treeCtrlMain.GetSelections() emulation - self.window.treeCtrlMain = self.window - self.window.treeCtrlMain.GetSelections = self.dummy_dict - # self.window.treeCtrlMain.GetBranchType = self.dummy_true - self.window.quitting = False - self.test() - - def dummy(self, *args, **kwds): - pass - - def dummy_dict(self, *args, **kwds): - return [True] - - def dummy_true(self, *args, **kwds): - return True - - def test(self): - """Testing code goes here.""" - project = LoadProject(datafile("lcmo.ddp")) - fstru = project.getPhases()[0] - self.window.configuration = fstru - self.window.results = fstru.refined - self.window.constraints = fstru.constraints - self.window.refresh() - - -class MyApp(wx.App): - def OnInit(self): - frame_1 = MyFrame(None, -1, "") - self.SetTopWindow(frame_1) - frame_1.Show() - return True - - -if __name__ == "__main__": - app = MyApp(0) - app.MainLoop() - -# End of file diff --git a/tests/test_structureviewer.py b/tests/test_structureviewer.py deleted file mode 100644 index 8421e046..00000000 --- a/tests/test_structureviewer.py +++ /dev/null @@ -1,116 +0,0 @@ -#!/usr/bin/env python - -"""Unit tests for diffpy.pdfgui.control.structureviewer.""" - - -import os -import unittest - -from testutils import datafile - -from diffpy.pdfgui.control.controlerrors import ControlConfigError -from diffpy.pdfgui.control.structureviewer import StructureViewer, getStructureViewer - - -############################################################################## -class TestRoutines(unittest.TestCase): - def test_getStructureViewer(self): - """Check getStructureViewer() returns a singleton.""" - sv0 = getStructureViewer() - uid0 = id(sv0) - del sv0 - sv1 = getStructureViewer() - uid1 = id(sv1) - self.assertEqual(uid0, uid1) - return - - -# End of class TestRoutines - - -############################################################################## -class TestStructureViewer(unittest.TestCase): - def setUp(self): - return - - def tearDown(self): - return - - def test___init__(self): - """Check StructureViewer.__init__()""" - sv = StructureViewer() - self.assertEqual("%s", sv.argstr) - return - - def test_getConfig(self): - """Check StructureViewer.getConfig()""" - sv = StructureViewer() - self.assertEqual("%s", sv.getConfig()["argstr"]) - sv.argstr = "foooo" - self.assertEqual("foooo", sv.getConfig()["argstr"]) - return - - def test_setConfig(self): - """Check StructureViewer.setConfig()""" - sv = StructureViewer() - cfg0 = sv.getConfig() - sv.setConfig({"asdf": 7}) - self.assertEqual(cfg0, sv.getConfig()) - sv.setConfig({"executable": None}) - self.assertNotEqual(cfg0, sv.getConfig()) - return - - def test_plot(self): - """Check StructureViewer.plot()""" - from diffpy.pdfgui.control.fitstructure import FitStructure - - sv = StructureViewer() - # default executable is empty string - self.assertEqual("", sv.executable) - # and so plot raises ControlConfigError - fs = FitStructure("s1") - fs.read(datafile("LaMnO3.stru")) - self.assertRaises(ControlConfigError, sv.plot, fs) - sv.executable = "does/not/exist" - self.assertTrue(None is sv._tmpdir) - self.assertEqual(0, sv._plotcount) - self.assertRaises(ControlConfigError, sv.plot, fs) - self.assertTrue(os.path.isdir(sv._tmpdir)) - self.assertEqual(1, sv._plotcount) - return - - def test___del__(self): - """Check StructureViewer.__del__()""" - import gc - - from diffpy.pdfgui.control.fitstructure import FitStructure - - sv = StructureViewer() - sv.executable = "does/not/exist" - fs = FitStructure("s1") - fs.read(datafile("LaMnO3.stru")) - self.assertRaises(ControlConfigError, sv.plot, fs) - tmpd = sv._tmpdir - self.assertTrue(os.path.isdir(tmpd)) - del sv - gc.collect() - self.assertFalse(os.path.isdir(tmpd)) - return - - -# def test__writeTemporaryStructure(self): -# """check StructureViewer._writeTemporaryStructure() -# """ -# return -# -# def test__createTemporaryDirectory(self): -# """check StructureViewer._createTemporaryDirectory() -# """ -# return - -# End of class TestStructureViewer - -if __name__ == "__main__": - unittest.main() - -# End of file diff --git a/tests/test_temperatureseriespanel.py b/tests/test_temperatureseriespanel.py deleted file mode 100644 index dd02acfb..00000000 --- a/tests/test_temperatureseriespanel.py +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# diffpy.pdfgui Complex Modeling Initiative -# (c) 2019 Brookhaven Science Associates, -# Brookhaven National Laboratory. -# All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""Unit tests for the TemperatureSeriesPanel class.""" - -import unittest - -import wx -from testutils import GUITestCase, datafile, overridefiledialog - -from diffpy.pdfgui.gui.temperatureseriespanel import TemperatureSeriesPanel - -# ---------------------------------------------------------------------------- - - -class TestTemperatureSeriesPanel(GUITestCase): - def setUp(self): - self.app = wx.App() - self.frame = wx.Frame(None) - self.panel = TemperatureSeriesPanel(self.frame) - self.panel.mainFrame = self._mockUpMainFrame() - self.panel.mainFrame.workpath = datafile("") - return - - def tearDown(self): - self.frame.Close() - self.app.Destroy() - return - - def test_onAdd(self): - "Check TemperatureSeriesPanel.onAdd" - panel = self.panel - paths = ["T017K.gr", "137K.gr", "lcmo_00.gr", "lcmo_20.gr"] - paths = [datafile(p) for p in paths] - with overridefiledialog(wx.ID_OK, paths): - panel.onAdd(None) - self.assertEqual(paths[-1], panel.fullpath) - self.assertEqual([17, 137, 10, 10], [tf[0] for tf in panel.datasets]) - return - - -# End of class TestTemperatureSeriesPanel - -# ---------------------------------------------------------------------------- - -if __name__ == "__main__": - unittest.main() diff --git a/tests/test_version.py b/tests/test_version.py deleted file mode 100644 index d4519637..00000000 --- a/tests/test_version.py +++ /dev/null @@ -1,10 +0,0 @@ -"""Unit tests for __version__.py.""" - -import diffpy.pdfgui - - -def test_package_version(): - """Ensure the package version is defined and not set to the initial - placeholder.""" - assert hasattr(diffpy.pdfgui, "__version__") - assert diffpy.pdfgui.__version__ != "0.0.0" diff --git a/tests/testdata/300K.gr b/tests/testdata/300K.gr deleted file mode 100644 index 15578911..00000000 --- a/tests/testdata/300K.gr +++ /dev/null @@ -1,2062 +0,0 @@ -History written: Fri Apr 30 13:05:36 2004 -produced by -##### Run Information runCorrection=T -prep=gsas machine=npdf -run=300K background=npdf_00907 -smooth=2 smoothParam=32 32 0 backKillThresh=-1.0 -in beam: radius=0.635 height=2.54 -temp=308 runTitle=Run 1018: LMO - RT (before), HIPPO-furnace - -##### Vanadium runCorrection=T -run=npdf_00709 background=npdf_00710 -smooth=2 smoothParam=32 32 0 vanKillThresh=4.0 vBackKillThresh=-1.0 -in beam: radius=0.635 height=2.54 - -##### Container runCorrection=T -run=npdf_00917 background=npdf_00907 -smooth=2 smoothParam=32 32 0 cBackKillThresh=-1.0 -wallThick=0.023 atomDensity=0.072110 -atomic information: scattCS=5.100 absorpCS=5.080 - -##### Sample Material numElements=3 NormLaue=0.47445 -Element relAtomNum atomMass atomCoherCS atomIncoherCS atomAbsorpCS - O 0.6000 15.999 4.2320 0.0008 0.00019 - Mn 0.2000 54.931 -1.7500 0.4000 13.30000 - La 0.2000 138.905 8.5300 1.1300 8.97000 -density= effDensity=3.4138 - -##### Banks=6 deltaQ=0.01 matchRef=0 matchScal=T matchOffset=T -bank angle blendQmin blendQmax (0.0 means no info) - 1 90.0 1.62 29.42 - 2 -90.0 1.62 29.42 - 3 119.0 1.97 35.85 - 4 -119.0 1.97 35.85 - 5 148.0 2.20 40.00 - 6 -148.0 2.20 40.00 - -##### Program Specific Information -## Ft calcError=1 (1 for true, 0 for false) -numRpoints=2000 maxR=20.0 numDensity=0.0 intMaxR=1.5 -## Damp Qmin=2.0 Qmax=32 startDampQ=32 QAveMin=0.6 -dampFuncType=0 modEqn=1.0000*S(Q) +0.0000 +0.0000*Q dampExtraToZero=0 -## Blend numBanks=6 banks=1,2,3,4,5,6 -## Soqd minProcOut=0 -samPlazcek=0 vanPlazcek=0 smoothData=0 modifyData=1 -## Corps minProcOut=0 numBanksMiss=0 - -##### prepgsas prepOutput=1 numBanksMiss=0 fileExt=gsa -instParamFile=npdf_displex_757.iparm -numBanksAdd=0 -numBanksMult=6 -Bank# mulData mulBack - 1 1.0230 1.0000 - 2 1.0300 1.0000 - 3 1.0200 1.0000 - 4 0.9800 1.0000 - 5 0.9930 1.0000 - 6 0.9750 1.0000 -##### start data -#O0 rg_int sig_rg_int low_int sig_low_int rmax rhofit -#S 1 - PDF from PDFgetN -#P0 -4.09986 0.44295 0.11702 0.01370 1.50 0.0731 -#L r G(r) dr dG(r) - 0.010 0.086 0.0 0.0441 - 0.020 0.149 0.0 0.0849 - 0.030 0.169 0.0 0.1193 - 0.040 0.130 0.0 0.1448 - 0.050 0.021 0.0 0.1598 - 0.060 -0.160 0.0 0.1637 - 0.070 -0.410 0.0 0.1568 - 0.080 -0.717 0.0 0.1411 - 0.090 -1.064 0.0 0.1196 - 0.100 -1.428 0.0 0.0979 - 0.110 -1.782 0.0 0.0842 - 0.120 -2.101 0.0 0.0854 - 0.130 -2.359 0.0 0.0992 - 0.140 -2.535 0.0 0.1166 - 0.150 -2.612 0.0 0.1311 - 0.160 -2.581 0.0 0.1392 - 0.170 -2.440 0.0 0.1400 - 0.180 -2.196 0.0 0.1341 - 0.190 -1.863 0.0 0.1238 - 0.200 -1.462 0.0 0.1126 - 0.210 -1.017 0.0 0.1050 - 0.220 -0.556 0.0 0.1044 - 0.230 -0.109 0.0 0.1107 - 0.240 0.299 0.0 0.1202 - 0.250 0.643 0.0 0.1290 - 0.260 0.906 0.0 0.1341 - 0.270 1.077 0.0 0.1343 - 0.280 1.152 0.0 0.1298 - 0.290 1.134 0.0 0.1222 - 0.300 1.035 0.0 0.1143 - 0.310 0.870 0.0 0.1091 - 0.320 0.660 0.0 0.1090 - 0.330 0.426 0.0 0.1137 - 0.340 0.193 0.0 0.1209 - 0.350 -0.019 0.0 0.1275 - 0.360 -0.192 0.0 0.1313 - 0.370 -0.313 0.0 0.1313 - 0.380 -0.373 0.0 0.1276 - 0.390 -0.372 0.0 0.1217 - 0.400 -0.314 0.0 0.1156 - 0.410 -0.207 0.0 0.1119 - 0.420 -0.065 0.0 0.1121 - 0.430 0.095 0.0 0.1159 - 0.440 0.257 0.0 0.1215 - 0.450 0.404 0.0 0.1267 - 0.460 0.523 0.0 0.1295 - 0.470 0.601 0.0 0.1292 - 0.480 0.632 0.0 0.1259 - 0.490 0.614 0.0 0.1210 - 0.500 0.548 0.0 0.1163 - 0.510 0.443 0.0 0.1136 - 0.520 0.307 0.0 0.1141 - 0.530 0.152 0.0 0.1175 - 0.540 -0.007 0.0 0.1222 - 0.550 -0.158 0.0 0.1263 - 0.560 -0.290 0.0 0.1283 - 0.570 -0.393 0.0 0.1277 - 0.580 -0.461 0.0 0.1248 - 0.590 -0.493 0.0 0.1205 - 0.600 -0.490 0.0 0.1166 - 0.610 -0.458 0.0 0.1146 - 0.620 -0.404 0.0 0.1153 - 0.630 -0.338 0.0 0.1184 - 0.640 -0.271 0.0 0.1225 - 0.650 -0.214 0.0 0.1259 - 0.660 -0.176 0.0 0.1275 - 0.670 -0.163 0.0 0.1268 - 0.680 -0.180 0.0 0.1240 - 0.690 -0.228 0.0 0.1203 - 0.700 -0.306 0.0 0.1171 - 0.710 -0.409 0.0 0.1156 - 0.720 -0.529 0.0 0.1164 - 0.730 -0.659 0.0 0.1192 - 0.740 -0.789 0.0 0.1226 - 0.750 -0.910 0.0 0.1254 - 0.760 -1.015 0.0 0.1265 - 0.770 -1.097 0.0 0.1257 - 0.780 -1.153 0.0 0.1232 - 0.790 -1.181 0.0 0.1200 - 0.800 -1.185 0.0 0.1173 - 0.810 -1.166 0.0 0.1163 - 0.820 -1.132 0.0 0.1173 - 0.830 -1.088 0.0 0.1198 - 0.840 -1.043 0.0 0.1228 - 0.850 -1.002 0.0 0.1251 - 0.860 -0.973 0.0 0.1259 - 0.870 -0.958 0.0 0.1249 - 0.880 -0.961 0.0 0.1226 - 0.890 -0.982 0.0 0.1198 - 0.900 -1.018 0.0 0.1177 - 0.910 -1.066 0.0 0.1170 - 0.920 -1.122 0.0 0.1181 - 0.930 -1.179 0.0 0.1204 - 0.940 -1.232 0.0 0.1229 - 0.950 -1.277 0.0 0.1247 - 0.960 -1.308 0.0 0.1251 - 0.970 -1.324 0.0 0.1240 - 0.980 -1.325 0.0 0.1219 - 0.990 -1.311 0.0 0.1195 - 1.000 -1.287 0.0 0.1178 - 1.010 -1.255 0.0 0.1175 - 1.020 -1.222 0.0 0.1187 - 1.030 -1.192 0.0 0.1208 - 1.040 -1.170 0.0 0.1231 - 1.050 -1.161 0.0 0.1245 - 1.060 -1.165 0.0 0.1246 - 1.070 -1.185 0.0 0.1234 - 1.080 -1.217 0.0 0.1214 - 1.090 -1.260 0.0 0.1193 - 1.100 -1.309 0.0 0.1180 - 1.110 -1.358 0.0 0.1180 - 1.120 -1.401 0.0 0.1193 - 1.130 -1.432 0.0 0.1212 - 1.140 -1.448 0.0 0.1231 - 1.150 -1.443 0.0 0.1242 - 1.160 -1.417 0.0 0.1241 - 1.170 -1.371 0.0 0.1228 - 1.180 -1.307 0.0 0.1209 - 1.190 -1.230 0.0 0.1191 - 1.200 -1.147 0.0 0.1182 - 1.210 -1.065 0.0 0.1184 - 1.220 -0.992 0.0 0.1198 - 1.230 -0.934 0.0 0.1217 - 1.240 -0.898 0.0 0.1233 - 1.250 -0.888 0.0 0.1241 - 1.260 -0.905 0.0 0.1237 - 1.270 -0.950 0.0 0.1224 - 1.280 -1.019 0.0 0.1206 - 1.290 -1.106 0.0 0.1191 - 1.300 -1.205 0.0 0.1184 - 1.310 -1.306 0.0 0.1188 - 1.320 -1.400 0.0 0.1202 - 1.330 -1.479 0.0 0.1220 - 1.340 -1.534 0.0 0.1234 - 1.350 -1.562 0.0 0.1239 - 1.360 -1.557 0.0 0.1234 - 1.370 -1.519 0.0 0.1220 - 1.380 -1.452 0.0 0.1204 - 1.390 -1.360 0.0 0.1190 - 1.400 -1.251 0.0 0.1186 - 1.410 -1.133 0.0 0.1193 - 1.420 -1.017 0.0 0.1207 - 1.430 -0.913 0.0 0.1224 - 1.440 -0.830 0.0 0.1236 - 1.450 -0.775 0.0 0.1239 - 1.460 -0.755 0.0 0.1232 - 1.470 -0.770 0.0 0.1217 - 1.480 -0.822 0.0 0.1201 - 1.490 -0.906 0.0 0.1190 - 1.500 -1.017 0.0 0.1188 - 1.510 -1.147 0.0 0.1196 - 1.520 -1.285 0.0 0.1210 - 1.530 -1.422 0.0 0.1226 - 1.540 -1.548 0.0 0.1236 - 1.550 -1.653 0.0 0.1238 - 1.560 -1.730 0.0 0.1230 - 1.570 -1.774 0.0 0.1216 - 1.580 -1.781 0.0 0.1201 - 1.590 -1.753 0.0 0.1191 - 1.600 -1.691 0.0 0.1190 - 1.610 -1.600 0.0 0.1198 - 1.620 -1.487 0.0 0.1213 - 1.630 -1.360 0.0 0.1227 - 1.640 -1.227 0.0 0.1236 - 1.650 -1.097 0.0 0.1236 - 1.660 -0.977 0.0 0.1227 - 1.670 -0.876 0.0 0.1213 - 1.680 -0.797 0.0 0.1200 - 1.690 -0.747 0.0 0.1191 - 1.700 -0.727 0.0 0.1191 - 1.710 -0.739 0.0 0.1200 - 1.720 -0.782 0.0 0.1214 - 1.730 -0.858 0.0 0.1227 - 1.740 -0.964 0.0 0.1234 - 1.750 -1.099 0.0 0.1234 - 1.760 -1.262 0.0 0.1225 - 1.770 -1.452 0.0 0.1212 - 1.780 -1.668 0.0 0.1200 - 1.790 -1.908 0.0 0.1193 - 1.800 -2.171 0.0 0.1195 - 1.810 -2.456 0.0 0.1204 - 1.820 -2.758 0.0 0.1216 - 1.830 -3.075 0.0 0.1227 - 1.840 -3.401 0.0 0.1233 - 1.850 -3.730 0.0 0.1230 - 1.860 -4.053 0.0 0.1221 - 1.870 -4.362 0.0 0.1209 - 1.880 -4.647 0.0 0.1198 - 1.890 -4.897 0.0 0.1194 - 1.900 -5.103 0.0 0.1197 - 1.910 -5.256 0.0 0.1206 - 1.920 -5.349 0.0 0.1218 - 1.930 -5.378 0.0 0.1227 - 1.940 -5.342 0.0 0.1231 - 1.950 -5.241 0.0 0.1227 - 1.960 -5.081 0.0 0.1218 - 1.970 -4.869 0.0 0.1207 - 1.980 -4.618 0.0 0.1198 - 1.990 -4.340 0.0 0.1196 - 2.000 -4.050 0.0 0.1200 - 2.010 -3.762 0.0 0.1210 - 2.020 -3.493 0.0 0.1221 - 2.030 -3.253 0.0 0.1229 - 2.040 -3.056 0.0 0.1231 - 2.050 -2.907 0.0 0.1226 - 2.060 -2.811 0.0 0.1215 - 2.070 -2.769 0.0 0.1204 - 2.080 -2.778 0.0 0.1197 - 2.090 -2.831 0.0 0.1196 - 2.100 -2.918 0.0 0.1201 - 2.110 -3.029 0.0 0.1211 - 2.120 -3.150 0.0 0.1222 - 2.130 -3.270 0.0 0.1229 - 2.140 -3.377 0.0 0.1229 - 2.150 -3.460 0.0 0.1223 - 2.160 -3.511 0.0 0.1213 - 2.170 -3.525 0.0 0.1202 - 2.180 -3.499 0.0 0.1196 - 2.190 -3.432 0.0 0.1196 - 2.200 -3.327 0.0 0.1202 - 2.210 -3.188 0.0 0.1213 - 2.220 -3.019 0.0 0.1223 - 2.230 -2.825 0.0 0.1229 - 2.240 -2.613 0.0 0.1229 - 2.250 -2.385 0.0 0.1222 - 2.260 -2.145 0.0 0.1212 - 2.270 -1.895 0.0 0.1202 - 2.280 -1.633 0.0 0.1197 - 2.290 -1.359 0.0 0.1197 - 2.300 -1.069 0.0 0.1204 - 2.310 -0.761 0.0 0.1214 - 2.320 -0.431 0.0 0.1223 - 2.330 -0.077 0.0 0.1228 - 2.340 0.303 0.0 0.1227 - 2.350 0.706 0.0 0.1221 - 2.360 1.131 0.0 0.1211 - 2.370 1.571 0.0 0.1203 - 2.380 2.020 0.0 0.1198 - 2.390 2.466 0.0 0.1199 - 2.400 2.899 0.0 0.1206 - 2.410 3.309 0.0 0.1215 - 2.420 3.682 0.0 0.1223 - 2.430 4.010 0.0 0.1227 - 2.440 4.285 0.0 0.1225 - 2.450 4.501 0.0 0.1218 - 2.460 4.656 0.0 0.1210 - 2.470 4.751 0.0 0.1203 - 2.480 4.792 0.0 0.1200 - 2.490 4.788 0.0 0.1203 - 2.500 4.749 0.0 0.1210 - 2.510 4.688 0.0 0.1218 - 2.520 4.620 0.0 0.1225 - 2.530 4.558 0.0 0.1226 - 2.540 4.518 0.0 0.1223 - 2.550 4.508 0.0 0.1215 - 2.560 4.539 0.0 0.1207 - 2.570 4.615 0.0 0.1201 - 2.580 4.738 0.0 0.1200 - 2.590 4.907 0.0 0.1204 - 2.600 5.115 0.0 0.1212 - 2.610 5.354 0.0 0.1220 - 2.620 5.613 0.0 0.1226 - 2.630 5.882 0.0 0.1226 - 2.640 6.146 0.0 0.1222 - 2.650 6.395 0.0 0.1213 - 2.660 6.619 0.0 0.1205 - 2.670 6.808 0.0 0.1200 - 2.680 6.957 0.0 0.1200 - 2.690 7.063 0.0 0.1205 - 2.700 7.126 0.0 0.1214 - 2.710 7.148 0.0 0.1222 - 2.720 7.134 0.0 0.1227 - 2.730 7.090 0.0 0.1226 - 2.740 7.023 0.0 0.1221 - 2.750 6.941 0.0 0.1212 - 2.760 6.849 0.0 0.1204 - 2.770 6.754 0.0 0.1200 - 2.780 6.659 0.0 0.1201 - 2.790 6.567 0.0 0.1206 - 2.800 6.477 0.0 0.1215 - 2.810 6.388 0.0 0.1222 - 2.820 6.297 0.0 0.1226 - 2.830 6.201 0.0 0.1225 - 2.840 6.094 0.0 0.1219 - 2.850 5.972 0.0 0.1211 - 2.860 5.832 0.0 0.1204 - 2.870 5.671 0.0 0.1200 - 2.880 5.487 0.0 0.1202 - 2.890 5.281 0.0 0.1209 - 2.900 5.053 0.0 0.1217 - 2.910 4.807 0.0 0.1224 - 2.920 4.548 0.0 0.1227 - 2.930 4.279 0.0 0.1225 - 2.940 4.006 0.0 0.1218 - 2.950 3.734 0.0 0.1210 - 2.960 3.467 0.0 0.1203 - 2.970 3.208 0.0 0.1200 - 2.980 2.958 0.0 0.1202 - 2.990 2.720 0.0 0.1209 - 3.000 2.491 0.0 0.1218 - 3.010 2.269 0.0 0.1224 - 3.020 2.053 0.0 0.1227 - 3.030 1.838 0.0 0.1224 - 3.040 1.622 0.0 0.1217 - 3.050 1.402 0.0 0.1209 - 3.060 1.176 0.0 0.1202 - 3.070 0.942 0.0 0.1200 - 3.080 0.703 0.0 0.1203 - 3.090 0.459 0.0 0.1210 - 3.100 0.213 0.0 0.1218 - 3.110 -0.029 0.0 0.1224 - 3.120 -0.263 0.0 0.1226 - 3.130 -0.484 0.0 0.1223 - 3.140 -0.688 0.0 0.1216 - 3.150 -0.868 0.0 0.1208 - 3.160 -1.024 0.0 0.1202 - 3.170 -1.152 0.0 0.1201 - 3.180 -1.254 0.0 0.1204 - 3.190 -1.330 0.0 0.1211 - 3.200 -1.385 0.0 0.1218 - 3.210 -1.423 0.0 0.1223 - 3.220 -1.450 0.0 0.1224 - 3.230 -1.472 0.0 0.1220 - 3.240 -1.495 0.0 0.1214 - 3.250 -1.526 0.0 0.1206 - 3.260 -1.568 0.0 0.1202 - 3.270 -1.625 0.0 0.1201 - 3.280 -1.698 0.0 0.1205 - 3.290 -1.787 0.0 0.1212 - 3.300 -1.888 0.0 0.1220 - 3.310 -1.998 0.0 0.1224 - 3.320 -2.111 0.0 0.1224 - 3.330 -2.220 0.0 0.1219 - 3.340 -2.319 0.0 0.1212 - 3.350 -2.401 0.0 0.1205 - 3.360 -2.460 0.0 0.1201 - 3.370 -2.492 0.0 0.1201 - 3.380 -2.495 0.0 0.1206 - 3.390 -2.467 0.0 0.1213 - 3.400 -2.411 0.0 0.1220 - 3.410 -2.329 0.0 0.1224 - 3.420 -2.229 0.0 0.1223 - 3.430 -2.116 0.0 0.1219 - 3.440 -1.998 0.0 0.1212 - 3.450 -1.885 0.0 0.1205 - 3.460 -1.785 0.0 0.1202 - 3.470 -1.705 0.0 0.1202 - 3.480 -1.652 0.0 0.1207 - 3.490 -1.631 0.0 0.1214 - 3.500 -1.645 0.0 0.1220 - 3.510 -1.696 0.0 0.1223 - 3.520 -1.782 0.0 0.1222 - 3.530 -1.901 0.0 0.1217 - 3.540 -2.049 0.0 0.1211 - 3.550 -2.219 0.0 0.1205 - 3.560 -2.405 0.0 0.1203 - 3.570 -2.600 0.0 0.1204 - 3.580 -2.797 0.0 0.1209 - 3.590 -2.990 0.0 0.1215 - 3.600 -3.171 0.0 0.1220 - 3.610 -3.337 0.0 0.1223 - 3.620 -3.483 0.0 0.1221 - 3.630 -3.605 0.0 0.1216 - 3.640 -3.702 0.0 0.1210 - 3.650 -3.771 0.0 0.1205 - 3.660 -3.813 0.0 0.1204 - 3.670 -3.826 0.0 0.1206 - 3.680 -3.810 0.0 0.1211 - 3.690 -3.765 0.0 0.1217 - 3.700 -3.691 0.0 0.1221 - 3.710 -3.589 0.0 0.1222 - 3.720 -3.456 0.0 0.1219 - 3.730 -3.294 0.0 0.1214 - 3.740 -3.101 0.0 0.1209 - 3.750 -2.880 0.0 0.1205 - 3.760 -2.629 0.0 0.1205 - 3.770 -2.351 0.0 0.1208 - 3.780 -2.049 0.0 0.1213 - 3.790 -1.726 0.0 0.1219 - 3.800 -1.387 0.0 0.1222 - 3.810 -1.038 0.0 0.1222 - 3.820 -0.686 0.0 0.1219 - 3.830 -0.338 0.0 0.1213 - 3.840 -0.003 0.0 0.1208 - 3.850 0.312 0.0 0.1205 - 3.860 0.598 0.0 0.1205 - 3.870 0.848 0.0 0.1209 - 3.880 1.056 0.0 0.1215 - 3.890 1.215 0.0 0.1220 - 3.900 1.323 0.0 0.1223 - 3.910 1.377 0.0 0.1222 - 3.920 1.376 0.0 0.1218 - 3.930 1.322 0.0 0.1212 - 3.940 1.217 0.0 0.1206 - 3.950 1.065 0.0 0.1204 - 3.960 0.871 0.0 0.1205 - 3.970 0.640 0.0 0.1210 - 3.980 0.378 0.0 0.1216 - 3.990 0.091 0.0 0.1221 - 4.000 -0.215 0.0 0.1223 - 4.010 -0.536 0.0 0.1222 - 4.020 -0.866 0.0 0.1217 - 4.030 -1.203 0.0 0.1211 - 4.040 -1.543 0.0 0.1206 - 4.050 -1.884 0.0 0.1204 - 4.060 -2.224 0.0 0.1206 - 4.070 -2.562 0.0 0.1211 - 4.080 -2.896 0.0 0.1217 - 4.090 -3.225 0.0 0.1222 - 4.100 -3.547 0.0 0.1223 - 4.110 -3.859 0.0 0.1221 - 4.120 -4.159 0.0 0.1216 - 4.130 -4.443 0.0 0.1210 - 4.140 -4.707 0.0 0.1205 - 4.150 -4.946 0.0 0.1203 - 4.160 -5.155 0.0 0.1205 - 4.170 -5.329 0.0 0.1211 - 4.180 -5.463 0.0 0.1217 - 4.190 -5.552 0.0 0.1222 - 4.200 -5.595 0.0 0.1224 - 4.210 -5.588 0.0 0.1221 - 4.220 -5.529 0.0 0.1216 - 4.230 -5.421 0.0 0.1210 - 4.240 -5.265 0.0 0.1205 - 4.250 -5.064 0.0 0.1204 - 4.260 -4.824 0.0 0.1206 - 4.270 -4.551 0.0 0.1211 - 4.280 -4.251 0.0 0.1217 - 4.290 -3.932 0.0 0.1221 - 4.300 -3.602 0.0 0.1222 - 4.310 -3.268 0.0 0.1219 - 4.320 -2.936 0.0 0.1214 - 4.330 -2.613 0.0 0.1209 - 4.340 -2.302 0.0 0.1205 - 4.350 -2.007 0.0 0.1204 - 4.360 -1.729 0.0 0.1207 - 4.370 -1.469 0.0 0.1212 - 4.380 -1.226 0.0 0.1218 - 4.390 -0.996 0.0 0.1221 - 4.400 -0.779 0.0 0.1222 - 4.410 -0.569 0.0 0.1219 - 4.420 -0.365 0.0 0.1213 - 4.430 -0.162 0.0 0.1208 - 4.440 0.042 0.0 0.1205 - 4.450 0.248 0.0 0.1205 - 4.460 0.456 0.0 0.1208 - 4.470 0.667 0.0 0.1213 - 4.480 0.878 0.0 0.1218 - 4.490 1.086 0.0 0.1221 - 4.500 1.288 0.0 0.1220 - 4.510 1.481 0.0 0.1217 - 4.520 1.658 0.0 0.1212 - 4.530 1.818 0.0 0.1207 - 4.540 1.955 0.0 0.1204 - 4.550 2.067 0.0 0.1205 - 4.560 2.153 0.0 0.1208 - 4.570 2.213 0.0 0.1214 - 4.580 2.249 0.0 0.1218 - 4.590 2.262 0.0 0.1221 - 4.600 2.258 0.0 0.1220 - 4.610 2.241 0.0 0.1216 - 4.620 2.219 0.0 0.1211 - 4.630 2.198 0.0 0.1207 - 4.640 2.185 0.0 0.1204 - 4.650 2.185 0.0 0.1206 - 4.660 2.205 0.0 0.1209 - 4.670 2.249 0.0 0.1214 - 4.680 2.319 0.0 0.1219 - 4.690 2.416 0.0 0.1220 - 4.700 2.540 0.0 0.1219 - 4.710 2.688 0.0 0.1215 - 4.720 2.856 0.0 0.1210 - 4.730 3.037 0.0 0.1206 - 4.740 3.226 0.0 0.1204 - 4.750 3.413 0.0 0.1206 - 4.760 3.592 0.0 0.1210 - 4.770 3.755 0.0 0.1215 - 4.780 3.896 0.0 0.1219 - 4.790 4.007 0.0 0.1220 - 4.800 4.084 0.0 0.1219 - 4.810 4.125 0.0 0.1215 - 4.820 4.129 0.0 0.1210 - 4.830 4.094 0.0 0.1207 - 4.840 4.025 0.0 0.1206 - 4.850 3.923 0.0 0.1208 - 4.860 3.794 0.0 0.1212 - 4.870 3.642 0.0 0.1216 - 4.880 3.474 0.0 0.1219 - 4.890 3.295 0.0 0.1220 - 4.900 3.112 0.0 0.1218 - 4.910 2.928 0.0 0.1214 - 4.920 2.748 0.0 0.1210 - 4.930 2.576 0.0 0.1207 - 4.940 2.412 0.0 0.1207 - 4.950 2.258 0.0 0.1210 - 4.960 2.113 0.0 0.1214 - 4.970 1.977 0.0 0.1218 - 4.980 1.847 0.0 0.1220 - 4.990 1.720 0.0 0.1220 - 5.000 1.594 0.0 0.1217 - 5.010 1.467 0.0 0.1213 - 5.020 1.336 0.0 0.1209 - 5.030 1.199 0.0 0.1207 - 5.040 1.057 0.0 0.1208 - 5.050 0.908 0.0 0.1211 - 5.060 0.754 0.0 0.1215 - 5.070 0.597 0.0 0.1219 - 5.080 0.440 0.0 0.1220 - 5.090 0.286 0.0 0.1219 - 5.100 0.140 0.0 0.1216 - 5.110 0.005 0.0 0.1211 - 5.120 -0.113 0.0 0.1208 - 5.130 -0.212 0.0 0.1206 - 5.140 -0.288 0.0 0.1207 - 5.150 -0.338 0.0 0.1211 - 5.160 -0.360 0.0 0.1216 - 5.170 -0.356 0.0 0.1220 - 5.180 -0.325 0.0 0.1221 - 5.190 -0.270 0.0 0.1220 - 5.200 -0.195 0.0 0.1216 - 5.210 -0.104 0.0 0.1211 - 5.220 -0.003 0.0 0.1208 - 5.230 0.102 0.0 0.1207 - 5.240 0.205 0.0 0.1208 - 5.250 0.299 0.0 0.1212 - 5.260 0.378 0.0 0.1217 - 5.270 0.439 0.0 0.1220 - 5.280 0.476 0.0 0.1221 - 5.290 0.487 0.0 0.1219 - 5.300 0.472 0.0 0.1215 - 5.310 0.432 0.0 0.1210 - 5.320 0.368 0.0 0.1207 - 5.330 0.285 0.0 0.1206 - 5.340 0.188 0.0 0.1208 - 5.350 0.084 0.0 0.1212 - 5.360 -0.020 0.0 0.1217 - 5.370 -0.116 0.0 0.1220 - 5.380 -0.197 0.0 0.1220 - 5.390 -0.256 0.0 0.1218 - 5.400 -0.287 0.0 0.1214 - 5.410 -0.287 0.0 0.1209 - 5.420 -0.250 0.0 0.1206 - 5.430 -0.178 0.0 0.1206 - 5.440 -0.070 0.0 0.1208 - 5.450 0.070 0.0 0.1212 - 5.460 0.240 0.0 0.1217 - 5.470 0.433 0.0 0.1219 - 5.480 0.643 0.0 0.1219 - 5.490 0.863 0.0 0.1217 - 5.500 1.086 0.0 0.1212 - 5.510 1.306 0.0 0.1208 - 5.520 1.515 0.0 0.1206 - 5.530 1.711 0.0 0.1206 - 5.540 1.889 0.0 0.1209 - 5.550 2.048 0.0 0.1214 - 5.560 2.187 0.0 0.1218 - 5.570 2.307 0.0 0.1221 - 5.580 2.412 0.0 0.1220 - 5.590 2.504 0.0 0.1217 - 5.600 2.587 0.0 0.1213 - 5.610 2.664 0.0 0.1209 - 5.620 2.740 0.0 0.1206 - 5.630 2.817 0.0 0.1207 - 5.640 2.897 0.0 0.1210 - 5.650 2.979 0.0 0.1214 - 5.660 3.062 0.0 0.1218 - 5.670 3.144 0.0 0.1220 - 5.680 3.221 0.0 0.1219 - 5.690 3.287 0.0 0.1216 - 5.700 3.338 0.0 0.1212 - 5.710 3.366 0.0 0.1208 - 5.720 3.366 0.0 0.1206 - 5.730 3.333 0.0 0.1207 - 5.740 3.264 0.0 0.1210 - 5.750 3.156 0.0 0.1214 - 5.760 3.009 0.0 0.1218 - 5.770 2.825 0.0 0.1219 - 5.780 2.606 0.0 0.1218 - 5.790 2.357 0.0 0.1215 - 5.800 2.087 0.0 0.1211 - 5.810 1.802 0.0 0.1207 - 5.820 1.511 0.0 0.1206 - 5.830 1.222 0.0 0.1207 - 5.840 0.944 0.0 0.1210 - 5.850 0.684 0.0 0.1214 - 5.860 0.447 0.0 0.1218 - 5.870 0.238 0.0 0.1219 - 5.880 0.059 0.0 0.1217 - 5.890 -0.089 0.0 0.1214 - 5.900 -0.208 0.0 0.1210 - 5.910 -0.301 0.0 0.1207 - 5.920 -0.374 0.0 0.1206 - 5.930 -0.430 0.0 0.1208 - 5.940 -0.477 0.0 0.1212 - 5.950 -0.520 0.0 0.1216 - 5.960 -0.566 0.0 0.1219 - 5.970 -0.619 0.0 0.1219 - 5.980 -0.684 0.0 0.1217 - 5.990 -0.763 0.0 0.1214 - 6.000 -0.859 0.0 0.1210 - 6.010 -0.971 0.0 0.1207 - 6.020 -1.098 0.0 0.1207 - 6.030 -1.238 0.0 0.1209 - 6.040 -1.388 0.0 0.1212 - 6.050 -1.545 0.0 0.1216 - 6.060 -1.705 0.0 0.1219 - 6.070 -1.865 0.0 0.1220 - 6.080 -2.021 0.0 0.1217 - 6.090 -2.172 0.0 0.1214 - 6.100 -2.315 0.0 0.1210 - 6.110 -2.449 0.0 0.1207 - 6.120 -2.575 0.0 0.1207 - 6.130 -2.694 0.0 0.1209 - 6.140 -2.805 0.0 0.1213 - 6.150 -2.912 0.0 0.1217 - 6.160 -3.016 0.0 0.1219 - 6.170 -3.119 0.0 0.1219 - 6.180 -3.223 0.0 0.1217 - 6.190 -3.329 0.0 0.1213 - 6.200 -3.439 0.0 0.1210 - 6.210 -3.552 0.0 0.1208 - 6.220 -3.669 0.0 0.1208 - 6.230 -3.789 0.0 0.1211 - 6.240 -3.911 0.0 0.1214 - 6.250 -4.033 0.0 0.1217 - 6.260 -4.153 0.0 0.1219 - 6.270 -4.269 0.0 0.1218 - 6.280 -4.378 0.0 0.1216 - 6.290 -4.478 0.0 0.1213 - 6.300 -4.567 0.0 0.1210 - 6.310 -4.640 0.0 0.1208 - 6.320 -4.697 0.0 0.1209 - 6.330 -4.734 0.0 0.1212 - 6.340 -4.751 0.0 0.1215 - 6.350 -4.745 0.0 0.1218 - 6.360 -4.714 0.0 0.1219 - 6.370 -4.659 0.0 0.1218 - 6.380 -4.578 0.0 0.1215 - 6.390 -4.473 0.0 0.1211 - 6.400 -4.344 0.0 0.1209 - 6.410 -4.194 0.0 0.1208 - 6.420 -4.025 0.0 0.1209 - 6.430 -3.840 0.0 0.1212 - 6.440 -3.645 0.0 0.1215 - 6.450 -3.443 0.0 0.1218 - 6.460 -3.241 0.0 0.1219 - 6.470 -3.045 0.0 0.1217 - 6.480 -2.860 0.0 0.1214 - 6.490 -2.691 0.0 0.1211 - 6.500 -2.545 0.0 0.1208 - 6.510 -2.424 0.0 0.1208 - 6.520 -2.333 0.0 0.1210 - 6.530 -2.272 0.0 0.1213 - 6.540 -2.241 0.0 0.1217 - 6.550 -2.239 0.0 0.1219 - 6.560 -2.262 0.0 0.1219 - 6.570 -2.305 0.0 0.1216 - 6.580 -2.361 0.0 0.1213 - 6.590 -2.425 0.0 0.1209 - 6.600 -2.488 0.0 0.1207 - 6.610 -2.541 0.0 0.1207 - 6.620 -2.578 0.0 0.1209 - 6.630 -2.592 0.0 0.1213 - 6.640 -2.577 0.0 0.1216 - 6.650 -2.530 0.0 0.1219 - 6.660 -2.449 0.0 0.1218 - 6.670 -2.334 0.0 0.1216 - 6.680 -2.187 0.0 0.1213 - 6.690 -2.012 0.0 0.1209 - 6.700 -1.815 0.0 0.1207 - 6.710 -1.601 0.0 0.1207 - 6.720 -1.380 0.0 0.1209 - 6.730 -1.158 0.0 0.1213 - 6.740 -0.944 0.0 0.1216 - 6.750 -0.743 0.0 0.1218 - 6.760 -0.562 0.0 0.1218 - 6.770 -0.404 0.0 0.1216 - 6.780 -0.272 0.0 0.1212 - 6.790 -0.166 0.0 0.1209 - 6.800 -0.083 0.0 0.1208 - 6.810 -0.022 0.0 0.1208 - 6.820 0.023 0.0 0.1211 - 6.830 0.057 0.0 0.1214 - 6.840 0.088 0.0 0.1217 - 6.850 0.122 0.0 0.1218 - 6.860 0.164 0.0 0.1217 - 6.870 0.222 0.0 0.1214 - 6.880 0.299 0.0 0.1211 - 6.890 0.398 0.0 0.1208 - 6.900 0.521 0.0 0.1207 - 6.910 0.667 0.0 0.1208 - 6.920 0.835 0.0 0.1211 - 6.930 1.021 0.0 0.1215 - 6.940 1.221 0.0 0.1217 - 6.950 1.428 0.0 0.1218 - 6.960 1.636 0.0 0.1217 - 6.970 1.839 0.0 0.1214 - 6.980 2.030 0.0 0.1211 - 6.990 2.203 0.0 0.1209 - 7.000 2.353 0.0 0.1208 - 7.010 2.476 0.0 0.1209 - 7.020 2.569 0.0 0.1212 - 7.030 2.630 0.0 0.1215 - 7.040 2.660 0.0 0.1217 - 7.050 2.658 0.0 0.1217 - 7.060 2.627 0.0 0.1216 - 7.070 2.571 0.0 0.1213 - 7.080 2.493 0.0 0.1210 - 7.090 2.397 0.0 0.1207 - 7.100 2.289 0.0 0.1207 - 7.110 2.173 0.0 0.1209 - 7.120 2.053 0.0 0.1213 - 7.130 1.933 0.0 0.1216 - 7.140 1.819 0.0 0.1218 - 7.150 1.712 0.0 0.1218 - 7.160 1.615 0.0 0.1216 - 7.170 1.531 0.0 0.1213 - 7.180 1.461 0.0 0.1210 - 7.190 1.405 0.0 0.1209 - 7.200 1.366 0.0 0.1209 - 7.210 1.342 0.0 0.1211 - 7.220 1.333 0.0 0.1214 - 7.230 1.340 0.0 0.1217 - 7.240 1.363 0.0 0.1218 - 7.250 1.401 0.0 0.1218 - 7.260 1.455 0.0 0.1216 - 7.270 1.524 0.0 0.1213 - 7.280 1.608 0.0 0.1210 - 7.290 1.707 0.0 0.1208 - 7.300 1.823 0.0 0.1209 - 7.310 1.954 0.0 0.1211 - 7.320 2.099 0.0 0.1215 - 7.330 2.260 0.0 0.1217 - 7.340 2.434 0.0 0.1219 - 7.350 2.620 0.0 0.1218 - 7.360 2.816 0.0 0.1216 - 7.370 3.018 0.0 0.1213 - 7.380 3.224 0.0 0.1210 - 7.390 3.430 0.0 0.1209 - 7.400 3.631 0.0 0.1210 - 7.410 3.823 0.0 0.1213 - 7.420 4.001 0.0 0.1216 - 7.430 4.160 0.0 0.1218 - 7.440 4.297 0.0 0.1219 - 7.450 4.406 0.0 0.1218 - 7.460 4.486 0.0 0.1215 - 7.470 4.534 0.0 0.1212 - 7.480 4.550 0.0 0.1209 - 7.490 4.533 0.0 0.1208 - 7.500 4.485 0.0 0.1210 - 7.510 4.408 0.0 0.1212 - 7.520 4.306 0.0 0.1216 - 7.530 4.183 0.0 0.1218 - 7.540 4.044 0.0 0.1218 - 7.550 3.892 0.0 0.1217 - 7.560 3.733 0.0 0.1214 - 7.570 3.571 0.0 0.1211 - 7.580 3.409 0.0 0.1209 - 7.590 3.251 0.0 0.1208 - 7.600 3.097 0.0 0.1210 - 7.610 2.949 0.0 0.1213 - 7.620 2.804 0.0 0.1216 - 7.630 2.663 0.0 0.1218 - 7.640 2.523 0.0 0.1218 - 7.650 2.380 0.0 0.1216 - 7.660 2.233 0.0 0.1213 - 7.670 2.077 0.0 0.1210 - 7.680 1.911 0.0 0.1208 - 7.690 1.734 0.0 0.1208 - 7.700 1.543 0.0 0.1210 - 7.710 1.341 0.0 0.1213 - 7.720 1.128 0.0 0.1216 - 7.730 0.906 0.0 0.1218 - 7.740 0.681 0.0 0.1218 - 7.750 0.455 0.0 0.1216 - 7.760 0.234 0.0 0.1213 - 7.770 0.022 0.0 0.1209 - 7.780 -0.176 0.0 0.1208 - 7.790 -0.356 0.0 0.1208 - 7.800 -0.514 0.0 0.1210 - 7.810 -0.650 0.0 0.1213 - 7.820 -0.761 0.0 0.1216 - 7.830 -0.848 0.0 0.1218 - 7.840 -0.912 0.0 0.1217 - 7.850 -0.957 0.0 0.1215 - 7.860 -0.984 0.0 0.1212 - 7.870 -0.997 0.0 0.1209 - 7.880 -1.000 0.0 0.1208 - 7.890 -0.996 0.0 0.1208 - 7.900 -0.988 0.0 0.1210 - 7.910 -0.978 0.0 0.1213 - 7.920 -0.968 0.0 0.1216 - 7.930 -0.958 0.0 0.1217 - 7.940 -0.949 0.0 0.1217 - 7.950 -0.939 0.0 0.1214 - 7.960 -0.928 0.0 0.1211 - 7.970 -0.914 0.0 0.1209 - 7.980 -0.897 0.0 0.1207 - 7.990 -0.876 0.0 0.1208 - 8.000 -0.850 0.0 0.1211 - 8.010 -0.821 0.0 0.1214 - 8.020 -0.791 0.0 0.1217 - 8.030 -0.761 0.0 0.1218 - 8.040 -0.736 0.0 0.1217 - 8.050 -0.718 0.0 0.1215 - 8.060 -0.711 0.0 0.1211 - 8.070 -0.718 0.0 0.1209 - 8.080 -0.742 0.0 0.1208 - 8.090 -0.784 0.0 0.1209 - 8.100 -0.845 0.0 0.1211 - 8.110 -0.922 0.0 0.1214 - 8.120 -1.014 0.0 0.1217 - 8.130 -1.115 0.0 0.1218 - 8.140 -1.220 0.0 0.1216 - 8.150 -1.322 0.0 0.1214 - 8.160 -1.415 0.0 0.1211 - 8.170 -1.489 0.0 0.1208 - 8.180 -1.540 0.0 0.1208 - 8.190 -1.561 0.0 0.1209 - 8.200 -1.549 0.0 0.1212 - 8.210 -1.501 0.0 0.1215 - 8.220 -1.417 0.0 0.1217 - 8.230 -1.300 0.0 0.1218 - 8.240 -1.155 0.0 0.1217 - 8.250 -0.988 0.0 0.1214 - 8.260 -0.808 0.0 0.1211 - 8.270 -0.624 0.0 0.1209 - 8.280 -0.445 0.0 0.1209 - 8.290 -0.282 0.0 0.1210 - 8.300 -0.144 0.0 0.1213 - 8.310 -0.038 0.0 0.1216 - 8.320 0.030 0.0 0.1218 - 8.330 0.056 0.0 0.1218 - 8.340 0.039 0.0 0.1216 - 8.350 -0.020 0.0 0.1214 - 8.360 -0.119 0.0 0.1211 - 8.370 -0.253 0.0 0.1210 - 8.380 -0.415 0.0 0.1209 - 8.390 -0.598 0.0 0.1211 - 8.400 -0.794 0.0 0.1214 - 8.410 -0.996 0.0 0.1216 - 8.420 -1.195 0.0 0.1217 - 8.430 -1.387 0.0 0.1217 - 8.440 -1.565 0.0 0.1216 - 8.450 -1.725 0.0 0.1213 - 8.460 -1.864 0.0 0.1211 - 8.470 -1.980 0.0 0.1210 - 8.480 -2.073 0.0 0.1210 - 8.490 -2.143 0.0 0.1211 - 8.500 -2.189 0.0 0.1214 - 8.510 -2.213 0.0 0.1216 - 8.520 -2.215 0.0 0.1217 - 8.530 -2.196 0.0 0.1217 - 8.540 -2.156 0.0 0.1215 - 8.550 -2.096 0.0 0.1213 - 8.560 -2.016 0.0 0.1210 - 8.570 -1.916 0.0 0.1210 - 8.580 -1.798 0.0 0.1210 - 8.590 -1.664 0.0 0.1212 - 8.600 -1.516 0.0 0.1214 - 8.610 -1.358 0.0 0.1216 - 8.620 -1.194 0.0 0.1217 - 8.630 -1.030 0.0 0.1216 - 8.640 -0.872 0.0 0.1214 - 8.650 -0.728 0.0 0.1212 - 8.660 -0.604 0.0 0.1210 - 8.670 -0.508 0.0 0.1210 - 8.680 -0.446 0.0 0.1211 - 8.690 -0.423 0.0 0.1213 - 8.700 -0.442 0.0 0.1215 - 8.710 -0.505 0.0 0.1217 - 8.720 -0.611 0.0 0.1217 - 8.730 -0.758 0.0 0.1216 - 8.740 -0.941 0.0 0.1214 - 8.750 -1.154 0.0 0.1211 - 8.760 -1.387 0.0 0.1210 - 8.770 -1.633 0.0 0.1210 - 8.780 -1.883 0.0 0.1211 - 8.790 -2.127 0.0 0.1213 - 8.800 -2.357 0.0 0.1215 - 8.810 -2.568 0.0 0.1216 - 8.820 -2.753 0.0 0.1216 - 8.830 -2.911 0.0 0.1215 - 8.840 -3.041 0.0 0.1212 - 8.850 -3.144 0.0 0.1210 - 8.860 -3.222 0.0 0.1209 - 8.870 -3.280 0.0 0.1210 - 8.880 -3.323 0.0 0.1212 - 8.890 -3.357 0.0 0.1214 - 8.900 -3.384 0.0 0.1216 - 8.910 -3.411 0.0 0.1217 - 8.920 -3.438 0.0 0.1216 - 8.930 -3.467 0.0 0.1214 - 8.940 -3.498 0.0 0.1212 - 8.950 -3.529 0.0 0.1209 - 8.960 -3.554 0.0 0.1208 - 8.970 -3.571 0.0 0.1209 - 8.980 -3.574 0.0 0.1211 - 8.990 -3.556 0.0 0.1214 - 9.000 -3.515 0.0 0.1216 - 9.010 -3.445 0.0 0.1217 - 9.020 -3.346 0.0 0.1216 - 9.030 -3.215 0.0 0.1214 - 9.040 -3.055 0.0 0.1211 - 9.050 -2.869 0.0 0.1209 - 9.060 -2.661 0.0 0.1208 - 9.070 -2.438 0.0 0.1209 - 9.080 -2.207 0.0 0.1212 - 9.090 -1.976 0.0 0.1214 - 9.100 -1.752 0.0 0.1216 - 9.110 -1.542 0.0 0.1217 - 9.120 -1.351 0.0 0.1216 - 9.130 -1.183 0.0 0.1214 - 9.140 -1.041 0.0 0.1211 - 9.150 -0.925 0.0 0.1209 - 9.160 -0.835 0.0 0.1209 - 9.170 -0.768 0.0 0.1210 - 9.180 -0.720 0.0 0.1212 - 9.190 -0.688 0.0 0.1215 - 9.200 -0.666 0.0 0.1217 - 9.210 -0.651 0.0 0.1217 - 9.220 -0.638 0.0 0.1216 - 9.230 -0.626 0.0 0.1214 - 9.240 -0.611 0.0 0.1211 - 9.250 -0.593 0.0 0.1209 - 9.260 -0.572 0.0 0.1209 - 9.270 -0.546 0.0 0.1210 - 9.280 -0.518 0.0 0.1212 - 9.290 -0.487 0.0 0.1215 - 9.300 -0.453 0.0 0.1217 - 9.310 -0.416 0.0 0.1217 - 9.320 -0.372 0.0 0.1216 - 9.330 -0.320 0.0 0.1213 - 9.340 -0.255 0.0 0.1211 - 9.350 -0.172 0.0 0.1209 - 9.360 -0.066 0.0 0.1209 - 9.370 0.070 0.0 0.1211 - 9.380 0.241 0.0 0.1213 - 9.390 0.451 0.0 0.1215 - 9.400 0.704 0.0 0.1217 - 9.410 1.001 0.0 0.1217 - 9.420 1.341 0.0 0.1215 - 9.430 1.721 0.0 0.1213 - 9.440 2.135 0.0 0.1211 - 9.450 2.576 0.0 0.1210 - 9.460 3.035 0.0 0.1210 - 9.470 3.500 0.0 0.1211 - 9.480 3.959 0.0 0.1214 - 9.490 4.403 0.0 0.1216 - 9.500 4.819 0.0 0.1217 - 9.510 5.199 0.0 0.1217 - 9.520 5.536 0.0 0.1215 - 9.530 5.823 0.0 0.1213 - 9.540 6.060 0.0 0.1210 - 9.550 6.246 0.0 0.1209 - 9.560 6.384 0.0 0.1210 - 9.570 6.477 0.0 0.1211 - 9.580 6.533 0.0 0.1214 - 9.590 6.558 0.0 0.1216 - 9.600 6.558 0.0 0.1217 - 9.610 6.541 0.0 0.1216 - 9.620 6.512 0.0 0.1215 - 9.630 6.474 0.0 0.1212 - 9.640 6.430 0.0 0.1210 - 9.650 6.379 0.0 0.1210 - 9.660 6.321 0.0 0.1210 - 9.670 6.251 0.0 0.1212 - 9.680 6.166 0.0 0.1215 - 9.690 6.060 0.0 0.1216 - 9.700 5.929 0.0 0.1217 - 9.710 5.768 0.0 0.1216 - 9.720 5.574 0.0 0.1214 - 9.730 5.346 0.0 0.1212 - 9.740 5.085 0.0 0.1210 - 9.750 4.792 0.0 0.1210 - 9.760 4.472 0.0 0.1211 - 9.770 4.132 0.0 0.1213 - 9.780 3.778 0.0 0.1215 - 9.790 3.420 0.0 0.1216 - 9.800 3.065 0.0 0.1217 - 9.810 2.722 0.0 0.1216 - 9.820 2.398 0.0 0.1214 - 9.830 2.098 0.0 0.1211 - 9.840 1.826 0.0 0.1210 - 9.850 1.584 0.0 0.1210 - 9.860 1.371 0.0 0.1211 - 9.870 1.185 0.0 0.1213 - 9.880 1.021 0.0 0.1215 - 9.890 0.875 0.0 0.1217 - 9.900 0.741 0.0 0.1216 - 9.910 0.613 0.0 0.1215 - 9.920 0.485 0.0 0.1213 - 9.930 0.354 0.0 0.1211 - 9.940 0.216 0.0 0.1210 - 9.950 0.070 0.0 0.1210 - 9.960 -0.084 0.0 0.1211 - 9.970 -0.244 0.0 0.1213 - 9.980 -0.408 0.0 0.1215 - 9.990 -0.570 0.0 0.1217 - 10.000 -0.727 0.0 0.1216 - 10.010 -0.872 0.0 0.1215 - 10.020 -1.002 0.0 0.1212 - 10.030 -1.112 0.0 0.1210 - 10.040 -1.200 0.0 0.1209 - 10.050 -1.262 0.0 0.1210 - 10.060 -1.299 0.0 0.1212 - 10.070 -1.312 0.0 0.1214 - 10.080 -1.300 0.0 0.1216 - 10.090 -1.268 0.0 0.1217 - 10.100 -1.216 0.0 0.1216 - 10.110 -1.148 0.0 0.1214 - 10.120 -1.065 0.0 0.1212 - 10.130 -0.970 0.0 0.1210 - 10.140 -0.863 0.0 0.1209 - 10.150 -0.744 0.0 0.1210 - 10.160 -0.612 0.0 0.1212 - 10.170 -0.465 0.0 0.1214 - 10.180 -0.303 0.0 0.1216 - 10.190 -0.123 0.0 0.1217 - 10.200 0.075 0.0 0.1216 - 10.210 0.293 0.0 0.1214 - 10.220 0.529 0.0 0.1212 - 10.230 0.781 0.0 0.1210 - 10.240 1.044 0.0 0.1209 - 10.250 1.314 0.0 0.1210 - 10.260 1.582 0.0 0.1212 - 10.270 1.841 0.0 0.1214 - 10.280 2.081 0.0 0.1216 - 10.290 2.293 0.0 0.1217 - 10.300 2.466 0.0 0.1216 - 10.310 2.593 0.0 0.1213 - 10.320 2.666 0.0 0.1211 - 10.330 2.679 0.0 0.1209 - 10.340 2.630 0.0 0.1209 - 10.350 2.518 0.0 0.1210 - 10.360 2.343 0.0 0.1212 - 10.370 2.109 0.0 0.1215 - 10.380 1.822 0.0 0.1216 - 10.390 1.489 0.0 0.1217 - 10.400 1.119 0.0 0.1215 - 10.410 0.718 0.0 0.1213 - 10.420 0.298 0.0 0.1211 - 10.430 -0.135 0.0 0.1209 - 10.440 -0.574 0.0 0.1209 - 10.450 -1.012 0.0 0.1210 - 10.460 -1.444 0.0 0.1212 - 10.470 -1.868 0.0 0.1214 - 10.480 -2.282 0.0 0.1216 - 10.490 -2.685 0.0 0.1216 - 10.500 -3.077 0.0 0.1215 - 10.510 -3.458 0.0 0.1213 - 10.520 -3.829 0.0 0.1211 - 10.530 -4.190 0.0 0.1210 - 10.540 -4.541 0.0 0.1210 - 10.550 -4.879 0.0 0.1211 - 10.560 -5.204 0.0 0.1213 - 10.570 -5.511 0.0 0.1215 - 10.580 -5.797 0.0 0.1217 - 10.590 -6.059 0.0 0.1216 - 10.600 -6.290 0.0 0.1215 - 10.610 -6.489 0.0 0.1213 - 10.620 -6.650 0.0 0.1211 - 10.630 -6.771 0.0 0.1210 - 10.640 -6.850 0.0 0.1210 - 10.650 -6.888 0.0 0.1211 - 10.660 -6.886 0.0 0.1214 - 10.670 -6.845 0.0 0.1216 - 10.680 -6.769 0.0 0.1217 - 10.690 -6.663 0.0 0.1216 - 10.700 -6.532 0.0 0.1215 - 10.710 -6.380 0.0 0.1213 - 10.720 -6.212 0.0 0.1211 - 10.730 -6.032 0.0 0.1210 - 10.740 -5.844 0.0 0.1211 - 10.750 -5.648 0.0 0.1212 - 10.760 -5.445 0.0 0.1214 - 10.770 -5.234 0.0 0.1216 - 10.780 -5.013 0.0 0.1217 - 10.790 -4.780 0.0 0.1216 - 10.800 -4.529 0.0 0.1214 - 10.810 -4.257 0.0 0.1212 - 10.820 -3.959 0.0 0.1211 - 10.830 -3.633 0.0 0.1210 - 10.840 -3.274 0.0 0.1211 - 10.850 -2.880 0.0 0.1213 - 10.860 -2.452 0.0 0.1215 - 10.870 -1.989 0.0 0.1216 - 10.880 -1.494 0.0 0.1217 - 10.890 -0.970 0.0 0.1215 - 10.900 -0.421 0.0 0.1214 - 10.910 0.147 0.0 0.1211 - 10.920 0.727 0.0 0.1210 - 10.930 1.315 0.0 0.1210 - 10.940 1.901 0.0 0.1211 - 10.950 2.481 0.0 0.1213 - 10.960 3.047 0.0 0.1215 - 10.970 3.594 0.0 0.1217 - 10.980 4.115 0.0 0.1217 - 10.990 4.605 0.0 0.1216 - 11.000 5.060 0.0 0.1214 - 11.010 5.475 0.0 0.1212 - 11.020 5.846 0.0 0.1210 - 11.030 6.169 0.0 0.1210 - 11.040 6.441 0.0 0.1211 - 11.050 6.658 0.0 0.1213 - 11.060 6.817 0.0 0.1215 - 11.070 6.915 0.0 0.1216 - 11.080 6.950 0.0 0.1216 - 11.090 6.919 0.0 0.1215 - 11.100 6.823 0.0 0.1213 - 11.110 6.661 0.0 0.1211 - 11.120 6.434 0.0 0.1210 - 11.130 6.144 0.0 0.1210 - 11.140 5.793 0.0 0.1212 - 11.150 5.386 0.0 0.1214 - 11.160 4.929 0.0 0.1215 - 11.170 4.427 0.0 0.1216 - 11.180 3.888 0.0 0.1216 - 11.190 3.318 0.0 0.1214 - 11.200 2.725 0.0 0.1212 - 11.210 2.117 0.0 0.1211 - 11.220 1.502 0.0 0.1210 - 11.230 0.885 0.0 0.1210 - 11.240 0.272 0.0 0.1212 - 11.250 -0.330 0.0 0.1213 - 11.260 -0.918 0.0 0.1215 - 11.270 -1.488 0.0 0.1215 - 11.280 -2.037 0.0 0.1215 - 11.290 -2.563 0.0 0.1213 - 11.300 -3.065 0.0 0.1211 - 11.310 -3.539 0.0 0.1210 - 11.320 -3.986 0.0 0.1209 - 11.330 -4.404 0.0 0.1210 - 11.340 -4.791 0.0 0.1212 - 11.350 -5.146 0.0 0.1214 - 11.360 -5.467 0.0 0.1216 - 11.370 -5.752 0.0 0.1216 - 11.380 -5.999 0.0 0.1215 - 11.390 -6.206 0.0 0.1213 - 11.400 -6.371 0.0 0.1211 - 11.410 -6.493 0.0 0.1210 - 11.420 -6.571 0.0 0.1209 - 11.430 -6.605 0.0 0.1210 - 11.440 -6.595 0.0 0.1212 - 11.450 -6.543 0.0 0.1214 - 11.460 -6.450 0.0 0.1216 - 11.470 -6.319 0.0 0.1216 - 11.480 -6.154 0.0 0.1215 - 11.490 -5.958 0.0 0.1213 - 11.500 -5.735 0.0 0.1211 - 11.510 -5.488 0.0 0.1210 - 11.520 -5.222 0.0 0.1210 - 11.530 -4.940 0.0 0.1211 - 11.540 -4.646 0.0 0.1213 - 11.550 -4.342 0.0 0.1215 - 11.560 -4.031 0.0 0.1216 - 11.570 -3.713 0.0 0.1216 - 11.580 -3.391 0.0 0.1215 - 11.590 -3.064 0.0 0.1213 - 11.600 -2.734 0.0 0.1211 - 11.610 -2.399 0.0 0.1210 - 11.620 -2.062 0.0 0.1210 - 11.630 -1.720 0.0 0.1211 - 11.640 -1.375 0.0 0.1213 - 11.650 -1.026 0.0 0.1215 - 11.660 -0.673 0.0 0.1216 - 11.670 -0.319 0.0 0.1216 - 11.680 0.038 0.0 0.1215 - 11.690 0.395 0.0 0.1212 - 11.700 0.752 0.0 0.1210 - 11.710 1.106 0.0 0.1210 - 11.720 1.456 0.0 0.1210 - 11.730 1.800 0.0 0.1212 - 11.740 2.136 0.0 0.1214 - 11.750 2.461 0.0 0.1216 - 11.760 2.774 0.0 0.1217 - 11.770 3.071 0.0 0.1216 - 11.780 3.351 0.0 0.1215 - 11.790 3.611 0.0 0.1213 - 11.800 3.849 0.0 0.1211 - 11.810 4.063 0.0 0.1210 - 11.820 4.251 0.0 0.1210 - 11.830 4.411 0.0 0.1212 - 11.840 4.542 0.0 0.1214 - 11.850 4.644 0.0 0.1216 - 11.860 4.718 0.0 0.1216 - 11.870 4.763 0.0 0.1215 - 11.880 4.782 0.0 0.1214 - 11.890 4.776 0.0 0.1212 - 11.900 4.749 0.0 0.1210 - 11.910 4.704 0.0 0.1210 - 11.920 4.644 0.0 0.1211 - 11.930 4.574 0.0 0.1213 - 11.940 4.496 0.0 0.1215 - 11.950 4.416 0.0 0.1217 - 11.960 4.334 0.0 0.1217 - 11.970 4.254 0.0 0.1216 - 11.980 4.177 0.0 0.1214 - 11.990 4.102 0.0 0.1212 - 12.000 4.030 0.0 0.1211 - 12.010 3.959 0.0 0.1210 - 12.020 3.886 0.0 0.1211 - 12.030 3.809 0.0 0.1213 - 12.040 3.725 0.0 0.1215 - 12.050 3.631 0.0 0.1216 - 12.060 3.524 0.0 0.1217 - 12.070 3.403 0.0 0.1216 - 12.080 3.266 0.0 0.1214 - 12.090 3.115 0.0 0.1212 - 12.100 2.950 0.0 0.1211 - 12.110 2.775 0.0 0.1211 - 12.120 2.593 0.0 0.1212 - 12.130 2.411 0.0 0.1214 - 12.140 2.233 0.0 0.1215 - 12.150 2.066 0.0 0.1216 - 12.160 1.916 0.0 0.1216 - 12.170 1.789 0.0 0.1215 - 12.180 1.690 0.0 0.1213 - 12.190 1.622 0.0 0.1211 - 12.200 1.587 0.0 0.1210 - 12.210 1.587 0.0 0.1210 - 12.220 1.620 0.0 0.1211 - 12.230 1.684 0.0 0.1213 - 12.240 1.774 0.0 0.1215 - 12.250 1.886 0.0 0.1216 - 12.260 2.013 0.0 0.1216 - 12.270 2.150 0.0 0.1215 - 12.280 2.290 0.0 0.1213 - 12.290 2.427 0.0 0.1211 - 12.300 2.556 0.0 0.1210 - 12.310 2.673 0.0 0.1210 - 12.320 2.775 0.0 0.1212 - 12.330 2.860 0.0 0.1213 - 12.340 2.928 0.0 0.1215 - 12.350 2.979 0.0 0.1215 - 12.360 3.015 0.0 0.1215 - 12.370 3.036 0.0 0.1214 - 12.380 3.046 0.0 0.1212 - 12.390 3.045 0.0 0.1211 - 12.400 3.035 0.0 0.1210 - 12.410 3.016 0.0 0.1211 - 12.420 2.987 0.0 0.1212 - 12.430 2.947 0.0 0.1214 - 12.440 2.894 0.0 0.1215 - 12.450 2.825 0.0 0.1216 - 12.460 2.736 0.0 0.1215 - 12.470 2.625 0.0 0.1213 - 12.480 2.488 0.0 0.1211 - 12.490 2.322 0.0 0.1210 - 12.500 2.127 0.0 0.1209 - 12.510 1.901 0.0 0.1210 - 12.520 1.647 0.0 0.1212 - 12.530 1.367 0.0 0.1214 - 12.540 1.064 0.0 0.1215 - 12.550 0.745 0.0 0.1215 - 12.560 0.416 0.0 0.1214 - 12.570 0.083 0.0 0.1213 - 12.580 -0.245 0.0 0.1211 - 12.590 -0.561 0.0 0.1210 - 12.600 -0.858 0.0 0.1210 - 12.610 -1.131 0.0 0.1211 - 12.620 -1.376 0.0 0.1213 - 12.630 -1.588 0.0 0.1215 - 12.640 -1.767 0.0 0.1216 - 12.650 -1.912 0.0 0.1216 - 12.660 -2.026 0.0 0.1214 - 12.670 -2.111 0.0 0.1212 - 12.680 -2.172 0.0 0.1210 - 12.690 -2.212 0.0 0.1209 - 12.700 -2.237 0.0 0.1210 - 12.710 -2.251 0.0 0.1211 - 12.720 -2.259 0.0 0.1213 - 12.730 -2.264 0.0 0.1215 - 12.740 -2.269 0.0 0.1216 - 12.750 -2.276 0.0 0.1216 - 12.760 -2.285 0.0 0.1215 - 12.770 -2.297 0.0 0.1213 - 12.780 -2.310 0.0 0.1211 - 12.790 -2.324 0.0 0.1210 - 12.800 -2.336 0.0 0.1210 - 12.810 -2.345 0.0 0.1212 - 12.820 -2.350 0.0 0.1214 - 12.830 -2.349 0.0 0.1216 - 12.840 -2.343 0.0 0.1216 - 12.850 -2.333 0.0 0.1216 - 12.860 -2.319 0.0 0.1214 - 12.870 -2.303 0.0 0.1212 - 12.880 -2.289 0.0 0.1211 - 12.890 -2.279 0.0 0.1210 - 12.900 -2.275 0.0 0.1210 - 12.910 -2.282 0.0 0.1212 - 12.920 -2.301 0.0 0.1214 - 12.930 -2.333 0.0 0.1216 - 12.940 -2.381 0.0 0.1217 - 12.950 -2.444 0.0 0.1216 - 12.960 -2.521 0.0 0.1215 - 12.970 -2.612 0.0 0.1212 - 12.980 -2.712 0.0 0.1210 - 12.990 -2.820 0.0 0.1210 - 13.000 -2.931 0.0 0.1210 - 13.010 -3.043 0.0 0.1212 - 13.020 -3.150 0.0 0.1214 - 13.030 -3.251 0.0 0.1216 - 13.040 -3.342 0.0 0.1217 - 13.050 -3.420 0.0 0.1216 - 13.060 -3.485 0.0 0.1215 - 13.070 -3.535 0.0 0.1213 - 13.080 -3.570 0.0 0.1211 - 13.090 -3.592 0.0 0.1210 - 13.100 -3.601 0.0 0.1211 - 13.110 -3.599 0.0 0.1212 - 13.120 -3.589 0.0 0.1214 - 13.130 -3.571 0.0 0.1216 - 13.140 -3.549 0.0 0.1216 - 13.150 -3.524 0.0 0.1216 - 13.160 -3.497 0.0 0.1214 - 13.170 -3.469 0.0 0.1212 - 13.180 -3.441 0.0 0.1211 - 13.190 -3.412 0.0 0.1210 - 13.200 -3.381 0.0 0.1211 - 13.210 -3.349 0.0 0.1213 - 13.220 -3.314 0.0 0.1215 - 13.230 -3.273 0.0 0.1216 - 13.240 -3.226 0.0 0.1216 - 13.250 -3.170 0.0 0.1216 - 13.260 -3.105 0.0 0.1214 - 13.270 -3.028 0.0 0.1212 - 13.280 -2.939 0.0 0.1211 - 13.290 -2.836 0.0 0.1210 - 13.300 -2.719 0.0 0.1211 - 13.310 -2.587 0.0 0.1213 - 13.320 -2.440 0.0 0.1214 - 13.330 -2.277 0.0 0.1215 - 13.340 -2.100 0.0 0.1216 - 13.350 -1.907 0.0 0.1215 - 13.360 -1.701 0.0 0.1213 - 13.370 -1.483 0.0 0.1212 - 13.380 -1.252 0.0 0.1211 - 13.390 -1.012 0.0 0.1211 - 13.400 -0.763 0.0 0.1212 - 13.410 -0.508 0.0 0.1213 - 13.420 -0.251 0.0 0.1215 - 13.430 0.007 0.0 0.1216 - 13.440 0.261 0.0 0.1215 - 13.450 0.507 0.0 0.1214 - 13.460 0.743 0.0 0.1212 - 13.470 0.962 0.0 0.1211 - 13.480 1.162 0.0 0.1210 - 13.490 1.338 0.0 0.1210 - 13.500 1.486 0.0 0.1212 - 13.510 1.604 0.0 0.1213 - 13.520 1.689 0.0 0.1215 - 13.530 1.739 0.0 0.1216 - 13.540 1.755 0.0 0.1215 - 13.550 1.735 0.0 0.1214 - 13.560 1.682 0.0 0.1213 - 13.570 1.599 0.0 0.1212 - 13.580 1.489 0.0 0.1211 - 13.590 1.357 0.0 0.1211 - 13.600 1.208 0.0 0.1212 - 13.610 1.047 0.0 0.1213 - 13.620 0.882 0.0 0.1214 - 13.630 0.717 0.0 0.1215 - 13.640 0.559 0.0 0.1214 - 13.650 0.412 0.0 0.1213 - 13.660 0.282 0.0 0.1211 - 13.670 0.171 0.0 0.1211 - 13.680 0.081 0.0 0.1210 - 13.690 0.014 0.0 0.1211 - 13.700 -0.031 0.0 0.1213 - 13.710 -0.054 0.0 0.1214 - 13.720 -0.059 0.0 0.1215 - 13.730 -0.048 0.0 0.1215 - 13.740 -0.025 0.0 0.1214 - 13.750 0.006 0.0 0.1213 - 13.760 0.041 0.0 0.1211 - 13.770 0.075 0.0 0.1210 - 13.780 0.105 0.0 0.1210 - 13.790 0.128 0.0 0.1211 - 13.800 0.141 0.0 0.1213 - 13.810 0.143 0.0 0.1215 - 13.820 0.131 0.0 0.1216 - 13.830 0.107 0.0 0.1215 - 13.840 0.070 0.0 0.1214 - 13.850 0.021 0.0 0.1213 - 13.860 -0.039 0.0 0.1212 - 13.870 -0.109 0.0 0.1211 - 13.880 -0.187 0.0 0.1211 - 13.890 -0.273 0.0 0.1212 - 13.900 -0.364 0.0 0.1214 - 13.910 -0.461 0.0 0.1215 - 13.920 -0.564 0.0 0.1216 - 13.930 -0.671 0.0 0.1215 - 13.940 -0.782 0.0 0.1214 - 13.950 -0.897 0.0 0.1212 - 13.960 -1.017 0.0 0.1210 - 13.970 -1.138 0.0 0.1210 - 13.980 -1.261 0.0 0.1210 - 13.990 -1.381 0.0 0.1212 - 14.000 -1.497 0.0 0.1214 - 14.010 -1.605 0.0 0.1215 - 14.020 -1.699 0.0 0.1216 - 14.030 -1.774 0.0 0.1216 - 14.040 -1.825 0.0 0.1214 - 14.050 -1.846 0.0 0.1212 - 14.060 -1.830 0.0 0.1211 - 14.070 -1.775 0.0 0.1210 - 14.080 -1.674 0.0 0.1211 - 14.090 -1.526 0.0 0.1212 - 14.100 -1.330 0.0 0.1214 - 14.110 -1.085 0.0 0.1215 - 14.120 -0.795 0.0 0.1216 - 14.130 -0.463 0.0 0.1215 - 14.140 -0.094 0.0 0.1214 - 14.150 0.302 0.0 0.1212 - 14.160 0.720 0.0 0.1211 - 14.170 1.148 0.0 0.1211 - 14.180 1.579 0.0 0.1212 - 14.190 2.002 0.0 0.1213 - 14.200 2.410 0.0 0.1215 - 14.210 2.795 0.0 0.1216 - 14.220 3.150 0.0 0.1216 - 14.230 3.470 0.0 0.1215 - 14.240 3.753 0.0 0.1214 - 14.250 3.998 0.0 0.1212 - 14.260 4.203 0.0 0.1211 - 14.270 4.370 0.0 0.1211 - 14.280 4.503 0.0 0.1212 - 14.290 4.603 0.0 0.1213 - 14.300 4.674 0.0 0.1215 - 14.310 4.722 0.0 0.1216 - 14.320 4.748 0.0 0.1216 - 14.330 4.756 0.0 0.1215 - 14.340 4.750 0.0 0.1214 - 14.350 4.732 0.0 0.1212 - 14.360 4.703 0.0 0.1211 - 14.370 4.666 0.0 0.1211 - 14.380 4.622 0.0 0.1212 - 14.390 4.572 0.0 0.1213 - 14.400 4.519 0.0 0.1215 - 14.410 4.464 0.0 0.1215 - 14.420 4.410 0.0 0.1215 - 14.430 4.361 0.0 0.1215 - 14.440 4.320 0.0 0.1213 - 14.450 4.290 0.0 0.1212 - 14.460 4.276 0.0 0.1211 - 14.470 4.282 0.0 0.1211 - 14.480 4.310 0.0 0.1212 - 14.490 4.363 0.0 0.1214 - 14.500 4.442 0.0 0.1215 - 14.510 4.546 0.0 0.1216 - 14.520 4.674 0.0 0.1216 - 14.530 4.820 0.0 0.1215 - 14.540 4.980 0.0 0.1213 - 14.550 5.145 0.0 0.1211 - 14.560 5.308 0.0 0.1211 - 14.570 5.460 0.0 0.1211 - 14.580 5.591 0.0 0.1212 - 14.590 5.691 0.0 0.1213 - 14.600 5.752 0.0 0.1214 - 14.610 5.768 0.0 0.1215 - 14.620 5.734 0.0 0.1214 - 14.630 5.646 0.0 0.1213 - 14.640 5.503 0.0 0.1212 - 14.650 5.307 0.0 0.1211 - 14.660 5.063 0.0 0.1210 - 14.670 4.775 0.0 0.1211 - 14.680 4.451 0.0 0.1212 - 14.690 4.098 0.0 0.1214 - 14.700 3.724 0.0 0.1215 - 14.710 3.337 0.0 0.1215 - 14.720 2.945 0.0 0.1215 - 14.730 2.554 0.0 0.1213 - 14.740 2.166 0.0 0.1212 - 14.750 1.786 0.0 0.1211 - 14.760 1.414 0.0 0.1211 - 14.770 1.049 0.0 0.1211 - 14.780 0.689 0.0 0.1213 - 14.790 0.333 0.0 0.1214 - 14.800 -0.023 0.0 0.1215 - 14.810 -0.383 0.0 0.1215 - 14.820 -0.746 0.0 0.1215 - 14.830 -1.116 0.0 0.1213 - 14.840 -1.491 0.0 0.1212 - 14.850 -1.869 0.0 0.1211 - 14.860 -2.248 0.0 0.1211 - 14.870 -2.622 0.0 0.1211 - 14.880 -2.986 0.0 0.1213 - 14.890 -3.333 0.0 0.1214 - 14.900 -3.657 0.0 0.1215 - 14.910 -3.952 0.0 0.1215 - 14.920 -4.213 0.0 0.1214 - 14.930 -4.434 0.0 0.1213 - 14.940 -4.615 0.0 0.1212 - 14.950 -4.754 0.0 0.1211 - 14.960 -4.852 0.0 0.1211 - 14.970 -4.914 0.0 0.1212 - 14.980 -4.942 0.0 0.1213 - 14.990 -4.942 0.0 0.1215 - 15.000 -4.921 0.0 0.1215 - 15.010 -4.884 0.0 0.1215 - 15.020 -4.837 0.0 0.1214 - 15.030 -4.785 0.0 0.1213 - 15.040 -4.730 0.0 0.1211 - 15.050 -4.676 0.0 0.1211 - 15.060 -4.622 0.0 0.1211 - 15.070 -4.568 0.0 0.1212 - 15.080 -4.511 0.0 0.1213 - 15.090 -4.449 0.0 0.1215 - 15.100 -4.380 0.0 0.1215 - 15.110 -4.299 0.0 0.1215 - 15.120 -4.204 0.0 0.1214 - 15.130 -4.096 0.0 0.1212 - 15.140 -3.973 0.0 0.1211 - 15.150 -3.838 0.0 0.1211 - 15.160 -3.693 0.0 0.1211 - 15.170 -3.544 0.0 0.1213 - 15.180 -3.397 0.0 0.1214 - 15.190 -3.257 0.0 0.1215 - 15.200 -3.131 0.0 0.1215 - 15.210 -3.025 0.0 0.1215 - 15.220 -2.943 0.0 0.1213 - 15.230 -2.888 0.0 0.1212 - 15.240 -2.862 0.0 0.1211 - 15.250 -2.863 0.0 0.1211 - 15.260 -2.888 0.0 0.1212 - 15.270 -2.931 0.0 0.1213 - 15.280 -2.986 0.0 0.1215 - 15.290 -3.044 0.0 0.1216 - 15.300 -3.097 0.0 0.1216 - 15.310 -3.137 0.0 0.1215 - 15.320 -3.155 0.0 0.1213 - 15.330 -3.146 0.0 0.1212 - 15.340 -3.106 0.0 0.1211 - 15.350 -3.035 0.0 0.1211 - 15.360 -2.932 0.0 0.1212 - 15.370 -2.804 0.0 0.1213 - 15.380 -2.654 0.0 0.1215 - 15.390 -2.492 0.0 0.1216 - 15.400 -2.326 0.0 0.1216 - 15.410 -2.165 0.0 0.1215 - 15.420 -2.018 0.0 0.1213 - 15.430 -1.892 0.0 0.1212 - 15.440 -1.793 0.0 0.1211 - 15.450 -1.725 0.0 0.1211 - 15.460 -1.687 0.0 0.1212 - 15.470 -1.677 0.0 0.1214 - 15.480 -1.690 0.0 0.1215 - 15.490 -1.720 0.0 0.1216 - 15.500 -1.757 0.0 0.1216 - 15.510 -1.793 0.0 0.1215 - 15.520 -1.819 0.0 0.1213 - 15.530 -1.825 0.0 0.1212 - 15.540 -1.806 0.0 0.1211 - 15.550 -1.757 0.0 0.1211 - 15.560 -1.677 0.0 0.1212 - 15.570 -1.566 0.0 0.1214 - 15.580 -1.430 0.0 0.1215 - 15.590 -1.273 0.0 0.1216 - 15.600 -1.106 0.0 0.1215 - 15.610 -0.939 0.0 0.1214 - 15.620 -0.782 0.0 0.1213 - 15.630 -0.645 0.0 0.1211 - 15.640 -0.537 0.0 0.1211 - 15.650 -0.467 0.0 0.1211 - 15.660 -0.437 0.0 0.1212 - 15.670 -0.450 0.0 0.1214 - 15.680 -0.505 0.0 0.1215 - 15.690 -0.596 0.0 0.1216 - 15.700 -0.716 0.0 0.1215 - 15.710 -0.857 0.0 0.1214 - 15.720 -1.006 0.0 0.1212 - 15.730 -1.152 0.0 0.1211 - 15.740 -1.284 0.0 0.1210 - 15.750 -1.392 0.0 0.1211 - 15.760 -1.465 0.0 0.1212 - 15.770 -1.498 0.0 0.1214 - 15.780 -1.486 0.0 0.1215 - 15.790 -1.428 0.0 0.1215 - 15.800 -1.325 0.0 0.1215 - 15.810 -1.181 0.0 0.1213 - 15.820 -1.001 0.0 0.1212 - 15.830 -0.793 0.0 0.1211 - 15.840 -0.564 0.0 0.1210 - 15.850 -0.323 0.0 0.1211 - 15.860 -0.078 0.0 0.1212 - 15.870 0.164 0.0 0.1214 - 15.880 0.398 0.0 0.1215 - 15.890 0.619 0.0 0.1215 - 15.900 0.824 0.0 0.1214 - 15.910 1.010 0.0 0.1213 - 15.920 1.178 0.0 0.1211 - 15.930 1.328 0.0 0.1210 - 15.940 1.459 0.0 0.1210 - 15.950 1.574 0.0 0.1211 - 15.960 1.671 0.0 0.1212 - 15.970 1.752 0.0 0.1214 - 15.980 1.815 0.0 0.1215 - 15.990 1.860 0.0 0.1215 - 16.000 1.884 0.0 0.1214 - 16.010 1.885 0.0 0.1213 - 16.020 1.861 0.0 0.1212 - 16.030 1.810 0.0 0.1211 - 16.040 1.731 0.0 0.1211 - 16.050 1.623 0.0 0.1212 - 16.060 1.488 0.0 0.1213 - 16.070 1.326 0.0 0.1214 - 16.080 1.143 0.0 0.1215 - 16.090 0.942 0.0 0.1215 - 16.100 0.731 0.0 0.1214 - 16.110 0.516 0.0 0.1213 - 16.120 0.305 0.0 0.1211 - 16.130 0.106 0.0 0.1211 - 16.140 -0.075 0.0 0.1211 - 16.150 -0.230 0.0 0.1212 - 16.160 -0.355 0.0 0.1213 - 16.170 -0.444 0.0 0.1215 - 16.180 -0.496 0.0 0.1215 - 16.190 -0.510 0.0 0.1215 - 16.200 -0.484 0.0 0.1214 - 16.210 -0.421 0.0 0.1212 - 16.220 -0.323 0.0 0.1211 - 16.230 -0.192 0.0 0.1211 - 16.240 -0.032 0.0 0.1211 - 16.250 0.155 0.0 0.1212 - 16.260 0.366 0.0 0.1213 - 16.270 0.599 0.0 0.1215 - 16.280 0.852 0.0 0.1215 - 16.290 1.124 0.0 0.1215 - 16.300 1.413 0.0 0.1214 - 16.310 1.720 0.0 0.1212 - 16.320 2.042 0.0 0.1211 - 16.330 2.378 0.0 0.1211 - 16.340 2.725 0.0 0.1212 - 16.350 3.079 0.0 0.1213 - 16.360 3.437 0.0 0.1215 - 16.370 3.793 0.0 0.1216 - 16.380 4.141 0.0 0.1216 - 16.390 4.475 0.0 0.1215 - 16.400 4.786 0.0 0.1214 - 16.410 5.070 0.0 0.1212 - 16.420 5.319 0.0 0.1211 - 16.430 5.529 0.0 0.1211 - 16.440 5.696 0.0 0.1212 - 16.450 5.818 0.0 0.1213 - 16.460 5.897 0.0 0.1214 - 16.470 5.932 0.0 0.1215 - 16.480 5.929 0.0 0.1215 - 16.490 5.891 0.0 0.1215 - 16.500 5.825 0.0 0.1213 - 16.510 5.736 0.0 0.1212 - 16.520 5.630 0.0 0.1211 - 16.530 5.513 0.0 0.1211 - 16.540 5.388 0.0 0.1212 - 16.550 5.258 0.0 0.1213 - 16.560 5.123 0.0 0.1215 - 16.570 4.982 0.0 0.1215 - 16.580 4.832 0.0 0.1215 - 16.590 4.669 0.0 0.1214 - 16.600 4.487 0.0 0.1213 - 16.610 4.280 0.0 0.1212 - 16.620 4.045 0.0 0.1211 - 16.630 3.776 0.0 0.1211 - 16.640 3.472 0.0 0.1212 - 16.650 3.131 0.0 0.1214 - 16.660 2.757 0.0 0.1215 - 16.670 2.352 0.0 0.1216 - 16.680 1.925 0.0 0.1215 - 16.690 1.484 0.0 0.1214 - 16.700 1.040 0.0 0.1213 - 16.710 0.603 0.0 0.1212 - 16.720 0.185 0.0 0.1211 - 16.730 -0.203 0.0 0.1211 - 16.740 -0.553 0.0 0.1212 - 16.750 -0.856 0.0 0.1213 - 16.760 -1.110 0.0 0.1215 - 16.770 -1.313 0.0 0.1215 - 16.780 -1.465 0.0 0.1215 - 16.790 -1.573 0.0 0.1214 - 16.800 -1.643 0.0 0.1212 - 16.810 -1.684 0.0 0.1211 - 16.820 -1.705 0.0 0.1211 - 16.830 -1.716 0.0 0.1212 - 16.840 -1.727 0.0 0.1213 - 16.850 -1.746 0.0 0.1214 - 16.860 -1.778 0.0 0.1215 - 16.870 -1.826 0.0 0.1215 - 16.880 -1.892 0.0 0.1214 - 16.890 -1.972 0.0 0.1213 - 16.900 -2.062 0.0 0.1212 - 16.910 -2.154 0.0 0.1211 - 16.920 -2.241 0.0 0.1211 - 16.930 -2.313 0.0 0.1211 - 16.940 -2.362 0.0 0.1213 - 16.950 -2.379 0.0 0.1214 - 16.960 -2.360 0.0 0.1215 - 16.970 -2.299 0.0 0.1215 - 16.980 -2.197 0.0 0.1214 - 16.990 -2.055 0.0 0.1213 - 17.000 -1.878 0.0 0.1212 - 17.010 -1.673 0.0 0.1211 - 17.020 -1.449 0.0 0.1211 - 17.030 -1.216 0.0 0.1212 - 17.040 -0.985 0.0 0.1213 - 17.050 -0.766 0.0 0.1214 - 17.060 -0.568 0.0 0.1215 - 17.070 -0.398 0.0 0.1215 - 17.080 -0.261 0.0 0.1214 - 17.090 -0.159 0.0 0.1212 - 17.100 -0.093 0.0 0.1211 - 17.110 -0.060 0.0 0.1210 - 17.120 -0.056 0.0 0.1211 - 17.130 -0.073 0.0 0.1212 - 17.140 -0.105 0.0 0.1213 - 17.150 -0.146 0.0 0.1215 - 17.160 -0.187 0.0 0.1215 - 17.170 -0.223 0.0 0.1215 - 17.180 -0.250 0.0 0.1214 - 17.190 -0.266 0.0 0.1213 - 17.200 -0.270 0.0 0.1211 - 17.210 -0.264 0.0 0.1211 - 17.220 -0.252 0.0 0.1211 - 17.230 -0.237 0.0 0.1212 - 17.240 -0.226 0.0 0.1213 - 17.250 -0.225 0.0 0.1215 - 17.260 -0.238 0.0 0.1215 - 17.270 -0.270 0.0 0.1215 - 17.280 -0.325 0.0 0.1214 - 17.290 -0.405 0.0 0.1212 - 17.300 -0.509 0.0 0.1211 - 17.310 -0.636 0.0 0.1211 - 17.320 -0.782 0.0 0.1211 - 17.330 -0.943 0.0 0.1213 - 17.340 -1.114 0.0 0.1214 - 17.350 -1.289 0.0 0.1215 - 17.360 -1.462 0.0 0.1216 - 17.370 -1.629 0.0 0.1215 - 17.380 -1.783 0.0 0.1214 - 17.390 -1.923 0.0 0.1212 - 17.400 -2.046 0.0 0.1211 - 17.410 -2.151 0.0 0.1211 - 17.420 -2.237 0.0 0.1211 - 17.430 -2.307 0.0 0.1213 - 17.440 -2.360 0.0 0.1214 - 17.450 -2.399 0.0 0.1215 - 17.460 -2.425 0.0 0.1216 - 17.470 -2.439 0.0 0.1215 - 17.480 -2.441 0.0 0.1214 - 17.490 -2.431 0.0 0.1213 - 17.500 -2.407 0.0 0.1211 - 17.510 -2.369 0.0 0.1211 - 17.520 -2.313 0.0 0.1212 - 17.530 -2.239 0.0 0.1213 - 17.540 -2.145 0.0 0.1214 - 17.550 -2.031 0.0 0.1215 - 17.560 -1.896 0.0 0.1215 - 17.570 -1.743 0.0 0.1215 - 17.580 -1.575 0.0 0.1213 - 17.590 -1.397 0.0 0.1212 - 17.600 -1.216 0.0 0.1211 - 17.610 -1.038 0.0 0.1211 - 17.620 -0.873 0.0 0.1212 - 17.630 -0.727 0.0 0.1213 - 17.640 -0.610 0.0 0.1215 - 17.650 -0.528 0.0 0.1216 - 17.660 -0.486 0.0 0.1216 - 17.670 -0.488 0.0 0.1215 - 17.680 -0.536 0.0 0.1214 - 17.690 -0.628 0.0 0.1212 - 17.700 -0.761 0.0 0.1211 - 17.710 -0.930 0.0 0.1211 - 17.720 -1.127 0.0 0.1212 - 17.730 -1.343 0.0 0.1213 - 17.740 -1.570 0.0 0.1215 - 17.750 -1.797 0.0 0.1215 - 17.760 -2.015 0.0 0.1215 - 17.770 -2.217 0.0 0.1214 - 17.780 -2.396 0.0 0.1213 - 17.790 -2.547 0.0 0.1211 - 17.800 -2.666 0.0 0.1211 - 17.810 -2.754 0.0 0.1211 - 17.820 -2.810 0.0 0.1212 - 17.830 -2.837 0.0 0.1214 - 17.840 -2.839 0.0 0.1215 - 17.850 -2.819 0.0 0.1216 - 17.860 -2.781 0.0 0.1215 - 17.870 -2.730 0.0 0.1214 - 17.880 -2.668 0.0 0.1213 - 17.890 -2.599 0.0 0.1211 - 17.900 -2.522 0.0 0.1210 - 17.910 -2.438 0.0 0.1211 - 17.920 -2.346 0.0 0.1212 - 17.930 -2.244 0.0 0.1213 - 17.940 -2.130 0.0 0.1214 - 17.950 -2.001 0.0 0.1215 - 17.960 -1.855 0.0 0.1215 - 17.970 -1.690 0.0 0.1214 - 17.980 -1.505 0.0 0.1213 - 17.990 -1.302 0.0 0.1211 - 18.000 -1.080 0.0 0.1211 - 18.010 -0.845 0.0 0.1211 - 18.020 -0.598 0.0 0.1212 - 18.030 -0.344 0.0 0.1213 - 18.040 -0.090 0.0 0.1215 - 18.050 0.161 0.0 0.1215 - 18.060 0.404 0.0 0.1215 - 18.070 0.635 0.0 0.1214 - 18.080 0.849 0.0 0.1212 - 18.090 1.047 0.0 0.1211 - 18.100 1.226 0.0 0.1211 - 18.110 1.387 0.0 0.1211 - 18.120 1.532 0.0 0.1212 - 18.130 1.662 0.0 0.1214 - 18.140 1.779 0.0 0.1215 - 18.150 1.887 0.0 0.1215 - 18.160 1.987 0.0 0.1214 - 18.170 2.081 0.0 0.1213 - 18.180 2.170 0.0 0.1212 - 18.190 2.251 0.0 0.1211 - 18.200 2.325 0.0 0.1211 - 18.210 2.388 0.0 0.1212 - 18.220 2.437 0.0 0.1213 - 18.230 2.467 0.0 0.1214 - 18.240 2.475 0.0 0.1214 - 18.250 2.457 0.0 0.1215 - 18.260 2.410 0.0 0.1214 - 18.270 2.332 0.0 0.1213 - 18.280 2.224 0.0 0.1212 - 18.290 2.086 0.0 0.1211 - 18.300 1.922 0.0 0.1211 - 18.310 1.736 0.0 0.1212 - 18.320 1.534 0.0 0.1213 - 18.330 1.324 0.0 0.1214 - 18.340 1.113 0.0 0.1215 - 18.350 0.909 0.0 0.1215 - 18.360 0.719 0.0 0.1214 - 18.370 0.550 0.0 0.1213 - 18.380 0.406 0.0 0.1212 - 18.390 0.291 0.0 0.1211 - 18.400 0.207 0.0 0.1211 - 18.410 0.153 0.0 0.1212 - 18.420 0.127 0.0 0.1213 - 18.430 0.126 0.0 0.1214 - 18.440 0.145 0.0 0.1215 - 18.450 0.180 0.0 0.1215 - 18.460 0.224 0.0 0.1214 - 18.470 0.273 0.0 0.1213 - 18.480 0.323 0.0 0.1212 - 18.490 0.370 0.0 0.1212 - 18.500 0.413 0.0 0.1212 - 18.510 0.452 0.0 0.1213 - 18.520 0.486 0.0 0.1214 - 18.530 0.519 0.0 0.1215 - 18.540 0.553 0.0 0.1215 - 18.550 0.592 0.0 0.1214 - 18.560 0.640 0.0 0.1213 - 18.570 0.700 0.0 0.1212 - 18.580 0.775 0.0 0.1212 - 18.590 0.866 0.0 0.1212 - 18.600 0.973 0.0 0.1212 - 18.610 1.097 0.0 0.1213 - 18.620 1.233 0.0 0.1214 - 18.630 1.379 0.0 0.1215 - 18.640 1.530 0.0 0.1215 - 18.650 1.681 0.0 0.1215 - 18.660 1.827 0.0 0.1213 - 18.670 1.963 0.0 0.1212 - 18.680 2.085 0.0 0.1212 - 18.690 2.188 0.0 0.1212 - 18.700 2.271 0.0 0.1212 - 18.710 2.333 0.0 0.1213 - 18.720 2.374 0.0 0.1215 - 18.730 2.396 0.0 0.1215 - 18.740 2.402 0.0 0.1215 - 18.750 2.394 0.0 0.1214 - 18.760 2.376 0.0 0.1213 - 18.770 2.351 0.0 0.1212 - 18.780 2.323 0.0 0.1211 - 18.790 2.292 0.0 0.1211 - 18.800 2.261 0.0 0.1212 - 18.810 2.228 0.0 0.1214 - 18.820 2.193 0.0 0.1215 - 18.830 2.154 0.0 0.1215 - 18.840 2.106 0.0 0.1215 - 18.850 2.047 0.0 0.1214 - 18.860 1.973 0.0 0.1213 - 18.870 1.880 0.0 0.1211 - 18.880 1.767 0.0 0.1211 - 18.890 1.631 0.0 0.1211 - 18.900 1.474 0.0 0.1212 - 18.910 1.296 0.0 0.1213 - 18.920 1.100 0.0 0.1214 - 18.930 0.892 0.0 0.1215 - 18.940 0.678 0.0 0.1215 - 18.950 0.462 0.0 0.1214 - 18.960 0.254 0.0 0.1213 - 18.970 0.060 0.0 0.1212 - 18.980 -0.114 0.0 0.1211 - 18.990 -0.262 0.0 0.1212 - 19.000 -0.380 0.0 0.1213 - 19.010 -0.465 0.0 0.1214 - 19.020 -0.517 0.0 0.1215 - 19.030 -0.536 0.0 0.1215 - 19.040 -0.526 0.0 0.1214 - 19.050 -0.490 0.0 0.1213 - 19.060 -0.434 0.0 0.1212 - 19.070 -0.363 0.0 0.1211 - 19.080 -0.284 0.0 0.1211 - 19.090 -0.203 0.0 0.1211 - 19.100 -0.125 0.0 0.1212 - 19.110 -0.055 0.0 0.1214 - 19.120 0.005 0.0 0.1215 - 19.130 0.054 0.0 0.1215 - 19.140 0.090 0.0 0.1214 - 19.150 0.114 0.0 0.1213 - 19.160 0.130 0.0 0.1212 - 19.170 0.139 0.0 0.1211 - 19.180 0.146 0.0 0.1211 - 19.190 0.152 0.0 0.1212 - 19.200 0.161 0.0 0.1213 - 19.210 0.175 0.0 0.1214 - 19.220 0.195 0.0 0.1215 - 19.230 0.221 0.0 0.1215 - 19.240 0.253 0.0 0.1214 - 19.250 0.287 0.0 0.1213 - 19.260 0.321 0.0 0.1212 - 19.270 0.351 0.0 0.1211 - 19.280 0.373 0.0 0.1211 - 19.290 0.383 0.0 0.1212 - 19.300 0.377 0.0 0.1213 - 19.310 0.354 0.0 0.1214 - 19.320 0.310 0.0 0.1215 - 19.330 0.245 0.0 0.1215 - 19.340 0.160 0.0 0.1214 - 19.350 0.057 0.0 0.1213 - 19.360 -0.060 0.0 0.1212 - 19.370 -0.187 0.0 0.1211 - 19.380 -0.320 0.0 0.1211 - 19.390 -0.453 0.0 0.1212 - 19.400 -0.580 0.0 0.1213 - 19.410 -0.696 0.0 0.1214 - 19.420 -0.798 0.0 0.1215 - 19.430 -0.880 0.0 0.1215 - 19.440 -0.942 0.0 0.1214 - 19.450 -0.981 0.0 0.1213 - 19.460 -0.999 0.0 0.1211 - 19.470 -0.996 0.0 0.1211 - 19.480 -0.976 0.0 0.1211 - 19.490 -0.941 0.0 0.1212 - 19.500 -0.896 0.0 0.1213 - 19.510 -0.845 0.0 0.1214 - 19.520 -0.793 0.0 0.1215 - 19.530 -0.743 0.0 0.1215 - 19.540 -0.699 0.0 0.1214 - 19.550 -0.664 0.0 0.1213 - 19.560 -0.641 0.0 0.1212 - 19.570 -0.631 0.0 0.1211 - 19.580 -0.634 0.0 0.1211 - 19.590 -0.650 0.0 0.1212 - 19.600 -0.678 0.0 0.1214 - 19.610 -0.718 0.0 0.1215 - 19.620 -0.767 0.0 0.1215 - 19.630 -0.825 0.0 0.1215 - 19.640 -0.888 0.0 0.1214 - 19.650 -0.957 0.0 0.1213 - 19.660 -1.028 0.0 0.1212 - 19.670 -1.102 0.0 0.1211 - 19.680 -1.176 0.0 0.1212 - 19.690 -1.250 0.0 0.1213 - 19.700 -1.323 0.0 0.1214 - 19.710 -1.395 0.0 0.1215 - 19.720 -1.463 0.0 0.1215 - 19.730 -1.529 0.0 0.1215 - 19.740 -1.589 0.0 0.1214 - 19.750 -1.643 0.0 0.1213 - 19.760 -1.690 0.0 0.1212 - 19.770 -1.727 0.0 0.1212 - 19.780 -1.754 0.0 0.1212 - 19.790 -1.767 0.0 0.1213 - 19.800 -1.767 0.0 0.1214 - 19.810 -1.751 0.0 0.1215 - 19.820 -1.720 0.0 0.1215 - 19.830 -1.672 0.0 0.1215 - 19.840 -1.609 0.0 0.1213 - 19.850 -1.530 0.0 0.1212 - 19.860 -1.438 0.0 0.1211 - 19.870 -1.334 0.0 0.1211 - 19.880 -1.219 0.0 0.1212 - 19.890 -1.097 0.0 0.1213 - 19.900 -0.969 0.0 0.1214 - 19.910 -0.837 0.0 0.1215 - 19.920 -0.703 0.0 0.1215 - 19.930 -0.568 0.0 0.1214 - 19.940 -0.432 0.0 0.1213 - 19.950 -0.298 0.0 0.1212 - 19.960 -0.163 0.0 0.1211 - 19.970 -0.028 0.0 0.1211 - 19.980 0.108 0.0 0.1212 - 19.990 0.245 0.0 0.1213 - 20.000 0.384 0.0 0.1214 diff --git a/tests/testdata/550K.gr b/tests/testdata/550K.gr deleted file mode 100644 index 9786b3e4..00000000 --- a/tests/testdata/550K.gr +++ /dev/null @@ -1,2062 +0,0 @@ -History written: Fri Apr 30 14:12:28 2004 -produced by -##### Run Information runCorrection=T -prep=gsas machine=npdf -run=550K background=npdf_00907 -smooth=2 smoothParam=32 32 0 backKillThresh=-1.0 -in beam: radius=0.635 height=2.54 -temp=308 runTitle=LaMnO3 550.0, npdf_01031 HIPPO-furnace (cooling) - -##### Vanadium runCorrection=T -run=npdf_00709 background=npdf_00710 -smooth=2 smoothParam=32 32 0 vanKillThresh=4.0 vBackKillThresh=-1.0 -in beam: radius=0.635 height=2.54 - -##### Container runCorrection=T -run=npdf_00917 background=npdf_00907 -smooth=2 smoothParam=32 32 0 cBackKillThresh=-1.0 -wallThick=0.023 atomDensity=0.072110 -atomic information: scattCS=5.100 absorpCS=5.080 - -##### Sample Material numElements=3 NormLaue=0.47445 -Element relAtomNum atomMass atomCoherCS atomIncoherCS atomAbsorpCS - O 0.6000 15.999 4.2320 0.0008 0.00019 - Mn 0.2000 54.931 -1.7500 0.4000 13.30000 - La 0.2000 138.905 8.5300 1.1300 8.97000 -density= effDensity=3.3650 - -##### Banks=6 deltaQ=0.01 matchRef=0 matchScal=T matchOffset=T -bank angle blendQmin blendQmax (0.0 means no info) - 1 90.0 1.62 29.42 - 2 -90.0 1.62 29.42 - 3 119.0 1.97 35.85 - 4 -119.0 1.97 35.85 - 5 148.0 2.20 40.00 - 6 -148.0 2.20 40.00 - -##### Program Specific Information -## Ft calcError=1 (1 for true, 0 for false) -numRpoints=2000 maxR=20.0 numDensity=0.0 intMaxR=1.5 -## Damp Qmin=2.0 Qmax=32 startDampQ=32 QAveMin=0.6 -dampFuncType=0 modEqn=1.0000*S(Q) +0.0000 +0.0000*Q dampExtraToZero=0 -## Blend numBanks=6 banks=1,2,3,4,5,6 -## Soqd minProcOut=0 -samPlazcek=0 vanPlazcek=0 smoothData=0 modifyData=1 -## Corps minProcOut=0 numBanksMiss=0 - -##### prepgsas prepOutput=1 numBanksMiss=0 fileExt=gsa -instParamFile=npdf_displex_757.iparm -numBanksAdd=0 -numBanksMult=6 -Bank# mulData mulBack - 1 1.0230 1.0000 - 2 1.0300 1.0000 - 3 1.0200 1.0000 - 4 0.9800 1.0000 - 5 0.9930 1.0000 - 6 0.9750 1.0000 -##### start data -#O0 rg_int sig_rg_int low_int sig_low_int rmax rhofit -#S 1 - PDF from PDFgetN -#P0 -3.48169 0.30988 0.13070 0.00958 1.50 0.0737 -#L r G(r) dr dG(r) - 0.010 0.172 0.0 0.0309 - 0.020 0.323 0.0 0.0594 - 0.030 0.433 0.0 0.0835 - 0.040 0.488 0.0 0.1013 - 0.050 0.478 0.0 0.1118 - 0.060 0.399 0.0 0.1145 - 0.070 0.254 0.0 0.1097 - 0.080 0.053 0.0 0.0987 - 0.090 -0.189 0.0 0.0837 - 0.100 -0.452 0.0 0.0685 - 0.110 -0.713 0.0 0.0588 - 0.120 -0.948 0.0 0.0598 - 0.130 -1.135 0.0 0.0694 - 0.140 -1.252 0.0 0.0816 - 0.150 -1.286 0.0 0.0917 - 0.160 -1.228 0.0 0.0974 - 0.170 -1.076 0.0 0.0979 - 0.180 -0.834 0.0 0.0938 - 0.190 -0.516 0.0 0.0866 - 0.200 -0.140 0.0 0.0787 - 0.210 0.272 0.0 0.0734 - 0.220 0.694 0.0 0.0730 - 0.230 1.099 0.0 0.0774 - 0.240 1.464 0.0 0.0841 - 0.250 1.765 0.0 0.0902 - 0.260 1.987 0.0 0.0938 - 0.270 2.118 0.0 0.0940 - 0.280 2.155 0.0 0.0908 - 0.290 2.100 0.0 0.0855 - 0.300 1.963 0.0 0.0799 - 0.310 1.760 0.0 0.0763 - 0.320 1.511 0.0 0.0763 - 0.330 1.236 0.0 0.0795 - 0.340 0.961 0.0 0.0845 - 0.350 0.705 0.0 0.0892 - 0.360 0.489 0.0 0.0918 - 0.370 0.328 0.0 0.0918 - 0.380 0.230 0.0 0.0893 - 0.390 0.199 0.0 0.0851 - 0.400 0.234 0.0 0.0809 - 0.410 0.325 0.0 0.0783 - 0.420 0.462 0.0 0.0784 - 0.430 0.628 0.0 0.0811 - 0.440 0.805 0.0 0.0850 - 0.450 0.976 0.0 0.0886 - 0.460 1.124 0.0 0.0906 - 0.470 1.235 0.0 0.0904 - 0.480 1.298 0.0 0.0881 - 0.490 1.307 0.0 0.0847 - 0.500 1.262 0.0 0.0813 - 0.510 1.165 0.0 0.0795 - 0.520 1.024 0.0 0.0798 - 0.530 0.851 0.0 0.0822 - 0.540 0.659 0.0 0.0855 - 0.550 0.461 0.0 0.0883 - 0.560 0.272 0.0 0.0898 - 0.570 0.104 0.0 0.0894 - 0.580 -0.033 0.0 0.0873 - 0.590 -0.132 0.0 0.0843 - 0.600 -0.192 0.0 0.0816 - 0.610 -0.212 0.0 0.0802 - 0.620 -0.197 0.0 0.0807 - 0.630 -0.156 0.0 0.0828 - 0.640 -0.096 0.0 0.0856 - 0.650 -0.030 0.0 0.0880 - 0.660 0.033 0.0 0.0892 - 0.670 0.081 0.0 0.0887 - 0.680 0.106 0.0 0.0868 - 0.690 0.103 0.0 0.0842 - 0.700 0.068 0.0 0.0820 - 0.710 0.001 0.0 0.0809 - 0.720 -0.095 0.0 0.0815 - 0.730 -0.214 0.0 0.0834 - 0.740 -0.349 0.0 0.0858 - 0.750 -0.492 0.0 0.0877 - 0.760 -0.634 0.0 0.0885 - 0.770 -0.765 0.0 0.0879 - 0.780 -0.880 0.0 0.0862 - 0.790 -0.971 0.0 0.0839 - 0.800 -1.035 0.0 0.0821 - 0.810 -1.073 0.0 0.0814 - 0.820 -1.084 0.0 0.0821 - 0.830 -1.073 0.0 0.0838 - 0.840 -1.044 0.0 0.0859 - 0.850 -1.004 0.0 0.0875 - 0.860 -0.961 0.0 0.0881 - 0.870 -0.919 0.0 0.0874 - 0.880 -0.886 0.0 0.0858 - 0.890 -0.867 0.0 0.0838 - 0.900 -0.863 0.0 0.0823 - 0.910 -0.877 0.0 0.0819 - 0.920 -0.907 0.0 0.0826 - 0.930 -0.952 0.0 0.0842 - 0.940 -1.007 0.0 0.0860 - 0.950 -1.068 0.0 0.0872 - 0.960 -1.130 0.0 0.0875 - 0.970 -1.187 0.0 0.0868 - 0.980 -1.236 0.0 0.0853 - 0.990 -1.272 0.0 0.0836 - 1.000 -1.293 0.0 0.0824 - 1.010 -1.298 0.0 0.0822 - 1.020 -1.288 0.0 0.0831 - 1.030 -1.264 0.0 0.0845 - 1.040 -1.231 0.0 0.0861 - 1.050 -1.190 0.0 0.0871 - 1.060 -1.148 0.0 0.0871 - 1.070 -1.109 0.0 0.0863 - 1.080 -1.076 0.0 0.0849 - 1.090 -1.053 0.0 0.0835 - 1.100 -1.043 0.0 0.0826 - 1.110 -1.046 0.0 0.0826 - 1.120 -1.063 0.0 0.0835 - 1.130 -1.092 0.0 0.0848 - 1.140 -1.132 0.0 0.0861 - 1.150 -1.180 0.0 0.0869 - 1.160 -1.232 0.0 0.0868 - 1.170 -1.285 0.0 0.0859 - 1.180 -1.335 0.0 0.0846 - 1.190 -1.378 0.0 0.0834 - 1.200 -1.413 0.0 0.0827 - 1.210 -1.438 0.0 0.0829 - 1.220 -1.451 0.0 0.0838 - 1.230 -1.453 0.0 0.0851 - 1.240 -1.443 0.0 0.0863 - 1.250 -1.424 0.0 0.0868 - 1.260 -1.398 0.0 0.0865 - 1.270 -1.366 0.0 0.0856 - 1.280 -1.331 0.0 0.0844 - 1.290 -1.295 0.0 0.0833 - 1.300 -1.261 0.0 0.0828 - 1.310 -1.231 0.0 0.0832 - 1.320 -1.206 0.0 0.0841 - 1.330 -1.187 0.0 0.0854 - 1.340 -1.175 0.0 0.0863 - 1.350 -1.170 0.0 0.0867 - 1.360 -1.172 0.0 0.0863 - 1.370 -1.181 0.0 0.0853 - 1.380 -1.196 0.0 0.0842 - 1.390 -1.217 0.0 0.0833 - 1.400 -1.242 0.0 0.0830 - 1.410 -1.271 0.0 0.0835 - 1.420 -1.303 0.0 0.0845 - 1.430 -1.337 0.0 0.0856 - 1.440 -1.372 0.0 0.0865 - 1.450 -1.406 0.0 0.0867 - 1.460 -1.440 0.0 0.0862 - 1.470 -1.473 0.0 0.0852 - 1.480 -1.502 0.0 0.0840 - 1.490 -1.528 0.0 0.0832 - 1.500 -1.550 0.0 0.0831 - 1.510 -1.567 0.0 0.0836 - 1.520 -1.578 0.0 0.0847 - 1.530 -1.584 0.0 0.0858 - 1.540 -1.583 0.0 0.0865 - 1.550 -1.577 0.0 0.0866 - 1.560 -1.564 0.0 0.0860 - 1.570 -1.546 0.0 0.0850 - 1.580 -1.523 0.0 0.0840 - 1.590 -1.495 0.0 0.0833 - 1.600 -1.463 0.0 0.0832 - 1.610 -1.428 0.0 0.0838 - 1.620 -1.392 0.0 0.0848 - 1.630 -1.355 0.0 0.0858 - 1.640 -1.318 0.0 0.0865 - 1.650 -1.283 0.0 0.0865 - 1.660 -1.252 0.0 0.0858 - 1.670 -1.226 0.0 0.0849 - 1.680 -1.207 0.0 0.0839 - 1.690 -1.197 0.0 0.0833 - 1.700 -1.199 0.0 0.0834 - 1.710 -1.215 0.0 0.0840 - 1.720 -1.249 0.0 0.0850 - 1.730 -1.302 0.0 0.0859 - 1.740 -1.377 0.0 0.0864 - 1.750 -1.477 0.0 0.0863 - 1.760 -1.602 0.0 0.0857 - 1.770 -1.754 0.0 0.0848 - 1.780 -1.932 0.0 0.0839 - 1.790 -2.134 0.0 0.0835 - 1.800 -2.359 0.0 0.0836 - 1.810 -2.601 0.0 0.0842 - 1.820 -2.857 0.0 0.0851 - 1.830 -3.120 0.0 0.0859 - 1.840 -3.383 0.0 0.0862 - 1.850 -3.639 0.0 0.0861 - 1.860 -3.881 0.0 0.0854 - 1.870 -4.101 0.0 0.0846 - 1.880 -4.292 0.0 0.0838 - 1.890 -4.450 0.0 0.0835 - 1.900 -4.571 0.0 0.0837 - 1.910 -4.651 0.0 0.0844 - 1.920 -4.692 0.0 0.0852 - 1.930 -4.693 0.0 0.0859 - 1.940 -4.658 0.0 0.0861 - 1.950 -4.592 0.0 0.0859 - 1.960 -4.501 0.0 0.0852 - 1.970 -4.391 0.0 0.0844 - 1.980 -4.270 0.0 0.0838 - 1.990 -4.145 0.0 0.0836 - 2.000 -4.022 0.0 0.0839 - 2.010 -3.907 0.0 0.0846 - 2.020 -3.805 0.0 0.0854 - 2.030 -3.718 0.0 0.0860 - 2.040 -3.648 0.0 0.0861 - 2.050 -3.594 0.0 0.0857 - 2.060 -3.555 0.0 0.0850 - 2.070 -3.527 0.0 0.0842 - 2.080 -3.508 0.0 0.0837 - 2.090 -3.492 0.0 0.0836 - 2.100 -3.477 0.0 0.0840 - 2.110 -3.457 0.0 0.0848 - 2.120 -3.430 0.0 0.0855 - 2.130 -3.392 0.0 0.0860 - 2.140 -3.343 0.0 0.0860 - 2.150 -3.281 0.0 0.0856 - 2.160 -3.207 0.0 0.0849 - 2.170 -3.121 0.0 0.0841 - 2.180 -3.024 0.0 0.0836 - 2.190 -2.918 0.0 0.0836 - 2.200 -2.803 0.0 0.0841 - 2.210 -2.681 0.0 0.0848 - 2.220 -2.549 0.0 0.0856 - 2.230 -2.409 0.0 0.0860 - 2.240 -2.258 0.0 0.0860 - 2.250 -2.094 0.0 0.0855 - 2.260 -1.914 0.0 0.0848 - 2.270 -1.716 0.0 0.0841 - 2.280 -1.495 0.0 0.0837 - 2.290 -1.250 0.0 0.0837 - 2.300 -0.980 0.0 0.0842 - 2.310 -0.684 0.0 0.0849 - 2.320 -0.363 0.0 0.0856 - 2.330 -0.020 0.0 0.0859 - 2.340 0.340 0.0 0.0859 - 2.350 0.712 0.0 0.0854 - 2.360 1.089 0.0 0.0848 - 2.370 1.464 0.0 0.0841 - 2.380 1.828 0.0 0.0838 - 2.390 2.175 0.0 0.0839 - 2.400 2.497 0.0 0.0844 - 2.410 2.789 0.0 0.0850 - 2.420 3.046 0.0 0.0855 - 2.430 3.267 0.0 0.0858 - 2.440 3.451 0.0 0.0857 - 2.450 3.600 0.0 0.0852 - 2.460 3.718 0.0 0.0846 - 2.470 3.810 0.0 0.0841 - 2.480 3.882 0.0 0.0839 - 2.490 3.941 0.0 0.0842 - 2.500 3.995 0.0 0.0846 - 2.510 4.049 0.0 0.0852 - 2.520 4.109 0.0 0.0857 - 2.530 4.181 0.0 0.0858 - 2.540 4.267 0.0 0.0855 - 2.550 4.368 0.0 0.0850 - 2.560 4.485 0.0 0.0844 - 2.570 4.616 0.0 0.0840 - 2.580 4.757 0.0 0.0840 - 2.590 4.906 0.0 0.0843 - 2.600 5.058 0.0 0.0848 - 2.610 5.209 0.0 0.0854 - 2.620 5.355 0.0 0.0858 - 2.630 5.492 0.0 0.0858 - 2.640 5.619 0.0 0.0855 - 2.650 5.734 0.0 0.0849 - 2.660 5.837 0.0 0.0843 - 2.670 5.928 0.0 0.0839 - 2.680 6.009 0.0 0.0839 - 2.690 6.082 0.0 0.0843 - 2.700 6.147 0.0 0.0849 - 2.710 6.208 0.0 0.0855 - 2.720 6.265 0.0 0.0858 - 2.730 6.319 0.0 0.0858 - 2.740 6.369 0.0 0.0854 - 2.750 6.415 0.0 0.0848 - 2.760 6.453 0.0 0.0843 - 2.770 6.481 0.0 0.0839 - 2.780 6.497 0.0 0.0840 - 2.790 6.496 0.0 0.0844 - 2.800 6.474 0.0 0.0850 - 2.810 6.429 0.0 0.0855 - 2.820 6.360 0.0 0.0858 - 2.830 6.263 0.0 0.0857 - 2.840 6.140 0.0 0.0853 - 2.850 5.992 0.0 0.0847 - 2.860 5.820 0.0 0.0842 - 2.870 5.629 0.0 0.0840 - 2.880 5.422 0.0 0.0841 - 2.890 5.203 0.0 0.0845 - 2.900 4.978 0.0 0.0851 - 2.910 4.751 0.0 0.0856 - 2.920 4.525 0.0 0.0858 - 2.930 4.305 0.0 0.0857 - 2.940 4.092 0.0 0.0852 - 2.950 3.888 0.0 0.0846 - 2.960 3.693 0.0 0.0841 - 2.970 3.507 0.0 0.0839 - 2.980 3.327 0.0 0.0841 - 2.990 3.152 0.0 0.0846 - 3.000 2.979 0.0 0.0852 - 3.010 2.806 0.0 0.0857 - 3.020 2.632 0.0 0.0858 - 3.030 2.454 0.0 0.0856 - 3.040 2.272 0.0 0.0851 - 3.050 2.084 0.0 0.0845 - 3.060 1.892 0.0 0.0841 - 3.070 1.697 0.0 0.0839 - 3.080 1.500 0.0 0.0842 - 3.090 1.302 0.0 0.0847 - 3.100 1.106 0.0 0.0852 - 3.110 0.913 0.0 0.0856 - 3.120 0.726 0.0 0.0858 - 3.130 0.544 0.0 0.0855 - 3.140 0.369 0.0 0.0851 - 3.150 0.201 0.0 0.0845 - 3.160 0.039 0.0 0.0841 - 3.170 -0.118 0.0 0.0840 - 3.180 -0.271 0.0 0.0842 - 3.190 -0.422 0.0 0.0847 - 3.200 -0.571 0.0 0.0852 - 3.210 -0.719 0.0 0.0856 - 3.220 -0.868 0.0 0.0857 - 3.230 -1.017 0.0 0.0854 - 3.240 -1.167 0.0 0.0849 - 3.250 -1.315 0.0 0.0844 - 3.260 -1.460 0.0 0.0840 - 3.270 -1.601 0.0 0.0840 - 3.280 -1.737 0.0 0.0843 - 3.290 -1.864 0.0 0.0848 - 3.300 -1.981 0.0 0.0853 - 3.310 -2.086 0.0 0.0856 - 3.320 -2.179 0.0 0.0856 - 3.330 -2.260 0.0 0.0853 - 3.340 -2.327 0.0 0.0848 - 3.350 -2.382 0.0 0.0843 - 3.360 -2.426 0.0 0.0840 - 3.370 -2.460 0.0 0.0840 - 3.380 -2.486 0.0 0.0843 - 3.390 -2.505 0.0 0.0848 - 3.400 -2.519 0.0 0.0853 - 3.410 -2.529 0.0 0.0856 - 3.420 -2.536 0.0 0.0856 - 3.430 -2.541 0.0 0.0852 - 3.440 -2.544 0.0 0.0848 - 3.450 -2.546 0.0 0.0843 - 3.460 -2.548 0.0 0.0841 - 3.470 -2.548 0.0 0.0841 - 3.480 -2.548 0.0 0.0845 - 3.490 -2.547 0.0 0.0849 - 3.500 -2.548 0.0 0.0853 - 3.510 -2.550 0.0 0.0855 - 3.520 -2.556 0.0 0.0855 - 3.530 -2.567 0.0 0.0851 - 3.540 -2.585 0.0 0.0847 - 3.550 -2.612 0.0 0.0843 - 3.560 -2.649 0.0 0.0841 - 3.570 -2.697 0.0 0.0842 - 3.580 -2.755 0.0 0.0846 - 3.590 -2.824 0.0 0.0850 - 3.600 -2.900 0.0 0.0854 - 3.610 -2.982 0.0 0.0855 - 3.620 -3.065 0.0 0.0854 - 3.630 -3.143 0.0 0.0851 - 3.640 -3.213 0.0 0.0846 - 3.650 -3.267 0.0 0.0843 - 3.660 -3.301 0.0 0.0842 - 3.670 -3.310 0.0 0.0844 - 3.680 -3.288 0.0 0.0847 - 3.690 -3.234 0.0 0.0851 - 3.700 -3.145 0.0 0.0854 - 3.710 -3.021 0.0 0.0855 - 3.720 -2.865 0.0 0.0853 - 3.730 -2.679 0.0 0.0850 - 3.740 -2.468 0.0 0.0846 - 3.750 -2.238 0.0 0.0843 - 3.760 -1.996 0.0 0.0843 - 3.770 -1.748 0.0 0.0845 - 3.780 -1.501 0.0 0.0848 - 3.790 -1.262 0.0 0.0852 - 3.800 -1.036 0.0 0.0855 - 3.810 -0.828 0.0 0.0855 - 3.820 -0.640 0.0 0.0853 - 3.830 -0.475 0.0 0.0849 - 3.840 -0.334 0.0 0.0845 - 3.850 -0.214 0.0 0.0843 - 3.860 -0.116 0.0 0.0843 - 3.870 -0.038 0.0 0.0846 - 3.880 0.024 0.0 0.0850 - 3.890 0.070 0.0 0.0853 - 3.900 0.103 0.0 0.0855 - 3.910 0.123 0.0 0.0855 - 3.920 0.129 0.0 0.0852 - 3.930 0.122 0.0 0.0848 - 3.940 0.099 0.0 0.0844 - 3.950 0.058 0.0 0.0842 - 3.960 -0.003 0.0 0.0843 - 3.970 -0.088 0.0 0.0846 - 3.980 -0.199 0.0 0.0851 - 3.990 -0.338 0.0 0.0854 - 4.000 -0.504 0.0 0.0856 - 4.010 -0.699 0.0 0.0855 - 4.020 -0.920 0.0 0.0851 - 4.030 -1.165 0.0 0.0847 - 4.040 -1.429 0.0 0.0843 - 4.050 -1.707 0.0 0.0842 - 4.060 -1.993 0.0 0.0843 - 4.070 -2.280 0.0 0.0847 - 4.080 -2.562 0.0 0.0851 - 4.090 -2.833 0.0 0.0855 - 4.100 -3.086 0.0 0.0856 - 4.110 -3.318 0.0 0.0854 - 4.120 -3.525 0.0 0.0851 - 4.130 -3.704 0.0 0.0846 - 4.140 -3.855 0.0 0.0843 - 4.150 -3.977 0.0 0.0842 - 4.160 -4.071 0.0 0.0843 - 4.170 -4.140 0.0 0.0847 - 4.180 -4.186 0.0 0.0851 - 4.190 -4.210 0.0 0.0855 - 4.200 -4.215 0.0 0.0856 - 4.210 -4.203 0.0 0.0854 - 4.220 -4.174 0.0 0.0851 - 4.230 -4.130 0.0 0.0846 - 4.240 -4.071 0.0 0.0843 - 4.250 -3.996 0.0 0.0842 - 4.260 -3.904 0.0 0.0844 - 4.270 -3.794 0.0 0.0847 - 4.280 -3.666 0.0 0.0851 - 4.290 -3.519 0.0 0.0854 - 4.300 -3.353 0.0 0.0855 - 4.310 -3.169 0.0 0.0853 - 4.320 -2.969 0.0 0.0850 - 4.330 -2.755 0.0 0.0846 - 4.340 -2.531 0.0 0.0843 - 4.350 -2.299 0.0 0.0842 - 4.360 -2.064 0.0 0.0844 - 4.370 -1.830 0.0 0.0848 - 4.380 -1.601 0.0 0.0851 - 4.390 -1.380 0.0 0.0854 - 4.400 -1.169 0.0 0.0854 - 4.410 -0.970 0.0 0.0852 - 4.420 -0.783 0.0 0.0849 - 4.430 -0.609 0.0 0.0845 - 4.440 -0.445 0.0 0.0843 - 4.450 -0.289 0.0 0.0843 - 4.460 -0.139 0.0 0.0845 - 4.470 0.008 0.0 0.0849 - 4.480 0.155 0.0 0.0852 - 4.490 0.304 0.0 0.0854 - 4.500 0.457 0.0 0.0854 - 4.510 0.615 0.0 0.0851 - 4.520 0.778 0.0 0.0848 - 4.530 0.944 0.0 0.0844 - 4.540 1.112 0.0 0.0843 - 4.550 1.279 0.0 0.0843 - 4.560 1.443 0.0 0.0845 - 4.570 1.600 0.0 0.0849 - 4.580 1.748 0.0 0.0852 - 4.590 1.883 0.0 0.0854 - 4.600 2.004 0.0 0.0853 - 4.610 2.111 0.0 0.0851 - 4.620 2.203 0.0 0.0847 - 4.630 2.282 0.0 0.0844 - 4.640 2.349 0.0 0.0843 - 4.650 2.408 0.0 0.0843 - 4.660 2.461 0.0 0.0846 - 4.670 2.512 0.0 0.0849 - 4.680 2.565 0.0 0.0852 - 4.690 2.621 0.0 0.0854 - 4.700 2.685 0.0 0.0853 - 4.710 2.756 0.0 0.0850 - 4.720 2.835 0.0 0.0847 - 4.730 2.921 0.0 0.0844 - 4.740 3.012 0.0 0.0843 - 4.750 3.105 0.0 0.0844 - 4.760 3.197 0.0 0.0847 - 4.770 3.283 0.0 0.0850 - 4.780 3.361 0.0 0.0852 - 4.790 3.425 0.0 0.0853 - 4.800 3.472 0.0 0.0852 - 4.810 3.501 0.0 0.0850 - 4.820 3.509 0.0 0.0847 - 4.830 3.496 0.0 0.0844 - 4.840 3.462 0.0 0.0844 - 4.850 3.409 0.0 0.0845 - 4.860 3.338 0.0 0.0848 - 4.870 3.253 0.0 0.0851 - 4.880 3.156 0.0 0.0853 - 4.890 3.050 0.0 0.0853 - 4.900 2.939 0.0 0.0852 - 4.910 2.823 0.0 0.0849 - 4.920 2.706 0.0 0.0846 - 4.930 2.588 0.0 0.0845 - 4.940 2.471 0.0 0.0845 - 4.950 2.353 0.0 0.0847 - 4.960 2.234 0.0 0.0849 - 4.970 2.115 0.0 0.0852 - 4.980 1.993 0.0 0.0854 - 4.990 1.868 0.0 0.0853 - 5.000 1.740 0.0 0.0851 - 5.010 1.608 0.0 0.0848 - 5.020 1.474 0.0 0.0845 - 5.030 1.337 0.0 0.0844 - 5.040 1.200 0.0 0.0845 - 5.050 1.064 0.0 0.0847 - 5.060 0.932 0.0 0.0850 - 5.070 0.805 0.0 0.0853 - 5.080 0.686 0.0 0.0854 - 5.090 0.578 0.0 0.0853 - 5.100 0.480 0.0 0.0851 - 5.110 0.396 0.0 0.0848 - 5.120 0.324 0.0 0.0845 - 5.130 0.264 0.0 0.0844 - 5.140 0.216 0.0 0.0845 - 5.150 0.179 0.0 0.0847 - 5.160 0.151 0.0 0.0851 - 5.170 0.129 0.0 0.0853 - 5.180 0.113 0.0 0.0854 - 5.190 0.100 0.0 0.0853 - 5.200 0.089 0.0 0.0850 - 5.210 0.080 0.0 0.0847 - 5.220 0.071 0.0 0.0845 - 5.230 0.064 0.0 0.0844 - 5.240 0.058 0.0 0.0845 - 5.250 0.055 0.0 0.0848 - 5.260 0.056 0.0 0.0851 - 5.270 0.061 0.0 0.0853 - 5.280 0.073 0.0 0.0854 - 5.290 0.091 0.0 0.0852 - 5.300 0.118 0.0 0.0850 - 5.310 0.152 0.0 0.0846 - 5.320 0.195 0.0 0.0844 - 5.330 0.244 0.0 0.0844 - 5.340 0.299 0.0 0.0845 - 5.350 0.360 0.0 0.0848 - 5.360 0.424 0.0 0.0851 - 5.370 0.490 0.0 0.0853 - 5.380 0.556 0.0 0.0854 - 5.390 0.623 0.0 0.0852 - 5.400 0.688 0.0 0.0849 - 5.410 0.752 0.0 0.0846 - 5.420 0.814 0.0 0.0844 - 5.430 0.875 0.0 0.0843 - 5.440 0.936 0.0 0.0845 - 5.450 0.997 0.0 0.0848 - 5.460 1.060 0.0 0.0851 - 5.470 1.124 0.0 0.0853 - 5.480 1.192 0.0 0.0853 - 5.490 1.263 0.0 0.0851 - 5.500 1.337 0.0 0.0848 - 5.510 1.414 0.0 0.0845 - 5.520 1.494 0.0 0.0843 - 5.530 1.575 0.0 0.0844 - 5.540 1.656 0.0 0.0846 - 5.550 1.737 0.0 0.0849 - 5.560 1.815 0.0 0.0852 - 5.570 1.890 0.0 0.0854 - 5.580 1.961 0.0 0.0853 - 5.590 2.027 0.0 0.0851 - 5.600 2.088 0.0 0.0848 - 5.610 2.144 0.0 0.0845 - 5.620 2.194 0.0 0.0844 - 5.630 2.241 0.0 0.0844 - 5.640 2.283 0.0 0.0846 - 5.650 2.321 0.0 0.0849 - 5.660 2.355 0.0 0.0852 - 5.670 2.384 0.0 0.0853 - 5.680 2.409 0.0 0.0853 - 5.690 2.427 0.0 0.0851 - 5.700 2.438 0.0 0.0848 - 5.710 2.438 0.0 0.0845 - 5.720 2.427 0.0 0.0844 - 5.730 2.402 0.0 0.0844 - 5.740 2.361 0.0 0.0847 - 5.750 2.303 0.0 0.0850 - 5.760 2.225 0.0 0.0852 - 5.770 2.129 0.0 0.0853 - 5.780 2.014 0.0 0.0852 - 5.790 1.882 0.0 0.0850 - 5.800 1.734 0.0 0.0847 - 5.810 1.574 0.0 0.0844 - 5.820 1.405 0.0 0.0843 - 5.830 1.230 0.0 0.0844 - 5.840 1.054 0.0 0.0847 - 5.850 0.880 0.0 0.0850 - 5.860 0.712 0.0 0.0852 - 5.870 0.552 0.0 0.0853 - 5.880 0.402 0.0 0.0852 - 5.890 0.263 0.0 0.0849 - 5.900 0.135 0.0 0.0847 - 5.910 0.017 0.0 0.0844 - 5.920 -0.093 0.0 0.0844 - 5.930 -0.197 0.0 0.0845 - 5.940 -0.298 0.0 0.0848 - 5.950 -0.399 0.0 0.0851 - 5.960 -0.501 0.0 0.0853 - 5.970 -0.608 0.0 0.0853 - 5.980 -0.720 0.0 0.0852 - 5.990 -0.839 0.0 0.0849 - 6.000 -0.964 0.0 0.0846 - 6.010 -1.095 0.0 0.0844 - 6.020 -1.229 0.0 0.0844 - 6.030 -1.365 0.0 0.0846 - 6.040 -1.501 0.0 0.0848 - 6.050 -1.632 0.0 0.0851 - 6.060 -1.758 0.0 0.0853 - 6.070 -1.876 0.0 0.0853 - 6.080 -1.984 0.0 0.0852 - 6.090 -2.082 0.0 0.0849 - 6.100 -2.171 0.0 0.0846 - 6.110 -2.250 0.0 0.0845 - 6.120 -2.322 0.0 0.0845 - 6.130 -2.389 0.0 0.0846 - 6.140 -2.453 0.0 0.0849 - 6.150 -2.517 0.0 0.0851 - 6.160 -2.584 0.0 0.0853 - 6.170 -2.655 0.0 0.0853 - 6.180 -2.733 0.0 0.0851 - 6.190 -2.816 0.0 0.0849 - 6.200 -2.907 0.0 0.0846 - 6.210 -3.003 0.0 0.0845 - 6.220 -3.103 0.0 0.0845 - 6.230 -3.205 0.0 0.0847 - 6.240 -3.307 0.0 0.0849 - 6.250 -3.405 0.0 0.0852 - 6.260 -3.497 0.0 0.0853 - 6.270 -3.582 0.0 0.0852 - 6.280 -3.657 0.0 0.0850 - 6.290 -3.721 0.0 0.0848 - 6.300 -3.775 0.0 0.0846 - 6.310 -3.818 0.0 0.0845 - 6.320 -3.853 0.0 0.0846 - 6.330 -3.880 0.0 0.0848 - 6.340 -3.902 0.0 0.0851 - 6.350 -3.920 0.0 0.0853 - 6.360 -3.935 0.0 0.0853 - 6.370 -3.950 0.0 0.0852 - 6.380 -3.964 0.0 0.0850 - 6.390 -3.977 0.0 0.0847 - 6.400 -3.987 0.0 0.0845 - 6.410 -3.993 0.0 0.0845 - 6.420 -3.993 0.0 0.0846 - 6.430 -3.984 0.0 0.0848 - 6.440 -3.961 0.0 0.0850 - 6.450 -3.924 0.0 0.0852 - 6.460 -3.869 0.0 0.0853 - 6.470 -3.796 0.0 0.0851 - 6.480 -3.703 0.0 0.0849 - 6.490 -3.591 0.0 0.0847 - 6.500 -3.462 0.0 0.0845 - 6.510 -3.320 0.0 0.0845 - 6.520 -3.168 0.0 0.0846 - 6.530 -3.011 0.0 0.0849 - 6.540 -2.854 0.0 0.0851 - 6.550 -2.703 0.0 0.0853 - 6.560 -2.563 0.0 0.0853 - 6.570 -2.437 0.0 0.0851 - 6.580 -2.329 0.0 0.0849 - 6.590 -2.240 0.0 0.0846 - 6.600 -2.172 0.0 0.0844 - 6.610 -2.121 0.0 0.0844 - 6.620 -2.087 0.0 0.0846 - 6.630 -2.064 0.0 0.0848 - 6.640 -2.048 0.0 0.0851 - 6.650 -2.034 0.0 0.0853 - 6.660 -2.016 0.0 0.0852 - 6.670 -1.987 0.0 0.0851 - 6.680 -1.945 0.0 0.0848 - 6.690 -1.884 0.0 0.0846 - 6.700 -1.803 0.0 0.0844 - 6.710 -1.701 0.0 0.0844 - 6.720 -1.579 0.0 0.0846 - 6.730 -1.439 0.0 0.0848 - 6.740 -1.285 0.0 0.0851 - 6.750 -1.121 0.0 0.0852 - 6.760 -0.952 0.0 0.0852 - 6.770 -0.784 0.0 0.0850 - 6.780 -0.622 0.0 0.0848 - 6.790 -0.471 0.0 0.0846 - 6.800 -0.335 0.0 0.0845 - 6.810 -0.216 0.0 0.0845 - 6.820 -0.115 0.0 0.0847 - 6.830 -0.031 0.0 0.0849 - 6.840 0.035 0.0 0.0851 - 6.850 0.089 0.0 0.0852 - 6.860 0.133 0.0 0.0851 - 6.870 0.172 0.0 0.0850 - 6.880 0.211 0.0 0.0847 - 6.890 0.254 0.0 0.0845 - 6.900 0.305 0.0 0.0845 - 6.910 0.367 0.0 0.0845 - 6.920 0.444 0.0 0.0847 - 6.930 0.535 0.0 0.0850 - 6.940 0.642 0.0 0.0852 - 6.950 0.761 0.0 0.0852 - 6.960 0.892 0.0 0.0851 - 6.970 1.031 0.0 0.0849 - 6.980 1.174 0.0 0.0847 - 6.990 1.317 0.0 0.0845 - 7.000 1.457 0.0 0.0845 - 7.010 1.589 0.0 0.0846 - 7.020 1.710 0.0 0.0848 - 7.030 1.819 0.0 0.0850 - 7.040 1.913 0.0 0.0851 - 7.050 1.991 0.0 0.0852 - 7.060 2.055 0.0 0.0851 - 7.070 2.105 0.0 0.0849 - 7.080 2.142 0.0 0.0846 - 7.090 2.169 0.0 0.0845 - 7.100 2.188 0.0 0.0845 - 7.110 2.202 0.0 0.0846 - 7.120 2.212 0.0 0.0848 - 7.130 2.221 0.0 0.0851 - 7.140 2.229 0.0 0.0852 - 7.150 2.239 0.0 0.0852 - 7.160 2.250 0.0 0.0851 - 7.170 2.263 0.0 0.0849 - 7.180 2.278 0.0 0.0847 - 7.190 2.293 0.0 0.0845 - 7.200 2.309 0.0 0.0845 - 7.210 2.325 0.0 0.0847 - 7.220 2.341 0.0 0.0849 - 7.230 2.356 0.0 0.0851 - 7.240 2.371 0.0 0.0852 - 7.250 2.386 0.0 0.0852 - 7.260 2.402 0.0 0.0851 - 7.270 2.419 0.0 0.0848 - 7.280 2.440 0.0 0.0847 - 7.290 2.465 0.0 0.0845 - 7.300 2.495 0.0 0.0846 - 7.310 2.532 0.0 0.0847 - 7.320 2.576 0.0 0.0850 - 7.330 2.626 0.0 0.0851 - 7.340 2.683 0.0 0.0852 - 7.350 2.746 0.0 0.0852 - 7.360 2.814 0.0 0.0850 - 7.370 2.885 0.0 0.0848 - 7.380 2.957 0.0 0.0847 - 7.390 3.029 0.0 0.0846 - 7.400 3.097 0.0 0.0847 - 7.410 3.160 0.0 0.0848 - 7.420 3.215 0.0 0.0850 - 7.430 3.262 0.0 0.0852 - 7.440 3.300 0.0 0.0853 - 7.450 3.326 0.0 0.0852 - 7.460 3.343 0.0 0.0850 - 7.470 3.348 0.0 0.0848 - 7.480 3.344 0.0 0.0846 - 7.490 3.331 0.0 0.0846 - 7.500 3.311 0.0 0.0847 - 7.510 3.284 0.0 0.0848 - 7.520 3.253 0.0 0.0851 - 7.530 3.217 0.0 0.0852 - 7.540 3.179 0.0 0.0852 - 7.550 3.138 0.0 0.0851 - 7.560 3.095 0.0 0.0849 - 7.570 3.050 0.0 0.0847 - 7.580 3.002 0.0 0.0846 - 7.590 2.951 0.0 0.0845 - 7.600 2.895 0.0 0.0847 - 7.610 2.833 0.0 0.0849 - 7.620 2.765 0.0 0.0851 - 7.630 2.689 0.0 0.0852 - 7.640 2.604 0.0 0.0852 - 7.650 2.509 0.0 0.0851 - 7.660 2.406 0.0 0.0849 - 7.670 2.293 0.0 0.0846 - 7.680 2.171 0.0 0.0845 - 7.690 2.041 0.0 0.0845 - 7.700 1.905 0.0 0.0846 - 7.710 1.764 0.0 0.0849 - 7.720 1.619 0.0 0.0851 - 7.730 1.472 0.0 0.0852 - 7.740 1.326 0.0 0.0852 - 7.750 1.180 0.0 0.0850 - 7.760 1.036 0.0 0.0848 - 7.770 0.896 0.0 0.0846 - 7.780 0.760 0.0 0.0845 - 7.790 0.628 0.0 0.0845 - 7.800 0.499 0.0 0.0847 - 7.810 0.375 0.0 0.0849 - 7.820 0.254 0.0 0.0851 - 7.830 0.137 0.0 0.0852 - 7.840 0.021 0.0 0.0852 - 7.850 -0.092 0.0 0.0850 - 7.860 -0.203 0.0 0.0848 - 7.870 -0.312 0.0 0.0846 - 7.880 -0.418 0.0 0.0844 - 7.890 -0.521 0.0 0.0845 - 7.900 -0.621 0.0 0.0847 - 7.910 -0.716 0.0 0.0849 - 7.920 -0.804 0.0 0.0851 - 7.930 -0.886 0.0 0.0852 - 7.940 -0.958 0.0 0.0852 - 7.950 -1.022 0.0 0.0850 - 7.960 -1.075 0.0 0.0847 - 7.970 -1.118 0.0 0.0845 - 7.980 -1.151 0.0 0.0845 - 7.990 -1.174 0.0 0.0845 - 8.000 -1.187 0.0 0.0847 - 8.010 -1.193 0.0 0.0849 - 8.020 -1.193 0.0 0.0851 - 8.030 -1.189 0.0 0.0852 - 8.040 -1.181 0.0 0.0851 - 8.050 -1.174 0.0 0.0850 - 8.060 -1.166 0.0 0.0847 - 8.070 -1.162 0.0 0.0846 - 8.080 -1.160 0.0 0.0845 - 8.090 -1.161 0.0 0.0846 - 8.100 -1.166 0.0 0.0847 - 8.110 -1.174 0.0 0.0850 - 8.120 -1.183 0.0 0.0851 - 8.130 -1.193 0.0 0.0852 - 8.140 -1.202 0.0 0.0851 - 8.150 -1.207 0.0 0.0849 - 8.160 -1.207 0.0 0.0847 - 8.170 -1.201 0.0 0.0845 - 8.180 -1.186 0.0 0.0845 - 8.190 -1.162 0.0 0.0846 - 8.200 -1.128 0.0 0.0848 - 8.210 -1.084 0.0 0.0850 - 8.220 -1.032 0.0 0.0851 - 8.230 -0.971 0.0 0.0852 - 8.240 -0.903 0.0 0.0851 - 8.250 -0.832 0.0 0.0849 - 8.260 -0.758 0.0 0.0847 - 8.270 -0.686 0.0 0.0846 - 8.280 -0.617 0.0 0.0846 - 8.290 -0.555 0.0 0.0847 - 8.300 -0.502 0.0 0.0849 - 8.310 -0.460 0.0 0.0850 - 8.320 -0.431 0.0 0.0852 - 8.330 -0.417 0.0 0.0852 - 8.340 -0.419 0.0 0.0851 - 8.350 -0.438 0.0 0.0849 - 8.360 -0.472 0.0 0.0847 - 8.370 -0.523 0.0 0.0846 - 8.380 -0.588 0.0 0.0846 - 8.390 -0.668 0.0 0.0847 - 8.400 -0.760 0.0 0.0849 - 8.410 -0.862 0.0 0.0851 - 8.420 -0.972 0.0 0.0852 - 8.430 -1.088 0.0 0.0852 - 8.440 -1.207 0.0 0.0850 - 8.450 -1.327 0.0 0.0849 - 8.460 -1.445 0.0 0.0847 - 8.470 -1.558 0.0 0.0846 - 8.480 -1.664 0.0 0.0846 - 8.490 -1.761 0.0 0.0848 - 8.500 -1.846 0.0 0.0849 - 8.510 -1.917 0.0 0.0851 - 8.520 -1.973 0.0 0.0852 - 8.530 -2.012 0.0 0.0851 - 8.540 -2.035 0.0 0.0850 - 8.550 -2.040 0.0 0.0848 - 8.560 -2.030 0.0 0.0847 - 8.570 -2.004 0.0 0.0846 - 8.580 -1.964 0.0 0.0846 - 8.590 -1.914 0.0 0.0848 - 8.600 -1.854 0.0 0.0850 - 8.610 -1.790 0.0 0.0851 - 8.620 -1.722 0.0 0.0852 - 8.630 -1.656 0.0 0.0851 - 8.640 -1.592 0.0 0.0850 - 8.650 -1.535 0.0 0.0848 - 8.660 -1.486 0.0 0.0847 - 8.670 -1.447 0.0 0.0846 - 8.680 -1.418 0.0 0.0847 - 8.690 -1.401 0.0 0.0848 - 8.700 -1.394 0.0 0.0850 - 8.710 -1.397 0.0 0.0851 - 8.720 -1.409 0.0 0.0851 - 8.730 -1.427 0.0 0.0850 - 8.740 -1.450 0.0 0.0849 - 8.750 -1.476 0.0 0.0847 - 8.760 -1.504 0.0 0.0846 - 8.770 -1.533 0.0 0.0846 - 8.780 -1.560 0.0 0.0847 - 8.790 -1.586 0.0 0.0849 - 8.800 -1.611 0.0 0.0850 - 8.810 -1.636 0.0 0.0851 - 8.820 -1.661 0.0 0.0851 - 8.830 -1.688 0.0 0.0850 - 8.840 -1.718 0.0 0.0848 - 8.850 -1.752 0.0 0.0847 - 8.860 -1.793 0.0 0.0846 - 8.870 -1.840 0.0 0.0846 - 8.880 -1.896 0.0 0.0847 - 8.890 -1.958 0.0 0.0849 - 8.900 -2.029 0.0 0.0851 - 8.910 -2.105 0.0 0.0851 - 8.920 -2.186 0.0 0.0851 - 8.930 -2.269 0.0 0.0850 - 8.940 -2.353 0.0 0.0848 - 8.950 -2.435 0.0 0.0846 - 8.960 -2.513 0.0 0.0845 - 8.970 -2.583 0.0 0.0846 - 8.980 -2.644 0.0 0.0847 - 8.990 -2.694 0.0 0.0849 - 9.000 -2.732 0.0 0.0851 - 9.010 -2.756 0.0 0.0851 - 9.020 -2.767 0.0 0.0851 - 9.030 -2.764 0.0 0.0849 - 9.040 -2.748 0.0 0.0847 - 9.050 -2.719 0.0 0.0846 - 9.060 -2.679 0.0 0.0845 - 9.070 -2.629 0.0 0.0846 - 9.080 -2.569 0.0 0.0848 - 9.090 -2.501 0.0 0.0849 - 9.100 -2.427 0.0 0.0851 - 9.110 -2.346 0.0 0.0851 - 9.120 -2.261 0.0 0.0851 - 9.130 -2.172 0.0 0.0849 - 9.140 -2.080 0.0 0.0847 - 9.150 -1.987 0.0 0.0846 - 9.160 -1.892 0.0 0.0845 - 9.170 -1.798 0.0 0.0846 - 9.180 -1.706 0.0 0.0848 - 9.190 -1.617 0.0 0.0850 - 9.200 -1.531 0.0 0.0851 - 9.210 -1.450 0.0 0.0852 - 9.220 -1.375 0.0 0.0851 - 9.230 -1.306 0.0 0.0849 - 9.240 -1.242 0.0 0.0847 - 9.250 -1.183 0.0 0.0846 - 9.260 -1.128 0.0 0.0845 - 9.270 -1.074 0.0 0.0846 - 9.280 -1.019 0.0 0.0848 - 9.290 -0.960 0.0 0.0850 - 9.300 -0.893 0.0 0.0851 - 9.310 -0.815 0.0 0.0851 - 9.320 -0.722 0.0 0.0851 - 9.330 -0.611 0.0 0.0849 - 9.340 -0.479 0.0 0.0847 - 9.350 -0.325 0.0 0.0846 - 9.360 -0.146 0.0 0.0846 - 9.370 0.057 0.0 0.0847 - 9.380 0.282 0.0 0.0848 - 9.390 0.529 0.0 0.0850 - 9.400 0.793 0.0 0.0851 - 9.410 1.071 0.0 0.0851 - 9.420 1.359 0.0 0.0850 - 9.430 1.651 0.0 0.0849 - 9.440 1.945 0.0 0.0847 - 9.450 2.235 0.0 0.0846 - 9.460 2.517 0.0 0.0846 - 9.470 2.790 0.0 0.0847 - 9.480 3.052 0.0 0.0849 - 9.490 3.301 0.0 0.0851 - 9.500 3.537 0.0 0.0852 - 9.510 3.763 0.0 0.0851 - 9.520 3.978 0.0 0.0850 - 9.530 4.186 0.0 0.0849 - 9.540 4.387 0.0 0.0847 - 9.550 4.584 0.0 0.0846 - 9.560 4.777 0.0 0.0846 - 9.570 4.966 0.0 0.0847 - 9.580 5.150 0.0 0.0849 - 9.590 5.328 0.0 0.0851 - 9.600 5.497 0.0 0.0851 - 9.610 5.652 0.0 0.0851 - 9.620 5.790 0.0 0.0850 - 9.630 5.906 0.0 0.0848 - 9.640 5.996 0.0 0.0847 - 9.650 6.055 0.0 0.0846 - 9.660 6.080 0.0 0.0847 - 9.670 6.068 0.0 0.0848 - 9.680 6.020 0.0 0.0850 - 9.690 5.936 0.0 0.0851 - 9.700 5.818 0.0 0.0851 - 9.710 5.669 0.0 0.0851 - 9.720 5.494 0.0 0.0849 - 9.730 5.299 0.0 0.0848 - 9.740 5.089 0.0 0.0847 - 9.750 4.872 0.0 0.0846 - 9.760 4.652 0.0 0.0847 - 9.770 4.435 0.0 0.0848 - 9.780 4.225 0.0 0.0850 - 9.790 4.023 0.0 0.0851 - 9.800 3.832 0.0 0.0851 - 9.810 3.651 0.0 0.0851 - 9.820 3.478 0.0 0.0849 - 9.830 3.310 0.0 0.0848 - 9.840 3.145 0.0 0.0847 - 9.850 2.977 0.0 0.0846 - 9.860 2.803 0.0 0.0847 - 9.870 2.620 0.0 0.0849 - 9.880 2.427 0.0 0.0850 - 9.890 2.220 0.0 0.0851 - 9.900 2.001 0.0 0.0851 - 9.910 1.772 0.0 0.0850 - 9.920 1.536 0.0 0.0848 - 9.930 1.296 0.0 0.0847 - 9.940 1.059 0.0 0.0846 - 9.950 0.830 0.0 0.0846 - 9.960 0.615 0.0 0.0847 - 9.970 0.419 0.0 0.0849 - 9.980 0.248 0.0 0.0850 - 9.990 0.105 0.0 0.0851 - 10.000 -0.008 0.0 0.0851 - 10.010 -0.090 0.0 0.0850 - 10.020 -0.143 0.0 0.0848 - 10.030 -0.168 0.0 0.0847 - 10.040 -0.170 0.0 0.0846 - 10.050 -0.154 0.0 0.0846 - 10.060 -0.124 0.0 0.0848 - 10.070 -0.087 0.0 0.0849 - 10.080 -0.047 0.0 0.0851 - 10.090 -0.009 0.0 0.0851 - 10.100 0.022 0.0 0.0851 - 10.110 0.046 0.0 0.0849 - 10.120 0.062 0.0 0.0848 - 10.130 0.069 0.0 0.0846 - 10.140 0.070 0.0 0.0846 - 10.150 0.068 0.0 0.0846 - 10.160 0.067 0.0 0.0848 - 10.170 0.071 0.0 0.0849 - 10.180 0.083 0.0 0.0851 - 10.190 0.108 0.0 0.0851 - 10.200 0.148 0.0 0.0851 - 10.210 0.204 0.0 0.0849 - 10.220 0.277 0.0 0.0848 - 10.230 0.366 0.0 0.0846 - 10.240 0.468 0.0 0.0846 - 10.250 0.578 0.0 0.0846 - 10.260 0.691 0.0 0.0848 - 10.270 0.803 0.0 0.0850 - 10.280 0.905 0.0 0.0851 - 10.290 0.991 0.0 0.0851 - 10.300 1.056 0.0 0.0850 - 10.310 1.094 0.0 0.0849 - 10.320 1.101 0.0 0.0847 - 10.330 1.073 0.0 0.0846 - 10.340 1.008 0.0 0.0846 - 10.350 0.907 0.0 0.0846 - 10.360 0.770 0.0 0.0848 - 10.370 0.599 0.0 0.0850 - 10.380 0.399 0.0 0.0851 - 10.390 0.173 0.0 0.0851 - 10.400 -0.074 0.0 0.0850 - 10.410 -0.338 0.0 0.0849 - 10.420 -0.612 0.0 0.0847 - 10.430 -0.892 0.0 0.0846 - 10.440 -1.174 0.0 0.0846 - 10.450 -1.454 0.0 0.0847 - 10.460 -1.729 0.0 0.0848 - 10.470 -1.997 0.0 0.0850 - 10.480 -2.257 0.0 0.0851 - 10.490 -2.506 0.0 0.0851 - 10.500 -2.746 0.0 0.0850 - 10.510 -2.977 0.0 0.0848 - 10.520 -3.198 0.0 0.0847 - 10.530 -3.410 0.0 0.0846 - 10.540 -3.614 0.0 0.0846 - 10.550 -3.811 0.0 0.0847 - 10.560 -4.002 0.0 0.0849 - 10.570 -4.186 0.0 0.0850 - 10.580 -4.363 0.0 0.0851 - 10.590 -4.533 0.0 0.0851 - 10.600 -4.696 0.0 0.0850 - 10.610 -4.850 0.0 0.0848 - 10.620 -4.995 0.0 0.0847 - 10.630 -5.128 0.0 0.0846 - 10.640 -5.247 0.0 0.0846 - 10.650 -5.351 0.0 0.0847 - 10.660 -5.438 0.0 0.0849 - 10.670 -5.504 0.0 0.0850 - 10.680 -5.549 0.0 0.0851 - 10.690 -5.570 0.0 0.0851 - 10.700 -5.565 0.0 0.0850 - 10.710 -5.533 0.0 0.0848 - 10.720 -5.473 0.0 0.0847 - 10.730 -5.385 0.0 0.0847 - 10.740 -5.268 0.0 0.0847 - 10.750 -5.123 0.0 0.0848 - 10.760 -4.952 0.0 0.0849 - 10.770 -4.756 0.0 0.0851 - 10.780 -4.538 0.0 0.0851 - 10.790 -4.300 0.0 0.0851 - 10.800 -4.045 0.0 0.0850 - 10.810 -3.776 0.0 0.0848 - 10.820 -3.496 0.0 0.0847 - 10.830 -3.208 0.0 0.0847 - 10.840 -2.914 0.0 0.0847 - 10.850 -2.615 0.0 0.0848 - 10.860 -2.314 0.0 0.0850 - 10.870 -2.010 0.0 0.0851 - 10.880 -1.703 0.0 0.0851 - 10.890 -1.394 0.0 0.0851 - 10.900 -1.081 0.0 0.0849 - 10.910 -0.764 0.0 0.0848 - 10.920 -0.440 0.0 0.0847 - 10.930 -0.110 0.0 0.0846 - 10.940 0.227 0.0 0.0847 - 10.950 0.571 0.0 0.0848 - 10.960 0.921 0.0 0.0850 - 10.970 1.277 0.0 0.0851 - 10.980 1.634 0.0 0.0851 - 10.990 1.991 0.0 0.0851 - 11.000 2.344 0.0 0.0849 - 11.010 2.687 0.0 0.0848 - 11.020 3.016 0.0 0.0847 - 11.030 3.327 0.0 0.0847 - 11.040 3.613 0.0 0.0847 - 11.050 3.869 0.0 0.0849 - 11.060 4.093 0.0 0.0850 - 11.070 4.280 0.0 0.0851 - 11.080 4.427 0.0 0.0851 - 11.090 4.533 0.0 0.0850 - 11.100 4.597 0.0 0.0849 - 11.110 4.618 0.0 0.0848 - 11.120 4.597 0.0 0.0847 - 11.130 4.535 0.0 0.0847 - 11.140 4.435 0.0 0.0847 - 11.150 4.299 0.0 0.0849 - 11.160 4.128 0.0 0.0850 - 11.170 3.926 0.0 0.0851 - 11.180 3.695 0.0 0.0851 - 11.190 3.437 0.0 0.0850 - 11.200 3.155 0.0 0.0848 - 11.210 2.850 0.0 0.0847 - 11.220 2.524 0.0 0.0847 - 11.230 2.179 0.0 0.0847 - 11.240 1.816 0.0 0.0848 - 11.250 1.439 0.0 0.0849 - 11.260 1.048 0.0 0.0850 - 11.270 0.647 0.0 0.0850 - 11.280 0.238 0.0 0.0850 - 11.290 -0.177 0.0 0.0849 - 11.300 -0.593 0.0 0.0848 - 11.310 -1.007 0.0 0.0847 - 11.320 -1.416 0.0 0.0846 - 11.330 -1.818 0.0 0.0847 - 11.340 -2.207 0.0 0.0848 - 11.350 -2.583 0.0 0.0849 - 11.360 -2.941 0.0 0.0850 - 11.370 -3.280 0.0 0.0851 - 11.380 -3.597 0.0 0.0850 - 11.390 -3.893 0.0 0.0849 - 11.400 -4.164 0.0 0.0847 - 11.410 -4.411 0.0 0.0846 - 11.420 -4.633 0.0 0.0846 - 11.430 -4.830 0.0 0.0847 - 11.440 -5.000 0.0 0.0848 - 11.450 -5.144 0.0 0.0849 - 11.460 -5.260 0.0 0.0850 - 11.470 -5.347 0.0 0.0850 - 11.480 -5.405 0.0 0.0850 - 11.490 -5.433 0.0 0.0849 - 11.500 -5.429 0.0 0.0847 - 11.510 -5.394 0.0 0.0847 - 11.520 -5.326 0.0 0.0847 - 11.530 -5.225 0.0 0.0847 - 11.540 -5.093 0.0 0.0848 - 11.550 -4.930 0.0 0.0850 - 11.560 -4.739 0.0 0.0850 - 11.570 -4.521 0.0 0.0850 - 11.580 -4.280 0.0 0.0850 - 11.590 -4.019 0.0 0.0848 - 11.600 -3.741 0.0 0.0847 - 11.610 -3.450 0.0 0.0846 - 11.620 -3.149 0.0 0.0847 - 11.630 -2.842 0.0 0.0847 - 11.640 -2.529 0.0 0.0849 - 11.650 -2.214 0.0 0.0850 - 11.660 -1.898 0.0 0.0851 - 11.670 -1.580 0.0 0.0851 - 11.680 -1.260 0.0 0.0850 - 11.690 -0.939 0.0 0.0848 - 11.700 -0.614 0.0 0.0847 - 11.710 -0.286 0.0 0.0846 - 11.720 0.046 0.0 0.0847 - 11.730 0.383 0.0 0.0848 - 11.740 0.724 0.0 0.0849 - 11.750 1.067 0.0 0.0850 - 11.760 1.411 0.0 0.0851 - 11.770 1.751 0.0 0.0851 - 11.780 2.085 0.0 0.0850 - 11.790 2.409 0.0 0.0848 - 11.800 2.717 0.0 0.0847 - 11.810 3.004 0.0 0.0847 - 11.820 3.268 0.0 0.0847 - 11.830 3.503 0.0 0.0848 - 11.840 3.707 0.0 0.0849 - 11.850 3.878 0.0 0.0850 - 11.860 4.017 0.0 0.0851 - 11.870 4.123 0.0 0.0850 - 11.880 4.199 0.0 0.0849 - 11.890 4.248 0.0 0.0848 - 11.900 4.273 0.0 0.0847 - 11.910 4.280 0.0 0.0846 - 11.920 4.273 0.0 0.0847 - 11.930 4.256 0.0 0.0848 - 11.940 4.233 0.0 0.0850 - 11.950 4.208 0.0 0.0851 - 11.960 4.183 0.0 0.0851 - 11.970 4.157 0.0 0.0851 - 11.980 4.133 0.0 0.0849 - 11.990 4.107 0.0 0.0848 - 12.000 4.079 0.0 0.0847 - 12.010 4.046 0.0 0.0847 - 12.020 4.006 0.0 0.0847 - 12.030 3.955 0.0 0.0848 - 12.040 3.892 0.0 0.0850 - 12.050 3.816 0.0 0.0851 - 12.060 3.725 0.0 0.0851 - 12.070 3.621 0.0 0.0850 - 12.080 3.506 0.0 0.0849 - 12.090 3.383 0.0 0.0848 - 12.100 3.254 0.0 0.0847 - 12.110 3.126 0.0 0.0847 - 12.120 3.002 0.0 0.0848 - 12.130 2.886 0.0 0.0849 - 12.140 2.783 0.0 0.0850 - 12.150 2.696 0.0 0.0851 - 12.160 2.628 0.0 0.0851 - 12.170 2.578 0.0 0.0850 - 12.180 2.548 0.0 0.0849 - 12.190 2.536 0.0 0.0848 - 12.200 2.539 0.0 0.0847 - 12.210 2.554 0.0 0.0847 - 12.220 2.577 0.0 0.0848 - 12.230 2.604 0.0 0.0849 - 12.240 2.631 0.0 0.0850 - 12.250 2.656 0.0 0.0851 - 12.260 2.675 0.0 0.0850 - 12.270 2.687 0.0 0.0850 - 12.280 2.691 0.0 0.0848 - 12.290 2.689 0.0 0.0847 - 12.300 2.681 0.0 0.0847 - 12.310 2.671 0.0 0.0847 - 12.320 2.659 0.0 0.0848 - 12.330 2.651 0.0 0.0849 - 12.340 2.647 0.0 0.0850 - 12.350 2.651 0.0 0.0850 - 12.360 2.663 0.0 0.0850 - 12.370 2.684 0.0 0.0849 - 12.380 2.712 0.0 0.0848 - 12.390 2.747 0.0 0.0847 - 12.400 2.784 0.0 0.0846 - 12.410 2.820 0.0 0.0847 - 12.420 2.850 0.0 0.0848 - 12.430 2.870 0.0 0.0849 - 12.440 2.876 0.0 0.0850 - 12.450 2.862 0.0 0.0850 - 12.460 2.827 0.0 0.0850 - 12.470 2.768 0.0 0.0849 - 12.480 2.683 0.0 0.0847 - 12.490 2.574 0.0 0.0846 - 12.500 2.441 0.0 0.0846 - 12.510 2.287 0.0 0.0847 - 12.520 2.116 0.0 0.0848 - 12.530 1.931 0.0 0.0849 - 12.540 1.736 0.0 0.0850 - 12.550 1.536 0.0 0.0850 - 12.560 1.334 0.0 0.0850 - 12.570 1.133 0.0 0.0848 - 12.580 0.936 0.0 0.0847 - 12.590 0.743 0.0 0.0846 - 12.600 0.556 0.0 0.0846 - 12.610 0.373 0.0 0.0847 - 12.620 0.195 0.0 0.0849 - 12.630 0.019 0.0 0.0850 - 12.640 -0.156 0.0 0.0850 - 12.650 -0.333 0.0 0.0850 - 12.660 -0.511 0.0 0.0849 - 12.670 -0.693 0.0 0.0848 - 12.680 -0.879 0.0 0.0847 - 12.690 -1.067 0.0 0.0846 - 12.700 -1.257 0.0 0.0846 - 12.710 -1.448 0.0 0.0847 - 12.720 -1.637 0.0 0.0849 - 12.730 -1.820 0.0 0.0850 - 12.740 -1.997 0.0 0.0851 - 12.750 -2.164 0.0 0.0851 - 12.760 -2.319 0.0 0.0850 - 12.770 -2.460 0.0 0.0848 - 12.780 -2.586 0.0 0.0847 - 12.790 -2.697 0.0 0.0846 - 12.800 -2.793 0.0 0.0847 - 12.810 -2.874 0.0 0.0848 - 12.820 -2.943 0.0 0.0849 - 12.830 -3.000 0.0 0.0850 - 12.840 -3.048 0.0 0.0851 - 12.850 -3.089 0.0 0.0851 - 12.860 -3.124 0.0 0.0850 - 12.870 -3.154 0.0 0.0848 - 12.880 -3.181 0.0 0.0847 - 12.890 -3.205 0.0 0.0847 - 12.900 -3.227 0.0 0.0847 - 12.910 -3.246 0.0 0.0848 - 12.920 -3.262 0.0 0.0850 - 12.930 -3.276 0.0 0.0851 - 12.940 -3.285 0.0 0.0851 - 12.950 -3.291 0.0 0.0851 - 12.960 -3.294 0.0 0.0850 - 12.970 -3.293 0.0 0.0848 - 12.980 -3.291 0.0 0.0847 - 12.990 -3.286 0.0 0.0846 - 13.000 -3.283 0.0 0.0847 - 13.010 -3.280 0.0 0.0848 - 13.020 -3.282 0.0 0.0849 - 13.030 -3.287 0.0 0.0851 - 13.040 -3.299 0.0 0.0851 - 13.050 -3.316 0.0 0.0851 - 13.060 -3.341 0.0 0.0850 - 13.070 -3.371 0.0 0.0848 - 13.080 -3.406 0.0 0.0847 - 13.090 -3.445 0.0 0.0847 - 13.100 -3.486 0.0 0.0847 - 13.110 -3.525 0.0 0.0848 - 13.120 -3.562 0.0 0.0849 - 13.130 -3.594 0.0 0.0850 - 13.140 -3.619 0.0 0.0851 - 13.150 -3.635 0.0 0.0850 - 13.160 -3.641 0.0 0.0849 - 13.170 -3.637 0.0 0.0848 - 13.180 -3.623 0.0 0.0847 - 13.190 -3.598 0.0 0.0847 - 13.200 -3.565 0.0 0.0847 - 13.210 -3.524 0.0 0.0849 - 13.220 -3.475 0.0 0.0850 - 13.230 -3.422 0.0 0.0851 - 13.240 -3.363 0.0 0.0851 - 13.250 -3.300 0.0 0.0850 - 13.260 -3.232 0.0 0.0849 - 13.270 -3.159 0.0 0.0848 - 13.280 -3.080 0.0 0.0847 - 13.290 -2.993 0.0 0.0847 - 13.300 -2.896 0.0 0.0848 - 13.310 -2.788 0.0 0.0849 - 13.320 -2.668 0.0 0.0850 - 13.330 -2.532 0.0 0.0850 - 13.340 -2.381 0.0 0.0850 - 13.350 -2.214 0.0 0.0850 - 13.360 -2.031 0.0 0.0849 - 13.370 -1.834 0.0 0.0848 - 13.380 -1.623 0.0 0.0847 - 13.390 -1.402 0.0 0.0847 - 13.400 -1.173 0.0 0.0848 - 13.410 -0.940 0.0 0.0849 - 13.420 -0.705 0.0 0.0850 - 13.430 -0.473 0.0 0.0850 - 13.440 -0.247 0.0 0.0850 - 13.450 -0.028 0.0 0.0849 - 13.460 0.180 0.0 0.0848 - 13.470 0.376 0.0 0.0847 - 13.480 0.560 0.0 0.0847 - 13.490 0.729 0.0 0.0847 - 13.500 0.886 0.0 0.0848 - 13.510 1.028 0.0 0.0849 - 13.520 1.158 0.0 0.0850 - 13.530 1.275 0.0 0.0850 - 13.540 1.379 0.0 0.0850 - 13.550 1.471 0.0 0.0849 - 13.560 1.549 0.0 0.0848 - 13.570 1.613 0.0 0.0847 - 13.580 1.662 0.0 0.0847 - 13.590 1.694 0.0 0.0847 - 13.600 1.708 0.0 0.0848 - 13.610 1.703 0.0 0.0849 - 13.620 1.678 0.0 0.0850 - 13.630 1.632 0.0 0.0850 - 13.640 1.566 0.0 0.0849 - 13.650 1.480 0.0 0.0848 - 13.660 1.375 0.0 0.0847 - 13.670 1.255 0.0 0.0847 - 13.680 1.122 0.0 0.0847 - 13.690 0.978 0.0 0.0848 - 13.700 0.829 0.0 0.0849 - 13.710 0.678 0.0 0.0850 - 13.720 0.528 0.0 0.0850 - 13.730 0.382 0.0 0.0850 - 13.740 0.244 0.0 0.0849 - 13.750 0.115 0.0 0.0848 - 13.760 -0.004 0.0 0.0847 - 13.770 -0.112 0.0 0.0846 - 13.780 -0.210 0.0 0.0846 - 13.790 -0.299 0.0 0.0847 - 13.800 -0.381 0.0 0.0849 - 13.810 -0.458 0.0 0.0850 - 13.820 -0.532 0.0 0.0850 - 13.830 -0.606 0.0 0.0850 - 13.840 -0.680 0.0 0.0850 - 13.850 -0.755 0.0 0.0848 - 13.860 -0.833 0.0 0.0847 - 13.870 -0.913 0.0 0.0847 - 13.880 -0.994 0.0 0.0847 - 13.890 -1.075 0.0 0.0848 - 13.900 -1.153 0.0 0.0849 - 13.910 -1.226 0.0 0.0850 - 13.920 -1.291 0.0 0.0850 - 13.930 -1.346 0.0 0.0850 - 13.940 -1.388 0.0 0.0849 - 13.950 -1.416 0.0 0.0848 - 13.960 -1.428 0.0 0.0847 - 13.970 -1.422 0.0 0.0846 - 13.980 -1.400 0.0 0.0847 - 13.990 -1.360 0.0 0.0848 - 14.000 -1.304 0.0 0.0849 - 14.010 -1.232 0.0 0.0850 - 14.020 -1.145 0.0 0.0851 - 14.030 -1.046 0.0 0.0850 - 14.040 -0.934 0.0 0.0849 - 14.050 -0.811 0.0 0.0848 - 14.060 -0.679 0.0 0.0847 - 14.070 -0.537 0.0 0.0847 - 14.080 -0.387 0.0 0.0847 - 14.090 -0.229 0.0 0.0848 - 14.100 -0.063 0.0 0.0849 - 14.110 0.110 0.0 0.0850 - 14.120 0.289 0.0 0.0851 - 14.130 0.474 0.0 0.0850 - 14.140 0.663 0.0 0.0849 - 14.150 0.855 0.0 0.0848 - 14.160 1.048 0.0 0.0847 - 14.170 1.241 0.0 0.0847 - 14.180 1.430 0.0 0.0847 - 14.190 1.615 0.0 0.0849 - 14.200 1.793 0.0 0.0850 - 14.210 1.962 0.0 0.0851 - 14.220 2.122 0.0 0.0851 - 14.230 2.272 0.0 0.0850 - 14.240 2.412 0.0 0.0849 - 14.250 2.543 0.0 0.0848 - 14.260 2.665 0.0 0.0847 - 14.270 2.781 0.0 0.0847 - 14.280 2.892 0.0 0.0848 - 14.290 3.000 0.0 0.0849 - 14.300 3.107 0.0 0.0850 - 14.310 3.215 0.0 0.0851 - 14.320 3.325 0.0 0.0851 - 14.330 3.437 0.0 0.0850 - 14.340 3.552 0.0 0.0849 - 14.350 3.670 0.0 0.0848 - 14.360 3.789 0.0 0.0847 - 14.370 3.908 0.0 0.0847 - 14.380 4.025 0.0 0.0848 - 14.390 4.138 0.0 0.0849 - 14.400 4.244 0.0 0.0850 - 14.410 4.343 0.0 0.0850 - 14.420 4.434 0.0 0.0850 - 14.430 4.515 0.0 0.0850 - 14.440 4.587 0.0 0.0849 - 14.450 4.650 0.0 0.0848 - 14.460 4.706 0.0 0.0847 - 14.470 4.757 0.0 0.0847 - 14.480 4.804 0.0 0.0848 - 14.490 4.850 0.0 0.0849 - 14.500 4.897 0.0 0.0850 - 14.510 4.946 0.0 0.0851 - 14.520 4.999 0.0 0.0850 - 14.530 5.054 0.0 0.0850 - 14.540 5.112 0.0 0.0848 - 14.550 5.171 0.0 0.0847 - 14.560 5.229 0.0 0.0847 - 14.570 5.282 0.0 0.0847 - 14.580 5.327 0.0 0.0848 - 14.590 5.361 0.0 0.0849 - 14.600 5.379 0.0 0.0850 - 14.610 5.379 0.0 0.0850 - 14.620 5.358 0.0 0.0850 - 14.630 5.313 0.0 0.0849 - 14.640 5.243 0.0 0.0848 - 14.650 5.148 0.0 0.0847 - 14.660 5.029 0.0 0.0847 - 14.670 4.887 0.0 0.0847 - 14.680 4.723 0.0 0.0848 - 14.690 4.541 0.0 0.0849 - 14.700 4.342 0.0 0.0850 - 14.710 4.129 0.0 0.0850 - 14.720 3.904 0.0 0.0849 - 14.730 3.668 0.0 0.0849 - 14.740 3.423 0.0 0.0848 - 14.750 3.168 0.0 0.0847 - 14.760 2.904 0.0 0.0847 - 14.770 2.630 0.0 0.0847 - 14.780 2.344 0.0 0.0848 - 14.790 2.047 0.0 0.0849 - 14.800 1.738 0.0 0.0850 - 14.810 1.415 0.0 0.0850 - 14.820 1.080 0.0 0.0850 - 14.830 0.734 0.0 0.0849 - 14.840 0.379 0.0 0.0848 - 14.850 0.018 0.0 0.0847 - 14.860 -0.347 0.0 0.0847 - 14.870 -0.710 0.0 0.0847 - 14.880 -1.068 0.0 0.0848 - 14.890 -1.416 0.0 0.0849 - 14.900 -1.750 0.0 0.0850 - 14.910 -2.068 0.0 0.0850 - 14.920 -2.366 0.0 0.0849 - 14.930 -2.644 0.0 0.0848 - 14.940 -2.900 0.0 0.0847 - 14.950 -3.135 0.0 0.0847 - 14.960 -3.350 0.0 0.0847 - 14.970 -3.548 0.0 0.0848 - 14.980 -3.732 0.0 0.0849 - 14.990 -3.904 0.0 0.0850 - 15.000 -4.067 0.0 0.0850 - 15.010 -4.223 0.0 0.0850 - 15.020 -4.373 0.0 0.0849 - 15.030 -4.518 0.0 0.0848 - 15.040 -4.658 0.0 0.0847 - 15.050 -4.790 0.0 0.0847 - 15.060 -4.912 0.0 0.0847 - 15.070 -5.022 0.0 0.0848 - 15.080 -5.115 0.0 0.0849 - 15.090 -5.188 0.0 0.0850 - 15.100 -5.238 0.0 0.0850 - 15.110 -5.263 0.0 0.0850 - 15.120 -5.260 0.0 0.0849 - 15.130 -5.230 0.0 0.0848 - 15.140 -5.173 0.0 0.0847 - 15.150 -5.093 0.0 0.0847 - 15.160 -4.993 0.0 0.0847 - 15.170 -4.878 0.0 0.0848 - 15.180 -4.754 0.0 0.0849 - 15.190 -4.626 0.0 0.0850 - 15.200 -4.499 0.0 0.0850 - 15.210 -4.380 0.0 0.0850 - 15.220 -4.272 0.0 0.0849 - 15.230 -4.178 0.0 0.0848 - 15.240 -4.100 0.0 0.0847 - 15.250 -4.037 0.0 0.0847 - 15.260 -3.989 0.0 0.0847 - 15.270 -3.953 0.0 0.0848 - 15.280 -3.924 0.0 0.0850 - 15.290 -3.898 0.0 0.0850 - 15.300 -3.872 0.0 0.0850 - 15.310 -3.839 0.0 0.0850 - 15.320 -3.797 0.0 0.0849 - 15.330 -3.742 0.0 0.0848 - 15.340 -3.674 0.0 0.0847 - 15.350 -3.591 0.0 0.0847 - 15.360 -3.494 0.0 0.0848 - 15.370 -3.387 0.0 0.0849 - 15.380 -3.271 0.0 0.0850 - 15.390 -3.151 0.0 0.0851 - 15.400 -3.031 0.0 0.0851 - 15.410 -2.915 0.0 0.0850 - 15.420 -2.806 0.0 0.0849 - 15.430 -2.707 0.0 0.0848 - 15.440 -2.619 0.0 0.0847 - 15.450 -2.543 0.0 0.0847 - 15.460 -2.477 0.0 0.0848 - 15.470 -2.419 0.0 0.0849 - 15.480 -2.366 0.0 0.0850 - 15.490 -2.315 0.0 0.0851 - 15.500 -2.261 0.0 0.0851 - 15.510 -2.201 0.0 0.0850 - 15.520 -2.132 0.0 0.0849 - 15.530 -2.051 0.0 0.0848 - 15.540 -1.957 0.0 0.0847 - 15.550 -1.851 0.0 0.0847 - 15.560 -1.732 0.0 0.0848 - 15.570 -1.605 0.0 0.0849 - 15.580 -1.471 0.0 0.0850 - 15.590 -1.336 0.0 0.0851 - 15.600 -1.204 0.0 0.0850 - 15.610 -1.078 0.0 0.0850 - 15.620 -0.963 0.0 0.0849 - 15.630 -0.861 0.0 0.0848 - 15.640 -0.774 0.0 0.0847 - 15.650 -0.702 0.0 0.0847 - 15.660 -0.645 0.0 0.0848 - 15.670 -0.600 0.0 0.0849 - 15.680 -0.566 0.0 0.0850 - 15.690 -0.537 0.0 0.0850 - 15.700 -0.510 0.0 0.0850 - 15.710 -0.482 0.0 0.0849 - 15.720 -0.449 0.0 0.0848 - 15.730 -0.408 0.0 0.0847 - 15.740 -0.358 0.0 0.0847 - 15.750 -0.298 0.0 0.0847 - 15.760 -0.230 0.0 0.0848 - 15.770 -0.156 0.0 0.0849 - 15.780 -0.078 0.0 0.0850 - 15.790 -0.001 0.0 0.0850 - 15.800 0.073 0.0 0.0850 - 15.810 0.138 0.0 0.0849 - 15.820 0.193 0.0 0.0848 - 15.830 0.235 0.0 0.0847 - 15.840 0.263 0.0 0.0847 - 15.850 0.278 0.0 0.0847 - 15.860 0.280 0.0 0.0848 - 15.870 0.274 0.0 0.0849 - 15.880 0.263 0.0 0.0850 - 15.890 0.251 0.0 0.0850 - 15.900 0.245 0.0 0.0849 - 15.910 0.248 0.0 0.0849 - 15.920 0.264 0.0 0.0848 - 15.930 0.297 0.0 0.0847 - 15.940 0.348 0.0 0.0847 - 15.950 0.418 0.0 0.0847 - 15.960 0.505 0.0 0.0848 - 15.970 0.605 0.0 0.0849 - 15.980 0.714 0.0 0.0850 - 15.990 0.828 0.0 0.0850 - 16.000 0.938 0.0 0.0849 - 16.010 1.040 0.0 0.0848 - 16.020 1.128 0.0 0.0848 - 16.030 1.196 0.0 0.0847 - 16.040 1.240 0.0 0.0847 - 16.050 1.260 0.0 0.0848 - 16.060 1.253 0.0 0.0849 - 16.070 1.223 0.0 0.0850 - 16.080 1.171 0.0 0.0850 - 16.090 1.102 0.0 0.0850 - 16.100 1.021 0.0 0.0849 - 16.110 0.935 0.0 0.0848 - 16.120 0.850 0.0 0.0847 - 16.130 0.770 0.0 0.0847 - 16.140 0.702 0.0 0.0847 - 16.150 0.649 0.0 0.0848 - 16.160 0.613 0.0 0.0849 - 16.170 0.595 0.0 0.0850 - 16.180 0.595 0.0 0.0850 - 16.190 0.611 0.0 0.0850 - 16.200 0.639 0.0 0.0849 - 16.210 0.678 0.0 0.0848 - 16.220 0.722 0.0 0.0847 - 16.230 0.769 0.0 0.0847 - 16.240 0.817 0.0 0.0847 - 16.250 0.862 0.0 0.0848 - 16.260 0.905 0.0 0.0849 - 16.270 0.947 0.0 0.0850 - 16.280 0.989 0.0 0.0850 - 16.290 1.035 0.0 0.0850 - 16.300 1.087 0.0 0.0849 - 16.310 1.152 0.0 0.0848 - 16.320 1.232 0.0 0.0847 - 16.330 1.331 0.0 0.0847 - 16.340 1.454 0.0 0.0848 - 16.350 1.602 0.0 0.0849 - 16.360 1.775 0.0 0.0850 - 16.370 1.974 0.0 0.0850 - 16.380 2.194 0.0 0.0851 - 16.390 2.433 0.0 0.0850 - 16.400 2.685 0.0 0.0849 - 16.410 2.945 0.0 0.0848 - 16.420 3.205 0.0 0.0847 - 16.430 3.460 0.0 0.0847 - 16.440 3.703 0.0 0.0848 - 16.450 3.927 0.0 0.0849 - 16.460 4.130 0.0 0.0850 - 16.470 4.308 0.0 0.0850 - 16.480 4.459 0.0 0.0850 - 16.490 4.582 0.0 0.0850 - 16.500 4.678 0.0 0.0849 - 16.510 4.749 0.0 0.0848 - 16.520 4.798 0.0 0.0847 - 16.530 4.827 0.0 0.0847 - 16.540 4.840 0.0 0.0848 - 16.550 4.838 0.0 0.0849 - 16.560 4.824 0.0 0.0850 - 16.570 4.800 0.0 0.0850 - 16.580 4.766 0.0 0.0850 - 16.590 4.720 0.0 0.0850 - 16.600 4.663 0.0 0.0849 - 16.610 4.591 0.0 0.0848 - 16.620 4.503 0.0 0.0847 - 16.630 4.397 0.0 0.0847 - 16.640 4.268 0.0 0.0848 - 16.650 4.117 0.0 0.0849 - 16.660 3.942 0.0 0.0850 - 16.670 3.742 0.0 0.0850 - 16.680 3.519 0.0 0.0850 - 16.690 3.275 0.0 0.0850 - 16.700 3.012 0.0 0.0848 - 16.710 2.735 0.0 0.0848 - 16.720 2.447 0.0 0.0847 - 16.730 2.153 0.0 0.0847 - 16.740 1.859 0.0 0.0848 - 16.750 1.569 0.0 0.0849 - 16.760 1.288 0.0 0.0850 - 16.770 1.017 0.0 0.0850 - 16.780 0.761 0.0 0.0850 - 16.790 0.521 0.0 0.0849 - 16.800 0.297 0.0 0.0848 - 16.810 0.090 0.0 0.0847 - 16.820 -0.101 0.0 0.0847 - 16.830 -0.278 0.0 0.0847 - 16.840 -0.441 0.0 0.0848 - 16.850 -0.594 0.0 0.0849 - 16.860 -0.736 0.0 0.0850 - 16.870 -0.869 0.0 0.0850 - 16.880 -0.994 0.0 0.0850 - 16.890 -1.111 0.0 0.0849 - 16.900 -1.220 0.0 0.0848 - 16.910 -1.320 0.0 0.0847 - 16.920 -1.409 0.0 0.0847 - 16.930 -1.487 0.0 0.0847 - 16.940 -1.552 0.0 0.0848 - 16.950 -1.603 0.0 0.0849 - 16.960 -1.639 0.0 0.0850 - 16.970 -1.660 0.0 0.0850 - 16.980 -1.666 0.0 0.0850 - 16.990 -1.657 0.0 0.0849 - 17.000 -1.634 0.0 0.0848 - 17.010 -1.600 0.0 0.0847 - 17.020 -1.556 0.0 0.0847 - 17.030 -1.506 0.0 0.0848 - 17.040 -1.450 0.0 0.0848 - 17.050 -1.392 0.0 0.0849 - 17.060 -1.334 0.0 0.0850 - 17.070 -1.278 0.0 0.0850 - 17.080 -1.224 0.0 0.0849 - 17.090 -1.175 0.0 0.0848 - 17.100 -1.129 0.0 0.0847 - 17.110 -1.087 0.0 0.0847 - 17.120 -1.049 0.0 0.0847 - 17.130 -1.014 0.0 0.0848 - 17.140 -0.981 0.0 0.0849 - 17.150 -0.949 0.0 0.0850 - 17.160 -0.918 0.0 0.0850 - 17.170 -0.887 0.0 0.0850 - 17.180 -0.857 0.0 0.0849 - 17.190 -0.827 0.0 0.0848 - 17.200 -0.798 0.0 0.0848 - 17.210 -0.772 0.0 0.0847 - 17.220 -0.748 0.0 0.0847 - 17.230 -0.730 0.0 0.0848 - 17.240 -0.718 0.0 0.0849 - 17.250 -0.713 0.0 0.0850 - 17.260 -0.717 0.0 0.0850 - 17.270 -0.730 0.0 0.0850 - 17.280 -0.752 0.0 0.0849 - 17.290 -0.783 0.0 0.0848 - 17.300 -0.823 0.0 0.0847 - 17.310 -0.872 0.0 0.0847 - 17.320 -0.926 0.0 0.0847 - 17.330 -0.986 0.0 0.0848 - 17.340 -1.050 0.0 0.0849 - 17.350 -1.115 0.0 0.0850 - 17.360 -1.181 0.0 0.0850 - 17.370 -1.246 0.0 0.0850 - 17.380 -1.309 0.0 0.0849 - 17.390 -1.369 0.0 0.0848 - 17.400 -1.426 0.0 0.0847 - 17.410 -1.479 0.0 0.0847 - 17.420 -1.529 0.0 0.0848 - 17.430 -1.577 0.0 0.0848 - 17.440 -1.621 0.0 0.0849 - 17.450 -1.663 0.0 0.0850 - 17.460 -1.702 0.0 0.0850 - 17.470 -1.740 0.0 0.0850 - 17.480 -1.776 0.0 0.0849 - 17.490 -1.811 0.0 0.0848 - 17.500 -1.843 0.0 0.0847 - 17.510 -1.872 0.0 0.0847 - 17.520 -1.899 0.0 0.0848 - 17.530 -1.922 0.0 0.0849 - 17.540 -1.940 0.0 0.0850 - 17.550 -1.955 0.0 0.0850 - 17.560 -1.964 0.0 0.0850 - 17.570 -1.969 0.0 0.0850 - 17.580 -1.970 0.0 0.0849 - 17.590 -1.966 0.0 0.0848 - 17.600 -1.959 0.0 0.0847 - 17.610 -1.950 0.0 0.0847 - 17.620 -1.940 0.0 0.0848 - 17.630 -1.930 0.0 0.0849 - 17.640 -1.921 0.0 0.0850 - 17.650 -1.915 0.0 0.0851 - 17.660 -1.912 0.0 0.0851 - 17.670 -1.913 0.0 0.0850 - 17.680 -1.920 0.0 0.0849 - 17.690 -1.931 0.0 0.0848 - 17.700 -1.948 0.0 0.0847 - 17.710 -1.969 0.0 0.0847 - 17.720 -1.994 0.0 0.0848 - 17.730 -2.023 0.0 0.0849 - 17.740 -2.054 0.0 0.0850 - 17.750 -2.086 0.0 0.0850 - 17.760 -2.118 0.0 0.0850 - 17.770 -2.150 0.0 0.0849 - 17.780 -2.181 0.0 0.0848 - 17.790 -2.209 0.0 0.0848 - 17.800 -2.234 0.0 0.0847 - 17.810 -2.256 0.0 0.0847 - 17.820 -2.275 0.0 0.0848 - 17.830 -2.289 0.0 0.0849 - 17.840 -2.298 0.0 0.0850 - 17.850 -2.304 0.0 0.0850 - 17.860 -2.304 0.0 0.0850 - 17.870 -2.298 0.0 0.0849 - 17.880 -2.287 0.0 0.0848 - 17.890 -2.269 0.0 0.0847 - 17.900 -2.243 0.0 0.0847 - 17.910 -2.209 0.0 0.0847 - 17.920 -2.166 0.0 0.0848 - 17.930 -2.113 0.0 0.0849 - 17.940 -2.050 0.0 0.0850 - 17.950 -1.975 0.0 0.0850 - 17.960 -1.888 0.0 0.0850 - 17.970 -1.790 0.0 0.0849 - 17.980 -1.680 0.0 0.0848 - 17.990 -1.559 0.0 0.0847 - 18.000 -1.428 0.0 0.0847 - 18.010 -1.289 0.0 0.0847 - 18.020 -1.142 0.0 0.0848 - 18.030 -0.989 0.0 0.0849 - 18.040 -0.833 0.0 0.0850 - 18.050 -0.674 0.0 0.0850 - 18.060 -0.515 0.0 0.0850 - 18.070 -0.357 0.0 0.0849 - 18.080 -0.202 0.0 0.0848 - 18.090 -0.050 0.0 0.0847 - 18.100 0.098 0.0 0.0847 - 18.110 0.241 0.0 0.0847 - 18.120 0.379 0.0 0.0848 - 18.130 0.512 0.0 0.0849 - 18.140 0.642 0.0 0.0850 - 18.150 0.767 0.0 0.0850 - 18.160 0.889 0.0 0.0850 - 18.170 1.007 0.0 0.0849 - 18.180 1.123 0.0 0.0848 - 18.190 1.236 0.0 0.0847 - 18.200 1.346 0.0 0.0847 - 18.210 1.452 0.0 0.0848 - 18.220 1.553 0.0 0.0848 - 18.230 1.648 0.0 0.0849 - 18.240 1.735 0.0 0.0850 - 18.250 1.814 0.0 0.0850 - 18.260 1.881 0.0 0.0849 - 18.270 1.937 0.0 0.0848 - 18.280 1.980 0.0 0.0848 - 18.290 2.008 0.0 0.0847 - 18.300 2.022 0.0 0.0847 - 18.310 2.021 0.0 0.0848 - 18.320 2.007 0.0 0.0849 - 18.330 1.981 0.0 0.0849 - 18.340 1.943 0.0 0.0850 - 18.350 1.898 0.0 0.0850 - 18.360 1.846 0.0 0.0849 - 18.370 1.792 0.0 0.0848 - 18.380 1.737 0.0 0.0848 - 18.390 1.684 0.0 0.0847 - 18.400 1.636 0.0 0.0847 - 18.410 1.595 0.0 0.0848 - 18.420 1.561 0.0 0.0849 - 18.430 1.535 0.0 0.0850 - 18.440 1.518 0.0 0.0850 - 18.450 1.508 0.0 0.0850 - 18.460 1.504 0.0 0.0849 - 18.470 1.505 0.0 0.0848 - 18.480 1.507 0.0 0.0848 - 18.490 1.510 0.0 0.0847 - 18.500 1.511 0.0 0.0848 - 18.510 1.507 0.0 0.0848 - 18.520 1.498 0.0 0.0849 - 18.530 1.482 0.0 0.0850 - 18.540 1.460 0.0 0.0850 - 18.550 1.432 0.0 0.0850 - 18.560 1.398 0.0 0.0849 - 18.570 1.362 0.0 0.0848 - 18.580 1.325 0.0 0.0847 - 18.590 1.289 0.0 0.0847 - 18.600 1.258 0.0 0.0848 - 18.610 1.235 0.0 0.0849 - 18.620 1.221 0.0 0.0850 - 18.630 1.219 0.0 0.0850 - 18.640 1.230 0.0 0.0850 - 18.650 1.253 0.0 0.0850 - 18.660 1.290 0.0 0.0849 - 18.670 1.337 0.0 0.0848 - 18.680 1.394 0.0 0.0848 - 18.690 1.456 0.0 0.0848 - 18.700 1.521 0.0 0.0848 - 18.710 1.586 0.0 0.0849 - 18.720 1.645 0.0 0.0850 - 18.730 1.697 0.0 0.0850 - 18.740 1.737 0.0 0.0850 - 18.750 1.764 0.0 0.0849 - 18.760 1.776 0.0 0.0849 - 18.770 1.772 0.0 0.0848 - 18.780 1.752 0.0 0.0847 - 18.790 1.717 0.0 0.0848 - 18.800 1.670 0.0 0.0848 - 18.810 1.612 0.0 0.0849 - 18.820 1.545 0.0 0.0850 - 18.830 1.474 0.0 0.0850 - 18.840 1.400 0.0 0.0850 - 18.850 1.327 0.0 0.0849 - 18.860 1.256 0.0 0.0848 - 18.870 1.189 0.0 0.0848 - 18.880 1.128 0.0 0.0847 - 18.890 1.071 0.0 0.0847 - 18.900 1.020 0.0 0.0848 - 18.910 0.973 0.0 0.0849 - 18.920 0.929 0.0 0.0850 - 18.930 0.886 0.0 0.0850 - 18.940 0.844 0.0 0.0850 - 18.950 0.801 0.0 0.0849 - 18.960 0.756 0.0 0.0848 - 18.970 0.708 0.0 0.0848 - 18.980 0.658 0.0 0.0847 - 18.990 0.605 0.0 0.0848 - 19.000 0.552 0.0 0.0848 - 19.010 0.499 0.0 0.0849 - 19.020 0.447 0.0 0.0850 - 19.030 0.400 0.0 0.0850 - 19.040 0.359 0.0 0.0850 - 19.050 0.325 0.0 0.0849 - 19.060 0.300 0.0 0.0848 - 19.070 0.285 0.0 0.0847 - 19.080 0.281 0.0 0.0847 - 19.090 0.287 0.0 0.0848 - 19.100 0.303 0.0 0.0848 - 19.110 0.327 0.0 0.0849 - 19.120 0.359 0.0 0.0850 - 19.130 0.395 0.0 0.0850 - 19.140 0.435 0.0 0.0850 - 19.150 0.475 0.0 0.0849 - 19.160 0.514 0.0 0.0848 - 19.170 0.550 0.0 0.0847 - 19.180 0.582 0.0 0.0847 - 19.190 0.607 0.0 0.0847 - 19.200 0.626 0.0 0.0848 - 19.210 0.637 0.0 0.0849 - 19.220 0.641 0.0 0.0850 - 19.230 0.638 0.0 0.0850 - 19.240 0.627 0.0 0.0849 - 19.250 0.610 0.0 0.0848 - 19.260 0.587 0.0 0.0848 - 19.270 0.558 0.0 0.0847 - 19.280 0.524 0.0 0.0847 - 19.290 0.485 0.0 0.0848 - 19.300 0.440 0.0 0.0849 - 19.310 0.390 0.0 0.0849 - 19.320 0.336 0.0 0.0850 - 19.330 0.276 0.0 0.0850 - 19.340 0.213 0.0 0.0849 - 19.350 0.145 0.0 0.0848 - 19.360 0.074 0.0 0.0848 - 19.370 0.001 0.0 0.0847 - 19.380 -0.073 0.0 0.0847 - 19.390 -0.146 0.0 0.0848 - 19.400 -0.219 0.0 0.0848 - 19.410 -0.288 0.0 0.0849 - 19.420 -0.353 0.0 0.0850 - 19.430 -0.412 0.0 0.0850 - 19.440 -0.466 0.0 0.0849 - 19.450 -0.513 0.0 0.0848 - 19.460 -0.554 0.0 0.0848 - 19.470 -0.589 0.0 0.0847 - 19.480 -0.620 0.0 0.0847 - 19.490 -0.649 0.0 0.0848 - 19.500 -0.676 0.0 0.0849 - 19.510 -0.704 0.0 0.0849 - 19.520 -0.735 0.0 0.0850 - 19.530 -0.770 0.0 0.0850 - 19.540 -0.812 0.0 0.0849 - 19.550 -0.861 0.0 0.0848 - 19.560 -0.918 0.0 0.0847 - 19.570 -0.983 0.0 0.0847 - 19.580 -1.055 0.0 0.0847 - 19.590 -1.134 0.0 0.0848 - 19.600 -1.218 0.0 0.0849 - 19.610 -1.306 0.0 0.0850 - 19.620 -1.395 0.0 0.0850 - 19.630 -1.484 0.0 0.0850 - 19.640 -1.571 0.0 0.0849 - 19.650 -1.654 0.0 0.0848 - 19.660 -1.732 0.0 0.0848 - 19.670 -1.803 0.0 0.0847 - 19.680 -1.867 0.0 0.0848 - 19.690 -1.924 0.0 0.0848 - 19.700 -1.973 0.0 0.0849 - 19.710 -2.014 0.0 0.0850 - 19.720 -2.047 0.0 0.0850 - 19.730 -2.072 0.0 0.0850 - 19.740 -2.089 0.0 0.0849 - 19.750 -2.096 0.0 0.0848 - 19.760 -2.093 0.0 0.0848 - 19.770 -2.079 0.0 0.0848 - 19.780 -2.052 0.0 0.0848 - 19.790 -2.012 0.0 0.0849 - 19.800 -1.956 0.0 0.0850 - 19.810 -1.884 0.0 0.0850 - 19.820 -1.796 0.0 0.0850 - 19.830 -1.691 0.0 0.0850 - 19.840 -1.571 0.0 0.0849 - 19.850 -1.436 0.0 0.0848 - 19.860 -1.290 0.0 0.0848 - 19.870 -1.135 0.0 0.0848 - 19.880 -0.975 0.0 0.0848 - 19.890 -0.815 0.0 0.0849 - 19.900 -0.658 0.0 0.0850 - 19.910 -0.510 0.0 0.0850 - 19.920 -0.373 0.0 0.0850 - 19.930 -0.252 0.0 0.0849 - 19.940 -0.148 0.0 0.0849 - 19.950 -0.063 0.0 0.0848 - 19.960 0.003 0.0 0.0847 - 19.970 0.052 0.0 0.0847 - 19.980 0.085 0.0 0.0848 - 19.990 0.106 0.0 0.0849 - 20.000 0.119 0.0 0.0850 diff --git a/tests/testdata/CdSe_bulk_wur.stru b/tests/testdata/CdSe_bulk_wur.stru deleted file mode 100644 index 558e7e37..00000000 --- a/tests/testdata/CdSe_bulk_wur.stru +++ /dev/null @@ -1,33 +0,0 @@ -title Cell structure file of CdSe #186 -format pdffit -scale 0.846685 -sharp 0.366927, 0.591251, 3.700000 -spcgr P63mc -cell 4.29904, 4.29904, 7.0106027, 90.000000, 90.000000,120.000000 -dcell 0.000493, 0.000493, 0.001368, 0.000000, 0.000000, 0.000000 -ncell 1, 1, 1, 4 -atoms -CD 0.33340001 0.66670001 0.00000000 1.0000 - 0.00000000 0.00000000 0.00000000 0.0000 - 0.01303035 0.01303035 0.01401959 - 0.00011127 0.00011127 0.00019575 - 0.00000000 0.00000000 0.00000000 - 0.00000000 0.00000000 0.00000000 -CD 0.66659999 0.33329999 0.50000000 1.0000 - 0.00000000 0.00000000 0.00000000 0.0000 - 0.01303035 0.01303035 0.01401959 - 0.00011127 0.00011127 0.00019575 - 0.00000000 0.00000000 0.00000000 - 0.00000000 0.00000000 0.00000000 -SE 0.33340001 0.66670001 0.37667000 1.0000 - 0.00000000 0.00000000 0.00000000 0.0000 - 0.01567255 0.01567255 0.04616401 - 0.00022268 0.00022268 0.00071372 - 0.00000000 0.00000000 0.00000000 - 0.00000000 0.00000000 0.00000000 -SE 0.66659999 0.33329999 0.87667000 1.0000 - 0.00000000 0.00000000 0.00000000 0.0000 - 0.01567255 0.01567255 0.04616401 - 0.00022268 0.00022268 0.00071372 - 0.00000000 0.00000000 0.00000000 - 0.00000000 0.00000000 0.00000000 diff --git a/tests/testdata/LaMnO3.stru b/tests/testdata/LaMnO3.stru deleted file mode 100644 index 43d76891..00000000 --- a/tests/testdata/LaMnO3.stru +++ /dev/null @@ -1,129 +0,0 @@ -title Cell structure file of LaMnO3.0 -format pdffit -scale 1.000000 -sharp 0.000000, 1.000000, 3.500000 -spcgr Pbnm -cell 5.486341, 5.619215, 7.628206, 90.000000, 90.000000, 90.000000 -dcell 0.000118, 0.000156, 0.000118, 0.000000, 0.000000, 0.000000 -ncell 1, 1, 1, 20 -atoms -LA 0.99609631 0.03214940 0.25000000 1.0000 - 0.00003041 0.00000852 0.00000000 0.0000 - 0.00253993 0.00253993 0.00253993 - 0.00000214 0.00000214 0.00000214 - 0.00000000 0.00000000 0.00000000 - 0.00000000 0.00000000 0.00000000 -LA 0.49609631 0.46785060 0.75000000 1.0000 - 0.00003041 0.00000852 0.00000000 0.0000 - 0.00253993 0.00253993 0.00253993 - 0.00000214 0.00000214 0.00000214 - 0.00000000 0.00000000 0.00000000 - 0.00000000 0.00000000 0.00000000 -LA 0.00390369 0.96785063 0.75000000 1.0000 - 0.00003041 0.00000852 0.00000000 0.0000 - 0.00253993 0.00253993 0.00253993 - 0.00000214 0.00000214 0.00000214 - 0.00000000 0.00000000 0.00000000 - 0.00000000 0.00000000 0.00000000 -LA 0.50390369 0.53214937 0.25000000 1.0000 - 0.00003041 0.00000852 0.00000000 0.0000 - 0.00253993 0.00253993 0.00253993 - 0.00000214 0.00000214 0.00000214 - 0.00000000 0.00000000 0.00000000 - 0.00000000 0.00000000 0.00000000 -MN 0.00000000 0.50000000 0.00000000 1.0000 - 0.00000000 0.00000000 0.00000000 0.0000 - 0.00065337 0.00065337 0.00065337 - 0.00000165 0.00000165 0.00000165 - 0.00000000 0.00000000 0.00000000 - 0.00000000 0.00000000 0.00000000 -MN 0.50000000 0.00000000 0.00000000 1.0000 - 0.00000000 0.00000000 0.00000000 0.0000 - 0.00065337 0.00065337 0.00065337 - 0.00000165 0.00000165 0.00000165 - 0.00000000 0.00000000 0.00000000 - 0.00000000 0.00000000 0.00000000 -MN 0.00000000 0.50000000 0.50000000 1.0000 - 0.00000000 0.00000000 0.00000000 0.0000 - 0.00065337 0.00065337 0.00065337 - 0.00000165 0.00000165 0.00000165 - 0.00000000 0.00000000 0.00000000 - 0.00000000 0.00000000 0.00000000 -MN 0.50000000 0.00000000 0.50000000 1.0000 - 0.00000000 0.00000000 0.00000000 0.0000 - 0.00065337 0.00065337 0.00065337 - 0.00000165 0.00000165 0.00000165 - 0.00000000 0.00000000 0.00000000 - 0.00000000 0.00000000 0.00000000 -O 0.05957463 0.49616399 0.25000000 1.0000 - 0.00001546 0.00001610 0.00000000 0.0000 - 0.00082010 0.00082010 0.00082010 - 0.00000137 0.00000137 0.00000137 - 0.00000000 0.00000000 0.00000000 - 0.00000000 0.00000000 0.00000000 -O 0.55957460 0.00383601 0.75000000 1.0000 - 0.00001546 0.00001610 0.00000000 0.0000 - 0.00082010 0.00082010 0.00082010 - 0.00000137 0.00000137 0.00000137 - 0.00000000 0.00000000 0.00000000 - 0.00000000 0.00000000 0.00000000 -O 0.94042540 0.50383604 0.75000000 1.0000 - 0.00001546 0.00001610 0.00000000 0.0000 - 0.00082010 0.00082010 0.00082010 - 0.00000137 0.00000137 0.00000137 - 0.00000000 0.00000000 0.00000000 - 0.00000000 0.00000000 0.00000000 -O 0.44042537 0.99616396 0.25000000 1.0000 - 0.00001546 0.00001610 0.00000000 0.0000 - 0.00082010 0.00082010 0.00082010 - 0.00000137 0.00000137 0.00000137 - 0.00000000 0.00000000 0.00000000 - 0.00000000 0.00000000 0.00000000 -O 0.72005206 0.28938726 0.03111255 1.0000 - 0.00001528 0.00001560 0.00002506 0.0000 - 0.00512371 0.00512371 0.00512371 - 0.00000153 0.00000153 0.00000153 - 0.00000000 0.00000000 0.00000000 - 0.00000000 0.00000000 0.00000000 -O 0.22005206 0.21061274 0.96888745 1.0000 - 0.00001528 0.00001560 0.00002506 0.0000 - 0.00512371 0.00512371 0.00512371 - 0.00000153 0.00000153 0.00000153 - 0.00000000 0.00000000 0.00000000 - 0.00000000 0.00000000 0.00000000 -O 0.27994794 0.71061277 0.53111255 1.0000 - 0.00001528 0.00001560 0.00002506 0.0000 - 0.00512371 0.00512371 0.00512371 - 0.00000153 0.00000153 0.00000153 - 0.00000000 0.00000000 0.00000000 - 0.00000000 0.00000000 0.00000000 -O 0.77994794 0.78938723 0.46888745 1.0000 - 0.00001528 0.00001560 0.00002506 0.0000 - 0.00512371 0.00512371 0.00512371 - 0.00000153 0.00000153 0.00000153 - 0.00000000 0.00000000 0.00000000 - 0.00000000 0.00000000 0.00000000 -O 0.27994794 0.71061277 0.96888745 1.0000 - 0.00001528 0.00001560 0.00002506 0.0000 - 0.00512371 0.00512371 0.00512371 - 0.00000153 0.00000153 0.00000153 - 0.00000000 0.00000000 0.00000000 - 0.00000000 0.00000000 0.00000000 -O 0.77994794 0.78938723 0.03111255 1.0000 - 0.00001528 0.00001560 0.00002506 0.0000 - 0.00512371 0.00512371 0.00512371 - 0.00000153 0.00000153 0.00000153 - 0.00000000 0.00000000 0.00000000 - 0.00000000 0.00000000 0.00000000 -O 0.72005206 0.28938726 0.46888745 1.0000 - 0.00001528 0.00001560 0.00002506 0.0000 - 0.00512371 0.00512371 0.00512371 - 0.00000153 0.00000153 0.00000153 - 0.00000000 0.00000000 0.00000000 - 0.00000000 0.00000000 0.00000000 -O 0.22005206 0.21061274 0.53111255 1.0000 - 0.00001528 0.00001560 0.00002506 0.0000 - 0.00512371 0.00512371 0.00512371 - 0.00000153 0.00000153 0.00000153 - 0.00000000 0.00000000 0.00000000 - 0.00000000 0.00000000 0.00000000 diff --git a/tests/testdata/Ni.dat b/tests/testdata/Ni.dat deleted file mode 100644 index 360a4d6b..00000000 --- a/tests/testdata/Ni.dat +++ /dev/null @@ -1,1001 +0,0 @@ - 1.50000 -0.539443 0.00000 1.00000 0.539443 - 1.51850 -1.03098 0.00000 1.00000 1.03098 - 1.53700 -1.43712 0.00000 1.00000 1.43712 - 1.55550 -1.73810 0.00000 1.00000 1.73810 - 1.57400 -1.93402 0.00000 1.00000 1.93402 - 1.59250 -2.04145 0.00000 1.00000 2.04145 - 1.61100 -2.08593 0.00000 1.00000 2.08593 - 1.62950 -2.09295 0.00000 1.00000 2.09295 - 1.64800 -2.08072 0.00000 1.00000 2.08072 - 1.66650 -2.05688 0.00000 1.00000 2.05688 - 1.68500 -2.02006 0.00000 1.00000 2.02006 - 1.70350 -1.96554 0.00000 1.00000 1.96554 - 1.72200 -1.89239 0.00000 1.00000 1.89239 - 1.74050 -1.80936 0.00000 1.00000 1.80936 - 1.75900 -1.73670 0.00000 1.00000 1.73670 - 1.77750 -1.70255 0.00000 1.00000 1.70255 - 1.79600 -1.73461 0.00000 1.00000 1.73461 - 1.81450 -1.84946 0.00000 1.00000 1.84946 - 1.83300 -2.04300 0.00000 1.00000 2.04300 - 1.85150 -2.28566 0.00000 1.00000 2.28566 - 1.87000 -2.52486 0.00000 1.00000 2.52486 - 1.88850 -2.69615 0.00000 1.00000 2.69615 - 1.90700 -2.74180 0.00000 1.00000 2.74180 - 1.92550 -2.63223 0.00000 1.00000 2.63223 - 1.94400 -2.38239 0.00000 1.00000 2.38239 - 1.96250 -2.05565 0.00000 1.00000 2.05565 - 1.98100 -1.75092 0.00000 1.00000 1.75092 - 1.99950 -1.57518 0.00000 1.00000 1.57518 - 2.01800 -1.60914 0.00000 1.00000 1.60914 - 2.03650 -1.87687 0.00000 1.00000 1.87687 - 2.05500 -2.33004 0.00000 1.00000 2.33004 - 2.07350 -2.85357 0.00000 1.00000 2.85357 - 2.09200 -3.29353 0.00000 1.00000 3.29353 - 2.11050 -3.50124 0.00000 1.00000 3.50124 - 2.12900 -3.38172 0.00000 1.00000 3.38172 - 2.14750 -2.93205 0.00000 1.00000 2.93205 - 2.16600 -2.25629 0.00000 1.00000 2.25629 - 2.18450 -1.54918 0.00000 1.00000 1.54918 - 2.20300 -1.04888 0.00000 1.00000 1.04888 - 2.22150 -0.968136 0.00000 1.00000 0.968136 - 2.24000 -1.42070 0.00000 1.00000 1.42070 - 2.25850 -2.36300 0.00000 1.00000 2.36300 - 2.27700 -3.56960 0.00000 1.00000 3.56960 - 2.29550 -4.65416 0.00000 1.00000 4.65416 - 2.31400 -5.13684 0.00000 1.00000 5.13684 - 2.33250 -4.54696 0.00000 1.00000 4.54696 - 2.35100 -2.53890 0.00000 1.00000 2.53890 - 2.36950 1.00656 0.00000 1.00000 -1.00656 - 2.38800 5.92223 0.00000 1.00000 -5.92223 - 2.40650 11.7527 0.00000 1.00000 -11.7527 - 2.42500 17.8143 0.00000 1.00000 -17.8143 - 2.44350 23.3057 0.00000 1.00000 -23.3057 - 2.46200 27.4478 0.00000 1.00000 -27.4478 - 2.48050 29.6246 0.00000 1.00000 -29.6246 - 2.49900 29.4986 0.00000 1.00000 -29.4986 - 2.51750 27.0749 0.00000 1.00000 -27.0749 - 2.53600 22.7028 0.00000 1.00000 -22.7028 - 2.55450 17.0112 0.00000 1.00000 -17.0112 - 2.57300 10.7932 0.00000 1.00000 -10.7932 - 2.59150 4.86134 0.00000 1.00000 -4.86134 - 2.61000 -0.0945224 0.00000 1.00000 0.0945224 - 2.62850 -3.61858 0.00000 1.00000 3.61858 - 2.64700 -5.54803 0.00000 1.00000 5.54803 - 2.66550 -6.01016 0.00000 1.00000 6.01016 - 2.68400 -5.36293 0.00000 1.00000 5.36293 - 2.70250 -4.09596 0.00000 1.00000 4.09596 - 2.72100 -2.71625 0.00000 1.00000 2.71625 - 2.73950 -1.64382 0.00000 1.00000 1.64382 - 2.75800 -1.13791 0.00000 1.00000 1.13791 - 2.77650 -1.26649 0.00000 1.00000 1.26649 - 2.79500 -1.92103 0.00000 1.00000 1.92103 - 2.81350 -2.86890 0.00000 1.00000 2.86890 - 2.83200 -3.82782 0.00000 1.00000 3.82782 - 2.85050 -4.54328 0.00000 1.00000 4.54328 - 2.86900 -4.85054 0.00000 1.00000 4.85054 - 2.88750 -4.70809 0.00000 1.00000 4.70809 - 2.90600 -4.19687 0.00000 1.00000 4.19687 - 2.92450 -3.48841 0.00000 1.00000 3.48841 - 2.94300 -2.79256 0.00000 1.00000 2.79256 - 2.96150 -2.29993 0.00000 1.00000 2.29993 - 2.98000 -2.13422 0.00000 1.00000 2.13422 - 2.99850 -2.32552 0.00000 1.00000 2.32552 - 3.01700 -2.80931 0.00000 1.00000 2.80931 - 3.03550 -3.44928 0.00000 1.00000 3.44928 - 3.05400 -4.07624 0.00000 1.00000 4.07624 - 3.07250 -4.53264 0.00000 1.00000 4.53264 - 3.09100 -4.71141 0.00000 1.00000 4.71141 - 3.10950 -4.58013 0.00000 1.00000 4.58013 - 3.12800 -4.18572 0.00000 1.00000 4.18572 - 3.14650 -3.63955 0.00000 1.00000 3.63955 - 3.16500 -3.08796 0.00000 1.00000 3.08796 - 3.18350 -2.67579 0.00000 1.00000 2.67579 - 3.20200 -2.51194 0.00000 1.00000 2.51194 - 3.22050 -2.64475 0.00000 1.00000 2.64475 - 3.23900 -3.05186 0.00000 1.00000 3.05186 - 3.25750 -3.64576 0.00000 1.00000 3.64576 - 3.27600 -4.29257 0.00000 1.00000 4.29257 - 3.29450 -4.83876 0.00000 1.00000 4.83876 - 3.31300 -5.14008 0.00000 1.00000 5.14008 - 3.33150 -5.08721 0.00000 1.00000 5.08721 - 3.35000 -4.62391 0.00000 1.00000 4.62391 - 3.36850 -3.75470 0.00000 1.00000 3.75470 - 3.38700 -2.54063 0.00000 1.00000 2.54063 - 3.40550 -1.08396 0.00000 1.00000 1.08396 - 3.42400 0.493223 0.00000 1.00000 -0.493223 - 3.44250 2.06874 0.00000 1.00000 -2.06874 - 3.46100 3.53152 0.00000 1.00000 -3.53152 - 3.47950 4.78254 0.00000 1.00000 -4.78254 - 3.49800 5.72969 0.00000 1.00000 -5.72969 - 3.51650 6.28423 0.00000 1.00000 -6.28423 - 3.53500 6.36504 0.00000 1.00000 -6.36504 - 3.55350 5.91247 0.00000 1.00000 -5.91247 - 3.57200 4.90861 0.00000 1.00000 -4.90861 - 3.59050 3.39740 0.00000 1.00000 -3.39740 - 3.60900 1.49612 0.00000 1.00000 -1.49612 - 3.62750 -0.608193 0.00000 1.00000 0.608193 - 3.64600 -2.68019 0.00000 1.00000 2.68019 - 3.66450 -4.47243 0.00000 1.00000 4.47243 - 3.68300 -5.76925 0.00000 1.00000 5.76925 - 3.70150 -6.42920 0.00000 1.00000 6.42920 - 3.72000 -6.41719 0.00000 1.00000 6.41719 - 3.73850 -5.81875 0.00000 1.00000 5.81875 - 3.75700 -4.83074 0.00000 1.00000 4.83074 - 3.77550 -3.72667 0.00000 1.00000 3.72667 - 3.79400 -2.80071 0.00000 1.00000 2.80071 - 3.81250 -2.30147 0.00000 1.00000 2.30147 - 3.83100 -2.37126 0.00000 1.00000 2.37126 - 3.84950 -3.00713 0.00000 1.00000 3.00713 - 3.86800 -4.05566 0.00000 1.00000 4.05566 - 3.88650 -5.24604 0.00000 1.00000 5.24604 - 3.90500 -6.25585 0.00000 1.00000 6.25585 - 3.92350 -6.79521 0.00000 1.00000 6.79521 - 3.94200 -6.68830 0.00000 1.00000 6.68830 - 3.96050 -5.93010 0.00000 1.00000 5.93010 - 3.97900 -4.70113 0.00000 1.00000 4.70113 - 3.99750 -3.33259 0.00000 1.00000 3.33259 - 4.01600 -2.22683 0.00000 1.00000 2.22683 - 4.03450 -1.75037 0.00000 1.00000 1.75037 - 4.05300 -2.12498 0.00000 1.00000 2.12498 - 4.07150 -3.34471 0.00000 1.00000 3.34471 - 4.09000 -5.14253 0.00000 1.00000 5.14253 - 4.10850 -7.01935 0.00000 1.00000 7.01935 - 4.12700 -8.33391 0.00000 1.00000 8.33391 - 4.14550 -8.43660 0.00000 1.00000 8.43660 - 4.16400 -6.81920 0.00000 1.00000 6.81920 - 4.18250 -3.24667 0.00000 1.00000 3.24667 - 4.20100 2.16009 0.00000 1.00000 -2.16009 - 4.21950 8.91152 0.00000 1.00000 -8.91152 - 4.23800 16.2134 0.00000 1.00000 -16.2134 - 4.25650 23.0973 0.00000 1.00000 -23.0973 - 4.27500 28.5935 0.00000 1.00000 -28.5935 - 4.29350 31.9106 0.00000 1.00000 -31.9106 - 4.31200 32.5842 0.00000 1.00000 -32.5842 - 4.33050 30.5617 0.00000 1.00000 -30.5617 - 4.34900 26.2027 0.00000 1.00000 -26.2027 - 4.36750 20.1990 0.00000 1.00000 -20.1990 - 4.38600 13.4320 0.00000 1.00000 -13.4320 - 4.40450 6.80337 0.00000 1.00000 -6.80337 - 4.42300 1.07527 0.00000 1.00000 -1.07527 - 4.44150 -3.24700 0.00000 1.00000 3.24700 - 4.46000 -5.96945 0.00000 1.00000 5.96945 - 4.47850 -7.19581 0.00000 1.00000 7.19581 - 4.49700 -7.25613 0.00000 1.00000 7.25613 - 4.51550 -6.59972 0.00000 1.00000 6.59972 - 4.53400 -5.68054 0.00000 1.00000 5.68054 - 4.55250 -4.86170 0.00000 1.00000 4.86170 - 4.57100 -4.35835 0.00000 1.00000 4.35835 - 4.58950 -4.22677 0.00000 1.00000 4.22677 - 4.60800 -4.39508 0.00000 1.00000 4.39508 - 4.62650 -4.72130 0.00000 1.00000 4.72130 - 4.64500 -5.05871 0.00000 1.00000 5.05871 - 4.66350 -5.30848 0.00000 1.00000 5.30848 - 4.68200 -5.44197 0.00000 1.00000 5.44197 - 4.70050 -5.50097 0.00000 1.00000 5.50097 - 4.71900 -5.56456 0.00000 1.00000 5.56456 - 4.73750 -5.69659 0.00000 1.00000 5.69659 - 4.75600 -5.90806 0.00000 1.00000 5.90806 - 4.77450 -6.13525 0.00000 1.00000 6.13525 - 4.79300 -6.24364 0.00000 1.00000 6.24364 - 4.81150 -6.05670 0.00000 1.00000 6.05670 - 4.83000 -5.40165 0.00000 1.00000 5.40165 - 4.84850 -4.16022 0.00000 1.00000 4.16022 - 4.86700 -2.31100 0.00000 1.00000 2.31100 - 4.88550 0.0479985 0.00000 1.00000 -0.0479985 - 4.90400 2.70271 0.00000 1.00000 -2.70271 - 4.92250 5.35252 0.00000 1.00000 -5.35252 - 4.94100 7.65960 0.00000 1.00000 -7.65960 - 4.95950 9.30734 0.00000 1.00000 -9.30734 - 4.97800 10.0558 0.00000 1.00000 -10.0558 - 4.99650 9.78268 0.00000 1.00000 -9.78268 - 5.01500 8.50309 0.00000 1.00000 -8.50309 - 5.03350 6.36470 0.00000 1.00000 -6.36470 - 5.05200 3.62252 0.00000 1.00000 -3.62252 - 5.07050 0.599290 0.00000 1.00000 -0.599290 - 5.08900 -2.36086 0.00000 1.00000 2.36086 - 5.10750 -4.93870 0.00000 1.00000 4.93870 - 5.12600 -6.88149 0.00000 1.00000 6.88149 - 5.14450 -8.03565 0.00000 1.00000 8.03565 - 5.16300 -8.36668 0.00000 1.00000 8.36668 - 5.18150 -7.96304 0.00000 1.00000 7.96304 - 5.20000 -7.02207 0.00000 1.00000 7.02207 - 5.21850 -5.81895 0.00000 1.00000 5.81895 - 5.23700 -4.66171 0.00000 1.00000 4.66171 - 5.25550 -3.83844 0.00000 1.00000 3.83844 - 5.27400 -3.56410 0.00000 1.00000 3.56410 - 5.29250 -3.93573 0.00000 1.00000 3.93573 - 5.31100 -4.90467 0.00000 1.00000 4.90467 - 5.32950 -6.27267 0.00000 1.00000 6.27267 - 5.34800 -7.71536 0.00000 1.00000 7.71536 - 5.36650 -8.83203 0.00000 1.00000 8.83203 - 5.38500 -9.21516 0.00000 1.00000 9.21516 - 5.40350 -8.52808 0.00000 1.00000 8.52808 - 5.42200 -6.57611 0.00000 1.00000 6.57611 - 5.44050 -3.35625 0.00000 1.00000 3.35625 - 5.45900 0.925287 0.00000 1.00000 -0.925287 - 5.47750 5.87209 0.00000 1.00000 -5.87209 - 5.49600 10.9500 0.00000 1.00000 -10.9500 - 5.51450 15.5640 0.00000 1.00000 -15.5640 - 5.53300 19.1477 0.00000 1.00000 -19.1477 - 5.55150 21.2490 0.00000 1.00000 -21.2490 - 5.57000 21.6003 0.00000 1.00000 -21.6003 - 5.58850 20.1588 0.00000 1.00000 -20.1588 - 5.60700 17.1124 0.00000 1.00000 -17.1124 - 5.62550 12.8494 0.00000 1.00000 -12.8494 - 5.64400 7.89927 0.00000 1.00000 -7.89927 - 5.66250 2.85190 0.00000 1.00000 -2.85190 - 5.68100 -1.72997 0.00000 1.00000 1.72997 - 5.69950 -5.39381 0.00000 1.00000 5.39381 - 5.71800 -7.86162 0.00000 1.00000 7.86162 - 5.73650 -9.06420 0.00000 1.00000 9.06420 - 5.75500 -9.13837 0.00000 1.00000 9.13837 - 5.77350 -8.38683 0.00000 1.00000 8.38683 - 5.79200 -7.20818 0.00000 1.00000 7.20818 - 5.81050 -6.01172 0.00000 1.00000 6.01172 - 5.82900 -5.13567 0.00000 1.00000 5.13567 - 5.84750 -4.78662 0.00000 1.00000 4.78662 - 5.86600 -5.01125 0.00000 1.00000 5.01125 - 5.88450 -5.70222 0.00000 1.00000 5.70222 - 5.90300 -6.63275 0.00000 1.00000 6.63275 - 5.92150 -7.51031 0.00000 1.00000 7.51031 - 5.94000 -8.03914 0.00000 1.00000 8.03914 - 5.95850 -7.98163 0.00000 1.00000 7.98163 - 5.97700 -7.20897 0.00000 1.00000 7.20897 - 5.99550 -5.73309 0.00000 1.00000 5.73309 - 6.01400 -3.71335 0.00000 1.00000 3.71335 - 6.03250 -1.43572 0.00000 1.00000 1.43572 - 6.05100 0.734316 0.00000 1.00000 -0.734316 - 6.06950 2.41816 0.00000 1.00000 -2.41816 - 6.08800 3.29880 0.00000 1.00000 -3.29880 - 6.10650 3.18922 0.00000 1.00000 -3.18922 - 6.12500 2.07961 0.00000 1.00000 -2.07961 - 6.14350 0.150522 0.00000 1.00000 -0.150522 - 6.16200 -2.25436 0.00000 1.00000 2.25436 - 6.18050 -4.69426 0.00000 1.00000 4.69426 - 6.19900 -6.72460 0.00000 1.00000 6.72460 - 6.21750 -7.99834 0.00000 1.00000 7.99834 - 6.23600 -8.35142 0.00000 1.00000 8.35142 - 6.25450 -7.84948 0.00000 1.00000 7.84948 - 6.27300 -6.78013 0.00000 1.00000 6.78013 - 6.29150 -5.58671 0.00000 1.00000 5.58671 - 6.31000 -4.75441 0.00000 1.00000 4.75441 - 6.32850 -4.67266 0.00000 1.00000 4.67266 - 6.34700 -5.50714 0.00000 1.00000 5.50714 - 6.36550 -7.11590 0.00000 1.00000 7.11590 - 6.38400 -9.03699 0.00000 1.00000 9.03699 - 6.40250 -10.5592 0.00000 1.00000 10.5592 - 6.42100 -10.8676 0.00000 1.00000 10.8676 - 6.43950 -9.23379 0.00000 1.00000 9.23379 - 6.45800 -5.20861 0.00000 1.00000 5.20861 - 6.47650 1.23011 0.00000 1.00000 -1.23011 - 6.49500 9.61241 0.00000 1.00000 -9.61241 - 6.51350 19.0142 0.00000 1.00000 -19.0142 - 6.53200 28.1967 0.00000 1.00000 -28.1967 - 6.55050 35.8243 0.00000 1.00000 -35.8243 - 6.56900 40.7166 0.00000 1.00000 -40.7166 - 6.58750 42.0833 0.00000 1.00000 -42.0833 - 6.60600 39.6873 0.00000 1.00000 -39.6873 - 6.62450 33.8989 0.00000 1.00000 -33.8989 - 6.64300 25.6256 0.00000 1.00000 -25.6256 - 6.66150 16.1324 0.00000 1.00000 -16.1324 - 6.68000 6.79125 0.00000 1.00000 -6.79125 - 6.69850 -1.18411 0.00000 1.00000 1.18411 - 6.71700 -6.95910 0.00000 1.00000 6.95910 - 6.73550 -10.2079 0.00000 1.00000 10.2079 - 6.75400 -11.1248 0.00000 1.00000 11.1248 - 6.77250 -10.3198 0.00000 1.00000 10.3198 - 6.79100 -8.62815 0.00000 1.00000 8.62815 - 6.80950 -6.88571 0.00000 1.00000 6.88571 - 6.82800 -5.72660 0.00000 1.00000 5.72660 - 6.84650 -5.45332 0.00000 1.00000 5.45332 - 6.86500 -6.00649 0.00000 1.00000 6.00649 - 6.88350 -7.03437 0.00000 1.00000 7.03437 - 6.90200 -8.03570 0.00000 1.00000 8.03570 - 6.92050 -8.53209 0.00000 1.00000 8.53209 - 6.93900 -8.22002 0.00000 1.00000 8.22002 - 6.95750 -7.06140 0.00000 1.00000 7.06140 - 6.97600 -5.29017 0.00000 1.00000 5.29017 - 6.99450 -3.33754 0.00000 1.00000 3.33754 - 7.01300 -1.70148 0.00000 1.00000 1.70148 - 7.03150 -0.800760 0.00000 1.00000 0.800760 - 7.05000 -0.856664 0.00000 1.00000 0.856664 - 7.06850 -1.83505 0.00000 1.00000 1.83505 - 7.08700 -3.46358 0.00000 1.00000 3.46358 - 7.10550 -5.31731 0.00000 1.00000 5.31731 - 7.12400 -6.94715 0.00000 1.00000 6.94715 - 7.14250 -8.01332 0.00000 1.00000 8.01332 - 7.16100 -8.38320 0.00000 1.00000 8.38320 - 7.17950 -8.16268 0.00000 1.00000 8.16268 - 7.19800 -7.64952 0.00000 1.00000 7.64952 - 7.21650 -7.22129 0.00000 1.00000 7.22129 - 7.23500 -7.19206 0.00000 1.00000 7.19206 - 7.25350 -7.68220 0.00000 1.00000 7.68220 - 7.27200 -8.54371 0.00000 1.00000 8.54371 - 7.29050 -9.36819 0.00000 1.00000 9.36819 - 7.30900 -9.58072 0.00000 1.00000 9.58072 - 7.32750 -8.59790 0.00000 1.00000 8.59790 - 7.34600 -6.00785 0.00000 1.00000 6.00785 - 7.36450 -1.72106 0.00000 1.00000 1.72106 - 7.38300 3.95269 0.00000 1.00000 -3.95269 - 7.40150 10.3276 0.00000 1.00000 -10.3276 - 7.42000 16.4640 0.00000 1.00000 -16.4640 - 7.43850 21.3618 0.00000 1.00000 -21.3618 - 7.45700 24.1782 0.00000 1.00000 -24.1782 - 7.47550 24.4162 0.00000 1.00000 -24.4162 - 7.49400 22.0356 0.00000 1.00000 -22.0356 - 7.51250 17.4573 0.00000 1.00000 -17.4573 - 7.53100 11.4623 0.00000 1.00000 -11.4623 - 7.54950 5.01118 0.00000 1.00000 -5.01118 - 7.56800 -0.965076 0.00000 1.00000 0.965076 - 7.58650 -5.75153 0.00000 1.00000 5.75153 - 7.60500 -8.96799 0.00000 1.00000 8.96799 - 7.62350 -10.5969 0.00000 1.00000 10.5969 - 7.64200 -10.9206 0.00000 1.00000 10.9206 - 7.66050 -10.3893 0.00000 1.00000 10.3893 - 7.67900 -9.46200 0.00000 1.00000 9.46200 - 7.69750 -8.46444 0.00000 1.00000 8.46444 - 7.71600 -7.50854 0.00000 1.00000 7.50854 - 7.73450 -6.49304 0.00000 1.00000 6.49304 - 7.75300 -5.18168 0.00000 1.00000 5.18168 - 7.77150 -3.32911 0.00000 1.00000 3.32911 - 7.79000 -0.811546 0.00000 1.00000 0.811546 - 7.80850 2.28073 0.00000 1.00000 -2.28073 - 7.82700 5.61902 0.00000 1.00000 -5.61902 - 7.84550 8.68909 0.00000 1.00000 -8.68909 - 7.86400 10.9073 0.00000 1.00000 -10.9073 - 7.88250 11.7676 0.00000 1.00000 -11.7676 - 7.90100 10.9777 0.00000 1.00000 -10.9777 - 7.91950 8.54633 0.00000 1.00000 -8.54633 - 7.93800 4.79627 0.00000 1.00000 -4.79627 - 7.95650 0.300695 0.00000 1.00000 -0.300695 - 7.97500 -4.24152 0.00000 1.00000 4.24152 - 7.99350 -8.15787 0.00000 1.00000 8.15787 - 8.01200 -10.9420 0.00000 1.00000 10.9420 - 8.03050 -12.3456 0.00000 1.00000 12.3456 - 8.04900 -12.4001 0.00000 1.00000 12.4001 - 8.06750 -11.3663 0.00000 1.00000 11.3663 - 8.08600 -9.63181 0.00000 1.00000 9.63181 - 8.10450 -7.58723 0.00000 1.00000 7.58723 - 8.12300 -5.52117 0.00000 1.00000 5.52117 - 8.14150 -3.56353 0.00000 1.00000 3.56353 - 8.16000 -1.69260 0.00000 1.00000 1.69260 - 8.17850 0.199827 0.00000 1.00000 -0.199827 - 8.19700 2.21044 0.00000 1.00000 -2.21044 - 8.21550 4.33057 0.00000 1.00000 -4.33057 - 8.23400 6.39218 0.00000 1.00000 -6.39218 - 8.25250 8.07555 0.00000 1.00000 -8.07555 - 8.27100 8.97896 0.00000 1.00000 -8.97896 - 8.28950 8.73073 0.00000 1.00000 -8.73073 - 8.30800 7.11016 0.00000 1.00000 -7.11016 - 8.32650 4.14151 0.00000 1.00000 -4.14151 - 8.34500 0.130936 0.00000 1.00000 -0.130936 - 8.36350 -4.36837 0.00000 1.00000 4.36837 - 8.38200 -8.65854 0.00000 1.00000 8.65854 - 8.40050 -12.0433 0.00000 1.00000 12.0433 - 8.41900 -13.9807 0.00000 1.00000 13.9807 - 8.43750 -14.2030 0.00000 1.00000 14.2030 - 8.45600 -12.7704 0.00000 1.00000 12.7704 - 8.47450 -10.0445 0.00000 1.00000 10.0445 - 8.49300 -6.58938 0.00000 1.00000 6.58938 - 8.51150 -3.02663 0.00000 1.00000 3.02663 - 8.53000 0.112114 0.00000 1.00000 -0.112114 - 8.54850 2.49566 0.00000 1.00000 -2.49566 - 8.56700 4.03580 0.00000 1.00000 -4.03580 - 8.58550 4.85377 0.00000 1.00000 -4.85377 - 8.60400 5.18537 0.00000 1.00000 -5.18537 - 8.62250 5.25808 0.00000 1.00000 -5.25808 - 8.64100 5.18193 0.00000 1.00000 -5.18193 - 8.65950 4.89182 0.00000 1.00000 -4.89182 - 8.67800 4.16349 0.00000 1.00000 -4.16349 - 8.69650 2.70252 0.00000 1.00000 -2.70252 - 8.71500 0.282220 0.00000 1.00000 -0.282220 - 8.73350 -3.11124 0.00000 1.00000 3.11124 - 8.75200 -7.17490 0.00000 1.00000 7.17490 - 8.77050 -11.2672 0.00000 1.00000 11.2672 - 8.78900 -14.4886 0.00000 1.00000 14.4886 - 8.80750 -15.8559 0.00000 1.00000 15.8559 - 8.82600 -14.5328 0.00000 1.00000 14.5328 - 8.84450 -10.0609 0.00000 1.00000 10.0609 - 8.86300 -2.52773 0.00000 1.00000 2.52773 - 8.88150 7.37428 0.00000 1.00000 -7.37428 - 8.90000 18.4240 0.00000 1.00000 -18.4240 - 8.91850 29.0726 0.00000 1.00000 -29.0726 - 8.93700 37.7295 0.00000 1.00000 -37.7295 - 8.95550 43.0717 0.00000 1.00000 -43.0717 - 8.97400 44.3044 0.00000 1.00000 -44.3044 - 8.99250 41.3154 0.00000 1.00000 -41.3154 - 9.01100 34.6857 0.00000 1.00000 -34.6857 - 9.02950 25.5570 0.00000 1.00000 -25.5570 - 9.04800 15.3859 0.00000 1.00000 -15.3859 - 9.06650 5.64529 0.00000 1.00000 -5.64529 - 9.08500 -2.45985 0.00000 1.00000 2.45985 - 9.10350 -8.19758 0.00000 1.00000 8.19758 - 9.12200 -11.3936 0.00000 1.00000 11.3936 - 9.14050 -12.3840 0.00000 1.00000 12.3840 - 9.15900 -11.8591 0.00000 1.00000 11.8591 - 9.17750 -10.6446 0.00000 1.00000 10.6446 - 9.19600 -9.48212 0.00000 1.00000 9.48212 - 9.21450 -8.86286 0.00000 1.00000 8.86286 - 9.23300 -8.95166 0.00000 1.00000 8.95166 - 9.25150 -9.60978 0.00000 1.00000 9.60978 - 9.27000 -10.4985 0.00000 1.00000 10.4985 - 9.28850 -11.2264 0.00000 1.00000 11.2264 - 9.30700 -11.4956 0.00000 1.00000 11.4956 - 9.32550 -11.2056 0.00000 1.00000 11.2056 - 9.34400 -10.4851 0.00000 1.00000 10.4851 - 9.36250 -9.64367 0.00000 1.00000 9.64367 - 9.38100 -9.05839 0.00000 1.00000 9.05839 - 9.39950 -9.03059 0.00000 1.00000 9.03059 - 9.41800 -9.65891 0.00000 1.00000 9.65891 - 9.43650 -10.7695 0.00000 1.00000 10.7695 - 9.45500 -11.9282 0.00000 1.00000 11.9282 - 9.47350 -12.5352 0.00000 1.00000 12.5352 - 9.49200 -11.9793 0.00000 1.00000 11.9793 - 9.51050 -9.80968 0.00000 1.00000 9.80968 - 9.52900 -5.88098 0.00000 1.00000 5.88098 - 9.54750 -0.429865 0.00000 1.00000 0.429865 - 9.56600 5.93738 0.00000 1.00000 -5.93738 - 9.58450 12.3467 0.00000 1.00000 -12.3467 - 9.60300 17.8253 0.00000 1.00000 -17.8253 - 9.62150 21.4983 0.00000 1.00000 -21.4983 - 9.64000 22.7684 0.00000 1.00000 -22.7684 - 9.65850 21.4353 0.00000 1.00000 -21.4353 - 9.67700 17.7297 0.00000 1.00000 -17.7297 - 9.69550 12.2556 0.00000 1.00000 -12.2556 - 9.71400 5.85940 0.00000 1.00000 -5.85940 - 9.73250 -0.539853 0.00000 1.00000 0.539853 - 9.75100 -6.11696 0.00000 1.00000 6.11696 - 9.76950 -10.2704 0.00000 1.00000 10.2704 - 9.78800 -12.6954 0.00000 1.00000 12.6954 - 9.80650 -13.3941 0.00000 1.00000 13.3941 - 9.82500 -12.6315 0.00000 1.00000 12.6315 - 9.84350 -10.8487 0.00000 1.00000 10.8487 - 9.86200 -8.55755 0.00000 1.00000 8.55755 - 9.88050 -6.24003 0.00000 1.00000 6.24003 - 9.89900 -4.27478 0.00000 1.00000 4.27478 - 9.91750 -2.90328 0.00000 1.00000 2.90328 - 9.93600 -2.23386 0.00000 1.00000 2.23386 - 9.95450 -2.27104 0.00000 1.00000 2.27104 - 9.97300 -2.95175 0.00000 1.00000 2.95175 - 9.99150 -4.17209 0.00000 1.00000 4.17209 - 10.0100 -5.79607 0.00000 1.00000 5.79607 - 10.0285 -7.64859 0.00000 1.00000 7.64859 - 10.0470 -9.50283 0.00000 1.00000 9.50283 - 10.0655 -11.0757 0.00000 1.00000 11.0757 - 10.0840 -12.0425 0.00000 1.00000 12.0425 - 10.1025 -12.0751 0.00000 1.00000 12.0751 - 10.1210 -10.9017 0.00000 1.00000 10.9017 - 10.1395 -8.37613 0.00000 1.00000 8.37613 - 10.1580 -4.54026 0.00000 1.00000 4.54026 - 10.1765 0.338357 0.00000 1.00000 -0.338357 - 10.1950 5.76996 0.00000 1.00000 -5.76996 - 10.2135 11.0939 0.00000 1.00000 -11.0939 - 10.2320 15.5741 0.00000 1.00000 -15.5741 - 10.2505 18.5225 0.00000 1.00000 -18.5225 - 10.2690 19.4270 0.00000 1.00000 -19.4270 - 10.2875 18.0567 0.00000 1.00000 -18.0567 - 10.3060 14.5227 0.00000 1.00000 -14.5227 - 10.3245 9.27796 0.00000 1.00000 -9.27796 - 10.3430 3.05599 0.00000 1.00000 -3.05599 - 10.3615 -3.24345 0.00000 1.00000 3.24345 - 10.3800 -8.70145 0.00000 1.00000 8.70145 - 10.3985 -12.5330 0.00000 1.00000 12.5330 - 10.4170 -14.2182 0.00000 1.00000 14.2182 - 10.4355 -13.5885 0.00000 1.00000 13.5885 - 10.4540 -10.8525 0.00000 1.00000 10.8525 - 10.4725 -6.55772 0.00000 1.00000 6.55772 - 10.4910 -1.49640 0.00000 1.00000 1.49640 - 10.5095 3.42852 0.00000 1.00000 -3.42852 - 10.5280 7.35363 0.00000 1.00000 -7.35363 - 10.5465 9.59717 0.00000 1.00000 -9.59717 - 10.5650 9.77054 0.00000 1.00000 -9.77054 - 10.5835 7.84234 0.00000 1.00000 -7.84234 - 10.6020 4.14584 0.00000 1.00000 -4.14584 - 10.6205 -0.671143 0.00000 1.00000 0.671143 - 10.6390 -5.74603 0.00000 1.00000 5.74603 - 10.6575 -10.1361 0.00000 1.00000 10.1361 - 10.6760 -12.9671 0.00000 1.00000 12.9671 - 10.6945 -13.5738 0.00000 1.00000 13.5738 - 10.7130 -11.6108 0.00000 1.00000 11.6108 - 10.7315 -7.11852 0.00000 1.00000 7.11852 - 10.7500 -0.532582 0.00000 1.00000 0.532582 - 10.7685 7.36496 0.00000 1.00000 -7.36496 - 10.7870 15.5502 0.00000 1.00000 -15.5502 - 10.8055 22.9046 0.00000 1.00000 -22.9046 - 10.8240 28.3836 0.00000 1.00000 -28.3836 - 10.8425 31.1819 0.00000 1.00000 -31.1819 - 10.8610 30.8667 0.00000 1.00000 -30.8667 - 10.8795 27.4544 0.00000 1.00000 -27.4544 - 10.8980 21.4174 0.00000 1.00000 -21.4174 - 10.9165 13.6149 0.00000 1.00000 -13.6149 - 10.9350 5.15717 0.00000 1.00000 -5.15717 - 10.9535 -2.77403 0.00000 1.00000 2.77403 - 10.9720 -9.11963 0.00000 1.00000 9.11963 - 10.9905 -13.1166 0.00000 1.00000 13.1166 - 11.0090 -14.4189 0.00000 1.00000 14.4189 - 11.0275 -13.1446 0.00000 1.00000 13.1446 - 11.0460 -9.84069 0.00000 1.00000 9.84069 - 11.0645 -5.37361 0.00000 1.00000 5.37361 - 11.0830 -0.766336 0.00000 1.00000 0.766336 - 11.1015 2.99059 0.00000 1.00000 -2.99059 - 11.1200 5.12102 0.00000 1.00000 -5.12102 - 11.1385 5.20555 0.00000 1.00000 -5.20555 - 11.1570 3.25580 0.00000 1.00000 -3.25580 - 11.1755 -0.295787 0.00000 1.00000 0.295787 - 11.1940 -4.68917 0.00000 1.00000 4.68917 - 11.2125 -8.99252 0.00000 1.00000 8.99252 - 11.2310 -12.2872 0.00000 1.00000 12.2872 - 11.2495 -13.8447 0.00000 1.00000 13.8447 - 11.2680 -13.2610 0.00000 1.00000 13.2610 - 11.2865 -10.5280 0.00000 1.00000 10.5280 - 11.3050 -6.02790 0.00000 1.00000 6.02790 - 11.3235 -0.457428 0.00000 1.00000 0.457428 - 11.3420 5.30272 0.00000 1.00000 -5.30272 - 11.3605 10.3468 0.00000 1.00000 -10.3468 - 11.3790 13.9003 0.00000 1.00000 -13.9003 - 11.3975 15.4459 0.00000 1.00000 -15.4459 - 11.4160 14.7993 0.00000 1.00000 -14.7993 - 11.4345 12.1251 0.00000 1.00000 -12.1251 - 11.4530 7.89515 0.00000 1.00000 -7.89515 - 11.4715 2.79743 0.00000 1.00000 -2.79743 - 11.4900 -2.38402 0.00000 1.00000 2.38402 - 11.5085 -6.89848 0.00000 1.00000 6.89848 - 11.5270 -10.1446 0.00000 1.00000 10.1446 - 11.5455 -11.7562 0.00000 1.00000 11.7562 - 11.5640 -11.6477 0.00000 1.00000 11.6477 - 11.5825 -10.0156 0.00000 1.00000 10.0156 - 11.6010 -7.29778 0.00000 1.00000 7.29778 - 11.6195 -4.09885 0.00000 1.00000 4.09885 - 11.6380 -1.08810 0.00000 1.00000 1.08810 - 11.6565 1.11439 0.00000 1.00000 -1.11439 - 11.6750 2.04788 0.00000 1.00000 -2.04788 - 11.6935 1.49867 0.00000 1.00000 -1.49867 - 11.7120 -0.451611 0.00000 1.00000 0.451611 - 11.7305 -3.42848 0.00000 1.00000 3.42848 - 11.7490 -6.82125 0.00000 1.00000 6.82125 - 11.7675 -9.88740 0.00000 1.00000 9.88740 - 11.7860 -11.8896 0.00000 1.00000 11.8896 - 11.8045 -12.2430 0.00000 1.00000 12.2430 - 11.8230 -10.6446 0.00000 1.00000 10.6446 - 11.8415 -7.15722 0.00000 1.00000 7.15722 - 11.8600 -2.22583 0.00000 1.00000 2.22583 - 11.8785 3.38458 0.00000 1.00000 -3.38458 - 11.8970 8.72108 0.00000 1.00000 -8.72108 - 11.9155 12.8213 0.00000 1.00000 -12.8213 - 11.9340 14.9032 0.00000 1.00000 -14.9032 - 11.9525 14.5281 0.00000 1.00000 -14.5281 - 11.9710 11.6999 0.00000 1.00000 -11.6999 - 11.9895 6.87776 0.00000 1.00000 -6.87776 - 12.0080 0.891504 0.00000 1.00000 -0.891504 - 12.0265 -5.22565 0.00000 1.00000 5.22565 - 12.0450 -10.4522 0.00000 1.00000 10.4522 - 12.0635 -13.9931 0.00000 1.00000 13.9931 - 12.0820 -15.4435 0.00000 1.00000 15.4435 - 12.1005 -14.8644 0.00000 1.00000 14.8644 - 12.1190 -12.7520 0.00000 1.00000 12.7520 - 12.1375 -9.90845 0.00000 1.00000 9.90845 - 12.1560 -7.24453 0.00000 1.00000 7.24453 - 12.1745 -5.56166 0.00000 1.00000 5.56166 - 12.1930 -5.36161 0.00000 1.00000 5.36161 - 12.2115 -6.72586 0.00000 1.00000 6.72586 - 12.2300 -9.28835 0.00000 1.00000 9.28835 - 12.2485 -12.3067 0.00000 1.00000 12.3067 - 12.2670 -14.8178 0.00000 1.00000 14.8178 - 12.2855 -15.8476 0.00000 1.00000 15.8476 - 12.3040 -14.6332 0.00000 1.00000 14.6332 - 12.3225 -10.8097 0.00000 1.00000 10.8097 - 12.3410 -4.52145 0.00000 1.00000 4.52145 - 12.3595 3.57058 0.00000 1.00000 -3.57058 - 12.3780 12.3893 0.00000 1.00000 -12.3893 - 12.3965 20.6314 0.00000 1.00000 -20.6314 - 12.4150 27.0092 0.00000 1.00000 -27.0092 - 12.4335 30.4959 0.00000 1.00000 -30.4959 - 12.4520 30.5247 0.00000 1.00000 -30.5247 - 12.4705 27.1034 0.00000 1.00000 -27.1034 - 12.4890 20.8197 0.00000 1.00000 -20.8197 - 12.5075 12.7348 0.00000 1.00000 -12.7348 - 12.5260 4.18409 0.00000 1.00000 -4.18409 - 12.5445 -3.47600 0.00000 1.00000 3.47600 - 12.5630 -9.12640 0.00000 1.00000 9.12640 - 12.5815 -12.0958 0.00000 1.00000 12.0958 - 12.6000 -12.2803 0.00000 1.00000 12.2803 - 12.6185 -10.1467 0.00000 1.00000 10.1467 - 12.6370 -6.61573 0.00000 1.00000 6.61573 - 12.6555 -2.84816 0.00000 1.00000 2.84816 - 12.6740 0.0234471 0.00000 1.00000 -0.0234471 - 12.6925 1.16051 0.00000 1.00000 -1.16051 - 12.7110 0.222329 0.00000 1.00000 -0.222329 - 12.7295 -2.53923 0.00000 1.00000 2.53923 - 12.7480 -6.31966 0.00000 1.00000 6.31966 - 12.7665 -9.93250 0.00000 1.00000 9.93250 - 12.7850 -12.0782 0.00000 1.00000 12.0782 - 12.8035 -11.6556 0.00000 1.00000 11.6556 - 12.8220 -8.04822 0.00000 1.00000 8.04822 - 12.8405 -1.31753 0.00000 1.00000 1.31753 - 12.8590 7.74657 0.00000 1.00000 -7.74657 - 12.8775 17.7420 0.00000 1.00000 -17.7420 - 12.8960 26.9214 0.00000 1.00000 -26.9214 - 12.9145 33.5578 0.00000 1.00000 -33.5578 - 12.9330 36.3277 0.00000 1.00000 -36.3277 - 12.9515 34.6234 0.00000 1.00000 -34.6234 - 12.9700 28.7156 0.00000 1.00000 -28.7156 - 12.9885 19.7233 0.00000 1.00000 -19.7233 - 13.0070 9.38804 0.00000 1.00000 -9.38804 - 13.0255 -0.297908 0.00000 1.00000 0.297908 - 13.0440 -7.52791 0.00000 1.00000 7.52791 - 13.0625 -11.0794 0.00000 1.00000 11.0794 - 13.0810 -10.5807 0.00000 1.00000 10.5807 - 13.0995 -6.58087 0.00000 1.00000 6.58087 - 13.1180 -0.404585 0.00000 1.00000 0.404585 - 13.1365 6.17556 0.00000 1.00000 -6.17556 - 13.1550 11.3708 0.00000 1.00000 -11.3708 - 13.1735 13.8053 0.00000 1.00000 -13.8053 - 13.1920 12.8357 0.00000 1.00000 -12.8357 - 13.2105 8.68336 0.00000 1.00000 -8.68336 - 13.2290 2.34908 0.00000 1.00000 -2.34908 - 13.2475 -4.66287 0.00000 1.00000 4.66287 - 13.2660 -10.7379 0.00000 1.00000 10.7379 - 13.2845 -14.5602 0.00000 1.00000 14.5602 - 13.3030 -15.4343 0.00000 1.00000 15.4343 - 13.3215 -13.4393 0.00000 1.00000 13.4393 - 13.3400 -9.37967 0.00000 1.00000 9.37967 - 13.3585 -4.55053 0.00000 1.00000 4.55053 - 13.3770 -0.382431 0.00000 1.00000 0.382431 - 13.3955 1.93839 0.00000 1.00000 -1.93839 - 13.4140 1.77366 0.00000 1.00000 -1.77366 - 13.4325 -0.818874 0.00000 1.00000 0.818874 - 13.4510 -5.13072 0.00000 1.00000 5.13072 - 13.4695 -10.0255 0.00000 1.00000 10.0255 - 13.4880 -14.2744 0.00000 1.00000 14.2744 - 13.5065 -16.9060 0.00000 1.00000 16.9060 - 13.5250 -17.4714 0.00000 1.00000 17.4714 - 13.5435 -16.1512 0.00000 1.00000 16.1512 - 13.5620 -13.6784 0.00000 1.00000 13.6784 - 13.5805 -11.1043 0.00000 1.00000 11.1043 - 13.5990 -9.47288 0.00000 1.00000 9.47288 - 13.6175 -9.49567 0.00000 1.00000 9.49567 - 13.6360 -11.3153 0.00000 1.00000 11.3153 - 13.6545 -14.4268 0.00000 1.00000 14.4268 - 13.6730 -17.7824 0.00000 1.00000 17.7824 - 13.6915 -20.0552 0.00000 1.00000 20.0552 - 13.7100 -19.9965 0.00000 1.00000 19.9965 - 13.7285 -16.7898 0.00000 1.00000 16.7898 - 13.7470 -10.3089 0.00000 1.00000 10.3089 - 13.7655 -1.20781 0.00000 1.00000 1.20781 - 13.7840 9.18567 0.00000 1.00000 -9.18567 - 13.8025 19.1488 0.00000 1.00000 -19.1488 - 13.8210 26.9489 0.00000 1.00000 -26.9489 - 13.8395 31.2366 0.00000 1.00000 -31.2366 - 13.8580 31.3496 0.00000 1.00000 -31.3496 - 13.8765 27.4511 0.00000 1.00000 -27.4511 - 13.8950 20.4697 0.00000 1.00000 -20.4697 - 13.9135 11.8582 0.00000 1.00000 -11.8582 - 13.9320 3.23523 0.00000 1.00000 -3.23523 - 13.9505 -3.99882 0.00000 1.00000 3.99882 - 13.9690 -8.96984 0.00000 1.00000 8.96984 - 13.9875 -11.4848 0.00000 1.00000 11.4848 - 14.0060 -11.9967 0.00000 1.00000 11.9967 - 14.0245 -11.3970 0.00000 1.00000 11.3970 - 14.0430 -10.7008 0.00000 1.00000 10.7008 - 14.0615 -10.7168 0.00000 1.00000 10.7168 - 14.0800 -11.7936 0.00000 1.00000 11.7936 - 14.0985 -13.7115 0.00000 1.00000 13.7115 - 14.1170 -15.7457 0.00000 1.00000 15.7457 - 14.1355 -16.8835 0.00000 1.00000 16.8835 - 14.1540 -16.1342 0.00000 1.00000 16.1342 - 14.1725 -12.8466 0.00000 1.00000 12.8466 - 14.1910 -6.94542 0.00000 1.00000 6.94542 - 14.2095 0.982134 0.00000 1.00000 -0.982134 - 14.2280 9.77953 0.00000 1.00000 -9.77953 - 14.2465 17.9729 0.00000 1.00000 -17.9729 - 14.2650 24.1178 0.00000 1.00000 -24.1178 - 14.2835 27.1485 0.00000 1.00000 -27.1485 - 14.3020 26.6355 0.00000 1.00000 -26.6355 - 14.3205 22.8839 0.00000 1.00000 -22.8839 - 14.3390 16.8479 0.00000 1.00000 -16.8479 - 14.3575 9.88786 0.00000 1.00000 -9.88786 - 14.3760 3.43554 0.00000 1.00000 -3.43554 - 14.3945 -1.34253 0.00000 1.00000 1.34253 - 14.4130 -3.79922 0.00000 1.00000 3.79922 - 14.4315 -3.91650 0.00000 1.00000 3.91650 - 14.4500 -2.25034 0.00000 1.00000 2.25034 - 14.4685 0.265934 0.00000 1.00000 -0.265934 - 14.4870 2.60091 0.00000 1.00000 -2.60091 - 14.5055 3.90902 0.00000 1.00000 -3.90902 - 14.5240 3.74411 0.00000 1.00000 -3.74411 - 14.5425 2.15013 0.00000 1.00000 -2.15013 - 14.5610 -0.388481 0.00000 1.00000 0.388481 - 14.5795 -3.11515 0.00000 1.00000 3.11515 - 14.5980 -5.23631 0.00000 1.00000 5.23631 - 14.6165 -6.15513 0.00000 1.00000 6.15513 - 14.6350 -5.63898 0.00000 1.00000 5.63898 - 14.6535 -3.87566 0.00000 1.00000 3.87566 - 14.6720 -1.40645 0.00000 1.00000 1.40645 - 14.6905 1.04029 0.00000 1.00000 -1.04029 - 14.7090 2.76304 0.00000 1.00000 -2.76304 - 14.7275 3.28473 0.00000 1.00000 -3.28473 - 14.7460 2.47788 0.00000 1.00000 -2.47788 - 14.7645 0.584519 0.00000 1.00000 -0.584519 - 14.7830 -1.87052 0.00000 1.00000 1.87052 - 14.8015 -4.24417 0.00000 1.00000 4.24417 - 14.8200 -5.96765 0.00000 1.00000 5.96765 - 14.8385 -6.70965 0.00000 1.00000 6.70965 - 14.8570 -6.46211 0.00000 1.00000 6.46211 - 14.8755 -5.52356 0.00000 1.00000 5.52356 - 14.8940 -4.38544 0.00000 1.00000 4.38544 - 14.9125 -3.55512 0.00000 1.00000 3.55512 - 14.9310 -3.36898 0.00000 1.00000 3.36898 - 14.9495 -3.85281 0.00000 1.00000 3.85281 - 14.9680 -4.67590 0.00000 1.00000 4.67590 - 14.9865 -5.21922 0.00000 1.00000 5.21922 - 15.0050 -4.74479 0.00000 1.00000 4.74479 - 15.0235 -2.62144 0.00000 1.00000 2.62144 - 15.0420 1.45687 0.00000 1.00000 -1.45687 - 15.0605 7.32500 0.00000 1.00000 -7.32500 - 15.0790 14.3193 0.00000 1.00000 -14.3193 - 15.0975 21.3835 0.00000 1.00000 -21.3835 - 15.1160 27.2852 0.00000 1.00000 -27.2852 - 15.1345 30.8902 0.00000 1.00000 -30.8902 - 15.1530 31.4245 0.00000 1.00000 -31.4245 - 15.1715 28.6588 0.00000 1.00000 -28.6588 - 15.1900 22.9682 0.00000 1.00000 -22.9682 - 15.2085 15.2541 0.00000 1.00000 -15.2541 - 15.2270 6.74712 0.00000 1.00000 -6.74712 - 15.2455 -1.25964 0.00000 1.00000 1.25964 - 15.2640 -7.68049 0.00000 1.00000 7.68049 - 15.2825 -11.8442 0.00000 1.00000 11.8442 - 15.3010 -13.5919 0.00000 1.00000 13.5919 - 15.3195 -13.2493 0.00000 1.00000 13.2493 - 15.3380 -11.4916 0.00000 1.00000 11.4916 - 15.3565 -9.14144 0.00000 1.00000 9.14144 - 15.3750 -6.95504 0.00000 1.00000 6.95504 - 15.3935 -5.44896 0.00000 1.00000 5.44896 - 15.4120 -4.80772 0.00000 1.00000 4.80772 - 15.4305 -4.88897 0.00000 1.00000 4.88897 - 15.4490 -5.31706 0.00000 1.00000 5.31706 - 15.4675 -5.63285 0.00000 1.00000 5.63285 - 15.4860 -5.45462 0.00000 1.00000 5.45462 - 15.5045 -4.60459 0.00000 1.00000 4.60459 - 15.5230 -3.16776 0.00000 1.00000 3.16776 - 15.5415 -1.46992 0.00000 1.00000 1.46992 - 15.5600 0.0157586 0.00000 1.00000 -0.0157586 - 15.5785 0.806047 0.00000 1.00000 -0.806047 - 15.5970 0.550242 0.00000 1.00000 -0.550242 - 15.6155 -0.861348 0.00000 1.00000 0.861348 - 15.6340 -3.25430 0.00000 1.00000 3.25430 - 15.6525 -6.20584 0.00000 1.00000 6.20584 - 15.6710 -9.14992 0.00000 1.00000 9.14992 - 15.6895 -11.5204 0.00000 1.00000 11.5204 - 15.7080 -12.8909 0.00000 1.00000 12.8909 - 15.7265 -13.0717 0.00000 1.00000 13.0717 - 15.7450 -12.1417 0.00000 1.00000 12.1417 - 15.7635 -10.4097 0.00000 1.00000 10.4097 - 15.7820 -8.32011 0.00000 1.00000 8.32011 - 15.8005 -6.33136 0.00000 1.00000 6.33136 - 15.8190 -4.80087 0.00000 1.00000 4.80087 - 15.8375 -3.90675 0.00000 1.00000 3.90675 - 15.8560 -3.62474 0.00000 1.00000 3.62474 - 15.8745 -3.76225 0.00000 1.00000 3.76225 - 15.8930 -4.03596 0.00000 1.00000 4.03596 - 15.9115 -4.16761 0.00000 1.00000 4.16761 - 15.9300 -3.96959 0.00000 1.00000 3.96959 - 15.9485 -3.39629 0.00000 1.00000 3.39629 - 15.9670 -2.54969 0.00000 1.00000 2.54969 - 15.9855 -1.64188 0.00000 1.00000 1.64188 - 16.0040 -0.928772 0.00000 1.00000 0.928772 - 16.0225 -0.634845 0.00000 1.00000 0.634845 - 16.0410 -0.888145 0.00000 1.00000 0.888145 - 16.0595 -1.67980 0.00000 1.00000 1.67980 - 16.0780 -2.85514 0.00000 1.00000 2.85514 - 16.0965 -4.13661 0.00000 1.00000 4.13661 - 16.1150 -5.17310 0.00000 1.00000 5.17310 - 16.1335 -5.60636 0.00000 1.00000 5.60636 - 16.1520 -5.14159 0.00000 1.00000 5.14159 - 16.1705 -3.60734 0.00000 1.00000 3.60734 - 16.1890 -0.992023 0.00000 1.00000 0.992023 - 16.2075 2.54958 0.00000 1.00000 -2.54958 - 16.2260 6.71807 0.00000 1.00000 -6.71807 - 16.2445 11.1120 0.00000 1.00000 -11.1120 - 16.2630 15.2812 0.00000 1.00000 -15.2812 - 16.2815 18.7822 0.00000 1.00000 -18.7822 - 16.3000 21.2269 0.00000 1.00000 -21.2269 - 16.3185 22.3212 0.00000 1.00000 -22.3212 - 16.3370 21.8912 0.00000 1.00000 -21.8912 - 16.3555 19.8991 0.00000 1.00000 -19.8991 - 16.3740 16.4493 0.00000 1.00000 -16.4493 - 16.3925 11.7863 0.00000 1.00000 -11.7863 - 16.4110 6.28331 0.00000 1.00000 -6.28331 - 16.4295 0.418687 0.00000 1.00000 -0.418687 - 16.4480 -5.25963 0.00000 1.00000 5.25963 - 16.4665 -10.1842 0.00000 1.00000 10.1842 - 16.4850 -13.8295 0.00000 1.00000 13.8295 - 16.5035 -15.7785 0.00000 1.00000 15.7785 - 16.5220 -15.7830 0.00000 1.00000 15.7830 - 16.5405 -13.8070 0.00000 1.00000 13.8070 - 16.5590 -10.0391 0.00000 1.00000 10.0391 - 16.5775 -4.87264 0.00000 1.00000 4.87264 - 16.5960 1.14589 0.00000 1.00000 -1.14589 - 16.6145 7.38649 0.00000 1.00000 -7.38649 - 16.6330 13.2091 0.00000 1.00000 -13.2091 - 16.6515 18.0296 0.00000 1.00000 -18.0296 - 16.6700 21.3708 0.00000 1.00000 -21.3708 - 16.6885 22.8991 0.00000 1.00000 -22.8991 - 16.7070 22.4456 0.00000 1.00000 -22.4456 - 16.7255 20.0158 0.00000 1.00000 -20.0158 - 16.7440 15.7881 0.00000 1.00000 -15.7881 - 16.7625 10.1035 0.00000 1.00000 -10.1035 - 16.7810 3.44424 0.00000 1.00000 -3.44424 - 16.7995 -3.59847 0.00000 1.00000 3.59847 - 16.8180 -10.3717 0.00000 1.00000 10.3717 - 16.8365 -16.2205 0.00000 1.00000 16.2205 - 16.8550 -20.5580 0.00000 1.00000 20.5580 - 16.8735 -22.9372 0.00000 1.00000 22.9372 - 16.8920 -23.1129 0.00000 1.00000 23.1129 - 16.9105 -21.0837 0.00000 1.00000 21.0837 - 16.9290 -17.1032 0.00000 1.00000 17.1032 - 16.9475 -11.6563 0.00000 1.00000 11.6563 - 16.9660 -5.39998 0.00000 1.00000 5.39998 - 16.9845 0.923758 0.00000 1.00000 -0.923758 - 17.0030 6.59122 0.00000 1.00000 -6.59122 - 17.0215 10.9979 0.00000 1.00000 -10.9979 - 17.0400 13.7383 0.00000 1.00000 -13.7383 - 17.0585 14.6477 0.00000 1.00000 -14.6477 - 17.0770 13.7998 0.00000 1.00000 -13.7998 - 17.0955 11.4638 0.00000 1.00000 -11.4638 - 17.1140 8.03578 0.00000 1.00000 -8.03578 - 17.1325 3.96378 0.00000 1.00000 -3.96378 - 17.1510 -0.316698 0.00000 1.00000 0.316698 - 17.1695 -4.42438 0.00000 1.00000 4.42438 - 17.1880 -8.04681 0.00000 1.00000 8.04681 - 17.2065 -10.9324 0.00000 1.00000 10.9324 - 17.2250 -12.8725 0.00000 1.00000 12.8725 - 17.2435 -13.6898 0.00000 1.00000 13.6898 - 17.2620 -13.2456 0.00000 1.00000 13.2456 - 17.2805 -11.4675 0.00000 1.00000 11.4675 - 17.2990 -8.39144 0.00000 1.00000 8.39144 - 17.3175 -4.20001 0.00000 1.00000 4.20001 - 17.3360 0.758004 0.00000 1.00000 -0.758004 - 17.3545 5.98116 0.00000 1.00000 -5.98116 - 17.3730 10.8661 0.00000 1.00000 -10.8661 - 17.3915 14.7906 0.00000 1.00000 -14.7906 - 17.4100 17.2137 0.00000 1.00000 -17.2137 - 17.4285 17.7745 0.00000 1.00000 -17.7745 - 17.4470 16.3661 0.00000 1.00000 -16.3661 - 17.4655 13.1690 0.00000 1.00000 -13.1690 - 17.4840 8.63053 0.00000 1.00000 -8.63053 - 17.5025 3.39246 0.00000 1.00000 -3.39246 - 17.5210 -1.82203 0.00000 1.00000 1.82203 - 17.5395 -6.33848 0.00000 1.00000 6.33848 - 17.5580 -9.64981 0.00000 1.00000 9.64981 - 17.5765 -11.4978 0.00000 1.00000 11.4978 - 17.5950 -11.9009 0.00000 1.00000 11.9009 - 17.6135 -11.1239 0.00000 1.00000 11.1239 - 17.6320 -9.59944 0.00000 1.00000 9.59944 - 17.6505 -7.81972 0.00000 1.00000 7.81972 - 17.6690 -6.22442 0.00000 1.00000 6.22442 - 17.6875 -5.11122 0.00000 1.00000 5.11122 - 17.7060 -4.58875 0.00000 1.00000 4.58875 - 17.7245 -4.58029 0.00000 1.00000 4.58029 - 17.7430 -4.87225 0.00000 1.00000 4.87225 - 17.7615 -5.18968 0.00000 1.00000 5.18968 - 17.7800 -5.27616 0.00000 1.00000 5.27616 - 17.7985 -4.95771 0.00000 1.00000 4.95771 - 17.8170 -4.17763 0.00000 1.00000 4.17763 - 17.8355 -2.99861 0.00000 1.00000 2.99861 - 17.8540 -1.57655 0.00000 1.00000 1.57655 - 17.8725 -0.115674 0.00000 1.00000 0.115674 - 17.8910 1.18232 0.00000 1.00000 -1.18232 - 17.9095 2.16253 0.00000 1.00000 -2.16253 - 17.9280 2.74507 0.00000 1.00000 -2.74507 - 17.9465 2.93310 0.00000 1.00000 -2.93310 - 17.9650 2.80225 0.00000 1.00000 -2.80225 - 17.9835 2.47685 0.00000 1.00000 -2.47685 - 18.0020 2.09940 0.00000 1.00000 -2.09940 - 18.0205 1.79907 0.00000 1.00000 -1.79907 - 18.0390 1.66403 0.00000 1.00000 -1.66403 - 18.0575 1.72260 0.00000 1.00000 -1.72260 - 18.0760 1.93703 0.00000 1.00000 -1.93703 - 18.0945 2.21113 0.00000 1.00000 -2.21113 - 18.1130 2.40837 0.00000 1.00000 -2.40837 - 18.1315 2.37442 0.00000 1.00000 -2.37442 - 18.1500 1.95988 0.00000 1.00000 -1.95988 - 18.1685 1.04724 0.00000 1.00000 -1.04724 - 18.1870 -0.426523 0.00000 1.00000 0.426523 - 18.2055 -2.45315 0.00000 1.00000 2.45315 - 18.2240 -4.90773 0.00000 1.00000 4.90773 - 18.2425 -7.52944 0.00000 1.00000 7.52944 - 18.2610 -9.92715 0.00000 1.00000 9.92715 - 18.2795 -11.6174 0.00000 1.00000 11.6174 - 18.2980 -12.0956 0.00000 1.00000 12.0956 - 18.3165 -10.9327 0.00000 1.00000 10.9327 - 18.3350 -7.88331 0.00000 1.00000 7.88331 - 18.3535 -2.98071 0.00000 1.00000 2.98071 - 18.3720 3.40650 0.00000 1.00000 -3.40650 - 18.3905 10.5811 0.00000 1.00000 -10.5811 - 18.4090 17.5968 0.00000 1.00000 -17.5968 - 18.4275 23.4036 0.00000 1.00000 -23.4036 - 18.4460 27.0310 0.00000 1.00000 -27.0310 - 18.4645 27.7731 0.00000 1.00000 -27.7731 - 18.4830 25.3345 0.00000 1.00000 -25.3345 - 18.5015 19.9052 0.00000 1.00000 -19.9052 - 18.5200 12.1472 0.00000 1.00000 -12.1472 - 18.5385 3.09099 0.00000 1.00000 -3.09099 - 18.5570 -6.03798 0.00000 1.00000 6.03798 - 18.5755 -14.0281 0.00000 1.00000 14.0281 - 18.5940 -19.8843 0.00000 1.00000 19.8843 - 18.6125 -22.9844 0.00000 1.00000 22.9844 - 18.6310 -23.1597 0.00000 1.00000 23.1597 - 18.6495 -20.6881 0.00000 1.00000 20.6881 - 18.6680 -16.2075 0.00000 1.00000 16.2075 - 18.6865 -10.5714 0.00000 1.00000 10.5714 - 18.7050 -4.68098 0.00000 1.00000 4.68098 - 18.7235 0.671251 0.00000 1.00000 -0.671251 - 18.7420 4.91529 0.00000 1.00000 -4.91529 - 18.7605 7.75797 0.00000 1.00000 -7.75797 - 18.7790 9.17588 0.00000 1.00000 -9.17588 - 18.7975 9.35965 0.00000 1.00000 -9.35965 - 18.8160 8.63035 0.00000 1.00000 -8.63035 - 18.8345 7.35145 0.00000 1.00000 -7.35145 - 18.8530 5.85510 0.00000 1.00000 -5.85510 - 18.8715 4.39513 0.00000 1.00000 -4.39513 - 18.8900 3.13002 0.00000 1.00000 -3.13002 - 18.9085 2.13168 0.00000 1.00000 -2.13168 - 18.9270 1.40976 0.00000 1.00000 -1.40976 - 18.9455 0.939913 0.00000 1.00000 -0.939913 - 18.9640 0.686429 0.00000 1.00000 -0.686429 - 18.9825 0.614229 0.00000 1.00000 -0.614229 - 19.0010 0.690570 0.00000 1.00000 -0.690570 - 19.0195 0.880032 0.00000 1.00000 -0.880032 - 19.0380 1.13788 0.00000 1.00000 -1.13788 - 19.0565 1.40627 0.00000 1.00000 -1.40627 - 19.0750 1.61604 0.00000 1.00000 -1.61604 - 19.0935 1.69418 0.00000 1.00000 -1.69418 - 19.1120 1.57467 0.00000 1.00000 -1.57467 - 19.1305 1.20912 0.00000 1.00000 -1.20912 - 19.1490 0.574418 0.00000 1.00000 -0.574418 - 19.1675 -0.322868 0.00000 1.00000 0.322868 - 19.1860 -1.44364 0.00000 1.00000 1.44364 - 19.2045 -2.71278 0.00000 1.00000 2.71278 - 19.2230 -4.01492 0.00000 1.00000 4.01492 - 19.2415 -5.19189 0.00000 1.00000 5.19189 - 19.2600 -6.04623 0.00000 1.00000 6.04623 - 19.2785 -6.35560 0.00000 1.00000 6.35560 - 19.2970 -5.90135 0.00000 1.00000 5.90135 - 19.3155 -4.51168 0.00000 1.00000 4.51168 - 19.3340 -2.11474 0.00000 1.00000 2.11474 - 19.3525 1.20914 0.00000 1.00000 -1.20914 - 19.3710 5.19105 0.00000 1.00000 -5.19105 - 19.3895 9.36912 0.00000 1.00000 -9.36912 - 19.4080 13.1271 0.00000 1.00000 -13.1271 - 19.4265 15.7779 0.00000 1.00000 -15.7779 - 19.4450 16.6827 0.00000 1.00000 -16.6827 - 19.4635 15.3867 0.00000 1.00000 -15.3867 - 19.4820 11.7418 0.00000 1.00000 -11.7418 - 19.5005 5.98757 0.00000 1.00000 -5.98757 - 19.5190 -1.23710 0.00000 1.00000 1.23710 - 19.5375 -8.96359 0.00000 1.00000 8.96359 - 19.5560 -16.0382 0.00000 1.00000 16.0382 - 19.5745 -21.3164 0.00000 1.00000 21.3164 - 19.5930 -23.8699 0.00000 1.00000 23.8699 - 19.6115 -23.1644 0.00000 1.00000 23.1644 - 19.6300 -19.1740 0.00000 1.00000 19.1740 - 19.6485 -12.4057 0.00000 1.00000 12.4057 - 19.6670 -3.82669 0.00000 1.00000 3.82669 - 19.6855 5.29471 0.00000 1.00000 -5.29471 - 19.7040 13.6058 0.00000 1.00000 -13.6058 - 19.7225 19.9014 0.00000 1.00000 -19.9014 - 19.7410 23.3260 0.00000 1.00000 -23.3260 - 19.7595 23.5068 0.00000 1.00000 -23.5068 - 19.7780 20.5929 0.00000 1.00000 -20.5929 - 19.7965 15.1973 0.00000 1.00000 -15.1973 - 19.8150 8.25741 0.00000 1.00000 -8.25741 - 19.8335 0.846490 0.00000 1.00000 -0.846490 - 19.8520 -6.02165 0.00000 1.00000 6.02165 - 19.8705 -11.5565 0.00000 1.00000 11.5565 - 19.8890 -15.2939 0.00000 1.00000 15.2939 - 19.9075 -17.1257 0.00000 1.00000 17.1257 - 19.9260 -17.2573 0.00000 1.00000 17.2573 - 19.9445 -16.1119 0.00000 1.00000 16.1119 - 19.9630 -14.2055 0.00000 1.00000 14.2055 - 19.9815 -12.0275 0.00000 1.00000 12.0275 - 20.0000 -9.95383 0.00000 1.00000 9.95383 diff --git a/tests/testdata/Ni.stru b/tests/testdata/Ni.stru deleted file mode 100644 index e13f2693..00000000 --- a/tests/testdata/Ni.stru +++ /dev/null @@ -1,33 +0,0 @@ -title structure Ni FCC -format pdffit -scale 1.000000 -sharp 0.000000, 0.000000, 1.000000, 0.000000 -spcgr Fm-3m -cell 3.520000, 3.520000, 3.520000, 90.000000, 90.000000, 90.000000 -dcell 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000 -ncell 1, 1, 1, 4 -atoms -NI 0.00000000 0.00000000 0.00000000 1.0000 - 0.00000000 0.00000000 0.00000000 0.0000 - 0.00126651 0.00126651 0.00126651 - 0.00000000 0.00000000 0.00000000 - 0.00000000 0.00000000 0.00000000 - 0.00000000 0.00000000 0.00000000 -NI 0.00000000 0.50000000 0.50000000 1.0000 - 0.00000000 0.00000000 0.00000000 0.0000 - 0.00126651 0.00126651 0.00126651 - 0.00000000 0.00000000 0.00000000 - 0.00000000 0.00000000 0.00000000 - 0.00000000 0.00000000 0.00000000 -NI 0.50000000 0.00000000 0.50000000 1.0000 - 0.00000000 0.00000000 0.00000000 0.0000 - 0.00126651 0.00126651 0.00126651 - 0.00000000 0.00000000 0.00000000 - 0.00000000 0.00000000 0.00000000 - 0.00000000 0.00000000 0.00000000 -NI 0.50000000 0.50000000 0.00000000 1.0000 - 0.00000000 0.00000000 0.00000000 0.0000 - 0.00126651 0.00126651 0.00126651 - 0.00000000 0.00000000 0.00000000 - 0.00000000 0.00000000 0.00000000 - 0.00000000 0.00000000 0.00000000 diff --git a/tests/testdata/Ni_2-8.chi.gr b/tests/testdata/Ni_2-8.chi.gr deleted file mode 100644 index eebbc5e0..00000000 --- a/tests/testdata/Ni_2-8.chi.gr +++ /dev/null @@ -1,2134 +0,0 @@ -History written: Wed Jul 30 00:37:52 2003 -Produced by me -####### Get_XPDF ####### - -##### General_Setting -title=RAPDF -workingdirectory=/u24/masadeh/research/projects/RAPDF_develop/performed_testes/withANDwoBkg_refinement/Ni_MUCAT0307/ -sourcedir=/u24/local/pdfgetx2/ -logfile=.pdfgetx2.log -quiet=0 debug=0 autosave_isa=1 savefilenamebase=Ni_2-8.chi -iqfilesurfix=.iq sqfilesurfix=.sq fqfilesurfix=.fq grfilesurfix=.gr - -##### DataFileFormat -datatype=1 (0:SPEC, 1:CHI, 2:nxm column, 3:unknown) -num_skiplines=4 comment_id=# delimiter= -### SPEC Format scan_id=#S scan_delimiter= -columnname_id=#L columnname_delimiter= -data_id= data_delimiter= -### CHI Format -### nxm column Format -### End of file format - -##### Data&Background -samfile=Ni_2-8.chi.new num_sams=1 -sambkgfile= num_sambkgs=1 -confile= num_cons=1 -conbkgfile= num_conbkgs=1 -det# used xcol detcol deterrcol xmin xmax add_det mul_det add_bkg mul_bkg add_con mul_con add_conbkg mul_conbkg - 0 1 0 1 3 0.00000 35.0000 0.00000 1.00000 0.00000 0.998691 0.00000 1.00000 0.00000 1.00000 - -##### Experiment_Setup -title=PDF analysis -user=me -facility=In house -temperature=300.000 containermut=0.0200000 filtermut=0.0200000 -## X-Ray radiationtype=3 - (0: Ag K_alpha, 1:Cu K_alpha, 2:Mo K_alpha, 3:Customize) -lambda=0.126514 energy=98.0010 polartype=2 polardegree=0.960000 -## MonoChromator crystaltype=0 (0:Perfect, 1:Mosaic, 2:None) -position=0 (0:Primary beam, 1:Diffracted beam) -dspacetype=0 (0:Si{111}, 1:Ge{111}, 2:Customize) dspacing=3.13200 - -##### Sample_Setup information num_atoms=1 -#L symbol valence fractions z user_f1 user_f2 user_macoef - Ni 0.00 1.000000 28 0.000000 0.000000 0.000000 -geometry=2 mut=0.10590000 numberdensity=0.109910 -thickness=0.00000 packingFraction=0.00000 theory_mut=0.00000 - -##### GetIQ_Setup -xformat=1 -smoothcorr_isa=0 selfnormalize_isa=0 -#L par_name sample sample_bkg container container_bkg -smooth_degree 2 2 2 2 -smooth_width 6 6 6 6 -selfnormalize 0 0 0 0 -filtercorr_isa=0 samfiltercorr_isa=0 sambkgfiltercorr_isa=0 -confiltercorr_isa=0 conbkgfiltercorr_isa=0 -scatveffcorr_isa=0 samconveffcorr_isa=1 sambkgveffcorr_isa=1 -conbkgveffcorr_isa=1 -nonegative_isa=1 negativevalue=-1.00000 - -##### Calibration_Data -## Detection efficiency energy dependence detedepxaxis=0 -detedepfunctype=0 detedep_elastic=1.00000 detedep_fluores=1.80000 -detedep_quadra=0.00000 detedep_spline=0.00000 detedep_file= -## Detector transmission energy dependence dettcoefxaxis=0 -dettcoeffunctype=0 dettcoef_elastic=0.950000 dettcoef_fluores=0.600000 -dettcoef_quadra=0.00000 dettcoef_spline=0.00000 dettcoef_file= - -##### IQ_Simulation -### Elastic used_isa=1 mymethod=1 -do_samabsorp=1 do_multscat=1 do_conabsorp=0 do_airabsorp=0 -do_polarization=1 do_oblincident=0 do_energydep=0 -do_breitdirac=0 breitdiracexpo=2.00000 -do_rulandwin=0 rulandwinwidth=0.00100000 -do_useredit=0 add_user=0.00000 mul_user=1.00000 -### Compton used_isa=1 mymethod=1 -do_samabsorp=1 do_multscat=1 do_conabsorp=0 do_airabsorp=0 -do_polarization=1 do_oblincident=0 do_energydep=0 -do_breitdirac=0 breitdiracexpo=2.00000 -do_rulandwin=0 rulandwinwidth=0.00100000 -do_useredit=0 add_user=0.00000 mul_user=1.00000 -### Fluores used_isa=1 mymethod=1 -do_samabsorp=1 do_multscat=1 do_conabsorp=0 do_airabsorp=0 -do_polarization=1 do_oblincident=0 do_energydep=0 -do_breitdirac=0 breitdiracexpo=2.00000 -do_rulandwin=0 rulandwinwidth=0.00100000 -do_useredit=0 add_user=0.00000 mul_user=1.00000 - -##### Correction_Setup corrmethod=0 -oblincident_isa=1 dettranscoef=0.999900 samfluore_isa=1 -samfluoretype=0 samfluorescale=0.030000000 -multiscat_isa=1 xraypolar_isa=1 samabsorp_isa=1 -highqscale_isa=1 highqratio=0.600000 scaleconst=122.37800 -scaleconst_theory=122.37800 -comptonscat_isa=1 rulandwin_isa=1 rulandintewidth=0.01000000 -comptonmethod=0 breitdirac_isa=1 breitdiracexponent=3 -detefficiency_isa=1 detefficiencytype=2 (0-1: linear, 2-3: quadratic) -detefficiency_a=-0.010944165 detefficiency_b=0.21833235 -lauediffuse_isa=1 -weight_isa=1 weighttype=0 (0: ^2, 1: , 2: Data Smoothed) -weightsmoothrmin=3.00000 weightsmoothwidth=100 weightsmoothcycles=600 -editsq_isa=0 editsqtype=0 add_sq=0.00000 mul_sq=1.00000 -editsqsmoothrmin=3.00000 editsqsmoothwidth=100 editsqsmoothcycles=600 -smoothdata_isa=0 smoothfunctype=0 smoothqmin=12.0000 smoothboxwidth=9 -interpolateqmin_isa=0 qmininterpolationtype=0 -dampfq_isa=0 dampfqtype=0 dampfqwidth=40.0000 - -##### SqGr_Optimization Setup -ftmethod=0 -## S(q) qmin=1.000000 qmax=40.000000 qgrid=0.000000 -## G(r) rmin=0.000000 rmax=20.000000 rgrid=0.010000 -## SqOptimization sqoptfunction=1 -optqmin=20.0000 optqmax=40.0000 optqgrid=0.00000 -optrmin=0.00000 optrmax=2.20000 optrgrid=0.01000000 -maxiter=20 relstep=0.00000 weighttype=0 weightfunc=0 -fitbkgmult_isa=0 fitsampmut_isa=0 fitpolariz_isa=0 -fitoblique_isa=0 fitfluores_isa=0 -fitrulandw_isa=0 fitenergya_isa=1 fitenergyb_isa=1 -fitsimurulandw_isa=1 fitDetEdepfluores_isa=0 fitDetEdepquadra_isa=0 -fitDetEdepspline_isa=0 fitDetTCoefElastic_isa=0 fitDetTCoefFluores_isa=0 -fitDetTcoefquadra_isa=0 fitDetTcoefspline_isa=0 - -##### Save&Plot Settings -datatype=GrData iqcorrtype=IntCorr iqsimutype=SimuIq -sqcorrtype=OblinCorr sqtofqtype=FqData -gropttype=OptFq miscdatatype=AtomASF -##### start data -#F Ni_2-8.chi.gr -#D Tue Feb 8 11:46:14 2005 -#C -#S 1 G(r) -#D -#L r G(r) d_r d_Gr - 1.000000e-02 -7.734561e-02 -1.381170e-02 3.134926e-02 - 2.000000e-02 -1.596764e-01 -2.762339e-02 6.045792e-02 - 3.000000e-02 -2.516875e-01 -4.143509e-02 8.526468e-02 - 4.000000e-02 -3.575096e-01 -5.524679e-02 1.040541e-01 - 5.000000e-02 -4.804651e-01 -6.905849e-02 1.155991e-01 - 6.000000e-02 -6.228668e-01 -8.287018e-02 1.192732e-01 - 7.000000e-02 -7.858705e-01 -9.668188e-02 1.151330e-01 - 8.000000e-02 -9.693874e-01 -1.104936e-01 1.039918e-01 - 9.000000e-02 -1.172061e+00 -1.243053e-01 8.755577e-02 - 1.000000e-01 -1.391306e+00 -1.381170e-01 6.884717e-02 - 1.100000e-01 -1.623409e+00 -1.519287e-01 5.341991e-02 - 1.200000e-01 -1.863680e+00 -1.657404e-01 4.979434e-02 - 1.300000e-01 -2.106649e+00 -1.795521e-01 6.017895e-02 - 1.400000e-01 -2.346295e+00 -1.933638e-01 7.640497e-02 - 1.500000e-01 -2.576293e+00 -2.071755e-01 9.161881e-02 - 1.600000e-01 -2.790268e+00 -2.209872e-01 1.024655e-01 - 1.700000e-01 -2.982047e+00 -2.347989e-01 1.074539e-01 - 1.800000e-01 -3.145891e+00 -2.486105e-01 1.062389e-01 - 1.900000e-01 -3.276707e+00 -2.624222e-01 9.942805e-02 - 2.000000e-01 -3.370223e+00 -2.762339e-01 8.860376e-02 - 2.100000e-01 -3.423130e+00 -2.900456e-01 7.650761e-02 - 2.200000e-01 -3.433181e+00 -3.038573e-01 6.719764e-02 - 2.300000e-01 -3.399254e+00 -3.176690e-01 6.493149e-02 - 2.400000e-01 -3.321377e+00 -3.314807e-01 7.061632e-02 - 2.500000e-01 -3.200715e+00 -3.452924e-01 8.074527e-02 - 2.600000e-01 -3.039527e+00 -3.591041e-01 9.101665e-02 - 2.700000e-01 -2.841094e+00 -3.729158e-01 9.850821e-02 - 2.800000e-01 -2.609626e+00 -3.867275e-01 1.017102e-01 - 2.900000e-01 -2.350147e+00 -4.005392e-01 1.002266e-01 - 3.000000e-01 -2.068363e+00 -4.143509e-01 9.462396e-02 - 3.100000e-01 -1.770519e+00 -4.281626e-01 8.640470e-02 - 3.200000e-01 -1.463237e+00 -4.419743e-01 7.800773e-02 - 3.300000e-01 -1.153355e+00 -4.557860e-01 7.249483e-02 - 3.400000e-01 -8.477479e-01 -4.695977e-01 7.224522e-02 - 3.500000e-01 -5.531450e-01 -4.834094e-01 7.713224e-02 - 3.600000e-01 -2.759477e-01 -4.972211e-01 8.467203e-02 - 3.700000e-01 -2.204310e-02 -5.110328e-01 9.195493e-02 - 3.800000e-01 2.033757e-01 -5.248445e-01 9.686320e-02 - 3.900000e-01 3.959788e-01 -5.386562e-01 9.828977e-02 - 4.000000e-01 5.524508e-01 -5.524679e-01 9.606310e-02 - 4.100000e-01 6.706182e-01 -5.662796e-01 9.087598e-02 - 4.200000e-01 7.495432e-01 -5.800913e-01 8.423689e-02 - 4.300000e-01 7.895774e-01 -5.939030e-01 7.831796e-02 - 4.400000e-01 7.923692e-01 -6.077147e-01 7.538431e-02 - 4.500000e-01 7.608195e-01 -6.215264e-01 7.662821e-02 - 4.600000e-01 6.989824e-01 -6.353381e-01 8.131523e-02 - 4.700000e-01 6.119129e-01 -6.491498e-01 8.737928e-02 - 4.800000e-01 5.054623e-01 -6.629615e-01 9.267455e-02 - 4.900000e-01 3.860302e-01 -6.767732e-01 9.569092e-02 - 5.000000e-01 2.602819e-01 -6.905849e-01 9.573000e-02 - 5.100000e-01 1.348438e-01 -7.043966e-01 9.289354e-02 - 5.200000e-01 1.599279e-02 -7.182083e-01 8.803723e-02 - 5.300000e-01 -9.064421e-02 -7.320200e-01 8.267435e-02 - 5.400000e-01 -1.803637e-01 -7.458316e-01 7.868367e-02 - 5.500000e-01 -2.496148e-01 -7.596433e-01 7.762463e-02 - 5.600000e-01 -2.961697e-01 -7.734550e-01 7.986113e-02 - 5.700000e-01 -3.192238e-01 -7.872667e-01 8.433275e-02 - 5.800000e-01 -3.194177e-01 -8.010784e-01 8.926692e-02 - 5.900000e-01 -2.987769e-01 -8.148901e-01 9.303294e-02 - 6.000000e-01 -2.605717e-01 -8.287018e-01 9.458206e-02 - 6.100000e-01 -2.091040e-01 -8.425135e-01 9.356811e-02 - 6.200000e-01 -1.494329e-01 -8.563252e-01 9.034444e-02 - 6.300000e-01 -8.705466e-02 -8.701369e-01 8.590452e-02 - 6.400000e-01 -2.755745e-02 -8.839486e-01 8.171553e-02 - 6.500000e-01 2.372868e-02 -8.977603e-01 7.931299e-02 - 6.600000e-01 6.206366e-02 -9.115720e-01 7.962749e-02 - 6.700000e-01 8.359014e-02 -9.253837e-01 8.244920e-02 - 6.800000e-01 8.556789e-02 -9.391954e-01 8.658046e-02 - 6.900000e-01 6.653458e-02 -9.530071e-01 9.051104e-02 - 7.000000e-01 2.638255e-02 -9.668188e-01 9.300732e-02 - 7.100000e-01 -3.365350e-02 -9.806305e-01 9.339048e-02 - 7.200000e-01 -1.110967e-01 -9.944422e-01 9.161189e-02 - 7.300000e-01 -2.024086e-01 -1.008254e+00 8.823550e-02 - 7.400000e-01 -3.032383e-01 -1.022066e+00 8.434109e-02 - 7.500000e-01 -4.087215e-01 -1.035877e+00 8.127899e-02 - 7.600000e-01 -5.138097e-01 -1.049689e+00 8.019975e-02 - 7.700000e-01 -6.136058e-01 -1.063501e+00 8.149425e-02 - 7.800000e-01 -7.036833e-01 -1.077312e+00 8.457797e-02 - 7.900000e-01 -7.803670e-01 -1.091124e+00 8.824255e-02 - 8.000000e-01 -8.409562e-01 -1.104936e+00 9.123004e-02 - 8.100000e-01 -8.838756e-01 -1.118747e+00 9.263856e-02 - 8.200000e-01 -9.087437e-01 -1.132559e+00 9.209884e-02 - 8.300000e-01 -9.163567e-01 -1.146371e+00 8.981209e-02 - 8.400000e-01 -9.085893e-01 -1.160183e+00 8.650416e-02 - 8.500000e-01 -8.882216e-01 -1.173994e+00 8.327654e-02 - 8.600000e-01 -8.587063e-01 -1.187806e+00 8.129051e-02 - 8.700000e-01 -8.238944e-01 -1.201618e+00 8.129498e-02 - 8.800000e-01 -7.877398e-01 -1.215429e+00 8.324441e-02 - 8.900000e-01 -7.540061e-01 -1.229241e+00 8.633665e-02 - 9.000000e-01 -7.259969e-01 -1.243053e+00 8.943578e-02 - 9.100000e-01 -7.063286e-01 -1.256864e+00 9.152907e-02 - 9.200000e-01 -6.967632e-01 -1.270676e+00 9.200378e-02 - 9.300000e-01 -6.981108e-01 -1.284488e+00 9.075509e-02 - 9.400000e-01 -7.102095e-01 -1.298300e+00 8.818933e-02 - 9.500000e-01 -7.319798e-01 -1.312111e+00 8.513983e-02 - 9.600000e-01 -7.615502e-01 -1.325923e+00 8.266016e-02 - 9.700000e-01 -7.964408e-01 -1.339735e+00 8.166394e-02 - 9.800000e-01 -8.337897e-01 -1.353546e+00 8.251468e-02 - 9.900000e-01 -8.706036e-01 -1.367358e+00 8.484194e-02 - 1.000000e-00 -9.040117e-01 -1.381170e+00 8.774748e-02 - 1.010000e+00 -9.315033e-01 -1.394981e+00 9.021996e-02 - 1.020000e+00 -9.511296e-01 -1.408793e+00 9.148261e-02 - 1.030000e+00 -9.616553e-01 -1.422605e+00 9.117828e-02 - 1.040000e+00 -9.626475e-01 -1.436417e+00 8.942710e-02 - 1.050000e+00 -9.544971e-01 -1.450228e+00 8.679399e-02 - 1.060000e+00 -9.383712e-01 -1.464040e+00 8.415952e-02 - 1.070000e+00 -9.161027e-01 -1.477852e+00 8.246149e-02 - 1.080000e+00 -8.900263e-01 -1.491663e+00 8.233013e-02 - 1.090000e+00 -8.627749e-01 -1.505475e+00 8.378993e-02 - 1.100000e+00 -8.370557e-01 -1.519287e+00 8.625490e-02 - 1.110000e+00 -8.154227e-01 -1.533098e+00 8.882170e-02 - 1.120000e+00 -8.000647e-01 -1.546910e+00 9.063428e-02 - 1.130000e+00 -7.926282e-01 -1.560722e+00 9.113887e-02 - 1.140000e+00 -7.940862e-01 -1.574533e+00 9.020245e-02 - 1.150000e+00 -8.046667e-01 -1.588345e+00 8.812929e-02 - 1.160000e+00 -8.238427e-01 -1.602157e+00 8.559113e-02 - 1.170000e+00 -8.503875e-01 -1.615969e+00 8.345275e-02 - 1.180000e+00 -8.824866e-01 -1.629780e+00 8.248185e-02 - 1.190000e+00 -9.178991e-01 -1.643592e+00 8.302436e-02 - 1.200000e+00 -9.541530e-01 -1.657404e+00 8.484068e-02 - 1.210000e+00 -9.887581e-01 -1.671215e+00 8.723378e-02 - 1.220000e+00 -1.019420e+00 -1.685027e+00 8.936506e-02 - 1.230000e+00 -1.044233e+00 -1.698839e+00 9.055378e-02 - 1.240000e+00 -1.061845e+00 -1.712650e+00 9.045794e-02 - 1.250000e+00 -1.071566e+00 -1.726462e+00 8.914106e-02 - 1.260000e+00 -1.073431e+00 -1.740274e+00 8.704942e-02 - 1.270000e+00 -1.068188e+00 -1.754086e+00 8.489959e-02 - 1.280000e+00 -1.057242e+00 -1.767897e+00 8.346229e-02 - 1.290000e+00 -1.042527e+00 -1.781709e+00 8.327095e-02 - 1.300000e+00 -1.026351e+00 -1.795521e+00 8.438368e-02 - 1.310000e+00 -1.011191e+00 -1.809332e+00 8.636090e-02 - 1.320000e+00 -9.994919e-01 -1.823144e+00 8.847613e-02 - 1.330000e+00 -9.934586e-01 -1.836956e+00 9.000844e-02 - 1.340000e+00 -9.948682e-01 -1.850767e+00 9.047021e-02 - 1.350000e+00 -1.004922e+00 -1.864579e+00 8.972635e-02 - 1.360000e+00 -1.024143e+00 -1.878391e+00 8.801881e-02 - 1.370000e+00 -1.052329e+00 -1.892203e+00 8.590676e-02 - 1.380000e+00 -1.088569e+00 -1.906014e+00 8.411382e-02 - 1.390000e+00 -1.131312e+00 -1.919826e+00 8.328369e-02 - 1.400000e+00 -1.178493e+00 -1.933638e+00 8.371558e-02 - 1.410000e+00 -1.227697e+00 -1.947449e+00 8.522786e-02 - 1.420000e+00 -1.276352e+00 -1.961261e+00 8.724927e-02 - 1.430000e+00 -1.321931e+00 -1.975073e+00 8.906920e-02 - 1.440000e+00 -1.362151e+00 -1.988884e+00 9.009276e-02 - 1.450000e+00 -1.395148e+00 -2.002696e+00 9.000846e-02 - 1.460000e+00 -1.419612e+00 -2.016508e+00 8.885776e-02 - 1.470000e+00 -1.434881e+00 -2.030319e+00 8.702023e-02 - 1.480000e+00 -1.440976e+00 -2.044131e+00 8.511516e-02 - 1.490000e+00 -1.438578e+00 -2.057943e+00 8.381334e-02 - 1.500000e+00 -1.428952e+00 -2.071755e+00 8.358812e-02 - 1.510000e+00 -1.413823e+00 -2.085566e+00 8.451113e-02 - 1.520000e+00 -1.395219e+00 -2.099378e+00 8.622309e-02 - 1.530000e+00 -1.375288e+00 -2.113190e+00 8.810063e-02 - 1.540000e+00 -1.356109e+00 -2.127001e+00 8.950526e-02 - 1.550000e+00 -1.339521e+00 -2.140813e+00 8.998983e-02 - 1.560000e+00 -1.326967e+00 -2.154625e+00 8.941412e-02 - 1.570000e+00 -1.319389e+00 -2.168436e+00 8.797326e-02 - 1.580000e+00 -1.317160e+00 -2.182248e+00 8.614643e-02 - 1.590000e+00 -1.320081e+00 -2.196060e+00 8.456224e-02 - 1.600000e+00 -1.327421e+00 -2.209872e+00 8.378773e-02 - 1.610000e+00 -1.338016e+00 -2.223683e+00 8.410190e-02 - 1.620000e+00 -1.350401e+00 -2.237495e+00 8.537324e-02 - 1.630000e+00 -1.362974e+00 -2.251307e+00 8.712414e-02 - 1.640000e+00 -1.374170e+00 -2.265118e+00 8.873653e-02 - 1.650000e+00 -1.382635e+00 -2.278930e+00 8.967598e-02 - 1.660000e+00 -1.387368e+00 -2.292742e+00 8.964903e-02 - 1.670000e+00 -1.387843e+00 -2.306553e+00 8.867411e-02 - 1.680000e+00 -1.384077e+00 -2.320365e+00 8.707293e-02 - 1.690000e+00 -1.376637e+00 -2.334177e+00 8.538419e-02 - 1.700000e+00 -1.366606e+00 -2.347989e+00 8.419842e-02 - 1.710000e+00 -1.355480e+00 -2.361800e+00 8.394229e-02 - 1.720000e+00 -1.345031e+00 -2.375612e+00 8.470005e-02 - 1.730000e+00 -1.337123e+00 -2.389424e+00 8.617890e-02 - 1.740000e+00 -1.333527e+00 -2.403235e+00 8.784186e-02 - 1.750000e+00 -1.335716e+00 -2.417047e+00 8.912123e-02 - 1.760000e+00 -1.344696e+00 -2.430859e+00 8.960623e-02 - 1.770000e+00 -1.360861e+00 -2.444670e+00 8.915473e-02 - 1.780000e+00 -1.383901e+00 -2.458482e+00 8.792463e-02 - 1.790000e+00 -1.412776e+00 -2.472294e+00 8.633026e-02 - 1.800000e+00 -1.445754e+00 -2.486105e+00 8.492298e-02 - 1.810000e+00 -1.480514e+00 -2.499917e+00 8.420620e-02 - 1.820000e+00 -1.514312e+00 -2.513729e+00 8.443860e-02 - 1.830000e+00 -1.544202e+00 -2.527541e+00 8.552365e-02 - 1.840000e+00 -1.567278e+00 -2.541352e+00 8.705601e-02 - 1.850000e+00 -1.580939e+00 -2.555164e+00 8.849338e-02 - 1.860000e+00 -1.583140e+00 -2.568976e+00 8.935436e-02 - 1.870000e+00 -1.572609e+00 -2.582787e+00 8.936496e-02 - 1.880000e+00 -1.549013e+00 -2.596599e+00 8.852906e-02 - 1.890000e+00 -1.513057e+00 -2.610411e+00 8.712423e-02 - 1.900000e+00 -1.466490e+00 -2.624222e+00 8.562504e-02 - 1.910000e+00 -1.412034e+00 -2.638034e+00 8.455578e-02 - 1.920000e+00 -1.353220e+00 -2.651846e+00 8.430059e-02 - 1.930000e+00 -1.294150e+00 -2.665658e+00 8.494598e-02 - 1.940000e+00 -1.239192e+00 -2.679469e+00 8.624521e-02 - 1.950000e+00 -1.192639e+00 -2.693281e+00 8.772760e-02 - 1.960000e+00 -1.158358e+00 -2.707093e+00 8.888395e-02 - 1.970000e+00 -1.139441e+00 -2.720904e+00 8.933725e-02 - 1.980000e+00 -1.137915e+00 -2.734716e+00 8.894918e-02 - 1.990000e+00 -1.154511e+00 -2.748528e+00 8.785320e-02 - 2.000000e+00 -1.188531e+00 -2.762339e+00 8.641699e-02 - 2.010000e+00 -1.237823e+00 -2.776151e+00 8.513478e-02 - 2.020000e+00 -1.298870e+00 -2.789963e+00 8.446166e-02 - 2.030000e+00 -1.366998e+00 -2.803775e+00 8.463800e-02 - 2.040000e+00 -1.436686e+00 -2.817586e+00 8.558855e-02 - 2.050000e+00 -1.501962e+00 -2.831398e+00 8.695755e-02 - 2.060000e+00 -1.556856e+00 -2.845210e+00 8.825708e-02 - 2.070000e+00 -1.595879e+00 -2.859021e+00 8.904528e-02 - 2.080000e+00 -1.614491e+00 -2.872833e+00 8.906364e-02 - 2.090000e+00 -1.609514e+00 -2.886645e+00 8.830655e-02 - 2.100000e+00 -1.579460e+00 -2.900456e+00 8.702107e-02 - 2.110000e+00 -1.524741e+00 -2.914268e+00 8.563829e-02 - 2.120000e+00 -1.447736e+00 -2.928080e+00 8.463963e-02 - 2.130000e+00 -1.352693e+00 -2.941891e+00 8.438444e-02 - 2.140000e+00 -1.245484e+00 -2.955703e+00 8.496517e-02 - 2.150000e+00 -1.133191e+00 -2.969515e+00 8.616936e-02 - 2.160000e+00 -1.023574e+00 -2.983327e+00 8.757206e-02 - 2.170000e+00 -9.244251e-01 -2.997138e+00 8.870195e-02 - 2.180000e+00 -8.428719e-01 -3.010950e+00 8.920000e-02 - 2.190000e+00 -7.846657e-01 -3.024762e+00 8.892219e-02 - 2.200000e+00 -7.535071e-01 -3.038573e+00 8.797447e-02 - 2.210000e+00 -7.504647e-01 -3.052385e+00 8.668116e-02 - 2.220000e+00 -7.735306e-01 -3.066197e+00 8.548894e-02 - 2.230000e+00 -8.173576e-01 -3.080008e+00 8.481846e-02 - 2.240000e+00 -8.732071e-01 -3.093820e+00 8.490579e-02 - 2.250000e+00 -9.291271e-01 -3.107632e+00 8.570642e-02 - 2.260000e+00 -9.703641e-01 -3.121444e+00 8.691730e-02 - 2.270000e+00 -9.799987e-01 -3.135255e+00 8.810312e-02 - 2.280000e+00 -9.397761e-01 -3.149067e+00 8.885701e-02 - 2.290000e+00 -8.310933e-01 -3.162879e+00 8.893019e-02 - 2.300000e+00 -6.360900e-01 -3.176690e+00 8.830113e-02 - 2.310000e+00 -3.387799e-01 -3.190502e+00 8.717917e-02 - 2.320000e+00 7.384109e-02 -3.204314e+00 8.594395e-02 - 2.330000e+00 6.107803e-01 -3.218125e+00 8.502589e-02 - 2.340000e+00 1.276191e+00 -3.231937e+00 8.475268e-02 - 2.350000e+00 2.068731e+00 -3.245749e+00 8.521931e-02 - 2.360000e+00 2.981181e+00 -3.259561e+00 8.624936e-02 - 2.370000e+00 4.000357e+00 -3.273372e+00 8.747046e-02 - 2.380000e+00 5.107337e+00 -3.287184e+00 8.845949e-02 - 2.390000e+00 6.277992e+00 -3.300996e+00 8.888735e-02 - 2.400000e+00 7.483803e+00 -3.314807e+00 8.861696e-02 - 2.410000e+00 8.692939e+00 -3.328619e+00 8.773945e-02 - 2.420000e+00 9.871525e+00 -3.342431e+00 8.654753e-02 - 2.430000e+00 1.098505e+01 -3.356242e+00 8.544831e-02 - 2.440000e+00 1.199985e+01 -3.370054e+00 8.482790e-02 - 2.450000e+00 1.288455e+01 -3.383866e+00 8.490680e-02 - 2.460000e+00 1.361146e+01 -3.397678e+00 8.565094e-02 - 2.470000e+00 1.415774e+01 -3.411489e+00 8.678792e-02 - 2.480000e+00 1.450644e+01 -3.425301e+00 8.791879e-02 - 2.490000e+00 1.464718e+01 -3.439113e+00 8.866444e-02 - 2.500000e+00 1.457658e+01 -3.452924e+00 8.878714e-02 - 2.510000e+00 1.429830e+01 -3.466736e+00 8.825730e-02 - 2.520000e+00 1.382281e+01 -3.480548e+00 8.725920e-02 - 2.530000e+00 1.316686e+01 -3.494359e+00 8.613645e-02 - 2.540000e+00 1.235258e+01 -3.508171e+00 8.528323e-02 - 2.550000e+00 1.140650e+01 -3.521983e+00 8.500491e-02 - 2.560000e+00 1.035826e+01 -3.535794e+00 8.539895e-02 - 2.570000e+00 9.239323e+00 -3.549606e+00 8.631613e-02 - 2.580000e+00 8.081607e+00 -3.563418e+00 8.742391e-02 - 2.590000e+00 6.916163e+00 -3.577230e+00 8.833600e-02 - 2.600000e+00 5.771973e+00 -3.591041e+00 8.874584e-02 - 2.610000e+00 4.674897e+00 -3.604853e+00 8.852008e-02 - 2.620000e+00 3.646830e+00 -3.618665e+00 8.773500e-02 - 2.630000e+00 2.705100e+00 -3.632476e+00 8.665363e-02 - 2.640000e+00 1.862122e+00 -3.646288e+00 8.564608e-02 - 2.650000e+00 1.125307e+00 -3.660100e+00 8.506583e-02 - 2.660000e+00 4.972252e-01 -3.673911e+00 8.511794e-02 - 2.670000e+00 -2.400927e-02 -3.687723e+00 8.577693e-02 - 2.680000e+00 -4.441723e-01 -3.701535e+00 8.679855e-02 - 2.690000e+00 -7.722150e-01 -3.715347e+00 8.781860e-02 - 2.700000e+00 -1.019459e+00 -3.729158e+00 8.848654e-02 - 2.710000e+00 -1.198748e+00 -3.742970e+00 8.857941e-02 - 2.720000e+00 -1.323610e+00 -3.756782e+00 8.806668e-02 - 2.730000e+00 -1.407472e+00 -3.770593e+00 8.711793e-02 - 2.740000e+00 -1.462967e+00 -3.784405e+00 8.605324e-02 - 2.750000e+00 -1.501372e+00 -3.798217e+00 8.524228e-02 - 2.760000e+00 -1.532185e+00 -3.812028e+00 8.497442e-02 - 2.770000e+00 -1.562860e+00 -3.825840e+00 8.534686e-02 - 2.780000e+00 -1.598702e+00 -3.839652e+00 8.622582e-02 - 2.790000e+00 -1.642903e+00 -3.853464e+00 8.730239e-02 - 2.800000e+00 -1.696711e+00 -3.867275e+00 8.821161e-02 - 2.810000e+00 -1.759700e+00 -3.881087e+00 8.865812e-02 - 2.820000e+00 -1.830120e+00 -3.894899e+00 8.850613e-02 - 2.830000e+00 -1.905285e+00 -3.908710e+00 8.781616e-02 - 2.840000e+00 -1.981979e+00 -3.922522e+00 8.682582e-02 - 2.850000e+00 -2.056843e+00 -3.936334e+00 8.587719e-02 - 2.860000e+00 -2.126718e+00 -3.950145e+00 8.530316e-02 - 2.870000e+00 -2.188935e+00 -3.963957e+00 8.530532e-02 - 2.880000e+00 -2.241518e+00 -3.977769e+00 8.587504e-02 - 2.890000e+00 -2.283314e+00 -3.991580e+00 8.679888e-02 - 2.900000e+00 -2.314031e+00 -4.005392e+00 8.774513e-02 - 2.910000e+00 -2.334204e+00 -4.019204e+00 8.838627e-02 - 2.920000e+00 -2.345096e+00 -4.033016e+00 8.850696e-02 - 2.930000e+00 -2.348533e+00 -4.046827e+00 8.806776e-02 - 2.940000e+00 -2.346723e+00 -4.060639e+00 8.721507e-02 - 2.950000e+00 -2.342043e+00 -4.074451e+00 8.623706e-02 - 2.960000e+00 -2.336835e+00 -4.088262e+00 8.547181e-02 - 2.970000e+00 -2.333219e+00 -4.102074e+00 8.518872e-02 - 2.980000e+00 -2.332935e+00 -4.115886e+00 8.548554e-02 - 2.990000e+00 -2.337236e+00 -4.129697e+00 8.624986e-02 - 3.000000e+00 -2.346817e+00 -4.143509e+00 8.720597e-02 - 3.010000e+00 -2.361806e+00 -4.157321e+00 8.802122e-02 - 3.020000e+00 -2.381792e+00 -4.171133e+00 8.842215e-02 - 3.030000e+00 -2.405909e+00 -4.184944e+00 8.828001e-02 - 3.040000e+00 -2.432939e+00 -4.198756e+00 8.764730e-02 - 3.050000e+00 -2.461444e+00 -4.212568e+00 8.674126e-02 - 3.060000e+00 -2.489911e+00 -4.226379e+00 8.587672e-02 - 3.070000e+00 -2.516886e+00 -4.240191e+00 8.536071e-02 - 3.080000e+00 -2.541103e+00 -4.254003e+00 8.537964e-02 - 3.090000e+00 -2.561584e+00 -4.267814e+00 8.592621e-02 - 3.100000e+00 -2.577712e+00 -4.281626e+00 8.680329e-02 - 3.110000e+00 -2.589266e+00 -4.295438e+00 8.770250e-02 - 3.120000e+00 -2.596420e+00 -4.309250e+00 8.831725e-02 - 3.130000e+00 -2.599709e+00 -4.323061e+00 8.844402e-02 - 3.140000e+00 -2.599957e+00 -4.336873e+00 8.804325e-02 - 3.150000e+00 -2.598188e+00 -4.350685e+00 8.724975e-02 - 3.160000e+00 -2.595516e+00 -4.364496e+00 8.633174e-02 - 3.170000e+00 -2.593021e+00 -4.378308e+00 8.560513e-02 - 3.180000e+00 -2.591636e+00 -4.392120e+00 8.532290e-02 - 3.190000e+00 -2.592035e+00 -4.405931e+00 8.557901e-02 - 3.200000e+00 -2.594543e+00 -4.419743e+00 8.627157e-02 - 3.210000e+00 -2.599066e+00 -4.433555e+00 8.714478e-02 - 3.220000e+00 -2.605049e+00 -4.447366e+00 8.788730e-02 - 3.230000e+00 -2.611468e+00 -4.461178e+00 8.824143e-02 - 3.240000e+00 -2.616842e+00 -4.474990e+00 8.808516e-02 - 3.250000e+00 -2.619286e+00 -4.488802e+00 8.746838e-02 - 3.260000e+00 -2.616581e+00 -4.502613e+00 8.659820e-02 - 3.270000e+00 -2.606259e+00 -4.516425e+00 8.577550e-02 - 3.280000e+00 -2.585719e+00 -4.530237e+00 8.529449e-02 - 3.290000e+00 -2.552333e+00 -4.544048e+00 8.533489e-02 - 3.300000e+00 -2.503569e+00 -4.557860e+00 8.589126e-02 - 3.310000e+00 -2.437100e+00 -4.571672e+00 8.677526e-02 - 3.320000e+00 -2.350917e+00 -4.585483e+00 8.768926e-02 - 3.330000e+00 -2.243420e+00 -4.599295e+00 8.833407e-02 - 3.340000e+00 -2.113503e+00 -4.613107e+00 8.850678e-02 - 3.350000e+00 -1.960618e+00 -4.626919e+00 8.816083e-02 - 3.360000e+00 -1.784825e+00 -4.640730e+00 8.741788e-02 - 3.370000e+00 -1.586825e+00 -4.654542e+00 8.653083e-02 - 3.380000e+00 -1.367979e+00 -4.668354e+00 8.580368e-02 - 3.390000e+00 -1.130302e+00 -4.682165e+00 8.548686e-02 - 3.400000e+00 -8.764571e-01 -4.695977e+00 8.568406e-02 - 3.410000e+00 -6.097196e-01 -4.709789e+00 8.631281e-02 - 3.420000e+00 -3.339377e-01 -4.723600e+00 8.713910e-02 - 3.430000e+00 -5.347346e-02 -4.737412e+00 8.786787e-02 - 3.440000e+00 2.268704e-01 -4.751224e+00 8.824708e-02 - 3.450000e+00 5.019383e-01 -4.765036e+00 8.814830e-02 - 3.460000e+00 7.663258e-01 -4.778847e+00 8.760434e-02 - 3.470000e+00 1.014500e+00 -4.792659e+00 8.679847e-02 - 3.480000e+00 1.240932e+00 -4.806471e+00 8.600717e-02 - 3.490000e+00 1.440250e+00 -4.820282e+00 8.550784e-02 - 3.500000e+00 1.607392e+00 -4.834094e+00 8.547816e-02 - 3.510000e+00 1.737778e+00 -4.847906e+00 8.592753e-02 - 3.520000e+00 1.827471e+00 -4.861717e+00 8.669413e-02 - 3.530000e+00 1.873343e+00 -4.875529e+00 8.750884e-02 - 3.540000e+00 1.873221e+00 -4.889341e+00 8.809407e-02 - 3.550000e+00 1.826015e+00 -4.903152e+00 8.825661e-02 - 3.560000e+00 1.731819e+00 -4.916964e+00 8.794676e-02 - 3.570000e+00 1.591965e+00 -4.930776e+00 8.727197e-02 - 3.580000e+00 1.409047e+00 -4.944588e+00 8.646361e-02 - 3.590000e+00 1.186882e+00 -4.958399e+00 8.580261e-02 - 3.600000e+00 9.304277e-01 -4.972211e+00 8.552186e-02 - 3.610000e+00 6.456414e-01 -4.986023e+00 8.571906e-02 - 3.620000e+00 3.392945e-01 -4.999834e+00 8.631881e-02 - 3.630000e+00 1.873856e-02 -5.013646e+00 8.710326e-02 - 3.640000e+00 -3.083619e-01 -5.027458e+00 8.779520e-02 - 3.650000e+00 -6.343206e-01 -5.041269e+00 8.815575e-02 - 3.660000e+00 -9.517301e-01 -5.055081e+00 8.806124e-02 - 3.670000e+00 -1.253756e+00 -5.068893e+00 8.754045e-02 - 3.680000e+00 -1.534413e+00 -5.082705e+00 8.676573e-02 - 3.690000e+00 -1.788795e+00 -5.096516e+00 8.599990e-02 - 3.700000e+00 -2.013266e+00 -5.110328e+00 8.550922e-02 - 3.710000e+00 -2.205580e+00 -5.124140e+00 8.546775e-02 - 3.720000e+00 -2.364928e+00 -5.137951e+00 8.589091e-02 - 3.730000e+00 -2.491921e+00 -5.151763e+00 8.663012e-02 - 3.740000e+00 -2.588479e+00 -5.165575e+00 8.743106e-02 - 3.750000e+00 -2.657671e+00 -5.179386e+00 8.802674e-02 - 3.760000e+00 -2.703479e+00 -5.193198e+00 8.822663e-02 - 3.770000e+00 -2.730520e+00 -5.207010e+00 8.797479e-02 - 3.780000e+00 -2.743737e+00 -5.220822e+00 8.736478e-02 - 3.790000e+00 -2.748083e+00 -5.234633e+00 8.660995e-02 - 3.800000e+00 -2.748209e+00 -5.248445e+00 8.597450e-02 - 3.810000e+00 -2.748188e+00 -5.262257e+00 8.568213e-02 - 3.820000e+00 -2.751276e+00 -5.276068e+00 8.583325e-02 - 3.830000e+00 -2.759752e+00 -5.289880e+00 8.636683e-02 - 3.840000e+00 -2.774817e+00 -5.303692e+00 8.708555e-02 - 3.850000e+00 -2.796588e+00 -5.317503e+00 8.773157e-02 - 3.860000e+00 -2.824158e+00 -5.331315e+00 8.807818e-02 - 3.870000e+00 -2.855748e+00 -5.345127e+00 8.800391e-02 - 3.880000e+00 -2.888908e+00 -5.358939e+00 8.752973e-02 - 3.890000e+00 -2.920779e+00 -5.372750e+00 8.681247e-02 - 3.900000e+00 -2.948371e+00 -5.386562e+00 8.609591e-02 - 3.910000e+00 -2.968861e+00 -5.400374e+00 8.562970e-02 - 3.920000e+00 -2.979857e+00 -5.414185e+00 8.557964e-02 - 3.930000e+00 -2.979632e+00 -5.427997e+00 8.596450e-02 - 3.940000e+00 -2.967290e+00 -5.441809e+00 8.664908e-02 - 3.950000e+00 -2.942857e+00 -5.455620e+00 8.739672e-02 - 3.960000e+00 -2.907272e+00 -5.469432e+00 8.795581e-02 - 3.970000e+00 -2.862300e+00 -5.483244e+00 8.814437e-02 - 3.980000e+00 -2.810334e+00 -5.497055e+00 8.790624e-02 - 3.990000e+00 -2.754132e+00 -5.510867e+00 8.732687e-02 - 4.000000e+00 -2.696475e+00 -5.524679e+00 8.660621e-02 - 4.010000e+00 -2.639789e+00 -5.538491e+00 8.599417e-02 - 4.020000e+00 -2.585754e+00 -5.552302e+00 8.570445e-02 - 4.030000e+00 -2.534926e+00 -5.566114e+00 8.583588e-02 - 4.040000e+00 -2.486404e+00 -5.579926e+00 8.633496e-02 - 4.050000e+00 -2.437580e+00 -5.593737e+00 8.701785e-02 - 4.060000e+00 -2.383991e+00 -5.607549e+00 8.764065e-02 - 4.070000e+00 -2.319291e+00 -5.621361e+00 8.798621e-02 - 4.080000e+00 -2.235371e+00 -5.635172e+00 8.793541e-02 - 4.090000e+00 -2.122615e+00 -5.648984e+00 8.750393e-02 - 4.100000e+00 -1.970297e+00 -5.662796e+00 8.683711e-02 - 4.110000e+00 -1.767102e+00 -5.676608e+00 8.616432e-02 - 4.120000e+00 -1.501749e+00 -5.690419e+00 8.572243e-02 - 4.130000e+00 -1.163683e+00 -5.704231e+00 8.567084e-02 - 4.140000e+00 -7.438005e-01 -5.718043e+00 8.603091e-02 - 4.150000e+00 -2.351580e-01 -5.731854e+00 8.667774e-02 - 4.160000e+00 3.663656e-01 -5.745666e+00 8.738832e-02 - 4.170000e+00 1.061510e+00 -5.759478e+00 8.792278e-02 - 4.180000e+00 1.847208e+00 -5.773289e+00 8.810524e-02 - 4.190000e+00 2.716329e+00 -5.787101e+00 8.787868e-02 - 4.200000e+00 3.657618e+00 -5.800913e+00 8.732138e-02 - 4.210000e+00 4.655841e+00 -5.814725e+00 8.662233e-02 - 4.220000e+00 5.692133e+00 -5.828536e+00 8.602054e-02 - 4.230000e+00 6.744555e+00 -5.842348e+00 8.572319e-02 - 4.240000e+00 7.788825e+00 -5.856160e+00 8.583002e-02 - 4.250000e+00 8.799190e+00 -5.869971e+00 8.629595e-02 - 4.260000e+00 9.749408e+00 -5.883783e+00 8.694977e-02 - 4.270000e+00 1.061379e+01 -5.897595e+00 8.755959e-02 - 4.280000e+00 1.136822e+01 -5.911406e+00 8.791545e-02 - 4.290000e+00 1.199120e+01 -5.925218e+00 8.789847e-02 - 4.300000e+00 1.246467e+01 -5.939030e+00 8.751740e-02 - 4.310000e+00 1.277484e+01 -5.952841e+00 8.690514e-02 - 4.320000e+00 1.291270e+01 -5.966653e+00 8.627632e-02 - 4.330000e+00 1.287439e+01 -5.980465e+00 8.585518e-02 - 4.340000e+00 1.266135e+01 -5.994277e+00 8.579510e-02 - 4.350000e+00 1.228021e+01 -6.008088e+00 8.612033e-02 - 4.360000e+00 1.174245e+01 -6.021900e+00 8.671645e-02 - 4.370000e+00 1.106387e+01 -6.035712e+00 8.737418e-02 - 4.380000e+00 1.026392e+01 -6.049523e+00 8.786556e-02 - 4.390000e+00 9.364814e+00 -6.063335e+00 8.802129e-02 - 4.400000e+00 8.390613e+00 -6.077147e+00 8.778446e-02 - 4.410000e+00 7.366263e+00 -6.090958e+00 8.722793e-02 - 4.420000e+00 6.316617e+00 -6.104770e+00 8.653223e-02 - 4.430000e+00 5.265521e+00 -6.118582e+00 8.592841e-02 - 4.440000e+00 4.234999e+00 -6.132394e+00 8.561983e-02 - 4.450000e+00 3.244559e+00 -6.146205e+00 8.570877e-02 - 4.460000e+00 2.310668e+00 -6.160017e+00 8.615855e-02 - 4.470000e+00 1.446384e+00 -6.173829e+00 8.680890e-02 - 4.480000e+00 6.611823e-01 -6.187640e+00 8.743706e-02 - 4.490000e+00 -3.905441e-02 -6.201452e+00 8.783681e-02 - 4.500000e+00 -6.518808e-01 -6.215264e+00 8.788586e-02 - 4.510000e+00 -1.177993e+00 -6.229075e+00 8.758252e-02 - 4.520000e+00 -1.620823e+00 -6.242887e+00 8.704418e-02 - 4.530000e+00 -1.986045e+00 -6.256699e+00 8.646856e-02 - 4.540000e+00 -2.281044e+00 -6.270511e+00 8.606669e-02 - 4.550000e+00 -2.514362e+00 -6.284322e+00 8.598740e-02 - 4.560000e+00 -2.695158e+00 -6.298134e+00 8.626153e-02 - 4.570000e+00 -2.832719e+00 -6.311946e+00 8.679056e-02 - 4.580000e+00 -2.936024e+00 -6.325757e+00 8.738503e-02 - 4.590000e+00 -3.013391e+00 -6.339569e+00 8.783451e-02 - 4.600000e+00 -3.072212e+00 -6.353381e+00 8.798044e-02 - 4.610000e+00 -3.118767e+00 -6.367192e+00 8.776777e-02 - 4.620000e+00 -3.158134e+00 -6.381004e+00 8.726241e-02 - 4.630000e+00 -3.194163e+00 -6.394816e+00 8.663102e-02 - 4.640000e+00 -3.229516e+00 -6.408627e+00 8.608727e-02 - 4.650000e+00 -3.265756e+00 -6.422439e+00 8.581849e-02 - 4.660000e+00 -3.303465e+00 -6.436251e+00 8.591708e-02 - 4.670000e+00 -3.342377e+00 -6.450063e+00 8.634536e-02 - 4.680000e+00 -3.381515e+00 -6.463874e+00 8.695011e-02 - 4.690000e+00 -3.419326e+00 -6.477686e+00 8.751985e-02 - 4.700000e+00 -3.453792e+00 -6.491498e+00 8.785941e-02 - 4.710000e+00 -3.482530e+00 -6.505309e+00 8.785407e-02 - 4.720000e+00 -3.502873e+00 -6.519121e+00 8.750507e-02 - 4.730000e+00 -3.511939e+00 -6.532933e+00 8.692868e-02 - 4.740000e+00 -3.506682e+00 -6.546744e+00 8.631937e-02 - 4.750000e+00 -3.483957e+00 -6.560556e+00 8.588540e-02 - 4.760000e+00 -3.440576e+00 -6.574368e+00 8.577557e-02 - 4.770000e+00 -3.373385e+00 -6.588180e+00 8.602434e-02 - 4.780000e+00 -3.279357e+00 -6.601991e+00 8.653953e-02 - 4.790000e+00 -3.155710e+00 -6.615803e+00 8.713833e-02 - 4.800000e+00 -3.000036e+00 -6.629615e+00 8.761468e-02 - 4.810000e+00 -2.810458e+00 -6.643426e+00 8.781026e-02 - 4.820000e+00 -2.585794e+00 -6.657238e+00 8.766528e-02 - 4.830000e+00 -2.325724e+00 -6.671050e+00 8.723634e-02 - 4.840000e+00 -2.030943e+00 -6.684861e+00 8.667774e-02 - 4.850000e+00 -1.703304e+00 -6.698673e+00 8.619059e-02 - 4.860000e+00 -1.345909e+00 -6.712485e+00 8.595303e-02 - 4.870000e+00 -9.631702e-01 -6.726297e+00 8.605479e-02 - 4.880000e+00 -5.608041e-01 -6.740108e+00 8.646303e-02 - 4.890000e+00 -1.457638e-01 -6.753920e+00 8.703493e-02 - 4.900000e+00 2.738950e-01 -6.767732e+00 8.757120e-02 - 4.910000e+00 6.892164e-01 -6.781543e+00 8.788676e-02 - 4.920000e+00 1.090608e+00 -6.795355e+00 8.787244e-02 - 4.930000e+00 1.468155e+00 -6.809167e+00 8.752974e-02 - 4.940000e+00 1.811980e+00 -6.822978e+00 8.697063e-02 - 4.950000e+00 2.112617e+00 -6.836790e+00 8.638246e-02 - 4.960000e+00 2.361395e+00 -6.850602e+00 8.596608e-02 - 4.970000e+00 2.550801e+00 -6.864413e+00 8.586518e-02 - 4.980000e+00 2.674816e+00 -6.878225e+00 8.611303e-02 - 4.990000e+00 2.729185e+00 -6.892037e+00 8.661999e-02 - 5.000000e+00 2.711627e+00 -6.905849e+00 8.720766e-02 - 5.010000e+00 2.621959e+00 -6.919660e+00 8.767376e-02 - 5.020000e+00 2.462128e+00 -6.933472e+00 8.786104e-02 - 5.030000e+00 2.236157e+00 -6.947284e+00 8.770755e-02 - 5.040000e+00 1.949990e+00 -6.961095e+00 8.726511e-02 - 5.050000e+00 1.611265e+00 -6.974907e+00 8.668269e-02 - 5.060000e+00 1.229002e+00 -6.988719e+00 8.615816e-02 - 5.070000e+00 8.132488e-01 -7.002530e+00 8.587099e-02 - 5.080000e+00 3.746712e-01 -7.016342e+00 8.591790e-02 - 5.090000e+00 -7.586038e-02 -7.030154e+00 8.627722e-02 - 5.100000e+00 -5.276906e-01 -7.043966e+00 8.681827e-02 - 5.110000e+00 -9.707736e-01 -7.057777e+00 8.735105e-02 - 5.120000e+00 -1.396027e+00 -7.071589e+00 8.769425e-02 - 5.130000e+00 -1.795627e+00 -7.085401e+00 8.773588e-02 - 5.140000e+00 -2.163237e+00 -7.099212e+00 8.746834e-02 - 5.150000e+00 -2.494151e+00 -7.113024e+00 8.698983e-02 - 5.160000e+00 -2.785361e+00 -7.126836e+00 8.647198e-02 - 5.170000e+00 -3.035536e+00 -7.140647e+00 8.610178e-02 - 5.180000e+00 -3.244924e+00 -7.154459e+00 8.601496e-02 - 5.190000e+00 -3.415178e+00 -7.168271e+00 8.624523e-02 - 5.200000e+00 -3.549129e+00 -7.182083e+00 8.671154e-02 - 5.210000e+00 -3.650505e+00 -7.195894e+00 8.724892e-02 - 5.220000e+00 -3.723620e+00 -7.209706e+00 8.766895e-02 - 5.230000e+00 -3.773049e+00 -7.223518e+00 8.782505e-02 - 5.240000e+00 -3.803304e+00 -7.237329e+00 8.766071e-02 - 5.250000e+00 -3.818524e+00 -7.251141e+00 8.722768e-02 - 5.260000e+00 -3.822194e+00 -7.264953e+00 8.667016e-02 - 5.270000e+00 -3.816918e+00 -7.278764e+00 8.617831e-02 - 5.280000e+00 -3.804229e+00 -7.292576e+00 8.592329e-02 - 5.290000e+00 -3.784477e+00 -7.306388e+00 8.599517e-02 - 5.300000e+00 -3.756772e+00 -7.320200e+00 8.636886e-02 - 5.310000e+00 -3.718998e+00 -7.334011e+00 8.691337e-02 - 5.320000e+00 -3.667897e+00 -7.347823e+00 8.744021e-02 - 5.330000e+00 -3.599214e+00 -7.361635e+00 8.776965e-02 - 5.340000e+00 -3.507905e+00 -7.375446e+00 8.779011e-02 - 5.350000e+00 -3.388388e+00 -7.389258e+00 8.749321e-02 - 5.360000e+00 -3.234838e+00 -7.403070e+00 8.697617e-02 - 5.370000e+00 -3.041515e+00 -7.416881e+00 8.641121e-02 - 5.380000e+00 -2.803099e+00 -7.430693e+00 8.598917e-02 - 5.390000e+00 -2.515036e+00 -7.444505e+00 8.585342e-02 - 5.400000e+00 -2.173860e+00 -7.458316e+00 8.604798e-02 - 5.410000e+00 -1.777503e+00 -7.472128e+00 8.650183e-02 - 5.420000e+00 -1.325552e+00 -7.485940e+00 8.705661e-02 - 5.430000e+00 -8.194596e-01 -7.499752e+00 8.752478e-02 - 5.440000e+00 -2.626892e-01 -7.513563e+00 8.775421e-02 - 5.450000e+00 3.392176e-01 -7.527375e+00 8.767696e-02 - 5.460000e+00 9.786512e-01 -7.541187e+00 8.732932e-02 - 5.470000e+00 1.646031e+00 -7.554998e+00 8.683885e-02 - 5.480000e+00 2.329988e+00 -7.568810e+00 8.638176e-02 - 5.490000e+00 3.017633e+00 -7.582622e+00 8.612218e-02 - 5.500000e+00 3.694900e+00 -7.596433e+00 8.615289e-02 - 5.510000e+00 4.346958e+00 -7.610245e+00 8.646102e-02 - 5.520000e+00 4.958674e+00 -7.624057e+00 8.693372e-02 - 5.530000e+00 5.515119e+00 -7.637869e+00 8.740100e-02 - 5.540000e+00 6.002084e+00 -7.651680e+00 8.769710e-02 - 5.550000e+00 6.406594e+00 -7.665492e+00 8.771699e-02 - 5.560000e+00 6.717406e+00 -7.679304e+00 8.745053e-02 - 5.570000e+00 6.925442e+00 -7.693115e+00 8.698579e-02 - 5.580000e+00 7.024169e+00 -7.706927e+00 8.648066e-02 - 5.590000e+00 7.009884e+00 -7.720739e+00 8.610998e-02 - 5.600000e+00 6.881897e+00 -7.734550e+00 8.600369e-02 - 5.610000e+00 6.642601e+00 -7.748362e+00 8.619864e-02 - 5.620000e+00 6.297426e+00 -7.762174e+00 8.662450e-02 - 5.630000e+00 5.854665e+00 -7.775986e+00 8.713015e-02 - 5.640000e+00 5.325193e+00 -7.789797e+00 8.753878e-02 - 5.650000e+00 4.722072e+00 -7.803609e+00 8.770900e-02 - 5.660000e+00 4.060080e+00 -7.817421e+00 8.758144e-02 - 5.670000e+00 3.355160e+00 -7.831232e+00 8.719768e-02 - 5.680000e+00 2.623839e+00 -7.845044e+00 8.668744e-02 - 5.690000e+00 1.882618e+00 -7.858856e+00 8.622663e-02 - 5.700000e+00 1.147384e+00 -7.872667e+00 8.597749e-02 - 5.710000e+00 4.328576e-01 -7.886479e+00 8.603025e-02 - 5.720000e+00 -2.478914e-01 -7.900291e+00 8.636931e-02 - 5.730000e+00 -8.838435e-01 -7.914102e+00 8.687907e-02 - 5.740000e+00 -1.466320e+00 -7.927914e+00 8.738655e-02 - 5.750000e+00 -1.989158e+00 -7.941726e+00 8.772229e-02 - 5.760000e+00 -2.448757e+00 -7.955538e+00 8.777674e-02 - 5.770000e+00 -2.844007e+00 -7.969349e+00 8.753466e-02 - 5.780000e+00 -3.176100e+00 -7.983161e+00 8.707946e-02 - 5.790000e+00 -3.448233e+00 -7.996973e+00 8.656641e-02 - 5.800000e+00 -3.665236e+00 -8.010784e+00 8.617139e-02 - 5.810000e+00 -3.833133e+00 -8.024596e+00 8.602990e-02 - 5.820000e+00 -3.958675e+00 -8.038408e+00 8.618804e-02 - 5.830000e+00 -4.048865e+00 -8.052219e+00 8.658593e-02 - 5.840000e+00 -4.110503e+00 -8.066031e+00 8.708082e-02 - 5.850000e+00 -4.149782e+00 -8.079843e+00 8.749955e-02 - 5.860000e+00 -4.171953e+00 -8.093655e+00 8.769861e-02 - 5.870000e+00 -4.181080e+00 -8.107466e+00 8.761101e-02 - 5.880000e+00 -4.179890e+00 -8.121278e+00 8.726695e-02 - 5.890000e+00 -4.169735e+00 -8.135090e+00 8.678365e-02 - 5.900000e+00 -4.150654e+00 -8.148901e+00 8.632682e-02 - 5.910000e+00 -4.121538e+00 -8.162713e+00 8.605422e-02 - 5.920000e+00 -4.080373e+00 -8.176525e+00 8.605936e-02 - 5.930000e+00 -4.024548e+00 -8.190336e+00 8.633734e-02 - 5.940000e+00 -3.951214e+00 -8.204148e+00 8.678737e-02 - 5.950000e+00 -3.857649e+00 -8.217960e+00 8.725091e-02 - 5.960000e+00 -3.741620e+00 -8.231772e+00 8.756870e-02 - 5.970000e+00 -3.601711e+00 -8.245583e+00 8.763482e-02 - 5.980000e+00 -3.437595e+00 -8.259395e+00 8.743080e-02 - 5.990000e+00 -3.250224e+00 -8.273207e+00 8.703087e-02 - 6.000000e+00 -3.041939e+00 -8.287018e+00 8.657745e-02 - 6.010000e+00 -2.816474e+00 -8.300830e+00 8.623311e-02 - 6.020000e+00 -2.578867e+00 -8.314642e+00 8.612316e-02 - 6.030000e+00 -2.335272e+00 -8.328453e+00 8.628953e-02 - 6.040000e+00 -2.092693e+00 -8.342265e+00 8.667500e-02 - 6.050000e+00 -1.858648e+00 -8.356077e+00 8.714473e-02 - 6.060000e+00 -1.640791e+00 -8.369888e+00 8.753548e-02 - 6.070000e+00 -1.446513e+00 -8.383700e+00 8.771242e-02 - 6.080000e+00 -1.282544e+00 -8.397512e+00 8.761380e-02 - 6.090000e+00 -1.154595e+00 -8.411324e+00 8.727067e-02 - 6.100000e+00 -1.067042e+00 -8.425135e+00 8.679705e-02 - 6.110000e+00 -1.022691e+00 -8.438947e+00 8.635272e-02 - 6.120000e+00 -1.022633e+00 -8.452759e+00 8.608880e-02 - 6.130000e+00 -1.066192e+00 -8.466570e+00 8.609374e-02 - 6.140000e+00 -1.150981e+00 -8.480382e+00 8.636059e-02 - 6.150000e+00 -1.273047e+00 -8.494194e+00 8.678994e-02 - 6.160000e+00 -1.427113e+00 -8.508005e+00 8.722702e-02 - 6.170000e+00 -1.606882e+00 -8.521817e+00 8.751718e-02 - 6.180000e+00 -1.805393e+00 -8.535629e+00 8.755858e-02 - 6.190000e+00 -2.015408e+00 -8.549441e+00 8.733548e-02 - 6.200000e+00 -2.229787e+00 -8.563252e+00 8.692355e-02 - 6.210000e+00 -2.441843e+00 -8.577064e+00 8.646565e-02 - 6.220000e+00 -2.645638e+00 -8.590876e+00 8.612434e-02 - 6.230000e+00 -2.836214e+00 -8.604687e+00 8.602490e-02 - 6.240000e+00 -3.009722e+00 -8.618499e+00 8.620926e-02 - 6.250000e+00 -3.163462e+00 -8.632311e+00 8.661987e-02 - 6.260000e+00 -3.295813e+00 -8.646122e+00 8.712074e-02 - 6.270000e+00 -3.406071e+00 -8.659934e+00 8.754630e-02 - 6.280000e+00 -3.494195e+00 -8.673746e+00 8.775802e-02 - 6.290000e+00 -3.560494e+00 -8.687558e+00 8.768946e-02 - 6.300000e+00 -3.605266e+00 -8.701369e+00 8.736689e-02 - 6.310000e+00 -3.628425e+00 -8.715181e+00 8.690065e-02 - 6.320000e+00 -3.629147e+00 -8.728993e+00 8.644948e-02 - 6.330000e+00 -3.605564e+00 -8.742804e+00 8.616701e-02 - 6.340000e+00 -3.554534e+00 -8.756616e+00 8.614766e-02 - 6.350000e+00 -3.471511e+00 -8.770428e+00 8.639233e-02 - 6.360000e+00 -3.350547e+00 -8.784239e+00 8.680872e-02 - 6.370000e+00 -3.184410e+00 -8.798051e+00 8.724599e-02 - 6.380000e+00 -2.964853e+00 -8.811863e+00 8.754876e-02 - 6.390000e+00 -2.683002e+00 -8.825674e+00 8.760987e-02 - 6.400000e+00 -2.329863e+00 -8.839486e+00 8.740504e-02 - 6.410000e+00 -1.896913e+00 -8.853298e+00 8.700040e-02 - 6.420000e+00 -1.376751e+00 -8.867110e+00 8.653120e-02 - 6.430000e+00 -7.637666e-01 -8.880921e+00 8.615719e-02 - 6.440000e+00 -5.478658e-02 -8.894733e+00 8.600743e-02 - 6.450000e+00 7.503419e-01 -8.908545e+00 8.613388e-02 - 6.460000e+00 1.648275e+00 -8.922356e+00 8.649247e-02 - 6.470000e+00 2.631839e+00 -8.936168e+00 8.696004e-02 - 6.480000e+00 3.689864e+00 -8.949980e+00 8.737928e-02 - 6.490000e+00 4.807217e+00 -8.963791e+00 8.761334e-02 - 6.500000e+00 5.965040e+00 -8.977603e+00 8.759051e-02 - 6.510000e+00 7.141184e+00 -8.991415e+00 8.732628e-02 - 6.520000e+00 8.310844e+00 -9.005227e+00 8.691727e-02 - 6.530000e+00 9.447355e+00 -9.019038e+00 8.650892e-02 - 6.540000e+00 1.052313e+01 -9.032850e+00 8.624585e-02 - 6.550000e+00 1.151068e+01 -9.046662e+00 8.622056e-02 - 6.560000e+00 1.238368e+01 -9.060473e+00 8.643989e-02 - 6.570000e+00 1.311803e+01 -9.074285e+00 8.682322e-02 - 6.580000e+00 1.369284e+01 -9.088097e+00 8.723311e-02 - 6.590000e+00 1.409131e+01 -9.101908e+00 8.752513e-02 - 6.600000e+00 1.430143e+01 -9.115720e+00 8.759756e-02 - 6.610000e+00 1.431653e+01 -9.129532e+00 8.742490e-02 - 6.620000e+00 1.413553e+01 -9.143344e+00 8.706581e-02 - 6.630000e+00 1.376303e+01 -9.157155e+00 8.664383e-02 - 6.640000e+00 1.320907e+01 -9.170967e+00 8.630586e-02 - 6.650000e+00 1.248876e+01 -9.184779e+00 8.617074e-02 - 6.660000e+00 1.162158e+01 -9.198590e+00 8.628606e-02 - 6.670000e+00 1.063063e+01 -9.212402e+00 8.661044e-02 - 6.680000e+00 9.541615e+00 -9.226214e+00 8.702918e-02 - 6.690000e+00 8.381888e+00 -9.240025e+00 8.739620e-02 - 6.700000e+00 7.179331e+00 -9.253837e+00 8.758517e-02 - 6.710000e+00 5.961341e+00 -9.267649e+00 8.753185e-02 - 6.720000e+00 4.753851e+00 -9.281461e+00 8.725476e-02 - 6.730000e+00 3.580485e+00 -9.295272e+00 8.684917e-02 - 6.740000e+00 2.461850e+00 -9.309084e+00 8.645577e-02 - 6.750000e+00 1.415025e+00 -9.322896e+00 8.621269e-02 - 6.760000e+00 4.532287e-01 -9.336707e+00 8.620624e-02 - 6.770000e+00 -4.142968e-01 -9.350519e+00 8.643915e-02 - 6.780000e+00 -1.182223e+00 -9.364331e+00 8.682945e-02 - 6.790000e+00 -1.848891e+00 -9.378142e+00 8.724072e-02 - 6.800000e+00 -2.415919e+00 -9.391954e+00 8.753056e-02 - 6.810000e+00 -2.887703e+00 -9.405766e+00 8.759901e-02 - 6.820000e+00 -3.270830e+00 -9.419577e+00 8.742103e-02 - 6.830000e+00 -3.573468e+00 -9.433389e+00 8.705433e-02 - 6.840000e+00 -3.804748e+00 -9.447201e+00 8.662072e-02 - 6.850000e+00 -3.974192e+00 -9.461013e+00 8.626564e-02 - 6.860000e+00 -4.091203e+00 -9.474824e+00 8.610804e-02 - 6.870000e+00 -4.164653e+00 -9.488636e+00 8.619781e-02 - 6.880000e+00 -4.202570e+00 -9.502448e+00 8.649787e-02 - 6.890000e+00 -4.211947e+00 -9.516259e+00 8.689872e-02 - 6.900000e+00 -4.198652e+00 -9.530071e+00 8.725885e-02 - 6.910000e+00 -4.167450e+00 -9.543883e+00 8.745463e-02 - 6.920000e+00 -4.122095e+00 -9.557694e+00 8.742188e-02 - 6.930000e+00 -4.065505e+00 -9.571506e+00 8.717653e-02 - 6.940000e+00 -3.999959e+00 -9.585318e+00 8.680901e-02 - 6.950000e+00 -3.927327e+00 -9.599130e+00 8.645406e-02 - 6.960000e+00 -3.849278e+00 -9.612941e+00 8.624413e-02 - 6.970000e+00 -3.767473e+00 -9.626753e+00 8.626168e-02 - 6.980000e+00 -3.683709e+00 -9.640565e+00 8.650827e-02 - 6.990000e+00 -3.600007e+00 -9.654376e+00 8.690351e-02 - 7.000000e+00 -3.518647e+00 -9.668188e+00 8.731419e-02 - 7.010000e+00 -3.442143e+00 -9.682000e+00 8.760140e-02 - 7.020000e+00 -3.373162e+00 -9.695811e+00 8.766765e-02 - 7.030000e+00 -3.314405e+00 -9.709623e+00 8.748867e-02 - 7.040000e+00 -3.268464e+00 -9.723435e+00 8.712136e-02 - 7.050000e+00 -3.237658e+00 -9.737247e+00 8.668565e-02 - 7.060000e+00 -3.223883e+00 -9.751058e+00 8.632511e-02 - 7.070000e+00 -3.228470e+00 -9.764870e+00 8.615774e-02 - 7.080000e+00 -3.252079e+00 -9.778682e+00 8.623406e-02 - 7.090000e+00 -3.294630e+00 -9.792493e+00 8.651903e-02 - 7.100000e+00 -3.355279e+00 -9.806305e+00 8.690579e-02 - 7.110000e+00 -3.432434e+00 -9.820117e+00 8.725504e-02 - 7.120000e+00 -3.523812e+00 -9.833928e+00 8.744407e-02 - 7.130000e+00 -3.626529e+00 -9.847740e+00 8.740803e-02 - 7.140000e+00 -3.737210e+00 -9.861552e+00 8.716079e-02 - 7.150000e+00 -3.852113e+00 -9.875363e+00 8.679014e-02 - 7.160000e+00 -3.967249e+00 -9.889175e+00 8.642857e-02 - 7.170000e+00 -4.078489e+00 -9.902987e+00 8.620775e-02 - 7.180000e+00 -4.181658e+00 -9.916799e+00 8.621132e-02 - 7.190000e+00 -4.272592e+00 -9.930610e+00 8.644384e-02 - 7.200000e+00 -4.347178e+00 -9.944422e+00 8.682872e-02 - 7.210000e+00 -4.401366e+00 -9.958234e+00 8.723616e-02 - 7.220000e+00 -4.431155e+00 -9.972045e+00 8.752910e-02 - 7.230000e+00 -4.432579e+00 -9.985857e+00 8.760985e-02 - 7.240000e+00 -4.401686e+00 -9.999669e+00 8.745203e-02 - 7.250000e+00 -4.334534e+00 -1.001348e+01 8.710905e-02 - 7.260000e+00 -4.227210e+00 -1.002729e+01 8.669701e-02 - 7.270000e+00 -4.075886e+00 -1.004110e+01 8.635634e-02 - 7.280000e+00 -3.876916e+00 -1.005492e+01 8.620357e-02 - 7.290000e+00 -3.626982e+00 -1.006873e+01 8.628964e-02 - 7.300000e+00 -3.323282e+00 -1.008254e+01 8.658147e-02 - 7.310000e+00 -2.963758e+00 -1.009635e+01 8.697451e-02 - 7.320000e+00 -2.547353e+00 -1.011016e+01 8.733096e-02 - 7.330000e+00 -2.074275e+00 -1.012397e+01 8.752789e-02 - 7.340000e+00 -1.546259e+00 -1.013779e+01 8.749837e-02 - 7.350000e+00 -9.667883e-01 -1.015160e+01 8.725294e-02 - 7.360000e+00 -3.412800e-01 -1.016541e+01 8.687595e-02 - 7.370000e+00 3.228177e-01 -1.017922e+01 8.649780e-02 - 7.380000e+00 1.016010e+00 -1.019303e+01 8.625065e-02 - 7.390000e+00 1.726847e+00 -1.020684e+01 8.622171e-02 - 7.400000e+00 2.442125e+00 -1.022066e+01 8.642147e-02 - 7.410000e+00 3.147204e+00 -1.023447e+01 8.677992e-02 - 7.420000e+00 3.826419e+00 -1.024828e+01 8.717238e-02 - 7.430000e+00 4.463596e+00 -1.026209e+01 8.746396e-02 - 7.440000e+00 5.042623e+00 -1.027590e+01 8.755554e-02 - 7.450000e+00 5.548071e+00 -1.028971e+01 8.741620e-02 - 7.460000e+00 5.965823e+00 -1.030353e+01 8.709278e-02 - 7.470000e+00 6.283678e+00 -1.031734e+01 8.669456e-02 - 7.480000e+00 6.491899e+00 -1.033115e+01 8.635679e-02 - 7.490000e+00 6.583679e+00 -1.034496e+01 8.619412e-02 - 7.500000e+00 6.555482e+00 -1.035877e+01 8.625962e-02 - 7.510000e+00 6.407260e+00 -1.037258e+01 8.652573e-02 - 7.520000e+00 6.142512e+00 -1.038640e+01 8.689495e-02 - 7.530000e+00 5.768195e+00 -1.040021e+01 8.723582e-02 - 7.540000e+00 5.294482e+00 -1.041402e+01 8.742941e-02 - 7.550000e+00 4.734383e+00 -1.042783e+01 8.740958e-02 - 7.560000e+00 4.103251e+00 -1.044164e+01 8.718460e-02 - 7.570000e+00 3.418196e+00 -1.045545e+01 8.683440e-02 - 7.580000e+00 2.697439e+00 -1.046927e+01 8.648406e-02 - 7.590000e+00 1.959645e+00 -1.048308e+01 8.626112e-02 - 7.600000e+00 1.223256e+00 -1.049689e+01 8.625008e-02 - 7.610000e+00 5.058789e-01 -1.051070e+01 8.646118e-02 - 7.620000e+00 -1.762705e-01 -1.052451e+01 8.682625e-02 - 7.630000e+00 -8.088206e-01 -1.053832e+01 8.722328e-02 - 7.640000e+00 -1.379593e+00 -1.055214e+01 8.751959e-02 - 7.650000e+00 -1.878834e+00 -1.056595e+01 8.761687e-02 - 7.660000e+00 -2.299321e+00 -1.057976e+01 8.748327e-02 - 7.670000e+00 -2.636371e+00 -1.059357e+01 8.716352e-02 - 7.680000e+00 -2.887729e+00 -1.060738e+01 8.676455e-02 - 7.690000e+00 -3.053399e+00 -1.062120e+01 8.642026e-02 - 7.700000e+00 -3.135390e+00 -1.063501e+01 8.624582e-02 - 7.710000e+00 -3.137448e+00 -1.064882e+01 8.629701e-02 - 7.720000e+00 -3.064754e+00 -1.066263e+01 8.655023e-02 - 7.730000e+00 -2.923640e+00 -1.067644e+01 8.691194e-02 - 7.740000e+00 -2.721321e+00 -1.069025e+01 8.725297e-02 - 7.750000e+00 -2.465665e+00 -1.070407e+01 8.745415e-02 - 7.760000e+00 -2.165005e+00 -1.071788e+01 8.744637e-02 - 7.770000e+00 -1.827993e+00 -1.073169e+01 8.723295e-02 - 7.780000e+00 -1.463495e+00 -1.074550e+01 8.688815e-02 - 7.790000e+00 -1.080518e+00 -1.075931e+01 8.653246e-02 - 7.800000e+00 -6.881554e-01 -1.077312e+01 8.629153e-02 - 7.810000e+00 -2.955460e-01 -1.078694e+01 8.625170e-02 - 7.820000e+00 8.818105e-02 -1.080075e+01 8.642853e-02 - 7.830000e+00 4.539747e-01 -1.081456e+01 8.676105e-02 - 7.840000e+00 7.929615e-01 -1.082837e+01 8.713417e-02 - 7.850000e+00 1.096579e+00 -1.084218e+01 8.741985e-02 - 7.860000e+00 1.356747e+00 -1.085599e+01 8.752100e-02 - 7.870000e+00 1.566073e+00 -1.086981e+01 8.740354e-02 - 7.880000e+00 1.718081e+00 -1.088362e+01 8.710728e-02 - 7.890000e+00 1.807461e+00 -1.089743e+01 8.673292e-02 - 7.900000e+00 1.830310e+00 -1.091124e+01 8.640862e-02 - 7.910000e+00 1.784361e+00 -1.092505e+01 8.624595e-02 - 7.920000e+00 1.669172e+00 -1.093886e+01 8.630016e-02 - 7.930000e+00 1.486265e+00 -1.095268e+01 8.655020e-02 - 7.940000e+00 1.239192e+00 -1.096649e+01 8.690681e-02 - 7.950000e+00 9.335295e-01 -1.098030e+01 8.724518e-02 - 7.960000e+00 5.767748e-01 -1.099411e+01 8.744885e-02 - 7.970000e+00 1.781685e-01 -1.100792e+01 8.744896e-02 - 7.980000e+00 -2.515741e-01 -1.102173e+01 8.724661e-02 - 7.990000e+00 -7.006017e-01 -1.103555e+01 8.691219e-02 - 8.000000e+00 -1.156323e+00 -1.104936e+01 8.656200e-02 - 8.010000e+00 -1.605844e+00 -1.106317e+01 8.631875e-02 - 8.020000e+00 -2.036420e+00 -1.107698e+01 8.626827e-02 - 8.030000e+00 -2.435906e+00 -1.109079e+01 8.642838e-02 - 8.040000e+00 -2.793178e+00 -1.110460e+01 8.674233e-02 - 8.050000e+00 -3.098512e+00 -1.111842e+01 8.709977e-02 - 8.060000e+00 -3.343890e+00 -1.113223e+01 8.737617e-02 - 8.070000e+00 -3.523241e+00 -1.114604e+01 8.747575e-02 - 8.080000e+00 -3.632589e+00 -1.115985e+01 8.736322e-02 - 8.090000e+00 -3.670114e+00 -1.117366e+01 8.707518e-02 - 8.100000e+00 -3.636133e+00 -1.118747e+01 8.670830e-02 - 8.110000e+00 -3.532999e+00 -1.120129e+01 8.638727e-02 - 8.120000e+00 -3.364936e+00 -1.121510e+01 8.622217e-02 - 8.130000e+00 -3.137818e+00 -1.122891e+01 8.626941e-02 - 8.140000e+00 -2.858915e+00 -1.124272e+01 8.651148e-02 - 8.150000e+00 -2.536611e+00 -1.125653e+01 8.686382e-02 - 8.160000e+00 -2.180124e+00 -1.127034e+01 8.720573e-02 - 8.170000e+00 -1.799223e+00 -1.128416e+01 8.742290e-02 - 8.180000e+00 -1.403965e+00 -1.129797e+01 8.744584e-02 - 8.190000e+00 -1.004458e+00 -1.131178e+01 8.727231e-02 - 8.200000e+00 -6.106442e-01 -1.132559e+01 8.696732e-02 - 8.210000e+00 -2.321136e-01 -1.133940e+01 8.664116e-02 - 8.220000e+00 1.220572e-01 -1.135322e+01 8.641148e-02 - 8.230000e+00 4.434491e-01 -1.136703e+01 8.636156e-02 - 8.240000e+00 7.244291e-01 -1.138084e+01 8.650989e-02 - 8.250000e+00 9.582697e-01 -1.139465e+01 8.680331e-02 - 8.260000e+00 1.139265e+00 -1.140846e+01 8.713658e-02 - 8.270000e+00 1.262844e+00 -1.142227e+01 8.739024e-02 - 8.280000e+00 1.325686e+00 -1.143609e+01 8.747210e-02 - 8.290000e+00 1.325830e+00 -1.144990e+01 8.734839e-02 - 8.300000e+00 1.262779e+00 -1.146371e+01 8.705530e-02 - 8.310000e+00 1.137587e+00 -1.147752e+01 8.668776e-02 - 8.320000e+00 9.529220e-01 -1.149133e+01 8.636844e-02 - 8.330000e+00 7.130975e-01 -1.150514e+01 8.620594e-02 - 8.340000e+00 4.240556e-01 -1.151896e+01 8.625642e-02 - 8.350000e+00 9.329779e-02 -1.153277e+01 8.650321e-02 - 8.360000e+00 -2.702450e-01 -1.154658e+01 8.686301e-02 - 8.370000e+00 -6.564063e-01 -1.156039e+01 8.721593e-02 - 8.380000e+00 -1.054043e+00 -1.157420e+01 8.744716e-02 - 8.390000e+00 -1.451351e+00 -1.158801e+01 8.748512e-02 - 8.400000e+00 -1.836238e+00 -1.160183e+01 8.732405e-02 - 8.410000e+00 -2.196723e+00 -1.161564e+01 8.702498e-02 - 8.420000e+00 -2.521366e+00 -1.162945e+01 8.669490e-02 - 8.430000e+00 -2.799690e+00 -1.164326e+01 8.645018e-02 - 8.440000e+00 -3.022590e+00 -1.165707e+01 8.637573e-02 - 8.450000e+00 -3.182695e+00 -1.167088e+01 8.649456e-02 - 8.460000e+00 -3.274671e+00 -1.168470e+01 8.675976e-02 - 8.470000e+00 -3.295447e+00 -1.169851e+01 8.707235e-02 - 8.480000e+00 -3.244348e+00 -1.171232e+01 8.731743e-02 - 8.490000e+00 -3.123134e+00 -1.172613e+01 8.740456e-02 - 8.500000e+00 -2.935929e+00 -1.173994e+01 8.729860e-02 - 8.510000e+00 -2.689061e+00 -1.175375e+01 8.703170e-02 - 8.520000e+00 -2.390808e+00 -1.176757e+01 8.669304e-02 - 8.530000e+00 -2.051063e+00 -1.178138e+01 8.639925e-02 - 8.540000e+00 -1.680950e+00 -1.179519e+01 8.625415e-02 - 8.550000e+00 -1.292393e+00 -1.180900e+01 8.631147e-02 - 8.560000e+00 -8.976655e-01 -1.182281e+01 8.655493e-02 - 8.570000e+00 -5.089507e-01 -1.183662e+01 8.690379e-02 - 8.580000e+00 -1.379157e-01 -1.185044e+01 8.724170e-02 - 8.590000e+00 2.046711e-01 -1.186425e+01 8.745698e-02 - 8.600000e+00 5.092724e-01 -1.187806e+01 8.747997e-02 - 8.610000e+00 7.678529e-01 -1.189187e+01 8.730537e-02 - 8.620000e+00 9.740860e-01 -1.190568e+01 8.699360e-02 - 8.630000e+00 1.123495e+00 -1.191949e+01 8.665084e-02 - 8.640000e+00 1.213531e+00 -1.193331e+01 8.639336e-02 - 8.650000e+00 1.243602e+00 -1.194712e+01 8.630718e-02 - 8.660000e+00 1.215045e+00 -1.196093e+01 8.641768e-02 - 8.670000e+00 1.131068e+00 -1.197474e+01 8.668092e-02 - 8.680000e+00 9.966652e-01 -1.198855e+01 8.700042e-02 - 8.690000e+00 8.184972e-01 -1.200236e+01 8.726226e-02 - 8.700000e+00 6.047687e-01 -1.201618e+01 8.737496e-02 - 8.710000e+00 3.650812e-01 -1.202999e+01 8.730014e-02 - 8.720000e+00 1.102728e-01 -1.204380e+01 8.706510e-02 - 8.730000e+00 -1.477617e-01 -1.205761e+01 8.675349e-02 - 8.740000e+00 -3.962768e-01 -1.207142e+01 8.647706e-02 - 8.750000e+00 -6.219127e-01 -1.208524e+01 8.633674e-02 - 8.760000e+00 -8.109697e-01 -1.209905e+01 8.638627e-02 - 8.770000e+00 -9.497260e-01 -1.211286e+01 8.661224e-02 - 8.780000e+00 -1.024799e+00 -1.212667e+01 8.693873e-02 - 8.790000e+00 -1.023552e+00 -1.214048e+01 8.725461e-02 - 8.800000e+00 -9.345354e-01 -1.215429e+01 8.745244e-02 - 8.810000e+00 -7.479563e-01 -1.216811e+01 8.746492e-02 - 8.820000e+00 -4.561570e-01 -1.218192e+01 8.728703e-02 - 8.830000e+00 -5.408176e-02 -1.219573e+01 8.697780e-02 - 8.840000e+00 4.602920e-01 -1.220954e+01 8.664106e-02 - 8.850000e+00 1.085586e+00 -1.222335e+01 8.639072e-02 - 8.860000e+00 1.816743e+00 -1.223716e+01 8.631117e-02 - 8.870000e+00 2.644869e+00 -1.225098e+01 8.642725e-02 - 8.880000e+00 3.557207e+00 -1.226479e+01 8.669538e-02 - 8.890000e+00 4.537280e+00 -1.227860e+01 8.701972e-02 - 8.900000e+00 5.565186e+00 -1.229241e+01 8.728657e-02 - 8.910000e+00 6.618072e+00 -1.230622e+01 8.740369e-02 - 8.920000e+00 7.670763e+00 -1.232003e+01 8.733101e-02 - 8.930000e+00 8.696530e+00 -1.233385e+01 8.709356e-02 - 8.940000e+00 9.667974e+00 -1.234766e+01 8.677302e-02 - 8.950000e+00 1.055799e+01 -1.236147e+01 8.648046e-02 - 8.960000e+00 1.134075e+01 -1.237528e+01 8.631808e-02 - 8.970000e+00 1.199270e+01 -1.238909e+01 8.634303e-02 - 8.980000e+00 1.249350e+01 -1.240290e+01 8.654665e-02 - 8.990000e+00 1.282679e+01 -1.241672e+01 8.685784e-02 - 9.000000e+00 1.298090e+01 -1.243053e+01 8.716892e-02 - 9.010000e+00 1.294932e+01 -1.244434e+01 8.737363e-02 - 9.020000e+00 1.273097e+01 -1.245815e+01 8.740326e-02 - 9.030000e+00 1.233022e+01 -1.247196e+01 8.724920e-02 - 9.040000e+00 1.175672e+01 -1.248577e+01 8.696564e-02 - 9.050000e+00 1.102496e+01 -1.249959e+01 8.665154e-02 - 9.060000e+00 1.015368e+01 -1.251340e+01 8.641715e-02 - 9.070000e+00 9.165054e+00 -1.252721e+01 8.634552e-02 - 9.080000e+00 8.083764e+00 -1.254102e+01 8.646260e-02 - 9.090000e+00 6.936027e+00 -1.255483e+01 8.672781e-02 - 9.100000e+00 5.748546e+00 -1.256864e+01 8.704891e-02 - 9.110000e+00 4.547501e+00 -1.258246e+01 8.731494e-02 - 9.120000e+00 3.357612e+00 -1.259627e+01 8.743453e-02 - 9.130000e+00 2.201315e+00 -1.261008e+01 8.736635e-02 - 9.140000e+00 1.098084e+00 -1.262389e+01 8.713241e-02 - 9.150000e+00 6.393724e-02 -1.263770e+01 8.681078e-02 - 9.160000e+00 -8.888679e-01 -1.265151e+01 8.650957e-02 - 9.170000e+00 -1.751948e+00 -1.266533e+01 8.633011e-02 - 9.180000e+00 -2.520712e+00 -1.267914e+01 8.633136e-02 - 9.190000e+00 -3.194120e+00 -1.269295e+01 8.650901e-02 - 9.200000e+00 -3.774287e+00 -1.270676e+01 8.679761e-02 - 9.210000e+00 -4.265986e+00 -1.272057e+01 8.709484e-02 - 9.220000e+00 -4.676078e+00 -1.273438e+01 8.729798e-02 - 9.230000e+00 -5.012897e+00 -1.274820e+01 8.733918e-02 - 9.240000e+00 -5.285654e+00 -1.276201e+01 8.720785e-02 - 9.250000e+00 -5.503858e+00 -1.277582e+01 8.695382e-02 - 9.260000e+00 -5.676820e+00 -1.278963e+01 8.667035e-02 - 9.270000e+00 -5.813222e+00 -1.280344e+01 8.646195e-02 - 9.280000e+00 -5.920798e+00 -1.281725e+01 8.640730e-02 - 9.290000e+00 -6.006108e+00 -1.283107e+01 8.653038e-02 - 9.300000e+00 -6.074419e+00 -1.284488e+01 8.679133e-02 - 9.310000e+00 -6.129667e+00 -1.285869e+01 8.710062e-02 - 9.320000e+00 -6.174503e+00 -1.287250e+01 8.735094e-02 - 9.330000e+00 -6.210392e+00 -1.288631e+01 8.745438e-02 - 9.340000e+00 -6.237755e+00 -1.290013e+01 8.737209e-02 - 9.350000e+00 -6.256124e+00 -1.291394e+01 8.712738e-02 - 9.360000e+00 -6.264304e+00 -1.292775e+01 8.679863e-02 - 9.370000e+00 -6.260523e+00 -1.294156e+01 8.649375e-02 - 9.380000e+00 -6.242561e+00 -1.295537e+01 8.631371e-02 - 9.390000e+00 -6.207852e+00 -1.296918e+01 8.631735e-02 - 9.400000e+00 -6.153565e+00 -1.298300e+01 8.650032e-02 - 9.410000e+00 -6.076659e+00 -1.299681e+01 8.679699e-02 - 9.420000e+00 -5.973936e+00 -1.301062e+01 8.710424e-02 - 9.430000e+00 -5.842086e+00 -1.302443e+01 8.731774e-02 - 9.440000e+00 -5.677740e+00 -1.303824e+01 8.736720e-02 - 9.450000e+00 -5.477554e+00 -1.305205e+01 8.723917e-02 - 9.460000e+00 -5.238312e+00 -1.306587e+01 8.698093e-02 - 9.470000e+00 -4.957070e+00 -1.307968e+01 8.668442e-02 - 9.480000e+00 -4.631329e+00 -1.309349e+01 8.645490e-02 - 9.490000e+00 -4.259246e+00 -1.310730e+01 8.637421e-02 - 9.500000e+00 -3.839860e+00 -1.312111e+01 8.647142e-02 - 9.510000e+00 -3.373332e+00 -1.313492e+01 8.671246e-02 - 9.520000e+00 -2.861170e+00 -1.314874e+01 8.701277e-02 - 9.530000e+00 -2.306436e+00 -1.316255e+01 8.726783e-02 - 9.540000e+00 -1.713899e+00 -1.317636e+01 8.738967e-02 - 9.550000e+00 -1.090124e+00 -1.319017e+01 8.733651e-02 - 9.560000e+00 -4.434820e-01 -1.320398e+01 8.712656e-02 - 9.570000e+00 2.159325e-01 -1.321779e+01 8.683195e-02 - 9.580000e+00 8.764886e-01 -1.323161e+01 8.655460e-02 - 9.590000e+00 1.525300e+00 -1.324542e+01 8.639119e-02 - 9.600000e+00 2.148600e+00 -1.325923e+01 8.639887e-02 - 9.610000e+00 2.732200e+00 -1.327304e+01 8.657453e-02 - 9.620000e+00 3.262001e+00 -1.328685e+01 8.685595e-02 - 9.630000e+00 3.724542e+00 -1.330066e+01 8.714429e-02 - 9.640000e+00 4.107565e+00 -1.331448e+01 8.733899e-02 - 9.650000e+00 4.400543e+00 -1.332829e+01 8.737213e-02 - 9.660000e+00 4.595165e+00 -1.334210e+01 8.723101e-02 - 9.670000e+00 4.685740e+00 -1.335591e+01 8.696239e-02 - 9.680000e+00 4.669497e+00 -1.336972e+01 8.665720e-02 - 9.690000e+00 4.546759e+00 -1.338353e+01 8.642001e-02 - 9.700000e+00 4.320990e+00 -1.339735e+01 8.633296e-02 - 9.710000e+00 3.998700e+00 -1.341116e+01 8.642649e-02 - 9.720000e+00 3.589214e+00 -1.342497e+01 8.666849e-02 - 9.730000e+00 3.104320e+00 -1.343878e+01 8.697614e-02 - 9.740000e+00 2.557813e+00 -1.345259e+01 8.724548e-02 - 9.750000e+00 1.964951e+00 -1.346640e+01 8.738734e-02 - 9.760000e+00 1.341861e+00 -1.348022e+01 8.735698e-02 - 9.770000e+00 7.049174e-01 -1.349403e+01 8.716823e-02 - 9.780000e+00 7.012748e-02 -1.350784e+01 8.688841e-02 - 9.790000e+00 -5.474493e-01 -1.352165e+01 8.661543e-02 - 9.800000e+00 -1.134219e+00 -1.353546e+01 8.644403e-02 - 9.810000e+00 -1.678491e+00 -1.354927e+01 8.643230e-02 - 9.820000e+00 -2.170806e+00 -1.356309e+01 8.658090e-02 - 9.830000e+00 -2.604164e+00 -1.357690e+01 8.683326e-02 - 9.840000e+00 -2.974131e+00 -1.359071e+01 8.709657e-02 - 9.850000e+00 -3.278823e+00 -1.360452e+01 8.727520e-02 - 9.860000e+00 -3.518798e+00 -1.361833e+01 8.730399e-02 - 9.870000e+00 -3.696842e+00 -1.363215e+01 8.717051e-02 - 9.880000e+00 -3.817675e+00 -1.364596e+01 8.691943e-02 - 9.890000e+00 -3.887602e+00 -1.365977e+01 8.663786e-02 - 9.900000e+00 -3.914115e+00 -1.367358e+01 8.642579e-02 - 9.910000e+00 -3.905480e+00 -1.368739e+01 8.636104e-02 - 9.920000e+00 -3.870320e+00 -1.370120e+01 8.647090e-02 - 9.930000e+00 -3.817203e+00 -1.371502e+01 8.672179e-02 - 9.940000e+00 -3.754274e+00 -1.372883e+01 8.703094e-02 - 9.950000e+00 -3.688918e+00 -1.374264e+01 8.729552e-02 - 9.960000e+00 -3.627475e+00 -1.375645e+01 8.742791e-02 - 9.970000e+00 -3.575013e+00 -1.377026e+01 8.738488e-02 - 9.980000e+00 -3.535158e+00 -1.378407e+01 8.718164e-02 - 9.990000e+00 -3.509989e+00 -1.379789e+01 8.688691e-02 - 1.000000e+01 -3.499993e+00 -1.381170e+01 8.660026e-02 - 1.001000e+01 -3.504072e+00 -1.382551e+01 8.641841e-02 - 1.002000e+01 -3.519616e+00 -1.383932e+01 8.640157e-02 - 1.003000e+01 -3.542627e+00 -1.385313e+01 8.655216e-02 - 1.004000e+01 -3.567881e+00 -1.386694e+01 8.681427e-02 - 1.005000e+01 -3.589155e+00 -1.388076e+01 8.709419e-02 - 1.006000e+01 -3.599469e+00 -1.389457e+01 8.729364e-02 - 1.007000e+01 -3.591385e+00 -1.390838e+01 8.734331e-02 - 1.008000e+01 -3.557318e+00 -1.392219e+01 8.722578e-02 - 1.009000e+01 -3.489873e+00 -1.393600e+01 8.698092e-02 - 1.010000e+01 -3.382189e+00 -1.394981e+01 8.669241e-02 - 1.011000e+01 -3.228289e+00 -1.396363e+01 8.645935e-02 - 1.012000e+01 -3.023408e+00 -1.397744e+01 8.636177e-02 - 1.013000e+01 -2.764303e+00 -1.399125e+01 8.643218e-02 - 1.014000e+01 -2.449523e+00 -1.400506e+01 8.664393e-02 - 1.015000e+01 -2.079619e+00 -1.401887e+01 8.692128e-02 - 1.016000e+01 -1.657294e+00 -1.403268e+01 8.716681e-02 - 1.017000e+01 -1.187470e+00 -1.404650e+01 8.729563e-02 - 1.018000e+01 -6.772696e-01 -1.406031e+01 8.726425e-02 - 1.019000e+01 -1.358937e-01 -1.407412e+01 8.708504e-02 - 1.020000e+01 4.255869e-01 -1.408793e+01 8.682200e-02 - 1.021000e+01 9.945439e-01 -1.410174e+01 8.656929e-02 - 1.022000e+01 1.557189e+00 -1.411555e+01 8.641868e-02 - 1.023000e+01 2.099047e+00 -1.412937e+01 8.642691e-02 - 1.024000e+01 2.605490e+00 -1.414318e+01 8.659488e-02 - 1.025000e+01 3.062306e+00 -1.415699e+01 8.686709e-02 - 1.026000e+01 3.456283e+00 -1.417080e+01 8.715138e-02 - 1.027000e+01 3.775775e+00 -1.418461e+01 8.735130e-02 - 1.028000e+01 4.011229e+00 -1.419842e+01 8.739897e-02 - 1.029000e+01 4.155640e+00 -1.421224e+01 8.727770e-02 - 1.030000e+01 4.204914e+00 -1.422605e+01 8.702751e-02 - 1.031000e+01 4.158113e+00 -1.423986e+01 8.673214e-02 - 1.032000e+01 4.017568e+00 -1.425367e+01 8.649118e-02 - 1.033000e+01 3.788855e+00 -1.426748e+01 8.638585e-02 - 1.034000e+01 3.480622e+00 -1.428129e+01 8.645047e-02 - 1.035000e+01 3.104278e+00 -1.429511e+01 8.666030e-02 - 1.036000e+01 2.673553e+00 -1.430892e+01 8.694084e-02 - 1.037000e+01 2.203951e+00 -1.432273e+01 8.719458e-02 - 1.038000e+01 1.712118e+00 -1.433654e+01 8.733498e-02 - 1.039000e+01 1.215153e+00 -1.435035e+01 8.731546e-02 - 1.040000e+01 7.298949e-01 -1.436417e+01 8.714454e-02 - 1.041000e+01 2.722260e-01 -1.437798e+01 8.688261e-02 - 1.042000e+01 -1.435834e-01 -1.439179e+01 8.662157e-02 - 1.043000e+01 -5.054535e-01 -1.440560e+01 8.645317e-02 - 1.044000e+01 -8.039674e-01 -1.441941e+01 8.643676e-02 - 1.045000e+01 -1.032717e+00 -1.443322e+01 8.657798e-02 - 1.046000e+01 -1.188507e+00 -1.444704e+01 8.682686e-02 - 1.047000e+01 -1.271401e+00 -1.446085e+01 8.709613e-02 - 1.048000e+01 -1.284622e+00 -1.447466e+01 8.729218e-02 - 1.049000e+01 -1.234299e+00 -1.448847e+01 8.734732e-02 - 1.050000e+01 -1.129080e+00 -1.450228e+01 8.724243e-02 - 1.051000e+01 -9.796357e-01 -1.451609e+01 8.701305e-02 - 1.052000e+01 -7.980667e-01 -1.452991e+01 8.673757e-02 - 1.053000e+01 -5.972583e-01 -1.454372e+01 8.651054e-02 - 1.054000e+01 -3.902032e-01 -1.455753e+01 8.640985e-02 - 1.055000e+01 -1.893300e-01 -1.457134e+01 8.646890e-02 - 1.056000e+01 -5.868969e-03 -1.458515e+01 8.666457e-02 - 1.057000e+01 1.507162e-01 -1.459896e+01 8.692576e-02 - 1.058000e+01 2.732033e-01 -1.461278e+01 8.715906e-02 - 1.059000e+01 3.569721e-01 -1.462659e+01 8.728155e-02 - 1.060000e+01 4.002350e-01 -1.464040e+01 8.724917e-02 - 1.061000e+01 4.041267e-01 -1.465421e+01 8.707157e-02 - 1.062000e+01 3.726514e-01 -1.466802e+01 8.680913e-02 - 1.063000e+01 3.124882e-01 -1.468183e+01 8.655297e-02 - 1.064000e+01 2.326669e-01 -1.469565e+01 8.639387e-02 - 1.065000e+01 1.441274e-01 -1.470946e+01 8.639026e-02 - 1.066000e+01 5.918253e-02 -1.472327e+01 8.654709e-02 - 1.067000e+01 -9.089408e-03 -1.473708e+01 8.681372e-02 - 1.068000e+01 -4.749838e-02 -1.475089e+01 8.710195e-02 - 1.069000e+01 -4.341128e-02 -1.476470e+01 8.731675e-02 - 1.070000e+01 1.459279e-02 -1.477852e+01 8.738842e-02 - 1.071000e+01 1.361100e-01 -1.479233e+01 8.729542e-02 - 1.072000e+01 3.283693e-01 -1.480614e+01 8.707112e-02 - 1.073000e+01 5.957845e-01 -1.481995e+01 8.679261e-02 - 1.074000e+01 9.396214e-01 -1.483376e+01 8.655478e-02 - 1.075000e+01 1.357797e+00 -1.484757e+01 8.643778e-02 - 1.076000e+01 1.844820e+00 -1.486139e+01 8.647898e-02 - 1.077000e+01 2.391879e+00 -1.487520e+01 8.665995e-02 - 1.078000e+01 2.987079e+00 -1.488901e+01 8.691370e-02 - 1.079000e+01 3.615810e+00 -1.490282e+01 8.714917e-02 - 1.080000e+01 4.261249e+00 -1.491663e+01 8.728329e-02 - 1.081000e+01 4.904966e+00 -1.493044e+01 8.726934e-02 - 1.082000e+01 5.527609e+00 -1.494426e+01 8.711234e-02 - 1.083000e+01 6.109646e+00 -1.495807e+01 8.686715e-02 - 1.084000e+01 6.632134e+00 -1.497188e+01 8.661987e-02 - 1.085000e+01 7.077476e+00 -1.498569e+01 8.645806e-02 - 1.086000e+01 7.430133e+00 -1.499950e+01 8.643983e-02 - 1.087000e+01 7.677269e+00 -1.501331e+01 8.657274e-02 - 1.088000e+01 7.809287e+00 -1.502713e+01 8.681111e-02 - 1.089000e+01 7.820243e+00 -1.504094e+01 8.707253e-02 - 1.090000e+01 7.708102e+00 -1.505475e+01 8.726713e-02 - 1.091000e+01 7.474844e+00 -1.506856e+01 8.732861e-02 - 1.092000e+01 7.126393e+00 -1.508237e+01 8.723654e-02 - 1.093000e+01 6.672383e+00 -1.509619e+01 8.702312e-02 - 1.094000e+01 6.125769e+00 -1.511000e+01 8.676251e-02 - 1.095000e+01 5.502291e+00 -1.512381e+01 8.654572e-02 - 1.096000e+01 4.819826e+00 -1.513762e+01 8.644903e-02 - 1.097000e+01 4.097651e+00 -1.515143e+01 8.650673e-02 - 1.098000e+01 3.355657e+00 -1.516524e+01 8.669867e-02 - 1.099000e+01 2.613538e+00 -1.517906e+01 8.695747e-02 - 1.100000e+01 1.890007e+00 -1.519287e+01 8.719265e-02 - 1.101000e+01 1.202072e+00 -1.520668e+01 8.732212e-02 - 1.102000e+01 5.644048e-01 -1.522049e+01 8.730016e-02 - 1.103000e+01 -1.117578e-02 -1.523430e+01 8.713260e-02 - 1.104000e+01 -5.160635e-01 -1.524811e+01 8.687511e-02 - 1.105000e+01 -9.450700e-01 -1.526193e+01 8.661474e-02 - 1.106000e+01 -1.296459e+00 -1.527574e+01 8.644044e-02 - 1.107000e+01 -1.571811e+00 -1.528955e+01 8.641206e-02 - 1.108000e+01 -1.775734e+00 -1.530336e+01 8.653895e-02 - 1.109000e+01 -1.915430e+00 -1.531717e+01 8.677666e-02 - 1.110000e+01 -2.000150e+00 -1.533098e+01 8.704302e-02 - 1.111000e+01 -2.040561e+00 -1.534480e+01 8.724705e-02 - 1.112000e+01 -2.048072e+00 -1.535861e+01 8.732011e-02 - 1.113000e+01 -2.034146e+00 -1.537242e+01 8.723861e-02 - 1.114000e+01 -2.009629e+00 -1.538623e+01 8.703151e-02 - 1.115000e+01 -1.984157e+00 -1.540004e+01 8.677052e-02 - 1.116000e+01 -1.965642e+00 -1.541385e+01 8.654577e-02 - 1.117000e+01 -1.959882e+00 -1.542767e+01 8.643477e-02 - 1.118000e+01 -1.970309e+00 -1.544148e+01 8.647500e-02 - 1.119000e+01 -1.997881e+00 -1.545529e+01 8.665064e-02 - 1.120000e+01 -2.041129e+00 -1.546910e+01 8.689860e-02 - 1.121000e+01 -2.096343e+00 -1.548291e+01 8.713137e-02 - 1.122000e+01 -2.157899e+00 -1.549672e+01 8.726780e-02 - 1.123000e+01 -2.218678e+00 -1.551054e+01 8.726082e-02 - 1.124000e+01 -2.270590e+00 -1.552435e+01 8.711302e-02 - 1.125000e+01 -2.305135e+00 -1.553816e+01 8.687573e-02 - 1.126000e+01 -2.313987e+00 -1.555197e+01 8.663170e-02 - 1.127000e+01 -2.289573e+00 -1.556578e+01 8.646671e-02 - 1.128000e+01 -2.225594e+00 -1.557959e+01 8.643942e-02 - 1.129000e+01 -2.117479e+00 -1.559341e+01 8.656027e-02 - 1.130000e+01 -1.962742e+00 -1.560722e+01 8.678773e-02 - 1.131000e+01 -1.761217e+00 -1.562103e+01 8.704332e-02 - 1.132000e+01 -1.515167e+00 -1.563484e+01 8.723945e-02 - 1.133000e+01 -1.229262e+00 -1.564865e+01 8.730965e-02 - 1.134000e+01 -9.104208e-01 -1.566246e+01 8.723088e-02 - 1.135000e+01 -5.675403e-01 -1.567628e+01 8.703110e-02 - 1.136000e+01 -2.111127e-01 -1.569009e+01 8.677987e-02 - 1.137000e+01 1.472366e-01 -1.570390e+01 8.656488e-02 - 1.138000e+01 4.952728e-01 -1.571771e+01 8.646148e-02 - 1.139000e+01 8.207056e-01 -1.573152e+01 8.650596e-02 - 1.140000e+01 1.111748e+00 -1.574533e+01 8.668240e-02 - 1.141000e+01 1.357647e+00 -1.575915e+01 8.692850e-02 - 1.142000e+01 1.549171e+00 -1.577296e+01 8.715797e-02 - 1.143000e+01 1.679013e+00 -1.578677e+01 8.729070e-02 - 1.144000e+01 1.742111e+00 -1.580058e+01 8.728018e-02 - 1.145000e+01 1.735857e+00 -1.581439e+01 8.712905e-02 - 1.146000e+01 1.660190e+00 -1.582820e+01 8.688833e-02 - 1.147000e+01 1.517580e+00 -1.584202e+01 8.664048e-02 - 1.148000e+01 1.312886e+00 -1.585583e+01 8.647135e-02 - 1.149000e+01 1.053117e+00 -1.586964e+01 8.644017e-02 - 1.150000e+01 7.471025e-01 -1.588345e+01 8.655827e-02 - 1.151000e+01 4.050765e-01 -1.589726e+01 8.678499e-02 - 1.152000e+01 3.822206e-02 -1.591108e+01 8.704223e-02 - 1.153000e+01 -3.418258e-01 -1.592489e+01 8.724198e-02 - 1.154000e+01 -7.234805e-01 -1.593870e+01 8.731646e-02 - 1.155000e+01 -1.095689e+00 -1.595251e+01 8.724078e-02 - 1.156000e+01 -1.448379e+00 -1.596632e+01 8.704099e-02 - 1.157000e+01 -1.772845e+00 -1.598013e+01 8.678539e-02 - 1.158000e+01 -2.062066e+00 -1.599395e+01 8.656163e-02 - 1.159000e+01 -2.310919e+00 -1.600776e+01 8.644656e-02 - 1.160000e+01 -2.516314e+00 -1.602157e+01 8.647927e-02 - 1.161000e+01 -2.677205e+00 -1.603538e+01 8.664723e-02 - 1.162000e+01 -2.794523e+00 -1.604919e+01 8.689108e-02 - 1.163000e+01 -2.870991e+00 -1.606300e+01 8.712607e-02 - 1.164000e+01 -2.910869e+00 -1.607682e+01 8.727177e-02 - 1.165000e+01 -2.919626e+00 -1.609063e+01 8.727937e-02 - 1.166000e+01 -2.903548e+00 -1.610444e+01 8.714783e-02 - 1.167000e+01 -2.869334e+00 -1.611825e+01 8.692387e-02 - 1.168000e+01 -2.823663e+00 -1.613206e+01 8.668616e-02 - 1.169000e+01 -2.772784e+00 -1.614587e+01 8.651824e-02 - 1.170000e+01 -2.722144e+00 -1.615969e+01 8.647921e-02 - 1.171000e+01 -2.676059e+00 -1.617350e+01 8.658254e-02 - 1.172000e+01 -2.637473e+00 -1.618731e+01 8.679125e-02 - 1.173000e+01 -2.607795e+00 -1.620112e+01 8.703142e-02 - 1.174000e+01 -2.586832e+00 -1.621493e+01 8.721852e-02 - 1.175000e+01 -2.572831e+00 -1.622874e+01 8.728674e-02 - 1.176000e+01 -2.562607e+00 -1.624256e+01 8.721136e-02 - 1.177000e+01 -2.551775e+00 -1.625637e+01 8.701698e-02 - 1.178000e+01 -2.535058e+00 -1.627018e+01 8.676945e-02 - 1.179000e+01 -2.506656e+00 -1.628399e+01 8.655367e-02 - 1.180000e+01 -2.460660e+00 -1.629780e+01 8.644429e-02 - 1.181000e+01 -2.391487e+00 -1.631161e+01 8.647926e-02 - 1.182000e+01 -2.294308e+00 -1.632543e+01 8.664617e-02 - 1.183000e+01 -2.165445e+00 -1.633924e+01 8.688672e-02 - 1.184000e+01 -2.002710e+00 -1.635305e+01 8.711760e-02 - 1.185000e+01 -1.805678e+00 -1.636686e+01 8.725964e-02 - 1.186000e+01 -1.575853e+00 -1.638067e+01 8.726476e-02 - 1.187000e+01 -1.316743e+00 -1.639448e+01 8.713197e-02 - 1.188000e+01 -1.033807e+00 -1.640830e+01 8.690762e-02 - 1.189000e+01 -7.343041e-01 -1.642211e+01 8.666991e-02 - 1.190000e+01 -4.270274e-01 -1.643592e+01 8.650215e-02 - 1.191000e+01 -1.219464e-01 -1.644973e+01 8.646365e-02 - 1.192000e+01 1.702256e-01 -1.646354e+01 8.656845e-02 - 1.193000e+01 4.385179e-01 -1.647735e+01 8.678025e-02 - 1.194000e+01 6.722155e-01 -1.649117e+01 8.702549e-02 - 1.195000e+01 8.613718e-01 -1.650498e+01 8.721939e-02 - 1.196000e+01 9.972917e-01 -1.651879e+01 8.729525e-02 - 1.197000e+01 1.072960e+00 -1.653260e+01 8.722691e-02 - 1.198000e+01 1.083388e+00 -1.654641e+01 8.703750e-02 - 1.199000e+01 1.025863e+00 -1.656022e+01 8.679182e-02 - 1.200000e+01 9.000883e-01 -1.657404e+01 8.657464e-02 - 1.201000e+01 7.081926e-01 -1.658785e+01 8.646157e-02 - 1.202000e+01 4.546330e-01 -1.660166e+01 8.649249e-02 - 1.203000e+01 1.459752e-01 -1.661547e+01 8.665720e-02 - 1.204000e+01 -2.094234e-01 -1.662928e+01 8.689918e-02 - 1.205000e+01 -6.018116e-01 -1.664310e+01 8.713577e-02 - 1.206000e+01 -1.020500e+00 -1.665691e+01 8.728698e-02 - 1.207000e+01 -1.454349e+00 -1.667072e+01 8.730257e-02 - 1.208000e+01 -1.892254e+00 -1.668453e+01 8.717861e-02 - 1.209000e+01 -2.323611e+00 -1.669834e+01 8.695856e-02 - 1.210000e+01 -2.738726e+00 -1.671215e+01 8.671861e-02 - 1.211000e+01 -3.129152e+00 -1.672597e+01 8.654174e-02 - 1.212000e+01 -3.487930e+00 -1.673978e+01 8.648877e-02 - 1.213000e+01 -3.809734e+00 -1.675359e+01 8.657682e-02 - 1.214000e+01 -4.090900e+00 -1.676740e+01 8.677324e-02 - 1.215000e+01 -4.329355e+00 -1.678121e+01 8.700753e-02 - 1.216000e+01 -4.524443e+00 -1.679502e+01 8.719647e-02 - 1.217000e+01 -4.676680e+00 -1.680884e+01 8.727295e-02 - 1.218000e+01 -4.787434e+00 -1.682265e+01 8.720863e-02 - 1.219000e+01 -4.858581e+00 -1.683646e+01 8.702334e-02 - 1.220000e+01 -4.892147e+00 -1.685027e+01 8.677848e-02 - 1.221000e+01 -4.889964e+00 -1.686408e+01 8.655639e-02 - 1.222000e+01 -4.853374e+00 -1.687789e+01 8.643217e-02 - 1.223000e+01 -4.782995e+00 -1.689171e+01 8.644725e-02 - 1.224000e+01 -4.678572e+00 -1.690552e+01 8.659482e-02 - 1.225000e+01 -4.538928e+00 -1.691933e+01 8.682247e-02 - 1.226000e+01 -4.362009e+00 -1.693314e+01 8.705119e-02 - 1.227000e+01 -4.145042e+00 -1.694695e+01 8.720315e-02 - 1.228000e+01 -3.884773e+00 -1.696076e+01 8.722833e-02 - 1.229000e+01 -3.577793e+00 -1.697458e+01 8.712105e-02 - 1.230000e+01 -3.220920e+00 -1.698839e+01 8.692162e-02 - 1.231000e+01 -2.811608e+00 -1.700220e+01 8.670249e-02 - 1.232000e+01 -2.348369e+00 -1.701601e+01 8.654327e-02 - 1.233000e+01 -1.831168e+00 -1.702982e+01 8.650268e-02 - 1.234000e+01 -1.261761e+00 -1.704363e+01 8.659741e-02 - 1.235000e+01 -6.439623e-01 -1.705745e+01 8.679596e-02 - 1.236000e+01 1.619533e-02 -1.707126e+01 8.702998e-02 - 1.237000e+01 7.104125e-01 -1.708507e+01 8.721853e-02 - 1.238000e+01 1.428205e+00 -1.709888e+01 8.729621e-02 - 1.239000e+01 2.157113e+00 -1.711269e+01 8.723538e-02 - 1.240000e+01 2.883035e+00 -1.712650e+01 8.705554e-02 - 1.241000e+01 3.590672e+00 -1.714032e+01 8.681702e-02 - 1.242000e+01 4.264062e+00 -1.715413e+01 8.660088e-02 - 1.243000e+01 4.887185e+00 -1.716794e+01 8.648117e-02 - 1.244000e+01 5.444599e+00 -1.718175e+01 8.649889e-02 - 1.245000e+01 5.922081e+00 -1.719556e+01 8.664741e-02 - 1.246000e+01 6.307240e+00 -1.720937e+01 8.687486e-02 - 1.247000e+01 6.590063e+00 -1.722319e+01 8.710268e-02 - 1.248000e+01 6.763375e+00 -1.723700e+01 8.725305e-02 - 1.249000e+01 6.823174e+00 -1.725081e+01 8.727533e-02 - 1.250000e+01 6.768833e+00 -1.726462e+01 8.716280e-02 - 1.251000e+01 6.603155e+00 -1.727843e+01 8.695464e-02 - 1.252000e+01 6.332272e+00 -1.729224e+01 8.672268e-02 - 1.253000e+01 5.965397e+00 -1.730606e+01 8.654691e-02 - 1.254000e+01 5.514443e+00 -1.731987e+01 8.648757e-02 - 1.255000e+01 4.993524e+00 -1.733368e+01 8.656378e-02 - 1.256000e+01 4.418364e+00 -1.734749e+01 8.674682e-02 - 1.257000e+01 3.805654e+00 -1.736130e+01 8.697064e-02 - 1.258000e+01 3.172377e+00 -1.737512e+01 8.715550e-02 - 1.259000e+01 2.535149e+00 -1.738893e+01 8.723579e-02 - 1.260000e+01 1.909600e+00 -1.740274e+01 8.718240e-02 - 1.261000e+01 1.309839e+00 -1.741655e+01 8.701253e-02 - 1.262000e+01 7.480110e-01 -1.743036e+01 8.678406e-02 - 1.263000e+01 2.339870e-01 -1.744417e+01 8.657617e-02 - 1.264000e+01 -2.248141e-01 -1.745799e+01 8.646206e-02 - 1.265000e+01 -6.234624e-01 -1.747180e+01 8.648318e-02 - 1.266000e+01 -9.594159e-01 -1.748561e+01 8.663426e-02 - 1.267000e+01 -1.232294e+00 -1.749942e+01 8.686518e-02 - 1.268000e+01 -1.443546e+00 -1.751323e+01 8.709868e-02 - 1.269000e+01 -1.596039e+00 -1.752704e+01 8.725726e-02 - 1.270000e+01 -1.693595e+00 -1.754086e+01 8.728943e-02 - 1.271000e+01 -1.740512e+00 -1.755467e+01 8.718665e-02 - 1.272000e+01 -1.741106e+00 -1.756848e+01 8.698587e-02 - 1.273000e+01 -1.699295e+00 -1.758229e+01 8.675708e-02 - 1.274000e+01 -1.618267e+00 -1.759610e+01 8.657944e-02 - 1.275000e+01 -1.500248e+00 -1.760991e+01 8.651388e-02 - 1.276000e+01 -1.346380e+00 -1.762373e+01 8.658162e-02 - 1.277000e+01 -1.156738e+00 -1.763754e+01 8.675681e-02 - 1.278000e+01 -9.304549e-01 -1.765135e+01 8.697617e-02 - 1.279000e+01 -6.659689e-01 -1.766516e+01 8.716167e-02 - 1.280000e+01 -3.613674e-01 -1.767897e+01 8.724787e-02 - 1.281000e+01 -1.479615e-02 -1.769278e+01 8.720413e-02 - 1.282000e+01 3.750883e-01 -1.770660e+01 8.704486e-02 - 1.283000e+01 8.086627e-01 -1.772041e+01 8.682463e-02 - 1.284000e+01 1.284911e+00 -1.773422e+01 8.661965e-02 - 1.285000e+01 1.801066e+00 -1.774803e+01 8.650142e-02 - 1.286000e+01 2.352344e+00 -1.776184e+01 8.651145e-02 - 1.287000e+01 2.931804e+00 -1.777565e+01 8.664630e-02 - 1.288000e+01 3.530348e+00 -1.778947e+01 8.685881e-02 - 1.289000e+01 4.136866e+00 -1.780328e+01 8.707494e-02 - 1.290000e+01 4.738538e+00 -1.781709e+01 8.721979e-02 - 1.291000e+01 5.321262e+00 -1.783090e+01 8.724332e-02 - 1.292000e+01 5.870205e+00 -1.784471e+01 8.713713e-02 - 1.293000e+01 6.370443e+00 -1.785852e+01 8.693730e-02 - 1.294000e+01 6.807651e+00 -1.787234e+01 8.671240e-02 - 1.295000e+01 7.168799e+00 -1.788615e+01 8.654021e-02 - 1.296000e+01 7.442828e+00 -1.789996e+01 8.648076e-02 - 1.297000e+01 7.621238e+00 -1.791377e+01 8.655504e-02 - 1.298000e+01 7.698580e+00 -1.792758e+01 8.673754e-02 - 1.299000e+01 7.672791e+00 -1.794139e+01 8.696542e-02 - 1.300000e+01 7.545364e+00 -1.795521e+01 8.716080e-02 - 1.301000e+01 7.321336e+00 -1.796902e+01 8.725769e-02 - 1.302000e+01 7.009091e+00 -1.798283e+01 8.722421e-02 - 1.303000e+01 6.619978e+00 -1.799664e+01 8.707300e-02 - 1.304000e+01 6.167776e+00 -1.801045e+01 8.685689e-02 - 1.305000e+01 5.668028e+00 -1.802426e+01 8.665092e-02 - 1.306000e+01 5.137281e+00 -1.803808e+01 8.652655e-02 - 1.307000e+01 4.592276e+00 -1.805189e+01 8.652657e-02 - 1.308000e+01 4.049143e+00 -1.806570e+01 8.664985e-02 - 1.309000e+01 3.522635e+00 -1.807951e+01 8.685195e-02 - 1.310000e+01 3.025452e+00 -1.809332e+01 8.706123e-02 - 1.311000e+01 2.567700e+00 -1.810714e+01 8.720411e-02 - 1.312000e+01 2.156499e+00 -1.812095e+01 8.723055e-02 - 1.313000e+01 1.795783e+00 -1.813476e+01 8.713085e-02 - 1.314000e+01 1.486275e+00 -1.814857e+01 8.693898e-02 - 1.315000e+01 1.225663e+00 -1.816238e+01 8.672112e-02 - 1.316000e+01 1.008933e+00 -1.817619e+01 8.655317e-02 - 1.317000e+01 8.288618e-01 -1.819001e+01 8.649430e-02 - 1.318000e+01 6.766120e-01 -1.820382e+01 8.656584e-02 - 1.319000e+01 5.424062e-01 -1.821763e+01 8.674359e-02 - 1.320000e+01 4.162247e-01 -1.823144e+01 8.696646e-02 - 1.321000e+01 2.884859e-01 -1.824525e+01 8.715806e-02 - 1.322000e+01 1.506670e-01 -1.825906e+01 8.725317e-02 - 1.323000e+01 -4.176142e-03 -1.827288e+01 8.721970e-02 - 1.324000e+01 -1.810185e-01 -1.828669e+01 8.706934e-02 - 1.325000e+01 -3.826260e-01 -1.830050e+01 8.685354e-02 - 1.326000e+01 -6.094786e-01 -1.831431e+01 8.664622e-02 - 1.327000e+01 -8.598531e-01 -1.832812e+01 8.651835e-02 - 1.328000e+01 -1.130056e+00 -1.834193e+01 8.651319e-02 - 1.329000e+01 -1.414786e+00 -1.835575e+01 8.663091e-02 - 1.330000e+01 -1.707590e+00 -1.836956e+01 8.682878e-02 - 1.331000e+01 -2.001388e+00 -1.838337e+01 8.703661e-02 - 1.332000e+01 -2.289020e+00 -1.839718e+01 8.718159e-02 - 1.333000e+01 -2.563773e+00 -1.841099e+01 8.721341e-02 - 1.334000e+01 -2.819863e+00 -1.842480e+01 8.712116e-02 - 1.335000e+01 -3.052826e+00 -1.843862e+01 8.693697e-02 - 1.336000e+01 -3.259805e+00 -1.845243e+01 8.672516e-02 - 1.337000e+01 -3.439707e+00 -1.846624e+01 8.656022e-02 - 1.338000e+01 -3.593226e+00 -1.848005e+01 8.650086e-02 - 1.339000e+01 -3.722743e+00 -1.849386e+01 8.656903e-02 - 1.340000e+01 -3.832096e+00 -1.850767e+01 8.674195e-02 - 1.341000e+01 -3.926265e+00 -1.852149e+01 8.696027e-02 - 1.342000e+01 -4.010981e+00 -1.853530e+01 8.714905e-02 - 1.343000e+01 -4.092286e+00 -1.854911e+01 8.724376e-02 - 1.344000e+01 -4.176105e+00 -1.856292e+01 8.721219e-02 - 1.345000e+01 -4.267821e+00 -1.857673e+01 8.706518e-02 - 1.346000e+01 -4.371916e+00 -1.859054e+01 8.685304e-02 - 1.347000e+01 -4.491687e+00 -1.860436e+01 8.664868e-02 - 1.348000e+01 -4.629050e+00 -1.861817e+01 8.652270e-02 - 1.349000e+01 -4.784448e+00 -1.863198e+01 8.651870e-02 - 1.350000e+01 -4.956864e+00 -1.864579e+01 8.663784e-02 - 1.351000e+01 -5.143928e+00 -1.865960e+01 8.683855e-02 - 1.352000e+01 -5.342101e+00 -1.867341e+01 8.705148e-02 - 1.353000e+01 -5.546924e+00 -1.868723e+01 8.720391e-02 - 1.354000e+01 -5.753306e+00 -1.870104e+01 8.724463e-02 - 1.355000e+01 -5.955817e+00 -1.871485e+01 8.716110e-02 - 1.356000e+01 -6.148971e+00 -1.872866e+01 8.698342e-02 - 1.357000e+01 -6.327478e+00 -1.874247e+01 8.677405e-02 - 1.358000e+01 -6.486436e+00 -1.875628e+01 8.660648e-02 - 1.359000e+01 -6.621461e+00 -1.877010e+01 8.653958e-02 - 1.360000e+01 -6.728749e+00 -1.878391e+01 8.659674e-02 - 1.361000e+01 -6.805065e+00 -1.879772e+01 8.675746e-02 - 1.362000e+01 -6.847679e+00 -1.881153e+01 8.696484e-02 - 1.363000e+01 -6.854252e+00 -1.882534e+01 8.714585e-02 - 1.364000e+01 -6.822699e+00 -1.883915e+01 8.723680e-02 - 1.365000e+01 -6.751047e+00 -1.885297e+01 8.720513e-02 - 1.366000e+01 -6.637312e+00 -1.886678e+01 8.706033e-02 - 1.367000e+01 -6.479411e+00 -1.888059e+01 8.685082e-02 - 1.368000e+01 -6.275138e+00 -1.889440e+01 8.664769e-02 - 1.369000e+01 -6.022197e+00 -1.890821e+01 8.652037e-02 - 1.370000e+01 -5.718318e+00 -1.892203e+01 8.651225e-02 - 1.371000e+01 -5.361436e+00 -1.893584e+01 8.662527e-02 - 1.372000e+01 -4.949941e+00 -1.894965e+01 8.681930e-02 - 1.373000e+01 -4.482964e+00 -1.896346e+01 8.702647e-02 - 1.374000e+01 -3.960701e+00 -1.897727e+01 8.717513e-02 - 1.375000e+01 -3.384724e+00 -1.899108e+01 8.721440e-02 - 1.376000e+01 -2.758268e+00 -1.900490e+01 8.713130e-02 - 1.377000e+01 -2.086466e+00 -1.901871e+01 8.695496e-02 - 1.378000e+01 -1.376492e+00 -1.903252e+01 8.674677e-02 - 1.379000e+01 -6.376060e-01 -1.904633e+01 8.657948e-02 - 1.380000e+01 1.189154e-01 -1.906014e+01 8.651187e-02 - 1.381000e+01 8.799825e-01 -1.907395e+01 8.656795e-02 - 1.382000e+01 1.631013e+00 -1.908777e+01 8.672833e-02 - 1.383000e+01 2.356368e+00 -1.910158e+01 8.693729e-02 - 1.384000e+01 3.039881e+00 -1.911539e+01 8.712256e-02 - 1.385000e+01 3.665462e+00 -1.912920e+01 8.722057e-02 - 1.386000e+01 4.217727e+00 -1.914301e+01 8.719805e-02 - 1.387000e+01 4.682640e+00 -1.915682e+01 8.706323e-02 - 1.388000e+01 5.048115e+00 -1.917064e+01 8.686301e-02 - 1.389000e+01 5.304554e+00 -1.918445e+01 8.666718e-02 - 1.390000e+01 5.445279e+00 -1.919826e+01 8.654443e-02 - 1.391000e+01 5.466843e+00 -1.921207e+01 8.653820e-02 - 1.392000e+01 5.369194e+00 -1.922588e+01 8.665117e-02 - 1.393000e+01 5.155694e+00 -1.923969e+01 8.684424e-02 - 1.394000e+01 4.832977e+00 -1.925351e+01 8.705052e-02 - 1.395000e+01 4.410678e+00 -1.926732e+01 8.719880e-02 - 1.396000e+01 3.901022e+00 -1.928113e+01 8.723803e-02 - 1.397000e+01 3.318331e+00 -1.929494e+01 8.715449e-02 - 1.398000e+01 2.678455e+00 -1.930875e+01 8.697640e-02 - 1.399000e+01 1.998167e+00 -1.932256e+01 8.676445e-02 - 1.400000e+01 1.294562e+00 -1.933638e+01 8.659131e-02 - 1.401000e+01 5.844846e-01 -1.935019e+01 8.651647e-02 - 1.402000e+01 -1.159802e-01 -1.936400e+01 8.656534e-02 - 1.403000e+01 -7.919358e-01 -1.937781e+01 8.672021e-02 - 1.404000e+01 -1.430003e+00 -1.939162e+01 8.692668e-02 - 1.405000e+01 -2.018545e+00 -1.940543e+01 8.711310e-02 - 1.406000e+01 -2.547779e+00 -1.941925e+01 8.721543e-02 - 1.407000e+01 -3.009802e+00 -1.943306e+01 8.719908e-02 - 1.408000e+01 -3.398520e+00 -1.944687e+01 8.707031e-02 - 1.409000e+01 -3.709518e+00 -1.946068e+01 8.687410e-02 - 1.410000e+01 -3.939893e+00 -1.947449e+01 8.667883e-02 - 1.411000e+01 -4.088053e+00 -1.948830e+01 8.655280e-02 - 1.412000e+01 -4.153539e+00 -1.950212e+01 8.654022e-02 - 1.413000e+01 -4.136856e+00 -1.951593e+01 8.664544e-02 - 1.414000e+01 -4.039348e+00 -1.952974e+01 8.683144e-02 - 1.415000e+01 -3.863122e+00 -1.954355e+01 8.703311e-02 - 1.416000e+01 -3.611024e+00 -1.955736e+01 8.718022e-02 - 1.417000e+01 -3.286660e+00 -1.957117e+01 8.722168e-02 - 1.418000e+01 -2.894460e+00 -1.958499e+01 8.714281e-02 - 1.419000e+01 -2.439767e+00 -1.959880e+01 8.697027e-02 - 1.420000e+01 -1.928925e+00 -1.961261e+01 8.676321e-02 - 1.421000e+01 -1.369369e+00 -1.962642e+01 8.659313e-02 - 1.422000e+01 -7.696641e-01 -1.964023e+01 8.651919e-02 - 1.423000e+01 -1.395087e-01 -1.965405e+01 8.656721e-02 - 1.424000e+01 5.103362e-01 -1.966786e+01 8.672041e-02 - 1.425000e+01 1.168189e+00 -1.968167e+01 8.692539e-02 - 1.426000e+01 1.821671e+00 -1.969548e+01 8.711108e-02 - 1.427000e+01 2.457998e+00 -1.970929e+01 8.721334e-02 - 1.428000e+01 3.064343e+00 -1.972310e+01 8.719685e-02 - 1.429000e+01 3.628244e+00 -1.973692e+01 8.706682e-02 - 1.430000e+01 4.138038e+00 -1.975073e+01 8.686730e-02 - 1.431000e+01 4.583296e+00 -1.976454e+01 8.666640e-02 - 1.432000e+01 4.955240e+00 -1.977835e+01 8.653308e-02 - 1.433000e+01 5.247099e+00 -1.979216e+01 8.651313e-02 - 1.434000e+01 5.454396e+00 -1.980597e+01 8.661301e-02 - 1.435000e+01 5.575138e+00 -1.981979e+01 8.679766e-02 - 1.436000e+01 5.609900e+00 -1.983360e+01 8.700313e-02 - 1.437000e+01 5.561781e+00 -1.984741e+01 8.715912e-02 - 1.438000e+01 5.436253e+00 -1.986122e+01 8.721313e-02 - 1.439000e+01 5.240895e+00 -1.987503e+01 8.714810e-02 - 1.440000e+01 4.985026e+00 -1.988884e+01 8.698788e-02 - 1.441000e+01 4.679273e+00 -1.990266e+01 8.678910e-02 - 1.442000e+01 4.335075e+00 -1.991647e+01 8.662183e-02 - 1.443000e+01 3.964178e+00 -1.993028e+01 8.654520e-02 - 1.444000e+01 3.578123e+00 -1.994409e+01 8.658651e-02 - 1.445000e+01 3.187783e+00 -1.995790e+01 8.673150e-02 - 1.446000e+01 2.802954e+00 -1.997171e+01 8.692952e-02 - 1.447000e+01 2.432023e+00 -1.998553e+01 8.711160e-02 - 1.448000e+01 2.081747e+00 -1.999934e+01 8.721460e-02 - 1.449000e+01 1.757120e+00 -2.001315e+01 8.720277e-02 - 1.450000e+01 1.461361e+00 -2.002696e+01 8.707979e-02 - 1.451000e+01 1.195997e+00 -2.004077e+01 8.688753e-02 - 1.452000e+01 9.610290e-01 -2.005458e+01 8.669200e-02 - 1.453000e+01 7.551803e-01 -2.006840e+01 8.656071e-02 - 1.454000e+01 5.761841e-01 -2.008221e+01 8.653907e-02 - 1.455000e+01 4.211026e-01 -2.009602e+01 8.663426e-02 - 1.456000e+01 2.866464e-01 -2.010983e+01 8.681266e-02 - 1.457000e+01 1.694743e-01 -2.012364e+01 8.701187e-02 - 1.458000e+01 6.645185e-02 -2.013745e+01 8.716272e-02 - 1.459000e+01 -2.514443e-02 -2.015127e+01 8.721308e-02 - 1.460000e+01 -1.074894e-01 -2.016508e+01 8.714545e-02 - 1.461000e+01 -1.821416e-01 -2.017889e+01 8.698281e-02 - 1.462000e+01 -2.500448e-01 -2.019270e+01 8.678086e-02 - 1.463000e+01 -3.115920e-01 -2.020651e+01 8.660920e-02 - 1.464000e+01 -3.667410e-01 -2.022032e+01 8.652729e-02 - 1.465000e+01 -4.151668e-01 -2.023414e+01 8.656352e-02 - 1.466000e+01 -4.564340e-01 -2.024795e+01 8.670512e-02 - 1.467000e+01 -4.901719e-01 -2.026176e+01 8.690285e-02 - 1.468000e+01 -5.162349e-01 -2.027557e+01 8.708850e-02 - 1.469000e+01 -5.348347e-01 -2.028938e+01 8.719871e-02 - 1.470000e+01 -5.466305e-01 -2.030319e+01 8.719651e-02 - 1.471000e+01 -5.527720e-01 -2.031701e+01 8.708366e-02 - 1.472000e+01 -5.548896e-01 -2.033082e+01 8.689996e-02 - 1.473000e+01 -5.550346e-01 -2.034463e+01 8.670973e-02 - 1.474000e+01 -5.555731e-01 -2.035844e+01 8.657974e-02 - 1.475000e+01 -5.590439e-01 -2.037225e+01 8.655587e-02 - 1.476000e+01 -5.679911e-01 -2.038607e+01 8.664678e-02 - 1.477000e+01 -5.847853e-01 -2.039988e+01 8.682083e-02 - 1.478000e+01 -6.114465e-01 -2.041369e+01 8.701749e-02 - 1.479000e+01 -6.494827e-01 -2.042750e+01 8.716862e-02 - 1.480000e+01 -6.997548e-01 -2.044131e+01 8.722207e-02 - 1.481000e+01 -7.623785e-01 -2.045512e+01 8.715926e-02 - 1.482000e+01 -8.366678e-01 -2.046894e+01 8.700137e-02 - 1.483000e+01 -9.211228e-01 -2.048275e+01 8.680223e-02 - 1.484000e+01 -1.013463e+00 -2.049656e+01 8.663007e-02 - 1.485000e+01 -1.110697e+00 -2.051037e+01 8.654393e-02 - 1.486000e+01 -1.209235e+00 -2.052418e+01 8.657293e-02 - 1.487000e+01 -1.305011e+00 -2.053799e+01 8.670590e-02 - 1.488000e+01 -1.393638e+00 -2.055181e+01 8.689546e-02 - 1.489000e+01 -1.470557e+00 -2.056562e+01 8.707496e-02 - 1.490000e+01 -1.531186e+00 -2.057943e+01 8.718178e-02 - 1.491000e+01 -1.571064e+00 -2.059324e+01 8.717868e-02 - 1.492000e+01 -1.585969e+00 -2.060705e+01 8.706638e-02 - 1.493000e+01 -1.572029e+00 -2.062086e+01 8.688319e-02 - 1.494000e+01 -1.525798e+00 -2.063468e+01 8.669216e-02 - 1.495000e+01 -1.444329e+00 -2.064849e+01 8.655945e-02 - 1.496000e+01 -1.325218e+00 -2.066230e+01 8.653123e-02 - 1.497000e+01 -1.166644e+00 -2.067611e+01 8.661736e-02 - 1.498000e+01 -9.674051e-01 -2.068992e+01 8.678785e-02 - 1.499000e+01 -7.269469e-01 -2.070373e+01 8.698363e-02 - 1.500000e+01 -4.454000e-01 -2.071755e+01 8.713743e-02 - 1.501000e+01 -1.236221e-01 -2.073136e+01 8.719695e-02 - 1.502000e+01 2.367538e-01 -2.074517e+01 8.714255e-02 - 1.503000e+01 6.332650e-01 -2.075898e+01 8.699371e-02 - 1.504000e+01 1.062564e+00 -2.077279e+01 8.680245e-02 - 1.505000e+01 1.520368e+00 -2.078660e+01 8.663558e-02 - 1.506000e+01 2.001423e+00 -2.080042e+01 8.655162e-02 - 1.507000e+01 2.499483e+00 -2.081423e+01 8.658014e-02 - 1.508000e+01 3.007331e+00 -2.082804e+01 8.671129e-02 - 1.509000e+01 3.516827e+00 -2.084185e+01 8.689934e-02 - 1.510000e+01 4.019008e+00 -2.085566e+01 8.707903e-02 - 1.511000e+01 4.504236e+00 -2.086947e+01 8.718840e-02 - 1.512000e+01 4.962400e+00 -2.088329e+01 8.719001e-02 - 1.513000e+01 5.383163e+00 -2.089710e+01 8.708351e-02 - 1.514000e+01 5.756255e+00 -2.091091e+01 8.690578e-02 - 1.515000e+01 6.071799e+00 -2.092472e+01 8.671843e-02 - 1.516000e+01 6.320652e+00 -2.093853e+01 8.658676e-02 - 1.517000e+01 6.494763e+00 -2.095234e+01 8.655692e-02 - 1.518000e+01 6.587501e+00 -2.096616e+01 8.663953e-02 - 1.519000e+01 6.593970e+00 -2.097997e+01 8.680590e-02 - 1.520000e+01 6.511261e+00 -2.099378e+01 8.699829e-02 - 1.521000e+01 6.338644e+00 -2.100759e+01 8.715026e-02 - 1.522000e+01 6.077686e+00 -2.102140e+01 8.720959e-02 - 1.523000e+01 5.732276e+00 -2.103521e+01 8.715597e-02 - 1.524000e+01 5.308559e+00 -2.104903e+01 8.700773e-02 - 1.525000e+01 4.814774e+00 -2.106284e+01 8.681567e-02 - 1.526000e+01 4.261014e+00 -2.107665e+01 8.664582e-02 - 1.527000e+01 3.658895e+00 -2.109046e+01 8.655666e-02 - 1.528000e+01 3.021173e+00 -2.110427e+01 8.657858e-02 - 1.529000e+01 2.361305e+00 -2.111808e+01 8.670310e-02 - 1.530000e+01 1.692992e+00 -2.113190e+01 8.688598e-02 - 1.531000e+01 1.029719e+00 -2.114571e+01 8.706302e-02 - 1.532000e+01 3.843055e-01 -2.115952e+01 8.717253e-02 - 1.533000e+01 -2.314983e-01 -2.117333e+01 8.717646e-02 - 1.534000e+01 -8.073607e-01 -2.118714e+01 8.707316e-02 - 1.535000e+01 -1.334647e+00 -2.120096e+01 8.689792e-02 - 1.536000e+01 -1.806617e+00 -2.121477e+01 8.671103e-02 - 1.537000e+01 -2.218534e+00 -2.122858e+01 8.657716e-02 - 1.538000e+01 -2.567686e+00 -2.124239e+01 8.654282e-02 - 1.539000e+01 -2.853326e+00 -2.125620e+01 8.661987e-02 - 1.540000e+01 -3.076533e+00 -2.127001e+01 8.678136e-02 - 1.541000e+01 -3.240015e+00 -2.128383e+01 8.697121e-02 - 1.542000e+01 -3.347861e+00 -2.129764e+01 8.712405e-02 - 1.543000e+01 -3.405258e+00 -2.131145e+01 8.718786e-02 - 1.544000e+01 -3.418200e+00 -2.132526e+01 8.714159e-02 - 1.545000e+01 -3.393192e+00 -2.133907e+01 8.700214e-02 - 1.546000e+01 -3.336974e+00 -2.135288e+01 8.681863e-02 - 1.547000e+01 -3.256275e+00 -2.136670e+01 8.665566e-02 - 1.548000e+01 -3.157593e+00 -2.138051e+01 8.657086e-02 - 1.549000e+01 -3.047040e+00 -2.139432e+01 8.659456e-02 - 1.550000e+01 -2.930208e+00 -2.140813e+01 8.671892e-02 - 1.551000e+01 -2.812102e+00 -2.142194e+01 8.690064e-02 - 1.552000e+01 -2.697099e+00 -2.143575e+01 8.707639e-02 - 1.553000e+01 -2.588949e+00 -2.144957e+01 8.718490e-02 - 1.554000e+01 -2.490803e+00 -2.146338e+01 8.718799e-02 - 1.555000e+01 -2.405253e+00 -2.147719e+01 8.708347e-02 - 1.556000e+01 -2.334388e+00 -2.149100e+01 8.690596e-02 - 1.557000e+01 -2.279846e+00 -2.150481e+01 8.671539e-02 - 1.558000e+01 -2.242860e+00 -2.151862e+01 8.657662e-02 - 1.559000e+01 -2.224294e+00 -2.153244e+01 8.653701e-02 - 1.560000e+01 -2.224665e+00 -2.154625e+01 8.660975e-02 - 1.561000e+01 -2.244148e+00 -2.156006e+01 8.676924e-02 - 1.562000e+01 -2.282567e+00 -2.157387e+01 8.696030e-02 - 1.563000e+01 -2.339377e+00 -2.158768e+01 8.711762e-02 - 1.564000e+01 -2.413641e+00 -2.160149e+01 8.718828e-02 - 1.565000e+01 -2.504009e+00 -2.161531e+01 8.714959e-02 - 1.566000e+01 -2.608694e+00 -2.162912e+01 8.701652e-02 - 1.567000e+01 -2.725478e+00 -2.164293e+01 8.683646e-02 - 1.568000e+01 -2.851718e+00 -2.165674e+01 8.667307e-02 - 1.569000e+01 -2.984382e+00 -2.167055e+01 8.658420e-02 - 1.570000e+01 -3.120107e+00 -2.168436e+01 8.660152e-02 - 1.571000e+01 -3.255281e+00 -2.169818e+01 8.671925e-02 - 1.572000e+01 -3.386141e+00 -2.171199e+01 8.689629e-02 - 1.573000e+01 -3.508893e+00 -2.172580e+01 8.707088e-02 - 1.574000e+01 -3.619842e+00 -2.173961e+01 8.718225e-02 - 1.575000e+01 -3.715524e+00 -2.175342e+01 8.719152e-02 - 1.576000e+01 -3.792840e+00 -2.176723e+01 8.709476e-02 - 1.577000e+01 -3.849176e+00 -2.178105e+01 8.692438e-02 - 1.578000e+01 -3.882504e+00 -2.179486e+01 8.673815e-02 - 1.579000e+01 -3.891464e+00 -2.180867e+01 8.659954e-02 - 1.580000e+01 -3.875416e+00 -2.182248e+01 8.655563e-02 - 1.581000e+01 -3.834455e+00 -2.183629e+01 8.662049e-02 - 1.582000e+01 -3.769399e+00 -2.185010e+01 8.677023e-02 - 1.583000e+01 -3.681745e+00 -2.186392e+01 8.695160e-02 - 1.584000e+01 -3.573588e+00 -2.187773e+01 8.710090e-02 - 1.585000e+01 -3.447530e+00 -2.189154e+01 8.716604e-02 - 1.586000e+01 -3.306553e+00 -2.190535e+01 8.712429e-02 - 1.587000e+01 -3.153896e+00 -2.191916e+01 8.698994e-02 - 1.588000e+01 -2.992916e+00 -2.193298e+01 8.680943e-02 - 1.589000e+01 -2.826957e+00 -2.194679e+01 8.664565e-02 - 1.590000e+01 -2.659230e+00 -2.196060e+01 8.655622e-02 - 1.591000e+01 -2.492706e+00 -2.197441e+01 8.657323e-02 - 1.592000e+01 -2.330024e+00 -2.198822e+01 8.669178e-02 - 1.593000e+01 -2.173434e+00 -2.200203e+01 8.687175e-02 - 1.594000e+01 -2.024744e+00 -2.201585e+01 8.705200e-02 - 1.595000e+01 -1.885313e+00 -2.202966e+01 8.717166e-02 - 1.596000e+01 -1.756044e+00 -2.204347e+01 8.719096e-02 - 1.597000e+01 -1.637404e+00 -2.205728e+01 8.710449e-02 - 1.598000e+01 -1.529458e+00 -2.207109e+01 8.694291e-02 - 1.599000e+01 -1.431911e+00 -2.208490e+01 8.676253e-02 - 1.600000e+01 -1.344145e+00 -2.209872e+01 8.662605e-02 - 1.601000e+01 -1.265271e+00 -2.211253e+01 8.658077e-02 - 1.602000e+01 -1.194158e+00 -2.212634e+01 8.664190e-02 - 1.603000e+01 -1.129475e+00 -2.214015e+01 8.678723e-02 - 1.604000e+01 -1.069708e+00 -2.215396e+01 8.696517e-02 - 1.605000e+01 -1.013175e+00 -2.216777e+01 8.711310e-02 - 1.606000e+01 -9.580365e-01 -2.218159e+01 8.717913e-02 - 1.607000e+01 -9.022976e-01 -2.219540e+01 8.713980e-02 - 1.608000e+01 -8.438092e-01 -2.220921e+01 8.700803e-02 - 1.609000e+01 -7.802728e-01 -2.222302e+01 8.682870e-02 - 1.610000e+01 -7.092517e-01 -2.223683e+01 8.666351e-02 - 1.611000e+01 -6.281935e-01 -2.225064e+01 8.656967e-02 - 1.612000e+01 -5.344664e-01 -2.226446e+01 8.657978e-02 - 1.613000e+01 -4.254127e-01 -2.227827e+01 8.669028e-02 - 1.614000e+01 -2.984207e-01 -2.229208e+01 8.686268e-02 - 1.615000e+01 -1.510139e-01 -2.230589e+01 8.703726e-02 - 1.616000e+01 1.904334e-02 -2.231970e+01 8.715393e-02 - 1.617000e+01 2.136275e-01 -2.233351e+01 8.717286e-02 - 1.618000e+01 4.341297e-01 -2.234733e+01 8.708780e-02 - 1.619000e+01 6.813283e-01 -2.236114e+01 8.692818e-02 - 1.620000e+01 9.552663e-01 -2.237495e+01 8.674911e-02 - 1.621000e+01 1.255142e+00 -2.238876e+01 8.661257e-02 - 1.622000e+01 1.579220e+00 -2.240257e+01 8.656588e-02 - 1.623000e+01 1.924770e+00 -2.241638e+01 8.662499e-02 - 1.624000e+01 2.288039e+00 -2.243020e+01 8.676888e-02 - 1.625000e+01 2.664263e+00 -2.244401e+01 8.694708e-02 - 1.626000e+01 3.047722e+00 -2.245782e+01 8.709763e-02 - 1.627000e+01 3.431836e+00 -2.247163e+01 8.716854e-02 - 1.628000e+01 3.809304e+00 -2.248544e+01 8.713550e-02 - 1.629000e+01 4.172289e+00 -2.249925e+01 8.701008e-02 - 1.630000e+01 4.512626e+00 -2.251307e+01 8.683574e-02 - 1.631000e+01 4.822073e+00 -2.252688e+01 8.667314e-02 - 1.632000e+01 5.092568e+00 -2.254069e+01 8.657922e-02 - 1.633000e+01 5.316504e+00 -2.255450e+01 8.658719e-02 - 1.634000e+01 5.487003e+00 -2.256831e+01 8.669477e-02 - 1.635000e+01 5.598176e+00 -2.258212e+01 8.686500e-02 - 1.636000e+01 5.645362e+00 -2.259594e+01 8.703936e-02 - 1.637000e+01 5.625337e+00 -2.260975e+01 8.715825e-02 - 1.638000e+01 5.536483e+00 -2.262356e+01 8.718141e-02 - 1.639000e+01 5.378903e+00 -2.263737e+01 8.710144e-02 - 1.640000e+01 5.154495e+00 -2.265118e+01 8.694617e-02 - 1.641000e+01 4.866954e+00 -2.266500e+01 8.676927e-02 - 1.642000e+01 4.521731e+00 -2.267881e+01 8.663185e-02 - 1.643000e+01 4.125925e+00 -2.269262e+01 8.658129e-02 - 1.644000e+01 3.688121e+00 -2.270643e+01 8.663452e-02 - 1.645000e+01 3.218184e+00 -2.272024e+01 8.677209e-02 - 1.646000e+01 2.727006e+00 -2.273405e+01 8.694519e-02 - 1.647000e+01 2.226214e+00 -2.274787e+01 8.709303e-02 - 1.648000e+01 1.727859e+00 -2.276168e+01 8.716397e-02 - 1.649000e+01 1.244083e+00 -2.277549e+01 8.713314e-02 - 1.650000e+01 7.867764e-01 -2.278930e+01 8.701083e-02 - 1.651000e+01 3.672473e-01 -2.280311e+01 8.683899e-02 - 1.652000e+01 -4.106897e-03 -2.281692e+01 8.667696e-02 - 1.653000e+01 -3.180983e-01 -2.283074e+01 8.658105e-02 - 1.654000e+01 -5.670198e-01 -2.284455e+01 8.658475e-02 - 1.655000e+01 -7.448772e-01 -2.285836e+01 8.668684e-02 - 1.656000e+01 -8.475763e-01 -2.287217e+01 8.685183e-02 - 1.657000e+01 -8.730600e-01 -2.288598e+01 8.702265e-02 - 1.658000e+01 -8.213907e-01 -2.289979e+01 8.714060e-02 - 1.659000e+01 -6.947757e-01 -2.291361e+01 8.716553e-02 - 1.660000e+01 -4.975349e-01 -2.292742e+01 8.708940e-02 - 1.661000e+01 -2.360089e-01 -2.294123e+01 8.693890e-02 - 1.662000e+01 8.158785e-02 -2.295504e+01 8.676641e-02 - 1.663000e+01 4.453688e-01 -2.296885e+01 8.663207e-02 - 1.664000e+01 8.440257e-01 -2.298266e+01 8.658288e-02 - 1.665000e+01 1.265123e+00 -2.299648e+01 8.663604e-02 - 1.666000e+01 1.695427e+00 -2.301029e+01 8.677288e-02 - 1.667000e+01 2.121268e+00 -2.302410e+01 8.694556e-02 - 1.668000e+01 2.528916e+00 -2.303791e+01 8.709395e-02 - 1.669000e+01 2.904967e+00 -2.305172e+01 8.716660e-02 - 1.670000e+01 3.236733e+00 -2.306553e+01 8.713823e-02 - 1.671000e+01 3.512608e+00 -2.307935e+01 8.701830e-02 - 1.672000e+01 3.722423e+00 -2.309316e+01 8.684779e-02 - 1.673000e+01 3.857756e+00 -2.310697e+01 8.668536e-02 - 1.674000e+01 3.912201e+00 -2.312078e+01 8.658717e-02 - 1.675000e+01 3.881580e+00 -2.313459e+01 8.658725e-02 - 1.676000e+01 3.764095e+00 -2.314840e+01 8.668542e-02 - 1.677000e+01 3.560410e+00 -2.316222e+01 8.684746e-02 - 1.678000e+01 3.273652e+00 -2.317603e+01 8.701727e-02 - 1.679000e+01 2.909355e+00 -2.318984e+01 8.713655e-02 - 1.680000e+01 2.475305e+00 -2.320365e+01 8.716485e-02 - 1.681000e+01 1.981337e+00 -2.321746e+01 8.709319e-02 - 1.682000e+01 1.439047e+00 -2.323127e+01 8.694702e-02 - 1.683000e+01 8.614615e-01 -2.324509e+01 8.677753e-02 - 1.684000e+01 2.626474e-01 -2.325890e+01 8.664413e-02 - 1.685000e+01 -3.427034e-01 -2.327271e+01 8.659376e-02 - 1.686000e+01 -9.397152e-01 -2.328652e+01 8.664432e-02 - 1.687000e+01 -1.513775e+00 -2.330033e+01 8.677822e-02 - 1.688000e+01 -2.050971e+00 -2.331414e+01 8.694875e-02 - 1.689000e+01 -2.538503e+00 -2.332796e+01 8.709653e-02 - 1.690000e+01 -2.965063e+00 -2.334177e+01 8.717022e-02 - 1.691000e+01 -3.321160e+00 -2.335558e+01 8.714398e-02 - 1.692000e+01 -3.599382e+00 -2.336939e+01 8.702621e-02 - 1.693000e+01 -3.794593e+00 -2.338320e+01 8.685672e-02 - 1.694000e+01 -3.904057e+00 -2.339702e+01 8.669324e-02 - 1.695000e+01 -3.927475e+00 -2.341083e+01 8.659162e-02 - 1.696000e+01 -3.866950e+00 -2.342464e+01 8.658630e-02 - 1.697000e+01 -3.726880e+00 -2.343845e+01 8.667811e-02 - 1.698000e+01 -3.513775e+00 -2.345226e+01 8.683405e-02 - 1.699000e+01 -3.236015e+00 -2.346607e+01 8.699912e-02 - 1.700000e+01 -2.903556e+00 -2.347989e+01 8.711559e-02 - 1.701000e+01 -2.527597e+00 -2.349370e+01 8.714296e-02 - 1.702000e+01 -2.120218e+00 -2.350751e+01 8.707167e-02 - 1.703000e+01 -1.694000e+00 -2.352132e+01 8.692631e-02 - 1.704000e+01 -1.261644e+00 -2.353513e+01 8.675731e-02 - 1.705000e+01 -8.356002e-01 -2.354894e+01 8.662374e-02 - 1.706000e+01 -4.277182e-01 -2.356276e+01 8.657281e-02 - 1.707000e+01 -4.892143e-02 -2.357657e+01 8.662316e-02 - 1.708000e+01 2.910743e-01 -2.359038e+01 8.675822e-02 - 1.709000e+01 5.840006e-01 -2.360419e+01 8.693214e-02 - 1.710000e+01 8.232263e-01 -2.361800e+01 8.708590e-02 - 1.711000e+01 1.003896e+00 -2.363181e+01 8.716778e-02 - 1.712000e+01 1.123014e+00 -2.364563e+01 8.715096e-02 - 1.713000e+01 1.179478e+00 -2.365944e+01 8.704241e-02 - 1.714000e+01 1.174056e+00 -2.367325e+01 8.688049e-02 - 1.715000e+01 1.109323e+00 -2.368706e+01 8.672189e-02 - 1.716000e+01 9.895443e-01 -2.370087e+01 8.662208e-02 - 1.717000e+01 8.205209e-01 -2.371468e+01 8.661594e-02 - 1.718000e+01 6.094028e-01 -2.372850e+01 8.670535e-02 - 1.719000e+01 3.644659e-01 -2.374231e+01 8.685859e-02 - 1.720000e+01 9.486754e-02 -2.375612e+01 8.702171e-02 - 1.721000e+01 -1.896189e-01 -2.376993e+01 8.713742e-02 - 1.722000e+01 -4.788820e-01 -2.378374e+01 8.716496e-02 - 1.723000e+01 -7.627576e-01 -2.379755e+01 8.709387e-02 - 1.724000e+01 -1.031315e+00 -2.381137e+01 8.694759e-02 - 1.725000e+01 -1.275137e+00 -2.382518e+01 8.677555e-02 - 1.726000e+01 -1.485587e+00 -2.383899e+01 8.663639e-02 - 1.727000e+01 -1.655059e+00 -2.385280e+01 8.657763e-02 - 1.728000e+01 -1.777198e+00 -2.386661e+01 8.661901e-02 - 1.729000e+01 -1.847091e+00 -2.388042e+01 8.674544e-02 - 1.730000e+01 -1.861422e+00 -2.389424e+01 8.691249e-02 - 1.731000e+01 -1.818574e+00 -2.390805e+01 8.706206e-02 - 1.732000e+01 -1.718697e+00 -2.392186e+01 8.714263e-02 - 1.733000e+01 -1.563709e+00 -2.393567e+01 8.712675e-02 - 1.734000e+01 -1.357258e+00 -2.394948e+01 8.702031e-02 - 1.735000e+01 -1.104620e+00 -2.396329e+01 8.686045e-02 - 1.736000e+01 -8.125520e-01 -2.397711e+01 8.670292e-02 - 1.737000e+01 -4.890906e-01 -2.399092e+01 8.660293e-02 - 1.738000e+01 -1.433124e-01 -2.400473e+01 8.659576e-02 - 1.739000e+01 2.149441e-01 -2.401854e+01 8.668431e-02 - 1.740000e+01 5.753838e-01 -2.403235e+01 8.683806e-02 - 1.741000e+01 9.275768e-01 -2.404616e+01 8.700392e-02 - 1.742000e+01 1.261287e+00 -2.405998e+01 8.712489e-02 - 1.743000e+01 1.566793e+00 -2.407379e+01 8.715968e-02 - 1.744000e+01 1.835197e+00 -2.408760e+01 8.709670e-02 - 1.745000e+01 2.058695e+00 -2.410141e+01 8.695786e-02 - 1.746000e+01 2.230823e+00 -2.411522e+01 8.679122e-02 - 1.747000e+01 2.346639e+00 -2.412903e+01 8.665454e-02 - 1.748000e+01 2.402862e+00 -2.414285e+01 8.659530e-02 - 1.749000e+01 2.397953e+00 -2.415666e+01 8.663394e-02 - 1.750000e+01 2.332120e+00 -2.417047e+01 8.675670e-02 - 1.751000e+01 2.207283e+00 -2.418428e+01 8.692050e-02 - 1.752000e+01 2.026962e+00 -2.419809e+01 8.706826e-02 - 1.753000e+01 1.796122e+00 -2.421191e+01 8.714880e-02 - 1.754000e+01 1.520973e+00 -2.422572e+01 8.713429e-02 - 1.755000e+01 1.208728e+00 -2.423953e+01 8.702966e-02 - 1.756000e+01 8.673386e-01 -2.425334e+01 8.687089e-02 - 1.757000e+01 5.052165e-01 -2.426715e+01 8.671285e-02 - 1.758000e+01 1.309496e-01 -2.428096e+01 8.661037e-02 - 1.759000e+01 -2.469724e-01 -2.429478e+01 8.659908e-02 - 1.760000e+01 -6.204145e-01 -2.430859e+01 8.668283e-02 - 1.761000e+01 -9.818255e-01 -2.432240e+01 8.683227e-02 - 1.762000e+01 -1.324432e+00 -2.433621e+01 8.699534e-02 - 1.763000e+01 -1.642390e+00 -2.435002e+01 8.711552e-02 - 1.764000e+01 -1.930898e+00 -2.436383e+01 8.715136e-02 - 1.765000e+01 -2.186256e+00 -2.437765e+01 8.709049e-02 - 1.766000e+01 -2.405888e+00 -2.439146e+01 8.695380e-02 - 1.767000e+01 -2.588317e+00 -2.440527e+01 8.678836e-02 - 1.768000e+01 -2.733104e+00 -2.441908e+01 8.665140e-02 - 1.769000e+01 -2.840752e+00 -2.443289e+01 8.659050e-02 - 1.770000e+01 -2.912593e+00 -2.444670e+01 8.662688e-02 - 1.771000e+01 -2.950643e+00 -2.446052e+01 8.674783e-02 - 1.772000e+01 -2.957458e+00 -2.447433e+01 8.691132e-02 - 1.773000e+01 -2.935981e+00 -2.448814e+01 8.706087e-02 - 1.774000e+01 -2.889393e+00 -2.450195e+01 8.714520e-02 - 1.775000e+01 -2.820974e+00 -2.451576e+01 8.713574e-02 - 1.776000e+01 -2.733977e+00 -2.452957e+01 8.703622e-02 - 1.777000e+01 -2.631524e+00 -2.454339e+01 8.688139e-02 - 1.778000e+01 -2.516520e+00 -2.455720e+01 8.672516e-02 - 1.779000e+01 -2.391589e+00 -2.457101e+01 8.662212e-02 - 1.780000e+01 -2.259035e+00 -2.458482e+01 8.660840e-02 - 1.781000e+01 -2.120827e+00 -2.459863e+01 8.668891e-02 - 1.782000e+01 -1.978597e+00 -2.461244e+01 8.683560e-02 - 1.783000e+01 -1.833662e+00 -2.462626e+01 8.699740e-02 - 1.784000e+01 -1.687057e+00 -2.464007e+01 8.711823e-02 - 1.785000e+01 -1.539578e+00 -2.465388e+01 8.715627e-02 - 1.786000e+01 -1.391838e+00 -2.466769e+01 8.709820e-02 - 1.787000e+01 -1.244314e+00 -2.468150e+01 8.696366e-02 - 1.788000e+01 -1.097405e+00 -2.469531e+01 8.679860e-02 - 1.789000e+01 -9.514796e-01 -2.470913e+01 8.665973e-02 - 1.790000e+01 -8.069198e-01 -2.472294e+01 8.659487e-02 - 1.791000e+01 -6.641559e-01 -2.473675e+01 8.662618e-02 - 1.792000e+01 -5.236915e-01 -2.475056e+01 8.674239e-02 - 1.793000e+01 -3.861179e-01 -2.476437e+01 8.690283e-02 - 1.794000e+01 -2.521187e-01 -2.477818e+01 8.705183e-02 - 1.795000e+01 -1.224641e-01 -2.479200e+01 8.713817e-02 - 1.796000e+01 2.002381e-03 -2.480581e+01 8.713247e-02 - 1.797000e+01 1.203851e-01 -2.481962e+01 8.703715e-02 - 1.798000e+01 2.317610e-01 -2.483343e+01 8.688545e-02 - 1.799000e+01 3.352080e-01 -2.484724e+01 8.673017e-02 - 1.800000e+01 4.298322e-01 -2.486105e+01 8.662547e-02 - 1.801000e+01 5.147948e-01 -2.487487e+01 8.660800e-02 - 1.802000e+01 5.893341e-01 -2.488868e+01 8.668387e-02 - 1.803000e+01 6.527827e-01 -2.490249e+01 8.682659e-02 - 1.804000e+01 7.045791e-01 -2.491630e+01 8.698645e-02 - 1.805000e+01 7.442724e-01 -2.493011e+01 8.710806e-02 - 1.806000e+01 7.715211e-01 -2.494393e+01 8.714944e-02 - 1.807000e+01 7.860873e-01 -2.495774e+01 8.709627e-02 - 1.808000e+01 7.878271e-01 -2.497155e+01 8.696669e-02 - 1.809000e+01 7.766795e-01 -2.498536e+01 8.680515e-02 - 1.810000e+01 7.526563e-01 -2.499917e+01 8.666724e-02 - 1.811000e+01 7.158358e-01 -2.501298e+01 8.660047e-02 - 1.812000e+01 6.663611e-01 -2.502680e+01 8.662762e-02 - 1.813000e+01 6.044479e-01 -2.504061e+01 8.673865e-02 - 1.814000e+01 5.303998e-01 -2.505442e+01 8.689440e-02 - 1.815000e+01 4.446352e-01 -2.506823e+01 8.704050e-02 - 1.816000e+01 3.477236e-01 -2.508204e+01 8.712634e-02 - 1.817000e+01 2.404307e-01 -2.509585e+01 8.712243e-02 - 1.818000e+01 1.237700e-01 -2.510967e+01 8.703037e-02 - 1.819000e+01 -9.416308e-04 -2.512348e+01 8.688225e-02 - 1.820000e+01 -1.320299e-01 -2.513729e+01 8.672973e-02 - 1.821000e+01 -2.674146e-01 -2.515110e+01 8.662628e-02 - 1.822000e+01 -4.045726e-01 -2.516491e+01 8.660846e-02 - 1.823000e+01 -5.405171e-01 -2.517872e+01 8.668296e-02 - 1.824000e+01 -6.717992e-01 -2.519254e+01 8.682420e-02 - 1.825000e+01 -7.945361e-01 -2.520635e+01 8.698340e-02 - 1.826000e+01 -9.044691e-01 -2.522016e+01 8.710574e-02 - 1.827000e+01 -9.970535e-01 -2.523397e+01 8.714922e-02 - 1.828000e+01 -1.067581e+00 -2.524778e+01 8.709899e-02 - 1.829000e+01 -1.111334e+00 -2.526159e+01 8.697229e-02 - 1.830000e+01 -1.123760e+00 -2.527541e+01 8.681263e-02 - 1.831000e+01 -1.100680e+00 -2.528922e+01 8.667502e-02 - 1.832000e+01 -1.038493e+00 -2.530303e+01 8.660692e-02 - 1.833000e+01 -9.343971e-01 -2.531684e+01 8.663167e-02 - 1.834000e+01 -7.865948e-01 -2.533065e+01 8.674018e-02 - 1.835000e+01 -5.944846e-01 -2.534446e+01 8.689429e-02 - 1.836000e+01 -3.588183e-01 -2.535828e+01 8.704028e-02 - 1.837000e+01 -8.181862e-02 -2.537209e+01 8.712763e-02 - 1.838000e+01 2.327552e-01 -2.538590e+01 8.712632e-02 - 1.839000e+01 5.796003e-01 -2.539971e+01 8.703698e-02 - 1.840000e+01 9.519272e-01 -2.541352e+01 8.689062e-02 - 1.841000e+01 1.341585e+00 -2.542733e+01 8.673808e-02 - 1.842000e+01 1.739249e+00 -2.544115e+01 8.663261e-02 - 1.843000e+01 2.134674e+00 -2.545496e+01 8.661124e-02 - 1.844000e+01 2.517002e+00 -2.546877e+01 8.668172e-02 - 1.845000e+01 2.875107e+00 -2.548258e+01 8.681972e-02 - 1.846000e+01 3.197976e+00 -2.549639e+01 8.697754e-02 - 1.847000e+01 3.475105e+00 -2.551020e+01 8.710080e-02 - 1.848000e+01 3.696893e+00 -2.552402e+01 8.714724e-02 - 1.849000e+01 3.855011e+00 -2.553783e+01 8.710102e-02 - 1.850000e+01 3.942748e+00 -2.555164e+01 8.697805e-02 - 1.851000e+01 3.955291e+00 -2.556545e+01 8.682055e-02 - 1.852000e+01 3.889955e+00 -2.557926e+01 8.668268e-02 - 1.853000e+01 3.746327e+00 -2.559307e+01 8.661186e-02 - 1.854000e+01 3.526329e+00 -2.560689e+01 8.663212e-02 - 1.855000e+01 3.234200e+00 -2.562070e+01 8.673571e-02 - 1.856000e+01 2.876383e+00 -2.563451e+01 8.688589e-02 - 1.857000e+01 2.461332e+00 -2.564832e+01 8.703003e-02 - 1.858000e+01 1.999250e+00 -2.566213e+01 8.711799e-02 - 1.859000e+01 1.501751e+00 -2.567595e+01 8.711936e-02 - 1.860000e+01 9.814823e-01 -2.568976e+01 8.703370e-02 - 1.861000e+01 4.517027e-01 -2.570357e+01 8.689062e-02 - 1.862000e+01 -7.414835e-02 -2.571738e+01 8.673974e-02 - 1.863000e+01 -5.828892e-01 -2.573119e+01 8.663363e-02 - 1.864000e+01 -1.062014e+00 -2.574500e+01 8.660942e-02 - 1.865000e+01 -1.500081e+00 -2.575882e+01 8.667576e-02 - 1.866000e+01 -1.887051e+00 -2.577263e+01 8.680969e-02 - 1.867000e+01 -2.214570e+00 -2.578644e+01 8.696490e-02 - 1.868000e+01 -2.476187e+00 -2.580025e+01 8.708798e-02 - 1.869000e+01 -2.667493e+00 -2.581406e+01 8.713694e-02 - 1.870000e+01 -2.786196e+00 -2.582787e+01 8.709541e-02 - 1.871000e+01 -2.832105e+00 -2.584169e+01 8.697819e-02 - 1.872000e+01 -2.807064e+00 -2.585550e+01 8.682608e-02 - 1.873000e+01 -2.714802e+00 -2.586931e+01 8.669201e-02 - 1.874000e+01 -2.560741e+00 -2.588312e+01 8.662265e-02 - 1.875000e+01 -2.351752e+00 -2.589693e+01 8.664204e-02 - 1.876000e+01 -2.095870e+00 -2.591074e+01 8.674305e-02 - 1.877000e+01 -1.802001e+00 -2.592456e+01 8.689001e-02 - 1.878000e+01 -1.479602e+00 -2.593837e+01 8.703136e-02 - 1.879000e+01 -1.138366e+00 -2.595218e+01 8.711776e-02 - 1.880000e+01 -7.879214e-01 -2.596599e+01 8.711906e-02 - 1.881000e+01 -4.375466e-01 -2.597980e+01 8.703452e-02 - 1.882000e+01 -9.591223e-02 -2.599361e+01 8.689316e-02 - 1.883000e+01 2.291400e-01 -2.600743e+01 8.674382e-02 - 1.884000e+01 5.307793e-01 -2.602124e+01 8.663848e-02 - 1.885000e+01 8.033258e-01 -2.603505e+01 8.661408e-02 - 1.886000e+01 1.042344e+00 -2.604886e+01 8.667944e-02 - 1.887000e+01 1.244694e+00 -2.606267e+01 8.681211e-02 - 1.888000e+01 1.408534e+00 -2.607648e+01 8.696633e-02 - 1.889000e+01 1.533284e+00 -2.609030e+01 8.708914e-02 - 1.890000e+01 1.619555e+00 -2.610411e+01 8.713861e-02 - 1.891000e+01 1.669032e+00 -2.611792e+01 8.709817e-02 - 1.892000e+01 1.684341e+00 -2.613173e+01 8.698215e-02 - 1.893000e+01 1.668888e+00 -2.614554e+01 8.683088e-02 - 1.894000e+01 1.626680e+00 -2.615935e+01 8.669698e-02 - 1.895000e+01 1.562134e+00 -2.617317e+01 8.662709e-02 - 1.896000e+01 1.479893e+00 -2.618698e+01 8.664556e-02 - 1.897000e+01 1.384630e+00 -2.620079e+01 8.674573e-02 - 1.898000e+01 1.280880e+00 -2.621460e+01 8.689237e-02 - 1.899000e+01 1.172869e+00 -2.622841e+01 8.703415e-02 - 1.900000e+01 1.064382e+00 -2.624222e+01 8.712155e-02 - 1.901000e+01 9.586432e-01 -2.625604e+01 8.712391e-02 - 1.902000e+01 8.582358e-01 -2.626985e+01 8.703982e-02 - 1.903000e+01 7.650479e-01 -2.628366e+01 8.689764e-02 - 1.904000e+01 6.802536e-01 -2.629747e+01 8.674590e-02 - 1.905000e+01 6.043264e-01 -2.631128e+01 8.663675e-02 - 1.906000e+01 5.370840e-01 -2.632509e+01 8.660775e-02 - 1.907000e+01 4.777607e-01 -2.633891e+01 8.666869e-02 - 1.908000e+01 4.251049e-01 -2.635272e+01 8.679810e-02 - 1.909000e+01 3.774942e-01 -2.636653e+01 8.695090e-02 - 1.910000e+01 3.330653e-01 -2.638034e+01 8.707426e-02 - 1.911000e+01 2.898492e-01 -2.639415e+01 8.712585e-02 - 1.912000e+01 2.459072e-01 -2.640797e+01 8.708827e-02 - 1.913000e+01 1.994612e-01 -2.642178e+01 8.697485e-02 - 1.914000e+01 1.490112e-01 -2.643559e+01 8.682517e-02 - 1.915000e+01 9.343576e-02 -2.644940e+01 8.669150e-02 - 1.916000e+01 3.207130e-02 -2.646321e+01 8.662080e-02 - 1.917000e+01 -3.523389e-02 -2.647702e+01 8.663819e-02 - 1.918000e+01 -1.080916e-01 -2.649084e+01 8.673807e-02 - 1.919000e+01 -1.855728e-01 -2.650465e+01 8.688609e-02 - 1.920000e+01 -2.662331e-01 -2.651846e+01 8.703131e-02 - 1.921000e+01 -3.481626e-01 -2.653227e+01 8.712394e-02 - 1.922000e+01 -4.290574e-01 -2.654608e+01 8.713244e-02 - 1.923000e+01 -5.063087e-01 -2.655989e+01 8.705411e-02 - 1.924000e+01 -5.771067e-01 -2.657371e+01 8.691603e-02 - 1.925000e+01 -6.385529e-01 -2.658752e+01 8.676580e-02 - 1.926000e+01 -6.877780e-01 -2.660133e+01 8.665529e-02 - 1.927000e+01 -7.220605e-01 -2.661514e+01 8.662258e-02 - 1.928000e+01 -7.389414e-01 -2.662895e+01 8.667855e-02 - 1.929000e+01 -7.363326e-01 -2.664276e+01 8.680308e-02 - 1.930000e+01 -7.126151e-01 -2.665658e+01 8.695223e-02 - 1.931000e+01 -6.667246e-01 -2.667039e+01 8.707374e-02 - 1.932000e+01 -5.982225e-01 -2.668420e+01 8.712516e-02 - 1.933000e+01 -5.073506e-01 -2.669801e+01 8.708834e-02 - 1.934000e+01 -3.950681e-01 -2.671182e+01 8.697554e-02 - 1.935000e+01 -2.630694e-01 -2.672563e+01 8.682530e-02 - 1.936000e+01 -1.137826e-01 -2.673945e+01 8.668935e-02 - 1.937000e+01 4.965341e-02 -2.675326e+01 8.661471e-02 - 1.938000e+01 2.234330e-01 -2.676707e+01 8.662727e-02 - 1.939000e+01 4.031503e-01 -2.678088e+01 8.672263e-02 - 1.940000e+01 5.838880e-01 -2.679469e+01 8.686764e-02 - 1.941000e+01 7.603286e-01 -2.680850e+01 8.701220e-02 - 1.942000e+01 9.268876e-01 -2.682232e+01 8.710673e-02 - 1.943000e+01 1.077867e+00 -2.683613e+01 8.711916e-02 - 1.944000e+01 1.207627e+00 -2.684994e+01 8.704579e-02 - 1.945000e+01 1.310772e+00 -2.686375e+01 8.691245e-02 - 1.946000e+01 1.382344e+00 -2.687756e+01 8.676570e-02 - 1.947000e+01 1.418029e+00 -2.689137e+01 8.665689e-02 - 1.948000e+01 1.414343e+00 -2.690519e+01 8.662421e-02 - 1.949000e+01 1.368829e+00 -2.691900e+01 8.667927e-02 - 1.950000e+01 1.280213e+00 -2.693281e+01 8.680296e-02 - 1.951000e+01 1.148547e+00 -2.694662e+01 8.695227e-02 - 1.952000e+01 9.753031e-01 -2.696043e+01 8.707545e-02 - 1.953000e+01 7.634311e-01 -2.697424e+01 8.712995e-02 - 1.954000e+01 5.173547e-01 -2.698806e+01 8.709697e-02 - 1.955000e+01 2.429157e-01 -2.700187e+01 8.698780e-02 - 1.956000e+01 -5.274497e-02 -2.701568e+01 8.684001e-02 - 1.957000e+01 -3.613665e-01 -2.702949e+01 8.670468e-02 - 1.958000e+01 -6.738055e-01 -2.704330e+01 8.662878e-02 - 1.959000e+01 -9.803250e-01 -2.705711e+01 8.663873e-02 - 1.960000e+01 -1.270927e+00 -2.707093e+01 8.673105e-02 - 1.961000e+01 -1.535714e+00 -2.708474e+01 8.687359e-02 - 1.962000e+01 -1.765271e+00 -2.709855e+01 8.701693e-02 - 1.963000e+01 -1.951044e+00 -2.711236e+01 8.711161e-02 - 1.964000e+01 -2.085707e+00 -2.712617e+01 8.712512e-02 - 1.965000e+01 -2.163487e+00 -2.713998e+01 8.705289e-02 - 1.966000e+01 -2.180452e+00 -2.715380e+01 8.691976e-02 - 1.967000e+01 -2.134721e+00 -2.716761e+01 8.677159e-02 - 1.968000e+01 -2.026606e+00 -2.718142e+01 8.665955e-02 - 1.969000e+01 -1.858664e+00 -2.719523e+01 8.662232e-02 - 1.970000e+01 -1.635658e+00 -2.720904e+01 8.667250e-02 - 1.971000e+01 -1.364429e+00 -2.722286e+01 8.679216e-02 - 1.972000e+01 -1.053676e+00 -2.723667e+01 8.693928e-02 - 1.973000e+01 -7.136597e-01 -2.725048e+01 8.706254e-02 - 1.974000e+01 -3.558338e-01 -2.726429e+01 8.711913e-02 - 1.975000e+01 7.572895e-03 -2.727810e+01 8.708940e-02 - 1.976000e+01 3.640104e-01 -2.729191e+01 8.698344e-02 - 1.977000e+01 7.010758e-01 -2.730573e+01 8.683771e-02 - 1.978000e+01 1.006975e+00 -2.731954e+01 8.670262e-02 - 1.979000e+01 1.270958e+00 -2.733335e+01 8.662514e-02 - 1.980000e+01 1.483711e+00 -2.734716e+01 8.663239e-02 - 1.981000e+01 1.637679e+00 -2.736097e+01 8.672204e-02 - 1.982000e+01 1.727326e+00 -2.737478e+01 8.686318e-02 - 1.983000e+01 1.749294e+00 -2.738860e+01 8.700723e-02 - 1.984000e+01 1.702483e+00 -2.740241e+01 8.710492e-02 - 1.985000e+01 1.588034e+00 -2.741622e+01 8.712322e-02 - 1.986000e+01 1.409227e+00 -2.743003e+01 8.705644e-02 - 1.987000e+01 1.171294e+00 -2.744384e+01 8.692811e-02 - 1.988000e+01 8.811625e-01 -2.745765e+01 8.678293e-02 - 1.989000e+01 5.471485e-01 -2.747147e+01 8.667148e-02 - 1.990000e+01 1.786013e-01 -2.748528e+01 8.663257e-02 - 1.991000e+01 -2.144701e-01 -2.749909e+01 8.667962e-02 - 1.992000e+01 -6.217781e-01 -2.751290e+01 8.679592e-02 - 1.993000e+01 -1.033127e+00 -2.752671e+01 8.694062e-02 - 1.994000e+01 -1.438757e+00 -2.754052e+01 8.706314e-02 - 1.995000e+01 -1.829651e+00 -2.755434e+01 8.712079e-02 - 1.996000e+01 -2.197791e+00 -2.756815e+01 8.709333e-02 - 1.997000e+01 -2.536358e+00 -2.758196e+01 8.698987e-02 - 1.998000e+01 -2.839868e+00 -2.759577e+01 8.684575e-02 - 1.999000e+01 -3.104253e+00 -2.760958e+01 8.671056e-02 - 2.000000e+01 -3.326870e+00 -2.762339e+01 8.663104e-02 diff --git a/tests/testdata/lcmo.ddp b/tests/testdata/lcmo.ddp deleted file mode 100644 index b4808b30..00000000 Binary files a/tests/testdata/lcmo.ddp and /dev/null differ diff --git a/tests/testdata/lcmo_00.gr b/tests/testdata/lcmo_00.gr deleted file mode 100644 index 0dd85532..00000000 --- a/tests/testdata/lcmo_00.gr +++ /dev/null @@ -1,57 +0,0 @@ -# Npoints -# 2001 -##### start data -#O0 rg_int sig_rg_int low_int sig_low_int rmax rhofit -#S 1 - PDF from PDFgetN lcmo x=0.000 T=10.0 qmax=35.0 -#P0 3.87291 0.30411 0.59852 0.00944 1.50 0.0783 -#L r G(r) dr dG(r) - 0.010 0.802 0.0 0.0149 - 0.020 1.550 0.0 0.0284 - 0.030 2.196 0.0 0.0393 - 0.040 2.697 0.0 0.0464 - 0.050 3.024 0.0 0.0493 - 0.060 3.160 0.0 0.0479 - 0.070 3.106 0.0 0.0427 - 0.080 2.873 0.0 0.0348 - 0.090 2.489 0.0 0.0265 - 0.100 1.989 0.0 0.0218 - 0.110 1.419 0.0 0.0243 - 0.120 0.827 0.0 0.0311 - 0.130 0.260 0.0 0.0379 - 0.140 -0.239 0.0 0.0424 - 0.150 -0.635 0.0 0.0438 - 0.160 -0.902 0.0 0.0420 - 0.170 -1.029 0.0 0.0379 - 0.180 -1.015 0.0 0.0328 - 0.190 -0.872 0.0 0.0291 - 0.200 -0.622 0.0 0.0289 - 0.210 -0.294 0.0 0.0320 - 0.220 0.077 0.0 0.0363 - 0.230 0.454 0.0 0.0398 - 0.240 0.804 0.0 0.0413 - 0.250 1.097 0.0 0.0405 - 0.260 1.312 0.0 0.0378 - 0.270 1.436 0.0 0.0342 - 0.280 1.465 0.0 0.0314 - 0.290 1.405 0.0 0.0309 - 0.300 1.273 0.0 0.0328 - 0.310 1.088 0.0 0.0360 - 0.320 0.876 0.0 0.0387 - 0.330 0.665 0.0 0.0401 - 0.340 0.480 0.0 0.0397 - 0.350 0.343 0.0 0.0376 - 0.360 0.271 0.0 0.0349 - 0.370 0.273 0.0 0.0326 - 0.380 0.349 0.0 0.0321 - 0.390 0.495 0.0 0.0334 - 0.400 0.696 0.0 0.0358 - 0.410 0.935 0.0 0.0381 - 0.420 1.190 0.0 0.0393 - 0.430 1.437 0.0 0.0390 - 0.440 1.654 0.0 0.0374 - 0.450 1.822 0.0 0.0352 - 0.460 1.928 0.0 0.0334 - 0.470 1.962 0.0 0.0329 - 0.480 1.922 0.0 0.0339 - 0.490 1.815 0.0 0.0358 - 0.500 1.650 0.0 0.0377 diff --git a/tests/testdata/lcmo_20.gr b/tests/testdata/lcmo_20.gr deleted file mode 100644 index 16faef61..00000000 --- a/tests/testdata/lcmo_20.gr +++ /dev/null @@ -1,57 +0,0 @@ -# Npoints -# 2001 -##### start data -#O0 rg_int sig_rg_int low_int sig_low_int rmax rhofit -#S 1 - PDF from PDFgetN lcmo x=0.200 T=10.0 qmax=35.0 -#P0 3.87291 0.30411 0.59852 0.00944 1.50 0.0783 -#L r G(r) dr dG(r) - 0.010 -1.834 0.0 0.0171 - 0.020 -3.568 0.0 0.0326 - 0.030 -5.110 0.0 0.0450 - 0.040 -6.380 0.0 0.0532 - 0.050 -7.317 0.0 0.0566 - 0.060 -7.885 0.0 0.0551 - 0.070 -8.072 0.0 0.0492 - 0.080 -7.890 0.0 0.0403 - 0.090 -7.374 0.0 0.0308 - 0.100 -6.581 0.0 0.0253 - 0.110 -5.579 0.0 0.0279 - 0.120 -4.446 0.0 0.0356 - 0.130 -3.263 0.0 0.0433 - 0.140 -2.106 0.0 0.0485 - 0.150 -1.042 0.0 0.0501 - 0.160 -0.126 0.0 0.0483 - 0.170 0.605 0.0 0.0437 - 0.180 1.132 0.0 0.0380 - 0.190 1.454 0.0 0.0338 - 0.200 1.583 0.0 0.0334 - 0.210 1.548 0.0 0.0368 - 0.220 1.384 0.0 0.0416 - 0.230 1.133 0.0 0.0455 - 0.240 0.838 0.0 0.0472 - 0.250 0.540 0.0 0.0464 - 0.260 0.271 0.0 0.0434 - 0.270 0.057 0.0 0.0395 - 0.280 -0.084 0.0 0.0364 - 0.290 -0.148 0.0 0.0358 - 0.300 -0.135 0.0 0.0379 - 0.310 -0.055 0.0 0.0413 - 0.320 0.076 0.0 0.0444 - 0.330 0.242 0.0 0.0459 - 0.340 0.423 0.0 0.0454 - 0.350 0.604 0.0 0.0432 - 0.360 0.770 0.0 0.0402 - 0.370 0.912 0.0 0.0377 - 0.380 1.024 0.0 0.0370 - 0.390 1.105 0.0 0.0385 - 0.400 1.156 0.0 0.0412 - 0.410 1.183 0.0 0.0437 - 0.420 1.192 0.0 0.0450 - 0.430 1.188 0.0 0.0447 - 0.440 1.176 0.0 0.0430 - 0.450 1.160 0.0 0.0405 - 0.460 1.141 0.0 0.0385 - 0.470 1.119 0.0 0.0379 - 0.480 1.092 0.0 0.0390 - 0.490 1.058 0.0 0.0412 - 0.500 1.014 0.0 0.0433 diff --git a/tests/testdata/lcmo_full.ddp b/tests/testdata/lcmo_full.ddp deleted file mode 100644 index ba77a23b..00000000 Binary files a/tests/testdata/lcmo_full.ddp and /dev/null differ diff --git a/tests/testdata/ni.ddp b/tests/testdata/ni.ddp deleted file mode 100644 index 83803af5..00000000 Binary files a/tests/testdata/ni.ddp and /dev/null differ diff --git a/tests/testutils.py b/tests/testutils.py deleted file mode 100644 index 06cedbd6..00000000 --- a/tests/testutils.py +++ /dev/null @@ -1,203 +0,0 @@ -#!/usr/bin/env python -############################################################################## -# -# diffpy.pdfgui by DANSE Diffraction group -# Simon J. L. Billinge -# (c) 2016-2024 Trustees of the Columbia University -# in the City of New York. All rights reserved. -# -# File coded by: Pavol Juhas -# -# See AUTHORS.txt for a list of people who contributed. -# See LICENSE.txt for license information. -# -############################################################################## -"""Helper routines for running other unit tests.""" - -import os -from contextlib import contextmanager -from unittest import TestCase - -import wx - -from diffpy.pdfgui.control import pdfguicontrol -from diffpy.pdfgui.gui import mainframe, pdfguiglobals - -# helper functions - - -def datafile(filename): - return "tests/testdata/" + filename - - -@contextmanager -def overridewebbrowser(fnc_open): - "Temporarily replace `webbrowser.open` with given function." - import webbrowser - - save_open = webbrowser.open - - def open_override(url, new=0, autoraise=True): - fnc_open(url) - return True - - webbrowser.open = open_override - try: - yield - finally: - webbrowser.open = save_open - - -@contextmanager -def overridefiledialog(status, paths): - "Temporarily replace wx.FileDialog with non-blocking ShowModal()." - save_filedialog = wx.FileDialog - - class NBFileDialog(wx.FileDialog): - def ShowModal(self): - return status - - def GetPath(self): - return paths[-1] if paths else "" - - def GetPaths(self): - return paths - - pass - - wx.FileDialog = NBFileDialog - try: - yield - finally: - wx.FileDialog = save_filedialog - return - - -@contextmanager -def overrideclipboard(): - "Temporarily replace wx.TheClipboard with a dummy object." - save_theclipboard = wx.TheClipboard - - class _TTheClipboard(object): - def IsSupported(self, fmt): - return False - - pass - - wx.TheClipboard = _TTheClipboard() - try: - yield wx.TheClipboard - finally: - wx.TheClipboard = save_theclipboard - return - - -def tooltiptext(widget): - tt = widget.GetToolTip() - return tt.GetTip() - - -def clickcell(grid, leftright, row, col, **kw): - """Simulate left or right mouse click over wx.grid.Grid. - - Parameters - ---------- - grid : wx.grid.Grid - The grid object to be clicked - leftright : str - The button that is clicked, possible values are ("left", "right"). - row : int - The zero-based row of the clicked cell. - col : int - The zero-based columnt of the clicked cell. - kw : misc, optional - Keyword arguments for the wx.GridEvent constructor. - Typically a keyboard modifier for the click. - """ - assert leftright in ("left", "right") - if leftright == "left": - eventtype = wx.grid.EVT_GRID_CELL_LEFT_CLICK.typeId - else: - eventtype = wx.grid.EVT_GRID_CELL_RIGHT_CLICK.typeId - kbd = {"kbd": wx.KeyboardState(**kw)} - # TODO: remove this after deprecations of wxpython 3 - if wx.VERSION[0] == 3: - kbd = {k.replace("Down", ""): v for k, v in kw.items()} - e = wx.grid.GridEvent(grid.Id, eventtype, grid, row, col, **kbd) - grid.ProcessEvent(e) - return - - -# GUI-specialized TestCase --------------------------------------------------- - - -class GUITestCase(TestCase): - "Test GUI widgets without invoking ErrorReportDialog." - - @classmethod - def setUpClass(cls): - cls._save_noerrordialog = pdfguiglobals.dbopts.noerrordialog - pdfguiglobals.dbopts.noerrordialog = True - cls._save_noconfirm = pdfguiglobals.dbopts.noconfirm - pdfguiglobals.dbopts.noconfirm = True - cls._save_cmdargs = list(pdfguiglobals.cmdargs) - cls._save_configfilename = pdfguiglobals.configfilename - cls._save_qmrun = (pdfguicontrol.PDFGuiControl.QueueManager.run,) - pdfguicontrol.PDFGuiControl.QueueManager.run = lambda self: None - cls._save_factory = (mainframe.pdfguicontrol,) - cls.__pdfguicontrol = None - assert mainframe.pdfguicontrol is pdfguicontrol.pdfguicontrol - mainframe.pdfguicontrol = cls.pdfguicontrol - pdfguicontrol.pdfguicontrol = cls.pdfguicontrol - pdfguiglobals.configfilename = os.devnull - return - - @classmethod - def tearDownClass(cls): - pdfguiglobals.dbopts.noerrordialog = cls._save_noerrordialog - pdfguiglobals.dbopts.noconfirm = cls._save_noconfirm - pdfguiglobals.cmdargs[:] = cls._save_cmdargs - pdfguiglobals.configfilename = cls._save_configfilename - (pdfguicontrol.PDFGuiControl.QueueManager.run,) = cls._save_qmrun - (mainframe.pdfguicontrol,) = cls._save_factory - (pdfguicontrol.pdfguicontrol,) = cls._save_factory - assert mainframe.pdfguicontrol is pdfguicontrol.pdfguicontrol - cls.__pdfguicontrol = None - return - - @classmethod - def setCmdArgs(cls, args): - assert hasattr(cls, "_save_cmdargs") - pdfguiglobals.cmdargs[:] = args - return - - @classmethod - def pdfguicontrol(cls, *args, **kwargs): - if cls.__pdfguicontrol is not None: - return cls.__pdfguicontrol - cls.__pdfguicontrol = pdfguicontrol.PDFGuiControl(*args, **kwargs) - return cls.pdfguicontrol() - - @staticmethod - def _mockUpMainFrame(): - return _TMainFrame() - - -# end of class GUITestCase - -# Helper for GUITestCase ----------------------------------------------------- - - -class _TMainFrame(object): - "Thin mockup of the used MainFrame methods." - - altered = False - - def needsSave(self): - self.altered = True - return - - -# end of class _TMainFrame - -# End of file diff --git a/tutorial.html b/tutorial.html new file mode 100644 index 00000000..a5316f8b --- /dev/null +++ b/tutorial.html @@ -0,0 +1,367 @@ + + + + + + + + + Tutorial — diffpy.pdfgui 3.1.0 documentation + + + + + + + + + + + + + + + + + +

+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Tutorial

+

Please, have your co-workers or students try it out and let us know if you +have any comments. We want to make it really easy for the new users to get +started with PDFgui.

+
+

Lesson 1: Creating simple fit of Ni PDF

+

Input files:

+
    +
  • +
    Ni data containing:
      +
    1. Ni-xray.gr - experimental X-ray PDF data

    2. +
    3. Ni.stru - Ni f.c.c. structure in PDFfit format

    4. +
    +
    +
    +
  • +
+

This manual will help you to get started with PDFgui. We strongly recommend that that you refer to +the book Atomic pair distribution function analysis: a primer by Simon J. L. Billinge, Kirsten Jensen +Soham Banerjee, Emil S. Bozin, Benjamin A. Frandsen, Maxwell W. Terban and Robert J. Koch, Oxford: +Oxford University Press, 2024. URL: https://global.oup.com/academic/product/atomicpair-distribution-function-analysis-9780198885801?cc=us&lang=en& +for much more extensive and detailed descriptions of carrying out fits with PDFgui (and the related program diffpy-cmi).

+

Procedure:

+
    +
  1. Open pdfgui. Instructions for doing this depend on your system, but an example would be +to open a terminal, activate your pdfgui conda environment, and type pdfgui at the prompt, +or to double-click a project file on windows.

  2. +
  3. +
    Create a new Fit:
      +
    1. In the GUI locate the Fit Tree panel. In the default layout it is at the top left of the page.

    2. +
    3. With your mouse on that panel, right-click the mouse and select “New Fit” from the pop-up menu.

    4. +
    5. By default, your fit will be called Fit 1. To give it a more meaningful name, left +click the Fit 1 name. It should open an editable box and you can type in a name for your +fit such as “Fit of Ni structure to Ni data”

    6. +
    7. Note, an alternative workflow to create a new fit is to find New fit under the Fits dropdown menu.

    8. +
    +
    +
    +
  4. +
  5. +
    Load structure model:
      +
    1. Carefully place your cursor on to the title of the Fit and right-click. Select “Insert Phase” from the pop-up menu.

    2. +
    3. Click the “Open” button and navigate to and load the Ni.stru file that you downloaded. You could select +valid structure model file, a .stru or a .cif file.

    4. +
    5. Note, an alternative workflow for adding structural models is to select New Phase from the Phases dropdown menu.

    6. +
    +
    +
    +

    If you select the Phase in the Fit Tree by left clicking on it, you will see in the +right panel 3 tabs, Configure Constraints, Results. Feel free to click one +these tabs and look inside. The Configure panel has the initial inputs from the loaded str or cif file, +The Constraints panel will hold the constraints we will set up for our fits, it should be empty now, +and the results tab will contain the results of any fit.

    +

    Note that what you see on the right is “Context Dependent”, it depends on what you have selected on the left. +By selecting a phase on the left, the tabs on the right contain information about that phase, and so on.

    +
  6. +
  7. +
    Load experimental PDF data:
      +
    1. As before, hover over your cursor over the title of your fit and right-click. This time select +Insert Data Set from the pop-up menu.

    2. +
    3. Navigate to and load the Ni-xray.gr file that you downloaded.

    4. +
    +
    +
    +

    Again, the right panel shows 3 tabs, now for properties of this dataset.

    +
  8. +
  9. +
    Define what is refined:
      +
    1. Click on the Ni-xray.gr data and select the “Constraints” tab.

    2. +
    3. Type @1 into the “Scale Factor” edit box.

    4. +
    5. Select the Ni.stru phase and its “Constraints” tab.

    6. +
    7. Fill “a”, “b”, “c” boxes with @5.

    8. +
    +
    +
    +

    Here we are defining “variables” that will be refined and giving them names +variable “@1”, “@5”, etc. and linking them to model parameters by typing them +in the text-box associated with the parameter. So by typing @1 in the +data “Scale-Factor” text box we are saying that we are logically assigning the constraint +equation data.scale_factor = variable("@1").

    +

    When we assign the three parameters a, b and c to the same variable, +@5, we are implicitly ensuring that the refinement will respect +the cubic symmetry of the nickel structure and that a = b = c, because the +three parameters are assigned to the same variable, so however much a +is changed in the refinement, b and c will be changed by the same amount. +Note that the variable ensures that changes to a, b and c are always +the same, so we have to also ensure that the initial values of a, b and c +are the same as each other to ensure that the structure is cubic and remains so.

    +

    PDFgui allows us to express more complex constraint equations than +simply assigning a parameter to a variable. +In general, we can type into be Constraints tab text box any math expression: +f(@n1, @n2, @n3, ...) where +@n1 stands for the fitted parameter, where it is understood that +n1, n2, ... are arbitrary positive integers. +This allows simple linking of related variables. For example, if we want to allow a +crystallographic site to contain either Ni or Pt, we don’t know how much Ni or Pt is +on the site, but we want it to be always fully occupied, we could create two lattice +site entries with the same fractional coordinates, with one assigned Ni as the element and the other +assigned Pt as the element. Then we could assign the Ni occupancy as @100. Then +typing 1-@100 into the constraint text box of the Pt occupancy ensures that however +much the occupancy of the Ni site goes down in a refinement, the occupancy of the Pt on that +same site goes up by the same amount. This ensures full occupancy of that site, as long +as the initial occupancies of the Ni and Pt added up to 1.

    +
  10. +
  11. +
    Start the refinement:
      +
    1. Select the fit to run by left clicking the title of the fit in the Fit Tree panel. +The Parameters panel on the right shows a list of variables that you have defined +and their initial values. Each one also has a check-box that allows you to fix them +(prevent them from varying in the subsequent refinement). Unchecked boxes mean the variable +will be refined.

    2. +
    3. When you are satisfied with the configuration, click the “gear” icon on the toolbar +and watch the fit progress in the terminal window.

    4. +
    +
    +
    +
  12. +
  13. +
    Plot the results:
      +
    1. Select the data in the fit (in this case the Ni-xray.gr dataset) by left clicking it.

    2. +
    3. Click the plot icon in the toolbar. This is the icon that looks a bit like a PDF +to the right of the Gear and the red/grey X.

    4. +
    +

    A new window pops up with the plots. It will show the data in blue, the best-fit model +curve in red, and offset below, the difference curve in green. The offset of the difference +curve appears at a default value of -5.0. You can make your plot more pretty and meaningful +by typing a different offset into the offset text box and hitting Plot again.

    +

    It is possible to configure the plot in the Plot Control panel in the GUI. +In the default layout it will be at the lower-left of the GUI panel.

    +
      +
    1. To plot the fit (as was done above) elect “r” as the X plotting variable.

    2. +
    3. Hold down shift and select “Gcalc” and “Gtrunc” as the Y plotting variables.

    4. +
    5. Click the “Plot” button.

    6. +
    +

    This panel allows more plotting options for advanced cases such as plotting the values +of parameters refined across multiple fits to extract temperature dependent information.

    +
    +
    +
  14. +
  15. Save your project for later use.

  16. +
+
+
+

Lesson 2: Build structure model using crystal symmetry

+

In the previous example the initial structure was defined by an existing file. However, PDFgui makes it very easy to build a structure model from scratch and constrain it with arbitrary crystal symmetry.

+
    +
  1. +
    Create a blank structure:
      +
    1. Click the FITTING tab.

    2. +
    3. Repeat steps 1-3a from Lesson 1, but choose the “New” button. Rename “New Phase” to “Ni fcc”.

    4. +
    +
    +
    +
  2. +
  3. +
    Define asymmetric unit:
      +
    1. Right click the header of the empty atoms grid in the “Configure” page.

    2. +
    3. Insert 1 atom using the popup menu.

    4. +
    5. Change the elem cell to “Ni”.

    6. +
    7. Select the u11-u33 cells and type “0.004” and press Enter.

    8. +
    +
    +
    +
  4. +
  5. +
    Expand to all equivalent positions:
      +
    1. Right click the first Ni atom and select “Expand space group”. A “Space Group Expansion” dialog should open.

    2. +
    3. In the dialog, select Fm-3m or just type 225 in the “Space Group” box and hit “OK”.

    4. +
    +
    +
    +

    You should now have four atoms in the atoms grid.

    +
  6. +
  7. +
    Generate symmetry constraints:
      +
    1. Select the “Constraints” tab.

    2. +
    3. Select all atoms. This can be done by dragging the mouse over the atom names or by clicking on the “elem” header.

    4. +
    5. Right click in a selected cell and select “Symmetry constraints.” A “Space Group Constraints” dialog should open.

    6. +
    7. “Fm-3m” should already appear in the “Space Group” box. If it does not, select it as you did in step 3 and hit “OK”.

    8. +
    +
    +
    +

    The u11-u33 cells should all read the same value. The “x”, “y” and “z” cells should be all empty because Ni atoms are at special positions in Fm-3m. You may try to select lower-symmetry space and check what happens with the constraints. The space group constraints may be mixed by selecting different groups of atoms, for example, when only certain species show lowered symmetry.

    +
  8. +
  9. Continue the fit as in Lesson 1.

  10. +
+
+
+

Lesson 3: Multi-stage fitting

+

Learn how to string together fits.

+
    +
  1. Create a fit as in Lesson 1.

  2. +
  3. +
    Copy the fit:
      +
    1. Right click on the fit name “Fit 1” in the right panel (the fit tree).

    2. +
    3. Select “Copy” from the pop-up menu.

    4. +
    +
    +
    +
  4. +
  5. +
    Paste the fit:
      +
    1. Right click in the empty space between the first fit in the fit tree.

    2. +
    3. Select “Paste Fit.” This will create “Fit 1_copy”, a copy of “Fit 1” in the fit tree.

    4. +
    +
    +
    +
  6. +
  7. +
    Link the fits:
      +
    1. Click on “Fit 1_copy” in the fit tree.

    2. +
    3. In the “Parameters” panel, select the entire “Initial” column.

    4. +
    5. Type =Fit 1 and then press Enter. The “Initial” values of the parameters should now read =Fit1:n, where “n” is the index of the parameter.

    6. +
    +
    +
    +

    This is the linking syntax: =name:index. +“name” is the name of another fit. +“index” is the index of a parameter in that fit. +If you omit “index”, it will default to the index of the parameter you are linking from. A linked parameter uses the refined value of the link as its initial value. This is useful when you are running several related fits.

    +
  8. +
  9. +
    Add more fit parameters:
      +
    1. Select the “Constraints” tab of the Ni.stru phase below “Fit 1_copy”.

    2. +
    3. Write @9 in the “delta2” box.

    4. +
    +
    +
    +
  10. +
  11. +
    Run the fit and plot the results:
      +
    1. Run the fit as in Lesson 1.

    2. +
    3. Plot the fit as in Lesson 1, but this time hold down Control and select the data sets from “Fit 1” and “Fit 1_copy”. You can change the “offset” in the plotting window to 0 to place the plots on top of each other.

    4. +
    +
    +
    +
  12. +
+
+
+

References

+
    +
  1. (pdf), +Th. Proffen and S. J. L. Billinge, PDFFIT a program for full profile structural refinement of the atomic pair distribution function, J. Appl. Crystallogr. 32, 572-575 (1999)

  2. +
  3. (pdf), +C. L. Farrow, P. Juhas, J. W. Liu, D. Bryndin, J. Bloch, Th. Proffen and S. J. L. Billinge, PDFfit2 and PDFgui: Computer programs for studying nanostructure in crystals, J. Phys.: Condens. Matter 19, 335219 (2007)

  4. +
+
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file