├── qiskit_aqua_interfaces ├── VERSION.txt ├── aqua │ ├── user_interface │ │ ├── input_template.json │ │ ├── __init__.py │ │ ├── __main__.py │ │ ├── command_line.py │ │ ├── _aquaguiprovider.py │ │ ├── _model.py │ │ ├── _aquathread.py │ │ ├── _controller.py │ │ └── _uipreferences.py │ ├── __init__.py │ ├── browser │ │ ├── __init__.py │ │ ├── __main__.py │ │ ├── _emptyview.py │ │ ├── _sectionpropertiesview.py │ │ ├── command_line.py │ │ ├── _scrollbarview.py │ │ ├── _controller.py │ │ ├── _sectionsview.py │ │ ├── _mainview.py │ │ └── _model.py │ └── command_line │ │ ├── __init__.py │ │ ├── __main__.py │ │ └── command_line.py ├── chemistry │ ├── user_interface │ │ ├── input_template.json │ │ ├── __init__.py │ │ ├── __main__.py │ │ ├── _chemsectionpropertiesview.py │ │ ├── command_line.py │ │ ├── _chemthread.py │ │ ├── _model.py │ │ ├── _uipreferences.py │ │ ├── _chemguiprovider.py │ │ └── _controller.py │ ├── __init__.py │ └── command_line │ │ ├── __init__.py │ │ ├── __main__.py │ │ └── command_line.py ├── __init__.py ├── user_interface │ ├── __init__.py │ ├── _emptyview.py │ ├── _scrollbarview.py │ ├── guiprovider.py │ ├── _sectiontextview.py │ ├── _sectionsview.py │ ├── _dialog.py │ ├── _toolbarview.py │ ├── _threadsafeoutputview.py │ ├── _sectionpropertiesview.py │ ├── _preferencesdialog.py │ └── _mainview.py ├── _extras_require.py └── version.py ├── MANIFEST.in ├── requirements-dev.txt ├── requirements.txt ├── test ├── resources │ ├── h2_0.735_sto-3g.hdf5 │ ├── hdf5_h2_0.735_sto-3g.txt │ └── vqe.json ├── __init__.py ├── common.py ├── test_aquamodel.py └── test_chemistrymodel.py ├── .pylintdict ├── .github ├── ISSUE_TEMPLATE │ ├── FEATURE_REQUEST.md │ ├── ENHANCEMENT_REQUEST.md │ └── BUG_REPORT.md ├── PULL_REQUEST_TEMPLATE.md └── ISSUE_TEMPLATE.md ├── Makefile ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── setup.py ├── README.md ├── CODE_OF_CONDUCT.md └── LICENSE.txt /qiskit_aqua_interfaces/VERSION.txt: -------------------------------------------------------------------------------- 1 | 0.2.1 2 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | recursive-include qiskit_aqua_interfaces *.json *.txt 2 | -------------------------------------------------------------------------------- /requirements-dev.txt: -------------------------------------------------------------------------------- 1 | discover 2 | parameterized 3 | pycodestyle 4 | pylint>=2.3 5 | pylintfileheader>=0.0.2 6 | pyenchant 7 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | qiskit-aqua>=0.6.0,<0.7.0 2 | pyobjc-core; sys_platform == 'darwin' 3 | pyobjc-framework-Cocoa; sys_platform == 'darwin' -------------------------------------------------------------------------------- /test/resources/h2_0.735_sto-3g.hdf5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qiskit-community/qiskit-aqua-interfaces/HEAD/test/resources/h2_0.735_sto-3g.hdf5 -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/aqua/user_interface/input_template.json: -------------------------------------------------------------------------------- 1 | { 2 | "algorithm": { 3 | "name": "VQE", 4 | "initial_point": null 5 | }, 6 | "backend": { 7 | "provider": "qiskit.BasicAer", 8 | "name": "statevector_simulator" 9 | } 10 | } -------------------------------------------------------------------------------- /.pylintdict: -------------------------------------------------------------------------------- 1 | args 2 | backend 3 | backends 4 | bool 5 | combobox 6 | cr 7 | dict 8 | exe 9 | filepath 10 | formatter 11 | hyperlink 12 | json 13 | lf 14 | matplotlib 15 | params 16 | pluggable 17 | pluggables 18 | popup 19 | pos 20 | qiskit 21 | relwidth 22 | repost 23 | scipy 24 | scrollbar 25 | sdk 26 | stdout 27 | str 28 | toolbar 29 | ui 30 | unicode 31 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🚀 Feature request 3 | about: Suggest an idea for this project 💡! 4 | --- 5 | 6 | 7 | 8 | 9 | ### What is the expected behavior? 10 | 11 | 12 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/ENHANCEMENT_REQUEST.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 💅 Enhancement request 3 | about: Suggest an improvement for this project 🆒! 4 | --- 5 | 6 | 7 | 8 | 9 | ### What is the expected enhancement? 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/resources/hdf5_h2_0.735_sto-3g.txt: -------------------------------------------------------------------------------- 1 | &name 2 | HDF5 H2 experiment 3 | &end 4 | 5 | &driver 6 | name=HDF5 7 | &end 8 | 9 | &hdf5 10 | hdf5_input=../h2_0.735_sto-3g.hdf5 11 | &end 12 | 13 | &operator 14 | name=hamiltonian 15 | qubit_mapping=parity 16 | &end 17 | 18 | &algorithm 19 | name=VQE 20 | &end 21 | 22 | &optimizer 23 | name=L_BFGS_B 24 | factr=10 25 | &end 26 | 27 | &variational_form 28 | name=RYRZ 29 | &end 30 | 31 | &backend 32 | provider=qiskit.BasicAer 33 | name=statevector_simulator 34 | &end 35 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/chemistry/user_interface/input_template.json: -------------------------------------------------------------------------------- 1 | { 2 | "algorithm": { 3 | "name": "VQE", 4 | "initial_point": null 5 | }, 6 | "backend": { 7 | "provider": "qiskit.BasicAer", 8 | "name": "statevector_simulator" 9 | }, 10 | "driver": { 11 | "name": "HDF5" 12 | }, 13 | "HDF5": { 14 | "hdf5_input": "molecule.hdf5" 15 | }, 16 | "operator": { 17 | "name" : "hamiltonian", 18 | "qubit_mapping": "parity" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /test/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2019 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 11 | 12 | ### Summary 13 | 14 | 15 | 16 | ### Details and comments 17 | 18 | 19 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/aqua/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/chemistry/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/aqua/browser/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/aqua/command_line/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/chemistry/command_line/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/BUG_REPORT.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🐛 Bug report 3 | about: Create a report to help us improve 🤔. 4 | --- 5 | 6 | 7 | 8 | 9 | ### Informations 10 | 11 | - **Qiskit Aqua Interfaces version**: 12 | - **Python version**: 13 | - **Operating system**: 14 | 15 | ### What is the current behavior? 16 | 17 | 18 | 19 | ### Steps to reproduce the problem 20 | 21 | 22 | 23 | ### What is the expected behavior? 24 | 25 | 26 | 27 | ### Suggested solutions 28 | 29 | 30 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/aqua/browser/__main__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Qiskit Aqua browser entry point.""" 16 | 17 | from qiskit_aqua_interfaces.aqua.browser.command_line import main 18 | 19 | main() 20 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/aqua/user_interface/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Qiskit Aqua User Interface imports""" 16 | 17 | from ._uipreferences import UIPreferences 18 | 19 | __all__ = ['UIPreferences'] 20 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/aqua/command_line/__main__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Qiskit Aqua command line entry point.""" 16 | 17 | from qiskit_aqua_interfaces.aqua.command_line.command_line import main 18 | 19 | main() 20 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/chemistry/user_interface/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Qiskit Chemistry User Interface imports""" 16 | 17 | from ._uipreferences import UIPreferences 18 | 19 | __all__ = ['UIPreferences'] 20 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/aqua/user_interface/__main__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Qiskit Aqua user interface entry point.""" 16 | 17 | from qiskit_aqua_interfaces.aqua.user_interface.command_line import main 18 | 19 | main() 20 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/chemistry/command_line/__main__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Qiskit Chemistry command line entry point.""" 16 | 17 | from qiskit_aqua_interfaces.chemistry.command_line.command_line import main 18 | 19 | main() 20 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/chemistry/user_interface/__main__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Qiskit Chemistry user interface entry point.""" 16 | 17 | from qiskit_aqua_interfaces.chemistry.user_interface.command_line import main 18 | 19 | main() 20 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Aqua Interfaces imports""" 16 | 17 | from .version import __version__ 18 | 19 | APP_DEPRECATION_MSG = '##### This application will stop working after Aqua 0.7.0 release. #####' 20 | 21 | __all__ = ['__version__'] 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | *BUG TEMPLATE* 5 | 6 | ### Informations 7 | 8 | - **Qiskit Aqua Interfaces version**: 9 | - **Python version**: 10 | - **Operating system**: 11 | 12 | ### What is the current behavior? 13 | 14 | 15 | 16 | ### Steps to reproduce the problem 17 | 18 | 19 | 20 | ### What is the expected behavior? 21 | 22 | 23 | 24 | ### Suggested solutions 25 | 26 | 27 | 28 | --- 29 | 30 | *FEATURE REQUEST TEMPLATE* 31 | 32 | ### What is the expected behavior? 33 | 34 | 35 | 36 | --- 37 | 38 | *ENHANCEMENT REQUEST TEMPLATE* 39 | 40 | ### What is the expected enhancement? 41 | 42 | 43 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # This code is part of Qiskit. 2 | # 3 | # (C) Copyright IBM 2019. 4 | # 5 | # This code is licensed under the Apache License, Version 2.0. You may 6 | # obtain a copy of this license in the LICENSE.txt file in the root directory 7 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 8 | # 9 | # Any modifications or derivative works of this code must retain this 10 | # copyright notice, and modified files need to carry a notice indicating 11 | # that they have been altered from the originals. 12 | 13 | 14 | .PHONY: lint style test 15 | 16 | lint: 17 | pylint -rn qiskit_aqua_interfaces test 18 | 19 | style: 20 | pycodestyle --max-line-length=100 qiskit_aqua_interfaces test 21 | 22 | test: 23 | python -m unittest discover -v test 24 | 25 | spell: 26 | pylint -rn --disable=all --enable=spelling --spelling-dict=en_US --spelling-private-dict-file=.pylintdict qiskit_aqua_interfaces test -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/user_interface/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Common User Interface""" 16 | 17 | from .guiprovider import GUIProvider 18 | from .base_controller import BaseController 19 | from .base_model import BaseModel 20 | from ._customwidgets import TextPopup 21 | from ._sectionpropertiesview import SectionPropertiesView 22 | from ._mainview import MainView 23 | 24 | __all__ = ['GUIProvider', 25 | 'BaseController', 26 | 'BaseModel', 27 | 'TextPopup', 28 | 'SectionPropertiesView', 29 | 'MainView'] 30 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/aqua/browser/_emptyview.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Empty Frame""" 16 | 17 | import tkinter as tk 18 | import tkinter.ttk as ttk 19 | 20 | 21 | class EmptyView(ttk.Frame): 22 | """ Aqua Browser Empty Frame """ 23 | def __init__(self, parent, **options) -> None: 24 | super(EmptyView, self).__init__(parent, **options) 25 | self._child = tk.Frame(self, background='white') 26 | 27 | def grid(self, **options): 28 | """ grid layout """ 29 | self._child.pack(side=tk.LEFT, fill=tk.BOTH, expand=tk.TRUE) 30 | ttk.Frame.grid(self, **options) 31 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/_extras_require.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Extra requirements check""" 16 | 17 | import pkg_resources 18 | 19 | 20 | def _check_extra_requires(entry_point_type, entry_point_name): 21 | """Check if extra requirements are installed""" 22 | 23 | entry_point = pkg_resources.get_entry_info('qiskit_aqua_interfaces', 24 | entry_point_type, 25 | entry_point_name) 26 | if not entry_point: 27 | raise ValueError("Entry Point not found: '{}' '{}'.".format(entry_point_type, 28 | entry_point_name)) 29 | 30 | # make sure that all extras are installed 31 | entry_point.require() 32 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/user_interface/_emptyview.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Empty view""" 16 | 17 | import tkinter as tk 18 | import tkinter.ttk as ttk 19 | 20 | 21 | class EmptyView(ttk.Frame): 22 | """ Empty View """ 23 | def __init__(self, parent, **options) -> None: 24 | super(EmptyView, self).__init__(parent, **options) 25 | self._child = tk.Frame(self, background='white') 26 | self._toolbar = ttk.Frame(self) 27 | 28 | def grid(self, **options): 29 | """ grid layout """ 30 | self._toolbar.pack(side=tk.BOTTOM, fill=tk.X) 31 | self._child.pack(side=tk.LEFT, fill=tk.BOTH, expand=tk.TRUE) 32 | ttk.Frame.grid(self, **options) 33 | 34 | def set_toolbar_size(self, size): 35 | """ set toolbar size """ 36 | self._toolbar.configure(width=size[0], height=size[1]) 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # MacOSX 2 | .DS_Store 3 | 4 | # Dolphin KDE 5 | .directory 6 | 7 | # Qiskit SDK config file 8 | Qconfig.py 9 | 10 | # editor files 11 | .vscode/ 12 | .idea/ 13 | 14 | # Standard python ignores follow 15 | 16 | # Byte-compiled / optimized / DLL files 17 | __pycache__/ 18 | *.py[cod] 19 | *$py.class 20 | 21 | # C extensions 22 | *.so 23 | *.so.dSYM 24 | *.dll 25 | 26 | # Distribution / packaging 27 | .Python 28 | env/ 29 | build/ 30 | develop-eggs/ 31 | dist/ 32 | downloads/ 33 | eggs/ 34 | .eggs/ 35 | parts/ 36 | sdist/ 37 | var/ 38 | wheels/ 39 | *.egg-info/ 40 | .installed.cfg 41 | *.egg 42 | MANIFEST 43 | install/ 44 | 45 | # PyInstaller 46 | # Usually these files are written by a python script from a template 47 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 48 | *.manifest 49 | *.spec 50 | 51 | # Installer logs 52 | pip-log.txt 53 | pip-delete-this-directory.txt 54 | 55 | # Unit test / coverage reports 56 | htmlcov/ 57 | .tox/ 58 | .coverage 59 | .coverage.* 60 | .cache 61 | nosetests.xml 62 | coverage.xml 63 | *,cover 64 | .hypothesis/ 65 | .pytest_cache/ 66 | test/*.log 67 | test/*.pdf 68 | test/*.prof 69 | 70 | # Translations 71 | *.mo 72 | *.pot 73 | 74 | # Django stuff: 75 | *.log 76 | .static_storage/ 77 | .media/ 78 | local_settings.py 79 | 80 | # Flask stuff: 81 | instance/ 82 | .webassets-cache 83 | 84 | # Scrapy stuff: 85 | .scrapy 86 | 87 | # PyBuilder 88 | target/ 89 | 90 | # Jupyter Notebook 91 | .ipynb_checkpoints 92 | 93 | # pyenv 94 | .python-version 95 | 96 | # celery beat schedule file 97 | celerybeat-schedule 98 | 99 | # SageMath parsed files 100 | *.sage.py 101 | 102 | # Environments 103 | .env 104 | .venv 105 | env/ 106 | venv/ 107 | ENV/ 108 | env.bak/ 109 | venv.bak/ 110 | 111 | # Spyder project settings 112 | .spyderproject 113 | .spyproject 114 | 115 | # Rope project settings 116 | .ropeproject 117 | 118 | # mkdocs documentation 119 | /site 120 | 121 | # mypy 122 | .mypy_cache/ 123 | -------------------------------------------------------------------------------- /test/resources/vqe.json: -------------------------------------------------------------------------------- 1 | { 2 | "algorithm": { 3 | "initial_point": null, 4 | "name": "VQE" 5 | }, 6 | "backend": { 7 | "provider": "qiskit.BasicAer", 8 | "name": "statevector_simulator", 9 | "skip_transpiler": false 10 | }, 11 | "initial_state": { 12 | "name": "ZERO" 13 | }, 14 | "input": { 15 | "aux_ops": [], 16 | "name": "EnergyInput", 17 | "qubit_op": { 18 | "paulis": [ 19 | { 20 | "coeff": { 21 | "imag": 0.0, 22 | "real": -1.052373245772859 23 | }, 24 | "label": "II" 25 | }, 26 | { 27 | "coeff": { 28 | "imag": 0.0, 29 | "real": 0.39793742484318045 30 | }, 31 | "label": "ZI" 32 | }, 33 | { 34 | "coeff": { 35 | "imag": 0.0, 36 | "real": -0.39793742484318045 37 | }, 38 | "label": "IZ" 39 | }, 40 | { 41 | "coeff": { 42 | "imag": 0.0, 43 | "real": -0.01128010425623538 44 | }, 45 | "label": "ZZ" 46 | }, 47 | { 48 | "coeff": { 49 | "imag": 0.0, 50 | "real": 0.18093119978423156 51 | }, 52 | "label": "XX" 53 | } 54 | ] 55 | } 56 | }, 57 | "optimizer": { 58 | "factr": 10, 59 | "iprint": -1, 60 | "maxfun": 1000, 61 | "name": "L_BFGS_B" 62 | }, 63 | "problem": { 64 | "name": "energy", 65 | "random_seed": null 66 | }, 67 | "variational_form": { 68 | "depth": 3, 69 | "entanglement": "linear", 70 | "entangler_map": null, 71 | "name": "RYRZ" 72 | } 73 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # This code is part of Qiskit. 2 | # 3 | # (C) Copyright IBM 2018, 2019. 4 | # 5 | # This code is licensed under the Apache License, Version 2.0. You may 6 | # obtain a copy of this license in the LICENSE.txt file in the root directory 7 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 8 | # 9 | # Any modifications or derivative works of this code must retain this 10 | # copyright notice, and modified files need to carry a notice indicating 11 | # that they have been altered from the originals. 12 | 13 | notifications: 14 | email: false 15 | 16 | cache: pip 17 | os: linux 18 | dist: xenial 19 | 20 | language: python 21 | python: 22 | - 3.5 23 | - 3.6 24 | - 3.7 25 | 26 | env: 27 | - DEPENDENCY_BRANCH=$(if [[ "$TRAVIS_BRANCH" == stable* ]]; then echo "stable"; else echo "master"; fi) 28 | 29 | before_install: 30 | # Install Dependencies 31 | - pip install --upgrade pip setuptools wheel 32 | - | 33 | # Download dependencies from master 34 | if [ "$DEPENDENCY_BRANCH" == "master" ]; then 35 | # Download github Terra 36 | wget https://codeload.github.com/Qiskit/qiskit-terra/zip/$DEPENDENCY_BRANCH -O /tmp/qiskit-terra.zip 37 | unzip /tmp/qiskit-terra.zip -d /tmp/ 38 | # Install local Qiskit Terra 39 | pip install -e /tmp/qiskit-terra-$DEPENDENCY_BRANCH --progress-bar off 40 | # Download github Ignis 41 | wget https://codeload.github.com/Qiskit/qiskit-ignis/zip/$DEPENDENCY_BRANCH -O /tmp/qiskit-ignis.zip 42 | unzip /tmp/qiskit-ignis.zip -d /tmp/ 43 | # Install local Qiskit Ignis 44 | pip install -e /tmp/qiskit-ignis-$DEPENDENCY_BRANCH --progress-bar off 45 | # download Qiskit Aqua and unzip it 46 | wget https://codeload.github.com/Qiskit/qiskit-aqua/zip/$DEPENDENCY_BRANCH -O /tmp/qiskit-aqua.zip 47 | unzip /tmp/qiskit-aqua.zip -d /tmp/ 48 | # Install local Qiskit Aqua 49 | pip install -e /tmp/qiskit-aqua-$DEPENDENCY_BRANCH --progress-bar off 50 | fi 51 | # Test 52 | install: 53 | # install spell check libraries 54 | - sudo apt-get -y install python3-enchant 55 | - sudo apt-get -y install hunspell-en-us 56 | # install library and dev requirements 57 | - pip install -U -r requirements-dev.txt --progress-bar off 58 | - pip install -e $TRAVIS_BUILD_DIR --progress-bar off 59 | script: 60 | - make spell && make style && make lint && python -m unittest discover -v test 61 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/aqua/browser/_sectionpropertiesview.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Section Properties view""" 16 | 17 | import tkinter as tk 18 | import tkinter.ttk as ttk 19 | from ._scrollbarview import ScrollbarView 20 | 21 | 22 | class SectionPropertiesView(ScrollbarView): 23 | """ Aqua Browser Section Properties View """ 24 | def __init__(self, controller, parent, **options) -> None: 25 | super(SectionPropertiesView, self).__init__(parent, **options) 26 | self._controller = controller 27 | self._tree = None 28 | 29 | def clear(self): 30 | """ clear sections """ 31 | if self._tree is not None: 32 | for i in self._tree.get_children(): 33 | self._tree.delete([i]) 34 | 35 | def populate(self, column_titles, properties): 36 | """ populate sections """ 37 | self.clear() 38 | ttk.Style().configure("BrowseSectionPropertiesView.Treeview.Heading", 39 | font=(None, 12, 'bold')) 40 | self._tree = ttk.Treeview(self, style='BrowseSectionPropertiesView.Treeview', 41 | selectmode=tk.BROWSE, columns=column_titles) 42 | self._tree.heading('#0', text='property') 43 | self.init_widgets(self._tree) 44 | for value in column_titles: 45 | self._tree.heading(value, text=value) 46 | 47 | self._controller._properties_view.grid(row=0, column=0, sticky='nsew') 48 | 49 | for name, props in properties.items(): 50 | values = [''] * len(column_titles) 51 | for k, v in props.items(): 52 | index = column_titles.index(k) 53 | if isinstance(v, list) and not v: 54 | v = str(v) 55 | values[index] = ','.join(str(t) for t in v) if isinstance(v, list) else str(v) 56 | 57 | self._tree.insert('', tk.END, text=name, values=values) 58 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | Changelog 2 | ========= 3 | 4 | All notable changes to this project will be documented in this file. 5 | 6 | The format is based on [Keep a 7 | Changelog](http://keepachangelog.com/en/1.0.0/). 8 | 9 | > **Types of changes:** 10 | > 11 | > - **Added**: for new features. 12 | > - **Changed**: for changes in existing functionality. 13 | > - **Deprecated**: for soon-to-be removed features. 14 | > - **Removed**: for now removed features. 15 | > - **Fixed**: for any bug fixes. 16 | > - **Security**: in case of vulnerabilities. 17 | 18 | 19 | [UNRELEASED](https://github.com/Qiskit/qiskit-aqua-interfaces/compare/0.2.1...HEAD) 20 | =================================================================================== 21 | 22 | [0.2.1](https://github.com/Qiskit/qiskit-aqua-interfaces/compare/0.2.0...0.2.1) - 2019-12-17 23 | ============================================================================================ 24 | 25 | Changed 26 | ------- 27 | 28 | - Application deprecate message (#54) 29 | 30 | Fixed 31 | ----- 32 | 33 | - Do not create output file on chemistry run (#53) 34 | - Change start aqua/chemistry process calls to run command line scripts (#52) 35 | - Open file only return False if file not found (#51) 36 | - Fix pylint errors, remove operator_mode (#49) 37 | 38 | 39 | 40 | [0.2.0](https://github.com/Qiskit/qiskit-aqua-interfaces/compare/0.1.0...0.2.0) - 2019-08-22 41 | ============================================================================================ 42 | 43 | Added 44 | ----- 45 | 46 | - IBMQ v2 support 47 | - More Information on About box. 48 | 49 | Changed 50 | ------- 51 | 52 | - Handle single value with different schema types, like array and integer 53 | - Improve PEP8 conformance 54 | - Remove qiskit-chemistry library dependency 55 | 56 | Fixed 57 | ----- 58 | 59 | - Refresh sections panel when removing a section 60 | - On MacOSX avoid possible matplotlib error in case it is imported by other imported libraries 61 | 62 | 63 | [0.1.0](https://github.com/Qiskit/qiskit-aqua-interfaces/compare/b1d21f0...0.1.0) - 2019-05-02 64 | ================================================================================= 65 | 66 | Added 67 | ----- 68 | 69 | - Moved Aqua GUI and command line to this repository 70 | - Moved Chemistry GUI and command line to this repository 71 | 72 | Changed 73 | ------- 74 | 75 | - Changed package name to dashes in setup.py. 76 | - Updated qiskit minimum version in setup.py. 77 | - Fixed links in readme.me. -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/user_interface/_scrollbarview.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Scrollbar View""" 16 | 17 | import tkinter as tk 18 | import tkinter.ttk as ttk 19 | 20 | 21 | class ScrollbarView(ttk.Frame): 22 | """ Scrollbar View """ 23 | def __init__(self, parent, **options) -> None: 24 | super(ScrollbarView, self).__init__(parent, **options) 25 | self._child = None 26 | self._hscrollbar = None 27 | self._vscrollbar = None 28 | 29 | def init_widgets(self, child): 30 | """ initialize widgets """ 31 | self._child = child 32 | self._hscrollbar = ttk.Scrollbar(self, orient=tk.HORIZONTAL) 33 | self._vscrollbar = ttk.Scrollbar(self, orient=tk.VERTICAL) 34 | self._child.config(yscrollcommand=self._vscrollbar.set) 35 | self._child.config(xscrollcommand=self._hscrollbar.set) 36 | self._vscrollbar.config(command=self._child.yview) 37 | self._hscrollbar.config(command=self._child.xview) 38 | 39 | def pack(self, **options): 40 | """ pack layout """ 41 | if self._hscrollbar is not None: 42 | self._hscrollbar.pack(side=tk.BOTTOM, fill=tk.X, expand=tk.FALSE) 43 | 44 | if self._vscrollbar is not None: 45 | self._vscrollbar.pack(side=tk.RIGHT, fill=tk.Y, expand=tk.FALSE) 46 | 47 | if self._child is not None: 48 | self._child.pack(side=tk.LEFT, fill=tk.BOTH, expand=tk.TRUE) 49 | 50 | ttk.Frame.pack(self, **options) 51 | 52 | def grid(self, **options): 53 | """ grid layout """ 54 | if self._hscrollbar is not None: 55 | self._hscrollbar.pack(side=tk.BOTTOM, fill=tk.X, expand=tk.FALSE) 56 | 57 | if self._vscrollbar is not None: 58 | self._vscrollbar.pack(side=tk.RIGHT, fill=tk.Y, expand=tk.FALSE) 59 | 60 | if self._child is not None: 61 | self._child.pack(side=tk.LEFT, fill=tk.BOTH, expand=tk.TRUE) 62 | 63 | ttk.Frame.grid(self, **options) 64 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/user_interface/guiprovider.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """User Interface Provider""" 16 | 17 | from abc import ABC, abstractmethod 18 | 19 | 20 | class GUIProvider(ABC): 21 | """Base class for GUIProviders.""" 22 | 23 | START, STOP = 'Start', 'Stop' 24 | 25 | @abstractmethod 26 | def __init__(self) -> None: 27 | pass 28 | 29 | @property 30 | @abstractmethod 31 | def title(self): 32 | """Return provider title.""" 33 | pass 34 | 35 | @property 36 | @abstractmethod 37 | def help_hyperlink(self): 38 | """Return provider help hyperlink.""" 39 | pass 40 | 41 | @property 42 | @abstractmethod 43 | def controller(self): 44 | """Return provider controller.""" 45 | pass 46 | 47 | @abstractmethod 48 | def create_uipreferences(self): 49 | """Creates provider UI preferences.""" 50 | pass 51 | 52 | @abstractmethod 53 | def get_logging_level(self): 54 | """get level for the named logger.""" 55 | pass 56 | 57 | @abstractmethod 58 | def set_logging_config(self, logging_config): 59 | """Update logger configurations using a SDK default one.""" 60 | pass 61 | 62 | @abstractmethod 63 | def build_logging_config(self, level): 64 | """Creates a the configuration dict of the named loggers""" 65 | pass 66 | 67 | @abstractmethod 68 | def create_section_properties_view(self, parent): 69 | """Creates provider section properties view""" 70 | pass 71 | 72 | @abstractmethod 73 | def add_toolbar_items(self, toolbar): 74 | """Add items to toolbar""" 75 | pass 76 | 77 | @abstractmethod 78 | def add_file_menu_items(self, file_menu): 79 | """Add items to file menu""" 80 | pass 81 | 82 | @abstractmethod 83 | def create_run_thread(self, model, outputview, thread_queue): 84 | """Creates run thread""" 85 | pass 86 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/user_interface/_sectiontextview.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Section Text view""" 16 | 17 | import tkinter as tk 18 | from ._toolbarview import ToolbarView 19 | from ._customwidgets import TextCustom 20 | 21 | _LINESEP = '\n' 22 | 23 | 24 | class SectionTextView(ToolbarView): 25 | """ Section Text View """ 26 | def __init__(self, controller, parent, **options) -> None: 27 | super(SectionTextView, self).__init__(parent, **options) 28 | self._controller = controller 29 | self._text_widget = TextCustom(self, wrap=tk.NONE, state=tk.NORMAL) 30 | self.init_widgets(self._text_widget) 31 | self.bind("", self._cb_update_value) 32 | self.bind("", self._cb_update_value) 33 | self._section_name = None 34 | self._text = None 35 | 36 | @property 37 | def section_name(self): 38 | """ get section name """ 39 | return self._section_name 40 | 41 | @section_name.setter 42 | def section_name(self, new_section_name): 43 | """ set section name """ 44 | self._section_name = new_section_name 45 | 46 | def populate(self, text): 47 | """ populate text """ 48 | self._text_widget.delete(1.0, tk.END) 49 | if text is not None: 50 | self._text_widget.insert(tk.END, text) 51 | 52 | self._text = text 53 | 54 | def clear(self): 55 | """ clear text """ 56 | self._text_widget.delete(1.0, tk.END) 57 | self._text = self._text_widget.get(1.0, tk.END) 58 | 59 | def _cb_update_value(self, *ignore): 60 | sep_pos = -len(_LINESEP) 61 | new_text = self._text_widget.get(1.0, tk.END) 62 | if len(new_text) >= len(_LINESEP) and new_text[sep_pos:] == _LINESEP: 63 | new_text = new_text[:sep_pos] 64 | 65 | if self._text != new_text: 66 | self._text = new_text 67 | self._controller.cb_text_set(self._section_name, new_text) 68 | 69 | def cb_defaults(self): 70 | self._controller.cb_section_defaults(self.section_name) 71 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/version.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Contains the Aqua Interfaces version.""" 16 | 17 | import os 18 | import subprocess 19 | 20 | ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) 21 | 22 | 23 | def _minimal_ext_cmd(cmd): 24 | # construct minimal environment 25 | env = {} 26 | for k in ['SYSTEMROOT', 'PATH']: 27 | v = os.environ.get(k) 28 | if v is not None: 29 | env[k] = v 30 | # LANGUAGE is used on win32 31 | env['LANGUAGE'] = 'C' 32 | env['LANG'] = 'C' 33 | env['LC_ALL'] = 'C' 34 | proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, 35 | stderr=subprocess.PIPE, env=env, 36 | cwd=os.path.join(os.path.dirname(ROOT_DIR))) 37 | stdout, stderr = proc.communicate() 38 | if proc.returncode > 0: 39 | raise OSError('Command {} exited with code {}: {}'.format( 40 | cmd, proc.returncode, stderr.strip().decode('ascii'))) 41 | return stdout 42 | 43 | 44 | def git_version(): 45 | """Get the current git head sha1.""" 46 | # Determine if we're at master 47 | try: 48 | out = _minimal_ext_cmd(['git', 'rev-parse', 'HEAD']) 49 | git_revision = out.strip().decode('ascii') 50 | except OSError: 51 | git_revision = "Unknown" 52 | 53 | return git_revision 54 | 55 | 56 | with open(os.path.join(ROOT_DIR, "VERSION.txt"), "r") as version_file: 57 | VERSION = version_file.read().strip() 58 | 59 | 60 | def get_version_info(): 61 | """Get the full version string.""" 62 | # Adding the git rev number needs to be done inside 63 | # write_version_py(), otherwise the import of scipy.version messes 64 | # up the build under Python 3. 65 | full_version = VERSION 66 | 67 | if not os.path.exists(os.path.join(os.path.dirname(ROOT_DIR), '.git')): 68 | return full_version 69 | try: 70 | release = _minimal_ext_cmd(['git', 'tag', '-l', '--points-at', 'HEAD']) 71 | except Exception: # pylint: disable=broad-except 72 | return full_version 73 | git_revision = git_version() 74 | if not release: 75 | full_version += '.dev0+' + git_revision[:7] 76 | 77 | return full_version 78 | 79 | 80 | __version__ = get_version_info() 81 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/aqua/browser/command_line.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Qiskit Aqua browser main.""" 16 | 17 | import sys 18 | import logging 19 | import tkinter as tk 20 | from qiskit_aqua_interfaces.aqua.user_interface import UIPreferences 21 | from qiskit_aqua_interfaces._extras_require import _check_extra_requires 22 | from ._mainview import MainView 23 | 24 | # pylint: disable=import-outside-toplevel 25 | 26 | 27 | def set_preferences_logging(): 28 | """Update logging setting with latest external packages""" 29 | from qiskit.aqua._logging import get_logging_level, build_logging_config, set_logging_config 30 | preferences = UIPreferences() 31 | logging_level = logging.INFO 32 | if preferences.get_logging_config() is not None: 33 | set_logging_config(preferences.get_logging_config()) 34 | logging_level = get_logging_level() 35 | 36 | preferences.set_logging_config(build_logging_config(logging_level)) 37 | preferences.save() 38 | 39 | set_logging_config(preferences.get_logging_config()) 40 | 41 | 42 | def main(): 43 | """Runs main Aqua browser command line.""" 44 | _check_extra_requires('gui_scripts', 'qiskit_aqua_browser') 45 | if sys.platform == 'darwin': 46 | # pylint: disable=no-name-in-module, import-error 47 | from Foundation import NSBundle 48 | bundle = NSBundle.mainBundle() 49 | if bundle: 50 | info = bundle.localizedInfoDictionary() or bundle.infoDictionary() 51 | info['CFBundleName'] = 'Qiskit Aqua Browser' 52 | 53 | root = tk.Tk() 54 | root.withdraw() 55 | root.update_idletasks() 56 | 57 | preferences = UIPreferences() 58 | geometry = preferences.get_browser_geometry() 59 | if geometry is None: 60 | w_s = root.winfo_screenwidth() 61 | h_s = root.winfo_screenheight() 62 | w_a = int(w_s / 1.2) 63 | h_a = int(h_s / 1.3) 64 | x = int(w_s / 2 - w_a / 2) 65 | y = int(h_s / 2 - h_a / 2) 66 | geometry = '{}x{}+{}+{}'.format(w_a, h_a, x, y) 67 | preferences.set_browser_geometry(geometry) 68 | preferences.save() 69 | 70 | root.geometry(geometry) 71 | 72 | MainView(root) 73 | root.after(0, root.deiconify) 74 | root.after(0, set_preferences_logging) 75 | root.mainloop() 76 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/aqua/browser/_scrollbarview.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Scrollbar view""" 16 | 17 | import tkinter as tk 18 | import tkinter.ttk as ttk 19 | 20 | 21 | class ScrollbarView(ttk.Frame): 22 | """ Aqua Browser Scrollbar View """ 23 | def __init__(self, parent, **options) -> None: 24 | super(ScrollbarView, self).__init__(parent, **options) 25 | self._child = None 26 | self._hscrollbar = None 27 | self._vscrollbar = None 28 | 29 | def init_widgets(self, child): 30 | """ initialize widget """ 31 | if self._child is not None: 32 | self._child.destroy() 33 | 34 | if self._hscrollbar is not None: 35 | self._hscrollbar.destroy() 36 | self._hscrollbar = None 37 | 38 | if self._vscrollbar is not None: 39 | self._vscrollbar.destroy() 40 | self._vscrollbar = None 41 | 42 | self._child = child 43 | self._hscrollbar = ttk.Scrollbar(self, orient=tk.HORIZONTAL) 44 | self._vscrollbar = ttk.Scrollbar(self, orient=tk.VERTICAL) 45 | self._child.config(yscrollcommand=self._vscrollbar.set) 46 | self._child.config(xscrollcommand=self._hscrollbar.set) 47 | self._vscrollbar.config(command=self._child.yview) 48 | self._hscrollbar.config(command=self._child.xview) 49 | 50 | def pack(self, **options): 51 | """ pack layout """ 52 | if self._hscrollbar is not None: 53 | self._hscrollbar.pack(side=tk.BOTTOM, fill=tk.X, expand=tk.FALSE) 54 | 55 | if self._vscrollbar is not None: 56 | self._vscrollbar.pack(side=tk.RIGHT, fill=tk.Y, expand=tk.FALSE) 57 | 58 | if self._child is not None: 59 | self._child.pack(side=tk.LEFT, fill=tk.BOTH, expand=tk.TRUE) 60 | 61 | ttk.Frame.pack(self, **options) 62 | 63 | def grid(self, **options): 64 | """ grid layout """ 65 | if self._hscrollbar is not None: 66 | self._hscrollbar.pack(side=tk.BOTTOM, fill=tk.X, expand=tk.FALSE) 67 | 68 | if self._vscrollbar is not None: 69 | self._vscrollbar.pack(side=tk.RIGHT, fill=tk.Y, expand=tk.FALSE) 70 | 71 | if self._child is not None: 72 | self._child.pack(side=tk.LEFT, fill=tk.BOTH, expand=tk.TRUE) 73 | 74 | ttk.Frame.grid(self, **options) 75 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/aqua/user_interface/command_line.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Qiskit Aqua user interface main.""" 16 | 17 | import sys 18 | import logging 19 | import tkinter as tk 20 | from qiskit_aqua_interfaces._extras_require import _check_extra_requires 21 | from qiskit_aqua_interfaces.user_interface._mainview import MainView 22 | from ._aquaguiprovider import AquaGUIProvider 23 | 24 | # pylint: disable=import-outside-toplevel 25 | 26 | 27 | def set_preferences_logging(): 28 | """Update logging setting with latest external packages""" 29 | from qiskit.aqua._logging import get_logging_level, build_logging_config, set_logging_config 30 | guiprovider = AquaGUIProvider() 31 | preferences = guiprovider.create_uipreferences() 32 | logging_level = logging.INFO 33 | if preferences.get_logging_config() is not None: 34 | set_logging_config(preferences.get_logging_config()) 35 | logging_level = get_logging_level() 36 | 37 | preferences.set_logging_config(build_logging_config(logging_level)) 38 | preferences.save() 39 | 40 | set_logging_config(preferences.get_logging_config()) 41 | 42 | 43 | def main(): 44 | """Runs main Aqua user interface.""" 45 | _check_extra_requires('gui_scripts', 'qiskit_aqua_ui') 46 | guiprovider = AquaGUIProvider() 47 | if sys.platform == 'darwin': 48 | # pylint: disable=no-name-in-module, import-error 49 | from Foundation import NSBundle 50 | bundle = NSBundle.mainBundle() 51 | if bundle: 52 | info = bundle.localizedInfoDictionary() or bundle.infoDictionary() 53 | info['CFBundleName'] = guiprovider.title 54 | 55 | root = tk.Tk() 56 | root.withdraw() 57 | root.update_idletasks() 58 | 59 | preferences = guiprovider.create_uipreferences() 60 | geometry = preferences.get_geometry() 61 | if geometry is None: 62 | w_s = root.winfo_screenwidth() 63 | h_s = root.winfo_screenheight() 64 | w_a = int(w_s / 1.3) 65 | h_a = int(h_s / 1.3) 66 | x = int(w_s / 2 - w_a / 2) 67 | y = int(h_s / 2 - h_a / 2) 68 | geometry = '{}x{}+{}+{}'.format(w_a, h_a, x, y) 69 | preferences.set_geometry(geometry) 70 | preferences.save() 71 | 72 | root.geometry(geometry) 73 | 74 | MainView(root, guiprovider) 75 | root.after(0, root.deiconify) 76 | root.after(0, set_preferences_logging) 77 | root.mainloop() 78 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | import setuptools 16 | import os 17 | 18 | long_description = """Qiskit Aqua Interfaces, a set of user-interface components for 19 | Qiskit Aqua.""" 20 | 21 | requirements = [ 22 | "qiskit-aqua>=0.6.0,<0.7.0", 23 | "pyobjc-core; sys_platform == 'darwin'", 24 | "pyobjc-framework-Cocoa; sys_platform == 'darwin'" 25 | ] 26 | 27 | VERSION_PATH = os.path.join(os.path.dirname(__file__), "qiskit_aqua_interfaces", "VERSION.txt") 28 | with open(VERSION_PATH, "r") as version_file: 29 | VERSION = version_file.read().strip() 30 | 31 | setuptools.setup( 32 | name='qiskit-aqua-interfaces', 33 | version=VERSION, 34 | description='Qiskit Aqua Interfaces', 35 | long_description=long_description, 36 | long_description_content_type="text/markdown", 37 | url='https://github.com/Qiskit/qiskit_aqua_interfaces', 38 | author='Qiskit Aqua Development Team', 39 | author_email='qiskit@us.ibm.com', 40 | license='Apache-2.0', 41 | classifiers=( 42 | "Environment :: Console", 43 | "License :: OSI Approved :: Apache Software License", 44 | "Intended Audience :: Developers", 45 | "Intended Audience :: Science/Research", 46 | "Operating System :: Microsoft :: Windows", 47 | "Operating System :: MacOS", 48 | "Operating System :: POSIX :: Linux", 49 | "Programming Language :: Python :: 3.5", 50 | "Programming Language :: Python :: 3.6", 51 | "Programming Language :: Python :: 3.7", 52 | "Topic :: Scientific/Engineering" 53 | ), 54 | keywords='qiskit sdk quantum aqua', 55 | packages=setuptools.find_packages(exclude=['test*']), 56 | install_requires=requirements, 57 | include_package_data=True, 58 | python_requires=">=3.5", 59 | entry_points={ 60 | 'console_scripts': [ 61 | 'qiskit_aqua_cmd=qiskit_aqua_interfaces.aqua.command_line.command_line:main', 62 | 'qiskit_chemistry_cmd=qiskit_aqua_interfaces.chemistry.command_line.command_line:main' 63 | ], 64 | 'gui_scripts': [ 65 | 'qiskit_aqua_ui=qiskit_aqua_interfaces.aqua.user_interface.command_line:main', 66 | 'qiskit_aqua_browser=qiskit_aqua_interfaces.aqua.browser.command_line:main', 67 | 'qiskit_chemistry_ui=qiskit_aqua_interfaces.chemistry.user_interface.command_line:main' 68 | ] 69 | } 70 | ) 71 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/chemistry/user_interface/_chemsectionpropertiesview.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """ Chemistry Section Properties View """ 16 | 17 | import tkinter as tk 18 | from tkinter import messagebox 19 | from qiskit_aqua_interfaces.user_interface import SectionPropertiesView, TextPopup 20 | 21 | 22 | class ChemSectionPropertiesView(SectionPropertiesView): 23 | """ Chemistry Section Properties View """ 24 | def populate(self, properties): 25 | self.clear() 26 | for property_name, value_tuple in properties.items(): 27 | value = '' if value_tuple[0] is None else str(value_tuple[0]) 28 | value = value.replace('\r', '\\r').replace('\n', '\\n') 29 | if value_tuple[1]: 30 | self._tree.insert('', tk.END, text=property_name, values=[], tags="SUBSTITUTIONS") 31 | else: 32 | self._tree.insert('', tk.END, text=property_name, values=[value]) 33 | 34 | self._tree.tag_configure('SUBSTITUTIONS', foreground='gray') 35 | self._properties = properties 36 | 37 | def _cb_tree_edit(self, event): 38 | rowid = self._tree.identify_row(event.y) 39 | if not rowid: 40 | return 41 | 42 | column = self._tree.identify_column(event.x) 43 | if column == '#1': 44 | x, y, width, height = self._tree.bbox(rowid, column) 45 | pady = height // 2 46 | 47 | item = self._tree.identify("item", event.x, event.y) 48 | property_name = self._tree.item(item, "text") 49 | value_tuple = self._properties[property_name] 50 | if not value_tuple[1]: 51 | try: 52 | self._popup_widget = self._controller.create_popup(self.section_name, 53 | property_name, 54 | self._tree, 55 | value_tuple[0]) 56 | except Exception as ex: # pylint: disable=broad-except 57 | messagebox.showerror("Error", str(ex)) 58 | return 59 | 60 | if isinstance(self._popup_widget, TextPopup): 61 | height = self._tree.winfo_height() - y 62 | self._popup_widget.place(x=x, y=y, width=width, height=height) 63 | else: 64 | self._popup_widget.place(x=x, y=y + pady, anchor=tk.W, width=width) 65 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/aqua/user_interface/_aquaguiprovider.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Aqua User Interface Provider""" 16 | 17 | from qiskit_aqua_interfaces.user_interface import GUIProvider, SectionPropertiesView 18 | from ._uipreferences import UIPreferences 19 | from ._aquathread import AquaThread 20 | from ._controller import Controller 21 | 22 | # pylint: disable=import-outside-toplevel 23 | 24 | 25 | class AquaGUIProvider(GUIProvider): 26 | """Aqua GUIProvider""" 27 | 28 | def __init__(self) -> None: 29 | super().__init__() 30 | self._controller = None 31 | 32 | @property 33 | def title(self): 34 | """Return provider title.""" 35 | return 'Qiskit Aqua' 36 | 37 | @property 38 | def help_hyperlink(self): 39 | """Return provider help hyperlink.""" 40 | return 'https://qiskit.org/' 41 | 42 | @property 43 | def controller(self): 44 | """Return provider controller.""" 45 | if self._controller is None: 46 | self._controller = Controller(self) 47 | 48 | return self._controller 49 | 50 | def create_uipreferences(self): 51 | """Creates provider UI preferences.""" 52 | return UIPreferences() 53 | 54 | def get_logging_level(self): 55 | """get level for the named logger.""" 56 | from qiskit.aqua._logging import get_logging_level as aqua_get_logging_level 57 | return aqua_get_logging_level() 58 | 59 | def set_logging_config(self, logging_config): 60 | """Update logger configurations using a SDK default one.""" 61 | from qiskit.aqua._logging import set_logging_config as aqua_set_logging_config 62 | aqua_set_logging_config(logging_config) 63 | 64 | def build_logging_config(self, level): 65 | """Creates a the configuration dict of the named loggers""" 66 | from qiskit.aqua._logging import build_logging_config as aqua_build_logging_config 67 | return aqua_build_logging_config(level) 68 | 69 | def create_section_properties_view(self, parent): 70 | """Creates provider section properties view""" 71 | return SectionPropertiesView(self.controller, parent) 72 | 73 | def add_toolbar_items(self, toolbar): 74 | """Add items to toolbar""" 75 | pass 76 | 77 | def add_file_menu_items(self, file_menu): 78 | """Add items to file menu""" 79 | pass 80 | 81 | def create_run_thread(self, model, outputview, thread_queue): 82 | """Creates run thread""" 83 | return AquaThread(model, outputview, thread_queue) 84 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/chemistry/user_interface/command_line.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Qiskit Chemistry user interface main.""" 16 | 17 | import sys 18 | import logging 19 | import tkinter as tk 20 | from tkinter import messagebox 21 | from qiskit_aqua_interfaces.user_interface import MainView 22 | from qiskit_aqua_interfaces._extras_require import _check_extra_requires 23 | from ._chemguiprovider import ChemistryGUIProvider 24 | 25 | # pylint: disable=import-outside-toplevel 26 | 27 | 28 | def set_preferences_logging(): 29 | """Update logging setting with latest external packages""" 30 | from qiskit.chemistry._logging import (get_logging_level, 31 | build_logging_config, 32 | set_logging_config) 33 | guiprovider = ChemistryGUIProvider() 34 | preferences = guiprovider.create_uipreferences() 35 | logging_level = logging.INFO 36 | if preferences.get_logging_config() is not None: 37 | set_logging_config(preferences.get_logging_config()) 38 | logging_level = get_logging_level() 39 | 40 | preferences.set_logging_config(build_logging_config(logging_level)) 41 | preferences.save() 42 | 43 | 44 | def main(): 45 | """Runs main Chemistry user interface.""" 46 | _check_extra_requires('gui_scripts', 'qiskit_chemistry_ui') 47 | error_msg = None 48 | guiprovider = ChemistryGUIProvider() 49 | 50 | if sys.platform == 'darwin' and guiprovider is not None: 51 | # pylint: disable=no-name-in-module, import-error 52 | from Foundation import NSBundle 53 | bundle = NSBundle.mainBundle() 54 | if bundle: 55 | info = bundle.localizedInfoDictionary() or bundle.infoDictionary() 56 | info['CFBundleName'] = guiprovider.title 57 | 58 | root = tk.Tk() 59 | root.withdraw() 60 | root.update_idletasks() 61 | if error_msg is not None: 62 | messagebox.showerror("Error", error_msg) 63 | return 64 | 65 | preferences = guiprovider.create_uipreferences() 66 | geometry = preferences.get_geometry() 67 | if geometry is None: 68 | w_s = root.winfo_screenwidth() 69 | h_s = root.winfo_screenheight() 70 | w_a = int(w_s / 1.3) 71 | h_a = int(h_s / 1.3) 72 | x = int(w_s / 2 - w_a / 2) 73 | y = int(h_s / 2 - h_a / 2) 74 | geometry = '{}x{}+{}+{}'.format(w_a, h_a, x, y) 75 | preferences.set_geometry(geometry) 76 | preferences.save() 77 | 78 | root.geometry(geometry) 79 | 80 | MainView(root, guiprovider) 81 | root.after(0, root.deiconify) 82 | root.after(0, set_preferences_logging) 83 | root.mainloop() 84 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Qiskit Aqua Interfaces 2 | **Qiskit** is an open-source framework for working with noisy quantum computers at the level of pulses, circuits, and algorithms. 3 | 4 | ## Note 5 | This project is currently deprecated and it will stop working after Qiskit Aqua 0.7.0 6 | 7 | ## Note 8 | As of July 12, 2019 Qiskit Chemistry has been merged into Qiskit Aqua, and all the code of the 9 | [Qiskit Chemistry repository](https://github.com/Qiskit/qiskit-chemistry) 10 | has been integrated into the [Qiskit Aqua](https://github.com/Qiskit/qiskit-aqua) repository. This change has impacted the 11 | dependencies of [Qiskit Aqua Intefaces](https://github.com/Qiskit/qiskit-aqua-interfaces). Follow the instructions in the 12 | [Qiskit Chemistry README file](https://github.com/Qiskit/qiskit-chemistry/blob/master/README.md) to update your installation of 13 | Qiskit Aqua and Qiskit Aqua Interfaces. 14 | 15 | ## Overview 16 | 17 | Qiskit is made up elements that work together to enable quantum computing. This repository contains **Qiskit Aqua Interfaces**, 18 | a set of user-interface components for [Qiskit Aqua](https://github.com/Qiskit/qiskit-aqua) (the element of Qiskit consisting 19 | of a library of cross-domain algorithms upon which domain-specific applications can be 20 | built) and Qiskit Chemistry (the chemistry-application component of Qiskit Aqua). 21 | 22 | The following user interfaces are currently included in this repository: 23 | 1. A command-line interface for Qiskit Aqua 24 | 2. A command-line interface for Qiskit Chemistry 25 | 3. A Qiskit Chemistry Graphical User Interface (GUI) wizard 26 | 4. A Qiskit Aqua GUI wizard 27 | 5. A visual browser for the Qiskit Aqua and Qiskit Chemistry Application Programming Interfaces (APIs) 28 | 29 | The command-line and wizards listed above include the following characteristics: 30 | - Through the command-line and wizard interfaces, the user can execute Qiskit Aqua or Qiskit Chemistry as tools. These 31 | interfaces allow the user to configure an experiment and execute it on top of one of the simulators or quantum computers 32 | interfaced by Qiskit. 33 | - The command-line and wizard interfaces embed a schema-based configuration-correctness enforcement mechanism that 34 | minimizes the chances for a user to make a configuration mistake, especially for experiments that mix domain- and 35 | quantum-specific information. 36 | - The command-line and wizard interfaces allow for configuration data and algorithm inputs to be serialized and deserialized 37 | at different stages. For example, Chemistry-specific information extracted from the classical computational-chemistry 38 | software packages interfaced by Aqua can be serialized in the [HDF5](https://www.hdfgroup.org/) binary format and later 39 | deserialized for faster experiment execution. This also allows experiment inputs to be shared among quantum researchers, 40 | thereby taking away the dependency from the particular classical computational-chemistry software package used to generate 41 | those inputs. Similarly, the input to a quantum algorithm can be serialized in [JSON](http://json.org/) format and later 42 | deserialized, thereby allowing a quantum experiment to be executed at the algorithmic level, without any dependency on the 43 | particular domain in which that input was generated. 44 | - Finally, the wizard interfaces allow for automatically generating a Python dictionary summarizing an entire experiment. 45 | Later on, that dictionary can be used as an input to the Qiskit Aqua or Qiskit Chemistry declarative API. 46 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Contributor Covenant Code of Conduct 3 | --- 4 | 5 | Our Pledge 6 | ========== 7 | 8 | In the interest of fostering an open and welcoming environment, we as 9 | contributors and maintainers pledge to making participation in our 10 | project and our community a harassment-free experience for everyone, 11 | regardless of age, body size, disability, ethnicity, gender identity and 12 | expression, level of experience, nationality, personal appearance, race, 13 | religion, or sexual identity and orientation. 14 | 15 | Our Standards 16 | ============= 17 | 18 | Examples of behavior that contributes to creating a positive environment 19 | include: 20 | 21 | - Using welcoming and inclusive language 22 | - Being respectful of differing viewpoints and experiences 23 | - Gracefully accepting constructive criticism 24 | - Focusing on what is best for the community 25 | - Showing empathy towards other community members 26 | 27 | Examples of unacceptable behavior by participants include: 28 | 29 | - The use of sexualized language or imagery and unwelcome sexual 30 | attention or advances 31 | - Trolling, insulting/derogatory comments, and personal or political 32 | attacks 33 | - Public or private harassment 34 | - Publishing others\' private information, such as a physical or 35 | electronic address, without explicit permission 36 | - Other conduct which could reasonably be considered inappropriate in 37 | a professional setting 38 | 39 | Our Responsibilities 40 | ==================== 41 | 42 | Project maintainers are responsible for clarifying the standards of 43 | acceptable behavior and are expected to take appropriate and fair 44 | corrective action in response to any instances of unacceptable behavior. 45 | 46 | Project maintainers have the right and responsibility to remove, edit, 47 | or reject comments, commits, code, wiki edits, issues, and other 48 | contributions that are not aligned to this Code of Conduct, or to ban 49 | temporarily or permanently any contributor for other behaviors that they 50 | deem inappropriate, threatening, offensive, or harmful. 51 | 52 | Scope 53 | ===== 54 | 55 | This Code of Conduct applies both within project spaces and in public 56 | spaces when an individual is representing the project or its community. 57 | Examples of representing a project or community include using an 58 | official project e-mail address, posting via an official social media 59 | account, or acting as an appointed representative at an online or 60 | offline event. Representation of a project may be further defined and 61 | clarified by project maintainers. 62 | 63 | Enforcement 64 | =========== 65 | 66 | Instances of abusive, harassing, or otherwise unacceptable behavior may 67 | be reported by contacting the project team at . The 68 | project team will review and investigate all complaints, and will 69 | respond in a way that it deems appropriate to the circumstances. The 70 | project team is obligated to maintain confidentiality with regard to the 71 | reporter of an incident. Further details of specific enforcement 72 | policies may be posted separately. 73 | 74 | Project maintainers who do not follow or enforce the Code of Conduct in 75 | good faith may face temporary or permanent repercussions as determined 76 | by other members of the project\'s leadership. 77 | 78 | Attribution 79 | =========== 80 | 81 | This Code of Conduct is adapted from the Contributor 82 | [Covenant](http://contributor-covenant.org), 83 | [version](http://contributor-covenant.org/version/1/4/) 1.4. 84 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/aqua/browser/_controller.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Qiskit Aqua browser controller.""" 16 | 17 | import tkinter as tk 18 | import logging 19 | from ._model import Model 20 | 21 | logger = logging.getLogger(__name__) 22 | 23 | 24 | class Controller: 25 | """ Aqua Browser Controller """ 26 | _NAME = 'name' 27 | 28 | def __init__(self, view) -> None: 29 | self._view = view 30 | self._model = None 31 | self._filemenu = None 32 | self._sections_view = None 33 | self._empty_view = None 34 | self._sections_view_title = tk.StringVar() 35 | self._properties_view = None 36 | 37 | @property 38 | def model(self): 39 | """ return model """ 40 | if self._model is None: 41 | self._model = Model() 42 | 43 | return self._model 44 | 45 | def pluggable_names(self): 46 | """ get pluggable names """ 47 | return self.model.pluggable_names() 48 | 49 | def populate_sections(self): 50 | """ populate sections """ 51 | self._sections_view.populate(self.model.get_sections()) 52 | 53 | def pluggable_type_select(self, pluggable_type): 54 | """ select pluggable type """ 55 | del pluggable_type 56 | self._sections_view_title.set('') 57 | self._empty_view.tkraise() 58 | 59 | def pluggable_schema_select(self, pluggable_type, pluggable_name): 60 | """ select pluggable schema """ 61 | self._sections_view_title.set( 62 | self.model.get_pluggable_description(pluggable_type, pluggable_name)) 63 | properties = self.model.get_pluggable_schema_properties(pluggable_type, pluggable_name) 64 | column_titles = \ 65 | self.model.get_pluggable_schema_property_titles(pluggable_type, pluggable_name) 66 | self._properties_view.populate(column_titles, properties) 67 | self._properties_view.tkraise() 68 | 69 | def pluggable_problems_select(self, pluggable_type, pluggable_name): 70 | """ select pluggable problems """ 71 | problems = \ 72 | self.model.get_pluggable_problems(pluggable_type, pluggable_name) 73 | self._properties_view.populate(['oneOf'], {'name': {'oneOf': problems}}) 74 | self._properties_view.tkraise() 75 | 76 | def pluggable_depends_select(self, pluggable_type, pluggable_name): 77 | """ select pluggable depends """ 78 | self._sections_view_title.set( 79 | self.model.get_pluggable_description(pluggable_type, pluggable_name)) 80 | self._empty_view.tkraise() 81 | 82 | def pluggable_dependency_select(self, pluggable_type, pluggable_name, dependency_type): 83 | """ select pluggable dependency """ 84 | dependency = \ 85 | self.model.get_pluggable_dependency(pluggable_type, pluggable_name, dependency_type) 86 | default = dependency.get('default', {}) 87 | self._properties_view.populate(list(default.keys()), {'default': default}) 88 | self._properties_view.tkraise() 89 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/user_interface/_sectionsview.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Qiskit user interface sections view.""" 16 | 17 | import tkinter as tk 18 | import tkinter.ttk as ttk 19 | from ._toolbarview import ToolbarView 20 | from ._customwidgets import SectionComboDialog 21 | 22 | 23 | class SectionsView(ToolbarView): 24 | """Sections toolbar view.""" 25 | 26 | def __init__(self, controller, parent, **options) -> None: 27 | super(SectionsView, self).__init__(parent, **options) 28 | self._controller = controller 29 | ttk.Style().configure("SectionsView.Treeview.Heading", font=(None, 12, 'bold')) 30 | self._tree = ttk.Treeview(self, style='SectionsView.Treeview', selectmode=tk.BROWSE) 31 | self._tree.heading('#0', text='Section') 32 | self._tree.bind('<>', self._cb_tree_select) 33 | self.init_widgets(self._tree) 34 | 35 | def clear(self): 36 | """Remove all entries from view. 37 | 38 | Returns: 39 | None 40 | """ 41 | for i in self._tree.get_children(): 42 | self._tree.delete([i]) 43 | 44 | def populate(self, section_names, section_select=None): 45 | """Populates all entries from view. 46 | 47 | Args: 48 | section_names (list[str]): list of names. 49 | section_select (str): name of selected entry 50 | 51 | Returns: 52 | None 53 | """ 54 | self.clear() 55 | item = None 56 | for name in section_names: 57 | i = self._tree.insert('', tk.END, text=name) 58 | if name == section_select: 59 | item = i 60 | 61 | if item is not None: 62 | self._tree.see(item) 63 | self._tree.selection_set(item) 64 | 65 | def has_selection(self): 66 | """Checks if an entry is selected. 67 | 68 | Returns: 69 | bool: True if the entry is selected, else False. 70 | """ 71 | return self._tree.selection() 72 | 73 | def _cb_tree_select(self, event): 74 | for item in self._tree.selection(): 75 | item_text = self._tree.item(item, 'text') 76 | self._controller.cb_section_select(item_text) 77 | return 78 | 79 | def cb_add(self): 80 | sections = self._controller.get_sections_names_missing() 81 | dialog = SectionComboDialog(self._controller, self.master) 82 | dialog.do_init(sections=sections) 83 | dialog.do_modal() 84 | if dialog.result is None: 85 | return 86 | 87 | if dialog.result: 88 | if self._controller.cb_section_add(dialog.result): 89 | self.populate(self._controller.model.get_section_names(), dialog.result) 90 | 91 | def cb_remove(self): 92 | for item in self._tree.selection(): 93 | item_text = self._tree.item(item, 'text') 94 | if self._controller.cb_section_remove(item_text): 95 | self.populate(self._controller.model.get_section_names()) 96 | self.show_remove_button(self.has_selection()) 97 | break 98 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/aqua/user_interface/_model.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Qiskit Aqua user interface model.""" 16 | 17 | import os 18 | import logging 19 | from qiskit_aqua_interfaces.aqua.user_interface._uipreferences import UIPreferences 20 | from qiskit_aqua_interfaces.user_interface import BaseModel 21 | 22 | logger = logging.getLogger(__name__) 23 | 24 | # pylint: disable=import-outside-toplevel 25 | 26 | 27 | class Model(BaseModel): 28 | """ Aqua Model """ 29 | def new(self): 30 | """ Create new model """ 31 | from qiskit.aqua.parser._inputparser import InputParser 32 | uipreferences = UIPreferences() 33 | return super().new_model(InputParser, 34 | os.path.join(os.path.dirname(__file__), 'input_template.json'), 35 | uipreferences.get_populate_defaults(True)) 36 | 37 | def load_file(self, filename): 38 | """ load input file """ 39 | from qiskit.aqua.parser._inputparser import InputParser 40 | uipreferences = UIPreferences() 41 | return super().load_model(filename, InputParser, uipreferences.get_populate_defaults(True)) 42 | 43 | def default_properties_equals_properties(self, section_name): 44 | from qiskit.aqua.parser import JSONSchema 45 | if self.section_is_text(section_name): 46 | return self.get_section_default_properties(section_name) == \ 47 | self.get_section_text(section_name) 48 | 49 | default_properties = self.get_section_default_properties(section_name) 50 | properties = self.get_section_properties(section_name) 51 | if not isinstance(default_properties, dict) or not isinstance(properties, dict): 52 | return default_properties == properties 53 | 54 | if JSONSchema.BACKEND == section_name and JSONSchema.PROVIDER in properties: 55 | default_properties[JSONSchema.PROVIDER] = properties[JSONSchema.PROVIDER] 56 | 57 | if JSONSchema.NAME in properties: 58 | default_properties[JSONSchema.NAME] = properties[JSONSchema.NAME] 59 | 60 | return dict(default_properties) == dict(properties) 61 | 62 | def get_input_section_names(self): 63 | """ get input section valid names """ 64 | from qiskit.aqua.parser._inputparser import InputParser 65 | from qiskit.aqua import local_pluggables, PluggableType 66 | from qiskit.aqua.parser import JSONSchema 67 | problem_name = None 68 | if self._parser is not None: 69 | problem_name = self.get_section_property(JSONSchema.PROBLEM, JSONSchema.NAME) 70 | if problem_name is None: 71 | problem_name = self.get_property_default_value(JSONSchema.PROBLEM, JSONSchema.NAME) 72 | 73 | if problem_name is None: 74 | return local_pluggables(PluggableType.INPUT) 75 | 76 | input_names = [] 77 | for input_name in local_pluggables(PluggableType.INPUT): 78 | problems = InputParser.get_input_problems(input_name) 79 | if problem_name in problems: 80 | input_names.append(input_name) 81 | 82 | return input_names 83 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/user_interface/_dialog.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Base Dialog view""" 16 | 17 | import tkinter as tk 18 | import tkinter.ttk as ttk 19 | 20 | 21 | class Dialog(tk.Toplevel): 22 | """ Dialog """ 23 | def __init__(self, controller, parent, title='') -> None: 24 | super(Dialog, self).__init__(parent) 25 | self.transient(parent) 26 | self.resizable(0, 0) 27 | self.title(title) 28 | self._controller = controller 29 | self.result = None 30 | self.initial_focus = None 31 | self.entry = None 32 | 33 | def do_init(self, cancel_side=tk.RIGHT, **options): 34 | """ initialize dialog """ 35 | body = ttk.Frame(self) 36 | self.initial_focus = self.body(body, options) 37 | body.pack(fill=tk.BOTH, expand=tk.TRUE) 38 | 39 | self._buttonbox(cancel_side) 40 | 41 | self.grab_set() 42 | 43 | if not self.initial_focus: 44 | self.initial_focus = self 45 | 46 | self.protocol("WM_DELETE_WINDOW", self._cb_cancel) 47 | 48 | w_s = self.master.winfo_reqwidth() 49 | h_s = self.master.winfo_reqheight() 50 | x = int(self.master.winfo_rootx() + w_s / 3 - self.winfo_reqwidth() / 2) 51 | y = int(self.master.winfo_rooty() + h_s / 3 - self.winfo_reqheight() / 2) 52 | 53 | self.geometry('+{}+{}'.format(x, y)) 54 | 55 | def do_modal(self): 56 | """ modal processing """ 57 | self.initial_focus.focus_set() 58 | self.wait_window(self) 59 | 60 | @property 61 | def controller(self): 62 | """ return controller """ 63 | return self._controller 64 | 65 | def _buttonbox(self, cancel_side=tk.RIGHT): 66 | box = ttk.Frame(self) 67 | 68 | w = ttk.Button(box, text="OK", width=10, command=self._cb_ok, default=tk.ACTIVE) 69 | w.pack(side=tk.LEFT, padx=5, pady=5) 70 | w = ttk.Button(box, text="Cancel", width=10, command=self._cb_cancel) 71 | w.pack(side=cancel_side, padx=5, pady=5) 72 | 73 | self.bind("", self._cb_ok) 74 | self.bind("", self._cb_cancel) 75 | 76 | box.pack(side=tk.BOTTOM, expand=tk.NO, fill=tk.X) 77 | 78 | def _cb_ok(self, event=None): 79 | if not self.validate(): 80 | self.initial_focus.focus_set() 81 | return 82 | 83 | self.withdraw() 84 | self.update_idletasks() 85 | 86 | self.apply() 87 | 88 | self._cb_cancel() 89 | 90 | def _cb_cancel(self, event=None): 91 | self.do_cancel() 92 | self.master.focus_set() 93 | self.destroy() 94 | 95 | def body(self, parent, options): 96 | """ populate body """ 97 | del parent 98 | del options 99 | return self # override 100 | 101 | def validate(self): 102 | """ validate entries """ 103 | return True # override 104 | 105 | def apply(self): 106 | """ save data """ 107 | pass # override 108 | 109 | def do_cancel(self): 110 | """ cancel entries """ 111 | pass # override 112 | -------------------------------------------------------------------------------- /test/common.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Shared functionality and helpers for the unit tests.""" 16 | 17 | from enum import Enum 18 | import inspect 19 | import logging 20 | import os 21 | import unittest 22 | import time 23 | 24 | from qiskit_aqua_interfaces import __path__ as qiskit_aqua_interfaces_path 25 | 26 | 27 | class Path(Enum): 28 | """Helper with paths commonly used during the tests.""" 29 | # Main SDK path: qiskit_aqua_interfaces/ 30 | SDK = qiskit_aqua_interfaces_path[0] 31 | # test.python path: test/ 32 | TEST = os.path.dirname(__file__) 33 | 34 | 35 | class QiskitAquaUisTestCase(unittest.TestCase): 36 | """Helper class that contains common functionality.""" 37 | 38 | def setUp(self): 39 | self._started_at = time.time() 40 | 41 | def tearDown(self): 42 | elapsed = time.time() - self._started_at 43 | if elapsed > 5.0: 44 | print('({:.2f}s)'.format(round(elapsed, 2)), flush=True) 45 | 46 | @classmethod 47 | def setUpClass(cls): 48 | cls.moduleName = os.path.splitext(inspect.getfile(cls))[0] 49 | cls.log = logging.getLogger(cls.__name__) 50 | 51 | # Set logging to file and stdout if the LOG_LEVEL environment variable 52 | # is set. 53 | if os.getenv('LOG_LEVEL'): 54 | # Set up formatter. 55 | log_fmt = ('{}.%(funcName)s:%(levelname)s:%(asctime)s:' 56 | ' %(message)s'.format(cls.__name__)) 57 | formatter = logging.Formatter(log_fmt) 58 | 59 | # Set up the file handler. 60 | log_file_name = '%s.log' % cls.moduleName 61 | file_handler = logging.FileHandler(log_file_name) 62 | file_handler.setFormatter(formatter) 63 | cls.log.addHandler(file_handler) 64 | 65 | # Set the logging level from the environment variable, defaulting 66 | # to INFO if it is not a valid level. 67 | level = logging._nameToLevel.get(os.getenv('LOG_LEVEL'), 68 | logging.INFO) 69 | cls.log.setLevel(level) 70 | 71 | @staticmethod 72 | def _get_resource_path(filename, path=Path.TEST): 73 | """ Get the absolute path to a resource. 74 | Args: 75 | filename (string): filename or relative path to the resource. 76 | path (Path): path used as relative to the filename. 77 | Returns: 78 | str: the absolute path to the resource. 79 | """ 80 | return os.path.normpath(os.path.join(path.value, filename)) 81 | 82 | def assertNoLogs(self, logger=None, level=None): 83 | """The opposite to assertLogs. 84 | """ 85 | # pylint: disable=invalid-name 86 | return _AssertNoLogsContext(self, logger, level) 87 | 88 | 89 | class _AssertNoLogsContext(unittest.case._AssertLogsContext): 90 | """A context manager used to implement TestCase.assertNoLogs().""" 91 | 92 | LOGGING_FORMAT = "%(levelname)s:%(name)s:%(message)s" 93 | 94 | # pylint: disable=inconsistent-return-statements 95 | def __exit__(self, exc_type, exc_value, tb): 96 | """This is a modified version of unittest.case._AssertLogsContext.__exit__(...) 97 | """ 98 | self.logger.handlers = self.old_handlers 99 | self.logger.propagate = self.old_propagate 100 | self.logger.setLevel(self.old_level) 101 | if exc_type is not None: 102 | # let unexpected exceptions pass through 103 | return False 104 | for record in self.watcher.records: 105 | self._raiseFailure( 106 | "Something was logged in the logger %s by %s:%i" % 107 | (record.name, record.pathname, record.lineno)) 108 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/aqua/user_interface/_aquathread.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Aqua User Interface run experiment thread""" 16 | 17 | import threading 18 | import tempfile 19 | import sys 20 | import logging 21 | import io 22 | import platform 23 | import os 24 | import subprocess 25 | import traceback 26 | import psutil 27 | from qiskit_aqua_interfaces.user_interface import GUIProvider 28 | 29 | logger = logging.getLogger(__name__) 30 | 31 | 32 | def exception_to_string(excp): 33 | """ exception string formatter """ 34 | stack = traceback.extract_stack()[:-3] + traceback.extract_tb(excp.__traceback__) 35 | pretty = traceback.format_list(stack) 36 | return ''.join(pretty) + '\n {} {}'.format(excp.__class__, excp) 37 | 38 | 39 | class AquaThread(threading.Thread): 40 | """ Aqua Thread """ 41 | def __init__(self, model, output, queue) -> None: 42 | super(AquaThread, self).__init__(name='Aqua run thread') 43 | self.model = model 44 | self._output = output 45 | self._thread_queue = queue 46 | self._popen = None 47 | 48 | def stop(self): 49 | """ stop thread """ 50 | self._output = None 51 | self._thread_queue = None 52 | if self._popen is not None: 53 | proc = self._popen 54 | self._kill(proc.pid) 55 | proc.stdout.close() 56 | 57 | def _kill(self, proc_pid): 58 | try: 59 | process = psutil.Process(proc_pid) 60 | for proc in process.children(recursive=True): 61 | proc.kill() 62 | process.kill() 63 | except Exception as ex: # pylint: disable=broad-except 64 | if self._output is not None: 65 | self._output.write_line( 66 | 'Process kill has failed: {}'.format(str(ex))) 67 | 68 | def run(self): 69 | input_file = None 70 | temp_input = False 71 | try: 72 | input_file = self.model.get_filename() 73 | if input_file is None or self.model.is_modified(): 74 | f_d, input_file = tempfile.mkstemp(suffix='.in') 75 | os.close(f_d) 76 | temp_input = True 77 | self.model.save_to_file(input_file) 78 | 79 | startupinfo = None 80 | if sys.platform == 'win32': 81 | startupinfo = subprocess.STARTUPINFO() 82 | startupinfo.dwFlags = subprocess.STARTF_USESHOWWINDOW 83 | startupinfo.wShowWindow = subprocess.SW_HIDE 84 | 85 | self._popen = subprocess.Popen(['qiskit_aqua_cmd', input_file], 86 | stdin=subprocess.DEVNULL, 87 | stdout=subprocess.PIPE, 88 | stderr=subprocess.STDOUT, 89 | startupinfo=startupinfo) 90 | if self._thread_queue is not None: 91 | self._thread_queue.put(GUIProvider.START) 92 | 93 | for line in io.TextIOWrapper(self._popen.stdout, encoding='utf-8', newline=''): 94 | if self._output is not None: 95 | if platform.system() == "Windows": 96 | line = line.replace('\r\n', '\n') 97 | 98 | self._output.write(line) 99 | 100 | self._popen.stdout.close() 101 | self._popen.wait() 102 | except Exception as ex: # pylint: disable=broad-except 103 | if self._output is not None: 104 | self._output.write('Process has failed: {}'.format(exception_to_string(ex))) 105 | finally: 106 | self._popen = None 107 | if self._thread_queue is not None: 108 | self._thread_queue.put(GUIProvider.STOP) 109 | 110 | if temp_input and input_file is not None: 111 | os.remove(input_file) 112 | 113 | input_file = None 114 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/user_interface/_toolbarview.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Toolbar View""" 16 | 17 | import tkinter as tk 18 | import tkinter.ttk as ttk 19 | from ._scrollbarview import ScrollbarView 20 | 21 | 22 | class ToolbarView(ScrollbarView): 23 | """ Toolbar View """ 24 | def __init__(self, parent, **options) -> None: 25 | super(ToolbarView, self).__init__(parent, **options) 26 | self._child = None 27 | self._toolbar = None 28 | self._add_button = None 29 | self._remove_button = None 30 | self._defaults_button = None 31 | self._hscrollbar = None 32 | self._vscrollbar = None 33 | self._add_button_shown = False 34 | self._remove_button_shown = False 35 | self._defaults_button_shown = False 36 | self._make_toolbar() 37 | 38 | def _make_toolbar(self): 39 | self._toolbar = ttk.Frame(self) 40 | self._add_button = ttk.Button(self._toolbar, 41 | text='Add', 42 | state='enable', 43 | command=self.cb_add) 44 | self._remove_button = ttk.Button(self._toolbar, 45 | text='Remove', 46 | state='enable', 47 | command=self.cb_remove) 48 | self._defaults_button = ttk.Button(self._toolbar, 49 | text='Defaults', 50 | state='enable', 51 | command=self.cb_defaults) 52 | 53 | def cb_add(self): 54 | """ add callback """ 55 | pass 56 | 57 | def cb_remove(self): 58 | """ remove callback """ 59 | pass 60 | 61 | def cb_defaults(self): 62 | """ defaults callback """ 63 | pass 64 | 65 | def get_toolbar_size(self): 66 | """ get size """ 67 | if self._toolbar is None: 68 | return (0, 0) 69 | 70 | return (self._toolbar.winfo_width(), self._toolbar.winfo_height()) 71 | 72 | def pack(self, **options): 73 | """ pack layout """ 74 | if self._toolbar is not None: 75 | self._toolbar.pack(side=tk.BOTTOM, fill=tk.X) 76 | self._add_button.pack(side=tk.LEFT) 77 | self._remove_button.pack(side=tk.LEFT) 78 | self._defaults_button.pack(side=tk.RIGHT) 79 | 80 | ScrollbarView.pack(self, **options) 81 | 82 | def grid(self, **options): 83 | """ grid layout """ 84 | if self._toolbar is not None: 85 | self._toolbar.pack(side=tk.BOTTOM, fill=tk.X) 86 | self._add_button.pack(side=tk.LEFT) 87 | self._remove_button.pack(side=tk.LEFT) 88 | self._defaults_button.pack(side=tk.RIGHT) 89 | 90 | ScrollbarView.grid(self, **options) 91 | 92 | def show_add_button(self, show): 93 | """ show/hide add button """ 94 | self._add_button_shown = show 95 | if show: 96 | if self._remove_button_shown: 97 | self._remove_button.pack_forget() 98 | self._add_button.pack(side=tk.LEFT) 99 | if self._remove_button_shown: 100 | self._remove_button.pack(side=tk.LEFT) 101 | else: 102 | self._add_button.pack_forget() 103 | 104 | def show_remove_button(self, show): 105 | """ show/hide remove button """ 106 | self._remove_button_shown = show 107 | if show: 108 | self._remove_button.pack(side=tk.LEFT) 109 | else: 110 | self._remove_button.pack_forget() 111 | 112 | def show_defaults_button(self, show): 113 | """ show/hide defaults button """ 114 | self._defaults_button_shown = show 115 | if show: 116 | self._defaults_button.pack(side=tk.RIGHT) 117 | else: 118 | self._defaults_button.pack_forget() 119 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/chemistry/user_interface/_chemthread.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Chemistry User Interface run experiment thread""" 16 | 17 | import threading 18 | import tempfile 19 | import sys 20 | import logging 21 | import io 22 | import platform 23 | import os 24 | import subprocess 25 | import traceback 26 | import psutil 27 | from qiskit_aqua_interfaces.user_interface import GUIProvider 28 | 29 | logger = logging.getLogger(__name__) 30 | 31 | 32 | def exception_to_string(excp): 33 | """ exception string formatter """ 34 | stack = traceback.extract_stack()[:-3] + traceback.extract_tb(excp.__traceback__) 35 | pretty = traceback.format_list(stack) 36 | return ''.join(pretty) + '\n {} {}'.format(excp.__class__, excp) 37 | 38 | 39 | class ChemistryThread(threading.Thread): 40 | """ Chemistry Thread """ 41 | def __init__(self, model, output, queue, filename) -> None: 42 | super(ChemistryThread, self).__init__(name='Chemistry run thread') 43 | self.model = model 44 | self._output = output 45 | self._thread_queue = queue 46 | self._json_algo_file = filename 47 | self._popen = None 48 | 49 | def stop(self): 50 | """ stop thread """ 51 | self._output = None 52 | self._thread_queue = None 53 | if self._popen is not None: 54 | proc = self._popen 55 | self._kill(proc.pid) 56 | proc.stdout.close() 57 | 58 | def _kill(self, proc_pid): 59 | try: 60 | process = psutil.Process(proc_pid) 61 | for proc in process.children(recursive=True): 62 | proc.kill() 63 | process.kill() 64 | except Exception as ex: # pylint: disable=broad-except 65 | if self._output is not None: 66 | self._output.write_line( 67 | 'Process kill has failed: {}'.format(str(ex))) 68 | 69 | def run(self): 70 | input_file = None 71 | temp_input = False 72 | try: 73 | input_file = self.model.get_filename() 74 | if input_file is None or self.model.is_modified(): 75 | f_d, input_file = tempfile.mkstemp(suffix='.in') 76 | os.close(f_d) 77 | temp_input = True 78 | self.model.save_to_file(input_file) 79 | 80 | startupinfo = None 81 | if sys.platform == 'win32': 82 | startupinfo = subprocess.STARTUPINFO() 83 | startupinfo.dwFlags = subprocess.STARTF_USESHOWWINDOW 84 | startupinfo.wShowWindow = subprocess.SW_HIDE 85 | 86 | input_array = ['qiskit_chemistry_cmd', input_file] 87 | if self._json_algo_file: 88 | input_array.extend(['-jo', self._json_algo_file]) 89 | 90 | self._popen = subprocess.Popen(input_array, 91 | stdin=subprocess.DEVNULL, 92 | stdout=subprocess.PIPE, 93 | stderr=subprocess.STDOUT, 94 | startupinfo=startupinfo) 95 | if self._thread_queue is not None: 96 | self._thread_queue.put(GUIProvider.START) 97 | 98 | for line in io.TextIOWrapper(self._popen.stdout, encoding='utf-8', newline=''): 99 | if self._output is not None: 100 | if platform.system() == "Windows": 101 | line = line.replace('\r\n', '\n') 102 | 103 | self._output.write(line) 104 | 105 | self._popen.stdout.close() 106 | self._popen.wait() 107 | except Exception as ex: # pylint: disable=broad-except 108 | if self._output is not None: 109 | self._output.write('Process has failed: {}'.format(exception_to_string(ex))) 110 | finally: 111 | self._popen = None 112 | if self._thread_queue is not None: 113 | self._thread_queue.put(GUIProvider.STOP) 114 | 115 | if temp_input and input_file is not None: 116 | os.remove(input_file) 117 | 118 | input_file = None 119 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/aqua/command_line/command_line.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Qiskit Aqua command line main.""" 16 | 17 | import sys 18 | import argparse 19 | import json 20 | from collections import OrderedDict 21 | import textwrap 22 | import logging 23 | from qiskit_aqua_interfaces import APP_DEPRECATION_MSG 24 | from qiskit_aqua_interfaces._extras_require import _check_extra_requires 25 | 26 | # pylint: disable=import-outside-toplevel 27 | 28 | 29 | def main(): 30 | """Runs main Aqua command line.""" 31 | if sys.platform != 'darwin': 32 | _run() 33 | return 34 | 35 | # On MacOSX avoid possible matplotlib error in case it is imported by other imported libraries 36 | import tkinter as tk 37 | root = tk.Tk() 38 | root.withdraw() 39 | root.after(0, _run_delay, root) 40 | root.mainloop() 41 | 42 | 43 | def _run_delay(root): 44 | try: 45 | _run() 46 | finally: 47 | if root is not None: 48 | root.destroy() 49 | 50 | 51 | def _run(): 52 | _check_extra_requires('console_scripts', 'qiskit_aqua_cmd') 53 | from qiskit.aqua._logging import (get_logging_level, 54 | build_logging_config, 55 | set_logging_config, 56 | set_qiskit_aqua_logging) 57 | from qiskit_aqua_interfaces.aqua.user_interface import UIPreferences 58 | from qiskit.aqua import run_algorithm 59 | from qiskit.aqua.utils import convert_json_to_dict 60 | 61 | preferences = UIPreferences() 62 | log_levels = OrderedDict( 63 | [(logging.getLevelName(logging.CRITICAL).lower(), logging.CRITICAL), 64 | (logging.getLevelName(logging.ERROR).lower(), logging.ERROR), 65 | (logging.getLevelName(logging.WARNING).lower(), logging.WARNING), 66 | (logging.getLevelName(logging.INFO).lower(), logging.INFO), 67 | (logging.getLevelName(logging.DEBUG).lower(), logging.DEBUG), 68 | (logging.getLevelName(logging.NOTSET).lower(), logging.NOTSET)] 69 | ) 70 | 71 | parser = argparse.ArgumentParser(prog='qiskit_aqua_cmd', 72 | formatter_class=argparse.RawTextHelpFormatter, 73 | description='Qiskit Aqua Command Line Tool') 74 | parser.add_argument('input', 75 | metavar='input', 76 | help='Algorithm JSON input file') 77 | parser.add_argument('-jo', 78 | metavar='output', 79 | help='Algorithm JSON output file name') 80 | parser.add_argument('-l', 81 | metavar='logging', 82 | choices=log_levels.keys(), 83 | help=textwrap.dedent('''\ 84 | Logging level: 85 | {} 86 | (defaults to level from preferences file: {}) 87 | '''.format(list(log_levels.keys()), preferences.filepath)) 88 | ) 89 | 90 | args = parser.parse_args() 91 | 92 | if args.l is not None: 93 | set_qiskit_aqua_logging(log_levels.get(args.l, logging.INFO)) 94 | else: 95 | # update logging setting with latest external packages 96 | logging_level = logging.INFO 97 | if preferences.get_logging_config() is not None: 98 | set_logging_config(preferences.get_logging_config()) 99 | logging_level = get_logging_level() 100 | 101 | preferences.set_logging_config(build_logging_config(logging_level)) 102 | preferences.save() 103 | set_logging_config(preferences.get_logging_config()) 104 | 105 | params = None 106 | with open(args.input) as json_file: 107 | params = json.load(json_file) 108 | 109 | print(APP_DEPRECATION_MSG) 110 | ret = run_algorithm(params, None, True) 111 | 112 | if args.jo is not None: 113 | with open(args.jo, 'w') as run_output: 114 | print('{}'.format(ret), file=run_output) 115 | else: 116 | convert_json_to_dict(ret) 117 | print('\n\n--------------------------------- R E S U L T -----' 118 | '-------------------------------\n') 119 | if isinstance(ret, dict): 120 | for k, v in ret.items(): 121 | print("'{}': {}".format(k, v)) 122 | else: 123 | print(ret) 124 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/chemistry/user_interface/_model.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Qiskit Chemistry user interface model.""" 16 | 17 | import os 18 | from collections import OrderedDict 19 | import logging 20 | from qiskit_aqua_interfaces.user_interface import BaseModel 21 | from ._uipreferences import UIPreferences 22 | 23 | logger = logging.getLogger(__name__) 24 | 25 | # pylint: disable=import-outside-toplevel 26 | 27 | 28 | class Model(BaseModel): 29 | """ Chemistry Model """ 30 | def new(self): 31 | """ new model """ 32 | from qiskit.chemistry.parser import InputParser 33 | uipreferences = UIPreferences() 34 | return super().new_model(InputParser, 35 | os.path.join(os.path.dirname(__file__), 'input_template.json'), 36 | uipreferences.get_populate_defaults(True)) 37 | 38 | def load_file(self, filename): 39 | """ load input data """ 40 | from qiskit.chemistry.parser import InputParser 41 | uipreferences = UIPreferences() 42 | return super().load_model(filename, InputParser, uipreferences.get_populate_defaults(True)) 43 | 44 | def default_properties_equals_properties(self, section_name): 45 | """ check if default properties are the same as current properties """ 46 | from qiskit.aqua.parser import JSONSchema 47 | if self.section_is_text(section_name): 48 | return self.get_section_default_properties(section_name) == \ 49 | self.get_section_text(section_name) 50 | 51 | default_properties = self.get_section_default_properties(section_name) 52 | properties = self.get_section_properties(section_name) 53 | if not isinstance(default_properties, dict) or not isinstance(properties, dict): 54 | return default_properties == properties 55 | 56 | if JSONSchema.BACKEND == section_name and JSONSchema.PROVIDER in properties: 57 | default_properties[JSONSchema.PROVIDER] = properties[JSONSchema.PROVIDER] 58 | 59 | if JSONSchema.NAME in properties: 60 | default_properties[JSONSchema.NAME] = properties[JSONSchema.NAME] 61 | 62 | if len(default_properties) != len(properties): 63 | return False 64 | 65 | substitution_tuples = self._parser.check_if_substitution_key( 66 | section_name, list(properties.keys())) 67 | for substitution_tuple in substitution_tuples: 68 | property_name = substitution_tuple[0] 69 | if property_name not in default_properties: 70 | return False 71 | 72 | if not substitution_tuple[1]: 73 | if default_properties[property_name] != properties[property_name]: 74 | return False 75 | 76 | return True 77 | 78 | def get_dictionary(self): 79 | """ get data dictionary """ 80 | if self.is_empty(): 81 | raise Exception("Empty input data.") 82 | 83 | return self._parser.to_dictionary() 84 | 85 | def export_dictionary(self, filename): 86 | """ export data dictionary """ 87 | if self.is_empty(): 88 | raise Exception("Empty input data.") 89 | 90 | self._parser.export_dictionary(filename) 91 | 92 | def get_section_properties_with_substitution(self, section_name): 93 | """ get section properties after updating values """ 94 | properties = self.get_section_properties(section_name) 95 | result_tuples = \ 96 | self._parser.check_if_substitution_key(section_name, list(properties.keys())) 97 | properties_with_substitution = OrderedDict() 98 | for result_tuple in result_tuples: 99 | properties_with_substitution[result_tuple[0]] = \ 100 | (properties[result_tuple[0]], result_tuple[1]) 101 | 102 | return properties_with_substitution 103 | 104 | def get_operator_section_names(self): 105 | """ get operator section names """ 106 | from qiskit.aqua.parser import JSONSchema 107 | from qiskit.chemistry.parser import InputParser 108 | from qiskit.chemistry.core import local_chemistry_operators 109 | problem_name = None 110 | if self._parser is not None: 111 | problem_name = self.get_section_property(JSONSchema.PROBLEM, JSONSchema.NAME) 112 | if problem_name is None: 113 | problem_name = self.get_property_default_value(JSONSchema.PROBLEM, JSONSchema.NAME) 114 | 115 | if problem_name is None: 116 | return local_chemistry_operators() 117 | 118 | operator_names = [] 119 | for operator_name in local_chemistry_operators(): 120 | problems = InputParser.get_operator_problems(operator_name) 121 | if problem_name in problems: 122 | operator_names.append(operator_name) 123 | 124 | return operator_names 125 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/chemistry/user_interface/_uipreferences.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Qiskit Chemistry user interface preferences.""" 16 | 17 | import os 18 | import json 19 | from typing import Optional, List, Dict 20 | 21 | 22 | class UIPreferences: 23 | """ Chemistry UI Preferences """ 24 | _FILENAME = '.qiskit_chemistry_ui' 25 | _VERSION = '1.0' 26 | 27 | def __init__(self) -> None: 28 | """Create UIPreferences object.""" 29 | self._preferences = { 30 | 'version': UIPreferences._VERSION 31 | } 32 | home = os.path.expanduser("~") 33 | self._filepath = os.path.join(home, UIPreferences._FILENAME) 34 | try: 35 | with open(self._filepath) as json_pref: 36 | self._preferences = json.load(json_pref) 37 | except Exception: # pylint: disable=broad-except 38 | pass 39 | 40 | @property 41 | def filepath(self) -> str: 42 | """ get filepath """ 43 | return self._filepath 44 | 45 | def save(self) -> None: 46 | """ save preferences """ 47 | with open(self._filepath, 'w') as pref_output: 48 | json.dump(self._preferences, pref_output, sort_keys=True, indent=4) 49 | 50 | def get_version(self) -> str: 51 | """ get version """ 52 | if 'version' in self._preferences: 53 | return self._preferences['version'] 54 | 55 | return None 56 | 57 | def get_geometry(self, default_value: Optional[str] = None) -> str: 58 | """ get chemistry geometry """ 59 | if 'geometry' in self._preferences: 60 | return self._preferences['geometry'] 61 | 62 | return default_value 63 | 64 | def set_geometry(self, geometry: str) -> None: 65 | """ set chemistry geometry """ 66 | self._preferences['geometry'] = geometry 67 | 68 | def get_openfile_initialdir(self) -> str: 69 | """ get open file initial folder """ 70 | if 'openfile_initialdir' in self._preferences: 71 | if not os.path.isdir(self._preferences['openfile_initialdir']): 72 | self._preferences['openfile_initialdir'] = os.getcwd() 73 | 74 | return self._preferences['openfile_initialdir'] 75 | 76 | return os.getcwd() 77 | 78 | def set_openfile_initialdir(self, initialdir: str) -> None: 79 | """ set open file initial folder """ 80 | self._preferences['openfile_initialdir'] = initialdir 81 | 82 | def get_savefile_initialdir(self) -> str: 83 | """ get save file initial folder """ 84 | if 'savefile_initialdir' in self._preferences: 85 | if not os.path.isdir(self._preferences['savefile_initialdir']): 86 | self._preferences['savefile_initialdir'] = os.getcwd() 87 | 88 | return self._preferences['savefile_initialdir'] 89 | 90 | return os.getcwd() 91 | 92 | def set_savefile_initialdir(self, initialdir: str) -> None: 93 | """ set save file initial folder """ 94 | self._preferences['savefile_initialdir'] = initialdir 95 | 96 | def get_populate_defaults(self, default_value: Optional[bool] = None) -> bool: 97 | """ get populate defaults flag """ 98 | if 'populate_defaults' in self._preferences: 99 | return self._preferences['populate_defaults'] 100 | 101 | return default_value 102 | 103 | def set_populate_defaults(self, populate_defaults: bool) -> None: 104 | """ set populate defaults flag """ 105 | self._preferences['populate_defaults'] = populate_defaults 106 | 107 | def get_recent_files(self) -> List[str]: 108 | """ get recent files list """ 109 | files = [] 110 | if 'recent_files' in self._preferences: 111 | for file in self._preferences['recent_files']: 112 | if os.path.isfile(file): 113 | files.append(file) 114 | 115 | self._preferences['recent_files'] = files 116 | 117 | return files 118 | 119 | def add_recent_file(self, file: str) -> None: 120 | """ add a recent file """ 121 | recent_files = self.get_recent_files() 122 | if file not in recent_files: 123 | recent_files.append(file) 124 | if len(recent_files) > 6: 125 | recent_files = recent_files[1:] 126 | self._preferences['recent_files'] = recent_files 127 | 128 | def clear_recent_files(self) -> None: 129 | """ clear recent files list """ 130 | if 'recent_files' in self._preferences: 131 | del self._preferences['recent_files'] 132 | 133 | def get_logging_config(self, 134 | default_value: Optional[Dict[str, object]] = None) -> Dict[str, object]: 135 | """ get chemistry logging """ 136 | if 'logging_config' in self._preferences: 137 | return self._preferences['logging_config'] 138 | 139 | return default_value 140 | 141 | def set_logging_config(self, logging_config: Dict[str, object]) -> None: 142 | """ set chemistry logging """ 143 | self._preferences['logging_config'] = logging_config 144 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/aqua/user_interface/_controller.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Qiskit Aqua user interface controller.""" 16 | 17 | from tkinter import messagebox 18 | import logging 19 | from qiskit_aqua_interfaces.user_interface import BaseController 20 | from ._model import Model 21 | 22 | logger = logging.getLogger(__name__) 23 | 24 | # pylint: disable=import-outside-toplevel 25 | 26 | 27 | class Controller(BaseController): 28 | """ Aqua Controller """ 29 | def __init__(self, guiprovider) -> None: 30 | super().__init__(guiprovider, Model()) 31 | 32 | def open_file(self, filename): 33 | ret = super().open_file(filename) 34 | if ret and not self.model.get_section_names(): 35 | self.outputview.write_line('The file appears not to be ' 36 | 'a qiskit aqua input file; no sections found.') 37 | 38 | return ret 39 | 40 | def cb_section_select(self, section_name): 41 | self._sections_view.show_remove_button(True) 42 | self._sections_view_title.set(section_name) 43 | if self.model.section_is_text(section_name): 44 | self._text_view.populate(self.model.get_section_text(section_name)) 45 | self._text_view.section_name = section_name 46 | self._text_view.show_add_button(False) 47 | self._text_view.show_remove_button(False) 48 | self._text_view.show_defaults_button( 49 | not self.model.default_properties_equals_properties(section_name)) 50 | self._text_view.tkraise() 51 | else: 52 | self._properties_view.show_add_button(self.shows_add_button(section_name)) 53 | self._properties_view.populate(self.model.get_section_properties(section_name)) 54 | self._properties_view.section_name = section_name 55 | self._properties_view.show_remove_button(False) 56 | self._properties_view.show_defaults_button( 57 | not self.model.default_properties_equals_properties(section_name)) 58 | self._properties_view.tkraise() 59 | 60 | def cb_section_defaults(self, section_name): 61 | try: 62 | self.model.set_default_properties_for_name(section_name) 63 | self.cb_section_select(section_name) 64 | return True 65 | except Exception as ex: # pylint: disable=broad-except 66 | messagebox.showerror("Error", str(ex)) 67 | 68 | return False 69 | 70 | def cb_property_set(self, section_name, property_name, value): 71 | from qiskit.aqua.parser import JSONSchema 72 | try: 73 | self.model.set_section_property(section_name, property_name, value) 74 | except Exception as ex: # pylint: disable=broad-except 75 | messagebox.showerror("Error", str(ex)) 76 | return False 77 | 78 | try: 79 | self._properties_view.populate(self.model.get_section_properties(section_name)) 80 | self._properties_view.show_add_button(self.shows_add_button(section_name)) 81 | _show_remove = property_name not in (JSONSchema.PROVIDER, JSONSchema.NAME) \ 82 | if section_name == JSONSchema.BACKEND else property_name != JSONSchema.NAME 83 | self._properties_view.show_remove_button( 84 | _show_remove and self._properties_view.has_selection()) 85 | self._properties_view.show_defaults_button( 86 | not self.model.default_properties_equals_properties(section_name)) 87 | section_names = self.model.get_section_names() 88 | self._sections_view.populate(section_names, section_name) 89 | missing = self.get_sections_names_missing() 90 | self._sections_view.show_add_button(bool(missing)) 91 | return True 92 | except Exception as ex: # pylint: disable=broad-except 93 | messagebox.showerror("Error", str(ex)) 94 | 95 | return False 96 | 97 | def cb_section_property_remove(self, section_name, property_name): 98 | try: 99 | self.model.delete_section_property(section_name, property_name) 100 | self._properties_view.populate(self.model.get_section_properties(section_name)) 101 | self._properties_view.show_add_button(self.shows_add_button(section_name)) 102 | self._properties_view.show_remove_button(False) 103 | self._properties_view.show_defaults_button( 104 | not self.model.default_properties_equals_properties(section_name)) 105 | except Exception as ex: # pylint: disable=broad-except 106 | self.outputview.write_line(str(ex)) 107 | 108 | def get_combobox_parameters(self, section_name, property_name): 109 | from qiskit.aqua import PluggableType 110 | from qiskit.aqua.parser import JSONSchema 111 | values = None 112 | types = ['string'] 113 | combobox_state = 'readonly' 114 | if PluggableType.INPUT.value == section_name and JSONSchema.NAME == property_name: 115 | values = self.model.get_input_section_names() 116 | else: 117 | combobox_state, types, values = \ 118 | super().get_combobox_parameters(section_name, property_name) 119 | 120 | return combobox_state, types, values 121 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/user_interface/_threadsafeoutputview.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Thread Safe Output View""" 16 | 17 | import tkinter as tk 18 | from tkinter.font import Font 19 | import queue 20 | import string 21 | import platform 22 | from ._scrollbarview import ScrollbarView 23 | from ._customwidgets import TextCustom 24 | 25 | 26 | class ThreadSafeOutputView(ScrollbarView): 27 | """ Thread Safe Output View """ 28 | _DELAY = 50 29 | _TOTAL_ITERATIONS = 120 30 | _FULL_BLOCK_CHAR = u'█' 31 | _CR = '\r' 32 | _LF = '\n' 33 | _FONT_FAMILIES = { 34 | 'Darwin': 'Menlo Regular', 35 | } 36 | 37 | def __init__(self, parent, **options) -> None: 38 | super(ThreadSafeOutputView, self).__init__(parent, **options) 39 | self._queue = queue.Queue() 40 | self._text_widget = TextCustom(self, wrap=tk.NONE, state=tk.DISABLED) 41 | font_family = ThreadSafeOutputView._FONT_FAMILIES.get(platform.system()) 42 | if font_family: 43 | self._text_widget.configure(font=Font(family=font_family)) 44 | self.init_widgets(self._text_widget) 45 | self._update_text() 46 | 47 | def _update_text(self): 48 | try: 49 | iterations = 0 50 | while iterations < ThreadSafeOutputView._TOTAL_ITERATIONS: 51 | line = self._queue.get_nowait() 52 | iterations += 1 53 | if line is None: 54 | self._write() 55 | else: 56 | self._write(str(line), False) 57 | 58 | self.update_idletasks() 59 | except Exception: # pylint: disable=broad-except 60 | pass 61 | 62 | self.after(ThreadSafeOutputView._DELAY, self._update_text) 63 | 64 | def write(self, text): 65 | """ write text """ 66 | if text is None: 67 | return 68 | 69 | text = str(text) 70 | if not text: 71 | return 72 | 73 | # remove any non printable character that will cause the Text widget to hang 74 | text = ''.join([x if x == ThreadSafeOutputView._FULL_BLOCK_CHAR or 75 | x in string.printable else '' for x in text]) 76 | if platform.system() == 'Windows': # Under Windows unicode block is escaped 77 | text = text.replace('\\u2588', u"\u2588") 78 | if not text: 79 | return 80 | 81 | # break cr into separate queue entries 82 | pos = text.find(ThreadSafeOutputView._CR) # look for cr in text 83 | while pos >= 0: # text contains cr 84 | line = text[:pos] # up to but not including the end cr 85 | if line: 86 | self._queue.put(line) 87 | 88 | text = text[pos:] # get text with cr in front 89 | pos = text.find(ThreadSafeOutputView._CR, 1) # look for cr in text after first pos 90 | 91 | if text: # insert any remaining text 92 | self._queue.put(text) 93 | 94 | def flush(self): 95 | """ flush data """ 96 | pass 97 | 98 | def buffer_empty(self): 99 | """ check if buffer is empty """ 100 | return self._queue.empty() 101 | 102 | def clear_buffer(self): 103 | """Create another queue to ignore current queue output""" 104 | self._queue = queue.Queue() 105 | 106 | def write_line(self, text): 107 | """ write a line """ 108 | self.write(text + '\n') 109 | 110 | def clear(self): 111 | """ clear queue """ 112 | self._queue.put(None) 113 | 114 | def _write(self, text=None, erase=True): 115 | self._text_widget.config(state=tk.NORMAL) 116 | if erase: 117 | self._text_widget.delete(1.0, tk.END) 118 | 119 | if text is not None: 120 | self._write_text(text) 121 | pos = self._vscrollbar.get()[1] 122 | # scrolls only when scroll bar is at the bottom 123 | if pos == 1.0: 124 | self._text_widget.yview(tk.END) 125 | 126 | self._text_widget.config(state=tk.DISABLED) 127 | 128 | def _write_text(self, text): 129 | new_text = text 130 | pos = new_text.find(ThreadSafeOutputView._CR) # look for cr in new text 131 | while pos >= 0: # new text contains cr 132 | line = new_text[:pos] # up to but not including the cr 133 | if line: 134 | self._text_widget.insert(tk.END, line) 135 | 136 | # look for last lf 137 | prev_index_lf = self._text_widget.search(ThreadSafeOutputView._LF, 138 | '{}-1c'.format(tk.END), 139 | '1.0', 140 | backwards=True) 141 | if prev_index_lf: 142 | # remove previous line after lf 143 | self._text_widget.delete('{} + 1c'.format(prev_index_lf), '{}-1c'.format(tk.END)) 144 | else: 145 | # remove whole text 146 | self._text_widget.delete(1.0, tk.END) 147 | 148 | new_text = new_text[pos+1:] # get text after cr 149 | pos = new_text.find(ThreadSafeOutputView._CR) # look for cr in new text 150 | 151 | if new_text: # insert any remaining text 152 | self._text_widget.insert(tk.END, new_text) 153 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/aqua/browser/_sectionsview.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Sections view""" 16 | 17 | import tkinter as tk 18 | import tkinter.ttk as ttk 19 | from ._scrollbarview import ScrollbarView 20 | 21 | 22 | class SectionsView(ScrollbarView): 23 | """ Aqua Browser Sections View """ 24 | _TAG_PLUGGABLE_TYPE = 'PLUGGABLE_TYPE' 25 | _TAG_PLUGGABLE = 'PLUGGABLE' 26 | _TAG_PROBLEMS = 'PROBLEMS' 27 | _TAG_DEPENDS = 'DEPENDS' 28 | _TAG_DEPENDENCY = 'DEPENDENCY' 29 | 30 | def __init__(self, controller, parent, **options) -> None: 31 | super(SectionsView, self).__init__(parent, **options) 32 | self._controller = controller 33 | ttk.Style().configure("BrowseSectionsView.Treeview.Heading", font=(None, 12, 'bold')) 34 | self._tree = ttk.Treeview(self, style='BrowseSectionsView.Treeview', selectmode=tk.BROWSE) 35 | self._tree.heading('#0', text='Sections') 36 | self._tree.bind('<>', self._cb_tree_select) 37 | self.init_widgets(self._tree) 38 | 39 | def clear(self): 40 | """ clear view """ 41 | for i in self._tree.get_children(): 42 | self._tree.delete([i]) 43 | 44 | def populate(self, algos): 45 | """ populate view with pluggables """ 46 | self.clear() 47 | root_identifier = None 48 | for pluggable_type, section_types in algos.items(): 49 | identifier = self._tree.insert('', 50 | tk.END, 51 | text=pluggable_type, 52 | values=[''], 53 | tags=SectionsView._TAG_PLUGGABLE_TYPE) 54 | if root_identifier is None: 55 | root_identifier = identifier 56 | 57 | child_identifier = None 58 | for pluggable_name, pluggable_name_values in section_types.items(): 59 | child_identifier = self._tree.insert(identifier, 60 | tk.END, 61 | text=pluggable_name, 62 | values=[pluggable_type], 63 | tags=SectionsView._TAG_PLUGGABLE) 64 | 65 | problems = pluggable_name_values['problems'] 66 | if problems: 67 | self._tree.insert(child_identifier, 68 | tk.END, 69 | text='problems', 70 | values=[pluggable_type, pluggable_name], 71 | tags=SectionsView._TAG_PROBLEMS) 72 | 73 | depends = pluggable_name_values['depends'] 74 | if depends: 75 | depends_identifier = self._tree.insert(child_identifier, 76 | tk.END, 77 | text='depends', 78 | values=[pluggable_type, pluggable_name], 79 | tags=SectionsView._TAG_DEPENDS) 80 | for dependency in depends: 81 | if 'pluggable_type' in dependency: 82 | self._tree.insert(depends_identifier, 83 | tk.END, 84 | text=dependency['pluggable_type'], 85 | values=[pluggable_type, pluggable_name], 86 | tags=SectionsView._TAG_DEPENDENCY) 87 | 88 | if child_identifier is not None: 89 | self._tree.see(child_identifier) 90 | 91 | if root_identifier is not None: 92 | self._tree.see(root_identifier) 93 | 94 | def has_selection(self): 95 | """ check if an entry is selected """ 96 | return self._tree.selection() 97 | 98 | def _cb_tree_select(self, event): 99 | for item in self._tree.selection(): 100 | item_tag = self._tree.item(item, 'tag')[0] 101 | if item_tag == SectionsView._TAG_PLUGGABLE_TYPE: 102 | item_text = self._tree.item(item, 'text') 103 | self._controller.pluggable_type_select(item_text) 104 | elif item_tag == SectionsView._TAG_PLUGGABLE: 105 | item_text = self._tree.item(item, 'text') 106 | values = self._tree.item(item, 'values') 107 | self._controller.pluggable_schema_select(values[0], item_text) 108 | elif item_tag == SectionsView._TAG_PROBLEMS: 109 | values = self._tree.item(item, 'values') 110 | self._controller.pluggable_problems_select(values[0], values[1]) 111 | elif item_tag == SectionsView._TAG_DEPENDS: 112 | values = self._tree.item(item, 'values') 113 | self._controller.pluggable_depends_select(values[0], values[1]) 114 | elif item_tag == SectionsView._TAG_DEPENDENCY: 115 | item_text = self._tree.item(item, 'text') 116 | values = self._tree.item(item, 'values') 117 | self._controller.pluggable_dependency_select(values[0], values[1], item_text) 118 | 119 | return 120 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/user_interface/_sectionpropertiesview.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Section Properties View""" 16 | 17 | import tkinter as tk 18 | import tkinter.ttk as ttk 19 | from tkinter import messagebox 20 | from ._toolbarview import ToolbarView 21 | from ._customwidgets import PropertyComboDialog, PropertyEntryDialog, TextPopup 22 | 23 | 24 | class SectionPropertiesView(ToolbarView): 25 | """ Section Properties View """ 26 | def __init__(self, controller, parent, **options) -> None: 27 | super(SectionPropertiesView, self).__init__(parent, **options) 28 | self._controller = controller 29 | ttk.Style().configure("SectionPropertiesView.Treeview.Heading", font=(None, 12, 'bold')) 30 | self._tree = ttk.Treeview(self, style='SectionPropertiesView.Treeview', 31 | selectmode=tk.BROWSE, columns=['value']) 32 | self._tree.heading('#0', text='Name') 33 | self._tree.heading('value', text='Value') 34 | self._tree.bind('<>', self._cb_tree_select) 35 | self._tree.bind('', self._cb_tree_edit) 36 | self.init_widgets(self._tree) 37 | self._section_name = None 38 | self._properties = {} 39 | self._popup_widget = None 40 | 41 | @property 42 | def section_name(self): 43 | """ get section name """ 44 | return self._section_name 45 | 46 | @section_name.setter 47 | def section_name(self, new_section_name): 48 | """ set section name """ 49 | self._section_name = new_section_name 50 | 51 | def clear(self): 52 | """ clear entries """ 53 | if self._popup_widget is not None and self._popup_widget.winfo_exists(): 54 | self._popup_widget.destroy() 55 | 56 | self._popup_widget = None 57 | for i in self._tree.get_children(): 58 | self._tree.delete([i]) 59 | 60 | self._properties = {} 61 | 62 | def populate(self, properties): 63 | """ populate entries """ 64 | self.clear() 65 | for name, value in properties.items(): 66 | value = '' if value is None else str(value) 67 | value = value.replace('\r', '\\r').replace('\n', '\\n') 68 | self._tree.insert('', tk.END, text=name, values=[value]) 69 | 70 | self._properties = properties 71 | 72 | def set_property(self, property_name, value): 73 | """ set property """ 74 | for item in self._tree.get_children(): 75 | name = self._tree.item(item, "text") 76 | if name == property_name: 77 | self._tree.item(item, values=[value]) 78 | break 79 | 80 | def has_selection(self): 81 | """ check if entry is selected """ 82 | return self._tree.selection() 83 | 84 | def _cb_tree_select(self, event): 85 | for item in self._tree.selection(): 86 | property_name = self._tree.item(item, 'text') 87 | self._controller.cb_property_select(self._section_name, property_name) 88 | return 89 | 90 | def _cb_tree_edit(self, event): 91 | rowid = self._tree.identify_row(event.y) 92 | if not rowid: 93 | return 94 | 95 | column = self._tree.identify_column(event.x) 96 | if column == '#1': 97 | x, y, width, height = self._tree.bbox(rowid, column) 98 | pady = height // 2 99 | 100 | item = self._tree.identify("item", event.x, event.y) 101 | property_name = self._tree.item(item, "text") 102 | try: 103 | self._popup_widget = self._controller.create_popup(self.section_name, 104 | property_name, 105 | self._tree, 106 | self._properties[property_name]) 107 | except Exception as ex: # pylint: disable=broad-except 108 | messagebox.showerror("Error", str(ex)) 109 | return 110 | 111 | if isinstance(self._popup_widget, TextPopup): 112 | height = self._tree.winfo_height() - y 113 | self._popup_widget.place(x=x, y=y, width=width, height=height) 114 | else: 115 | self._popup_widget.place(x=x, y=y + pady, anchor=tk.W, width=width) 116 | 117 | def cb_add(self): 118 | dialog = None 119 | if self._controller.model.allows_additional_properties(self.section_name): 120 | dialog = PropertyEntryDialog(self._controller, self.section_name, self.master) 121 | dialog.do_init() 122 | else: 123 | properties = self._controller.get_property_names_missing(self.section_name) 124 | dialog = PropertyComboDialog(self._controller, self.section_name, self.master) 125 | dialog.do_init(values=properties) 126 | 127 | dialog.do_modal() 128 | if dialog.result is None: 129 | return 130 | 131 | if dialog.result: 132 | self._controller.on_property_add(self.section_name, dialog.result) 133 | 134 | def cb_remove(self): 135 | for item in self._tree.selection(): 136 | property_name = self._tree.item(item, 'text') 137 | self._controller.cb_section_property_remove(self.section_name, property_name) 138 | break 139 | 140 | def cb_defaults(self): 141 | self._controller.cb_section_defaults(self.section_name) 142 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/aqua/user_interface/_uipreferences.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Qiskit Aqua user interface preferences.""" 16 | 17 | import os 18 | import json 19 | from typing import Optional, List, Dict 20 | 21 | 22 | class UIPreferences: 23 | """ Aqua UI Preferences """ 24 | _FILENAME = '.qiskit_aqua_ui' 25 | _VERSION = '1.0' 26 | 27 | def __init__(self) -> None: 28 | """Create UIPreferences object.""" 29 | self._preferences = { 30 | 'version': UIPreferences._VERSION 31 | } 32 | home = os.path.expanduser("~") 33 | self._filepath = os.path.join(home, UIPreferences._FILENAME) 34 | try: 35 | with open(self._filepath) as json_pref: 36 | self._preferences = json.load(json_pref) 37 | except Exception: # pylint: disable=broad-except 38 | pass 39 | 40 | @property 41 | def filepath(self) -> str: 42 | """ get filepath """ 43 | return self._filepath 44 | 45 | def save(self) -> None: 46 | """ save preferences """ 47 | with open(self._filepath, 'w') as pref_output: 48 | json.dump(self._preferences, pref_output, sort_keys=True, indent=4) 49 | 50 | def get_version(self) -> str: 51 | """ get version """ 52 | if 'version' in self._preferences: 53 | return self._preferences['version'] 54 | 55 | return None 56 | 57 | def get_browser_geometry(self, default_value: Optional[str] = None) -> str: 58 | """ get aqua browser geometry """ 59 | if 'browser_geometry' in self._preferences: 60 | return self._preferences['browser_geometry'] 61 | 62 | return default_value 63 | 64 | def set_browser_geometry(self, geometry: str) -> None: 65 | """ set aqua browser geometry """ 66 | self._preferences['browser_geometry'] = geometry 67 | 68 | def get_geometry(self, default_value: Optional[str] = None) -> str: 69 | """ get aqua geometry """ 70 | if 'run_geometry' in self._preferences: 71 | return self._preferences['run_geometry'] 72 | 73 | return default_value 74 | 75 | def set_geometry(self, geometry: str) -> None: 76 | """ set aqua geometry """ 77 | self._preferences['run_geometry'] = geometry 78 | 79 | def get_openfile_initialdir(self) -> str: 80 | """ get open file initial folder """ 81 | if 'openfile_initialdir' in self._preferences: 82 | if not os.path.isdir(self._preferences['openfile_initialdir']): 83 | self._preferences['openfile_initialdir'] = os.getcwd() 84 | 85 | return self._preferences['openfile_initialdir'] 86 | 87 | return os.getcwd() 88 | 89 | def set_openfile_initialdir(self, initialdir: str) -> None: 90 | """ set open file initial folder """ 91 | self._preferences['openfile_initialdir'] = initialdir 92 | 93 | def get_savefile_initialdir(self) -> str: 94 | """ get save file initial folder """ 95 | if 'savefile_initialdir' in self._preferences: 96 | if not os.path.isdir(self._preferences['savefile_initialdir']): 97 | self._preferences['savefile_initialdir'] = os.getcwd() 98 | 99 | return self._preferences['savefile_initialdir'] 100 | 101 | return os.getcwd() 102 | 103 | def set_savefile_initialdir(self, initialdir: str) -> None: 104 | """ set save file initial folder """ 105 | self._preferences['savefile_initialdir'] = initialdir 106 | 107 | def get_populate_defaults(self, default_value: Optional[bool] = None) -> bool: 108 | """ get populate defaults flag """ 109 | if 'populate_defaults' in self._preferences: 110 | return self._preferences['populate_defaults'] 111 | 112 | return default_value 113 | 114 | def set_populate_defaults(self, populate_defaults: bool) -> None: 115 | """ set populate defaults flag """ 116 | self._preferences['populate_defaults'] = populate_defaults 117 | 118 | def get_recent_files(self) -> List[str]: 119 | """ get recent files list """ 120 | files = [] 121 | if 'recent_files' in self._preferences: 122 | for file in self._preferences['recent_files']: 123 | if os.path.isfile(file): 124 | files.append(file) 125 | 126 | self._preferences['recent_files'] = files 127 | 128 | return files 129 | 130 | def add_recent_file(self, file: str) -> None: 131 | """ add a recent file """ 132 | recent_files = self.get_recent_files() 133 | if file not in recent_files: 134 | recent_files.append(file) 135 | if len(recent_files) > 6: 136 | recent_files = recent_files[1:] 137 | self._preferences['recent_files'] = recent_files 138 | 139 | def clear_recent_files(self) -> None: 140 | """ clear recent files list """ 141 | if 'recent_files' in self._preferences: 142 | del self._preferences['recent_files'] 143 | 144 | def get_logging_config(self, 145 | default_value: Optional[Dict[str, object]] = None) -> Dict[str, object]: 146 | """ get aqua logging """ 147 | if 'logging_config' in self._preferences: 148 | return self._preferences['logging_config'] 149 | 150 | return default_value 151 | 152 | def set_logging_config(self, logging_config: Dict[str, object]) -> None: 153 | """ set aqua logging """ 154 | self._preferences['logging_config'] = logging_config 155 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/aqua/browser/_mainview.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Main View""" 16 | 17 | import sys 18 | import tkinter as tk 19 | import tkinter.messagebox as tkmb 20 | import tkinter.ttk as ttk 21 | from tkinter import font 22 | import webbrowser 23 | from qiskit_aqua_interfaces import __version__ 24 | from qiskit_aqua_interfaces.aqua.user_interface import UIPreferences 25 | from ._controller import Controller 26 | from ._sectionsview import SectionsView 27 | from ._sectionpropertiesview import SectionPropertiesView 28 | from ._emptyview import EmptyView 29 | 30 | # pylint: disable=import-outside-toplevel 31 | 32 | 33 | class MainView(ttk.Frame): 34 | """ Aqua Browser Main View """ 35 | _HELP_LINK = 'https://qiskit.org/' 36 | 37 | def __init__(self, parent=None) -> None: 38 | """Create MainView object.""" 39 | super(MainView, self).__init__(parent) 40 | self._controller = Controller(self) 41 | self.pack(expand=tk.YES, fill=tk.BOTH) 42 | self._create_widgets() 43 | self.master.title('Qiskit Aqua Browser') 44 | if parent is not None: 45 | parent.protocol('WM_DELETE_WINDOW', self.quit) 46 | 47 | def _show_about_dialog(self): 48 | import qiskit.aqua as qa 49 | lines = ['Qiskit Aqua Interfaces', 50 | 'Version: {}'.format(__version__), 51 | '', 52 | 'Qiskit Aqua', 53 | 'Version: {}'.format(qa.__version__), 54 | ] 55 | tkmb.showinfo('Qiskit Aqua Browser', message='\n'.join(lines)) 56 | 57 | def _create_widgets(self): 58 | self._make_menubar() 59 | self._create_pane() 60 | 61 | def _make_menubar(self): 62 | menubar = tk.Menu(self.master) 63 | if sys.platform == 'darwin': 64 | app_menu = tk.Menu(menubar, name='apple') 65 | menubar.add_cascade(menu=app_menu) 66 | app_menu.add_command(label='About Qiskit Aqua Browser', command=self._show_about_dialog) 67 | self.master.createcommand('tk::mac::Quit', self.quit) 68 | 69 | self.master.config(menu=menubar) 70 | self._controller._filemenu = self._make_filemenu(menubar) 71 | 72 | help_menu = tk.Menu(menubar, tearoff=False) 73 | if sys.platform != 'darwin': 74 | help_menu.add_command(label='About Qiskit Aqua Browser', 75 | command=self._show_about_dialog) 76 | 77 | help_menu.add_command(label='Open Help Center', command=self._open_help_center) 78 | menubar.add_cascade(label='Help', menu=help_menu) 79 | 80 | def _open_help_center(self): 81 | webbrowser.open(MainView._HELP_LINK) 82 | 83 | def _make_filemenu(self, menubar): 84 | if sys.platform != 'darwin': 85 | file_menu = tk.Menu(menubar, tearoff=False) 86 | file_menu.add_separator() 87 | file_menu.add_command(label='Exit', command=self.quit) 88 | menubar.add_cascade(label='File', menu=file_menu) 89 | return file_menu 90 | 91 | return None 92 | 93 | def _create_pane(self): 94 | main_pane = ttk.PanedWindow(self, orient=tk.VERTICAL) 95 | main_pane.pack(expand=tk.YES, fill=tk.BOTH) 96 | top_pane = ttk.PanedWindow(main_pane, orient=tk.HORIZONTAL) 97 | top_pane.pack(expand=tk.YES, fill=tk.BOTH) 98 | main_pane.add(top_pane) 99 | 100 | self._controller._sections_view = SectionsView(self._controller, top_pane) 101 | self._controller._sections_view.pack(expand=tk.YES, fill=tk.BOTH) 102 | top_pane.add(self._controller._sections_view) 103 | 104 | main_container = tk.Frame(top_pane) 105 | main_container.pack(expand=tk.YES, fill=tk.BOTH) 106 | style = ttk.Style() 107 | style.configure('PropViewTitle.TLabel', 108 | borderwidth=1, 109 | relief=tk.RIDGE, 110 | anchor=tk.CENTER) 111 | label = ttk.Label(main_container, 112 | style='PropViewTitle.TLabel', 113 | padding=(5, 5, 5, 5), 114 | textvariable=self._controller._sections_view_title) 115 | label_font = font.nametofont('TkHeadingFont').copy() 116 | label_font.configure(size=12, weight='bold') 117 | label['font'] = label_font 118 | 119 | label.pack(side=tk.TOP, expand=tk.NO, fill=tk.X) 120 | container = tk.Frame(main_container) 121 | container.pack(side=tk.BOTTOM, expand=tk.YES, fill=tk.BOTH) 122 | container.grid_rowconfigure(0, weight=1) 123 | container.grid_columnconfigure(0, weight=1) 124 | self._controller._empty_view = EmptyView(container) 125 | self._controller._empty_view.grid(row=0, column=0, sticky='nsew') 126 | 127 | self._controller._properties_view = SectionPropertiesView(self._controller, container) 128 | self._controller._properties_view.grid(row=0, column=0, sticky='nsew') 129 | self._controller._empty_view.tkraise() 130 | top_pane.add(main_container, weight=1) 131 | 132 | self.update_idletasks() 133 | self.after(0, self._controller.populate_sections) 134 | 135 | def quit(self): 136 | if tkmb.askyesno('Verify quit', 'Are you sure you want to quit?'): 137 | preferences = UIPreferences() 138 | preferences.set_browser_geometry(self.master.winfo_geometry()) 139 | preferences.save() 140 | ttk.Frame.quit(self) 141 | return True 142 | 143 | return False 144 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/aqua/browser/_model.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Qiskit Aqua browser user interface model.""" 16 | 17 | from collections import OrderedDict 18 | import copy 19 | 20 | # pylint: disable=import-outside-toplevel 21 | 22 | 23 | class Model: 24 | """ Aqua Browser Model """ 25 | def __init__(self) -> None: 26 | """Create Model object.""" 27 | self._data_loaded = False 28 | self._schema_property_titles = None 29 | self._sections = None 30 | 31 | def _load_data(self): 32 | if self._data_loaded: 33 | return 34 | 35 | from qiskit.aqua import (local_pluggables_types, 36 | local_pluggables, 37 | get_pluggable_configuration) 38 | 39 | self._schema_property_titles = OrderedDict() 40 | self._sections = OrderedDict() 41 | for pluggable_type in sorted(local_pluggables_types(), key=lambda x: x.value): 42 | self._sections[pluggable_type.value] = OrderedDict() 43 | self._schema_property_titles[pluggable_type.value] = OrderedDict() 44 | for pluggable_name in sorted(local_pluggables(pluggable_type)): 45 | config = copy.deepcopy(get_pluggable_configuration(pluggable_type, pluggable_name)) 46 | self._populate_section(pluggable_type.value, pluggable_name, config) 47 | 48 | self._data_loaded = True 49 | 50 | def _populate_section(self, pluggable_type, pluggable_name, configuration): 51 | self._sections[pluggable_type][pluggable_name] = OrderedDict() 52 | self._sections[pluggable_type][pluggable_name]['description'] = pluggable_name 53 | self._sections[pluggable_type][pluggable_name]['properties'] = OrderedDict() 54 | self._sections[pluggable_type][pluggable_name]['problems'] = [] 55 | self._sections[pluggable_type][pluggable_name]['depends'] = OrderedDict() 56 | self._schema_property_titles[pluggable_type][pluggable_name] = OrderedDict() 57 | for config_name, config_value in configuration.items(): 58 | if config_name == 'description': 59 | self._sections[pluggable_type][pluggable_name]['description'] = str(config_value) 60 | continue 61 | 62 | if config_name == 'problems' and isinstance(config_value, list): 63 | self._sections[pluggable_type][pluggable_name]['problems'] = config_value 64 | continue 65 | 66 | if config_name == 'depends' and isinstance(config_value, list): 67 | self._sections[pluggable_type][pluggable_name]['depends'] = config_value 68 | continue 69 | 70 | if config_name == 'input_schema' and isinstance(config_value, dict): 71 | schema = config_value 72 | if 'properties' in schema: 73 | for prop, values in schema['properties'].items(): 74 | if 'items' in values: 75 | if 'type' in values['items']: 76 | values['items'] = values['items']['type'] 77 | if 'oneOf' in values: 78 | values['oneOf'] = values['oneOf'][0] 79 | if 'enum' in values['oneOf']: 80 | values['oneOf'] = values['oneOf']['enum'] 81 | 82 | values['one of'] = values['oneOf'] 83 | del values['oneOf'] 84 | 85 | self._sections[pluggable_type][pluggable_name]['properties'][prop] = values 86 | for k, _ in values.items(): 87 | self._schema_property_titles[pluggable_type][pluggable_name][k] = None 88 | continue 89 | 90 | self._schema_property_titles[pluggable_type][pluggable_name] = \ 91 | list(self._schema_property_titles[pluggable_type][pluggable_name].keys()) 92 | 93 | def pluggable_names(self): 94 | """ get all pluggable names """ 95 | self._load_data() 96 | return list(self._sections.keys()) 97 | 98 | def get_pluggable_description(self, pluggable_type, pluggable_name): 99 | """ get pluggable description """ 100 | self._load_data() 101 | return self._sections[pluggable_type][pluggable_name]['description'] 102 | 103 | def get_pluggable_problems(self, pluggable_type, pluggable_name): 104 | """ get pluggable problems """ 105 | self._load_data() 106 | return self._sections[pluggable_type][pluggable_name]['problems'] 107 | 108 | def get_pluggable_dependency(self, pluggable_type, pluggable_name, dependency_type): 109 | """ get pluggable dependency """ 110 | self._load_data() 111 | depends = self._sections[pluggable_type][pluggable_name]['depends'] 112 | for dependency in depends: 113 | if dependency.get('pluggable_type') == dependency_type: 114 | return dependency 115 | 116 | return {} 117 | 118 | def get_pluggable_schema_property_titles(self, pluggable_type, pluggable_name): 119 | """ get pluggable schema property titles """ 120 | self._load_data() 121 | return self._schema_property_titles[pluggable_type][pluggable_name] 122 | 123 | def get_sections(self): 124 | """ get sections """ 125 | self._load_data() 126 | return self._sections 127 | 128 | def get_pluggable_schema_properties(self, pluggable_type, pluggable_name): 129 | """ get pluggable schema properties """ 130 | self._load_data() 131 | return self._sections[pluggable_type][pluggable_name]['properties'] 132 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/chemistry/command_line/command_line.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Qiskit Chemistry command line main.""" 16 | 17 | import sys 18 | import argparse 19 | import json 20 | from collections import OrderedDict 21 | import textwrap 22 | import logging 23 | from qiskit_aqua_interfaces import APP_DEPRECATION_MSG 24 | from qiskit_aqua_interfaces.chemistry.user_interface import UIPreferences 25 | from qiskit_aqua_interfaces._extras_require import _check_extra_requires 26 | 27 | # pylint: disable=import-outside-toplevel 28 | 29 | 30 | def main(): 31 | """Runs main Chemistry command line.""" 32 | if sys.platform != 'darwin': 33 | _run() 34 | return 35 | 36 | # On MacOSX avoid possible matplotlib error in case it is imported by other imported libraries 37 | import tkinter as tk 38 | root = tk.Tk() 39 | root.withdraw() 40 | root.after(0, _run_delay, root) 41 | root.mainloop() 42 | 43 | 44 | def _run_delay(root): 45 | try: 46 | _run() 47 | finally: 48 | if root is not None: 49 | root.destroy() 50 | 51 | 52 | def _run_algorithm_from_json(params, output_file): 53 | """Runs the Aqua Chemistry experiment from Qiskit Aqua json dictionary 54 | 55 | Args: 56 | params (dictionary): Qiskit Aqua json dictionary 57 | output_file (filename): Output file name to save results 58 | """ 59 | from qiskit.aqua import run_algorithm 60 | from qiskit.aqua.utils import convert_json_to_dict 61 | 62 | ret = run_algorithm(params, None, True) 63 | if output_file is not None: 64 | with open(output_file, 'w') as run_output: 65 | print('{}'.format(ret), file=run_output) 66 | else: 67 | convert_json_to_dict(ret) 68 | print('\n\n--------------------------------- R E S U L T ----' 69 | '--------------------------------\n') 70 | if isinstance(ret, dict): 71 | for k, v in ret.items(): 72 | print("'{}': {}".format(k, v)) 73 | else: 74 | print(ret) 75 | 76 | 77 | def _run(): 78 | _check_extra_requires('console_scripts', 'qiskit_chemistry_cmd') 79 | from qiskit.chemistry import run_experiment, run_driver_to_json 80 | from qiskit.chemistry._logging import (get_logging_level, 81 | build_logging_config, 82 | set_logging_config, 83 | set_qiskit_chemistry_logging) 84 | preferences = UIPreferences() 85 | log_levels = OrderedDict( 86 | [(logging.getLevelName(logging.CRITICAL).lower(), logging.CRITICAL), 87 | (logging.getLevelName(logging.ERROR).lower(), logging.ERROR), 88 | (logging.getLevelName(logging.WARNING).lower(), logging.WARNING), 89 | (logging.getLevelName(logging.INFO).lower(), logging.INFO), 90 | (logging.getLevelName(logging.DEBUG).lower(), logging.DEBUG), 91 | (logging.getLevelName(logging.NOTSET).lower(), logging.NOTSET)] 92 | ) 93 | 94 | parser = argparse.ArgumentParser(prog='qiskit_chemistry_cmd', 95 | formatter_class=argparse.RawTextHelpFormatter, 96 | description='Qiskit Chemistry Command Line Tool') 97 | parser.add_argument('input', 98 | metavar='input', 99 | help='Qiskit Chemistry input file or saved JSON input file') 100 | group = parser.add_mutually_exclusive_group(required=False) 101 | group.add_argument('-o', 102 | metavar='output', 103 | help='Algorithm Results Output file name') 104 | group.add_argument('-jo', 105 | metavar='json output', 106 | help='Algorithm JSON Output file name') 107 | parser.add_argument('-l', 108 | metavar='logging', 109 | choices=log_levels.keys(), 110 | help=textwrap.dedent('''\ 111 | Logging level: 112 | {} 113 | (defaults to level from preferences file: {}) 114 | '''.format(list(log_levels.keys()), preferences.filepath)) 115 | ) 116 | 117 | args = parser.parse_args() 118 | 119 | if args.l is not None: 120 | set_qiskit_chemistry_logging(log_levels.get(args.l, logging.INFO)) 121 | else: 122 | # update logging setting with latest external packages 123 | logging_level = logging.INFO 124 | if preferences.get_logging_config() is not None: 125 | set_logging_config(preferences.get_logging_config()) 126 | logging_level = get_logging_level() 127 | 128 | preferences.set_logging_config(build_logging_config(logging_level)) 129 | preferences.save() 130 | set_logging_config(preferences.get_logging_config()) 131 | 132 | # check to see if input is json file 133 | params = None 134 | try: 135 | with open(args.input) as json_file: 136 | params = json.load(json_file) 137 | except Exception: # pylint: disable=broad-except 138 | pass 139 | 140 | print(APP_DEPRECATION_MSG) 141 | if params is not None: 142 | _run_algorithm_from_json(params, args.o) 143 | else: 144 | if args.jo is not None: 145 | run_driver_to_json(args.input, args.jo) 146 | else: 147 | result = run_experiment(args.input, args.o) 148 | if result is not None and 'printable' in result: 149 | print('\n\n--------------------------------- R E S U L T ' 150 | '------------------------------------\n') 151 | for line in result['printable']: 152 | print(line) 153 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/chemistry/user_interface/_chemguiprovider.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Chemistry User Interface Provider""" 16 | 17 | import tkinter as tk 18 | import tkinter.ttk as ttk 19 | import tkinter.filedialog as tkfd 20 | from tkinter import messagebox 21 | import os 22 | import json 23 | import pprint 24 | from qiskit_aqua_interfaces.user_interface import GUIProvider 25 | from ._uipreferences import UIPreferences 26 | from ._chemsectionpropertiesview import ChemSectionPropertiesView 27 | from ._chemthread import ChemistryThread 28 | from ._controller import Controller 29 | 30 | # pylint: disable=import-outside-toplevel 31 | 32 | 33 | class ChemistryGUIProvider(GUIProvider): 34 | """Chemistry GUIProvider""" 35 | 36 | def __init__(self) -> None: 37 | super().__init__() 38 | self._save_algo_json = None 39 | self._controller = None 40 | 41 | @property 42 | def save_algo_json(self): 43 | """ get save algorithm json flag """ 44 | if self._save_algo_json is None: 45 | self._save_algo_json = tk.IntVar() 46 | self._save_algo_json.set(0) 47 | 48 | return self._save_algo_json 49 | 50 | @property 51 | def title(self): 52 | """Return provider title.""" 53 | return 'Qiskit Chemistry' 54 | 55 | @property 56 | def help_hyperlink(self): 57 | """Return provider help hyperlink.""" 58 | return 'https://qiskit.org/' 59 | 60 | @property 61 | def controller(self): 62 | """Return provider controller.""" 63 | if self._controller is None: 64 | self._controller = Controller(self) 65 | 66 | return self._controller 67 | 68 | def create_uipreferences(self): 69 | """Creates provider UI preferences.""" 70 | return UIPreferences() 71 | 72 | def get_logging_level(self): 73 | """get level for the named logger.""" 74 | from qiskit.chemistry._logging import get_logging_level as chem_get_logging_level 75 | return chem_get_logging_level() 76 | 77 | def set_logging_config(self, logging_config): 78 | """Update logger configurations using a SDK default one.""" 79 | from qiskit.chemistry._logging import set_logging_config as chem_set_logging_config 80 | chem_set_logging_config(logging_config) 81 | 82 | def build_logging_config(self, level): 83 | """Creates a the configuration dict of the named loggers""" 84 | from qiskit.chemistry._logging import build_logging_config as chem_build_logging_config 85 | return chem_build_logging_config(level) 86 | 87 | def create_section_properties_view(self, parent): 88 | """Creates provider section properties view""" 89 | return ChemSectionPropertiesView(self.controller, parent) 90 | 91 | def add_toolbar_items(self, toolbar): 92 | """Add items to toolbar""" 93 | checkbutton = ttk.Checkbutton(toolbar, 94 | text="Generate Algorithm Input", 95 | variable=self.save_algo_json) 96 | checkbutton.pack(side=tk.LEFT) 97 | 98 | def add_file_menu_items(self, file_menu): 99 | """Add items to file menu""" 100 | dict_menu = tk.Menu(file_menu, tearoff=False) 101 | file_menu.add_cascade(label="Export Dictionary", menu=dict_menu) 102 | dict_menu.add_command(label='Clipboard', command=self._export_dictionary_to_clipboard) 103 | dict_menu.add_command(label='File...', command=self._export_dictionary_to_file) 104 | 105 | def create_run_thread(self, model, outputview, thread_queue): 106 | """Creates run thread""" 107 | filename = None 108 | if self.save_algo_json.get() != 0: 109 | preferences = self.create_uipreferences() 110 | filename = tkfd.asksaveasfilename(parent=self.controller.view, 111 | title='Algorithm Input', 112 | initialdir=preferences.get_savefile_initialdir()) 113 | if not filename: 114 | return None 115 | 116 | preferences.set_savefile_initialdir(os.path.dirname(filename)) 117 | preferences.save() 118 | 119 | return ChemistryThread(model, outputview, thread_queue, filename) 120 | 121 | def _export_dictionary_to_clipboard(self): 122 | if self.controller.is_empty(): 123 | self.controller.outputview.write_line("No data to export.") 124 | return 125 | 126 | try: 127 | value = json.loads(json.dumps(self.controller.model.get_dictionary())) 128 | value = pprint.pformat(value, indent=4) 129 | self.controller.view.clipboard_clear() 130 | self.controller.view.clipboard_append(value) 131 | self.controller.outputview.write_line("Exported to clibpoard.") 132 | except Exception as ex: # pylint: disable=broad-except 133 | messagebox.showerror("Error", str(ex)) 134 | 135 | def _export_dictionary_to_file(self): 136 | if self.controller.is_empty(): 137 | self.controller.outputview.write_line("No data to export.") 138 | return 139 | 140 | preferences = self.create_uipreferences() 141 | filename = tkfd.asksaveasfilename(parent=self.controller.view, 142 | title='Export Chemistry Input', 143 | initialdir=preferences.get_savefile_initialdir()) 144 | if filename: 145 | try: 146 | self.controller.model.export_dictionary(filename) 147 | self.controller.outputview.write_line("Exported to file: {}".format(filename)) 148 | preferences.set_savefile_initialdir(os.path.dirname(filename)) 149 | preferences.save() 150 | except Exception as ex: # pylint: disable=broad-except 151 | messagebox.showerror("Error", str(ex)) 152 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/chemistry/user_interface/_controller.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Qiskit Chemistry user interface controller.""" 16 | 17 | from tkinter import messagebox 18 | import logging 19 | from qiskit_aqua_interfaces.user_interface import BaseController 20 | from ._model import Model 21 | 22 | logger = logging.getLogger(__name__) 23 | 24 | # pylint: disable=import-outside-toplevel 25 | 26 | 27 | class Controller(BaseController): 28 | """ Chemistry Controller """ 29 | def __init__(self, guiprovider) -> None: 30 | super().__init__(guiprovider, Model()) 31 | 32 | def open_file(self, filename): 33 | ret = super().open_file(filename) 34 | if ret and not self.model.get_section_names(): 35 | self.outputview.write_line('The file appears not to be a qiskit chemistry input file; ' 36 | 'no begin/end sections found.') 37 | 38 | return ret 39 | 40 | def cb_section_select(self, section_name): 41 | self._sections_view.show_remove_button(True) 42 | self._sections_view_title.set(section_name) 43 | if self.model.section_is_text(section_name): 44 | self._text_view.populate(self.model.get_section_text(section_name)) 45 | self._text_view.section_name = section_name 46 | self._text_view.show_add_button(False) 47 | self._text_view.show_remove_button(False) 48 | self._text_view.show_defaults_button( 49 | not self.model.default_properties_equals_properties(section_name)) 50 | self._text_view.tkraise() 51 | else: 52 | self._properties_view.show_add_button(self.shows_add_button(section_name)) 53 | self._properties_view.populate( 54 | self.model.get_section_properties_with_substitution(section_name)) 55 | self._properties_view.section_name = section_name 56 | self._properties_view.show_remove_button(False) 57 | self._properties_view.show_defaults_button( 58 | not self.model.default_properties_equals_properties(section_name)) 59 | self._properties_view.tkraise() 60 | 61 | def cb_section_defaults(self, section_name): 62 | from qiskit.chemistry.parser import InputParser 63 | try: 64 | self.model.set_default_properties_for_name(section_name) 65 | if section_name == InputParser.DRIVER: 66 | section_names = self.model.get_section_names() 67 | self._sections_view.populate(section_names) 68 | missing = self.get_sections_names_missing() 69 | self._sections_view.show_add_button(bool(missing)) 70 | 71 | self.cb_section_select(section_name) 72 | return True 73 | except Exception as ex: # pylint: disable=broad-except 74 | messagebox.showerror("Error", str(ex)) 75 | 76 | return False 77 | 78 | def cb_property_set(self, section_name, property_name, value): 79 | from qiskit.aqua.parser import JSONSchema 80 | try: 81 | self.model.set_section_property(section_name, property_name, value) 82 | except Exception as ex: # pylint: disable=broad-except 83 | messagebox.showerror("Error", str(ex)) 84 | return False 85 | 86 | try: 87 | self._properties_view.populate( 88 | self.model.get_section_properties_with_substitution(section_name)) 89 | self._properties_view.show_add_button(self.shows_add_button(section_name)) 90 | _show_remove = property_name not in (JSONSchema.PROVIDER, JSONSchema.NAME) \ 91 | if section_name == JSONSchema.BACKEND else property_name != JSONSchema.NAME 92 | self._properties_view.show_remove_button( 93 | _show_remove and self._properties_view.has_selection()) 94 | self._properties_view.show_defaults_button( 95 | not self.model.default_properties_equals_properties(section_name)) 96 | section_names = self.model.get_section_names() 97 | self._sections_view.populate(section_names, section_name) 98 | missing = self.get_sections_names_missing() 99 | self._sections_view.show_add_button(bool(missing)) 100 | return True 101 | except Exception as ex: # pylint: disable=broad-except 102 | messagebox.showerror("Error", str(ex)) 103 | 104 | return False 105 | 106 | def cb_section_property_remove(self, section_name, property_name): 107 | try: 108 | self.model.delete_section_property(section_name, property_name) 109 | self._properties_view.populate( 110 | self.model.get_section_properties_with_substitution(section_name)) 111 | self._properties_view.show_add_button(self.shows_add_button(section_name)) 112 | self._properties_view.show_remove_button(False) 113 | self._properties_view.show_defaults_button( 114 | not self.model.default_properties_equals_properties(section_name)) 115 | except Exception as ex: # pylint: disable=broad-except 116 | self.outputview.write_line(str(ex)) 117 | 118 | def get_combobox_parameters(self, section_name, property_name): 119 | from qiskit.aqua.parser import JSONSchema 120 | from qiskit.chemistry.parser import InputParser 121 | from qiskit.chemistry.drivers import local_drivers 122 | values = None 123 | types = ['string'] 124 | combobox_state = 'readonly' 125 | if InputParser.OPERATOR == section_name and JSONSchema.NAME == property_name: 126 | values = self.model.get_operator_section_names() 127 | elif InputParser.DRIVER == section_name and JSONSchema.NAME == property_name: 128 | values = local_drivers() 129 | else: 130 | combobox_state, types, values = \ 131 | super().get_combobox_parameters(section_name, property_name) 132 | 133 | return combobox_state, types, values 134 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/user_interface/_preferencesdialog.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Preferences Dialog""" 16 | 17 | import tkinter as tk 18 | import tkinter.ttk as ttk 19 | from collections import OrderedDict 20 | import logging 21 | from ._dialog import Dialog 22 | from ._credentialsview import CredentialsView 23 | 24 | # pylint: disable=import-outside-toplevel 25 | 26 | 27 | class PreferencesDialog(Dialog): 28 | """ Preferences Dialog """ 29 | log_levels = OrderedDict( 30 | [(logging.CRITICAL, logging.getLevelName(logging.CRITICAL)), 31 | (logging.ERROR, logging.getLevelName(logging.ERROR)), 32 | (logging.WARNING, logging.getLevelName(logging.WARNING)), 33 | (logging.INFO, logging.getLevelName(logging.INFO)), 34 | (logging.DEBUG, logging.getLevelName(logging.DEBUG)), 35 | (logging.NOTSET, logging.getLevelName(logging.NOTSET))] 36 | ) 37 | 38 | def __init__(self, parent, guiprovider) -> None: 39 | super(PreferencesDialog, self).__init__(guiprovider.controller, parent, 'Preferences') 40 | self._guiprovider = guiprovider 41 | self._credentialsview = None 42 | self._level_combo = None 43 | self._check_button = None 44 | self._populate_defaults = tk.IntVar() 45 | 46 | def body(self, parent, options): 47 | preferences = self._guiprovider.create_uipreferences() 48 | logging_config = preferences.get_logging_config() 49 | if logging_config is not None: 50 | self._guiprovider.set_logging_config(logging_config) 51 | 52 | populate = preferences.get_populate_defaults(True) 53 | self._populate_defaults.set(1 if populate else 0) 54 | 55 | current_row = 0 56 | from qiskit.aqua.utils import has_ibmq 57 | if has_ibmq(): 58 | credentials_group = ttk.LabelFrame(parent, 59 | text='IBMQ Credentials', 60 | padding=(6, 6, 6, 6), 61 | borderwidth=4, 62 | relief=tk.GROOVE) 63 | credentials_group.grid(padx=(7, 7), pady=6, row=current_row, 64 | column=0, sticky='nsew') 65 | self._credentialsview = CredentialsView(credentials_group) 66 | current_row += 1 67 | 68 | defaults_group = ttk.LabelFrame(parent, 69 | text='Defaults', 70 | padding=(6, 6, 6, 6), 71 | borderwidth=4, 72 | relief=tk.GROOVE) 73 | defaults_group.grid(padx=(7, 7), pady=6, row=current_row, column=0, sticky='nsw') 74 | defaults_group.columnconfigure(1, pad=7) 75 | current_row += 1 76 | 77 | self._check_button = ttk.Checkbutton(defaults_group, 78 | text="Populate on file new/open", 79 | variable=self._populate_defaults) 80 | self._check_button.grid(row=0, column=1, sticky='nsw') 81 | 82 | logging_group = ttk.LabelFrame(parent, 83 | text='Logging Configuration', 84 | padding=(6, 6, 6, 6), 85 | borderwidth=4, 86 | relief=tk.GROOVE) 87 | logging_group.grid(padx=(7, 7), pady=6, row=current_row, column=0, sticky='nsw') 88 | logging_group.columnconfigure(1, pad=7) 89 | current_row += 1 90 | 91 | loglevel = self._guiprovider.get_logging_level() 92 | 93 | ttk.Label(logging_group, 94 | text="Level:", 95 | borderwidth=0, 96 | anchor=tk.E).grid(row=0, column=0, sticky='nsew') 97 | self._level_combo = ttk.Combobox(logging_group, 98 | exportselection=0, 99 | state='readonly', 100 | values=list(PreferencesDialog.log_levels.values())) 101 | index = list(PreferencesDialog.log_levels.keys()).index(loglevel) 102 | self._level_combo.current(index) 103 | self._level_combo.grid(row=0, column=1, sticky='nsw') 104 | 105 | self.entry = \ 106 | self._credentialsview.initial_focus if self._credentialsview else self._check_button 107 | return self.entry # initial focus 108 | 109 | def validate(self): 110 | if self._credentialsview: 111 | if not self._credentialsview.validate(): 112 | self.initial_focus = self._credentialsview.initial_focus 113 | return False 114 | 115 | self.initial_focus = self._credentialsview.initial_focus 116 | 117 | return True 118 | 119 | def apply(self): 120 | try: 121 | level_name = self._level_combo.get() 122 | levels = \ 123 | [key for key, value in PreferencesDialog.log_levels.items() if value == level_name] 124 | loglevel = levels[0] 125 | 126 | logging_config = self._guiprovider.build_logging_config(loglevel) 127 | populate = self._populate_defaults.get() 128 | preferences = self._guiprovider.create_uipreferences() 129 | preferences.set_logging_config(logging_config) 130 | preferences.set_populate_defaults(populate != 0) 131 | preferences.save() 132 | 133 | self._guiprovider.set_logging_config(logging_config) 134 | 135 | if self._credentialsview: 136 | from qiskit.aqua import Preferences 137 | preferences = Preferences() 138 | self._credentialsview.apply(preferences) 139 | preferences.save() 140 | 141 | self._controller.model.get_available_providers() 142 | except Exception as ex: # pylint: disable=broad-except 143 | self.controller.outputview.write_line(str(ex)) 144 | 145 | def do_cancel(self): 146 | if self._credentialsview: 147 | self._credentialsview.do_cancel() 148 | -------------------------------------------------------------------------------- /test/test_aquamodel.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Aqua Model test.""" 16 | 17 | import unittest 18 | from test.common import QiskitAquaUisTestCase 19 | from qiskit.aqua import AquaError 20 | from qiskit_aqua_interfaces.aqua.user_interface._model import Model 21 | 22 | 23 | class TestAquaModel(QiskitAquaUisTestCase): 24 | """Aqua UI Model tests.""" 25 | 26 | def setUp(self): 27 | super().setUp() 28 | _filepath = self._get_resource_path('resources/vqe.json') 29 | self._model = Model() 30 | self._model.load_file(_filepath) 31 | # make sure defaults are populated 32 | self._model._parser.validate_merge_defaults() 33 | 34 | def test_new(self): 35 | """Test new model. Passes if required sections are included.""" 36 | section_names = self._model.new() 37 | for name in ['algorithm', 'backend']: 38 | self.assertIn(name, section_names) 39 | 40 | def test_open(self): 41 | """Test open model. Passes if required sections are included.""" 42 | section_names = self._model.get_section_names() 43 | for name in ['algorithm', 'backend', 'initial_state', 'input', 44 | 'optimizer', 'problem', 'variational_form']: 45 | self.assertIn(name, section_names) 46 | 47 | def test_get_input_section_names(self): 48 | """Test if model has EnergyInput.""" 49 | section_names = self._model.get_input_section_names() 50 | self.assertEqual(section_names, ['EnergyInput']) 51 | 52 | def test_get_property_default_values(self): 53 | """Test if model has correct default values.""" 54 | initial_point = self._model.get_property_default_values('algorithm', 'initial_point') 55 | self.assertEqual(initial_point, None) 56 | 57 | def test_section_is_text(self): 58 | """Test if model has correct text section.""" 59 | ret = self._model.section_is_text('problem') 60 | self.assertFalse(ret) 61 | 62 | def test_get_section(self): 63 | """Test if model can access section.""" 64 | section = self._model.get_section('initial_state') 65 | self.assertEqual(section, {'name': 'ZERO'}) 66 | 67 | def test_get_section_text(self): 68 | """Test if model can access section text.""" 69 | text = self._model.get_section_text('algorithm') 70 | self.assertIsInstance(text, str) 71 | 72 | def test_get_section_properties(self): 73 | """Test if model can access section properties.""" 74 | expected = { 75 | 'depth': 3, 76 | 'entanglement': "linear", 77 | 'entangler_map': None, 78 | 'name': "RYRZ" 79 | } 80 | properties = self._model.get_section_properties('variational_form') 81 | subset = {k: v for k, v in properties.items() if k in expected} 82 | self.assertDictEqual(subset, expected) 83 | 84 | def test_default_properties_equals_properties(self): 85 | """Test if model default properties are the same as current properties.""" 86 | ret = self._model.default_properties_equals_properties('optimizer') 87 | self.assertTrue(ret) 88 | 89 | def test_get_section_property(self): 90 | """Test if model can access section property.""" 91 | prop = self._model.get_section_property('algorithm', 'name') 92 | self.assertEqual(prop, 'VQE') 93 | 94 | def test_set_section(self): 95 | """Test if model can update section.""" 96 | self._model.set_section('oracle') 97 | section_names = self._model.get_section_names() 98 | self.assertIn('oracle', section_names) 99 | 100 | def test_get_pluggable_section_names(self): 101 | """Test if model can access pluggable sections.""" 102 | section_names = self._model.get_pluggable_section_names('initial_state') 103 | for name in ['CUSTOM', 'ZERO', 'HartreeFock']: 104 | self.assertIn(name, section_names) 105 | 106 | def test_get_default_sections(self): 107 | """Test if model can access default sections.""" 108 | section_names = self._model.get_default_sections().keys() 109 | for name in ['algorithm', 'backend', 'initial_state', 'input', 110 | 'optimizer', 'problem', 'variational_form']: 111 | self.assertIn(name, section_names) 112 | 113 | def test_get_section_default_properties(self): 114 | """Test if model can access default section properties.""" 115 | properties = self._model.get_section_default_properties('initial_state') 116 | self.assertEqual(properties, {'name': 'ZERO'}) 117 | 118 | def test_allows_additional_properties(self): 119 | """Test if model can access default section properties.""" 120 | ret = self._model.allows_additional_properties('algorithm') 121 | self.assertFalse(ret) 122 | 123 | def test_get_property_default_value(self): 124 | """Test if model can access default section property default value.""" 125 | value = self._model.get_property_default_value('algorithm', 'name') 126 | self.assertEqual(value, 'VQE') 127 | 128 | def test_get_property_types(self): 129 | """Test if model can access property types.""" 130 | types = self._model.get_property_types('algorithm', 'initial_point') 131 | self.assertEqual(types, ['array', 'null']) 132 | 133 | def test_set_section_property(self): 134 | """Test if model can update property.""" 135 | self._model.set_section_property('algorithm', 'initial_point', None) 136 | prop = self._model.get_section_property('algorithm', 'initial_point') 137 | self.assertEqual(prop, None) 138 | 139 | def test_delete_section_property(self): 140 | """Test if model can delete property.""" 141 | self._model.delete_section_property('optimizer', 'factr') 142 | ret = self._model.get_section_property('optimizer', 'factr') 143 | self.assertIsNone(ret) 144 | 145 | def test_set_section_text(self): 146 | """check that it fails because algorithm doesn't allow text""" 147 | with self.assertRaises(AquaError): 148 | self._model.set_section_text('algorithm', 'dummy') 149 | 150 | 151 | if __name__ == '__main__': 152 | unittest.main() 153 | -------------------------------------------------------------------------------- /test/test_chemistrymodel.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Chemistry Model test.""" 16 | 17 | import unittest 18 | from test.common import QiskitAquaUisTestCase 19 | from qiskit.aqua import AquaError 20 | from qiskit_aqua_interfaces.chemistry.user_interface._model import Model 21 | 22 | 23 | class TestChemistryModel(QiskitAquaUisTestCase): 24 | """Aqua UI Model tests.""" 25 | 26 | def setUp(self): 27 | super().setUp() 28 | _filepath = self._get_resource_path('resources/hdf5_h2_0.735_sto-3g.txt') 29 | self._model = Model() 30 | self._model.load_file(_filepath) 31 | # make sure defaults are populated 32 | self._model._parser.validate_merge_defaults() 33 | 34 | def test_new(self): 35 | """Test new model. Passes if required sections are included.""" 36 | section_names = self._model.new() 37 | for name in ['algorithm', 'backend', 'driver', 'hdf5', 'operator']: 38 | self.assertIn(name, section_names) 39 | 40 | def test_open(self): 41 | """Test open model. Passes if required sections are included.""" 42 | section_names = self._model.get_section_names() 43 | for name in ['name', 'driver', 'hdf5', 'operator', 44 | 'optimizer', 'variational_form', 'algorithm', 'backend']: 45 | self.assertIn(name, section_names) 46 | 47 | def test_get_property_default_values(self): 48 | """Test if model has correct default values.""" 49 | initial_point = self._model.get_property_default_values('algorithm', 'initial_point') 50 | self.assertEqual(initial_point, None) 51 | 52 | def test_section_is_text(self): 53 | """Test if model has correct text section.""" 54 | ret = self._model.section_is_text('problem') 55 | self.assertFalse(ret) 56 | 57 | def test_get_section(self): 58 | """Test if model can access section.""" 59 | section = self._model.get_section('initial_state') 60 | self.assertEqual(section, {'name': 'ZERO'}) 61 | 62 | def test_get_section_text(self): 63 | """Test if model can access section text.""" 64 | text = self._model.get_section_text('algorithm') 65 | self.assertIsInstance(text, str) 66 | 67 | def test_get_section_properties(self): 68 | """Test if model can access section properties.""" 69 | expected = { 70 | 'depth': 3, 71 | 'entanglement': "full", 72 | 'entangler_map': None, 73 | 'name': "RYRZ" 74 | } 75 | properties = self._model.get_section_properties('variational_form') 76 | subset = {k: v for k, v in properties.items() if k in expected} 77 | self.assertDictEqual(subset, expected) 78 | 79 | def test_default_properties_equals_properties(self): 80 | """Test if model default properties are the same as current properties.""" 81 | ret = self._model.default_properties_equals_properties('optimizer') 82 | self.assertTrue(ret) 83 | 84 | def test_get_section_property(self): 85 | """Test if model can access section property.""" 86 | prop = self._model.get_section_property('algorithm', 'name') 87 | self.assertEqual(prop, 'VQE') 88 | 89 | def test_set_section(self): 90 | """Test if model can update section.""" 91 | self._model.set_section('oracle') 92 | section_names = self._model.get_section_names() 93 | self.assertIn('oracle', section_names) 94 | 95 | def test_get_pluggable_section_names(self): 96 | """Test if model can access pluggable sections.""" 97 | section_names = self._model.get_pluggable_section_names('initial_state') 98 | for name in ['CUSTOM', 'ZERO', 'HartreeFock']: 99 | self.assertIn(name, section_names) 100 | 101 | def test_get_default_sections(self): 102 | """Test if model can access default sections.""" 103 | section_names = self._model.get_default_sections().keys() 104 | for name in ['name', 'driver', 'hdf5', 'operator', 'optimizer', 105 | 'variational_form', 'algorithm', 'backend']: 106 | self.assertIn(name, section_names) 107 | 108 | def test_get_section_default_properties(self): 109 | """Test if model can access default section properties.""" 110 | properties = self._model.get_section_default_properties('initial_state') 111 | self.assertEqual(properties, {'name': 'ZERO'}) 112 | 113 | def test_allows_additional_properties(self): 114 | """Test if model section allows more properties.""" 115 | ret = self._model.allows_additional_properties('algorithm') 116 | self.assertFalse(ret) 117 | 118 | def test_get_property_default_value(self): 119 | """Test if model can access default section property default value.""" 120 | value = self._model.get_property_default_value('algorithm', 'name') 121 | self.assertEqual(value, 'VQE') 122 | 123 | def test_get_property_types(self): 124 | """Test if model can access property types.""" 125 | types = self._model.get_property_types('algorithm', 'initial_point') 126 | self.assertEqual(types, ['array', 'null']) 127 | 128 | def test_set_section_property(self): 129 | """Test if model can update property.""" 130 | self._model.set_section_property('algorithm', 'initial_point', None) 131 | prop = self._model.get_section_property('algorithm', 'initial_point') 132 | self.assertEqual(prop, None) 133 | 134 | def test_delete_section_property(self): 135 | """Test if model can delete property.""" 136 | self._model.delete_section_property('optimizer', 'factr') 137 | ret = self._model.get_section_property('optimizer', 'factr') 138 | self.assertIsNone(ret) 139 | 140 | def test_set_section_text(self): 141 | """check that it fails because algorithm doesn't allow text""" 142 | with self.assertRaises(AquaError): 143 | self._model.set_section_text('algorithm', 'dummy') 144 | 145 | def test_get_dictionary(self): 146 | """Test if model can access dictionary properties.""" 147 | ret = self._model.get_dictionary() 148 | self.assertIsInstance(ret, dict) 149 | 150 | def test_get_section_properties_with_substitution(self): 151 | """Test if model can access properties with substitutions.""" 152 | expected = {'name': ('ZERO', False)} 153 | props = self._model.get_section_properties_with_substitution('initial_state') 154 | self.assertEqual(props, expected) 155 | 156 | def test_get_operator_section_names(self): 157 | """Test if model can access operator section names.""" 158 | operators = self._model.get_operator_section_names() 159 | self.assertIn('hamiltonian', operators) 160 | 161 | 162 | if __name__ == '__main__': 163 | unittest.main() 164 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2017 IBM and its contributors 2 | 3 | Apache License 4 | Version 2.0, January 2004 5 | http://www.apache.org/licenses/ 6 | 7 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 8 | 9 | 1. Definitions. 10 | 11 | "License" shall mean the terms and conditions for use, reproduction, 12 | and distribution as defined by Sections 1 through 9 of this document. 13 | 14 | "Licensor" shall mean the copyright owner or entity authorized by 15 | the copyright owner that is granting the License. 16 | 17 | "Legal Entity" shall mean the union of the acting entity and all 18 | other entities that control, are controlled by, or are under common 19 | control with that entity. For the purposes of this definition, 20 | "control" means (i) the power, direct or indirect, to cause the 21 | direction or management of such entity, whether by contract or 22 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 23 | outstanding shares, or (iii) beneficial ownership of such entity. 24 | 25 | "You" (or "Your") shall mean an individual or Legal Entity 26 | exercising permissions granted by this License. 27 | 28 | "Source" form shall mean the preferred form for making modifications, 29 | including but not limited to software source code, documentation 30 | source, and configuration files. 31 | 32 | "Object" form shall mean any form resulting from mechanical 33 | transformation or translation of a Source form, including but 34 | not limited to compiled object code, generated documentation, 35 | and conversions to other media types. 36 | 37 | "Work" shall mean the work of authorship, whether in Source or 38 | Object form, made available under the License, as indicated by a 39 | copyright notice that is included in or attached to the work 40 | (an example is provided in the Appendix below). 41 | 42 | "Derivative Works" shall mean any work, whether in Source or Object 43 | form, that is based on (or derived from) the Work and for which the 44 | editorial revisions, annotations, elaborations, or other modifications 45 | represent, as a whole, an original work of authorship. For the purposes 46 | of this License, Derivative Works shall not include works that remain 47 | separable from, or merely link (or bind by name) to the interfaces of, 48 | the Work and Derivative Works thereof. 49 | 50 | "Contribution" shall mean any work of authorship, including 51 | the original version of the Work and any modifications or additions 52 | to that Work or Derivative Works thereof, that is intentionally 53 | submitted to Licensor for inclusion in the Work by the copyright owner 54 | or by an individual or Legal Entity authorized to submit on behalf of 55 | the copyright owner. For the purposes of this definition, "submitted" 56 | means any form of electronic, verbal, or written communication sent 57 | to the Licensor or its representatives, including but not limited to 58 | communication on electronic mailing lists, source code control systems, 59 | and issue tracking systems that are managed by, or on behalf of, the 60 | Licensor for the purpose of discussing and improving the Work, but 61 | excluding communication that is conspicuously marked or otherwise 62 | designated in writing by the copyright owner as "Not a Contribution." 63 | 64 | "Contributor" shall mean Licensor and any individual or Legal Entity 65 | on behalf of whom a Contribution has been received by Licensor and 66 | subsequently incorporated within the Work. 67 | 68 | 2. Grant of Copyright License. Subject to the terms and conditions of 69 | this License, each Contributor hereby grants to You a perpetual, 70 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 71 | copyright license to reproduce, prepare Derivative Works of, 72 | publicly display, publicly perform, sublicense, and distribute the 73 | Work and such Derivative Works in Source or Object form. 74 | 75 | 3. Grant of Patent License. Subject to the terms and conditions of 76 | this License, each Contributor hereby grants to You a perpetual, 77 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 78 | (except as stated in this section) patent license to make, have made, 79 | use, offer to sell, sell, import, and otherwise transfer the Work, 80 | where such license applies only to those patent claims licensable 81 | by such Contributor that are necessarily infringed by their 82 | Contribution(s) alone or by combination of their Contribution(s) 83 | with the Work to which such Contribution(s) was submitted. If You 84 | institute patent litigation against any entity (including a 85 | cross-claim or counterclaim in a lawsuit) alleging that the Work 86 | or a Contribution incorporated within the Work constitutes direct 87 | or contributory patent infringement, then any patent licenses 88 | granted to You under this License for that Work shall terminate 89 | as of the date such litigation is filed. 90 | 91 | 4. Redistribution. You may reproduce and distribute copies of the 92 | Work or Derivative Works thereof in any medium, with or without 93 | modifications, and in Source or Object form, provided that You 94 | meet the following conditions: 95 | 96 | (a) You must give any other recipients of the Work or 97 | Derivative Works a copy of this License; and 98 | 99 | (b) You must cause any modified files to carry prominent notices 100 | stating that You changed the files; and 101 | 102 | (c) You must retain, in the Source form of any Derivative Works 103 | that You distribute, all copyright, patent, trademark, and 104 | attribution notices from the Source form of the Work, 105 | excluding those notices that do not pertain to any part of 106 | the Derivative Works; and 107 | 108 | (d) If the Work includes a "NOTICE" text file as part of its 109 | distribution, then any Derivative Works that You distribute must 110 | include a readable copy of the attribution notices contained 111 | within such NOTICE file, excluding those notices that do not 112 | pertain to any part of the Derivative Works, in at least one 113 | of the following places: within a NOTICE text file distributed 114 | as part of the Derivative Works; within the Source form or 115 | documentation, if provided along with the Derivative Works; or, 116 | within a display generated by the Derivative Works, if and 117 | wherever such third-party notices normally appear. The contents 118 | of the NOTICE file are for informational purposes only and 119 | do not modify the License. You may add Your own attribution 120 | notices within Derivative Works that You distribute, alongside 121 | or as an addendum to the NOTICE text from the Work, provided 122 | that such additional attribution notices cannot be construed 123 | as modifying the License. 124 | 125 | You may add Your own copyright statement to Your modifications and 126 | may provide additional or different license terms and conditions 127 | for use, reproduction, or distribution of Your modifications, or 128 | for any such Derivative Works as a whole, provided Your use, 129 | reproduction, and distribution of the Work otherwise complies with 130 | the conditions stated in this License. 131 | 132 | 5. Submission of Contributions. Unless You explicitly state otherwise, 133 | any Contribution intentionally submitted for inclusion in the Work 134 | by You to the Licensor shall be under the terms and conditions of 135 | this License, without any additional terms or conditions. 136 | Notwithstanding the above, nothing herein shall supersede or modify 137 | the terms of any separate license agreement you may have executed 138 | with Licensor regarding such Contributions. 139 | 140 | 6. Trademarks. This License does not grant permission to use the trade 141 | names, trademarks, service marks, or product names of the Licensor, 142 | except as required for reasonable and customary use in describing the 143 | origin of the Work and reproducing the content of the NOTICE file. 144 | 145 | 7. Disclaimer of Warranty. Unless required by applicable law or 146 | agreed to in writing, Licensor provides the Work (and each 147 | Contributor provides its Contributions) on an "AS IS" BASIS, 148 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 149 | implied, including, without limitation, any warranties or conditions 150 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 151 | PARTICULAR PURPOSE. You are solely responsible for determining the 152 | appropriateness of using or redistributing the Work and assume any 153 | risks associated with Your exercise of permissions under this License. 154 | 155 | 8. Limitation of Liability. In no event and under no legal theory, 156 | whether in tort (including negligence), contract, or otherwise, 157 | unless required by applicable law (such as deliberate and grossly 158 | negligent acts) or agreed to in writing, shall any Contributor be 159 | liable to You for damages, including any direct, indirect, special, 160 | incidental, or consequential damages of any character arising as a 161 | result of this License or out of the use or inability to use the 162 | Work (including but not limited to damages for loss of goodwill, 163 | work stoppage, computer failure or malfunction, or any and all 164 | other commercial damages or losses), even if such Contributor 165 | has been advised of the possibility of such damages. 166 | 167 | 9. Accepting Warranty or Additional Liability. While redistributing 168 | the Work or Derivative Works thereof, You may choose to offer, 169 | and charge a fee for, acceptance of support, warranty, indemnity, 170 | or other liability obligations and/or rights consistent with this 171 | License. However, in accepting such obligations, You may act only 172 | on Your own behalf and on Your sole responsibility, not on behalf 173 | of any other Contributor, and only if You agree to indemnify, 174 | defend, and hold each Contributor harmless for any liability 175 | incurred by, or claims asserted against, such Contributor by reason 176 | of your accepting any such warranty or additional liability. 177 | 178 | END OF TERMS AND CONDITIONS 179 | 180 | APPENDIX: How to apply the Apache License to your work. 181 | 182 | To apply the Apache License to your work, attach the following 183 | boilerplate notice, with the fields enclosed by brackets "[]" 184 | replaced with your own identifying information. (Don't include 185 | the brackets!) The text should be enclosed in the appropriate 186 | comment syntax for the file format. We also recommend that a 187 | file or class name and description of purpose be included on the 188 | same "printed page" as the copyright notice for easier 189 | identification within third-party archives. 190 | 191 | Copyright 2017 IBM and its contributors. 192 | 193 | Licensed under the Apache License, Version 2.0 (the "License"); 194 | you may not use this file except in compliance with the License. 195 | You may obtain a copy of the License at 196 | 197 | http://www.apache.org/licenses/LICENSE-2.0 198 | 199 | Unless required by applicable law or agreed to in writing, software 200 | distributed under the License is distributed on an "AS IS" BASIS, 201 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 202 | See the License for the specific language governing permissions and 203 | limitations under the License. 204 | -------------------------------------------------------------------------------- /qiskit_aqua_interfaces/user_interface/_mainview.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # This code is part of Qiskit. 4 | # 5 | # (C) Copyright IBM 2018, 2019. 6 | # 7 | # This code is licensed under the Apache License, Version 2.0. You may 8 | # obtain a copy of this license in the LICENSE.txt file in the root directory 9 | # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. 10 | # 11 | # Any modifications or derivative works of this code must retain this 12 | # copyright notice, and modified files need to carry a notice indicating 13 | # that they have been altered from the originals. 14 | 15 | """Root main view""" 16 | 17 | import sys 18 | import tkinter as tk 19 | import tkinter.messagebox as tkmb 20 | import tkinter.ttk as ttk 21 | import tkinter.filedialog as tkfd 22 | from tkinter import font 23 | import webbrowser 24 | import os 25 | from qiskit_aqua_interfaces import __version__, APP_DEPRECATION_MSG 26 | from ._sectionsview import SectionsView 27 | from ._sectiontextview import SectionTextView 28 | from ._threadsafeoutputview import ThreadSafeOutputView 29 | from ._emptyview import EmptyView 30 | from ._preferencesdialog import PreferencesDialog 31 | 32 | # pylint: disable=import-outside-toplevel 33 | 34 | 35 | class MainView(ttk.Frame): 36 | """ Main View """ 37 | def __init__(self, parent, guiprovider) -> None: 38 | """Create MainView object.""" 39 | super(MainView, self).__init__(parent) 40 | self._guiprovider = guiprovider 41 | self._guiprovider.controller.view = self 42 | self.pack(expand=tk.YES, fill=tk.BOTH) 43 | self._create_widgets() 44 | self.master.title(self._guiprovider.title) 45 | if parent is not None: 46 | parent.protocol('WM_DELETE_WINDOW', self.quit) 47 | 48 | def _show_about_dialog(self): 49 | import qiskit.aqua as qa 50 | lines = ['Qiskit Aqua Interfaces', 51 | 'Version: {}'.format(__version__), 52 | '', 53 | 'Qiskit Aqua', 54 | 'Version: {}'.format(qa.__version__), 55 | ] 56 | tkmb.showinfo(self._guiprovider.title, message='\n'.join(lines)) 57 | 58 | def _show_preferences(self): 59 | dialog = PreferencesDialog(self, self._guiprovider) 60 | dialog.do_init(tk.LEFT) 61 | dialog.do_modal() 62 | 63 | def _create_widgets(self): 64 | self._make_menubar() 65 | self._make_toolbar() 66 | self._create_pane() 67 | 68 | def _make_toolbar(self): 69 | toolbar = ttk.Frame(self, relief=tk.SUNKEN, borderwidth=2) 70 | toolbar.pack(side=tk.BOTTOM, fill=tk.X) 71 | self._guiprovider.controller._button_text = tk.StringVar() 72 | self._guiprovider.controller._button_text.set(self._guiprovider.controller._command) 73 | self._guiprovider.controller._start_button = \ 74 | ttk.Button(toolbar, 75 | textvariable=self._guiprovider.controller._button_text, 76 | state='disabled', 77 | command=self._guiprovider.controller.toggle) 78 | self._guiprovider.controller._start_button.pack(side=tk.LEFT) 79 | self._guiprovider.add_toolbar_items(toolbar) 80 | self._guiprovider.controller._progress = ttk.Progressbar(toolbar, orient=tk.HORIZONTAL) 81 | self._guiprovider.controller._progress.pack(side=tk.RIGHT, fill=tk.BOTH, expand=tk.TRUE) 82 | 83 | def _make_menubar(self): 84 | menubar = tk.Menu(self.master) 85 | if sys.platform == 'darwin': 86 | app_menu = tk.Menu(menubar, name='apple') 87 | menubar.add_cascade(menu=app_menu) 88 | app_menu.add_command(label='About {}'.format( 89 | self._guiprovider.title), command=self._show_about_dialog) 90 | self.master.createcommand('tk::mac::ShowPreferences', self._show_preferences) 91 | self.master.createcommand('tk::mac::Quit', self.quit) 92 | 93 | self.master.config(menu=menubar) 94 | self._guiprovider.controller._filemenu = self._make_filemenu(menubar) 95 | 96 | if sys.platform != 'darwin': 97 | tools_menu = tk.Menu(menubar, tearoff=False) 98 | tools_menu.add_command(label='Options', command=self._show_preferences) 99 | menubar.add_cascade(label='Tools', menu=tools_menu) 100 | 101 | help_menu = tk.Menu(menubar, tearoff=False) 102 | if sys.platform != 'darwin': 103 | help_menu.add_command(label='About {}'.format(self._guiprovider.title), 104 | command=self._show_about_dialog) 105 | 106 | help_menu.add_command(label='Open Help Center', command=self._open_help_center) 107 | menubar.add_cascade(label='Help', menu=help_menu) 108 | 109 | def _open_help_center(self): 110 | webbrowser.open(self._guiprovider.help_hyperlink) 111 | 112 | def _make_filemenu(self, menubar): 113 | file_menu = tk.Menu(menubar, tearoff=False, postcommand=self._recent_files_menu) 114 | file_menu.add_command(label='New', command=self._new_input) 115 | file_menu.add_command(label='Open...', command=self._open_file) 116 | file_menu.add_cascade(label='Open Recent', menu=tk.Menu(file_menu, tearoff=False)) 117 | file_menu.add_separator() 118 | file_menu.add_command(label='Save', command=self._save_file) 119 | file_menu.add_command(label='Save As...', command=self._save_file_as) 120 | 121 | self._guiprovider.add_file_menu_items(file_menu) 122 | 123 | if sys.platform != 'darwin': 124 | file_menu.add_separator() 125 | file_menu.add_command(label='Exit', command=self.quit) 126 | 127 | menubar.add_cascade(label='File', menu=file_menu) 128 | return file_menu 129 | 130 | def _recent_files_menu(self): 131 | recent_menu = tk.Menu(self._guiprovider.controller._filemenu, tearoff=False) 132 | preferences = self._guiprovider.create_uipreferences() 133 | for file in preferences.get_recent_files(): 134 | recent_menu.add_command(label=file, command=lambda f=file: self._open_recent_file(f)) 135 | 136 | recent_menu.add_separator() 137 | recent_menu.add_command(label='Clear', command=self._clear_recent) 138 | self._guiprovider.controller._filemenu.entryconfig(2, menu=recent_menu) 139 | 140 | def _new_input(self): 141 | self._guiprovider.controller.new_input() 142 | 143 | def _open_file(self): 144 | preferences = self._guiprovider.create_uipreferences() 145 | filename = tkfd.askopenfilename(parent=self, 146 | title='Open File', 147 | initialdir=preferences.get_openfile_initialdir()) 148 | if filename and self._guiprovider.controller.open_file(filename): 149 | preferences.add_recent_file(filename) 150 | preferences.set_openfile_initialdir(os.path.dirname(filename)) 151 | preferences.save() 152 | 153 | def _open_recent_file(self, filename): 154 | self._guiprovider.controller.open_file(filename) 155 | 156 | def _clear_recent(self): 157 | preferences = self._guiprovider.create_uipreferences() 158 | preferences.clear_recent_files() 159 | preferences.save() 160 | 161 | def _save_file(self): 162 | self._guiprovider.controller.save_file() 163 | 164 | def _save_file_as(self): 165 | if self._guiprovider.controller.is_empty(): 166 | self._guiprovider.controller.outputview.write_line("No data to save.") 167 | return 168 | 169 | preferences = self._guiprovider.create_uipreferences() 170 | filename = tkfd.asksaveasfilename(parent=self, 171 | title='Save File', 172 | initialdir=preferences.get_savefile_initialdir()) 173 | if filename and self._guiprovider.controller.save_file_as(filename): 174 | preferences.add_recent_file(filename) 175 | preferences.set_savefile_initialdir(os.path.dirname(filename)) 176 | preferences.save() 177 | 178 | def _create_pane(self): 179 | label_font = font.nametofont('TkHeadingFont').copy() 180 | label_font.configure(size=12, weight='bold') 181 | style = ttk.Style() 182 | style.configure('Title.TLabel', 183 | borderwidth=0, 184 | anchor=tk.CENTER) 185 | label = ttk.Label(self, 186 | style='Title.TLabel', 187 | padding=(5, 5, 5, 5), 188 | textvariable=self._guiprovider.controller._title) 189 | label['font'] = label_font 190 | label.pack(side=tk.TOP, expand=tk.NO, fill=tk.X) 191 | main_pane = ttk.PanedWindow(self, orient=tk.VERTICAL) 192 | main_pane.pack(expand=tk.YES, fill=tk.BOTH) 193 | top_pane = ttk.PanedWindow(main_pane, orient=tk.HORIZONTAL) 194 | top_pane.pack(expand=tk.YES, fill=tk.BOTH) 195 | main_pane.add(top_pane) 196 | 197 | self._guiprovider.controller._sections_view = \ 198 | SectionsView(self._guiprovider.controller, top_pane) 199 | self._guiprovider.controller._sections_view.pack(expand=tk.YES, fill=tk.BOTH) 200 | top_pane.add(self._guiprovider.controller._sections_view, weight=1) 201 | 202 | main_container = tk.Frame(top_pane) 203 | main_container.pack(expand=tk.YES, fill=tk.BOTH) 204 | style = ttk.Style() 205 | style.configure('PropViewTitle.TLabel', 206 | borderwidth=1, 207 | relief=tk.RIDGE, 208 | anchor=tk.CENTER) 209 | label = ttk.Label(main_container, 210 | style='PropViewTitle.TLabel', 211 | padding=(5, 5, 5, 5), 212 | textvariable=self._guiprovider.controller._sections_view_title) 213 | label['font'] = label_font 214 | 215 | label.pack(side=tk.TOP, expand=tk.NO, fill=tk.X) 216 | container = tk.Frame(main_container) 217 | container.pack(side=tk.BOTTOM, expand=tk.YES, fill=tk.BOTH) 218 | container.grid_rowconfigure(0, weight=1) 219 | container.grid_columnconfigure(0, weight=1) 220 | self._guiprovider.controller._empty_view = EmptyView(container) 221 | self._guiprovider.controller._empty_view.grid(row=0, column=0, sticky='nsew') 222 | 223 | self._guiprovider.controller._text_view = \ 224 | SectionTextView(self._guiprovider.controller, container) 225 | self._guiprovider.controller._text_view.grid(row=0, column=0, sticky='nsew') 226 | 227 | self._guiprovider.controller._properties_view = \ 228 | self._guiprovider.create_section_properties_view(container) 229 | self._guiprovider.controller._properties_view.grid(row=0, column=0, sticky='nsew') 230 | self._guiprovider.controller._empty_view.tkraise() 231 | top_pane.add(main_container, weight=1) 232 | 233 | self._guiprovider.controller.outputview = ThreadSafeOutputView(main_pane) 234 | self._guiprovider.controller.outputview.pack(expand=tk.YES, fill=tk.BOTH) 235 | main_pane.add(self._guiprovider.controller.outputview) 236 | 237 | # redirect output 238 | sys.stdout = self._guiprovider.controller.outputview 239 | sys.stderr = self._guiprovider.controller.outputview 240 | # update logging after redirect 241 | self.after(0, self._set_preferences_logging) 242 | 243 | self.update_idletasks() 244 | self._guiprovider.controller._sections_view.show_add_button(False) 245 | self._guiprovider.controller._sections_view.show_remove_button(False) 246 | self._guiprovider.controller._sections_view.show_defaults_button(False) 247 | self._guiprovider.controller._empty_view.set_toolbar_size( 248 | self._guiprovider.controller._sections_view.get_toolbar_size()) 249 | 250 | self._guiprovider.controller.outputview.write_line(APP_DEPRECATION_MSG) 251 | 252 | def _set_preferences_logging(self): 253 | preferences = self._guiprovider.create_uipreferences() 254 | config = preferences.get_logging_config() 255 | if config is not None: 256 | self._guiprovider.set_logging_config(config) 257 | 258 | def quit(self): 259 | if tkmb.askyesno('Verify quit', 'Are you sure you want to quit?'): 260 | preferences = self._guiprovider.create_uipreferences() 261 | preferences.set_geometry(self.master.winfo_geometry()) 262 | preferences.save() 263 | self._guiprovider.controller.stop() 264 | ttk.Frame.quit(self) 265 | return True 266 | 267 | return False 268 | --------------------------------------------------------------------------------