diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 0a3111d33..1c3df23af 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -2,9 +2,9 @@ name: Tests
on:
# Run this workflow every time a new commit is pushed to or a pull request is created from one of these branches
push:
- branches: [main, "stable/*"]
+ branches: [main, 'stable/*']
pull_request:
- branches: [main, "stable/*"]
+ branches: [main, 'stable/*']
jobs:
# NOTE: The ubuntu-22.04 and macos-latest tests have been separated out because ubuntu
# requires installing some additional libraries (libglu1-mesa) for Gmsh to run. Please
@@ -17,7 +17,7 @@ jobs:
# Set matrix for runs-on
strategy:
matrix:
- python-version: ["3.9", "3.10"]
+ python-version: ['3.9', '3.10']
steps:
- name: Checkout code
uses: actions/checkout@v3
@@ -36,8 +36,9 @@ jobs:
ubuntu-latest-${{ matrix.python-version }}
- name: Install Deps
run: |
- python -m pip install -U tox==4.11.0 setuptools==67.3.1 virtualenv==20.24.3 wheel==0.38.4
- sudo apt install libglu1-mesa=9.0.2-1 libglu1-mesa-dev=9.0.2-1
+ python -m pip install -U tox setuptools virtualenv wheel
+ sudo apt update
+ sudo apt install libglu1-mesa libglu1-mesa-dev libegl1-mesa
- name: Install and Run Tests
run: tox -e py
macos-tests:
@@ -48,7 +49,7 @@ jobs:
# Set matrix for runs-on
strategy:
matrix:
- python-version: ["3.9", "3.10"]
+ python-version: ['3.9', '3.10']
steps:
- name: Chekout code
uses: actions/checkout@v3
@@ -74,7 +75,7 @@ jobs:
runs-on: windows-2022
strategy:
matrix:
- python-version: ["3.9", "3.10"]
+ python-version: ['3.9', '3.10']
steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
@@ -146,7 +147,7 @@ jobs:
sudo apt install -y graphviz=2.42.2-6 pandoc=2.9.2.1-3ubuntu2 qtbase5-dev=5.15.3+dfsg-2ubuntu0.2 qt5-qmake=5.15.3+dfsg-2ubuntu0.2
- name: Build Docs
run: tox -edocs
- - uses: actions/upload-artifact@v2
+ - uses: actions/upload-artifact@v3
with:
name: html_docs
path: docs/_build/html
diff --git a/.gitignore b/.gitignore
index ebd21023e..b89021976 100644
--- a/.gitignore
+++ b/.gitignore
@@ -57,6 +57,7 @@ instance/
# User Folders:
.scrapy
_sandbox_/
+_debug/
qiskit_metal/qlibrary/user_components/*
!qiskit_metal/qlibrary/user_components/__init__.py
!qiskit_metal/qlibrary/user_components/my_qcomponent.py
@@ -92,6 +93,7 @@ celerybeat-schedule
# virtualenv
.venv
venv/
+venvz/
ENV/
# Spyder project settings
diff --git a/.pylintrc b/.pylintrc
index 395adc8bf..fc036d79e 100644
--- a/.pylintrc
+++ b/.pylintrc
@@ -6,7 +6,7 @@
# A comma-separated list of package or module names from where C extensions may
# be loaded. Extensions are loading into the active Python interpreter and may
# run arbitrary code.
-extension-pkg-whitelist=PySide2
+extension-pkg-whitelist=PySide6,gdstk
# Add files or directories to the blacklist. They should be base names, not
# paths.
@@ -91,7 +91,7 @@ disable=apply-builtin,
dict-values-not-iterating,
dict-view-method,
div-method,
- eq-without-hash,
+; eq-without-hash,
exception-escape,
exception-message-attribute,
execfile-builtin,
@@ -108,21 +108,21 @@ disable=apply-builtin,
intern-builtin,
invalid-str-codec,
locally-disabled,
- logging-fstring-interpolation # fstrings inside logging
+ logging-fstring-interpolation, # fstrings inside logging
long-builtin,
- long-suffix,
+; long-suffix,
map-builtin-not-iterating,
metaclass-assignment,
missing-module-docstring,
next-method-called,
next-method-defined,
no-absolute-import,
- non-ascii-bytes-literal,
+; non-ascii-bytes-literal,
nonzero-method,
oct-method,
old-division,
- old-ne-operator,
- old-octal-literal,
+; old-ne-operator,
+; old-octal-literal,
old-raise-syntax,
parameter-unpacking,
print-statement,
@@ -339,8 +339,8 @@ max-module-lines=1000
# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.
# `trailing-comma` allows a space between comma and closing bracket: (a, ).
# `empty-line` allows space-only lines.
-no-space-check=trailing-comma,
- dict-separator
+; no-space-check=trailing-comma,
+; dict-separator
# Allow the body of a class to be on the same line as the declaration if body
# contains single statement.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 6b9aaf03c..b075bd494 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -43,15 +43,16 @@ https://google.github.io/styleguide/pyguide.html) for auto formatting. The custo
#### VSCode Setup
+Steps:
+1. Install the following extensions: `python` and `yapf` if you have not yet.
+2. Add the following workspace setting in the workspace `settings.json`.
+
If you are using VSCode for your code editor, you can add these settings
to your `settings.json` to enforce your code to our style. Make sure to add PySide2 to the linter:
-```
+```json
{
"python.linting.pylintEnabled": true,
"python.linting.enabled": true,
- "python.linting.pylintArgs": [
- "--extension-pkg-whitelist=PySide2"
- ],
"python.formatting.provider": "yapf",
"editor.formatOnSave": true,
"files.trimTrailingWhitespace": true,
@@ -59,6 +60,21 @@ to your `settings.json` to enforce your code to our style. Make sure to add PySi
}
```
+
+In newer versions of VS Code:
+```json
+{
+ "editor.formatOnSave": true,
+ "files.trimTrailingWhitespace": true,
+ "files.trimFinalNewlines": true,
+ "editor.defaultFormatter": "eeyore.yapf",
+ "notebook.defaultFormatter": "eeyore.yapf",
+ "[python]": {
+ "editor.defaultFormatter": "eeyore.yapf"
+ }
+}
+```
+
### Code Review
Code review is done in the open and open to anyone. While only maintainers have access to merge commits, providing feedback on pull requests is very valuable and helpful. It is also a good mechanism to learn about the code base. You can view a list of all open pull requests to review any open pull requests and provide feedback on it.
diff --git a/README.md b/README.md
index 96bcff0a3..98425c480 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@
We're excited to share that we're nearing the completion of porting Qiskit Metal from PySide2 to PySide6! This update enables native support for M* Macs (Apple Silicon) and includes several other enhancements for the upcoming release. Please take a moment to review and provide feedback on [Pull Request #1002](https://github.com/qiskit-community/qiskit-metal/pull/1002) before we proceed with merging and tagging. Your input is invaluable to ensure the release meets everyone's expectations. Thank you for your continued contributions!
## Installation
-If you are interested in customizing your experience, or if you are unable to install qiskit-metal using the `pip install` instructions below, consider installing directly the source code, following the instructions in the [documentation](https://qiskit-community.github.io/qiskit-metal/installation.html) and/or the [installation instructions for developers](https://github.com/Qiskit/qiskit-metal/blob/main/README_developers.md).
+If you are interested in customizing your experience, or if you are unable to install qiskit-metal using the `pip install` instructions below, consider installing directly the source code, following the instructions in the [documentation](https://qiskit-community.github.io/qiskit-metal/installation.html) and/or the [installation instructions for developers](https://github.com/Qiskit/qiskit-metal/blob/main/README_Developers.md).
For normal use, please continue reading.
@@ -106,11 +106,153 @@ We use [GitHub issues](https://github.com/Qiskit/qiskit-metal/issues) for tracki
[join the Qiskit Slack community](https://qisk.it/join-slack)
and use our [Qiskit Slack channel](https://qiskit.slack.com) for discussion and simple questions.
For questions that are more suited for a forum we use the Qiskit tag in the [Stack Exchange](https://quantumcomputing.stackexchange.com/questions/tagged/qiskit).
+
## Next Steps
Now you're set up and ready to check out some of the other examples from our
[Qiskit Metal Tutorials](https://github.com/Qiskit/qiskit-metal/blob/main/tutorials/) repository or [Qiskit Metal Documentation](https://qiskit-community.github.io/qiskit-metal/tut/).
+
+
+---
+
+# Big Picture Architecutre Overview
+
+### Diagram
+
+The **Qiskit Metal** codebase is organized into several key modules, each with a distinct role in enabling the design, analysis, and visualization of quantum circuits. Below is an overview of the primary components and their interactions, discussed deeper in the [Architecture Readme](README_Architecture.md) and the docs:
+
+```mermaid
+ %%{init: {"flowchart": {"htmlLabels": true}, 'theme':'forest'} }%%
+ graph TB
+ classDef core fill:#87cefa,stroke:#000000;
+ classDef gui fill:#FFDDC1,stroke:#000000;
+ classDef renderer fill:#DBB9FF,stroke:#000000;
+ classDef utility fill:#FFD700,stroke:#000000;
+ classDef design fill:#90EE90,stroke:#000000;
+ classDef analysis fill:#FFB6C1,stroke:#000000;
+
+ subgraph Qiskit_Metal
+ subgraph Core
+ QLibraryComponents["QLibrary Components"]
+ QDesign["QDesign"]
+ QComponent["QComponent"]
+ QRoute["QRoute"]
+ BaseQubit["BaseQubit"]
+ end
+
+ subgraph GUI
+ MetalGUI["MetalGUI"]
+ end
+
+ subgraph Renderers
+ QRenderer["QRenderer"]
+ QRendererGui["QRendererGui"]
+ QGDSRenderer["QGDSRenderer"]
+ QAnsysRenderer["QAnsysRenderer"]
+ QHFSSRenderer["QHFSSRenderer"]
+ QQ3DRenderer["QQ3DRenderer"]
+ QPyaedt["QPyaedt"]
+ QGmshRenderer["QGmshRenderer"]
+ QElmerRenderer["QElmerRenderer"]
+ end
+
+ subgraph Analyses
+ Hamiltonian["Hamiltonian"]
+ Sweep_Options["Sweep_Options"]
+ end
+
+ subgraph Utilities
+ Parsing["Parsing"]
+ Exceptions["Exceptions"]
+ Logging["Logging"]
+ Toolbox["Toolbox"]
+ end
+ end
+
+ QLibraryComponents --> QDesign
+ QRenderer --> QDesign
+ QRendererGui --> QRenderer
+ MetalGUI --> QRendererGui
+ MetalGUI --> QLibraryComponents
+ MetalGUI --> QDesign
+ QGDSRenderer --> QRenderer
+ QAnsysRenderer --> QRenderer
+ QHFSSRenderer --> QRenderer
+ QQ3DRenderer --> QRenderer
+ QPyaedt --> QRenderer
+ QGmshRenderer --> QRenderer
+ QElmerRenderer --> QRenderer
+ Parsing --> QDesign
+ Exceptions --> QDesign
+ Logging --> QDesign
+ Toolbox --> QDesign
+ QDesign --> QComponent
+ QDesign --> QRoute
+ QDesign --> BaseQubit
+ Hamiltonian --> QDesign
+ Sweep_Options --> QDesign
+
+ class QLibraryComponents,QDesign,QComponent,QRoute,BaseQubit core;
+ class MetalGUI gui;
+ class QRenderer,QRendererGui,QGDSRenderer,QAnsysRenderer,QHFSSRenderer,QQ3DRenderer,QPyaedt,QGmshRenderer,QElmerRenderer renderer;
+ class Parsing,Exceptions,Logging,Toolbox utility;
+ class Hamiltonian,Sweep_Options analysis;
+```
+
+
+### Core
+The **Core** module serves as the backbone of Qiskit Metal, housing essential elements for design and component creation:
+- **QLibrary Components**: Predefined library of quantum circuit elements, such as qubits and resonators, that can be used in designs.
+- **QDesign**: The central design framework that integrates all components and handles design rules.
+- **QComponent**: Base class for all components in the design.
+- **QRoute**: Specialized class for managing connections between components.
+- **BaseQubit**: Represents foundational qubit structures used in circuit designs.
+
+### Renderers
+The **Renderers** module facilitates exporting designs to external tools for electromagnetic simulation and layout rendering:
+- **QRenderer**: Base class for all renderers.
+- **QRendererGui**: GUI interface for managing renderers.
+- Specialized renderers like:
+ - **QGDSRenderer**
+ - **QAnsysRenderer**
+ - **QHFSSRenderer**
+ - **QQ3DRenderer**
+ - **QPyaedt**
+ - **QGmshRenderer**
+ - **QElmerRenderer**
+
+These renderers enable integration with industry-standard tools for detailed simulation and fabrication.
+
+### Analyses
+The **Analyses** module includes tools for performing simulations and extracting insights from designs:
+- **Hamiltonian**: Supports calculations of Hamiltonian parameters.
+- **Sweep Options**: Provides tools for parametric sweeps and optimizations.
+
+
+### GUI
+The **GUI** module provides tools for user-friendly interaction with Qiskit Metal. The **MetalGUI** clas is the primary graphical interface for managing designs and visualizations. It is discussed in more depth in the [Architecture Readme](README_Architecture.md).
+
+### Utilities
+The **Utilities** module supports the overall functionality of Qiskit Metal by offering supplementary tools.
+
+
+
+### Key Interactions
+- The **Core** modules form the foundation and integrate tightly with the **Renderers**, **GUI**, and **Analyses** modules.
+- The **GUI** depends on the **Core** and **Renderers** to provide visualization and interactivity.
+- The **Renderers** serve as bridges between Qiskit Metal and external tools, interacting with the **Core** to export designs.
+- The **Analyses** modules leverage the **Core** to extract meaningful data for optimization and validation.
+- The **Utilities** modules provide essential supporting functionalities across the entire codebase.
+
+This modular structure ensures scalability, flexibility, and ease of use for designing, analyzing, and fabricating quantum circuits.
+
+
+---
+
+# Backmatter
+
## Authors and Citation
Qiskit Metal is the work of [many people](https://github.com/Qiskit/qiskit-metal/pulse/monthly) who contribute to the project at different levels. Metal was conceived and developed by [Zlatko Minev](https://www.zlatko-minev.com) at IBM; then co-led with Thomas McConkey. If you use Qiskit Metal, please cite as per the included [BibTeX file](https://github.com/Qiskit/qiskit-metal/blob/main/Qiskit_Metal.bib). For icon attributions, see [here](https://github.com/Qiskit/qiskit-metal/blob/main/qiskit_metal/_gui/_imgs/icon_attributions.txt).
+
## Changelog and Release Notes
The changelog provides a quick overview of notable changes for a given release.
@@ -122,3 +264,5 @@ Additionally, as part of each release detailed release notes are written to docu
## License
[Apache License 2.0](https://github.com/Qiskit/qiskit-metal/blob/main/LICENSE.txt)
+
+
diff --git a/README_ARCH.md b/README_ARCH.md
deleted file mode 100644
index fa66077ca..000000000
--- a/README_ARCH.md
+++ /dev/null
@@ -1,57 +0,0 @@
-# Qiskit Metal Architecture
-The high level Metal architecture is diagramed in the overview below. The user workflow is diagramed in the workflow link below as well.
-
-* [Overview](/docs/overview.rst)
-* [Workflow](/docs/workflow.rst)
-
-## Required Attributes
-
-### QLibrary Components
-A base qlibrary component contains several attributes and a method that must be overridden by qlibrary components that extend the base.
-
-**Attributes**
-| Attribute | Description |
-| ------------------ | ------------------------------------------------------ |
-| default_options | Default drawing options |
-| component_metadata | Component metadata |
-| options | A dictionary of the component-designer-defined options |
-
-**Methods**
-| Method | Description |
-| ------ | ----------- |
-| make | The make function implements the logic that creates the geometry (poly, path, etc.) from the qcomponent.options dictionary of parameters, and the adds them to the design, using qcomponent.add_qgeometry(...), adding in extra needed information, such as layer, subtract, etc. |
-
-### QRenderer
-A base qrenderer contains several attributes and several methods that must be overridden by qrenderers that extend the base.
-
-**Attributes**
-| Attribute | Description |
-| ------------------ | ----------------------------- |
-| name | Renderer name |
-| element_extensions | Element extensions dictionary |
-| element_table_data | Element table data |
-
-**Methods**
-| Method | Description |
-| ------------------- | --------------------------------------------------------------------------------------- |
-| render_chips | Render all chips of the design. Calls render_chip for each chip. |
-| render_chip | Render the given chip. |
-| render_components | Render all components of the design. If selection is none, then render all components. |
-| render_component | Render the specified component. |
-| render_element | Render the specified element. |
-| render_element_path | Render an element path. |
-| render_element_poly | Render an element poly. |
-
-### QRendererGui
-In addition to the attributes and methods that must be overwritten by any QRenderer, a base qrenderergui has additional methods that must be overwritten by all qrendererguis that extend the base.
-
-| Method | Description |
-| ----------------- | --------------------------- |
-| setup_fig | Setup the given figure. |
-| style_axis | Style the axis. |
-| render_design | Render the design. |
-| render_component | Render the given component. |
-| render_shapely | Render shapely. |
-| render_connectors | Render connectors. |
-| clear_axis | Clear the axis. |
-| clear_figure | Clear the figure. |
diff --git a/README_Architecture.md b/README_Architecture.md
new file mode 100644
index 000000000..7c4ae9e03
--- /dev/null
+++ b/README_Architecture.md
@@ -0,0 +1,213 @@
+# Qiskit Metal Architecture
+The high level Metal architecture is diagramed in the overview below. The user workflow is diagramed in the workflow link below as well.
+
+* [Overview](/docs/overview.rst)
+* [Workflow](/docs/workflow.rst)
+
+
+## Big Picture Architecutre Overview
+
+### Diagram
+
+```mermaid
+ %%{init: {"flowchart": {"htmlLabels": true}, 'theme':'forest'} }%%
+ graph TB
+ classDef core fill:#87cefa,stroke:#000000;
+ classDef gui fill:#FFDDC1,stroke:#000000;
+ classDef renderer fill:#DBB9FF,stroke:#000000;
+ classDef utility fill:#FFD700,stroke:#000000;
+ classDef design fill:#90EE90,stroke:#000000;
+ classDef analysis fill:#FFB6C1,stroke:#000000;
+
+ subgraph Qiskit_Metal
+ subgraph Core
+ QLibraryComponents["QLibrary Components"]
+ QDesign["QDesign"]
+ QComponent["QComponent"]
+ QRoute["QRoute"]
+ BaseQubit["BaseQubit"]
+ end
+
+ subgraph GUI
+ MetalGUI["MetalGUI"]
+ ElementsWindow["ElementsWindow"]
+ NetListWindow["NetListWindow"]
+ ComponentWidget["ComponentWidget"]
+ QTableView_AllComponents["QTableView_AllComponents"]
+ QTreeView_Options["QTreeView_Options"]
+ QTextEditLogger["QTextEditLogger"]
+ end
+
+ subgraph Renderers
+ QRenderer["QRenderer"]
+ QRendererGui["QRendererGui"]
+ QGDSRenderer["QGDSRenderer"]
+ QAnsysRenderer["QAnsysRenderer"]
+ QHFSSRenderer["QHFSSRenderer"]
+ QQ3DRenderer["QQ3DRenderer"]
+ QPyaedt["QPyaedt"]
+ QGmshRenderer["QGmshRenderer"]
+ QElmerRenderer["QElmerRenderer"]
+ end
+
+ subgraph Analyses
+ Hamiltonian["Hamiltonian"]
+ Sweep_Options["Sweep_Options"]
+ end
+
+ subgraph Utilities
+ Parsing["Parsing"]
+ Exceptions["Exceptions"]
+ Logging["Logging"]
+ Toolbox["Toolbox"]
+ end
+ end
+
+ QLibraryComponents --> QDesign
+ QRenderer --> QDesign
+ QRendererGui --> QRenderer
+ MetalGUI --> QRendererGui
+ MetalGUI --> QLibraryComponents
+ MetalGUI --> QDesign
+ MetalGUI --> ElementsWindow
+ MetalGUI --> NetListWindow
+ MetalGUI --> ComponentWidget
+ MetalGUI --> QTableView_AllComponents
+ MetalGUI --> QTreeView_Options
+ MetalGUI --> QTextEditLogger
+ QGDSRenderer --> QRenderer
+ QAnsysRenderer --> QRenderer
+ QHFSSRenderer --> QRenderer
+ QQ3DRenderer --> QRenderer
+ QPyaedt --> QRenderer
+ QGmshRenderer --> QRenderer
+ QElmerRenderer --> QRenderer
+ Parsing --> QDesign
+ Exceptions --> QDesign
+ Logging --> QDesign
+ Toolbox --> QDesign
+ QDesign --> QComponent
+ QDesign --> QRoute
+ QDesign --> BaseQubit
+ Hamiltonian --> QDesign
+ Sweep_Options --> QDesign
+
+ class QLibraryComponents,QDesign,QComponent,QRoute,BaseQubit core;
+ class MetalGUI,ElementsWindow,NetListWindow,ComponentWidget,QTableView_AllComponents,QTreeView_Options,QTextEditLogger gui;
+ class QRenderer,QRendererGui,QGDSRenderer,QAnsysRenderer,QHFSSRenderer,QQ3DRenderer,QPyaedt,QGmshRenderer,QElmerRenderer renderer;
+ class Parsing,Exceptions,Logging,Toolbox utility;
+ class Hamiltonian,Sweep_Options analysis;
+```
+
+
+
+The **Qiskit Metal** codebase is organized into several key modules, each with a distinct role in enabling the design, analysis, and visualization of quantum circuits. Below is an overview of the primary components and their interactions:
+
+### Core
+The **Core** module serves as the backbone of Qiskit Metal, housing essential elements for design and component creation:
+- **QLibrary Components**: Predefined library of quantum circuit elements, such as qubits and resonators, that can be used in designs.
+- **QDesign**: The central design framework that integrates all components and handles design rules.
+- **QComponent**: Base class for all components in the design.
+- **QRoute**: Specialized class for managing connections between components.
+- **BaseQubit**: Represents foundational qubit structures used in circuit designs.
+
+### GUI
+The **GUI** module provides tools for user-friendly interaction with Qiskit Metal:
+- **MetalGUI**: The primary graphical interface for managing designs and visualizations.
+- **ElementsWindow**: Displays available circuit elements.
+- **NetListWindow**: Shows the connections between components.
+- **ComponentWidget**: Offers detailed views and controls for individual components.
+- **QTableView_AllComponents**: Lists all components in the design.
+- **QTreeView_Options**: Presents configuration options in a tree structure.
+- **QTextEditLogger**: Logs activities and messages for troubleshooting and feedback.
+
+### Renderers
+The **Renderers** module facilitates exporting designs to external tools for electromagnetic simulation and layout rendering:
+- **QRenderer**: Base class for all renderers.
+- **QRendererGui**: GUI interface for managing renderers.
+- Specialized renderers like:
+ - **QGDSRenderer**
+ - **QAnsysRenderer**
+ - **QHFSSRenderer**
+ - **QQ3DRenderer**
+ - **QPyaedt**
+ - **QGmshRenderer**
+ - **QElmerRenderer**
+
+These renderers enable integration with industry-standard tools for detailed simulation and fabrication.
+
+### Analyses
+The **Analyses** module includes tools for performing simulations and extracting insights from designs:
+- **Hamiltonian**: Supports calculations of Hamiltonian parameters.
+- **Sweep Options**: Provides tools for parametric sweeps and optimizations.
+
+### Utilities
+The **Utilities** module supports the overall functionality of Qiskit Metal by offering supplementary tools:
+- **Parsing**: Manages data parsing for design input and output.
+- **Exceptions**: Handles error reporting and debugging.
+- **Logging**: Tracks system activities and events.
+- **Toolbox**: Provides miscellaneous helper functions.
+
+---
+
+### Key Interactions
+- The **Core** modules form the foundation and integrate tightly with the **Renderers**, **GUI**, and **Analyses** modules.
+- The **GUI** depends on the **Core** and **Renderers** to provide visualization and interactivity.
+- The **Renderers** serve as bridges between Qiskit Metal and external tools, interacting with the **Core** to export designs.
+- The **Analyses** modules leverage the **Core** to extract meaningful data for optimization and validation.
+- The **Utilities** modules provide essential supporting functionalities across the entire codebase.
+
+This modular structure ensures scalability, flexibility, and ease of use for designing, analyzing, and fabricating quantum circuits.
+
+
+## Required Attributes for Custom Components
+
+### QLibrary Components
+A base qlibrary component contains several attributes and a method that must be overridden by qlibrary components that extend the base.
+
+**Attributes**
+| Attribute | Description |
+| ------------------ | ------------------------------------------------------ |
+| default_options | Default drawing options |
+| component_metadata | Component metadata |
+| options | A dictionary of the component-designer-defined options |
+
+**Methods**
+| Method | Description |
+| ------ | ----------- |
+| make | The make function implements the logic that creates the geometry (poly, path, etc.) from the qcomponent.options dictionary of parameters, and the adds them to the design, using qcomponent.add_qgeometry(...), adding in extra needed information, such as layer, subtract, etc. |
+
+### QRenderer
+A base qrenderer contains several attributes and several methods that must be overridden by qrenderers that extend the base.
+
+**Attributes**
+| Attribute | Description |
+| ------------------ | ----------------------------- |
+| name | Renderer name |
+| element_extensions | Element extensions dictionary |
+| element_table_data | Element table data |
+
+**Methods**
+| Method | Description |
+| ------------------- | --------------------------------------------------------------------------------------- |
+| render_chips | Render all chips of the design. Calls render_chip for each chip. |
+| render_chip | Render the given chip. |
+| render_components | Render all components of the design. If selection is none, then render all components. |
+| render_component | Render the specified component. |
+| render_element | Render the specified element. |
+| render_element_path | Render an element path. |
+| render_element_poly | Render an element poly. |
+
+### QRendererGui
+In addition to the attributes and methods that must be overwritten by any QRenderer, a base qrenderergui has additional methods that must be overwritten by all qrendererguis that extend the base.
+
+| Method | Description |
+| ----------------- | --------------------------- |
+| setup_fig | Setup the given figure. |
+| style_axis | Style the axis. |
+| render_design | Render the design. |
+| render_component | Render the given component. |
+| render_shapely | Render shapely. |
+| render_connectors | Render connectors. |
+| clear_axis | Clear the axis. |
+| clear_figure | Clear the figure. |
diff --git a/README_Tutorials.md b/README_Tutorials.md
index b32a45554..683a89cef 100644
--- a/README_Tutorials.md
+++ b/README_Tutorials.md
@@ -1,42 +1,42 @@
-# Tutorials - Access and Schedule
+# 📚 Tutorials - Access and Schedule
-Through June 2021 we are offering live tutorials and Q&A.
+Recordings of live tutorials and Q&A sessions with researchers, developers, and the community.
-[Sign up](https://airtable.com/shrxQEgKqZCf319F3) to receive updates and the invite to the upcoming sessions.
+[VIDEOS: YouTube Playlist of tutorial recordings - click here](https://www.youtube.com/playlist?list=PLOFEBzvs-VvqHl5ZqVmhB_FcSqmLufsjb).
-The streaming will also be recorded and made available [here](https://www.youtube.com/playlist?list=PLOFEBzvs-VvqHl5ZqVmhB_FcSqmLufsjb) for offline review.
+Join the [Qiskit](https://qisk.it/join-slack) `#metal` Slack channel to request topics of interest, give feedback, and participate in all Qiskit Metal discussions.
-Join the [Qiskit](https://qisk.it/join-slack) `#metal` slack channel to request topics of interest, to give us feedback and to participate to all qiskit metal discussions.
+## 🗓️ Recording Log
-## Current Schedule
-| Date | Type | Topic |
-| -------------------- | -------------------- | ------------------------------------ |
-| April 1 | Tutorial | [Introduction to Qiskit Metal.](https://youtu.be/NCNv3YPvveM) |
-| April 8 | Tutorial | Overview: Qubit chip design-flow. [Part 1](https://youtu.be/bsrsKZLTkTo) |
-| April 15 | Tutorial | Overview: Qubit chip design-flow. [Part 2](https://youtu.be/fj1hpAqZfmg) |
-| April 22 | Forum | First impressions - The Qiskit Metal team will take questions regarding what you learned, experienced and achieved so far. You can also share. | |
-| April 29 | Tutorial | [QComponents](https://youtu.be/ljzWF3dNHEU): How to use, modify and extend the qiskit-metal library. |
-| May 6 | Forum | Q&A - The Qiskit Metal team will take questions regarding customizing qiskit-metal design. You can also share your component work and ideas with us. | |
-| May 6 | Offline Recordings | Tutorials on analysis methods:
- [Method 1: Capacitance and frequency control](https://youtu.be/rY7Os7B9sg0)
- [Method 2: Eigenmode and Energy Participation Ratio](https://youtu.be/mvT9Fb7UGH4)
- [Theory: Energy Participation Ratio](https://youtu.be/ITCkKfjxcbc)
- [Summary EPR Quantization with Code Example](https://youtu.be/FXmPyYEyL9U)
- [Finish Eigenmode + Method 3: Impedance Analysis](https://youtu.be/4jBVdHzmJdw)
- [Continue Impedance Analysis: Example](https://youtu.be/Bi8ZVAq-0tw)
| |
-| May 13 | Tutorial | [Quantum Analysis 101](https://youtu.be/QIr2Rlj1cpI) |
-| May 20 | Tutorial | [Introduction to the transmon qubit](https://youtu.be/6KgOaU1BAxg) |
-| May 27 | Tutorial | [Physics of the Cooper Pair Box Transmon](https://youtu.be/Ql8AS4Iay-Q) |
-| June 3 | Tutorial | - [Parametric Sweeps](https://youtu.be/ZRsk5dvH1K0)
- [Github contribution how-to](https://youtu.be/rJWo1Pt19vI)
|
-| June 10 → July 8 | >Break< | No tutorials |
-| July 15 | Tutorial | - [Energy Participation Ratio in Qiskit Metal](https://youtu.be/HJNKG5z6Jys)
- [New Feature sneak peek - LOM analysis for composite systems](https://youtu.be/XpnTJSBjb8E)
- [New Feature - Export design to script](https://youtu.be/JpoD3SjObHc)
|
-| July 22 → Sept 16 | >Break< | No tutorials |
-| Sept 23 | Tutorial | [Making a QComponent from scratch](https://youtu.be/5iEOJDMWXDE) |
-| Oct 7 | Tutorial | [New LOM Analysis Methodology - Part 1](https://youtu.be/S8Wx2Lo2CxQ) |
-| Oct 21 | Tutorial | [New LOM Analysis Methodology - Part 2](https://youtu.be/b2azGJ-RCjk) |
-| Nov 4 | Tutorial | [New LOM Analysis Methodology - Part 3](https://youtu.be/kWFYYUa0V3k) |
-| Nov 18 | Forum | Q&A - The Qiskit Metal team will take any question |
-| Jan 13, 2022 | Forum | Q&A - The Qiskit Metal team will take any question |
-| Jan 27, 2022 | Forum | Helping users generate a custom component.
-| Feb 10, 2022 | Tutorial | - [GUI icons](https://youtu.be/aE2Dsc67S8w)
- [Jaynes Cummings model](https://youtu.be/dtwL_K-TJtY)
- [template_options, options, default_options](https://youtu.be/qKLyEyW7cbQ)|
-| Feb 24, 2022 | Tutorial | [Flip chip by guest speaker, Sandoko Kosen.](https://youtu.be/BUojR6Uti5Q)|
-| Mar 10, 2022 | Forum| Metal community provide feedback.|
-| Mar 24, 2022 | Tutorial | [Time Evolution for the CR gate](https://www.youtube.com/watch?v=icDryjZrUQ4)|
-| Aug 4, 2022 | Tutorial | [Open-Source Rendering and Simulation Solution for Qiskit Metal](https://youtu.be/sA0uXtCAhWw)|
-| Aug 11, 2022 | Tutorial | [Qiskit Metal E21. Quantum Spice Web App - Sneak Peak](https://youtu.be/3UE57DaG-HI)|
-| Feb 2, 2023 | Tutorial | [Qiskit Metal E22. Open-Source Simulation Renderers for Metal — Gmsh and ElmerFEM](https://youtu.be/84j3l_9fHko)|
-| 2022 → ... | TBD | Topics to potentially schedule:
- Analysis deep dives (as needed)
- What happens frequently when analyzing a chip.
- Metal use cases: Common problems with pins, ports, fillet matches meander distance
- GDS fabrication option, use cases
- QRenderers: How to use, modify and add new renderers
- New QAnalysis/QRenderer structure and usage
- ...
|
+
+| 📅 Date | 📌 Type | 📝 Topic |
+| ------------------ | ----------- | ------- |
+| **April 1** | Tutorial | [Introduction to Qiskit Metal](https://youtu.be/NCNv3YPvveM) |
+| **April 8** | Tutorial | Overview: Qubit chip design-flow. [Part 1](https://youtu.be/bsrsKZLTkTo) |
+| **April 15** | Tutorial | Overview: Qubit chip design-flow. [Part 2](https://youtu.be/fj1hpAqZfmg) |
+| **April 22** | Forum | First impressions - Qiskit Metal team answers questions and invites feedback. |
+| **April 29** | Tutorial | [QComponents](https://youtu.be/ljzWF3dNHEU): How to use, modify, and extend the Qiskit Metal library. |
+| **May 6** | Forum | Q&A - Customizing Qiskit Metal designs. Share your components and ideas with us. |
+| **May 6** | Offline Recordings | Tutorials on analysis methods: - [Capacitance and frequency control](https://youtu.be/rY7Os7B9sg0)
- [Eigenmode & Energy Participation Ratio](https://youtu.be/mvT9Fb7UGH4)
- [Energy Participation Ratio Theory](https://youtu.be/ITCkKfjxcbc)
- [EPR Quantization with Code Example](https://youtu.be/FXmPyYEyL9U)
- [Finish Eigenmode + Impedance Analysis](https://youtu.be/4jBVdHzmJdw)
- [Impedance Analysis Example](https://youtu.be/Bi8ZVAq-0tw)
|
+| **May 13** | Tutorial | [Quantum Analysis 101](https://youtu.be/QIr2Rlj1cpI) |
+| **May 20** | Tutorial | [Introduction to the Transmon Qubit](https://youtu.be/6KgOaU1BAxg) |
+| **May 27** | Tutorial | [Physics of the Cooper Pair Box Transmon](https://youtu.be/Ql8AS4Iay-Q) |
+| **June 3** | Tutorial | - [Parametric Sweeps](https://youtu.be/ZRsk5dvH1K0)
- [Github Contribution How-to](https://youtu.be/rJWo1Pt19vI)
|
+| **June 10 → July 8** | Break | No tutorials during this period. |
+| **July 15** | Tutorial | - [Energy Participation Ratio in Qiskit Metal](https://youtu.be/HJNKG5z6Jys)
- [New Feature: LOM Analysis for Composite Systems](https://youtu.be/XpnTJSBjb8E)
- [New Feature: Export Design to Script](https://youtu.be/JpoD3SjObHc)
|
+| **July 22 → Sept 16** | Break | No tutorials during this period. |
+| **Sept 23** | Tutorial | [Making a QComponent from Scratch](https://youtu.be/5iEOJDMWXDE) |
+| **Oct 7** | Tutorial | [New LOM Analysis Methodology - Part 1](https://youtu.be/S8Wx2Lo2CxQ) |
+| **Oct 21** | Tutorial | [New LOM Analysis Methodology - Part 2](https://youtu.be/b2azGJ-RCjk) |
+| **Nov 4** | Tutorial | [New LOM Analysis Methodology - Part 3](https://youtu.be/kWFYYUa0V3k) |
+| **Nov 18** | Forum | Q&A - Ask anything to the Qiskit Metal team. |
+| **Jan 13, 2022** | Forum | Q&A - Open discussion with the Qiskit Metal team. |
+| **Jan 27, 2022** | Forum | Helping users generate a custom component. |
+| **Feb 10, 2022** | Tutorial | - [GUI Icons](https://youtu.be/aE2Dsc67S8w)
- [Jaynes Cummings Model](https://youtu.be/dtwL_K-TJtY)
- [Template Options, Default Options](https://youtu.be/qKLyEyW7cbQ)
|
+| **Feb 24, 2022** | Tutorial | [Flip Chip by Guest Speaker, Sandoko Kosen](https://youtu.be/BUojR6Uti5Q) |
+| **Mar 10, 2022** | Forum | Metal community feedback session. |
+| **Mar 24, 2022** | Tutorial | [Time Evolution for the CR Gate](https://www.youtube.com/watch?v=icDryjZrUQ4) |
+| **Aug 4, 2022** | Tutorial | [Open-Source Rendering and Simulation Solution for Qiskit Metal](https://youtu.be/sA0uXtCAhWw) |
+| **Aug 11, 2022** | Tutorial | [Qiskit Metal E21: Quantum Spice Web App - Sneak Peak](https://youtu.be/3UE57DaG-HI) |
+| **Feb 2, 2023** | Tutorial | [Qiskit Metal E22: Open-Source Simulation Renderers — Gmsh & ElmerFEM](https://youtu.be/84j3l_9fHko) |
+| **2022 → ...** | TBD | Potential Topics: - Analysis Deep Dives (as needed)
- Common Chip Analysis Issues
- Metal Use Cases: Pin, Port, Fillet Matching
- GDS Fabrication Options
- QRenderers: How to Use & Modify
- New QAnalysis/QRenderer Structure
- ...
|
diff --git a/changelog.md b/changelog.md
new file mode 100644
index 000000000..59482b260
--- /dev/null
+++ b/changelog.md
@@ -0,0 +1,37 @@
+# Changelog Note Scratchpad for Developers
+
+This log is used by developers to jot notes.
+
+For the offical user-facing changelog for a particular release can be found in the correspondent Github release page. For example, you can find the changelog for the `0.0.4` release [here](https://github.com/Qiskit/qiskit-metal/releases/tag/0.0.4)
+
+The changelog for all releases can be found in the release page: [![Releases](https://img.shields.io/github/release/Qiskit/qiskit-metal.svg?style=popout-square)](https://github.com/Qiskit/qiskit-metal/releases)
+
+## QISKIT METAL v0.5 (2025)
+
+### Major Updates
+
+This release addresses significant package changes and ports:
+
+- **PyQt5 to PySide6**: A complete overhaul of the GUI.
+- **GDSPY to GDSTK**: Replaced GDSPY with the more robust GDSTK library.
+- **PYAEDT to Ansys (v1.0)**: Major update with a new syntax. Extensive testing required.
+- **Installation Improvements**: Transitioned to `venv` for faster environment setup, moving away from `conda`. Also, most package versions have been floated and upgraded.
+- **Docs**:
+ - Migrate qiskit_sphinx_theme to the new theme
+ - Add divs on the front page to tuts etc
+ - Add user content and showcase page
+
+---
+
+### GUI Enhancements
+
+1. **Traceback Reporting**: Added detailed traceback reporting in the logging system to aid debugging.
+2. **Model Reset Issue**: Fixed the issue causing the warning: *"metal: WARNING: endResetModel called on LibraryFileProxyModel(0x17fda8200) without calling beginResetModel first (No context available from Qt)"*.
+3. **MPL Renderer Issue**: Resolved the error: *"Ignoring fixed y limits to fulfill fixed data aspect with adjustable data limits. Ignoring fixed x limits to fulfill fixed data aspect with adjustable data limits."*.
+4. **UI Button Update**: Added a red border style to the "Create Component" button in the UI for better visibility.
+
+---
+
+### PYAEDT Update
+
+- **FutureWarning**: The `pyaedt` module has been restructured and is now an alias for the new package structure based on `ansys.aedt.core`. To avoid issues in future versions, please update your imports to use the new architecture. Additionally, several files have been renamed to follow the PEP 8 naming conventions. For more information, refer to the [Ansys AEDT documentation](https://aedt.docs.pyansys.com/version/stable/release_1_0.html).
diff --git a/docs/installation.rst b/docs/installation.rst
index 2252b07eb..9d43433d9 100644
--- a/docs/installation.rst
+++ b/docs/installation.rst
@@ -4,6 +4,19 @@
Installation
************
+~~~~~~~~~~~~~~~~~~~~~~~
+Outline of Installation
+~~~~~~~~~~~~~~~~~~~~~~~
+
+* **Basic Installation**: Quick setup instructions for PyPI deployment.
+* **Advanced Installation**: Detailed options for different environments.
+ - **Conda environment setup** (preferred setup): Instructions for creating a new or using an existing conda environment.
+ - **Without conda**: Alternative setup using Python virtual environments.
+* **Other**
+ * **Optional Jupyter Lab**: Steps to integrate the environment with Jupyter Lab.
+ * **Installation hints**: Tips and troubleshooting for setting up the environment.
+ * **Common Issues**: FAQ and solutions to common problems.
+
~~~~~~~~~~~~~~~~~~
Basic Installation
~~~~~~~~~~~~~~~~~~
@@ -67,7 +80,7 @@ Option 1: A new environment
^^^^^^^^^^^^^^^^^^^^^^^^^^^
The most reliable way to set up a qiskit_metal environment is to build one from scratch using the provided conda environment specification file `environment.yml`.
-To do so, first navigate to the folder created by the clone. For example:
+To do so, first navigate to the root folder created by the code clone. For example:
::
@@ -85,7 +98,7 @@ This creates a new environment with name `` with all the necessary lib
Then it activates the new environment.
Finally installs the local qiskit-metal code inside that environment.
-The `-e` flag install qiskit\_metal in `editable mode `_.
+The `-e` flag installs qiskit\_metal in `editable mode `_.
You can add the `-v` flag for verbose on-screen log information.
@@ -98,7 +111,7 @@ To do so, execute these commands in the top-level of the repository:
::
- conda env update -n environment.yml
+ conda env update -n -f environment.yml
conda activate
python -m pip install --no-deps -e .
@@ -108,15 +121,15 @@ Notes:
* Remember the period (".") at the end of the third command.
* **Important**: Remember to `conda activate ` if you intend to use qiskit-metal. See what a `conda environment is `_
-At this point you can already use qiskit-metal through jupyter notebook.
-However, if you prefer using jupyter lab, you will need to execute a couple of extra steps.
+At this point you can already use qiskit-metal through Jupyter Notebook.
+However, if you prefer using JupyterLab, you will need to execute a couple of extra steps.
^^^^^^^^^^^^^^^^^^^^^^
-(Optional) Jupyter lab
+(Optional) Jupyter Lab
^^^^^^^^^^^^^^^^^^^^^^
-Launching jupyter lab will execute python code in the conda `base` environment by default.
+Launching JupyterLab will execute Python code in the conda `base` environment by default.
-To change environment to the Qiskit Metal one you just finished setting up, denoted by ``, which we usually just call `metal`, you will need first to add to jupyter lab's list of available kernels.
+To change environment to the Qiskit Metal one you just finished setting up, denoted by ``, which we usually just call `metal`, you will need first to add to JupyterLab's list of available kernels.
From the command line, run the following lines (inside an active environment):
@@ -128,40 +141,19 @@ From the command line, run the following lines (inside an active envi
Using the above command, you will now have the current conda environment in any Jupyter notebook.
-Once inside `jupyter lab`, you can switch to the newly created Metal kernel to use qiskit-metal. Use the Menu `Kernel>Change Kernel`.
-
--------------------------------------------
-Subsequent updates of the conda environment
--------------------------------------------
-
-Package dependencies will evolve over time and could at some point require a new version of a library.
-For example, we can anticipate updating `pyEPR-quantum` to enable Ansys interactions previously unsupported.
-To update your local install, simply execute the metal package install command
-
-::
-
- python -m pip install -ve .
-
-Alternatively, you can remove your conda environment by executing the commands below and later re-create a new environment following the original install instructions in section 1.
-
-::
-
- conda env list
- conda env remove -n
-
-We discourage using conda commands to update packages after the install of Qiskit Metal.
-Indeed, since Qiskit Metal is installed using pip, the subsequent use of conda commands can introduce inconsistencies that could render your environment unusable.
+Once inside `JupyterLab`, you can switch to the newly created Metal kernel to use qiskit-metal. Use the Menu `Kernel>Change Kernel`.
------------------------------------------------------------
Without conda: Virtual environment setup (alternative setup)
------------------------------------------------------------
-**On Windows, do this first:** It is recommended that you first install `Visual C++ 14.0`, it is required for a successful install of `gdspy`.
-If you do not have `Visual C++ 14.0` installed you will be notified to install it when `gdspy` attempts to install.
+**On Windows, do this first:** It is recommended that you first install `Visual C++ 14.0`, required for a successful install of `gdspy`.
+If you do not have `Visual C++ 14.0` installed, you will be notified to install it when `gdspy` attempts to install.
You can do this by downloading and installing `C++ Build Tools `_.
Be sure to select the latest versions of `MSVCv142 - VS 2019 C++ x64/x86 build tools` and `Windows 10 SDK` in the installer as suggested in `this wiki `_ referenced by the gdspy documentation.
To use a Python virtual environment, execute these commands in the top-level of the repository:
+
::
python -m venv
@@ -169,9 +161,7 @@ To use a Python virtual environment, execute these commands in the top-level of
python -m pip install -U pip
python -m pip install -r requirements.txt -r requirements-dev.txt -e .
-
-where `` is where you want the Python virtual environment to be installed.
-On Windows, replace `source /bin/activate` with `.\\Scripts\activate`.
+On Windows, replace `source /bin/activate` with `.\Scripts\activate`.
------------------
Installation hints
@@ -181,9 +171,9 @@ Here are some things to consider when setting up a development environment:
* If using a virtual environment, make sure `pip` is up to date. In initial environment testing, PySide2 is installable with only the latest version of `pip`.
-* Add the path of your qiskit-metal folder to your PATH
+* Add the path of your qiskit-metal folder to your PATH.
-* Library errors when activating conda environments, or initializing jupyter notebook/lab, indicate a conflict between python libraries in the base and sub environments. Go ahead and manually delete the library from the base environment `site-packages` folder, shows in the error message. You might need to reinstall them in the sub environment, or create a new one.
+* Library errors when activating conda environments or initializing Jupyter Notebook/Lab indicate a conflict between Python libraries in the base and sub-environments. Go ahead and manually delete the library from the base environment `site-packages` folder shown in the error message. You might need to reinstall them in the sub-environment or create a new one.
--------------------------
Setting up precommit hooks
diff --git a/docs/tut/quick-topics/Managing-variables.ipynb b/docs/tut/quick-topics/Managing-variables.ipynb
index b30188c64..4737a8127 100644
--- a/docs/tut/quick-topics/Managing-variables.ipynb
+++ b/docs/tut/quick-topics/Managing-variables.ipynb
@@ -136,7 +136,7 @@
"metadata": {},
"outputs": [],
"source": [
- "from PySide2.QtWidgets import QAbstractItemView\n",
+ "from PySide6.QtWidgets import QAbstractItemView\n",
"table.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel)\n",
"table.setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel)"
]
@@ -170,7 +170,7 @@
"outputs": [
{
"data": {
- "image/png": "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8jVdbX53/4m+2mVLUucO7D8dX7J29eIGdt87+zfedvcae2/4F2+uvOxyECM7dx2aatEZvP2m1UoyPNyr5fvUeDQkil7wNt5x262jve/uOileuXGJJ5MYTXOL2wKDJw8cG5GXLOqq9XGJ4VP7ToY7Vi5JnDqS4hrvec97lYPpswASlqOjYd4ZXHt5c8AfGD154MCFyJWbbm518nt272UaV6xeHDi7f9fRoYSjtuWKNr8nEDh5rn/18p6zB7ceGZaWr97QU6vu3n7A3r7sys66wRP7jozg7o7W1o6G4SO7Dg4IK9es7+LsbicDFNN9xdoVrY53t+5O1S5a2uSK9h9L+ZZf3uY9tuftsxHyZY4w30AImR+LDQCSJEUSwrI1G0rbuVQXRZFVFSMENM1UauZKWhTOv7une5FZ8ggh5PP5iJQhVJsC+9GpGNtpRFNIVlSMcd94ZlFNgdDo2rsf/8JNzDe/+3vccPn/+OMPPPfjH6954IstdU9vvOWWn7/w1uf//JMv/vs/Lt646Xtf2W8818Zx7YMfW52OPfON71z1wKNLR949wAc+/NANx3BPZM8LY/Y1DyzpfTs6Hs2EXJfd/v61/gGe/VCDbYsE7544t/byRb3BzszQIaxQV97y3ls7JJ5b51fDfxjFHnfje99/14tvpD58b8N334g/ct/GX/Y23xiIvDHsDNptHRvvvm21exTVPeKAkSW31p585ZhYdPKD69z06LXNv9ox+tDD9z3f/5tbb2vZ09uyhD3/6pFkE9BLr7phkX3g+bOZx+9ZumNnLB6lY/zFL160reNzT979kxfeffyPNrz06y33ve9+6o2+m9c19/KeD98HB2PjEWoslcqAg1265laWn4gfIfaOhx+rG/59uPWGDyw++ooEANw1t9109IX9S3pa33717Pq77uHj+z7+oRu+/89Pp8Dpcrsfft+DP3p574cevOaZH71x4z23DiTffvCGVd86fkRO87HxpDAakjsBnME77lj2o2f7P/eRDT/41bGH7rspcwjdswLCsKInSKdbr+3b9esoLwGAp2v14/c0vbR9/C+eXPnt348+fM9m8YDz4atrB2X/B93Sf78re9wN73nf3ZkXT3ziYzc8/dOD9z14U+bN1IPr2F/u56/1OmqWXHv3jT2nxu0fuZ9+C666Du94Ga27d33XwAh+9P23PXuIPn/meLH/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6C9/b0QIRb2N6yojixbMbfNXb998ZNbtD1tYZU0sGgyGa4XQ3Dtnn30DLjD1ADk5Ob/+9a/bb5IkyfO8LMuqqiqKon8/+Xw+m82mfw3oSXSUbpBie/To0cOHD2+/qUfYiqJomiZJEk3TqqoKguB0OlVVbWhocLvdsix3+dWlwsLCp59+uv0mRVGrV6+uqqoaP358VVVVVlYWxtjv99vtdk3TWJZlWVbPrNiFfT5HRkbG0aNH4/H4iRMncnJywuEwwzCZmZnr16+PxWIHDx7Mz8/vhjNSaZrWe56QkFBfXz9ixAi/32+1WlVVpWlaTw0ly9101YKqqrIsa5omyzLGOBaL2Ww2o9HY1tamKIooil8vEN0dYIxVVdU/TBRF0U+B4zg9/OI4TpKki7fS1a7ECibEGV3XjR3uObptf+0XpZd67gqmb41iUv77dw+37lj95vub/Bd769FsxhO/mP7H3/zdD3FFB524gukaE41Gn3766ZUrV+bn5y9atGj69Om33XbbH/7wh5UrVx4+fFgUxYKCggcffLAbLlc5efLkn//8540bN5aXlz/22GOxWOzVV1/9/e9/v2LFio8++khRlAULFkydOrW7zeFoa2t78sknZVlmGOaXv/yl2Wy+5557lixZsnTp0rq6umg0Wl5efuutt3af4CAYDD755JOhUEjTtN/85jfLli0rKSkZNWrUE0884fF4RFF8+umnO06E7z5OnTr1v//7vyzL5uTkPPTQQw8++OBvfvObjRs3bt26VVXV9PT0H//4x1+/tNodrFq16pVXXqmpqZkxY8aUKVNWrFjx+9//ft26dW+88QZFUaNGjVq0aFH3eYW0i8fjL7744ttvv221WufMmWO3230+38SJE5csWSKKYiQSue+++7r5MNgzL/yz80MZc0L+1MG29z/Z1zGQ+x6GMgghmmFJpMmycgnD5QRNk4rSjX7VdQcQylwIxlgURf1CDE3TDMOIosiyrP67Si+H2w3jGISQqqrtP/LaR4/0UQ19u/5zsEv7eB4YY/251dMqIoQkSWJZVh8bI0mSYZju9i2l/8LWO6woCkmSFEXpGymKYhimGz7PCCGMsf6ssixLkqT+POsDHt35hY0QkmVZHwrV+6mfAsZYkiSMsX46Xd3H89B7qF9wpCiq/UKqPjzTnV8q7Z554Z9XYta94u414v6MfipCn298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\n",
+ "image/png": "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8jVdbX53/4m+2mVLUucO7D8dX7J29eIGdt87+zfedvcae2/4F2+uvOxyECM7dx2aatEZvP2m1UoyPNyr5fvUeDQkil7wNt5x262jve/uOileuXGJJ5MYTXOL2wKDJw8cG5GXLOqq9XGJ4VP7ToY7Vi5JnDqS4hrvec97lYPpswASlqOjYd4ZXHt5c8AfGD154MCFyJWbbm518nt272UaV6xeHDi7f9fRoYSjtuWKNr8nEDh5rn/18p6zB7ceGZaWr97QU6vu3n7A3r7sys66wRP7jozg7o7W1o6G4SO7Dg4IK9es7+LsbicDFNN9xdoVrY53t+5O1S5a2uSK9h9L+ZZf3uY9tuftsxHyZY4w30AImR+LDQCSJEUSwrI1G0rbuVQXRZFVFSMENM1UauZKWhTOv7une5FZ8ggh5PP5iJQhVJsC+9GpGNtpRFNIVlSMcd94ZlFNgdDo2rsf/8JNzDe/+3vccPn/+OMPPPfjH6954IstdU9vvOWWn7/w1uf//JMv/vs/Lt646Xtf2W8818Zx7YMfW52OPfON71z1wKNLR949wAc+/NANx3BPZM8LY/Y1DyzpfTs6Hs2EXJfd/v61/gGe/VCDbYsE7544t/byRb3BzszQIaxQV97y3ls7JJ5b51fDfxjFHnfje99/14tvpD58b8N334g/ct/GX/Y23xiIvDHsDNptHRvvvm21exTVPeKAkSW31p585ZhYdPKD69z06LXNv9ox+tDD9z3f/5tbb2vZ09uyhD3/6pFkE9BLr7phkX3g+bOZx+9ZumNnLB6lY/zFL160reNzT979kxfeffyPNrz06y33ve9+6o2+m9c19/KeD98HB2PjEWoslcqAg1265laWn4gfIfaOhx+rG/59uPWGDyw++ooEANw1t9109IX9S3pa33717Pq77uHj+z7+oRu+/89Pp8Dpcrsfft+DP3p574cevOaZH71x4z23DiTffvCGVd86fkRO87HxpDAakjsBnME77lj2o2f7P/eRDT/41bGH7rspcwjdswLCsKInSKdbr+3b9esoLwGAp2v14/c0vbR9/C+eXPnt348+fM9m8YDz4atrB2X/B93Sf78re9wN73nf3ZkXT3ziYzc8/dOD9z14U+bN1IPr2F/u56/1OmqWXHv3jT2nxu0fuZ9+C666Du94Ga27d33XwAh+9P23PXuIPn/meLH/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6C9/b0QIRb2N6yojixbMbfNXb998ZNbtD1tYZU0sGgyGa4XQ3Dtnn30DLjD1ADk5Ob/+9a/bb5IkyfO8LMuqqiqKon8/+Xw+m82mfw3oSXSUbpBie/To0cOHD2+/qUfYiqJomiZJEk3TqqoKguB0OlVVbWhocLvdsix3+dWlwsLCp59+uv0mRVGrV6+uqqoaP358VVVVVlYWxtjv99vtdk3TWJZlWVbPrNiFfT5HRkbG0aNH4/H4iRMncnJywuEwwzCZmZnr16+PxWIHDx7Mz8/vhjNSaZrWe56QkFBfXz9ixAi/32+1WlVVpWlaTw0ly9101YKqqrIsa5omyzLGOBaL2Ww2o9HY1tamKIooil8vEN0dYIxVVdU/TBRF0U+B4zg9/OI4TpKki7fS1a7ECibEGV3XjR3uObptf+0XpZd67gqmb41iUv77dw+37lj95vub/Bd769FsxhO/mP7H3/zdD3FFB524gukaE41Gn3766ZUrV+bn5y9atGj69Om33XbbH/7wh5UrVx4+fFgUxYKCggcffLAbLlc5efLkn//8540bN5aXlz/22GOxWOzVV1/9/e9/v2LFio8++khRlAULFkydOrW7zeFoa2t78sknZVlmGOaXv/yl2Wy+5557lixZsnTp0rq6umg0Wl5efuutt3af4CAYDD755JOhUEjTtN/85jfLli0rKSkZNWrUE0884fF4RFF8+umnO06E7z5OnTr1v//7vyzL5uTkPPTQQw8++OBvfvObjRs3bt26VVXV9PT0H//4x1+/tNodrFq16pVXXqmpqZkxY8aUKVNWrFjx+9//ft26dW+88QZFUaNGjVq0aFH3eYW0i8fjL7744ttvv221WufMmWO3230+38SJE5csWSKKYiQSue+++7r5MNgzL/yz80MZc0L+1MG29z/Z1zGQ+x6GMgghmmFJpMmycgnD5QRNk4rSjX7VdQcQylwIxlgURf1CDE3TDMOIosiyrP67Si+H2w3jGISQqqrtP/LaR4/0UQ19u/5zsEv7eB4YY/251dMqIoQkSWJZVh8bI0mSYZju9i2l/8LWO6woCkmSFEXpGymKYhimGz7PCCGMsf6ssixLkqT+POsDHt35hY0QkmVZHwrV+6mfAsZYkiSMsX46Xd3H89B7qF9wpCiq/UKqPjzTnV8q7Z554Z9XYta94u414v6MfipCn298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",
"text/plain": [
""
]
@@ -555,7 +555,7 @@
],
"metadata": {
"kernelspec": {
- "display_name": "Python 3",
+ "display_name": "Python 3.10.5 ('pob_pyside6')",
"language": "python",
"name": "python3"
},
@@ -569,7 +569,12 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.7.8"
+ "version": "3.10.5"
+ },
+ "vscode": {
+ "interpreter": {
+ "hash": "dfaca1dc5e36f3627306c0cd7529793f0c893d996af719425010aac17208ef7e"
+ }
}
},
"nbformat": 4,
diff --git a/environment.yml b/environment.yml
index d5c9a9b9c..00f4f9a75 100644
--- a/environment.yml
+++ b/environment.yml
@@ -2,28 +2,27 @@ name: qiskit-metal
channels:
- conda-forge
dependencies:
- - python>=3.9
- - addict==2.4.0
- - descartes==1.1.0
- - gdspy==1.6.12
- - geopandas==0.12.2
- - ipython==8.10.0
- - matplotlib==3.7.0
- - numpy==1.24.2
- - pandas==1.5.3
- - pint==0.20.1
- - pyepr-quantum==0.8.5.7
- - pygments==2.14.0
- - pyside2==5.15.8
- - qdarkstyle==3.1
- - qutip==4.7.1
- - scipy==1.10.0
- - shapely==2.0.1
- - jupyter==1.0.0
- - scqubits==3.1.0
- - pyyaml==6.0
- - pip==23.0
+ - python>=3.10.* # Let's see if we can float higher in future.
+ - scqubits==3.1.0 # Very careful to update higher, as it can break things. Want to update in future.
+ - addict>=2.4.0
+ - descartes>=1.1.0
+ - geopandas>=0.12.2
+ - ipython>=8.10.0
+ - matplotlib>=3.7.0
+ - numpy>=1.24.2
+ - pandas>=1.5.3
+ - pint>=0.20.1
+ - pyEPR-quantum==0.8.5.7
+ - pygments>=2.14.0
+ - qdarkstyle>=3.1
+ - qutip>=4.7.1
+ - scipy>=1.10.0
+ - shapely>=2.0.1
+ - jupyter
- cython<3.0.0
+ - pip
- pip:
- - pyaedt==0.6.46
- - gmsh==4.11.1
+ - pyaedt>=0.9.0 # Todo: update in future to latest. # Very careful to update higher, as it can break things. Want to update in future.
+ - gmsh>=4.11.1
+ - gdstk>=0.9 # Used to be gdspy>=1.6.12
+ - pyside6 # Critical to building gui, can causes lots of problems, careful.
diff --git a/qiskit_metal/__init__.py b/qiskit_metal/__init__.py
index f2c5d596b..d1f21f84a 100644
--- a/qiskit_metal/__init__.py
+++ b/qiskit_metal/__init__.py
@@ -15,7 +15,7 @@
# pylint: disable=wrong-import-order
# pylint: disable=wrong-import-position
"""Qiskit Metal"""
-__version__ = '0.1.5'
+__version__ = '0.5.0'
__license__ = "Apache 2.0"
__copyright__ = 'Copyright IBM 2019-2020'
__author__ = 'Zlatko Minev, Thomas McConkey, and them IBM Quantum Team'
@@ -55,10 +55,10 @@ def __setup_Qt_backend(): # pylint: disable=invalid-name
# When in vscode and in debug-mode, may want to comment
# next line out, "os.environ["QT_API"] = "pyside2""
- os.environ["QT_API"] = "pyside2"
+ os.environ["QT_API"] = "pyside6"
- from PySide2 import QtCore #, QtWidgets
- from PySide2.QtCore import Qt
+ from PySide6 import QtCore #, QtWidgets
+ from PySide6.QtCore import Qt
def set_attribute(name: str, value=True):
"""Describes attributes that change the behavior of application-wide
@@ -107,7 +107,7 @@ def set_attribute(name: str, value=True):
if not os.getenv('QISKIT_METAL_HEADLESS', None):
# pylint: disable=import-outside-toplevel
import matplotlib as mpl
- mpl.use("Qt5Agg")
+ mpl.use("QtAgg")
# pylint: disable=redefined-outer-name
import matplotlib.pyplot as plt
plt.ion() # interactive
diff --git a/qiskit_metal/_gui/__compile_ui_to_py.bat b/qiskit_metal/_gui/__compile_ui_to_py.bat
index bcf941648..4b427864e 100644
--- a/qiskit_metal/_gui/__compile_ui_to_py.bat
+++ b/qiskit_metal/_gui/__compile_ui_to_py.bat
@@ -6,12 +6,12 @@ cd /d "%~dp0"
echo "The current directory is %CD%"
-call pyside2-uic -o main_window_ui.py --from-imports main_window_ui.ui
-call pyside2-uic -o component_widget_ui.py --from-imports component_widget_ui.ui
-call pyside2-uic -o plot_window_ui.py --from-imports plot_window_ui.ui
-call pyside2-uic -o elements_ui.py --from-imports elements_ui.ui
+call pyside6-uic -o main_window_ui.py --from-imports main_window_ui.ui
+call pyside6-uic -o component_widget_ui.py --from-imports component_widget_ui.ui
+call pyside6-uic -o plot_window_ui.py --from-imports plot_window_ui.ui
+call pyside6-uic -o elements_ui.py --from-imports elements_ui.ui
-call pyside2-rcc -o main_window_rc_rc.py main_window_rc.qrc
+call pyside6-rcc -o main_window_rc_rc.py main_window_rc.qrc
rem ############################################################################
rem # Zlatko:
diff --git a/qiskit_metal/_gui/__compile_ui_to_py.shell b/qiskit_metal/_gui/__compile_ui_to_py.shell
index 91a25f0c1..cf0e7e8fa 100755
--- a/qiskit_metal/_gui/__compile_ui_to_py.shell
+++ b/qiskit_metal/_gui/__compile_ui_to_py.shell
@@ -7,9 +7,9 @@ cd "$(dirname "$0")"
echo -e "Present working directory: ${RED}${PWD}${NC}"
# Define conversion
-ui_to_py=pyside2-uic
-rc_to_py=pyside2-rcc
-# pyside2-uic
+ui_to_py=pyside6-uic
+rc_to_py=pyside6-rcc
+# pyside6-uic
# -o : The Python code generated is written to the file .
# -i : Resource modules are imported using
# from import ... rather than a simple import ....
diff --git a/qiskit_metal/_gui/component_widget_ui.py b/qiskit_metal/_gui/component_widget_ui.py
index c48ea94c7..d385af571 100644
--- a/qiskit_metal/_gui/component_widget_ui.py
+++ b/qiskit_metal/_gui/component_widget_ui.py
@@ -4,11 +4,11 @@
# licensing of './component_widget_ui.ui' applies.
#
# Created: Sat Jun 19 22:02:29 2021
-# by: pyside2-uic running on PySide2 5.13.2
+# by: pyside6-uic running on PySide2 5.13.2
#
# WARNING! All changes made in this file will be lost!
-from PySide2 import QtCore, QtGui, QtWidgets
+from PySide6 import QtCore, QtGui, QtWidgets
class Ui_ComponentWidget(object):
diff --git a/qiskit_metal/_gui/elements_ui.py b/qiskit_metal/_gui/elements_ui.py
index 4b03c135f..44324288d 100644
--- a/qiskit_metal/_gui/elements_ui.py
+++ b/qiskit_metal/_gui/elements_ui.py
@@ -4,11 +4,11 @@
# licensing of './elements_ui.ui' applies.
#
# Created: Thu Jun 30 16:30:20 2022
-# by: pyside2-uic running on PySide2 5.13.2
+# by: pyside6-uic running on PySide2 5.13.2
#
# WARNING! All changes made in this file will be lost!
-from PySide2 import QtCore, QtGui, QtWidgets
+from PySide6 import QtCore, QtGui, QtWidgets
class Ui_ElementsWindow(object):
@@ -50,7 +50,7 @@ def setupUi(self, ElementsWindow):
self.label.sizePolicy().hasHeightForWidth())
self.label.setSizePolicy(sizePolicy)
font = QtGui.QFont()
- font.setWeight(75)
+ font.setLegacyWeight(75)
font.setBold(True)
self.label.setFont(font)
self.label.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing |
@@ -77,7 +77,7 @@ def setupUi(self, ElementsWindow):
self.horizontalLayout.addWidget(self.line)
self.label_3 = QtWidgets.QLabel(self.centralwidget)
font = QtGui.QFont()
- font.setWeight(75)
+ font.setLegacyWeight(75)
font.setBold(True)
self.label_3.setFont(font)
self.label_3.setObjectName("label_3")
diff --git a/qiskit_metal/_gui/elements_window.py b/qiskit_metal/_gui/elements_window.py
index 738429e85..dad0af05a 100644
--- a/qiskit_metal/_gui/elements_window.py
+++ b/qiskit_metal/_gui/elements_window.py
@@ -15,10 +15,9 @@
from typing import TYPE_CHECKING
-import numpy as np
-from PySide2 import QtCore, QtWidgets
-from PySide2.QtCore import QAbstractTableModel, QModelIndex
-from PySide2.QtWidgets import QMainWindow
+from PySide6 import QtCore, QtWidgets
+from PySide6.QtCore import QAbstractTableModel, QModelIndex
+from PySide6.QtWidgets import QMainWindow
from .elements_ui import Ui_ElementsWindow
@@ -33,7 +32,7 @@ class ElementsWindow(QMainWindow):
Extends the `QMainWindow` class.
- PySide2 Signal / Slots Extensions:
+ PySide6 Signal / Slots Extensions:
The UI can call up to this class to execeute button clicks for instance
Extensiosn in qt designer on signals/slots are linked to this class
"""
@@ -108,13 +107,13 @@ class ElementTableModel(QAbstractTableModel):
__timer_interval = 500 # ms
def __init__(self, gui, parent=None, element_type='poly'):
- super().__init__(parent=parent)
"""
Args:
gui (MetalGUI): The GUI
parent (QMainWindowExtension): Parent window. Defaults to None.
element_type (str): The element type. Defaults to 'poly'.
"""
+ super().__init__(parent=parent)
self.logger = gui.logger
self.gui = gui
self._row_count = -1
@@ -165,7 +164,12 @@ def refresh(self):
Completely rebuild the model.
"""
- self.modelReset.emit()
+ self.beginResetModel()
+ try:
+ # parent_index = self.createIndex(0, 0, self.root)
+ self._row_count = self.rowCount(None)
+ finally:
+ self.endResetModel()
def refresh_auto(self):
"""Update row count etc."""
@@ -175,16 +179,22 @@ def refresh_auto(self):
if self._row_count != new_count:
#self.logger.info('Number of components changed')
- # When a model is reset it should be considered that all
- # information previously retrieved from it is invalid.
- # This includes but is not limited to the rowCount() and
- # columnCount(), flags(), data retrieved through data(), and roleNames().
- # This will loose the current selection.
- self.modelReset.emit()
+ # Wrap the reset logic in beginResetModel and endResetModel
+ self.beginResetModel()
+ try:
+
+ # When a model is reset it should be considered that all
+ # information previously retrieved from it is invalid.
+ # This includes but is not limited to the rowCount() and
+ # columnCount(), flags(), data retrieved through data(), and roleNames().
+ # This will loose the current selection.
+ # self.modelReset.emit()
- self._row_count = new_count
+ self._row_count = new_count
+ finally:
+ self.endResetModel()
- def rowCount(self, parent: QModelIndex = None):
+ def rowCount(self, parent: QModelIndex = None) -> int:
"""Counts all the rows.
Args:
@@ -193,11 +203,13 @@ def rowCount(self, parent: QModelIndex = None):
Returns:
int: The number of rows
"""
+ if parent is None:
+ parent = QModelIndex()
if self.table is None:
return 0
return self.table.shape[0]
- def columnCount(self, parent: QModelIndex = None):
+ def columnCount(self, parent: QModelIndex = None): #pylint: disable=unused-argument
"""Counts all the columns.
Args:
diff --git a/qiskit_metal/_gui/endcap_hfss_gui.py b/qiskit_metal/_gui/endcap_hfss_gui.py
index 2f8a9fdb5..151620aa6 100644
--- a/qiskit_metal/_gui/endcap_hfss_gui.py
+++ b/qiskit_metal/_gui/endcap_hfss_gui.py
@@ -14,7 +14,7 @@
from typing import Tuple
-from PySide2.QtWidgets import (QComboBox, QTableWidgetItem, QAbstractItemView,
+from PySide6.QtWidgets import (QComboBox, QTableWidgetItem, QAbstractItemView,
QMainWindow, QLineEdit)
from .endcap_hfss_ui import Ui_mainWindow
diff --git a/qiskit_metal/_gui/endcap_hfss_ui.py b/qiskit_metal/_gui/endcap_hfss_ui.py
index 24fa2a023..7b6139210 100644
--- a/qiskit_metal/_gui/endcap_hfss_ui.py
+++ b/qiskit_metal/_gui/endcap_hfss_ui.py
@@ -4,11 +4,11 @@
# licensing of './endcap_hfss_ui.ui' applies.
#
# Created: Sat Jun 19 22:02:30 2021
-# by: pyside2-uic running on PySide2 5.13.2
+# by: pyside6-uic running on PySide2 5.13.2
#
# WARNING! All changes made in this file will be lost!
-from PySide2 import QtCore, QtGui, QtWidgets
+from PySide6 import QtCore, QtGui, QtWidgets
class Ui_mainWindow(object):
diff --git a/qiskit_metal/_gui/endcap_q3d_gui.py b/qiskit_metal/_gui/endcap_q3d_gui.py
index 25bcaa49c..1ac997501 100644
--- a/qiskit_metal/_gui/endcap_q3d_gui.py
+++ b/qiskit_metal/_gui/endcap_q3d_gui.py
@@ -14,7 +14,7 @@
from typing import Tuple
-from PySide2.QtWidgets import (QComboBox, QTableWidgetItem, QAbstractItemView,
+from PySide6.QtWidgets import (QComboBox, QTableWidgetItem, QAbstractItemView,
QMainWindow)
from .endcap_q3d_ui import Ui_mainWindow
diff --git a/qiskit_metal/_gui/endcap_q3d_ui.py b/qiskit_metal/_gui/endcap_q3d_ui.py
index c5cc0127a..ce796040a 100644
--- a/qiskit_metal/_gui/endcap_q3d_ui.py
+++ b/qiskit_metal/_gui/endcap_q3d_ui.py
@@ -4,11 +4,11 @@
# licensing of './endcap_q3d_ui.ui' applies.
#
# Created: Sat Jun 19 22:02:29 2021
-# by: pyside2-uic running on PySide2 5.13.2
+# by: pyside6-uic running on PySide2 5.13.2
#
# WARNING! All changes made in this file will be lost!
-from PySide2 import QtCore, QtGui, QtWidgets
+from PySide6 import QtCore, QtGui, QtWidgets
class Ui_mainWindow(object):
diff --git a/qiskit_metal/_gui/list_model_base.py b/qiskit_metal/_gui/list_model_base.py
index 0ac492d94..1efed9b67 100644
--- a/qiskit_metal/_gui/list_model_base.py
+++ b/qiskit_metal/_gui/list_model_base.py
@@ -12,9 +12,9 @@
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
-from PySide2 import QtCore
-from PySide2.QtCore import Qt
-from PySide2.QtGui import QStandardItem, QStandardItemModel
+from PySide6 import QtCore
+from PySide6.QtCore import Qt
+from PySide6.QtGui import QStandardItem, QStandardItemModel
class DynamicList(QStandardItemModel):
diff --git a/qiskit_metal/_gui/main_window.py b/qiskit_metal/_gui/main_window.py
index 7b1aa6d18..fb175f1bb 100644
--- a/qiskit_metal/_gui/main_window.py
+++ b/qiskit_metal/_gui/main_window.py
@@ -18,11 +18,11 @@
from pathlib import Path
from typing import TYPE_CHECKING, List
-from PySide2.QtCore import Qt, QTimer
-from PySide2.QtGui import QIcon, QPixmap
-from PySide2.QtWidgets import (QAction, QDialog, QDockWidget, QFileDialog,
+from PySide6.QtCore import Qt, QTimer
+from PySide6.QtGui import QIcon, QPixmap, QAction
+from PySide6.QtWidgets import (QWidget, QDialog, QDockWidget, QFileDialog,
QLabel, QMainWindow, QMessageBox, QVBoxLayout)
-from PySide2.QtCore import QSortFilterProxyModel
+from PySide6.QtCore import QSortFilterProxyModel
from qiskit_metal._gui.widgets.qlibrary_display.delegate_qlibrary import \
LibraryDelegate
from qiskit_metal._gui.widgets.qlibrary_display.file_model_qlibrary import \
@@ -55,7 +55,7 @@
pass
if TYPE_CHECKING:
- from ..renderers.renderer_mpl.mpl_canvas import PlotCanvas
+ from ..renderers.renderer_mpl.mpl_canvas import PlotCanvas # pylint: disable=syntax-error
class QMainWindowExtension(QMainWindowExtensionBase):
@@ -126,7 +126,7 @@ def delete_all_components(self):
self,
'Delete all components?',
"Are you sure you want to clear all Metal components?",
- buttons=(QMessageBox.Yes | QMessageBox.No))
+ buttons=QMessageBox.Yes | QMessageBox.No)
if ret == QMessageBox.Yes:
self.logger.info('Delete all components.')
self.design.delete_all_components()
@@ -147,7 +147,7 @@ def save_design_copy(self):
pyscript = self.design.to_python_script()
#check whether filename is empty or not. Save file only when filename is non-empty.
if len(filename):
- with open(filename, 'w') as f:
+ with open(filename, 'w', encoding='utf-8') as f:
f.write(pyscript)
@slot_catch_error()
@@ -172,7 +172,7 @@ def save_design(self, _=None):
pyscript = self.design.to_python_script()
#check whether filename is empty or not. Save file only when filename is non-empty.
if len(filename):
- with open(filename, 'w') as f:
+ with open(filename, 'w', encoding='utf-8') as f:
f.write(pyscript)
#make it clear it's saving
@@ -262,7 +262,7 @@ def ok_to_close(self):
if reply == QMessageBox.Cancel:
return False
elif reply == QMessageBox.Yes:
- wait = self.save_design()
+ _ = self.save_design()
return True
return True
@@ -322,6 +322,7 @@ def __init__(self, design: QDesign = None):
self._setup_plot_widget()
self._setup_design_components_widget()
self._setup_elements_widget()
+ self.main_window.show()
self._setup_variables_widget()
self._ui_adjustments_final()
self._setup_library_widget()
@@ -329,6 +330,7 @@ def __init__(self, design: QDesign = None):
# Show and raise
self.main_window.show()
+
# self.qApp.processEvents(QEventLoop.AllEvents, 1)
# - don't think I need this here, it doesn't help to show and raise
# - need to call from different thread.
@@ -358,7 +360,7 @@ def _set_enabled_design_widgets(self, enabled: bool = True):
def setEnabled(parent, widgets):
for widgetname in widgets:
if hasattr(parent, widgetname):
- widget = getattr(parent, widgetname) # type: QWidget
+ widget: 'QWidget' = getattr(parent, widgetname)
if widget:
widget.setEnabled(enabled)
else:
@@ -485,8 +487,8 @@ def _add_additional_qactions_tool_bar_view(self):
icon = QIcon()
icon.addPixmap(QPixmap(iconName), QIcon.Normal, QIcon.Off)
- # Function call & monkey patch class instance
- dock.doShow = doShowHighlighWidget.__get__(dock, type(dock)) # pylint: disable=assignment-from-no-return
+ # Function call & monkey patch class instance ala Monkey Patch
+ dock.doShow = doShowHighlighWidget.__get__(dock, type(dock)) # pylint: disable=assignment-from-no-return, no-value-for-parameter
# QT Action with trigger, embed in toolbar
action = QAction('', dock, triggered=dock.doShow)
@@ -529,9 +531,9 @@ def _setup_plot_widget(self):
# Add to the tabbed main view
self.ui.mainViewTab.layout().addWidget(self.plot_win)
- # add highlight function
+ # add highlight function ala Monkey Patch
obj = self.ui.mainViewTab
- obj.doShow = doShowHighlighWidget.__get__(obj, type(obj)) # pylint: disable=assignment-from-no-return
+ obj.doShow = doShowHighlighWidget.__get__(obj, type(obj)) # pylint: disable=assignment-from-no-return, no-value-for-parameter
# Move the dock
self._move_dock_to_new_parent(self.ui.dockLog, self.plot_win)
@@ -547,7 +549,8 @@ def _move_dock_to_new_parent(self,
Args:
dock (QDockWidget): Dock to move
new_parent (QMainWindow): New parent window
- dock_location (Qt dock location): Location of the dock. Defaults to Qt.BottomDockWidgetArea.
+ dock_location (Qt dock location): Location of the dock.
+ Defaults to Qt.BottomDockWidgetArea.
"""
dock.setParent(new_parent)
new_parent.addDockWidget(dock_location, dock)
@@ -638,10 +641,12 @@ def filter_text_design_onChanged(self, text):
def _create_new_component_object_from_qlibrary(self, full_path: str):
"""
- Must be defined outside of _setup_library_widget to ensure self == MetalGUI and will retain opened ScrollArea
+ Must be defined outside of _setup_library_widget to ensure
+ self == MetalGUI and will retain opened ScrollArea
Args:
- relative_index: QModelIndex of the desired QComponent file in the Qlibrary GUI display
+ relative_index: QModelIndex of the desired QComponent file in
+ the Qlibrary GUI display
"""
try:
@@ -677,7 +682,11 @@ def _setup_library_widget(self):
dock.library_model.setRootPath(self.QLIBRARY_ROOT)
# QSortFilterProxyModel
- #QSortFilterProxyModel: sorting items, filtering out items, or both. maps the original model indexes to new indexes, allows a given source model to be restructured as far as views are concerned without requiring any transformations on the underlying data, and without duplicating the data in memory.
+ #QSortFilterProxyModel: sorting items, filtering out items, or both.
+ # maps the original model indexes to new indexes, allows a given
+ # source model to be restructured as far as views are concerned
+ # without requiring any transformations on the underlying data, and
+ # without duplicating the data in memory.
dock.proxy_library_model = LibraryFileProxyModel()
dock.proxy_library_model.setSourceModel(dock.library_model)
dock.proxy_library_model.setFilterCaseSensitivity(Qt.CaseInsensitive)
@@ -722,15 +731,21 @@ def dockLibrary_filter_onChanged(self, text):
"""
view = self.ui.dockLibrary_tree_view
dock = self.ui.dockLibrary
- dock.proxy_library_model.filter_text = text
+ proxy_model = dock.proxy_library_model
- dock.proxy_library_model.setFilterWildcard(text)
+ # Wrap changes to filter_text and setFilterWildcard with reset calls
+ proxy_model.beginResetModel()
+ try:
+ proxy_model.filter_text = text
+ proxy_model.setFilterWildcard(text)
+ finally:
+ proxy_model.endResetModel()
view.setRootIndex(
- dock.proxy_library_model.mapFromSource(
+ proxy_model.mapFromSource(
dock.library_model.index(dock.library_model.rootPath())))
- if len(text) >= 1 and dock.proxy_library_model.rowCount() > 0:
+ if len(text) >= 1 and proxy_model.rowCount() > 0:
view.expandAll()
else:
view.collapseAll()
@@ -765,7 +780,7 @@ def get_axes(self, num: int = None):
return axes
@property
- def axes(self) -> List['Axes']:
+ def axes(self) -> List['matplotlib.plt.Axes']:
"""Returns the axes."""
return self.plot_win.canvas.axes
@@ -869,3 +884,12 @@ def gui_create_build_log_window(self, _=None):
self.build_log_window = BuildHistoryScrollArea(
self.design.build_logs.data())
self.build_log_window.show()
+
+ def save_file(self):
+ """Save file. Called on exit.
+
+ Raises:
+ NotImplementedError: Function not written
+ """
+ print("TODO: Save file - not yet implemented here")
+ raise NotImplementedError()
diff --git a/qiskit_metal/_gui/main_window_base.py b/qiskit_metal/_gui/main_window_base.py
index 349185e3d..ef275ba2a 100644
--- a/qiskit_metal/_gui/main_window_base.py
+++ b/qiskit_metal/_gui/main_window_base.py
@@ -20,10 +20,10 @@
from copy import deepcopy
from pathlib import Path
-from PySide2 import QtCore, QtGui, QtWidgets
-from PySide2.QtCore import QTimer
-from PySide2.QtGui import QIcon
-from PySide2.QtWidgets import QApplication, QFileDialog, QMainWindow, QMessageBox, QDockWidget
+from PySide6 import QtCore, QtGui, QtWidgets
+from PySide6.QtCore import QTimer
+from PySide6.QtGui import QIcon
+from PySide6.QtWidgets import QApplication, QFileDialog, QMainWindow, QMessageBox, QDockWidget
from .. import Dict, config
from ..toolbox_python._logging import setup_logger
@@ -497,7 +497,7 @@ def load_stylesheet(self, path=None):
'Please do so from the terminal using\n'
' >>> pip install qdarkstyle')
- os.environ['QT_API'] = 'pyside2'
+ os.environ['QT_API'] = 'pyside6'
self.main_window.setStyleSheet(qdarkstyle.load_stylesheet())
elif path == 'metal_dark':
@@ -618,7 +618,7 @@ def kick_start_qApp():
try:
from IPython import get_ipython
ipython = get_ipython()
- ipython.magic('gui qt5')
+ ipython.magic('gui qt6')
except Exception as e:
print("exception")
diff --git a/qiskit_metal/_gui/main_window_rc_rc.py b/qiskit_metal/_gui/main_window_rc_rc.py
index 85c5181ba..3aafecb35 100644
--- a/qiskit_metal/_gui/main_window_rc_rc.py
+++ b/qiskit_metal/_gui/main_window_rc_rc.py
@@ -3,11 +3,11 @@
# Resource object code
#
# Created: Thu Jun 30 16:30:21 2022
-# by: The Resource Compiler for PySide2 (Qt v5.12.9)
+# by: The Resource Compiler for PySide6 (Qt v5.12.9)
#
# WARNING! All changes made in this file will be lost!
-from PySide2 import QtCore
+from PySide6 import QtCore
qt_resource_data = b"\
\x00\x00e\xee\
diff --git a/qiskit_metal/_gui/main_window_ui.py b/qiskit_metal/_gui/main_window_ui.py
index 39e659553..903c037df 100644
--- a/qiskit_metal/_gui/main_window_ui.py
+++ b/qiskit_metal/_gui/main_window_ui.py
@@ -4,11 +4,11 @@
# licensing of './main_window_ui.ui' applies.
#
# Created: Thu Jun 30 16:30:19 2022
-# by: pyside2-uic running on PySide2 5.13.2
+# by: pyside6-uic running on PySide6 5.13.2
#
# WARNING! All changes made in this file will be lost!
-from PySide2 import QtCore, QtGui, QtWidgets
+from PySide6 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
@@ -109,7 +109,7 @@ def setupUi(self, MainWindow):
MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBarDesign)
self.toolBarView = QtWidgets.QToolBar(MainWindow)
font = QtGui.QFont()
- font.setWeight(75)
+ font.setLegacyWeight(75)
font.setBold(True)
self.toolBarView.setFont(font)
self.toolBarView.setToolButtonStyle(QtCore.Qt.ToolButtonIconOnly)
@@ -121,7 +121,7 @@ def setupUi(self, MainWindow):
QtGui.QIcon.On)
self.dockDesign.setWindowIcon(icon5)
self.dockDesign.setFloating(False)
- self.dockDesign.setFeatures(QtWidgets.QDockWidget.AllDockWidgetFeatures)
+ # self.dockDesign.setFeatures(QtWidgets.QDockWidget.DockWidgetFeatures)
self.dockDesign.setObjectName("dockDesign")
self.dockWidgetContents = QtWidgets.QWidget()
self.dockWidgetContents.setObjectName("dockWidgetContents")
@@ -185,8 +185,8 @@ def setupUi(self, MainWindow):
icon8.addPixmap(QtGui.QPixmap(":/component"), QtGui.QIcon.Normal,
QtGui.QIcon.On)
self.dockLibrary.setWindowIcon(icon8)
- self.dockLibrary.setFeatures(
- QtWidgets.QDockWidget.AllDockWidgetFeatures)
+ # self.dockLibrary.setFeatures(
+ # QtWidgets.QDockWidget.AllDockWidgetFeatures)
self.dockLibrary.setObjectName("dockLibrary")
self.dockLibraryContents = QtWidgets.QWidget()
self.dockLibraryContents.setObjectName("dockLibraryContents")
@@ -204,8 +204,8 @@ def setupUi(self, MainWindow):
MainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(1), self.dockLibrary)
self.dockComponent = QtWidgets.QDockWidget(MainWindow)
self.dockComponent.setMinimumSize(QtCore.QSize(62, 38))
- self.dockComponent.setFeatures(
- QtWidgets.QDockWidget.AllDockWidgetFeatures)
+ # self.dockComponent.setFeatures(
+ # QtWidgets.QDockWidget.AllDockWidgetFeatures)
self.dockComponent.setObjectName("dockComponent")
self.dockComponentCental = QtWidgets.QWidget()
self.dockComponentCental.setObjectName("dockComponentCental")
@@ -222,7 +222,7 @@ def setupUi(self, MainWindow):
icon9.addPixmap(QtGui.QPixmap(":/log"), QtGui.QIcon.Normal,
QtGui.QIcon.On)
self.dockLog.setWindowIcon(icon9)
- self.dockLog.setFeatures(QtWidgets.QDockWidget.AllDockWidgetFeatures)
+ # self.dockLog.setFeatures(QtWidgets.QDockWidget.AllDockWidgetFeatures)
self.dockLog.setObjectName("dockLog")
self.dockWidgetContents_4 = QtWidgets.QWidget()
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred,
@@ -300,20 +300,20 @@ def setupUi(self, MainWindow):
self.toolbar_renderers.setIconSize(QtCore.QSize(32, 32))
self.toolbar_renderers.setObjectName("toolbar_renderers")
MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolbar_renderers)
- self.actionSave = QtWidgets.QAction(MainWindow)
+ self.actionSave = QtGui.QAction(MainWindow)
icon11 = QtGui.QIcon()
icon11.addPixmap(QtGui.QPixmap(":/save"), QtGui.QIcon.Normal,
QtGui.QIcon.Off)
self.actionSave.setIcon(icon11)
self.actionSave.setObjectName("actionSave")
- self.actionLoad = QtWidgets.QAction(MainWindow)
+ self.actionLoad = QtGui.QAction(MainWindow)
icon12 = QtGui.QIcon()
icon12.addPixmap(QtGui.QPixmap(":/load"), QtGui.QIcon.Normal,
QtGui.QIcon.Off)
self.actionLoad.setIcon(icon12)
self.actionLoad.setAutoRepeat(False)
self.actionLoad.setObjectName("actionLoad")
- self.actionDesign = QtWidgets.QAction(MainWindow)
+ self.actionDesign = QtGui.QAction(MainWindow)
self.actionDesign.setCheckable(True)
self.actionDesign.setChecked(True)
icon13 = QtGui.QIcon()
@@ -321,12 +321,12 @@ def setupUi(self, MainWindow):
QtGui.QIcon.Off)
self.actionDesign.setIcon(icon13)
self.actionDesign.setObjectName("actionDesign")
- self.actionElements = QtWidgets.QAction(MainWindow)
+ self.actionElements = QtGui.QAction(MainWindow)
self.actionElements.setCheckable(True)
self.actionElements.setChecked(False)
self.actionElements.setIcon(icon2)
self.actionElements.setObjectName("actionElements")
- self.actionLog = QtWidgets.QAction(MainWindow)
+ self.actionLog = QtGui.QAction(MainWindow)
self.actionLog.setCheckable(True)
self.actionLog.setChecked(True)
icon14 = QtGui.QIcon()
@@ -334,7 +334,7 @@ def setupUi(self, MainWindow):
QtGui.QIcon.Off)
self.actionLog.setIcon(icon14)
self.actionLog.setObjectName("actionLog")
- self.actionNewComponent = QtWidgets.QAction(MainWindow)
+ self.actionNewComponent = QtGui.QAction(MainWindow)
self.actionNewComponent.setCheckable(True)
self.actionNewComponent.setChecked(False)
icon15 = QtGui.QIcon()
@@ -342,26 +342,26 @@ def setupUi(self, MainWindow):
QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.actionNewComponent.setIcon(icon15)
self.actionNewComponent.setObjectName("actionNewComponent")
- self.actionDelete_All = QtWidgets.QAction(MainWindow)
+ self.actionDelete_All = QtGui.QAction(MainWindow)
icon16 = QtGui.QIcon()
icon16.addPixmap(QtGui.QPixmap(":/delete_all"), QtGui.QIcon.Normal,
QtGui.QIcon.Off)
self.actionDelete_All.setIcon(icon16)
- self.actionDelete_All.setPriority(QtWidgets.QAction.LowPriority)
+ self.actionDelete_All.setPriority(QtGui.QAction.LowPriority)
self.actionDelete_All.setObjectName("actionDelete_All")
- self.actionZoom = QtWidgets.QAction(MainWindow)
+ self.actionZoom = QtGui.QAction(MainWindow)
icon17 = QtGui.QIcon()
icon17.addPixmap(QtGui.QPixmap(":/plot/zoom"), QtGui.QIcon.Normal,
QtGui.QIcon.Off)
self.actionZoom.setIcon(icon17)
self.actionZoom.setObjectName("actionZoom")
- self.actionPan = QtWidgets.QAction(MainWindow)
+ self.actionPan = QtGui.QAction(MainWindow)
icon18 = QtGui.QIcon()
icon18.addPixmap(QtGui.QPixmap(":/plot/pan"), QtGui.QIcon.Normal,
QtGui.QIcon.On)
self.actionPan.setIcon(icon18)
self.actionPan.setObjectName("actionPan")
- self.actionConnectors = QtWidgets.QAction(MainWindow)
+ self.actionConnectors = QtGui.QAction(MainWindow)
self.actionConnectors.setCheckable(True)
self.actionConnectors.setChecked(False)
icon19 = QtGui.QIcon()
@@ -369,19 +369,19 @@ def setupUi(self, MainWindow):
QtGui.QIcon.Off)
self.actionConnectors.setIcon(icon19)
self.actionConnectors.setObjectName("actionConnectors")
- self.actionStyleOpen = QtWidgets.QAction(MainWindow)
+ self.actionStyleOpen = QtGui.QAction(MainWindow)
self.actionStyleOpen.setObjectName("actionStyleOpen")
- self.actionStyleDefault = QtWidgets.QAction(MainWindow)
+ self.actionStyleDefault = QtGui.QAction(MainWindow)
self.actionStyleDefault.setObjectName("actionStyleDefault")
- self.actionStyleDark = QtWidgets.QAction(MainWindow)
+ self.actionStyleDark = QtGui.QAction(MainWindow)
self.actionStyleDark.setObjectName("actionStyleDark")
- self.actionScreenshot = QtWidgets.QAction(MainWindow)
+ self.actionScreenshot = QtGui.QAction(MainWindow)
icon20 = QtGui.QIcon()
icon20.addPixmap(QtGui.QPixmap(":/screenshot"), QtGui.QIcon.Normal,
QtGui.QIcon.Off)
self.actionScreenshot.setIcon(icon20)
self.actionScreenshot.setObjectName("actionScreenshot")
- self.action_full_refresh = QtWidgets.QAction(MainWindow)
+ self.action_full_refresh = QtGui.QAction(MainWindow)
icon21 = QtGui.QIcon()
icon21.addPixmap(QtGui.QPixmap(":/force_refresh"), QtGui.QIcon.Normal,
QtGui.QIcon.Off)
@@ -389,42 +389,42 @@ def setupUi(self, MainWindow):
self.action_full_refresh.setShortcutContext(
QtCore.Qt.WidgetWithChildrenShortcut)
self.action_full_refresh.setAutoRepeat(False)
- self.action_full_refresh.setPriority(QtWidgets.QAction.HighPriority)
+ self.action_full_refresh.setPriority(QtGui.QAction.HighPriority)
self.action_full_refresh.setObjectName("action_full_refresh")
- self.actionRebuild = QtWidgets.QAction(MainWindow)
+ self.actionRebuild = QtGui.QAction(MainWindow)
icon22 = QtGui.QIcon()
icon22.addPixmap(QtGui.QPixmap(":/rebuild"), QtGui.QIcon.Normal,
QtGui.QIcon.Off)
icon22.addPixmap(QtGui.QPixmap(":/rebuild"), QtGui.QIcon.Active,
QtGui.QIcon.On)
self.actionRebuild.setIcon(icon22)
- self.actionRebuild.setPriority(QtWidgets.QAction.HighPriority)
+ self.actionRebuild.setPriority(QtGui.QAction.HighPriority)
self.actionRebuild.setObjectName("actionRebuild")
- self.actionFull_Screen = QtWidgets.QAction(MainWindow)
+ self.actionFull_Screen = QtGui.QAction(MainWindow)
icon23 = QtGui.QIcon()
icon23.addPixmap(QtGui.QPixmap(":/plot/----autozoom"),
QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.actionFull_Screen.setIcon(icon23)
self.actionFull_Screen.setObjectName("actionFull_Screen")
- self.actionMetal_Dark = QtWidgets.QAction(MainWindow)
+ self.actionMetal_Dark = QtGui.QAction(MainWindow)
self.actionMetal_Dark.setObjectName("actionMetal_Dark")
- self.actionSaveAs = QtWidgets.QAction(MainWindow)
+ self.actionSaveAs = QtGui.QAction(MainWindow)
self.actionSaveAs.setIcon(icon11)
self.actionSaveAs.setObjectName("actionSaveAs")
- self.actionSave_window_state = QtWidgets.QAction(MainWindow)
+ self.actionSave_window_state = QtGui.QAction(MainWindow)
self.actionSave_window_state.setIcon(icon11)
self.actionSave_window_state.setObjectName("actionSave_window_state")
- self.actionLabelDesign = QtWidgets.QAction(MainWindow)
+ self.actionLabelDesign = QtGui.QAction(MainWindow)
self.actionLabelDesign.setEnabled(False)
self.actionLabelDesign.setObjectName("actionLabelDesign")
- self.actionClose_window = QtWidgets.QAction(MainWindow)
+ self.actionClose_window = QtGui.QAction(MainWindow)
self.actionClose_window.setObjectName("actionClose_window")
- self.actionMetal_Window = QtWidgets.QAction(MainWindow)
+ self.actionMetal_Window = QtGui.QAction(MainWindow)
self.actionMetal_Window.setEnabled(False)
self.actionMetal_Window.setObjectName("actionMetal_Window")
- self.actionViewDummyLabel = QtWidgets.QAction(MainWindow)
+ self.actionViewDummyLabel = QtGui.QAction(MainWindow)
self.actionViewDummyLabel.setObjectName("actionViewDummyLabel")
- self.actionVariables = QtWidgets.QAction(MainWindow)
+ self.actionVariables = QtGui.QAction(MainWindow)
self.actionVariables.setCheckable(True)
self.actionVariables.setChecked(False)
icon24 = QtGui.QIcon()
@@ -432,34 +432,34 @@ def setupUi(self, MainWindow):
QtGui.QIcon.Off)
self.actionVariables.setIcon(icon24)
self.actionVariables.setObjectName("actionVariables")
- self.actionToggleDocks = QtWidgets.QAction(MainWindow)
+ self.actionToggleDocks = QtGui.QAction(MainWindow)
self.actionToggleDocks.setIcon(icon6)
self.actionToggleDocks.setObjectName("actionToggleDocks")
- self.actionGDS = QtWidgets.QAction(MainWindow)
+ self.actionGDS = QtGui.QAction(MainWindow)
icon25 = QtGui.QIcon()
icon25.addPixmap(QtGui.QPixmap(":/renderer/_imgs/renderers/GDS.png"),
QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.actionGDS.setIcon(icon25)
self.actionGDS.setObjectName("actionGDS")
- self.actionHFSS = QtWidgets.QAction(MainWindow)
+ self.actionHFSS = QtGui.QAction(MainWindow)
icon26 = QtGui.QIcon()
icon26.addPixmap(QtGui.QPixmap(":/renderer/_imgs/renderers/HFSS.png"),
QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.actionHFSS.setIcon(icon26)
self.actionHFSS.setObjectName("actionHFSS")
- self.actionQ3D = QtWidgets.QAction(MainWindow)
+ self.actionQ3D = QtGui.QAction(MainWindow)
icon27 = QtGui.QIcon()
icon27.addPixmap(QtGui.QPixmap(":/renderer/_imgs/renderers/Q3D.png"),
QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.actionQ3D.setIcon(icon27)
self.actionQ3D.setObjectName("actionQ3D")
- self.actionBuildHistory = QtWidgets.QAction(MainWindow)
+ self.actionBuildHistory = QtGui.QAction(MainWindow)
icon28 = QtGui.QIcon()
icon28.addPixmap(QtGui.QPixmap(":/build_history"), QtGui.QIcon.Normal,
QtGui.QIcon.Off)
self.actionBuildHistory.setIcon(icon28)
self.actionBuildHistory.setObjectName("actionBuildHistory")
- self.actionDeveloperMode = QtWidgets.QAction(MainWindow)
+ self.actionDeveloperMode = QtGui.QAction(MainWindow)
self.actionDeveloperMode.setCheckable(True)
icon29 = QtGui.QIcon()
icon29.addPixmap(QtGui.QPixmap(":/_imgs/lightbulb.png"),
@@ -468,7 +468,7 @@ def setupUi(self, MainWindow):
QtGui.QIcon.Normal, QtGui.QIcon.On)
self.actionDeveloperMode.setIcon(icon29)
self.actionDeveloperMode.setObjectName("actionDeveloperMode")
- self.actionWebHelp = QtWidgets.QAction(MainWindow)
+ self.actionWebHelp = QtGui.QAction(MainWindow)
icon30 = QtGui.QIcon()
icon30.addPixmap(QtGui.QPixmap(":/browser"), QtGui.QIcon.Normal,
QtGui.QIcon.Off)
diff --git a/qiskit_metal/_gui/net_list_ui.py b/qiskit_metal/_gui/net_list_ui.py
index 6d4d7b5a4..3cbf8757b 100644
--- a/qiskit_metal/_gui/net_list_ui.py
+++ b/qiskit_metal/_gui/net_list_ui.py
@@ -4,11 +4,11 @@
# licensing of './net_list_ui.ui' applies.
#
# Created: Wed May 25 09:29:27 2022
-# by: pyside2-uic running on PySide2 5.13.2
+# by: pyside6-uic running on PySide2 5.13.2
#
# WARNING! All changes made in this file will be lost!
-from PySide2 import QtCore, QtGui, QtWidgets
+from PySide6 import QtCore, QtGui, QtWidgets
class Ui_NetListWindow(object):
diff --git a/qiskit_metal/_gui/net_list_window.py b/qiskit_metal/_gui/net_list_window.py
index 9e1be7335..bb90f39cd 100644
--- a/qiskit_metal/_gui/net_list_window.py
+++ b/qiskit_metal/_gui/net_list_window.py
@@ -15,10 +15,9 @@
from typing import TYPE_CHECKING
-import numpy as np
-from PySide2 import QtCore, QtWidgets
-from PySide2.QtCore import QAbstractTableModel, QModelIndex
-from PySide2.QtWidgets import QMainWindow
+from PySide6 import QtCore
+from PySide6.QtCore import QAbstractTableModel, QModelIndex
+from PySide6.QtWidgets import QMainWindow
from .net_list_ui import Ui_NetListWindow
@@ -33,7 +32,7 @@ class NetListWindow(QMainWindow):
Extends the `QMainWindow` class.
- PySide2 Signal / Slots Extensions:
+ PySide6 Signal / Slots Extensions:
The UI can call up to this class to execute button clicks for instance
Extensions in qt designer on signals/slots are linked to this class
"""
@@ -88,13 +87,13 @@ class NetListTableModel(QAbstractTableModel):
__timer_interval = 500 # ms
def __init__(self, gui, parent=None):
- super().__init__(parent=parent)
"""
Args:
gui (MetalGUI): The GUI
parent (QMainWindowExtension): Parent window. Defaults to None.
element_type (str): The element type. Defaults to 'poly'.
"""
+ super().__init__(parent=parent)
self.logger = gui.logger
self.gui = gui
self._row_count = -1
@@ -139,7 +138,11 @@ def refresh(self):
Completely rebuild the model.
"""
- self.modelReset.emit()
+ self.beginResetModel()
+ try:
+ self._row_count = self.rowCount()
+ finally:
+ self.endResetModel()
def refresh_auto(self):
"""Update row count etc."""
@@ -149,16 +152,22 @@ def refresh_auto(self):
if self._row_count != new_count:
#self.logger.info('Number of components changed')
- # When a model is reset it should be considered that all
- # information previously retrieved from it is invalid.
- # This includes but is not limited to the rowCount() and
- # columnCount(), flags(), data retrieved through data(), and roleNames().
- # This will loose the current selection.
- self.modelReset.emit()
+ # Wrap the reset logic in beginResetModel and endResetModel
+ self.beginResetModel()
+ try:
+
+ # When a model is reset it should be considered that all
+ # information previously retrieved from it is invalid.
+ # This includes but is not limited to the rowCount() and
+ # columnCount(), flags(), data retrieved through data(), and roleNames().
+ # This will loose the current selection.
+ # self.modelReset.emit()
- self._row_count = new_count
+ self._row_count = new_count
+ finally:
+ self.endResetModel()
- def rowCount(self, parent: QModelIndex = None):
+ def rowCount(self, parent: QModelIndex = None): # pylint: disable=unused-argument
"""Counts all the rows.
Args:
@@ -171,7 +180,7 @@ def rowCount(self, parent: QModelIndex = None):
return 0
return self.net_info.shape[0]
- def columnCount(self, parent: QModelIndex = None):
+ def columnCount(self, parent: QModelIndex = None): # pylint: disable=unused-argument
"""Counts all the columns.
Args:
diff --git a/qiskit_metal/_gui/plot_window_ui.py b/qiskit_metal/_gui/plot_window_ui.py
index 94d8d662d..4f815953a 100644
--- a/qiskit_metal/_gui/plot_window_ui.py
+++ b/qiskit_metal/_gui/plot_window_ui.py
@@ -4,11 +4,11 @@
# licensing of './plot_window_ui.ui' applies.
#
# Created: Sat Jun 19 22:02:29 2021
-# by: pyside2-uic running on PySide2 5.13.2
+# by: pyside6-uic running on PySide2 5.13.2
#
# WARNING! All changes made in this file will be lost!
-from PySide2 import QtCore, QtGui, QtWidgets
+from PySide6 import QtCore, QtGui, QtWidgets
class Ui_MainWindowPlot(object):
@@ -37,19 +37,19 @@ def setupUi(self, MainWindowPlot):
self.toolBar.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon)
self.toolBar.setObjectName("toolBar")
MainWindowPlot.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar)
- self.actionPan = QtWidgets.QAction(MainWindowPlot)
+ self.actionPan = QtGui.QAction(MainWindowPlot)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(":/plot/pan"), QtGui.QIcon.Normal,
QtGui.QIcon.On)
self.actionPan.setIcon(icon)
self.actionPan.setObjectName("actionPan")
- self.actionZoom = QtWidgets.QAction(MainWindowPlot)
+ self.actionZoom = QtGui.QAction(MainWindowPlot)
icon1 = QtGui.QIcon()
icon1.addPixmap(QtGui.QPixmap(":/plot/zoom"), QtGui.QIcon.Normal,
QtGui.QIcon.Off)
self.actionZoom.setIcon(icon1)
self.actionZoom.setObjectName("actionZoom")
- self.actionConnectors = QtWidgets.QAction(MainWindowPlot)
+ self.actionConnectors = QtGui.QAction(MainWindowPlot)
self.actionConnectors.setCheckable(True)
self.actionConnectors.setChecked(False)
icon2 = QtGui.QIcon()
@@ -57,7 +57,7 @@ def setupUi(self, MainWindowPlot):
QtGui.QIcon.Off)
self.actionConnectors.setIcon(icon2)
self.actionConnectors.setObjectName("actionConnectors")
- self.actionCoords = QtWidgets.QAction(MainWindowPlot)
+ self.actionCoords = QtGui.QAction(MainWindowPlot)
self.actionCoords.setCheckable(True)
self.actionCoords.setChecked(True)
icon3 = QtGui.QIcon()
@@ -65,19 +65,19 @@ def setupUi(self, MainWindowPlot):
QtGui.QIcon.Off)
self.actionCoords.setIcon(icon3)
self.actionCoords.setObjectName("actionCoords")
- self.actionAuto = QtWidgets.QAction(MainWindowPlot)
+ self.actionAuto = QtGui.QAction(MainWindowPlot)
icon4 = QtGui.QIcon()
icon4.addPixmap(QtGui.QPixmap(":/plot/autozoom"), QtGui.QIcon.Normal,
QtGui.QIcon.Off)
self.actionAuto.setIcon(icon4)
self.actionAuto.setObjectName("actionAuto")
- self.actionReplot = QtWidgets.QAction(MainWindowPlot)
+ self.actionReplot = QtGui.QAction(MainWindowPlot)
icon5 = QtGui.QIcon()
icon5.addPixmap(QtGui.QPixmap(":/plot/refresh_plot"),
QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.actionReplot.setIcon(icon5)
self.actionReplot.setObjectName("actionReplot")
- self.actionRuler = QtWidgets.QAction(MainWindowPlot)
+ self.actionRuler = QtGui.QAction(MainWindowPlot)
icon6 = QtGui.QIcon()
icon6.addPixmap(QtGui.QPixmap(":/plot/ruler"), QtGui.QIcon.Normal,
QtGui.QIcon.Off)
diff --git a/qiskit_metal/_gui/renderer_gds_gui.py b/qiskit_metal/_gui/renderer_gds_gui.py
index 29cca8818..cc128eccf 100644
--- a/qiskit_metal/_gui/renderer_gds_gui.py
+++ b/qiskit_metal/_gui/renderer_gds_gui.py
@@ -12,7 +12,7 @@
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
-from PySide2.QtWidgets import (QAbstractItemView, QFileDialog, QMainWindow,
+from PySide6.QtWidgets import (QAbstractItemView, QFileDialog, QMainWindow,
QMessageBox)
from .list_model_base import DynamicList
diff --git a/qiskit_metal/_gui/renderer_gds_model.py b/qiskit_metal/_gui/renderer_gds_model.py
index 16580a3d4..aa7ce75ef 100644
--- a/qiskit_metal/_gui/renderer_gds_model.py
+++ b/qiskit_metal/_gui/renderer_gds_model.py
@@ -13,9 +13,9 @@
# that they have been altered from the originals.
# Tree model for GDS renderer
-import PySide2
-from PySide2 import QtWidgets
-from PySide2.QtWidgets import QTreeView, QWidget
+import PySide6
+from PySide6 import QtWidgets
+from PySide6.QtWidgets import QTreeView, QWidget
from .widgets.bases.dict_tree_base import QTreeModel_Base
diff --git a/qiskit_metal/_gui/renderer_gds_ui.py b/qiskit_metal/_gui/renderer_gds_ui.py
index 0da6f31fc..c4d717188 100644
--- a/qiskit_metal/_gui/renderer_gds_ui.py
+++ b/qiskit_metal/_gui/renderer_gds_ui.py
@@ -2,12 +2,13 @@
# Form implementation generated from reading ui file 'c:\Temp\GitHub\qiskit-metal\qiskit_metal\_gui\renderer_gds_ui.ui'
#
-# Created by: PyQt5 UI code generator 5.15.9
+# Created: Sat Jun 19 22:02:30 2021
+# by: pyside6-uic running on PySide2 5.13.2
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
-from PySide2 import QtCore, QtGui, QtWidgets
+from PySide6 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
@@ -124,5 +125,5 @@ def retranslateUi(self, MainWindow):
self.exportButton.setText(_translate("MainWindow", "Export"))
-from .tree_view_base import QTreeView_Base
from . import main_window_rc_rc
+from .tree_view_base import QTreeView_Base
diff --git a/qiskit_metal/_gui/renderer_hfss_gui.py b/qiskit_metal/_gui/renderer_hfss_gui.py
index d7422c243..b747bf000 100644
--- a/qiskit_metal/_gui/renderer_hfss_gui.py
+++ b/qiskit_metal/_gui/renderer_hfss_gui.py
@@ -12,7 +12,7 @@
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
-from PySide2.QtWidgets import (QAbstractItemView, QMainWindow, QMessageBox)
+from PySide6.QtWidgets import (QAbstractItemView, QMainWindow, QMessageBox)
from .list_model_base import DynamicList
from .renderer_hfss_model import RendererHFSS_Model
diff --git a/qiskit_metal/_gui/renderer_hfss_model.py b/qiskit_metal/_gui/renderer_hfss_model.py
index 6da82d8c8..8c6dff38c 100644
--- a/qiskit_metal/_gui/renderer_hfss_model.py
+++ b/qiskit_metal/_gui/renderer_hfss_model.py
@@ -13,9 +13,9 @@
# that they have been altered from the originals.
# Tree model for Ansys HFSS renderer
-import PySide2
-from PySide2 import QtWidgets
-from PySide2.QtWidgets import QTreeView, QWidget
+import PySide6
+from PySide6 import QtWidgets
+from PySide6.QtWidgets import QTreeView, QWidget
from .widgets.bases.dict_tree_base import QTreeModel_Base
diff --git a/qiskit_metal/_gui/renderer_hfss_ui.py b/qiskit_metal/_gui/renderer_hfss_ui.py
index 428cef2c5..6d37dc673 100644
--- a/qiskit_metal/_gui/renderer_hfss_ui.py
+++ b/qiskit_metal/_gui/renderer_hfss_ui.py
@@ -2,12 +2,13 @@
# Form implementation generated from reading ui file 'c:\Temp\GitHub\qiskit-metal\qiskit_metal\_gui\renderer_hfss_ui.ui'
#
-# Created by: PyQt5 UI code generator 5.15.9
+# Created: Sat Jun 19 22:02:29 2021
+# by: pyside6-uic running on PySide2 5.13.2
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
-from PySide2 import QtCore, QtGui, QtWidgets
+from PySide6 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
@@ -97,5 +98,5 @@ def retranslateUi(self, MainWindow):
"Confirm Selection"))
-from .tree_view_base import QTreeView_Base
from . import main_window_rc_rc
+from .tree_view_base import QTreeView_Base
diff --git a/qiskit_metal/_gui/renderer_q3d_gui.py b/qiskit_metal/_gui/renderer_q3d_gui.py
index 24f80c130..c4a6224c2 100644
--- a/qiskit_metal/_gui/renderer_q3d_gui.py
+++ b/qiskit_metal/_gui/renderer_q3d_gui.py
@@ -12,7 +12,7 @@
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
-from PySide2.QtWidgets import (QAbstractItemView, QMainWindow, QMessageBox)
+from PySide6.QtWidgets import (QAbstractItemView, QMainWindow, QMessageBox)
from .list_model_base import DynamicList
from .renderer_q3d_model import RendererQ3D_Model
diff --git a/qiskit_metal/_gui/renderer_q3d_model.py b/qiskit_metal/_gui/renderer_q3d_model.py
index a5295479f..cf99cbec6 100644
--- a/qiskit_metal/_gui/renderer_q3d_model.py
+++ b/qiskit_metal/_gui/renderer_q3d_model.py
@@ -13,9 +13,9 @@
# that they have been altered from the originals.
# Tree model for Ansys Q3D renderer
-import PySide2
-from PySide2 import QtWidgets
-from PySide2.QtWidgets import QTreeView, QWidget
+import PySide6
+from PySide6 import QtWidgets
+from PySide6.QtWidgets import QTreeView, QWidget
from .widgets.bases.dict_tree_base import QTreeModel_Base
diff --git a/qiskit_metal/_gui/renderer_q3d_ui.py b/qiskit_metal/_gui/renderer_q3d_ui.py
index a9f9f1b2c..e0f850c82 100644
--- a/qiskit_metal/_gui/renderer_q3d_ui.py
+++ b/qiskit_metal/_gui/renderer_q3d_ui.py
@@ -2,12 +2,13 @@
# Form implementation generated from reading ui file 'c:\Temp\GitHub\qiskit-metal\qiskit_metal\_gui\renderer_q3d_ui.ui'
#
-# Created by: PyQt5 UI code generator 5.15.9
+# Created: Sat Jun 19 22:02:29 2021
+# by: pyside6-uic running on PySide2 5.13.2
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
-from PySide2 import QtCore, QtGui, QtWidgets
+from PySide6 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
@@ -84,5 +85,5 @@ def retranslateUi(self, MainWindow):
"Confirm Selection"))
-from .tree_view_base import QTreeView_Base
from . import main_window_rc_rc
+from .tree_view_base import QTreeView_Base
diff --git a/qiskit_metal/_gui/styles/metal_dark/TODO.txt b/qiskit_metal/_gui/styles/metal_dark/TODO.txt
index e93f18f71..8fe2f8614 100644
--- a/qiskit_metal/_gui/styles/metal_dark/TODO.txt
+++ b/qiskit_metal/_gui/styles/metal_dark/TODO.txt
@@ -2,11 +2,18 @@ Remember to modify the highlight color to red for the QToolbar hover
QToolBar QToolButton:hover {
border: 1px solid #e74d10;
- ...
+ ...
+2025-01: Added to style.qss for teh New Component Button and added to _style.scss:
+```
+ QPushButton#create_qcomp_button {
+ border: 1px solid #e74d10;
+ border-radius: 1px;
+ }
+```
-How to update stylesheet
+How to update stylesheet
gui.load_stylesheet('metal_dark')
\ No newline at end of file
diff --git a/qiskit_metal/_gui/styles/metal_dark/qss/_styles.scss b/qiskit_metal/_gui/styles/metal_dark/qss/_styles.scss
index 1e12763c1..203caa80a 100755
--- a/qiskit_metal/_gui/styles/metal_dark/qss/_styles.scss
+++ b/qiskit_metal/_gui/styles/metal_dark/qss/_styles.scss
@@ -2271,3 +2271,8 @@ PlotWidget {
/* Fix cut labels in plots #134 */
padding: 0px;
}
+
+QPushButton#create_qcomp_button {
+ border: 1px solid #e74d10;
+ border-radius: 1px;
+ }
diff --git a/qiskit_metal/_gui/styles/metal_dark/style.qss b/qiskit_metal/_gui/styles/metal_dark/style.qss
index 4948a7bc8..1ae8e5f2a 100644
--- a/qiskit_metal/_gui/styles/metal_dark/style.qss
+++ b/qiskit_metal/_gui/styles/metal_dark/style.qss
@@ -2199,3 +2199,8 @@ PlotWidget {
/* Fix cut labels in plots #134 */
padding: 0px;
}
+
+QPushButton#create_qcomp_button {
+ border: 1px solid #e74d10;
+ border-radius: 1px;
+}
diff --git a/qiskit_metal/_gui/tree_view_base.py b/qiskit_metal/_gui/tree_view_base.py
index 162e6f6c0..63fc469a2 100644
--- a/qiskit_metal/_gui/tree_view_base.py
+++ b/qiskit_metal/_gui/tree_view_base.py
@@ -13,9 +13,9 @@
# that they have been altered from the originals.
"""Handles editing a QComponent."""
-from PySide2 import QtCore, QtWidgets
-from PySide2.QtCore import Qt, QTimer
-from PySide2.QtWidgets import QTreeView, QAbstractItemView
+from PySide6 import QtCore, QtWidgets
+from PySide6.QtCore import Qt, QTimer
+from PySide6.QtWidgets import QTreeView, QAbstractItemView
class QTreeView_Base(QTreeView):
diff --git a/qiskit_metal/_gui/utility/_handle_qt_messages.py b/qiskit_metal/_gui/utility/_handle_qt_messages.py
index 9b084a631..c8d519b8e 100644
--- a/qiskit_metal/_gui/utility/_handle_qt_messages.py
+++ b/qiskit_metal/_gui/utility/_handle_qt_messages.py
@@ -20,8 +20,8 @@
import types
from functools import wraps
-from PySide2 import QtCore
-from PySide2.QtCore import Slot
+from PySide6 import QtCore
+from PySide6.QtCore import Slot
from ... import logger
@@ -56,20 +56,40 @@ def _qt_message_handler(mode, context, message):
'QSocketNotifier: Multiple socket notifiers for same socket'):
pass # Caused by running %gui qt multiple times
else:
- if mode == QtCore.QtInfoMsg:
+ if mode == QtCore.QtMsgType.QtInfoMsg:
mode = 'INFO'
- elif mode == QtCore.QtWarningMsg:
+ elif mode == QtCore.QtMsgType.QtWarningMsg:
mode = 'WARNING'
- elif mode == QtCore.QtCriticalMsg:
+ elif mode == QtCore.QtMsgType.QtCriticalMsg:
mode = 'CRITICAL'
- elif mode == QtCore.QtFatalMsg:
+ elif mode == QtCore.QtMsgType.QtFatalMsg:
mode = 'FATAL'
else:
mode = 'DEBUG'
+ # logger.log(
+ # getattr(logging, 'CRITICAL'), 'line: %d, func: %s(), file: %s' %
+ # (context.line, context.function, context.file) + ' %s: %s\n' %
+ # (mode, message))
+
+ # Log basic message details
+ base_message = f"{mode}: {message}"
+
+ # Include context if available
+ if context.file and context.function:
+ base_message += (
+ f" (File: {context.file}, Line: {context.line}, Function: {context.function})"
+ )
+ else:
+ base_message += " (No context available from Qt)"
+
+ # Capture Python traceback for additional details
+ python_traceback = "".join(traceback.format_stack(limit=10))
+
+ # Log the message with the Python traceback
logger.log(
- getattr(logging, 'CRITICAL'), 'line: %d, func: %s(), file: %s' %
- (context.line, context.function, context.file) + ' %s: %s\n' %
- (mode, message))
+ getattr(logging, mode, logging.DEBUG),
+ f"{base_message}\nPython Traceback (most recent call last):\n{python_traceback}"
+ )
#######################################################################################
@@ -77,7 +97,7 @@ def _qt_message_handler(mode, context, message):
def do_debug(msg, name='info'):
- """Utility function used to print debug statements from PySide2 Socket
+ """Utility function used to print debug statements from PySide6 Socket
calls A bit of a cludge.
Args:
@@ -85,19 +105,19 @@ def do_debug(msg, name='info'):
name (str): info wran, debug, etc. Defaults to 'info'.
"""
- if 0:
- # This just gives the qt main loop traceback. Not useful.
- callers = []
- for i in range(1, 20):
- try:
- stack = inspect.stack()[i]
- callers += [f'{stack.function}[{stack.lineno}]']
- except Exception as e: # pylint: disable=broad-except
- print("Exception during do_debug exception handling: " +
- e.__repr__())
- callers = reversed(callers)
- callers = '\n'.join(callers)
- msg = callers + "\n" + str(msg) + '\n'
+ # if 0:
+ # # This just gives the qt main loop traceback. Not useful.
+ # callers = []
+ # for i in range(1, 20):
+ # try:
+ # stack = inspect.stack()[i]
+ # callers += [f'{stack.function}[{stack.lineno}]']
+ # except Exception as e: # pylint: disable=broad-except
+ # print("Exception during do_debug exception handling: " +
+ # e.__repr__())
+ # callers = reversed(callers)
+ # callers = '\n'.join(callers)
+ # msg = callers + "\n" + str(msg) + '\n'
getattr(logger, name)(msg)
diff --git a/qiskit_metal/_gui/utility/_toolbox_qt.py b/qiskit_metal/_gui/utility/_toolbox_qt.py
index e6e613d94..c974df572 100644
--- a/qiskit_metal/_gui/utility/_toolbox_qt.py
+++ b/qiskit_metal/_gui/utility/_toolbox_qt.py
@@ -12,11 +12,14 @@
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
"""This is a utility module used for qt."""
+# pylint: disable=invalid-name
-from PySide2 import QtCore, QtWidgets
-from PySide2.QtCore import QTimer
-from PySide2.QtGui import QColor
-from PySide2.QtWidgets import QDockWidget
+from types import MethodType
+
+# from PySide6 import QtCore, QtWidgets
+from PySide6.QtCore import QTimer
+from PySide6.QtGui import QColor
+from PySide6.QtWidgets import QDockWidget
__all__ = ['blend_colors']
@@ -44,27 +47,31 @@ def blend_colors(color1: QColor,
#------------------------------------------------------------------------------------------
-STYLE_HIGHLIGHT = r"""
+STYLE_HIGHLIGHT_ = r"""
QWidget {
outline: 3px solid red;
border: 3px solid red;
}"""
-def doShowHighlighWidget(self: QDockWidget,
- timeout=1500,
- STYLE_HIGHLIGHT=STYLE_HIGHLIGHT):
+def doShowHighlighWidget(self: QDockWidget, timeout=1500, style_highlight=None):
"""Highlight temporarily, raise, show the widget.
- Force resets the style at the component to None after a period.
+ Force resets the style at the component to None after a period.
"""
- self.setStyleSheet(STYLE_HIGHLIGHT)
+ if style_highlight is None:
+ style_highlight = STYLE_HIGHLIGHT_
+ self.setStyleSheet(style_highlight)
self.show()
self.raise_()
def doResetStyle(self: 'QDockWidget'):
+ """Reset the style of the widget."""
self.setStyleSheet('')
- self.doResetStyle = doResetStyle.__get__(self, type(self))
+ # Bind the method dynamically to the instance using MethodType
+ self.doResetStyle = MethodType(doResetStyle, self)
+
+ # self.doResetStyle = doResetStyle.__get__(self, type(self))
# monkey patch class instance:
# https://stackoverflow.com/questions/28127874/monkey-patching-python-an-instance-method
@@ -73,8 +80,8 @@ def doResetStyle(self: 'QDockWidget'):
### Alternative to doShowHighlighWidget:
-# from PySide2.QtWidgets import QFrame, QWidget
-# from PySide2 import QtCore
+# from PySide6.QtWidgets import QFrame, QWidget
+# from PySide6 import QtCore
# obj = gui.canvas
# frame = QFrame(obj.parent())
# frame.setGeometry(obj.frameGeometry())
@@ -93,6 +100,7 @@ def doResetStyle(self: 'QDockWidget'):
# # frame.setWindowFlags(QtCore.Qt.FramelessWindowHint)
# # frame.setAttribute(QtCore.Qt.WA_TranslucentBackground)
-# # Alternative see: https://stackoverflow.com/questions/58458323/how-to-use-qt-stylesheet-to-customize-only-partial-qwidget-border
+# # Alternative see:
+# https://stackoverflow.com/questions/58458323/how-to-use-qt-stylesheet-to-customize-only-partial-qwidget-border
#------------------------------------------------------------------------------------------
diff --git a/qiskit_metal/_gui/widgets/all_components/table_model_all_components.py b/qiskit_metal/_gui/widgets/all_components/table_model_all_components.py
index b9a75a3fe..d74541011 100644
--- a/qiskit_metal/_gui/widgets/all_components/table_model_all_components.py
+++ b/qiskit_metal/_gui/widgets/all_components/table_model_all_components.py
@@ -12,13 +12,13 @@
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
-import numpy as np
-from PySide2 import QtCore, QtWidgets
-from PySide2.QtCore import QAbstractTableModel, QModelIndex, Qt
-from PySide2.QtGui import QBrush, QColor, QFont, QIcon, QPixmap
-from PySide2.QtWidgets import QTableView
+# pylint: disable=invalid-name
-from ...utility._handle_qt_messages import slot_catch_error
+from PySide6 import QtCore
+from PySide6.QtCore import QAbstractTableModel, QModelIndex, Qt
+from PySide6.QtGui import QBrush, QColor, QFont, QIcon
+
+# from ...utility._handle_qt_messages import slot_catch_error
from ...utility._toolbox_qt import blend_colors
from typing import TYPE_CHECKING
@@ -84,9 +84,13 @@ def _create_timer(self):
def refresh(self):
"""Force refresh.
- Completly rebuild the model.
+ Completely rebuild the model.
"""
- self.modelReset.emit()
+ self.beginResetModel()
+ try:
+ self._row_count = self.rowCount()
+ finally:
+ self.endResetModel()
def refresh_auto(self):
"""Automatic refresh, update row count, view, etc."""
@@ -95,19 +99,25 @@ def refresh_auto(self):
# if the number of rows have changed
if self._row_count != new_count:
- #self.logger.info('Number of components changed')
+ # self.logger.info('Number of components changed')
+
+ # Wrap the reset logic in beginResetModel and endResetModel
+ self.beginResetModel()
+ try:
- # When a model is reset it should be considered that all
- # information previously retrieved from it is invalid.
- # This includes but is not limited to the rowCount() and
- # columnCount(), flags(), data retrieved through data(), and roleNames().
- # This will loose the current selection.
- self.modelReset.emit()
+ # When a model is reset it should be considered that all
+ # information previously retrieved from it is invalid.
+ # This includes but is not limited to the rowCount() and
+ # columnCount(), flags(), data retrieved through data(), and roleNames().
+ # This will loose the current selection.
+ # self.modelReset.emit()
+
+ self._row_count = new_count
+ finally:
+ self.endResetModel()
# for some reason the horizontal header is hidden even if i call this in init
self._tableView.horizontalHeader().show()
-
- self._row_count = new_count
self.update_view()
def update_view(self):
@@ -115,7 +125,7 @@ def update_view(self):
if self._tableView:
self._tableView.resizeColumnsToContents()
- def rowCount(self, parent: QModelIndex = None):
+ def rowCount(self, parent: QModelIndex = None): # pylint: disable=unused-argument
"""Returns the number of rows.
Args:
@@ -135,7 +145,7 @@ def rowCount(self, parent: QModelIndex = None):
self._tableView.show_placeholder_text()
return 0
- def columnCount(self, parent: QModelIndex = None):
+ def columnCount(self, parent: QModelIndex = None): # pylint: disable=unused-argument
"""Returns the number of columns.
Args:
@@ -248,5 +258,7 @@ def data(self, index: QModelIndex, role: int = Qt.DisplayRole):
elif role == Qt.ToolTipRole or role == Qt.StatusTipRole:
component = self.design.components[component_name]
- text = f"""Component name= "{component.name}" instance of class "{component.__class__.__name__}" from module "{component.__class__.__module__}" """
+ text = f"""Component name= "{component.name}" instance of """\
+ f"""class "{component.__class__.__name__}" from module""" \
+ f"""{component.__class__.__module__}" """
return text
diff --git a/qiskit_metal/_gui/widgets/all_components/table_view_all_components.py b/qiskit_metal/_gui/widgets/all_components/table_view_all_components.py
index 1ca330583..bc502e866 100644
--- a/qiskit_metal/_gui/widgets/all_components/table_view_all_components.py
+++ b/qiskit_metal/_gui/widgets/all_components/table_view_all_components.py
@@ -12,15 +12,14 @@
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
-from typing import TYPE_CHECKING
-from typing import List
+from typing import TYPE_CHECKING, List
-from PySide2 import QtCore, QtWidgets
-from PySide2.QtCore import QModelIndex, Qt, QTimer
-from PySide2.QtGui import QContextMenuEvent
-from PySide2.QtWidgets import (QInputDialog, QLabel, QLineEdit, QMenu,
- QMessageBox, QTableView, QVBoxLayout,
- QAbstractItemView)
+from PySide6 import QtCore, QtWidgets
+from PySide6.QtCore import QModelIndex, Qt, QTimer
+from PySide6.QtGui import QContextMenuEvent
+from PySide6.QtWidgets import (QAbstractItemView, QInputDialog, QLabel,
+ QLineEdit, QMenu, QMessageBox, QTableView,
+ QVBoxLayout)
from ...utility._handle_qt_messages import slot_catch_error
from ..bases.QWidget_PlaceholderText import QWidget_PlaceholderText
@@ -50,14 +49,18 @@ def __init__(self, parent: QtWidgets.QWidget):
QTableView.__init__(self, parent)
QWidget_PlaceholderText.__init__(
self,
- "No QComponents to show.\n\nCreate components from the QLibrary.")
+ "No QComponents to show.\n\nCreate components from the QLibrary.",
+ self)
+
+ # Connect signals
self.clicked.connect(self.viewClicked)
self.doubleClicked.connect(self.doDoubleClicked)
- # Handling selection dynamically
+ # Configure selection behavior
self.setSelectionMode(QAbstractItemView.ExtendedSelection)
self.setSelectionBehavior(QTableView.SelectRows)
+ # Apply styling
QTimer.singleShot(100, self.style2)
def style2(self):
diff --git a/qiskit_metal/_gui/widgets/bases/QWidget_PlaceholderText.py b/qiskit_metal/_gui/widgets/bases/QWidget_PlaceholderText.py
index 90251bbb0..2a4446d72 100644
--- a/qiskit_metal/_gui/widgets/bases/QWidget_PlaceholderText.py
+++ b/qiskit_metal/_gui/widgets/bases/QWidget_PlaceholderText.py
@@ -12,47 +12,45 @@
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
-from typing import TYPE_CHECKING
+from PySide6.QtCore import Qt
+from PySide6.QtWidgets import QLabel, QVBoxLayout, QWidget
-from PySide2 import QtCore, QtWidgets
-from PySide2.QtCore import QModelIndex, Qt
-from PySide2.QtGui import QContextMenuEvent
-from PySide2.QtWidgets import (QInputDialog, QLineEdit, QMenu, QMessageBox,
- QTableView, QLabel, QVBoxLayout, QWidget)
+class QWidget_PlaceholderText:
+ """QTableView or Tree with placeholder text if empty.
-class QWidget_PlaceholderText(QWidget):
- """QTableView or Tree with palceholder text if empty.
-
- This class extends the `QWidget` class.
+ This class acts as a mixin for placeholder text functionality.
"""
__placeholder_text = "The table is empty."
- def __init__(self, placeholder_text: str = None):
+ def __init__(self, placeholder_text: str = None, parent=None):
"""
Args:
- placeholder_text (str): Placeholder text.. Defaults to None.
+ placeholder_text (str): Placeholder text. Defaults to None.
+ parent: Parent widget.
"""
self._placeholder_text = placeholder_text if placeholder_text else self.__placeholder_text
+ self._placeholder_label = QLabel(self._placeholder_text, parent)
+ self.setup_placeholder_label(parent)
- self._placeholder_label = QLabel(self._placeholder_text, self)
- self.setup_placeholder_label()
-
- def setup_placeholder_label(self):
- """QComponents will be displayed here when you create them."""
+ def setup_placeholder_label(self, parent):
+ """Set up the placeholder label."""
+ # Update placeholder text
self.update_placeholder_text()
- if not self.layout():
- layout = QVBoxLayout()
- self.setLayout(layout)
+ # Ensure layout is present
+ if parent and not parent.layout():
+ layout = QVBoxLayout(parent)
+ parent.setLayout(layout)
- self.layout().addWidget(self._placeholder_label)
+ if parent:
+ parent.layout().addWidget(self._placeholder_label)
def update_placeholder_text(self, text=None):
"""Update the placeholder text to the given string.
Args:
- text (str): New placeholder text.. Defaults to None.
+ text (str): New placeholder text. Defaults to None.
"""
if text:
self._placeholder_text = text
@@ -60,24 +58,16 @@ def update_placeholder_text(self, text=None):
label = self._placeholder_label
label.setText(self._placeholder_text)
- # Text
+ # Styling
label.setWordWrap(True)
label.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
-
- # transperant
label.setAutoFillBackground(False)
label.setAttribute(Qt.WA_TranslucentBackground)
- # color PlaceholderText
- palette = self.palette()
- # This enum value has been introduced in Qt 5.12
- if hasattr(palette, 'PlaceholderText'):
- placeholder_color = palette.PlaceholderText
- else:
- placeholder_color = palette.WindowText
- color = palette.color(placeholder_color)
- palette.setColor(palette.Text, color)
- palette.setColor(palette.Text, color)
+ # Placeholder text color
+ palette = self._placeholder_label.palette()
+ color = palette.color(palette.ColorRole.WindowText) # Correct usage
+ palette.setColor(palette.ColorRole.Text, color)
label.setPalette(palette)
def show_placeholder_text(self):
@@ -86,4 +76,4 @@ def show_placeholder_text(self):
def hide_placeholder_text(self):
"""Hide the placeholder text."""
- self._placeholder_label.hide()
+ self._placeholder_label.hide()
\ No newline at end of file
diff --git a/qiskit_metal/_gui/widgets/bases/dict_tree_base.py b/qiskit_metal/_gui/widgets/bases/dict_tree_base.py
index 56931f66d..46f9937d0 100644
--- a/qiskit_metal/_gui/widgets/bases/dict_tree_base.py
+++ b/qiskit_metal/_gui/widgets/bases/dict_tree_base.py
@@ -12,20 +12,16 @@
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
"""Dict tree base."""
+# pylint: disable=invalid-name
import ast
-from pathlib import Path
from typing import Union, TYPE_CHECKING
-import numpy as np
-import PySide2
-from PySide2 import QtCore, QtGui, QtWidgets
-from PySide2.QtCore import QAbstractItemModel, QModelIndex, QTimer, Qt
-from PySide2.QtGui import QFont
-from PySide2.QtWidgets import (QAbstractItemView, QApplication, QFileDialog,
- QWidget, QTreeView, QLabel, QMainWindow,
- QMessageBox, QTabWidget)
-from .... import logger
+from PySide6 import QtCore
+from PySide6.QtCore import QAbstractItemModel, QModelIndex, QTimer, Qt
+from PySide6.QtGui import QFont
+from PySide6.QtWidgets import (QWidget, QTreeView)
+# from .... import logger
if TYPE_CHECKING:
from ....designs.design_base import QDesign
@@ -234,7 +230,7 @@ def __init__(self, parent: QWidget, gui: 'MetalGUI', view: QTreeView,
super().__init__(parent=parent)
self.logger = gui.logger
self._gui = gui
- self._rowCount = -1
+ self._row_count = -1
self._view = view
self.optionstype = child
if self.optionstype == 'component':
@@ -245,7 +241,7 @@ def __init__(self, parent: QWidget, gui: 'MetalGUI', view: QTreeView,
self.paths = []
self._start_timer()
- self.load()
+ self.load() # handles beginResetModel and endResetModel
@property
def gui(self):
@@ -277,10 +273,22 @@ def auto_refresh(self):
If so, completely rebuild the model and tree.
"""
# TODO: Check if new nodes have been added; if so, rebuild model.
- newRowCount = self.rowCount(self.createIndex(0, 0))
- if self._rowCount != newRowCount:
- self.modelReset.emit()
- self._rowCount = newRowCount
+ new_row_count = self.rowCount(self.createIndex(0, 0))
+ if self._row_count != new_row_count:
+ # Wrap the reset logic in beginResetModel and endResetModel
+ self.beginResetModel()
+ try:
+
+ # When a model is reset it should be considered that all
+ # information previously retrieved from it is invalid.
+ # This includes but is not limited to the rowCount() and
+ # columnCount(), flags(), data retrieved through data(), and roleNames().
+ # This will loose the current selection.
+ # self.modelReset.emit()
+
+ self._row_count = new_row_count
+ finally:
+ self.endResetModel()
if self._view:
self._view.autoresize_columns()
@@ -289,8 +297,14 @@ def refresh(self):
Completely rebuild the model and tree.
"""
- self.load() # rebuild the tree
- self.modelReset.emit()
+ # self.beginResetModel() # load handles refresh, cant nest
+ # try:
+ self.load(
+ ) # rebuild the tree; handles beginResetModel and endResetModel
+ parent_index = self.createIndex(0, 0, self.root)
+ self._row_count = self.rowCount(parent_index)
+ # finally:
+ # # self.endResetModel()
def getPaths(self, curdict: dict, curpath: list):
"""Recursively finds and saves all root-to-leaf paths in model."""
@@ -357,7 +371,7 @@ def rowCount(self, parent: QModelIndex):
return 0
return len(node)
- def columnCount(self, parent: QModelIndex):
+ def columnCount(self, parent: QModelIndex): # pylint: disable=unused-argument
"""Get the number of columns.
Args:
@@ -452,12 +466,13 @@ def setData(self,
lbl = node.label # option key
self.logger.info(
- f'Setting {self.optionstype} option {lbl:>10s}: old value={old_value}; new value={value};'
- )
+ f'Setting {self.optionstype} option {lbl:>10s}:'
+ f' old value={old_value}; new value={value};')
##### Parse value if not str ##############################
# Somewhat legacy code for extended handling of non string options
- # These days we tend to have all options be strings, so not so releavnt, but keep here for now
+ # These days we tend to have all options be strings,
+ # so not so releavnt, but keep here for now
# to allow extended use in te future
if not isinstance(old_value, str):
processed_value, used_ast = parse_param_from_str(
@@ -592,7 +607,7 @@ def parse_param_from_str(text):
try: # crude way to handle list and values
value = ast.literal_eval(text)
used_ast = True
- except Exception as exception:
+ except Exception: # as exception
pass
# print(exception)
return value, used_ast
diff --git a/qiskit_metal/_gui/widgets/bases/expanding_toolbar.py b/qiskit_metal/_gui/widgets/bases/expanding_toolbar.py
index a0be69c48..025c710be 100644
--- a/qiskit_metal/_gui/widgets/bases/expanding_toolbar.py
+++ b/qiskit_metal/_gui/widgets/bases/expanding_toolbar.py
@@ -12,9 +12,9 @@
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
-from PySide2 import QtCore, QtGui
-from PySide2.QtCore import Qt
-from PySide2.QtWidgets import QToolBar
+from PySide6 import QtCore, QtGui
+from PySide6.QtCore import Qt
+from PySide6.QtWidgets import QToolBar
import time
diff --git a/qiskit_metal/_gui/widgets/build_history/build_history_scroll_area.py b/qiskit_metal/_gui/widgets/build_history/build_history_scroll_area.py
index 293219002..c05ce65d6 100644
--- a/qiskit_metal/_gui/widgets/build_history/build_history_scroll_area.py
+++ b/qiskit_metal/_gui/widgets/build_history/build_history_scroll_area.py
@@ -1,4 +1,4 @@
-from PySide2.QtWidgets import (QLabel, QScrollArea, QVBoxLayout, QLabel,
+from PySide6.QtWidgets import (QLabel, QScrollArea, QVBoxLayout, QLabel,
QGroupBox)
from typing import List
from .build_history_scroll_area_ui import Ui_BuildHistory
diff --git a/qiskit_metal/_gui/widgets/build_history/build_history_scroll_area_ui.py b/qiskit_metal/_gui/widgets/build_history/build_history_scroll_area_ui.py
index 72d69b961..c95d5f723 100644
--- a/qiskit_metal/_gui/widgets/build_history/build_history_scroll_area_ui.py
+++ b/qiskit_metal/_gui/widgets/build_history/build_history_scroll_area_ui.py
@@ -4,11 +4,11 @@
# licensing of './widgets/build_history/build_history_scroll_area_ui.ui' applies.
#
# Created: Sat Jun 19 22:02:31 2021
-# by: pyside2-uic running on PySide2 5.13.2
+# by: pyside6-uic running on PySide2 5.13.2
#
# WARNING! All changes made in this file will be lost!
-from PySide2 import QtCore, QtGui, QtWidgets
+from PySide6 import QtCore, QtGui, QtWidgets
class Ui_BuildHistory(object):
diff --git a/qiskit_metal/_gui/widgets/create_component_window/model_view/tree_delegate_param_entry.py b/qiskit_metal/_gui/widgets/create_component_window/model_view/tree_delegate_param_entry.py
index be2cd6d7d..d946c2dcd 100644
--- a/qiskit_metal/_gui/widgets/create_component_window/model_view/tree_delegate_param_entry.py
+++ b/qiskit_metal/_gui/widgets/create_component_window/model_view/tree_delegate_param_entry.py
@@ -15,8 +15,8 @@
Delegate for Param Entry Window's MVD
"""
-from PySide2.QtCore import QAbstractItemModel, QModelIndex, Qt
-from PySide2.QtWidgets import QItemDelegate, QStyleOptionViewItem, QWidget
+from PySide6.QtCore import QAbstractItemModel, QModelIndex, Qt
+from PySide6.QtWidgets import QItemDelegate, QStyleOptionViewItem, QWidget
from qiskit_metal._gui.widgets.create_component_window.model_view.tree_model_param_entry import TreeModelParamEntry # pylint: disable=line-too-long
diff --git a/qiskit_metal/_gui/widgets/create_component_window/model_view/tree_model_param_entry.py b/qiskit_metal/_gui/widgets/create_component_window/model_view/tree_model_param_entry.py
index b1f1ca593..766a506d5 100644
--- a/qiskit_metal/_gui/widgets/create_component_window/model_view/tree_model_param_entry.py
+++ b/qiskit_metal/_gui/widgets/create_component_window/model_view/tree_model_param_entry.py
@@ -22,10 +22,10 @@
from typing import Union, TYPE_CHECKING, Any
import numpy as np
-from PySide2 import QtCore
-from PySide2.QtCore import QAbstractItemModel, QModelIndex, QTimer, Qt
-from PySide2.QtGui import QFont
-from PySide2.QtWidgets import (QComboBox, QTreeView, QWidget)
+from PySide6 import QtCore
+from PySide6.QtCore import QAbstractItemModel, QModelIndex, QTimer, Qt
+from PySide6.QtGui import QFont
+from PySide6.QtWidgets import (QComboBox, QTreeView, QWidget)
from addict import Dict
if TYPE_CHECKING:
@@ -376,7 +376,7 @@ def __init__(self,
design (QDesign): Current design using the model
"""
super().__init__(parent=parent)
- self._rowCount = -1 # pylint: disable=invalid-name
+ self._row_count = -1 # pylint: disable=invalid-name
self.root = BranchNode('')
self.view = view
self._design = design
@@ -497,10 +497,22 @@ def auto_refresh(self):
completely rebuild the model and tree.
"""
# TODO: Check if new nodes have been added; if so, rebuild model.
- newRowCount = self.rowCount(self.createIndex(0, 0)) # pylint: disable=invalid-name
- if self._rowCount != newRowCount:
- self.modelReset.emit()
- self._rowCount = newRowCount
+ new_row_count = self.rowCount(self.createIndex(0, 0)) # pylint: disable=invalid-name
+ if self._row_count != new_row_count:
+ # Wrap the reset logic in beginResetModel and endResetModel
+ self.beginResetModel()
+ try:
+
+ # When a model is reset it should be considered that all
+ # information previously retrieved from it is invalid.
+ # This includes but is not limited to the rowCount() and
+ # columnCount(), flags(), data retrieved through data(), and roleNames().
+ # This will loose the current selection.
+ # self.modelReset.emit()
+
+ self._row_count = new_row_count
+ finally:
+ self.endResetModel()
def getPaths(self, curdict: OrderedDict, curpath: list): # pylint: disable=invalid-name
"""Recursively finds and saves all root-to-leaf paths in model"""
diff --git a/qiskit_metal/_gui/widgets/create_component_window/model_view/tree_view_param_entry.py b/qiskit_metal/_gui/widgets/create_component_window/model_view/tree_view_param_entry.py
index f893da68a..8c602d032 100644
--- a/qiskit_metal/_gui/widgets/create_component_window/model_view/tree_view_param_entry.py
+++ b/qiskit_metal/_gui/widgets/create_component_window/model_view/tree_view_param_entry.py
@@ -15,9 +15,9 @@
Tree view for Param Entry Window
"""
-from PySide2 import QtGui, QtWidgets
-from PySide2.QtCore import QModelIndex
-from PySide2.QtWidgets import QTreeView
+from PySide6 import QtGui, QtWidgets
+from PySide6.QtCore import QModelIndex
+from PySide6.QtWidgets import QTreeView
class TreeViewParamEntry(QTreeView):
diff --git a/qiskit_metal/_gui/widgets/create_component_window/parameter_entry_window.py b/qiskit_metal/_gui/widgets/create_component_window/parameter_entry_window.py
index 1e5628387..bef043d18 100644
--- a/qiskit_metal/_gui/widgets/create_component_window/parameter_entry_window.py
+++ b/qiskit_metal/_gui/widgets/create_component_window/parameter_entry_window.py
@@ -41,10 +41,10 @@
from typing import TYPE_CHECKING, Union, Type
import numpy as np
-from PySide2 import QtGui, QtWidgets
-from PySide2.QtCore import Qt
-from PySide2.QtWidgets import QDockWidget, QWidget
-from PySide2.QtWidgets import (QMainWindow, QMessageBox)
+from PySide6 import QtGui, QtWidgets
+from PySide6.QtCore import Qt
+from PySide6.QtWidgets import QDockWidget, QWidget
+from PySide6.QtWidgets import (QMainWindow, QMessageBox)
from qiskit_metal import designs
from qiskit_metal.qlibrary.core import QComponent
diff --git a/qiskit_metal/_gui/widgets/create_component_window/parameter_entry_window_ui.py b/qiskit_metal/_gui/widgets/create_component_window/parameter_entry_window_ui.py
index 84c5a6432..8b4de5e45 100644
--- a/qiskit_metal/_gui/widgets/create_component_window/parameter_entry_window_ui.py
+++ b/qiskit_metal/_gui/widgets/create_component_window/parameter_entry_window_ui.py
@@ -4,11 +4,11 @@
# licensing of './widgets/create_component_window/parameter_entry_window_ui.ui' applies.
#
# Created: Sat Jun 19 22:02:30 2021
-# by: pyside2-uic running on PySide2 5.13.2
+# by: pyside6-uic running on PySide2 5.13.2
#
# WARNING! All changes made in this file will be lost!
-from PySide2 import QtCore, QtGui, QtWidgets
+from PySide6 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
diff --git a/qiskit_metal/_gui/widgets/edit_component/component_widget.py b/qiskit_metal/_gui/widgets/edit_component/component_widget.py
index cb4f9c360..e7f82e710 100644
--- a/qiskit_metal/_gui/widgets/edit_component/component_widget.py
+++ b/qiskit_metal/_gui/widgets/edit_component/component_widget.py
@@ -19,11 +19,11 @@
from typing import TYPE_CHECKING, Union
import numpy as np
-import PySide2
-from PySide2 import QtCore, QtGui, QtWidgets
-from PySide2.QtCore import QAbstractTableModel, QModelIndex, Qt
-from PySide2.QtGui import QFont, QColor
-from PySide2.QtWidgets import (QAbstractItemView, QApplication, QFileDialog,
+import PySide6
+from PySide6 import QtCore, QtGui, QtWidgets
+from PySide6.QtCore import QAbstractTableModel, QModelIndex, Qt
+from PySide6.QtGui import QFont, QColor
+from PySide6.QtWidgets import (QAbstractItemView, QApplication, QFileDialog,
QLabel, QMainWindow, QMessageBox, QTabWidget)
from .... import logger
@@ -137,7 +137,6 @@ def create_QTextDocument(doc: QtWidgets.QTextEdit) -> QtGui.QTextDocument:
font.setStyleHint(QFont.Arial)
else:
font.setStyleHint(QFont.Courier)
- font.setFamily("Courier")
document.setDefaultFont(font)
return document
diff --git a/qiskit_metal/_gui/widgets/edit_component/table_model_options.py b/qiskit_metal/_gui/widgets/edit_component/table_model_options.py
index 1ab0d6c14..209931b3e 100644
--- a/qiskit_metal/_gui/widgets/edit_component/table_model_options.py
+++ b/qiskit_metal/_gui/widgets/edit_component/table_model_options.py
@@ -18,9 +18,9 @@
from inspect import getfile, signature
from pathlib import Path
from typing import TYPE_CHECKING, Union
-from PySide2 import QtCore, QtGui, QtWidgets
-from PySide2.QtCore import QAbstractTableModel, QModelIndex, Qt
-from PySide2.QtGui import QFont
+from PySide6 import QtCore, QtGui, QtWidgets
+from PySide6.QtCore import QAbstractTableModel, QModelIndex, Qt
+from PySide6.QtGui import QFont
__all__ = ['parse_param_from_str']
diff --git a/qiskit_metal/_gui/widgets/edit_component/table_view_options.py b/qiskit_metal/_gui/widgets/edit_component/table_view_options.py
index 212fe4749..4533fc52a 100644
--- a/qiskit_metal/_gui/widgets/edit_component/table_view_options.py
+++ b/qiskit_metal/_gui/widgets/edit_component/table_view_options.py
@@ -15,9 +15,9 @@
from typing import TYPE_CHECKING
-from PySide2 import QtCore, QtWidgets
-from PySide2.QtCore import Qt, QTimer
-from PySide2.QtWidgets import QTableView, QAbstractItemView
+from PySide6 import QtCore, QtWidgets
+from PySide6.QtCore import Qt, QTimer
+from PySide6.QtWidgets import QTableView, QAbstractItemView
from ..bases.QWidget_PlaceholderText import QWidget_PlaceholderText
diff --git a/qiskit_metal/_gui/widgets/edit_component/tree_model_options.py b/qiskit_metal/_gui/widgets/edit_component/tree_model_options.py
index e3ff37e77..6beb653a7 100644
--- a/qiskit_metal/_gui/widgets/edit_component/tree_model_options.py
+++ b/qiskit_metal/_gui/widgets/edit_component/tree_model_options.py
@@ -14,9 +14,9 @@
"""Tree model for component options menu."""
from typing import TYPE_CHECKING
-from PySide2.QtCore import QModelIndex, Qt
-from PySide2.QtGui import QFont
-from PySide2.QtWidgets import QTreeView, QWidget
+from PySide6.QtCore import QModelIndex, Qt
+from PySide6.QtGui import QFont
+from PySide6.QtWidgets import QTreeView, QWidget
from ..bases.dict_tree_base import LeafNode, BranchNode, QTreeModel_Base, parse_param_from_str
if TYPE_CHECKING:
diff --git a/qiskit_metal/_gui/widgets/edit_component/tree_view_options.py b/qiskit_metal/_gui/widgets/edit_component/tree_view_options.py
index 63abf492f..7fff3f696 100644
--- a/qiskit_metal/_gui/widgets/edit_component/tree_view_options.py
+++ b/qiskit_metal/_gui/widgets/edit_component/tree_view_options.py
@@ -15,9 +15,9 @@
from typing import TYPE_CHECKING
-from PySide2 import QtCore, QtWidgets
-from PySide2.QtCore import Qt, QTimer
-from PySide2.QtWidgets import QTreeView, QAbstractItemView
+from PySide6 import QtCore, QtWidgets
+from PySide6.QtCore import Qt, QTimer
+from PySide6.QtWidgets import QTreeView, QAbstractItemView
from ..bases.QWidget_PlaceholderText import QWidget_PlaceholderText
diff --git a/qiskit_metal/_gui/widgets/log_widget/log_metal.py b/qiskit_metal/_gui/widgets/log_widget/log_metal.py
index afe8d8680..0a0997832 100644
--- a/qiskit_metal/_gui/widgets/log_widget/log_metal.py
+++ b/qiskit_metal/_gui/widgets/log_widget/log_metal.py
@@ -23,9 +23,10 @@
import random
from pathlib import Path
-from PySide2 import QtGui
-from PySide2.QtCore import Qt
-from PySide2.QtWidgets import QAction, QDockWidget, QTextEdit
+from PySide6 import QtGui
+from PySide6.QtCore import Qt
+from PySide6.QtGui import QAction
+from PySide6.QtWidgets import QDockWidget, QTextEdit
from .... import Dict, __version__, config
from ...utility._handle_qt_messages import slot_catch_error
diff --git a/qiskit_metal/_gui/widgets/plot_widget/plot_window.py b/qiskit_metal/_gui/widgets/plot_widget/plot_window.py
index 74869059a..7b2d920f0 100644
--- a/qiskit_metal/_gui/widgets/plot_widget/plot_window.py
+++ b/qiskit_metal/_gui/widgets/plot_widget/plot_window.py
@@ -21,8 +21,8 @@
from typing import TYPE_CHECKING
-from PySide2 import QtWidgets
-from PySide2.QtWidgets import (QApplication, QFileDialog, QLabel, QMainWindow,
+from PySide6 import QtWidgets
+from PySide6.QtWidgets import (QApplication, QFileDialog, QLabel, QMainWindow,
QMessageBox)
from ... import config
diff --git a/qiskit_metal/_gui/widgets/qlibrary_display/delegate_qlibrary.py b/qiskit_metal/_gui/widgets/qlibrary_display/delegate_qlibrary.py
index be6650511..2f87ed13d 100644
--- a/qiskit_metal/_gui/widgets/qlibrary_display/delegate_qlibrary.py
+++ b/qiskit_metal/_gui/widgets/qlibrary_display/delegate_qlibrary.py
@@ -19,9 +19,9 @@
import inspect
import os
-from PySide2.QtCore import QAbstractItemModel, QAbstractProxyModel, QModelIndex, Signal
-from PySide2.QtGui import QPainter
-from PySide2.QtWidgets import QItemDelegate, QStyle, QStyleOptionViewItem, QWidget
+from PySide6.QtCore import QAbstractItemModel, QAbstractProxyModel, QModelIndex, Signal
+from PySide6.QtGui import QPainter
+from PySide6.QtWidgets import QItemDelegate, QStyle, QStyleOptionViewItem, QWidget
from qiskit_metal._gui.widgets.qlibrary_display.file_model_qlibrary import QFileSystemLibraryModel
from qiskit_metal.toolbox_metal.exceptions import QLibraryGUIException
diff --git a/qiskit_metal/_gui/widgets/qlibrary_display/file_model_qlibrary.py b/qiskit_metal/_gui/widgets/qlibrary_display/file_model_qlibrary.py
index ea6d9423e..5ee1dd51e 100644
--- a/qiskit_metal/_gui/widgets/qlibrary_display/file_model_qlibrary.py
+++ b/qiskit_metal/_gui/widgets/qlibrary_display/file_model_qlibrary.py
@@ -18,9 +18,9 @@
import os
import typing
from pathlib import Path
-from PySide2.QtCore import QModelIndex, QTimeZone, Qt, QSize
-from PySide2.QtGui import QIcon, QPixmap
-from PySide2.QtWidgets import QFileSystemModel
+from PySide6.QtCore import QModelIndex, QTimeZone, Qt, QSize
+from PySide6.QtGui import QIcon, QPixmap
+from PySide6.QtWidgets import QFileSystemModel
from qiskit_metal._gui.utility.utils import findProperty
diff --git a/qiskit_metal/_gui/widgets/qlibrary_display/proxy_model_qlibrary.py b/qiskit_metal/_gui/widgets/qlibrary_display/proxy_model_qlibrary.py
index c8e03830f..0a88cbebc 100644
--- a/qiskit_metal/_gui/widgets/qlibrary_display/proxy_model_qlibrary.py
+++ b/qiskit_metal/_gui/widgets/qlibrary_display/proxy_model_qlibrary.py
@@ -14,11 +14,12 @@
"""
Proxy Model to clean display of QComponents in Library tab
"""
+# pylint: disable=invalid-name
import typing
-from PySide2.QtCore import QModelIndex, QSortFilterProxyModel, Qt, QSize
-from PySide2.QtWidgets import QWidget, QFileSystemModel
+from PySide6.QtCore import QModelIndex, QSortFilterProxyModel, Qt
+from PySide6.QtWidgets import QFileSystemModel, QWidget
class LibraryFileProxyModel(QSortFilterProxyModel):
@@ -38,7 +39,9 @@ def __init__(self, parent: QWidget = None):
# (Aren't hidden (begin w/ .), don't begin with __init__, don't begin with _template, etc. AND end in .py) OR (don't begin with __pycache__ and don't have a '.' in the name # pylint: disable=line-too-long
# (QComponent files) OR (Directories)
self.accepted_files__regex = r"(^((?!\.))(?!base)(?!__init__)(?!_template)(?!_parsed)(?!__pycache__).*\.py)|(?!__pycache__)(^([^.]+)$)" # pylint: disable=line-too-long
- self.setFilterRegExp(self.accepted_files__regex)
+ self.beginResetModel()
+ self.setFilterRegularExpression(self.accepted_files__regex)
+ self.endResetModel()
self.filter_text = ""
def filterAcceptsColumn(
@@ -78,11 +81,11 @@ def filterAcceptsRow(
relativeFilename] if relativeFilename in nameCache else None
#fi = source_model.fileInfo(index)
- if displayName != None:
+ if displayName is not None:
found = (self.filter_text in relativeFilename) or (self.filter_text
in displayName)
else:
- found = (self.filter_text in relativeFilename)
+ found = self.filter_text in relativeFilename
accept = (not relativeFilename.startswith("_")) and found
return accept
@@ -101,6 +104,10 @@ def data(self,
# allow editable
if role == Qt.EditRole:
- return self.data(index, Qt.DisplayRole)
+ self.beginResetModel()
+ try:
+ return self.data(index, Qt.DisplayRole)
+ finally:
+ self.endResetModel()
return super().data(index, role)
diff --git a/qiskit_metal/_gui/widgets/qlibrary_display/tree_view_qlibrary.py b/qiskit_metal/_gui/widgets/qlibrary_display/tree_view_qlibrary.py
index 80ab0d4ca..be79b98e1 100644
--- a/qiskit_metal/_gui/widgets/qlibrary_display/tree_view_qlibrary.py
+++ b/qiskit_metal/_gui/widgets/qlibrary_display/tree_view_qlibrary.py
@@ -15,9 +15,9 @@
Tree view for Param Entry Window
"""
-from PySide2 import QtCore, QtGui, QtWidgets
-from PySide2.QtCore import QModelIndex, Signal
-from PySide2.QtWidgets import QTreeView, QWidget
+from PySide6 import QtCore, QtGui, QtWidgets
+from PySide6.QtCore import QModelIndex, Signal
+from PySide6.QtWidgets import QTreeView, QWidget
from qiskit_metal._gui.widgets.qlibrary_display.proxy_model_qlibrary import LibraryFileProxyModel
from qiskit_metal.toolbox_metal.exceptions import QLibraryGUIException
diff --git a/qiskit_metal/_gui/widgets/variable_table/add_delete_table_ui.py b/qiskit_metal/_gui/widgets/variable_table/add_delete_table_ui.py
index 266f73fb4..e945b09a6 100644
--- a/qiskit_metal/_gui/widgets/variable_table/add_delete_table_ui.py
+++ b/qiskit_metal/_gui/widgets/variable_table/add_delete_table_ui.py
@@ -4,11 +4,11 @@
# licensing of './widgets/variable_table/add_delete_table_ui.ui' applies.
#
# Created: Sat Jun 19 22:02:31 2021
-# by: pyside2-uic running on PySide2 5.13.2
+# by: pyside6-uic running on PySide2 5.13.2
#
# WARNING! All changes made in this file will be lost!
-from PySide2 import QtCore, QtGui, QtWidgets
+from PySide6 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
diff --git a/qiskit_metal/_gui/widgets/variable_table/dialog_popup_ui.py b/qiskit_metal/_gui/widgets/variable_table/dialog_popup_ui.py
index e71d4f4a7..348d79790 100644
--- a/qiskit_metal/_gui/widgets/variable_table/dialog_popup_ui.py
+++ b/qiskit_metal/_gui/widgets/variable_table/dialog_popup_ui.py
@@ -4,11 +4,11 @@
# licensing of './widgets/variable_table/dialog_popup_ui.ui' applies.
#
# Created: Sat Jun 19 22:02:31 2021
-# by: pyside2-uic running on PySide2 5.13.2
+# by: pyside6-uic running on PySide2 5.13.2
#
# WARNING! All changes made in this file will be lost!
-from PySide2 import QtCore, QtGui, QtWidgets
+from PySide6 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
diff --git a/qiskit_metal/_gui/widgets/variable_table/prop_val_table_gui.py b/qiskit_metal/_gui/widgets/variable_table/prop_val_table_gui.py
index 256d9476e..d145a1b69 100644
--- a/qiskit_metal/_gui/widgets/variable_table/prop_val_table_gui.py
+++ b/qiskit_metal/_gui/widgets/variable_table/prop_val_table_gui.py
@@ -12,8 +12,8 @@
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
-from PySide2.QtCore import QModelIndex
-from PySide2.QtWidgets import QDialog, QMainWindow
+from PySide6.QtCore import QModelIndex
+from PySide6.QtWidgets import QDialog, QMainWindow
from .add_delete_table_ui import Ui_MainWindow
from .dialog_popup_ui import Ui_Dialog
diff --git a/qiskit_metal/_gui/widgets/variable_table/prop_val_table_model.py b/qiskit_metal/_gui/widgets/variable_table/prop_val_table_model.py
index 9b8c5eb91..c0152ab72 100644
--- a/qiskit_metal/_gui/widgets/variable_table/prop_val_table_model.py
+++ b/qiskit_metal/_gui/widgets/variable_table/prop_val_table_model.py
@@ -12,9 +12,9 @@
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
-from PySide2 import QtCore
-from PySide2.QtCore import QAbstractTableModel, QModelIndex, Qt
-from PySide2.QtGui import QFont
+from PySide6 import QtCore
+from PySide6.QtCore import QAbstractTableModel, QModelIndex, Qt
+from PySide6.QtGui import QFont
from .... import config
@@ -42,7 +42,7 @@ def __init__(self, design=None, gui=None, view: 'RightClickView' = None):
self._design = design
self._gui = gui
self._view = view
- self._rowCount = -1
+ self._row_count = -1
self._start_timer()
def set_design(self, design):
@@ -52,7 +52,8 @@ def set_design(self, design):
design (QDesign): The design
"""
self._design = design
- self.modelReset.emit()
+ # self.modelReset.emit()
+ self.auto_refresh()
# refresh table or something if needed
@property
@@ -75,10 +76,15 @@ def _start_timer(self):
def auto_refresh(self):
"""Do an automatic refresh."""
- newRowCount = self.rowCount(self)
- if self._rowCount != newRowCount:
- self.modelReset.emit()
- self._rowCount = newRowCount
+ new_row_count = self.rowCount(self)
+ if self._row_count != new_row_count:
+ # Wrap the reset logic in beginResetModel and endResetModel
+ self.beginResetModel()
+ try:
+ # self.modelReset.emit()
+ self._row_count = new_row_count
+ finally:
+ self.endResetModel()
if self._view:
self._view.resizeColumnsToContents()
diff --git a/qiskit_metal/_gui/widgets/variable_table/right_click_table_view.py b/qiskit_metal/_gui/widgets/variable_table/right_click_table_view.py
index 6c1a0b212..6b46ab09a 100644
--- a/qiskit_metal/_gui/widgets/variable_table/right_click_table_view.py
+++ b/qiskit_metal/_gui/widgets/variable_table/right_click_table_view.py
@@ -12,11 +12,11 @@
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
-from PySide2 import QtWidgets, QtCore, QtGui
-from PySide2.QtGui import QContextMenuEvent
-from PySide2.QtCore import QPoint, QModelIndex, QTimer
-from PySide2.QtWidgets import QInputDialog, QLineEdit, QTableView, QMenu, QMessageBox
-from PySide2.QtWidgets import QAbstractItemView
+from PySide6 import QtWidgets, QtCore, QtGui
+from PySide6.QtGui import QContextMenuEvent
+from PySide6.QtCore import QPoint, QModelIndex, QTimer
+from PySide6.QtWidgets import QInputDialog, QLineEdit, QTableView, QMenu, QMessageBox
+from PySide6.QtWidgets import QAbstractItemView
class RightClickView(QTableView):
diff --git a/qiskit_metal/renderers/renderer_gds/gds_renderer.py b/qiskit_metal/renderers/renderer_gds/gds_renderer.py
index c6e2e7670..6e39c38c0 100644
--- a/qiskit_metal/renderers/renderer_gds/gds_renderer.py
+++ b/qiskit_metal/renderers/renderer_gds/gds_renderer.py
@@ -16,21 +16,19 @@
from copy import deepcopy
from operator import itemgetter
-from typing import TYPE_CHECKING
-#from typing import Dict as Dict_
-from typing import Tuple, Union
-#from typing import List, Any, Iterable
-import math
+from typing import TYPE_CHECKING, Tuple, Union, Dict as DictType
+
import os
-from shapely.geometry import LineString
-#from pandas.api.types import is_numeric_dtype
+import math
+import pandas as pd
+import numpy as np
-import gdspy
-import geopandas
+import gdstk
import shapely
+import geopandas
+
from scipy.spatial import distance
-import pandas as pd
-import numpy as np
+from shapely.geometry import LineString
from qiskit_metal.renderers.renderer_base import QRenderer
from qiskit_metal.renderers.renderer_gds.make_cheese import Cheesing
@@ -40,9 +38,11 @@
from ... import Dict
from .. import config
+
if not config.is_building_docs():
from qiskit_metal.toolbox_python.utility_functions import can_write_to_path
- from qiskit_metal.toolbox_python.utility_functions import get_range_of_vertex_to_not_fillet
+ from qiskit_metal.toolbox_python.utility_functions import (
+ get_range_of_vertex_to_not_fillet,)
if TYPE_CHECKING:
# For linting typechecking, import modules that can't be loaded here under normal conditions.
@@ -51,6 +51,36 @@
from qiskit_metal.designs import QDesign
+def _new_cell(lib: "gdstk.Library", name: str,
+ overwrite_duplicate: bool) -> "gdstk.Cell":
+ """Helper to create or overwrite a gdstk cell in a library.
+
+ Args:
+ lib (gdstk.Library): Library to hold the new cell.
+ name (str): Name of the new cell.
+ overwrite_duplicate (bool): If True, remove existing cell of same name, then recreate.
+
+ Returns:
+ gdstk.Cell: The newly created cell.
+ """
+ existing = next((c for c in lib.cells if c.name == name), None)
+ if existing and overwrite_duplicate:
+ lib.remove(existing)
+ new_cell = gdstk.Cell(name)
+ lib.add(new_cell)
+ return new_cell
+
+
+def _rename_cell(cell: "gdstk.Cell", new_name: str) -> None:
+ """Helper to rename a gdstk cell.
+
+ Args:
+ cell (gdstk.Cell): Cell object to rename.
+ new_name (str): New name for the cell.
+ """
+ cell.name = new_name
+
+
class QGDSRenderer(QRenderer):
"""Extends QRenderer to export GDS formatted files. The methods which a
user will need for GDS export should be found within this class.
@@ -118,29 +148,26 @@ class QGDSRenderer(QRenderer):
# render_options.
# Type: Dict[str, str]
default_options = Dict(
-
# Before converting LINESTRING to FlexPath for GDS, check for fillet
# errors for LINESTRINGS in QGeometry in QGeometry due to short
# segments. If true, break up the LINESTRING so any segment which is
# shorter than the scaled-fillet by "fillet_scale_factor" will be
# separated so the short segment will not be fillet'ed.
- short_segments_to_not_fillet='True',
- check_short_segments_by_scaling_fillet='2.0',
-
+ short_segments_to_not_fillet="True",
+ check_short_segments_by_scaling_fillet="2.0",
# DO NOT MODIFY `gds_unit`. Gets overwritten by ``set_units``.
# gdspy unit is 1 meter. gds_units appear to ONLY be used during
# write_gds(). Note that gds_unit will be overwritten from the design
# units, during init().
+ # Moving to Gdstk, the default unit is 1 µm (10⁻⁶ m), but we overwrite this.
# WARNING: this cannot be changed since it is only used during the
# init once.
- gds_unit='1', # 1m
-
+ gds_unit="1", # 1m (one meter, if you want to set 1 um, set 1e-6)
# Implement creating a ground plane which is scaled from largest
# bounding box, then QGeometry which is marked as subtract will be
# removed from ground_plane. Then the balance of QGeometry will be
# placed placed in same layer as ground_plane.
- ground_plane='True',
-
+ ground_plane="True",
# By default, export_to_gds() will create a positive_mask for every
# chip and layer. Within the Dict, there needs to be an entry for each
# chip. Each chip has a list of layers that should export as a
@@ -148,7 +175,6 @@ class QGDSRenderer(QRenderer):
# for that layer. If user wants to export to a negative_mask for all
# layers, every layer_number MUST be in list.
negative_mask=Dict(main=[]),
-
# For the gds file, Show/Don't Show intermediate steps?
# If false, show the intermediate steps in the exported gds file.
# If true, show the geometries on either neg_datatype_fabricate or pos_datatype_fabricate.
@@ -156,8 +182,7 @@ class QGDSRenderer(QRenderer):
# delete for negative mask: TOP_main_#_NoCheese_99, TOP_main_#_one_hole
# delete for positive mask: TOP_main_#_NoCheese_99, TOP_main_#_one_hole,
# ground_main_#
- fabricate='False',
-
+ fabricate="False",
# corners: ('natural', 'miter', 'bevel', 'round', 'smooth',
# 'circular bend', callable, list)
# Type of joins. A callable must receive 6 arguments
@@ -165,8 +190,7 @@ class QGDSRenderer(QRenderer):
# the center and width of the path)
# and return a list of vertices that make the join.
# A list can be used to define the join for each parallel path.
- corners='circular bend',
-
+ corners="circular bend",
# tolerance > precision
# Precision used for gds lib, boolean operations and FlexPath should
# likely be kept the same. They can be different, but increases odds
@@ -177,95 +201,81 @@ class QGDSRenderer(QRenderer):
# to pop up if set precision too fine,
# but 1nm seems to be the finest precision we use anyhow.
# FOR NOW SPECIFY IN METERS.
- tolerance='0.00001', # 10.0 um
-
+ tolerance="0.00001", # 10.0 um
# With input from fab people, any of the weird artifacts
# (like unwanted gaps) that are less than 1nm in size can be ignored.
# They don't even show up in the fabricated masks.
# So, the precision of e-9 (so 1 nm) should be good as a default.
# FOR NOW SPECIFY IN METERS.
- precision='0.000000001', # 1.0 nm
-
+ precision="0.000000001", # 1.0 nm
# Since Qiskit Metal GUI, does not require a width for LineString, GDS,
# will provide a default value.
- width_LineString='10um',
-
+ width_LineString="10um",
# The file is expected to be in GDS format. The cell will be placed
# into gds Metal output without being edited. The name of the cell can
# be placed as options for a component, i.e. placing within a qubit.
# During export, the cell will NOT be edited, just imported.
- path_filename='../resources/Fake_Junctions.GDS',
-
+ path_filename="../resources/Fake_Junctions.GDS",
# For junction table, when cell from default_options.path_filename does
# not fit into linestring, QGDSRender will create two pads and add to
# junction to fill the location of lineString. The junction_pad_overlap
# is from the junction cell to the newly created pads.
- junction_pad_overlap='5um',
-
+ junction_pad_overlap="5um",
# Vertex limit for FlexPath
# max_points (integer) – If the number of points in the polygonal path
# boundary is greater than max_points, it will be fractured in smaller
# polygons with at most max_points each. If max_points is zero,
- # no fracture will occur. GDSpy uses 199 as the default. The historical
+ # no fracture will occur. GDSII used 199 as the default because the historical
# max value of vertices for a poly/path was 199 (fabrication equipment
# restrictions). The hard max limit that a GDSII file can
- # handle is 8191.
- max_points='199',
-
+ # handle is 8191. Gdstk allows arbitary numbers as does most modern software.
+ max_points="199",
# Cheesing is denoted by each chip and layer.
cheese=Dict(
- #Cheesing is NOT completed
- datatype='100',
-
+ # Cheesing is NOT completed
+ datatype="100",
# Expect to mostly cheese a square, but allow for expansion.
# 0 is rectangle, 1 is circle
- shape='0',
+ shape="0",
# rectangle
- cheese_0_x='25um',
- cheese_0_y='25um',
+ cheese_0_x="25um",
+ cheese_0_y="25um",
# circle
- cheese_1_radius='100um',
-
+ cheese_1_radius="100um",
# Identify which layers to view in gds output file, for each chip
view_in_file=Dict(main={1: True}),
-
# delta spacing between holes
- delta_x='100um',
- delta_y='100um',
-
+ delta_x="100um",
+ delta_y="100um",
# Keep a buffer around the perimeter of chip, that will
# not need cheesing.
- edge_nocheese='200um'),
-
+ edge_nocheese="200um",
+ ),
# Think of this as a keep-out region for cheesing.
no_cheese=Dict(
# For every layer, if there is a ground plane, do cheesing and
# place the output on the datatype number (sub-layer number)
- datatype='99',
- buffer='25um',
-
- #The styles of caps are specified by integer values:
+ datatype="99",
+ buffer="25um",
+ # The styles of caps are specified by integer values:
# 1 (round), 2 (flat), 3 (square).
- cap_style='2',
-
+ cap_style="2",
# The styles of joins between offset segments are specified by
# integer values:
# 1 (round), 2 (mitre), and 3 (bevel).
- join_style='2',
-
+ join_style="2",
# Identify which layers to view in gds output file, for each chip
view_in_file=Dict(main={1: True}),
),
-
# (float): Scale box of components to render.
# Should be greater than 1.0. For benefit of the GUI, keep this the
# last entry in the dict. GUI shows a note regarding bound_box.
- bounding_box_scale_x='1.2',
- bounding_box_scale_y='1.2',
+ bounding_box_scale_x="1.2",
+ bounding_box_scale_y="1.2",
)
"""Default options"""
- name = 'gds'
+ name = "gds"
"""Name"""
# When additional columns are added to QGeometry,
@@ -288,14 +298,16 @@ class QGDSRenderer(QRenderer):
element_table_data = dict(
# Cell_name must exist in gds file with: path_filename
- junction=dict(cell_name='my_other_junction'))
+ junction=dict(cell_name="my_other_junction"))
"""Element table data"""
- def __init__(self,
- design: 'QDesign',
- initiate=True,
- render_template: Dict = None,
- render_options: Dict = None):
+ def __init__(
+ self,
+ design: "QDesign",
+ initiate=True,
+ render_template: Dict = None,
+ render_options: Dict = None,
+ ):
"""Create a QRenderer for GDS interface: export and import.
Args:
@@ -309,35 +321,35 @@ def __init__(self,
Defaults to None.
"""
- super().__init__(design=design,
- initiate=initiate,
- render_template=render_template,
- render_options=render_options)
+ super().__init__(
+ design=design,
+ initiate=initiate,
+ render_template=render_template,
+ render_options=render_options,
+ )
- self.lib = None # type: gdspy.GdsLibrary
+ self.lib: Union[gdstk.Library, None] = None
self.new_gds_library()
- self.dict_bounds = Dict()
+ self.dict_bounds: DictType[str, Dict] = Dict()
# Updated each time export_to_gds() is called.
- self.chip_info = dict()
+ self.chip_info: DictType[str, dict] = dict()
# check the scale
self._check_bounding_box_scale()
# if imported, hold the path to file name, otherwise None.
- self.imported_junction_gds = None
+ self.imported_junction_gds: Union[str, None] = None # track only once
QGDSRenderer.load()
def _initiate_renderer(self):
- """Not used by the gds renderer at this time. only returns True.
- """
+ """Not used by the gds renderer at this time. Only returns True."""
return True
def _close_renderer(self):
- """Not used by the gds renderer at this time. only returns True.
- """
+ """Not used by the gds renderer at this time. Only returns True."""
return True
def render_design(self):
@@ -353,27 +365,22 @@ def _check_bounding_box_scale(self):
self.options.bounding_box_scale_y)
if bounding_box_scale_x < 1:
- self.options[
- 'bounding_box_scale_x'] = QGDSRenderer.default_options.bounding_box_scale_x
+ self.options["bounding_box_scale_x"] = (
+ QGDSRenderer.default_options.bounding_box_scale_x)
self.logger.warning(
- 'Expected float and number greater than or equal to'
- ' 1.0 for bounding_box_scale_x. User'
- f'provided bounding_box_scale_x = {bounding_box_scale_x}'
- ', using default_options.bounding_box_scale_x.')
+ "Expected float and number greater than or equal to"
+ " 1.0 for bounding_box_scale_x. User"
+ f"provided bounding_box_scale_x = {bounding_box_scale_x}"
+ ", using default_options.bounding_box_scale_x.")
if bounding_box_scale_y < 1:
- self.options[
- 'bounding_box_scale_y'] = QGDSRenderer.default_options.bounding_box_scale_y
+ self.options["bounding_box_scale_y"] = (
+ QGDSRenderer.default_options.bounding_box_scale_y)
self.logger.warning(
- 'Expected float and number greater than or equal to 1.0 for '
- 'bounding_box_scale_y. User provided '
- f'bounding_box_scale_y = {bounding_box_scale_y}, '
- 'using default_options.bounding_box_scale_y.')
-
- @staticmethod
- def _clear_library():
- """Clear current library."""
- gdspy.current_library.cells.clear()
+ "Expected float and number greater than or equal to 1.0 for "
+ "bounding_box_scale_y. User provided "
+ f"bounding_box_scale_y = {bounding_box_scale_y}, "
+ "using default_options.bounding_box_scale_y.")
def _can_write_to_path(self, file: str) -> int:
"""Check if can write file.
@@ -384,11 +391,11 @@ def _can_write_to_path(self, file: str) -> int:
Returns:
int: 1 if access is allowed. Else returns 0, if access not given.
"""
- status, directory_name = can_write_to_path(file)
+ status, directory_name = can_write_to_path(file) # pylint: disable=possibly-used-before-assignment
if status:
return 1
- self.logger.warning('Not able to write to directory.'
+ self.logger.warning("Not able to write to directory."
f'File:"{file}" not written.'
f' Checked directory:"{directory_name}".')
return 0
@@ -398,7 +405,7 @@ def _update_units(self):
Warning: DOES NOT CHANGE THE CURRENT LIB
"""
- self.options['gds_unit'] = 1.0 / self.design.parse_value('1 meter')
+ self.options["gds_unit"] = 1.0 / self.design.parse_value("1 meter")
def _separate_subtract_shapes(self, chip_name: str, table_name: str,
table: geopandas.GeoSeries) -> None:
@@ -412,18 +419,17 @@ def _separate_subtract_shapes(self, chip_name: str, table_name: str,
table (geopandas.GeoSeries): Table with similar qgeometries.
"""
# pylint: disable=singleton-comparison
- subtract_true = table[table['subtract'] == True]
+ subtract_true = table[table["subtract"] == True]
- subtract_false = table[table['subtract'] == False]
+ subtract_false = table[table["subtract"] == False]
- setattr(self, f'{chip_name}_{table_name}_subtract_true', subtract_true)
- setattr(self, f'{chip_name}_{table_name}_subtract_false',
+ setattr(self, f"{chip_name}_{table_name}_subtract_true", subtract_true)
+ setattr(self, f"{chip_name}_{table_name}_subtract_false",
subtract_false)
@staticmethod
def _get_bounds(
- gs_table: geopandas.GeoDataFrame
- ) -> Tuple[float, float, float, float]:
+ gs_table: geopandas.GeoDataFrame,) -> Tuple[float, float, float, float]:
"""Get the bounds for all of the elements in gs_table.
Args:
@@ -458,10 +464,12 @@ def _inclusive_bound(all_bounds: list) -> tuple:
if len(all_bounds) == 0:
return (0.0, 0.0, 0.0, 0.0)
- inclusive_tuple = (min(all_bounds, key=itemgetter(0))[0],
- min(all_bounds, key=itemgetter(1))[1],
- max(all_bounds, key=itemgetter(2))[2],
- max(all_bounds, key=itemgetter(3))[3])
+ inclusive_tuple = (
+ min(all_bounds, key=itemgetter(0))[0],
+ min(all_bounds, key=itemgetter(1))[1],
+ max(all_bounds, key=itemgetter(2))[2],
+ max(all_bounds, key=itemgetter(3))[3],
+ )
return inclusive_tuple
@staticmethod
@@ -514,20 +522,22 @@ def _scale_max_bounds(self, chip_name: str,
center_x = (minx + maxx) / 2
center_y = (miny + maxy) / 2
- scaled_width = (maxx - minx) * \
- self.parse_value(self.options.bounding_box_scale_x)
- scaled_height = (maxy - miny) * \
- self.parse_value(self.options.bounding_box_scale_y)
+ scaled_width = (maxx - minx) * self.parse_value(
+ self.options.bounding_box_scale_x)
+ scaled_height = (maxy - miny) * self.parse_value(
+ self.options.bounding_box_scale_y)
# Scaled inclusive bounding box by self.options.bounding_box_scale_x
# and self.options.bounding_box_scale_y.
- scaled_box = (center_x - (.5 * scaled_width),
- center_y - (.5 * scaled_height),
- center_x + (.5 * scaled_width),
- center_y + (.5 * scaled_height))
+ scaled_box = (
+ center_x - (0.5 * scaled_width),
+ center_y - (0.5 * scaled_height),
+ center_x + (0.5 * scaled_width),
+ center_y + (0.5 * scaled_height),
+ )
- self.dict_bounds[chip_name]['scaled_box'] = scaled_box
- self.dict_bounds[chip_name]['inclusive_box'] = (minx, miny, maxx, maxy)
+ self.dict_bounds[chip_name]["scaled_box"] = scaled_box
+ self.dict_bounds[chip_name]["inclusive_box"] = (minx, miny, maxx, maxy)
return scaled_box, (minx, miny, maxx, maxy)
@@ -558,8 +568,8 @@ def _check_qcomps(self,
for qcomp in unique_qcomponents:
if qcomp not in self.design.name_to_id:
self.logger.warning(
- f'The component={qcomp} in highlight_qcomponents not'
- ' in QDesign. The GDS data not generated.')
+ f"The component={qcomp} in highlight_qcomponents not"
+ " in QDesign. The GDS data not generated.")
return unique_qcomponents, 1
# For Subtraction bounding box.
@@ -614,12 +624,12 @@ def _create_qgeometry_for_gds(self,
# put the QGeometry into GDS format.
# There can be more than one chip in QGeometry.
# They all export to one gds file.
- self.chip_info[chip_name]['all_subtract'] = []
- self.chip_info[chip_name]['all_no_subtract'] = []
+ self.chip_info[chip_name]["all_subtract"] = []
+ self.chip_info[chip_name]["all_no_subtract"] = []
self.dict_bounds[chip_name] = Dict()
- self.dict_bounds[chip_name]['gather'] = []
- self.dict_bounds[chip_name]['for_subtract'] = tuple()
+ self.dict_bounds[chip_name]["gather"] = []
+ self.dict_bounds[chip_name]["for_subtract"] = tuple()
all_table_subtracts = []
all_table_no_subtracts = []
@@ -630,33 +640,37 @@ def _create_qgeometry_for_gds(self,
table = self._get_table(table_name, unique_qcomponents,
chip_name)
- if table_name == 'junction':
- self.chip_info[chip_name]['junction'] = deepcopy(table)
+ if table_name == "junction":
+ self.chip_info[chip_name]["junction"] = deepcopy(table)
else:
# For every chip, and layer, separate the "subtract"
# and "no_subtract" elements and gather bounds.
# self.dict_bounds[chip_name] = list_bounds
self._gather_subtract_elements_and_bounds(
- chip_name, table_name, table, all_table_subtracts,
- all_table_no_subtracts)
+ chip_name,
+ table_name,
+ table,
+ all_table_subtracts,
+ all_table_no_subtracts,
+ )
# If list of QComponents provided, use the
# bounding_box_scale(x and y), otherwise use self._chips.
scaled_max_bound, max_bound = self._scale_max_bounds(
- chip_name, self.dict_bounds[chip_name]['gather'])
+ chip_name, self.dict_bounds[chip_name]["gather"])
if highlight_qcomponents:
- self.dict_bounds[chip_name]['for_subtract'] = scaled_max_bound
+ self.dict_bounds[chip_name]["for_subtract"] = scaled_max_bound
else:
chip_box, status = self.design.get_x_y_for_chip(chip_name)
if status == 0:
- self.dict_bounds[chip_name]['for_subtract'] = chip_box
+ self.dict_bounds[chip_name]["for_subtract"] = chip_box
else:
- self.dict_bounds[chip_name]['for_subtract'] = max_bound
+ self.dict_bounds[chip_name]["for_subtract"] = max_bound
self.logger.warning(
- f'design.get_x_y_for_chip() did NOT return a good '
- f'code for chip={chip_name},for ground subtraction-box'
- f' using the size calculated from QGeometry, '
- f'({max_bound}) will be used. ')
+ f"design.get_x_y_for_chip() did NOT return a good "
+ f"code for chip={chip_name},for ground subtraction-box"
+ f" using the size calculated from QGeometry, "
+ f"({max_bound}) will be used. ")
if is_true(self.options.ground_plane):
self._handle_ground_plane(chip_name, all_table_subtracts,
all_table_no_subtracts)
@@ -695,38 +709,38 @@ def _handle_ground_plane(self, chip_name: str, all_table_subtracts: list,
copy_no_subtract = deepcopy(all_table_no_subtracts)
for item in copy_subtract:
- item.drop(item.index[item['layer'] != chip_layer], inplace=True)
+ item.drop(item.index[item["layer"] != chip_layer], inplace=True)
for item_no in copy_no_subtract:
- item_no.drop(item_no.index[item_no['layer'] != chip_layer],
+ item_no.drop(item_no.index[item_no["layer"] != chip_layer],
inplace=True)
- self.chip_info[chip_name][chip_layer][
- 'all_subtract_true'] = geopandas.GeoDataFrame(
- pd.concat(copy_subtract, ignore_index=False))
+ self.chip_info[chip_name][chip_layer]["all_subtract_true"] = (
+ geopandas.GeoDataFrame(
+ pd.concat(copy_subtract, ignore_index=False)))
- self.chip_info[chip_name][chip_layer][
- 'all_subtract_false'] = geopandas.GeoDataFrame(
- pd.concat(copy_no_subtract, ignore_index=False))
+ self.chip_info[chip_name][chip_layer]["all_subtract_false"] = (
+ geopandas.GeoDataFrame(
+ pd.concat(copy_no_subtract, ignore_index=False)))
self.chip_info[chip_name][chip_layer][
- 'all_subtract_true'].reset_index(inplace=True)
+ "all_subtract_true"].reset_index(inplace=True)
self.chip_info[chip_name][chip_layer][
- 'all_subtract_false'].reset_index(inplace=True)
+ "all_subtract_false"].reset_index(inplace=True)
if is_true(fix_short_segments):
self._fix_short_segments_within_table(chip_name, chip_layer,
- 'all_subtract_true')
+ "all_subtract_true")
self._fix_short_segments_within_table(chip_name, chip_layer,
- 'all_subtract_false')
+ "all_subtract_false")
self.chip_info[chip_name][chip_layer][
- 'q_subtract_true'] = self.chip_info[chip_name][chip_layer][
- 'all_subtract_true'].apply(self._qgeometry_to_gds, axis=1)
+ "q_subtract_true"] = self.chip_info[chip_name][chip_layer][
+ "all_subtract_true"].apply(self._qgeometry_to_gds, axis=1)
self.chip_info[chip_name][chip_layer][
- 'q_subtract_false'] = self.chip_info[chip_name][chip_layer][
- 'all_subtract_false'].apply(self._qgeometry_to_gds, axis=1)
+ "q_subtract_false"] = self.chip_info[chip_name][chip_layer][
+ "all_subtract_false"].apply(self._qgeometry_to_gds, axis=1)
# Handling Fillet issues.
@@ -748,7 +762,7 @@ def _fix_short_segments_within_table(self, chip_name: str, chip_layer: int,
# pylint: disable=too-many-locals
data_frame = self.chip_info[chip_name][chip_layer][
all_sub_true_or_false]
- df_fillet = data_frame[-data_frame['fillet'].isnull()]
+ df_fillet = data_frame[-data_frame["fillet"].isnull()]
if not df_fillet.empty:
# Don't edit the table when iterating through the rows.
@@ -773,8 +787,8 @@ def _fix_short_segments_within_table(self, chip_name: str, chip_layer: int,
df_copy = df_copy.drop(index=del_key)
for dummy_new_row, short_shape in the_shapes.items():
- orig_row['geometry'] = short_shape['line']
- orig_row['fillet'] = short_shape['fillet']
+ orig_row["geometry"] = short_shape["line"]
+ orig_row["fillet"] = short_shape["fillet"]
# Keep ignore_index=False, otherwise,
# the other del_key will not be found.
df_copy = df_copy.append(orig_row, ignore_index=False)
@@ -834,11 +848,11 @@ def _check_length(self, a_shapely: shapely.geometry.LineString,
shorter_lines = dict()
- idx_bad_fillet = sorted(all_idx_bad_fillet['reduced_idx'])
+ idx_bad_fillet = sorted(all_idx_bad_fillet["reduced_idx"])
status = len(idx_bad_fillet)
if status:
- midpoints = all_idx_bad_fillet['midpoints']
+ midpoints = all_idx_bad_fillet["midpoints"]
no_fillet_vertices = list()
fillet_vertices = list()
@@ -851,23 +865,23 @@ def _check_length(self, a_shapely: shapely.geometry.LineString,
# Every vertex should not be fillet'd
no_fillet_vertices = coords[start:len_coords]
shorter_lines[stop] = dict({
- 'line': LineString(no_fillet_vertices),
- 'fillet': float('NaN')
+ "line": LineString(no_fillet_vertices),
+ "fillet": float("NaN"),
})
else:
no_fillet_vertices = coords[start:stop + 1]
no_fillet_vertices.append(midpoints[stop])
shorter_lines[stop] = dict({
- 'line': LineString(no_fillet_vertices),
- 'fillet': float('NaN')
+ "line": LineString(no_fillet_vertices),
+ "fillet": float("NaN"),
})
elif idx == status - 1 and stop == len_coords - 1:
# The last segment
no_fillet_vertices = coords[start:stop + 1]
no_fillet_vertices.insert(0, midpoints[start - 1])
shorter_lines[stop] = dict({
- 'line': LineString(no_fillet_vertices),
- 'fillet': float('NaN')
+ "line": LineString(no_fillet_vertices),
+ "fillet": float("NaN")
})
else:
# Segment in between first and last segment.
@@ -875,8 +889,8 @@ def _check_length(self, a_shapely: shapely.geometry.LineString,
no_fillet_vertices.insert(0, midpoints[start - 1])
no_fillet_vertices.append(midpoints[stop])
shorter_lines[stop] = dict({
- 'line': LineString(no_fillet_vertices),
- 'fillet': float('NaN')
+ "line": LineString(no_fillet_vertices),
+ "fillet": float("NaN")
})
# Gather the fillet segments.
at_vertex = 0
@@ -888,15 +902,15 @@ def _check_length(self, a_shapely: shapely.geometry.LineString,
init_tuple = coords[0]
fillet_vertices = [init_tuple, midpoints[start - 1]]
shorter_lines[start] = dict({
- 'line': LineString(fillet_vertices),
- 'fillet': a_fillet
+ "line": LineString(fillet_vertices),
+ "fillet": a_fillet
})
if idx == 0 and start > 1:
fillet_vertices = coords[0:start]
fillet_vertices.append(midpoints[start - 1])
shorter_lines[start] = dict({
- 'line': LineString(fillet_vertices),
- 'fillet': a_fillet
+ "line": LineString(fillet_vertices),
+ "fillet": a_fillet
})
if idx == status - 1 and stop != len_coords - 1:
# Extra segment after the last no-fillet.
@@ -904,8 +918,8 @@ def _check_length(self, a_shapely: shapely.geometry.LineString,
fillet_vertices = coords[stop + 1:len_coords]
fillet_vertices.insert(0, midpoints[stop])
shorter_lines[len_coords] = dict({
- 'line': LineString(fillet_vertices),
- 'fillet': a_fillet
+ "line": LineString(fillet_vertices),
+ "fillet": a_fillet
})
elif idx == status - 1 and start == 0 and stop != len_coords - 1:
# At last tuple, and and start at first index,
@@ -913,8 +927,8 @@ def _check_length(self, a_shapely: shapely.geometry.LineString,
fillet_vertices = coords[stop + 1:len_coords]
fillet_vertices.insert(0, midpoints[stop])
shorter_lines[start] = dict({
- 'line': LineString(fillet_vertices),
- 'fillet': a_fillet
+ "line": LineString(fillet_vertices),
+ "fillet": a_fillet
})
elif idx == status - 1 and stop != len_coords - 1:
# At last tuple, and the stop is not last index of coords.
@@ -922,16 +936,16 @@ def _check_length(self, a_shapely: shapely.geometry.LineString,
fillet_vertices.insert(0, midpoints[at_vertex])
fillet_vertices.append(midpoints[start - 1])
shorter_lines[start] = dict({
- 'line': LineString(fillet_vertices),
- 'fillet': a_fillet
+ "line": LineString(fillet_vertices),
+ "fillet": a_fillet
})
# Extra segment after the last no-fillet.
fillet_vertices.clear()
fillet_vertices = coords[stop + 1:len_coords]
fillet_vertices.insert(0, midpoints[stop])
shorter_lines[len_coords] = dict({
- 'line': LineString(fillet_vertices),
- 'fillet': a_fillet
+ "line": LineString(fillet_vertices),
+ "fillet": a_fillet
})
else:
if (start - at_vertex) > 1:
@@ -939,8 +953,8 @@ def _check_length(self, a_shapely: shapely.geometry.LineString,
fillet_vertices.insert(0, midpoints[at_vertex])
fillet_vertices.append(midpoints[start - 1])
shorter_lines[start] = dict({
- 'line': LineString(fillet_vertices),
- 'fillet': a_fillet
+ "line": LineString(fillet_vertices),
+ "fillet": a_fillet
})
at_vertex = stop # Need to update for every loop.
else:
@@ -981,27 +995,30 @@ def _identify_vertex_not_to_fillet(self, coords: list, a_fillet: float,
# For now, DO NOT allow the user of GDS to provide the precision.
# user_precision = int(np.abs(np.log10(precision)))
- qdesign_precision = self.design.template_options.PRECISION
-
- all_idx_bad_fillet['reduced_idx'] = get_range_of_vertex_to_not_fillet(
- coords, a_fillet, qdesign_precision, add_endpoints=True)
-
- midpoints = list()
+ func = get_range_of_vertex_to_not_fillet # pylint: disable=possibly-used-before-assignment
+ all_idx_bad_fillet["reduced_idx"] = func(
+ coords,
+ a_fillet,
+ self.design.template_options.PRECISION,
+ add_endpoints=True)
midpoints = [
- QGDSRenderer._midpoint_xy(coords[idx - 1][0], coords[idx - 1][1],
- vertex2[0], vertex2[1])
+ self._midpoint_xy(coords[idx - 1][0], coords[idx - 1][1],
+ vertex2[0], vertex2[1])
for idx, vertex2 in enumerate(coords)
if idx > 0
]
- all_idx_bad_fillet['midpoints'] = midpoints
+ all_idx_bad_fillet["midpoints"] = midpoints
# Move data around to be useful for GDS
- def _gather_subtract_elements_and_bounds(self, chip_name: str,
- table_name: str,
- table: geopandas.GeoDataFrame,
- all_subtracts: list,
- all_no_subtracts: list):
+ def _gather_subtract_elements_and_bounds(
+ self,
+ chip_name: str,
+ table_name: str,
+ table: geopandas.GeoDataFrame,
+ all_subtracts: list,
+ all_no_subtracts: list,
+ ):
"""For every chip, and layer, separate the "subtract" and "no_subtract"
elements and gather bounds for all the elements in qgeometries. Use
format: f'{chip_name}_{table_name}s'.
@@ -1021,23 +1038,23 @@ def _gather_subtract_elements_and_bounds(self, chip_name: str,
bounds = tuple(self._get_bounds(table))
# Add the bounds of each table to list.
- self.dict_bounds[chip_name]['gather'].append(bounds)
+ self.dict_bounds[chip_name]["gather"].append(bounds)
if is_true(self.options.ground_plane):
self._separate_subtract_shapes(chip_name, table_name, table)
all_subtracts.append(
- getattr(self, f'{chip_name}_{table_name}_subtract_true'))
+ getattr(self, f"{chip_name}_{table_name}_subtract_true"))
all_no_subtracts.append(
- getattr(self, f'{chip_name}_{table_name}_subtract_false'))
+ getattr(self, f"{chip_name}_{table_name}_subtract_false"))
# Done because ground plane option may be false.
# This is not used anywhere currently.
# Keep this depreciated code.
# polys use gdspy.Polygon; paths use gdspy.LineString
- #q_geometries = table.apply(self._qgeometry_to_gds, axis=1)
- #setattr(self, f'{chip_name}_{table_name}s', q_geometries)
+ # q_geometries = table.apply(self._qgeometry_to_gds, axis=1)
+ # setattr(self, f'{chip_name}_{table_name}s', q_geometries)
def _get_table(self, table_name: str, unique_qcomponents: list,
chip_name: str) -> geopandas.GeoDataFrame:
@@ -1068,31 +1085,34 @@ def _get_table(self, table_name: str, unique_qcomponents: list,
]
# Remove QComponents which are not requested.
- table = table[table['component'].isin(highlight_id)]
+ table = table[table["component"].isin(highlight_id)]
- table = table[table['chip'] == chip_name]
+ table = table[table["chip"] == chip_name]
return table
# To export the data.
- def new_gds_library(self) -> gdspy.GdsLibrary:
+ def new_gds_library(self) -> "gdstk.Library":
"""Creates a new GDS Library. Deletes the old. Create a new GDS library
file. It can contains multiple cells.
Returns:
- gdspy.GdsLibrary: GDS library which can contain multiple cells.
+ gdstk.Library: GDS library which can contain multiple cells.
"""
self._update_units()
if self.lib:
- self._clear_library()
+ # Clear old cells from the library
+ for c in list(self.lib.cells):
+ self.lib.remove(c)
# Create a new GDS library file. It can contains multiple cells.
- self.lib = gdspy.GdsLibrary(
+ self.lib = gdstk.Library(
unit=float(self.parse_value(self.options.gds_unit)),
- precision=float(self.parse_value(self.options.precision)))
+ precision=float(self.parse_value(self.options.precision)),
+ )
return self.lib
@@ -1188,8 +1208,8 @@ def _check_either_cheese(self, chip: str, layer: int) -> int:
cheese_code = self._check_cheese(chip, layer)
if no_cheese_code == 0 or cheese_code == 0:
- self.logger.warning('Not able to get no_cheese_view_in_file or '
- 'cheese_view_in_file from self.options.')
+ self.logger.warning("Not able to get no_cheese_view_in_file or "
+ "cheese_view_in_file from self.options.")
code = 0
return code
if no_cheese_code == 1 and cheese_code == 1:
@@ -1207,14 +1227,14 @@ def _check_either_cheese(self, chip: str, layer: int) -> int:
if no_cheese_code == 3 or cheese_code == 3:
code = 5
self.logger.warning(
- f'Chip={chip} is not either in no_cheese_view_in_file '
- f'or cheese_view_in_file from self.options.')
+ f"Chip={chip} is not either in no_cheese_view_in_file "
+ f"or cheese_view_in_file from self.options.")
return code
if no_cheese_code == 4 or cheese_code == 4:
code = 6
self.logger.warning(
- f'layer={layer} is not in chip={chip} either in '
- f'no_cheese_view_in_file or cheese_view_in_file from self.options.'
+ f"layer={layer} is not in chip={chip} either in "
+ f"no_cheese_view_in_file or cheese_view_in_file from self.options."
)
return code
@@ -1240,14 +1260,28 @@ def _populate_cheese(self):
if status == 0:
minx, miny, maxx, maxy = chip_box
- self._cheese_based_on_shape(minx, miny, maxx, maxy,
- chip_name, chip_layer,
- cheese_sub_layer,
- nocheese_sub_layer)
-
- def _cheese_based_on_shape(self, minx: float, miny: float, maxx: float,
- maxy: float, chip_name: str, chip_layer: int,
- cheese_sub_layer: int, nocheese_sub_layer: int):
+ self._cheese_based_on_shape(
+ minx,
+ miny,
+ maxx,
+ maxy,
+ chip_name,
+ chip_layer,
+ cheese_sub_layer,
+ nocheese_sub_layer,
+ )
+
+ def _cheese_based_on_shape(
+ self,
+ minx: float,
+ miny: float,
+ maxx: float,
+ maxy: float,
+ chip_name: str,
+ chip_layer: int,
+ cheese_sub_layer: int,
+ nocheese_sub_layer: int,
+ ):
"""Instantiate class to do cheesing.
Args:
@@ -1267,9 +1301,9 @@ def _cheese_based_on_shape(self, minx: float, miny: float, maxx: float,
max_points = int(self.parse_value(self.options.max_points))
cheese_shape = int(self.parse_value(self.options.cheese.shape))
- all_nocheese = self.chip_info[chip_name][chip_layer]['no_cheese']
+ all_nocheese = self.chip_info[chip_name][chip_layer]["no_cheese"]
all_nocheese_gds = self.chip_info[chip_name][chip_layer][
- 'no_cheese_gds']
+ "no_cheese_gds"]
delta_x = float(self.parse_value(self.options.cheese.delta_x))
delta_y = float(self.parse_value(self.options.cheese.delta_y))
edge_nocheese = float(
@@ -1281,55 +1315,59 @@ def _cheese_based_on_shape(self, minx: float, miny: float, maxx: float,
if cheese_shape == 0:
cheese_x = float(self.parse_value(self.options.cheese.cheese_0_x))
cheese_y = float(self.parse_value(self.options.cheese.cheese_0_y))
- a_cheese = Cheesing(all_nocheese,
- all_nocheese_gds,
- self.lib,
- minx,
- miny,
- maxx,
- maxy,
- chip_name,
- edge_nocheese,
- chip_layer,
- is_neg_mask,
- cheese_sub_layer,
- nocheese_sub_layer,
- fab,
- self.logger,
- max_points,
- precision,
- cheese_shape=cheese_shape,
- shape_0_x=cheese_x,
- shape_0_y=cheese_y,
- delta_x=delta_x,
- delta_y=delta_y)
+ a_cheese = Cheesing(
+ all_nocheese,
+ all_nocheese_gds,
+ self.lib,
+ minx,
+ miny,
+ maxx,
+ maxy,
+ chip_name,
+ edge_nocheese,
+ chip_layer,
+ is_neg_mask,
+ cheese_sub_layer,
+ nocheese_sub_layer,
+ fab,
+ self.logger,
+ max_points,
+ precision,
+ cheese_shape=cheese_shape,
+ shape_0_x=cheese_x,
+ shape_0_y=cheese_y,
+ delta_x=delta_x,
+ delta_y=delta_y,
+ )
elif cheese_shape == 1:
cheese_radius = float(
self.parse_value(self.options.cheese.cheese_1_radius))
- a_cheese = Cheesing(all_nocheese,
- all_nocheese_gds,
- self.lib,
- minx,
- miny,
- maxx,
- maxy,
- chip_name,
- edge_nocheese,
- chip_layer,
- is_neg_mask,
- cheese_sub_layer,
- nocheese_sub_layer,
- fab,
- self.logger,
- max_points,
- precision,
- cheese_shape=cheese_shape,
- shape_1_radius=cheese_radius,
- delta_x=delta_x,
- delta_y=delta_y)
+ a_cheese = Cheesing(
+ all_nocheese,
+ all_nocheese_gds,
+ self.lib,
+ minx,
+ miny,
+ maxx,
+ maxy,
+ chip_name,
+ edge_nocheese,
+ chip_layer,
+ is_neg_mask,
+ cheese_sub_layer,
+ nocheese_sub_layer,
+ fab,
+ self.logger,
+ max_points,
+ precision,
+ cheese_shape=cheese_shape,
+ shape_1_radius=cheese_radius,
+ delta_x=delta_x,
+ delta_y=delta_y,
+ )
else:
self.logger.warning(
- f'The cheese_shape={cheese_shape} is unknown in QGDSRenderer.')
+ f"The cheese_shape={cheese_shape} is unknown in QGDSRenderer.")
a_cheese = None
if a_cheese is not None:
@@ -1352,7 +1390,6 @@ def _populate_no_cheese(self):
self.options.no_cheese.buffer))
sub_layer = int(self.parse_value(self.options.no_cheese.datatype))
lib = self.lib
-
fab = is_true(self.options.fabricate)
for chip_name, _ in self.chip_info.items():
@@ -1364,45 +1401,42 @@ def _populate_no_cheese(self):
if code in (1, 2, 3):
if len(self.chip_info[chip_name][chip_layer]
- ['all_subtract_true']) != 0:
-
+ ["all_subtract_true"]) != 0:
sub_df = self.chip_info[chip_name][chip_layer][
- 'all_subtract_true']
+ "all_subtract_true"]
no_cheese_multipolygon = self._cheese_buffer_maker(
sub_df, chip_name, no_cheese_buffer)
-
if no_cheese_multipolygon is not None:
self.chip_info[chip_name][chip_layer][
- 'no_cheese'] = no_cheese_multipolygon
- sub_layer = int(
- self.parse_value(
- self.options.no_cheese.datatype))
+ "no_cheese"] = no_cheese_multipolygon
all_nocheese_gds = self._multipolygon_to_gds(
no_cheese_multipolygon, chip_layer, sub_layer,
no_cheese_buffer)
self.chip_info[chip_name][chip_layer][
- 'no_cheese_gds'] = all_nocheese_gds
+ "no_cheese_gds"] = all_nocheese_gds
- # If fabricate.fab is true, then
- # do not put nocheese in gds file.
if self._check_no_cheese(
chip_name, chip_layer) == 1 and not fab:
no_cheese_subtract_cell_name = (
- f'TOP_{chip_name}_{chip_layer}'
- f'_NoCheese_{sub_layer}')
- no_cheese_cell = lib.new_cell(
- no_cheese_subtract_cell_name,
- overwrite_duplicate=True)
-
- no_cheese_cell.add(all_nocheese_gds)
-
- # Keep the cell out to layer, it becomes part of ground.
- chip_only_top_name = f'TOP_{chip_name}'
-
- if no_cheese_cell.get_bounding_box(
+ f"TOP_{chip_name}_{chip_layer}_NoCheese_{sub_layer}"
+ )
+ no_cheese_cell = _new_cell(
+ lib, no_cheese_subtract_cell_name, True)
+ for poly_el in all_nocheese_gds:
+ if isinstance(poly_el, list):
+ for sub_poly in poly_el:
+ no_cheese_cell.add(sub_poly)
+ else:
+ no_cheese_cell.add(poly_el)
+
+ chip_only_top_name = f"TOP_{chip_name}"
+ chip_only_top = next(
+ (c for c in lib.cells
+ if c.name == chip_only_top_name), None)
+ if chip_only_top and no_cheese_cell.bounding_box(
) is not None:
- lib.cells[chip_only_top_name].add(
- gdspy.CellReference(no_cheese_cell))
+ chip_only_top.add(
+ gdstk.Reference(no_cheese_cell))
else:
lib.remove(no_cheese_cell)
@@ -1433,13 +1467,13 @@ def _cheese_buffer_maker(
poly_sub_df = sub_df[sub_df.geometry.apply(
lambda x: isinstance(x, shapely.geometry.polygon.Polygon))]
- poly_sub_geo = poly_sub_df['geometry'].tolist()
+ poly_sub_geo = poly_sub_df["geometry"].tolist()
path_sub_df = sub_df[sub_df.geometry.apply(
lambda x: isinstance(x, shapely.geometry.linestring.LineString))]
- path_sub_geo = path_sub_df['geometry'].tolist()
- path_sub_width = path_sub_df['width'].tolist()
- #for n in range(len(path_sub_geo)):
+ path_sub_geo = path_sub_df["geometry"].tolist()
+ path_sub_width = path_sub_df["width"].tolist()
+ # for n in range(len(path_sub_geo)):
for index, _ in enumerate(path_sub_geo):
path_sub_geo[index] = path_sub_geo[index].buffer(
path_sub_width[index] / 2,
@@ -1451,7 +1485,7 @@ def _cheese_buffer_maker(
combo_shapely = draw.union(combo_list)
if not combo_shapely.is_empty:
- #Can return either Multipolygon or just one polygon.
+ # Can return either Multipolygon or just one polygon.
combo_shapely = combo_shapely.buffer(no_cheese_buffer,
cap_style=style_cap,
join_style=style_join)
@@ -1463,17 +1497,16 @@ def _cheese_buffer_maker(
if status == 0:
minx, miny, maxx, maxy = chip_box
c_minx, c_miny, c_maxx, c_maxy = combo_shapely.bounds
- if (c_minx < minx or c_miny < miny or c_maxx > maxx or
- c_maxy > maxy):
+ if c_minx < minx or c_miny < miny or c_maxx > maxx or c_maxy > maxy:
self.logger.warning(
- f'The bounding box for no-cheese is outside of chip size.\n'
- f'Bounding box for chip is {chip_box}.\n'
- f'Bounding box with no_cheese buffer is {combo_shapely.bounds}.'
+ f"The bounding box for no-cheese is outside of chip size.\n"
+ f"Bounding box for chip is {chip_box}.\n"
+ f"Bounding box with no_cheese buffer is {combo_shapely.bounds}."
)
else:
self.logger.warning(
- f'design.get_x_y_for_chip() did NOT return a good code for chip={chip_name},'
- f'for _cheese_buffer_maker. The chip boundary will not be tested.'
+ f"design.get_x_y_for_chip() did NOT return a good code for chip={chip_name},"
+ f"for _cheese_buffer_maker. The chip boundary will not be tested."
)
# The type of combo_shapely will be
@@ -1493,7 +1526,7 @@ def _get_rectangle_points(self, chip_name: str) -> Tuple[list, list]:
"""
layers_in_chip = self.design.qgeometry.get_all_unique_layers(chip_name)
- minx, miny, maxx, maxy = self.dict_bounds[chip_name]['for_subtract']
+ minx, miny, maxx, maxy = self.dict_bounds[chip_name]["for_subtract"]
rectangle_points = [(minx, miny), (maxx, miny), (maxx, maxy),
(minx, maxy)]
@@ -1519,11 +1552,11 @@ def _populate_poly_path_for_export(self):
lib = self.new_gds_library()
if is_true(self.options.ground_plane):
- all_chips_top_name = 'TOP'
+ all_chips_top_name = "TOP"
all_chips_top = lib.new_cell(all_chips_top_name,
overwrite_duplicate=True)
for chip_name, _ in self.chip_info.items():
- chip_only_top_name = f'TOP_{chip_name}'
+ chip_only_top_name = f"TOP_{chip_name}"
chip_only_top = lib.new_cell(chip_only_top_name,
overwrite_duplicate=True)
@@ -1531,51 +1564,77 @@ def _populate_poly_path_for_export(self):
chip_name)
for chip_layer in layers_in_chip:
- self._handle_photo_resist(lib, chip_only_top, chip_name,
- chip_layer, rectangle_points,
- precision, max_points)
+ self._handle_photo_resist(
+ lib,
+ chip_only_top,
+ chip_name,
+ chip_layer,
+ rectangle_points,
+ precision,
+ max_points,
+ )
# If junction table, import the cell and cell to chip_only_top
- if 'junction' in self.chip_info[chip_name]:
+ if "junction" in self.chip_info[chip_name]:
self._import_junctions_to_one_cell(chip_name, lib,
chip_only_top,
layers_in_chip)
# put all chips into TOP
if chip_only_top.get_bounding_box() is not None:
- all_chips_top.add(gdspy.CellReference(chip_only_top))
+ all_chips_top.add(gdstk.Reference(chip_only_top))
else:
lib.remove(chip_only_top)
- def _handle_photo_resist(self, lib: gdspy.GdsLibrary,
- chip_only_top: gdspy.library.Cell, chip_name: str,
- chip_layer: int, rectangle_points: list,
- precision: float, max_points: int):
+ def _handle_photo_resist(
+ self,
+ lib: "gdstk.Library",
+ chip_only_top: "gdstk.Cell",
+ chip_name: str,
+ chip_layer: int,
+ rectangle_points: list,
+ precision: float,
+ max_points: int,
+ ):
"""Handle the positive vs negative mask.
Args:
- lib (gdspy.GdsLibrary): The gdspy library to export.
- chip_only_top (gdspy.library.Cell): The gdspy cell for top.
+ lib (gdstk.Library): The GDS library to export.
+ chip_only_top (gdstk.Cell): The GDS cell for top.
chip_name (str): Name of chip to render.
chip_layer (int): Layer of the chip to render.
rectangle_points (list): The rectangle to denote the ground
for each layer.
- precision (float): Used for gdspy.
- max_points (int): Used for gdspy. GDSpy uses 199 as the default.
+ precision (float): Used for GDS python export.
+ max_points (int): Used for GDS python export, 199 as the default.
"""
- self.chip_info[chip_name]['subtract_poly'] = gdspy.Polygon(
- rectangle_points, chip_layer)
+ self.chip_info[chip_name]["subtract_poly"] = gdstk.Polygon(
+ rectangle_points, layer=chip_layer, datatype=10)
- ground_cell_name = f'TOP_{chip_name}_{chip_layer}'
+ ground_cell_name = f"TOP_{chip_name}_{chip_layer}"
ground_cell = lib.new_cell(ground_cell_name, overwrite_duplicate=True)
if self._is_negative_mask(chip_name, chip_layer):
- self._negative_mask(lib, chip_only_top, ground_cell, chip_name,
- chip_layer, precision, max_points)
+ self._negative_mask(
+ lib,
+ chip_only_top,
+ ground_cell,
+ chip_name,
+ chip_layer,
+ precision,
+ max_points,
+ )
else:
- self._positive_mask(lib, chip_only_top, ground_cell, chip_name,
- chip_layer, precision, max_points)
+ self._positive_mask(
+ lib,
+ chip_only_top,
+ ground_cell,
+ chip_name,
+ chip_layer,
+ precision,
+ max_points,
+ )
def _is_negative_mask(self, chip: str, layer: int) -> bool:
"""Check options to see if negative mask is requested for the
@@ -1595,78 +1654,96 @@ def _is_negative_mask(self, chip: str, layer: int) -> bool:
return False
- def _negative_mask(self, lib: gdspy.GdsLibrary,
- chip_only_top: gdspy.library.Cell,
- ground_cell: gdspy.library.Cell, chip_name: str,
- chip_layer: int, precision: float, max_points: int):
+ def _negative_mask(
+ self,
+ lib: "gdstk.Library",
+ chip_only_top: "gdstk.Cell",
+ ground_cell: "gdstk.Cell",
+ chip_name: str,
+ chip_layer: int,
+ precision: float,
+ max_points: int,
+ ):
"""Apply logic for negative_mask.
Args:
- lib (gdspy.GdsLibrary): The gdspy library to export.
- chip_only_top (gdspy.library.Cell): The gdspy cell for top.
- ground_cell (gdspy.library.Cell): Cell created for each layer.
+ lib (gdstk.Library): GDS library.
+ chip_only_top (gdstk.Cell): The chip's top cell.
+ ground_cell (gdstk.Cell): The ground cell for this layer.
chip_name (str): Name of chip to render.
chip_layer (int): Layer of the chip to render.
- precision (float): Used for gdspy.
- max_points (int): Used for gdspy. GDSpy uses 199 as the default.
+ precision (float): GDS geometry precision.
+ max_points (int): GDS geometry max points, default is 199.
"""
- if len(self.chip_info[chip_name][chip_layer]['q_subtract_true']) != 0:
+ if len(self.chip_info[chip_name][chip_layer]["q_subtract_true"]) != 0:
# When subtract==True for chip and layer.
- subtract_true_cell_name = f'SUBTRACT_true_{chip_name}_{chip_layer}'
+ subtract_true_cell_name = f"SUBTRACT_true_{chip_name}_{chip_layer}"
subtract_true_cell = lib.new_cell(subtract_true_cell_name,
overwrite_duplicate=True)
subtract_true_cell.add(
- self.chip_info[chip_name][chip_layer]['q_subtract_true'])
+ self.chip_info[chip_name][chip_layer]["q_subtract_true"])
- #When subtract==False for chip and layer.
- subtract_false_cell_name = f'SUBTRACT_false_{chip_name}_{chip_layer}'
+ # When subtract==False for chip and layer.
+ subtract_false_cell_name = f"SUBTRACT_false_{chip_name}_{chip_layer}"
subtract_false_cell = lib.new_cell(subtract_false_cell_name,
overwrite_duplicate=True)
subtract_false_cell.add(
- self.chip_info[chip_name][chip_layer]['q_subtract_false'])
+ self.chip_info[chip_name][chip_layer]["q_subtract_false"])
+
+ subtract_true_polygons = subtract_true_cell.polygons
+ subtract_false_polygons = subtract_false_cell.polygons
# Difference for True-False.
- diff_geometry = gdspy.boolean(subtract_true_cell.get_polygons(),
- subtract_false_cell.get_polygons(),
- 'not',
- max_points=max_points,
- precision=precision,
- layer=chip_layer)
+ diff_geometry = gdstk.boolean(
+ subtract_true_polygons,
+ subtract_false_polygons,
+ "not",
+ layer=chip_layer,
+ datatype=10,
+ precision=precision,
+ max_points=max_points,
+ )
lib.remove(subtract_true_cell)
lib.remove(subtract_false_cell)
if diff_geometry is None:
self.design.logger.warning(
- 'There is no table named diff_geometry to write.')
+ "There is no table named diff_geometry to write.")
else:
ground_cell.add(diff_geometry)
QGDSRenderer._add_groundcell_to_chip_only_top(lib, chip_only_top,
ground_cell)
- def _positive_mask(self, lib: gdspy.GdsLibrary,
- chip_only_top: gdspy.library.Cell,
- ground_cell: gdspy.library.Cell, chip_name: str,
- chip_layer: int, precision: float, max_points: int):
- """Apply logic for positive mask.
+ def _positive_mask(
+ self,
+ lib: "gdstk.Library",
+ chip_only_top: "gdstk.Cell",
+ ground_cell: "gdstk.Cell",
+ chip_name: str,
+ chip_layer: int,
+ precision: float,
+ max_points: int,
+ ):
+ """Apply logic for positive mask for a chip to render.
Args:
- lib (gdspy.GdsLibrary): The gdspy library to export.
- chip_only_top (gdspy.library.Cell): The gdspy cell for top.
- ground_cell (gdspy.library.Cell): Cell created for each layer.
- chip_name (str): Name of chip to render.
- chip_layer (int): Layer of the chip to render.
- precision (float): Used for gdspy.
- max_points (int): Used for gdspy. GDSpy uses 199 as the default.
+ lib (gdstk.Library): GDS library.
+ chip_only_top (gdstk.Cell): The chip's top cell.
+ ground_cell (gdstk.Cell): The ground cell for this layer.
+ chip_name (str): Chip name.
+ chip_layer (int): Layer index.
+ precision (float): GDS geometry precision.
+ max_points (int): GDS geometry max points.
"""
- if len(self.chip_info[chip_name][chip_layer]['q_subtract_true']) != 0:
- subtract_cell_name = f'SUBTRACT_{chip_name}_{chip_layer}'
+ if len(self.chip_info[chip_name][chip_layer]["q_subtract_true"]) != 0:
+ subtract_cell_name = f"SUBTRACT_{chip_name}_{chip_layer}"
subtract_cell = lib.new_cell(subtract_cell_name,
overwrite_duplicate=True)
subtract_cell.add(
- self.chip_info[chip_name][chip_layer]['q_subtract_true'])
+ self.chip_info[chip_name][chip_layer]["q_subtract_true"])
# gdspy.boolean() is not documented clearly. If there are multiple
# elements to subtract (both poly & path), the way I could
@@ -1674,72 +1751,74 @@ def _positive_mask(self, lib: gdspy.GdsLibrary,
# the method cell_name.get_polygons(), which appears to convert
# all elements within the cell to poly. After the boolean(),
# I deleted the cell from lib. The memory is freed up then.
- diff_geometry = gdspy.boolean(
- self.chip_info[chip_name]['subtract_poly'],
- subtract_cell.get_polygons(),
- 'not',
- max_points=max_points,
+ diff_geometry = gdstk.boolean(
+ [self.chip_info[chip_name]["subtract_poly"]],
+ subtract_cell.polygons,
+ "not",
+ layer=chip_layer,
+ datatype=10,
precision=precision,
- layer=chip_layer)
+ max_points=max_points,
+ )
lib.remove(subtract_cell)
if diff_geometry is None:
self.design.logger.warning(
- 'There is no table named diff_geometry to write.')
+ "There is no table named diff_geometry to write.")
else:
- ground_chip_layer_name = f'ground_{chip_name}_{chip_layer}'
+ ground_chip_layer_name = f"ground_{chip_name}_{chip_layer}"
ground_chip_layer = lib.new_cell(ground_chip_layer_name)
- #diff_geometry is a polygon set. So put into it's own cell.
+ # diff_geometry is a polygon set. So put into it's own cell.
ground_chip_layer.add(diff_geometry)
- ground_cell.add(gdspy.CellReference(ground_chip_layer))
+ ground_cell.add(gdstk.Reference(ground_chip_layer))
self._handle_q_subtract_false(chip_name, chip_layer, ground_cell)
QGDSRenderer._add_groundcell_to_chip_only_top(lib, chip_only_top,
ground_cell)
def _handle_q_subtract_false(self, chip_name: str, chip_layer: int,
- ground_cell: gdspy.library.Cell):
+ ground_cell: "gdstk.Cell"):
"""For each layer, add the subtract=false components to ground.
Args:
chip_name (str): Name of chip to render.
chip_layer (int): Name of layer to render.
- ground_cell (gdspy.library.Cell): The cell in lib to add to.
+ ground_cell (gdstk.Cell): The cell in lib to add to.
Cell created for each layer.
"""
- if self.chip_info[chip_name][chip_layer]['q_subtract_false'] is None:
- self.logger.warning(f'There is no table named '
- f'self.chip_info[{chip_name}][q_subtract_false]'
- f' to write.')
+ if self.chip_info[chip_name][chip_layer]["q_subtract_false"] is None:
+ self.logger.warning(f"There is no table named "
+ f"self.chip_info[{chip_name}][q_subtract_false]"
+ f" to write.")
else:
if len(self.chip_info[chip_name][chip_layer]
- ['q_subtract_false']) != 0:
+ ["q_subtract_false"]) != 0:
ground_cell.add(
- self.chip_info[chip_name][chip_layer]['q_subtract_false'])
+ self.chip_info[chip_name][chip_layer]["q_subtract_false"])
@classmethod
- def _add_groundcell_to_chip_only_top(cls, lib: gdspy.GdsLibrary,
- chip_only_top: gdspy.library.Cell,
- ground_cell: gdspy.library.Cell):
+ def _add_groundcell_to_chip_only_top(cls, lib: "gdstk.Library",
+ chip_only_top: "gdstk.Cell",
+ ground_cell: "gdstk.Cell") -> None:
"""Add the ground cell to the top of cell for chip.
Args:
- lib (gdspy.GdsLibrary): Holds all of the chips to export to gds.
- chip_only_top (gdspy.library.Cell): Cell which for a single chip.
- ground_cell (gdspy.library.Cell): The ground cell to add to
+ lib (gdstk.GdsLibrary): Holds all of the chips to export to gds.
+ chip_only_top (gdstk.Cell): Cell which for a single chip.
+ ground_cell (gdstk.Cell): The ground cell to add to
chip_only_top. Cell created for each layer.
"""
# put all cells into TOP_chipname, if not empty.
# When checking for bounding box, gdspy will return None if empty.
- if ground_cell.get_bounding_box() is not None:
- chip_only_top.add(gdspy.CellReference(ground_cell))
+ if ground_cell.bounding_box() is not None:
+ chip_only_top.add(gdstk.Reference(ground_cell))
else:
lib.remove(ground_cell)
def _get_linestring_characteristics(
- self, row: 'pd.Pandas') -> Tuple[Tuple, float, float]:
+ self, row: "pd.Pandas") -> Tuple[Tuple, float, float]:
"""Given a row in the Junction table, give the characteristics of
LineString in row.geometry.
@@ -1764,12 +1843,15 @@ def _get_linestring_characteristics(
rotation = math.degrees(math.atan2((maxy - miny), (maxx - minx)))
magnitude = np.round(
distance.euclidean(row.geometry.coords[0], row.geometry.coords[1]),
- for_rounding)
+ for_rounding,
+ )
return center, rotation, magnitude
def _give_rotation_center_twopads(
- self, row: 'pd.Pandas', a_cell_bounding_box: 'np.ndarray') -> Tuple:
+ self, row: pd.Series, a_cell_bounding_box: np.ndarray
+ ) -> Tuple[float, Tuple[float, float], Union[gdstk.Polygon, None], Union[
+ gdstk.Polygon, None]]:
"""Calculate the angle for rotation, center of LineString in
row.geometry, and if needed create two pads to connect the junction to
qubit.
@@ -1785,10 +1867,10 @@ def _give_rotation_center_twopads(
row.geometry.
* 2nd entry is Tuple[float,float]: The midpoint of Linestring
from row.geometry in format (x,y).
- * 3rd entry is gdspy.polygon.Rectangle: None if Magnitude of
+ * 3rd entry is gdstk.Rectangle: None if Magnitude of
LineString is smaller than width of cell from row.gds_cell_name.
Otherwise the rectangle for pad on LEFT of row.gds_cell_name.
- * 4th entry is gdspy.polygon.Rectangle: None if Magnitude of
+ * 4th entry is gdstk.Rectangle: None if Magnitude of
LineString is smaller than width of cell from row.gds_cell_name.
Otherwise the rectangle for pad on RIGHT of row.gds_cell_name.
"""
@@ -1805,7 +1887,7 @@ def _give_rotation_center_twopads(
jj_x_width = abs(jj_maxx - jj_minx)
jj_y_height = abs(jj_maxy - jj_miny)
- #jj_center_x = (jj_x_width / 2) + jj_minx
+ # jj_center_x = (jj_x_width / 2) + jj_minx
jj_center_y = (jj_y_height / 2) + jj_miny
pad_height = row.width
@@ -1814,31 +1896,39 @@ def _give_rotation_center_twopads(
# pylint: disable=protected-access
text_id = self.design._components[row.component]._name
self.logger.warning(
- f'In junction table, component={text_id} with name={row.name} '
- f'has width={pad_height} smaller than cell dimension={jj_y_height}.'
+ f"In junction table, component={text_id} with name={row.name} "
+ f"has width={pad_height} smaller than cell dimension={jj_y_height}."
)
if jj_x_width < magnitude:
pad_x_size_minus_overlap = (magnitude - jj_x_width) / 2
pad_miny = jj_center_y - (pad_height / 2)
- pad_left = gdspy.Rectangle(
- (jj_minx - pad_x_size_minus_overlap, pad_miny),
- (jj_minx + junction_pad_overlap, pad_miny + pad_height),
+ pad_left = gdstk.Polygon(
+ [
+ (jj_minx - pad_x_size_minus_overlap, pad_miny),
+ (jj_minx + junction_pad_overlap, pad_miny),
+ (jj_minx + junction_pad_overlap, pad_miny + pad_height),
+ (jj_minx - pad_x_size_minus_overlap, pad_miny + pad_height),
+ ],
layer=int(row.layer),
- datatype=10)
-
- pad_right = gdspy.Rectangle(
- (jj_maxx - junction_pad_overlap, pad_miny),
- (jj_maxx + pad_x_size_minus_overlap, pad_miny + pad_height),
+ datatype=10,
+ )
+ pad_right = gdstk.Polygon(
+ [
+ (jj_maxx - junction_pad_overlap, pad_miny),
+ (jj_maxx + pad_x_size_minus_overlap, pad_miny),
+ (jj_maxx + pad_x_size_minus_overlap, pad_miny + pad_height),
+ (jj_maxx - junction_pad_overlap, pad_miny + pad_height),
+ ],
layer=int(row.layer),
- datatype=10)
+ datatype=10,
+ )
return rotation, center, pad_left, pad_right
+ ############
-############
-
- def _import_junction_gds_file(self, lib: gdspy.library,
+ def _import_junction_gds_file(self, lib: "gdstk.Library",
directory_name: str) -> bool:
"""Import the file which contains all junctions for design.
If the file has already been imported, just return True.
@@ -1847,7 +1937,7 @@ def _import_junction_gds_file(self, lib: gdspy.library,
we only need to import file once to get ALL of the junctions.
Args:
- lib (gdspy.library): The library used to export the entire QDesign.
+ lib (gdstk.Library): The library used to export the entire QDesign.
directory_name (str): The path of directory to read file with junctions.
Returns:
@@ -1859,20 +1949,24 @@ def _import_junction_gds_file(self, lib: gdspy.library,
return True
if os.path.isfile(self.options.path_filename):
- lib.read_gds(self.options.path_filename, units='convert')
+ lib.read_gds(self.options.path_filename, units="convert")
self.imported_junction_gds = self.options.path_filename
return True
else:
message_str = (
f'Not able to find file:"{self.options.path_filename}". '
- f'Not used to replace junction.'
+ f"Not used to replace junction."
f' Checked directory:"{directory_name}".')
self.logger.warning(message_str)
return False
- def _import_junctions_to_one_cell(self, chip_name: str, lib: gdspy.library,
- chip_only_top: gdspy.library.Cell,
- layers_in_chip: list):
+ def _import_junctions_to_one_cell(
+ self,
+ chip_name: str,
+ lib: "gdstk.Library",
+ chip_only_top: "gdstk.Cell",
+ layers_in_chip: list,
+ ):
"""Given lib, import the gds file from default options. Based on the
cell name in QGeometry table, import the cell from the gds file and
place it in hierarchy of chip_only_top. In addition, the linestring
@@ -1885,8 +1979,8 @@ def _import_junctions_to_one_cell(self, chip_name: str, lib: gdspy.library,
Args:
chip_name (str): The name of chip.
- lib (gdspy.library): The library used to export the entire QDesign.
- chip_only_top (gdspy.library.Cell): The cell used for
+ lib (gdstk.Library): The library used to export the entire QDesign.
+ chip_only_top (gdstk.Cell): The cell used for
just chip_name.
layers_in_chip (list): List of all layers in chip.
"""
@@ -1894,10 +1988,9 @@ def _import_junctions_to_one_cell(self, chip_name: str, lib: gdspy.library,
# pylint: disable=too-many-nested-blocks
# Make sure the file exists, before trying to read it.
- dummy_status, directory_name = can_write_to_path(
- self.options.path_filename)
+ _, directory_name = can_write_to_path(self.options.path_filename)
layers_in_junction_table = set(
- self.chip_info[chip_name]['junction']['layer'])
+ self.chip_info[chip_name]["junction"]["layer"])
if self._import_junction_gds_file(lib=lib,
directory_name=directory_name):
@@ -1907,219 +2000,228 @@ def _import_junctions_to_one_cell(self, chip_name: str, lib: gdspy.library,
# Want to export negative mask
# Gather the pads into hold_all_pads_cell for same layer.
if iter_layer in layers_in_junction_table:
- chip_only_top_layer_name = f'TOP_{chip_name}_{iter_layer}'
- if chip_only_top_layer_name in lib.cells.keys():
- chip_only_top_layer = lib.cells[
- chip_only_top_layer_name]
- hold_all_pads_name = f'r_l_hold_all_pads_{iter_layer}'
- hold_all_pads_cell = lib.new_cell(
- hold_all_pads_name, overwrite_duplicate=True)
- chip_only_top_layer.add(
- gdspy.CellReference(hold_all_pads_cell))
-
- # Put all junctions into one cell for same layer.
- hold_all_jj_cell_name = f'all_jj_imported_{iter_layer}'
- hold_all_jj_cell = lib.new_cell(
- hold_all_jj_cell_name, overwrite_duplicate=True)
+ chip_only_top_layer_name = f"TOP_{chip_name}_{iter_layer}"
+ top_layer_cell = next(
+ (c for c in lib.cells
+ if c.name == chip_only_top_layer_name), None)
+ if top_layer_cell:
+ hold_all_pads_cell = _new_cell(
+ lib, f"r_l_hold_all_pads_{iter_layer}", True)
+ top_layer_cell.add(
+ gdstk.Reference(hold_all_pads_cell))
+ hold_all_jj_cell = _new_cell(
+ lib, f"all_jj_imported_{iter_layer}", True)
self._add_negative_extension_to_jj(
- chip_name, iter_layer, lib, chip_only_top,
- chip_only_top_layer, hold_all_pads_cell,
- hold_all_jj_cell)
+ chip_name,
+ iter_layer,
+ lib,
+ chip_only_top,
+ top_layer_cell,
+ hold_all_pads_cell,
+ hold_all_jj_cell,
+ )
else:
# By default, make a positive mask.
- for row in self.chip_info[chip_name]['junction'].itertuples(
+ for row in self.chip_info[chip_name]["junction"].itertuples(
):
chip_layer = int(row.layer)
- ground_cell_name = f'TOP_{chip_name}_{chip_layer}'
-
- if ground_cell_name in lib.cells.keys(
- ) and chip_layer == iter_layer:
- chip_layer_cell = lib.cells[ground_cell_name]
-
- if row.gds_cell_name in lib.cells.keys():
- # When positive mask, just add the pads to chip_only_top
+ ground_cell_name = f"TOP_{chip_name}_{chip_layer}"
+ if ground_cell_name in [c.name for c in lib.cells
+ ] and chip_layer == iter_layer:
+ chip_layer_cell = next(
+ (c for c in lib.cells
+ if c.name == ground_cell_name), None)
+ if row.gds_cell_name in [c.name for c in lib.cells]:
self._add_positive_extension_to_jj(
lib, row, chip_layer_cell)
else:
self.logger.warning(
- f'From the "junction" table, the cell named'
- f' "{row.gds_cell_name}"", is not in '
- f'file: {self.options.path_filename}.'
- f' The cell was not used.')
-
- def _add_negative_extension_to_jj(self, chip_name: str, jj_layer: int,
- lib: gdspy.library,
- chip_only_top: gdspy.library.Cell,
- chip_only_top_layer: gdspy.library.Cell,
- hold_all_pads_cell: gdspy.library.Cell,
- hold_all_jj_cell: gdspy.library.Cell):
- """Manipulate existing geometries for the layer that the junctions need
+ f"Cell={row.gds_cell_name} from junction"
+ f"table not found in {self.options.path_filename}."
+ )
+
+ def _add_negative_extension_to_jj(
+ self,
+ chip_name: str,
+ jj_layer: int,
+ lib: "gdstk.Library",
+ chip_only_top: "gdstk.Cell",
+ chip_only_top_layer: "gdstk.Cell",
+ hold_all_pads_cell: "gdstk.Cell",
+ hold_all_jj_cell: "gdstk.Cell",
+ ) -> None:
+ """Gather extension pads & junctions for negative mask usage.
+ Manipulate existing geometries for the layer that the junctions need
to be added. Since boolean subtraction is computationally intensive,
the method will gather the pads for a layer, and do the boolean just
once. Then add the junctions to difference.
Args:
- chip_name (str): The name of chip.
- jj_layer (int): The layer the
- lib (gdspy.library): The library used to export the entire QDesign.
- chip_only_top (gdspy.library.Cell): The cell used for
- just chip_name.
- chip_only_top_layer (gdspy.library.Cell): Cell under chip,
- with specific layer.
- hold_all_pads_cell (gdspy.library.Cell): Collect all the pads with movement.
- hold_all_jj_cell (gdspy.library.Cell): Collect all the jj's with movement.
+ chip_name (str): Chip name.
+ jj_layer (int): Layer index for junction.
+ lib (gdstk.Library): GDS library.
+ chip_only_top (gdstk.Cell): Chip top cell.
+ chip_only_top_layer (gdstk.Cell): Chip/layer cell.
+ hold_all_pads_cell (gdstk.Cell): Cell collecting extension pads.
+ hold_all_jj_cell (gdstk.Cell): Cell collecting junction references.
"""
-
- boolean_by_layer = self.chip_info[chip_name]['junction'][
- 'layer'] == jj_layer
- for row in self.chip_info[chip_name]['junction'][
+ boolean_by_layer = self.chip_info[chip_name]["junction"][
+ "layer"] == jj_layer
+ for row in self.chip_info[chip_name]["junction"][
boolean_by_layer].itertuples():
-
- if row.gds_cell_name in lib.cells.keys():
- # For negative mask, collect the pads to subtract per layer,
- # and subtract from chip_only_top_layer
+ if row.gds_cell_name in [c.name for c in lib.cells]:
self._gather_negative_extension_for_jj(lib, row,
hold_all_pads_cell,
hold_all_jj_cell)
else:
self.logger.warning(
- f'From the "junction" table, the cell named'
- f' "{row.gds_cell_name}", is not in file: '
- f'{self.options.path_filename}. The cell was not used.')
+ f"Junction cell={row.gds_cell_name} not "
+ f"n {self.options.path_filename} for negative "
+ "mask usage.")
- diff_r_l_pads_name = f'r_l_pads_diff_{jj_layer}'
- diff_pad_cell_layer = lib.new_cell(diff_r_l_pads_name,
- overwrite_duplicate=True)
- #chip_only_top_layer.add(gdspy.CellReference(diff_pad_cell_layer))
- chip_only_top.add(gdspy.CellReference(diff_pad_cell_layer))
+ diff_r_l_pads_name = f"r_l_pads_diff_{jj_layer}"
+ diff_pad_cell_layer = _new_cell(lib, diff_r_l_pads_name, True)
+ chip_only_top.add(gdstk.Reference(diff_pad_cell_layer))
- precision = self.parse_value(self.options.precision)
+ precision = float(self.parse_value(self.options.precision))
max_points = int(self.parse_value(self.options.max_points))
- # Make sure the pads to hold_all_pads_cell is not empty
+ if chip_only_top_layer.bounding_box() is not None:
+ boolean_result = gdstk.boolean(
+ chip_only_top_layer.polygons,
+ hold_all_pads_cell.polygons,
+ "not",
+ precision=precision,
+ max_points=max_points,
+ )
+ if boolean_result:
+ for poly in boolean_result:
+ diff_pad_cell_layer.add(poly)
- if chip_only_top_layer.get_bounding_box() is not None:
- jj_minus_pads = gdspy.boolean(chip_only_top_layer.get_polygons(),
- hold_all_pads_cell.get_polygons(),
- 'not',
- max_points=max_points,
- precision=precision)
- diff_pad_cell_layer.add(jj_minus_pads)
- if hold_all_jj_cell.get_bounding_box() is not None:
- diff_pad_cell_layer.add(gdspy.CellReference(hold_all_jj_cell))
+ if hold_all_jj_cell.bounding_box() is not None:
+ diff_pad_cell_layer.add(gdstk.Reference(hold_all_jj_cell))
self._clean_hierarchy(lib, chip_only_top, chip_only_top_layer,
diff_pad_cell_layer, hold_all_pads_cell)
@classmethod
- def _clean_hierarchy(cls, lib, chip_only_top, chip_only_top_layer,
- diff_pad_cell_layer, hold_all_pads_cell):
+ def _clean_hierarchy(
+ cls,
+ lib: "gdstk.Library",
+ chip_only_top: "gdstk.Cell",
+ chip_only_top_layer: "gdstk.Cell",
+ diff_pad_cell_layer: "gdstk.Cell",
+ hold_all_pads_cell: "gdstk.Cell",
+ ) -> None:
"""Delete cell that doesn't have pad nor jjs. Then use same
name for correct cell. Also, get rid of cell that had the pads
since subtraction happened and we don't need it any more.
Args:
- lib (gdspy.library): [The library used to export the entire QDesign.
- chip_only_top (gdspy.library.Cell): [description]
- chip_only_top_layer (gdspy.library.Cell): Cell under chip,
+ lib (gdstk.Library): [The library used to export the entire QDesign.
+ chip_only_top (gdstk.Cell): [description]
+ chip_only_top_layer (gdstk.Cell): Cell under chip,
with specific layer.
- diff_pad_cell_layer (gdspy.library.Cell): Holds result of top_layer - pads + jjs.
- hold_all_pads_cell (gdspy.library.Cell): Collect all the jj's with movement.
+ diff_pad_cell_layer (gdstk.Cell): Holds result of top_layer - pads + jjs.
+ hold_all_pads_cell (gdstk.Cell): Collect all the jj's with movement.
"""
hold_name = chip_only_top_layer.name
- lib.remove(hold_name)
- lib.rename_cell(diff_pad_cell_layer, hold_name)
+ lib.remove(chip_only_top_layer)
+ _rename_cell(diff_pad_cell_layer, hold_name)
- #Add to hierarchy only if cell is not empty.
- if diff_pad_cell_layer.get_bounding_box() is not None:
- chip_only_top.add(gdspy.CellReference(diff_pad_cell_layer))
+ if diff_pad_cell_layer.bounding_box() is not None:
+ chip_only_top.add(gdstk.Reference(diff_pad_cell_layer))
else:
lib.remove(diff_pad_cell_layer)
- # remove the sub libs before removing hold_all_pads_cells
- for _, value in enumerate(hold_all_pads_cell.references):
- lib.remove(value.ref_cell.name)
+
+ for ref in list(hold_all_pads_cell.references):
+ lib.remove(ref.ref_cell)
lib.remove(hold_all_pads_cell)
def _gather_negative_extension_for_jj(
- self, lib: gdspy.library, row: 'pd.core.frame.Pandas',
- hold_all_pads_cell: gdspy.library.Cell,
- hold_all_jj_cell: gdspy.library.Cell):
+ self,
+ lib: "gdstk.Library",
+ row: pd.Series,
+ hold_all_pads_cell: "gdstk.Cell",
+ hold_all_jj_cell: "gdstk.Cell",
+ ) -> None:
"""Gather the pads and jjs and put them in separate cells. The
the pads can be boolean'd 'not' just once. After boolean for pads, then
the jjs will be added to result. The boolean is very
time intensive, so just want to do it once.
Args:
- lib (gdspy.library): The library used to export the entire QDesign.
- row (pd.core.frame.Pandas): Each row is from the qgeometry junction table.
- hold_all_pads_cell (gdspy.library.Cell): Collect all the pads with movement.
- hold_all_jj_cell (gdspy.library.Cell): Collect all the jj's with movement.
+ lib (gdstk.Library): GDS library.
+ row (pd.Series): Row from junction table.
+ hold_all_pads_cell (gdstk.Cell): Collecting extension pads.
+ hold_all_jj_cell (gdstk.Cell): Collecting junction references.
"""
- a_cell = lib.extract(row.gds_cell_name)
- a_cell_bounding_box = a_cell.get_bounding_box()
+ a_cell = next((c for c in lib.cells if c.name == row.gds_cell_name),
+ None)
+ if a_cell is None:
+ return
+ bounding_box = a_cell.bounding_box()
+ if bounding_box is None:
+ return
rotation, center, pad_left, pad_right = self._give_rotation_center_twopads(
- row, a_cell_bounding_box)
-
- # String for JJ combined with pad Right and pad Left
- jj_pad_r_l_name = f'{row.gds_cell_name}_QComponent_is_{row.component}_Name_is_{row.name}_name_is_{row.name}'
- temp_cell = lib.new_cell(jj_pad_r_l_name, overwrite_duplicate=True)
-
+ row, bounding_box)
+ jj_pad_r_l_name = (f"{row.gds_cell_name}_QComponent_is_{row.component}"
+ f"_Name_is_{row.name}_name_is_{row.name}")
+ temp_cell = _new_cell(lib, jj_pad_r_l_name, True)
if pad_left is not None:
temp_cell.add(pad_left)
if pad_right is not None:
temp_cell.add(pad_right)
hold_all_jj_cell.add(
- gdspy.CellReference(a_cell, origin=center, rotation=rotation))
+ gdstk.Reference(a_cell, origin=center, rotation=rotation))
hold_all_pads_cell.add(
- gdspy.CellReference(temp_cell, origin=center, rotation=rotation))
-
- def _add_positive_extension_to_jj(self, lib: gdspy.library,
- row: 'pd.core.frame.Pandas',
- chip_only_top_layer: gdspy.library.Cell):
+ gdstk.Reference(temp_cell, origin=center, rotation=rotation))
+
+ def _add_positive_extension_to_jj(
+ self,
+ lib: "gdstk.Library",
+ row: "pd.Series",
+ chip_layer_cell: "gdstk.Cell",
+ ):
"""Get the extension pads, then add or subtract to extracted cell based on
positive or negative mask.
Args:
- lib (gdspy.library): The library used to export the entire QDesign.
+ lib (gdstk.Library): The library used to export the entire QDesign.
row (pd.core.frame.Pandas): Each row is from the qgeometry
junction table.
- chip_only_top_layer (gdspy.library.Cell): The cell used for
+ chip_layer_cell (gdstk.Cell): The cell used for
chip_name and layer_num.
"""
- a_cell = lib.extract(row.gds_cell_name)
- a_cell_bounding_box = a_cell.get_bounding_box()
+ a_cell = next((c for c in lib.cells if c.name == row.gds_cell_name),
+ None)
+ if a_cell is None:
+ return
+ bounding_box = a_cell.bounding_box()
+ if bounding_box is None:
+ return
rotation, center, pad_left, pad_right = self._give_rotation_center_twopads(
- row, a_cell_bounding_box)
-
- # String for JJ combined with pad Right and pad Left
- jj_pad_r_l_name = f'pads_{row.gds_cell_name}_QComponent_is_{row.component}_name_is_{row.name}'
- temp_cell = lib.new_cell(jj_pad_r_l_name, overwrite_duplicate=True)
- chip_only_top_layer.add(
- gdspy.CellReference(a_cell, origin=center, rotation=rotation))
+ row, bounding_box)
+ jj_pad_r_l_name = (
+ f"pads_{row.gds_cell_name}_QComponent_is_{row.component}_name_is_{row.name}"
+ )
+ temp_cell = _new_cell(lib, jj_pad_r_l_name, True)
if pad_left is not None:
- # chip_only_top_layer.add(
- # gdspy.CellReference(pad_left, origin=center, rotation=rotation))
-
temp_cell.add(pad_left)
-
if pad_right is not None:
- # chip_only_top_layer.add(
- # gdspy.CellReference(pad_right, origin=center,
- # rotation=rotation))
-
temp_cell.add(pad_right)
- # "temp_cell" is kept in the lib.
- if temp_cell.get_bounding_box() is not None:
- chip_only_top_layer.add(
- gdspy.CellReference(temp_cell, origin=center,
- rotation=rotation))
+ chip_layer_cell.add(
+ gdstk.Reference(a_cell, origin=center, rotation=rotation))
+ if temp_cell.bounding_box() is not None:
+ chip_layer_cell.add(
+ gdstk.Reference(temp_cell, origin=center, rotation=rotation))
else:
lib.remove(temp_cell)
@@ -2180,8 +2282,12 @@ def export_to_gds(self,
return 0
def _multipolygon_to_gds(
- self, multi_poly: shapely.geometry.multipolygon.MultiPolygon,
- layer: int, data_type: int, no_cheese_buffer: float) -> list:
+ self,
+ multi_poly: shapely.geometry.multipolygon.MultiPolygon,
+ layer: int,
+ data_type: int,
+ no_cheese_buffer: float, # pylint: disable=unused-argument
+ ) -> list:
"""Convert a shapely MultiPolygon to corresponding gdspy.
Args:
@@ -2197,40 +2303,42 @@ def _multipolygon_to_gds(
"""
# pylint: disable=too-many-locals
- dummy_keep_for_future_use = no_cheese_buffer
- precision = self.parse_value(self.options.precision)
+ precision = float(self.parse_value(self.options.precision))
max_points = int(self.parse_value(self.options.max_points))
all_polys = list(multi_poly.geoms)
all_gds = list()
+
for poly in all_polys:
- exterior_poly = gdspy.Polygon(
- list(poly.exterior.coords),
- layer=layer,
- datatype=data_type,
- )
+ exterior_coords = list(poly.exterior.coords)
+ exterior_poly = gdstk.Polygon(exterior_coords,
+ layer=layer,
+ datatype=data_type)
- all_interiors = list()
if poly.interiors:
+ holes = []
for hole in poly.interiors:
- interior_coords = list(hole.coords)
- all_interiors.append(interior_coords)
- a_poly_set = gdspy.PolygonSet(all_interiors,
- layer=layer,
- datatype=data_type)
- a_poly = gdspy.boolean(exterior_poly,
- a_poly_set,
- 'not',
- max_points=max_points,
- layer=layer,
- datatype=data_type,
- precision=precision)
+ hole_coords = list(hole.coords)
+ holes.append(
+ gdstk.Polygon(hole_coords,
+ layer=layer,
+ datatype=data_type))
+
+ diff_result = gdstk.boolean(
+ [exterior_poly],
+ holes,
+ "not",
+ layer=layer,
+ datatype=data_type,
+ precision=precision,
+ max_points=max_points,
+ )
# Poly fracturing leading to a funny shape. Leave this out of gds output for now.
# a_poly.fillet(no_cheese_buffer,
# points_per_2pi=128,
# max_points=max_points,
# precision=precision)
- all_gds.append(a_poly)
+ all_gds.append(diff_result)
else:
# Poly fracturing leading to a funny shape. Leave this out of gds output for now.
# exterior_poly.fillet(no_cheese_buffer,
@@ -2238,11 +2346,12 @@ def _multipolygon_to_gds(
# max_points=max_points,
# precision=precision)
all_gds.append(exterior_poly)
+
return all_gds
def _qgeometry_to_gds(
self, qgeometry_element: pd.Series
- ) -> Union['gdspy.polygon', 'gdspy.FlexPath', None]:
+ ) -> Union[gdstk.Polygon, gdstk.FlexPath, None]:
"""Convert the design.qgeometry table to format used by GDS renderer.
Convert the class to a series of GDSII elements.
@@ -2250,7 +2359,7 @@ def _qgeometry_to_gds(
qgeometry_element (pd.Series): Expect a shapely object.
Returns:
- Union['gdspy.polygon' or 'gdspy.FlexPath' or None]: Convert the
+ Union['gdstk.Polygon' or 'gdstk.FlexPath' or None]: Convert the
class to a series of GDSII format on the input pd.Series.
@@ -2272,103 +2381,102 @@ class to a series of GDSII format on the input pd.Series.
# pylint: disable=too-many-locals
- corners = self.options.corners
- tolerance = self.parse_value(self.options.tolerance)
+ # corners = self.options.corners
+ # tolerance = self.parse_value(self.options.tolerance)
+ # WARNING: corners and tolerance are not used in this method.
+ # TODO: CHECK THIS WORKS AS EXPECTED.
+ # The gdstk.FlexPath constructor does not support a direct equivalent
+ # for the corners, tolerance, or bend_radius parameters.
+ # a minimal conversion was implemented here without recreating the
+ # full behavior of these parameters.
+ # Filleting was handled using Shapely's buffer method.
+
precision = self.parse_value(self.options.precision)
max_points = int(self.parse_value(self.options.max_points))
- geom = qgeometry_element.geometry # type: shapely.geometry.base.BaseGeometry
+ geom = qgeometry_element.geometry
+ layer_num = int(qgeometry_element.layer)
if isinstance(geom, shapely.geometry.Polygon):
- exterior_poly = gdspy.Polygon(
- list(geom.exterior.coords),
- layer=qgeometry_element.layer,
+ exterior_coords = list(geom.exterior.coords)
+ exterior_poly = gdstk.Polygon(
+ exterior_coords,
+ layer=layer_num,
datatype=10,
)
- # If polygons have a holes, need to remove it for gdspy.
- all_interiors = list()
+ # Handle holes
if geom.interiors:
+ holes = []
for hole in geom.interiors:
- interior_coords = list(hole.coords)
- all_interiors.append(interior_coords)
- a_poly_set = gdspy.PolygonSet(all_interiors,
- layer=qgeometry_element.layer,
- datatype=10)
- # Since there is max_points in boolean, don't need to do this twice.
- # a_poly_set = a_poly_set.fracture(max_points=max_points)
- # exterior_poly = exterior_poly.fracture(max_points=max_points)
- a_poly = gdspy.boolean(exterior_poly,
- a_poly_set,
- 'not',
- max_points=max_points,
- precision=precision,
- layer=qgeometry_element.layer,
- datatype=10)
- return a_poly
-
- exterior_poly = exterior_poly.fracture(max_points=max_points,
- precision=precision)
+ hole_coords = list(hole.coords)
+ holes.append(
+ gdstk.Polygon(hole_coords, layer=layer_num,
+ datatype=10))
+ result = gdstk.boolean(
+ [exterior_poly],
+ holes,
+ "not",
+ layer=layer_num,
+ datatype=10,
+ max_points=max_points,
+ precision=float(precision),
+ )
+ return result
return exterior_poly
- if isinstance(geom, shapely.geometry.LineString):
- #class gdspy.FlexPath(points, width, offset=0, corners='natural',
- #ends='flush', bend_radius=None, tolerance=0.01, precision=0.001,
- #max_points=199, gdsii_path=False, width_transform=True, layer=0,
- #datatype=0)
-
- #Only fillet, if number is greater than zero.
+ if isinstance(geom, shapely.geometry.LineString):
use_width = self.parse_value(self.options.width_LineString)
-
- if math.isnan(qgeometry_element.width):
- qcomponent_id = self.parse_value(qgeometry_element.component)
- name = self.parse_value(qgeometry_element['name'])
- layer_num = self.parse_value(qgeometry_element.layer)
- width = self.parse_value(qgeometry_element.width)
- self.logger.warning(
- f'Since width:{width} for a Path is not a number, '
- f'it will be exported using width_LineString:'
- f' {use_width}. The component_id is:{qcomponent_id},'
- f' name is:{name}, layer is: {layer_num}')
- else:
+ if not math.isnan(qgeometry_element.width):
use_width = qgeometry_element.width
- if 'fillet' in qgeometry_element:
-
- if (math.isnan(qgeometry_element.fillet) or
- qgeometry_element.fillet <= 0 or
- qgeometry_element.fillet < qgeometry_element.width):
-
- to_return = gdspy.FlexPath(list(geom.coords),
- use_width,
- layer=qgeometry_element.layer,
- max_points=max_points,
- datatype=11)
- else:
- to_return = gdspy.FlexPath(
- list(geom.coords),
- use_width,
- layer=qgeometry_element.layer,
+ fillet_val = 0
+ if "fillet" in qgeometry_element and not (
+ math.isnan(qgeometry_element.fillet) or
+ qgeometry_element.fillet <= 0 or
+ qgeometry_element.fillet < qgeometry_element.width):
+ fillet_val = qgeometry_element.fillet
+
+ if fillet_val > 0:
+ # Apply fillet using shapely's buffer to create a rounded polygon
+ buffered = geom.buffer(fillet_val, cap_style=2, join_style=2)
+ if isinstance(buffered, shapely.geometry.Polygon):
+ exterior_coords = list(buffered.exterior.coords)
+ return gdstk.Polygon(
+ exterior_coords,
+ layer=layer_num,
datatype=11,
- max_points=max_points,
- corners=corners,
- bend_radius=qgeometry_element.fillet,
- tolerance=tolerance,
- precision=precision)
- return to_return
-
- # Could be junction table with a linestring.
- # Look for gds_path_filename in column.
- self.logger.warning(f'Linestring did not have fillet in column. '
- f'The qgeometry_element was not drawn.\n'
- f'The qgeometry_element within table is:\n'
- f'{qgeometry_element}')
- return None # Need explicitly to avoid lint warnings.
-
- self.logger.warning(
- f'Unexpected shapely object geometry.'
- f'The variable qgeometry_element is {type(geom)}, '
- f'method can currently handle Polygon and FlexPath.')
+ )
+ elif isinstance(buffered, shapely.geometry.MultiPolygon):
+ polygons = []
+ for poly in buffered:
+ exterior_coords = list(poly.exterior.coords)
+ polygons.append(
+ gdstk.Polygon(
+ exterior_coords,
+ layer=layer_num,
+ datatype=11,
+ ))
+ return polygons # Return list of polygons for MultiPolygon
+ else:
+ self.logger.warning(
+ f"Buffered geometry type={type(buffered)} not supported."
+ )
+ return None
+ else:
+ # No fillet; create a FlexPath as before
+ path_points = list(geom.coords)
+ new_flexpath = gdstk.FlexPath(
+ path_points,
+ use_width,
+ layer=layer_num,
+ datatype=11,
+ max_points=max_points,
+ )
+ return new_flexpath
+
+ self.logger.warning(f"Unsupported geometry type={type(geom)} in"
+ " _qgeometry_to_gds. Expected Polygon/LineString.")
return None
def _get_chip_names(self) -> Dict:
@@ -2384,7 +2492,7 @@ def _get_chip_names(self) -> Dict:
chip_names = Dict()
for table_name in self.design.qgeometry.get_element_types():
table = self.design.qgeometry.tables[table_name]
- names = table['chip'].unique().tolist()
+ names = table["chip"].unique().tolist()
chip_names += names
unique_list = list(set(chip_names))
diff --git a/qiskit_metal/renderers/renderer_gds/make_cheese.py b/qiskit_metal/renderers/renderer_gds/make_cheese.py
index 368572eb6..798c6c870 100644
--- a/qiskit_metal/renderers/renderer_gds/make_cheese.py
+++ b/qiskit_metal/renderers/renderer_gds/make_cheese.py
@@ -15,7 +15,7 @@
import logging
from typing import Union
-import gdspy
+# import gdspy # TODO: Replace with gdstk
import shapely
import numpy as np
@@ -35,7 +35,7 @@ def __init__(
self,
multi_poly: shapely.geometry.multipolygon.MultiPolygon,
all_nocheese_gds: list,
- lib: gdspy.GdsLibrary,
+ lib: "gdspy.GdsLibrary",
minx: float,
miny: float,
maxx: float,
@@ -166,7 +166,7 @@ def __init__(
self.hole = None
- def apply_cheesing(self) -> gdspy.GdsLibrary:
+ def apply_cheesing(self) -> "gdspy.GdsLibrary":
"""Prototype, not complete.
Need to populate self.lib with cheese holes.
@@ -228,7 +228,7 @@ def _make_one_hole_at_zero_zero(self):
f'The cheese_shape={self.cheese_shape} is unknown in Cheesing class.'
)
- def _hole_to_lib(self) -> gdspy.polygon.Polygon:
+ def _hole_to_lib(self) -> "gdspy.polygon.Polygon":
"""Convert the self.hole to a gds cell and add to self.lib.
Put the hole on datatype_cheese +2. This is expected to change when
we agree to some convention.
@@ -334,12 +334,12 @@ def _remove_cell_one_hole(self):
self.lib.remove(cheese_one_hole_cell_name)
def _subtract_from_ground_and_move_under_top_chip_layer(
- self, diff_holes_cell: gdspy.library.Cell):
+ self, diff_holes_cell: "gdstk.Cell"):
"""Get the existing chip_only_top_name cell, then add the holes to it.
Also, add ground_cheesed_cell under chip_only_top_name
Args:
- diff_holes_cell (gdspy.library.Cell): New cell with cheesed ground
+ diff_holes_cell (gdstk.Cell): New cell with cheesed ground
"""
#chip_only_top_name = f'TOP_{self.chip_name}'
@@ -358,12 +358,12 @@ def _subtract_from_ground_and_move_under_top_chip_layer(
self.lib.remove(diff_holes_cell)
def _subtract_keepout_from_hole_grid(
- self, gather_holes_cell: gdspy.library.Cell) -> gdspy.library.Cell:
+ self, gather_holes_cell: "gdstk.Cell") -> "gdstk.Cell":
"""Given a cell with all the holes, subtract the keepout region.
Then return a new cell with the result.
Args:
- gather_holes_cell (gdspy.library.Cell): Holds a grid of all
+ gather_holes_cell (gdstk.Cell): Holds a grid of all
the holes for cheesing.
Returns:
@@ -392,7 +392,7 @@ def _subtract_keepout_from_hole_grid(
self.lib.remove(temp_keepout_chip_layer_cell)
return diff_holes_cell
- def _get_all_holes(self) -> gdspy.library.Cell:
+ def _get_all_holes(self) -> "gdstk.Cell":
"""Return a cell with a grid of holes. The keepout has not been
applied yet.
@@ -422,7 +422,7 @@ def _get_all_holes(self) -> gdspy.library.Cell:
return gather_holes_cell
def _subtract_holes_from_ground(
- self, diff_holes_cell) -> Union[gdspy.library.Cell, None]:
+ self, diff_holes_cell) -> Union["gdstk.Cell", None]:
"""Get reference to ground cell and then subtract the holes from
ground. Place the difference into a new cell, which will eventually
be added under Top.
@@ -460,11 +460,11 @@ def _subtract_holes_from_ground(
f'Cheesing not implemented.')
return None
- def _move_to_under_top_chip_layer_name(self, a_cell: gdspy.library.Cell):
+ def _move_to_under_top_chip_layer_name(self, a_cell: "gdstk.Cell"):
"""Move the cell to under TOP__.
Args:
- a_cell (gdspy.library.Cell): A GDSPY cell.
+ a_cell (gdstk.Cell): A GDSPY cell.
"""
chip_only_top_chip_layer_name = f'TOP_{self.chip_name}_{self.layer}'
if chip_only_top_chip_layer_name in self.lib.cells:
diff --git a/qiskit_metal/renderers/renderer_mpl/extensions/animated_text.py b/qiskit_metal/renderers/renderer_mpl/extensions/animated_text.py
index 3efede528..bd3031342 100644
--- a/qiskit_metal/renderers/renderer_mpl/extensions/animated_text.py
+++ b/qiskit_metal/renderers/renderer_mpl/extensions/animated_text.py
@@ -14,7 +14,7 @@
""""""
import matplotlib.pyplot as plt
-from PySide2.QtCore import QTimer
+from PySide6.QtCore import QTimer
from ...._gui.utility._handle_qt_messages import slot_catch_error
diff --git a/qiskit_metal/renderers/renderer_mpl/mpl_canvas.py b/qiskit_metal/renderers/renderer_mpl/mpl_canvas.py
index 37296df94..7da57a214 100644
--- a/qiskit_metal/renderers/renderer_mpl/mpl_canvas.py
+++ b/qiskit_metal/renderers/renderer_mpl/mpl_canvas.py
@@ -15,6 +15,7 @@
from typing import TYPE_CHECKING, List
+import warnings
import matplotlib
import matplotlib as mpl
import matplotlib.patches as patches
@@ -26,8 +27,8 @@
FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
from matplotlib.transforms import Bbox
-from PySide2.QtCore import QTimer
-from PySide2.QtWidgets import QSizePolicy
+from PySide6.QtCore import QTimer
+from PySide6.QtWidgets import QSizePolicy
from ... import Dict
from ...designs import QDesign
from .mpl_interaction import PanAndZoom
@@ -44,7 +45,7 @@
from ..._gui.widgets.plot_widget.plot_window import QMainWindowPlot
# @mfacchin - moved to the root __init__ to prevent windows from hanging
-# mpl.use("Qt5Agg")
+# mpl.use("QtAgg")
BACKGROUND_COLOR = '#F4F4F4'
MPL_CONTEXT_DEFAULT = {
@@ -343,6 +344,8 @@ def __init__(self,
self.mpl_context = MPL_CONTEXT_DEFAULT.copy()
+ warnings.filterwarnings("ignore", ".*Ignoring fixed.*")
+
with mpl.rc_context(rc=self.mpl_context):
fig = Figure()
@@ -560,10 +563,17 @@ def style_axis(self, ax, num: int):
num (int): Not used
"""
ax.set_aspect(1)
-
- # If 'box', change the physical dimensions of the Axes. If 'datalim',
- # change the x or y data limits.
+ # # If 'box', change the physical dimensions of the Axes. If 'datalim',
+ # # change the x or y data limits.
ax.set_adjustable('datalim')
+ ax.set_anchor('C') # Center the plot
+
+ # Set axis scales to be equal
+ ax.set_xscale('linear')
+ ax.set_yscale('linear')
+
+ # Ensure data units are equal
+ ax.set_box_aspect(None)
ax.set_xlabel('x position (mm)')
ax.set_ylabel('y position (mm)')
@@ -733,8 +743,7 @@ def highlight_components(self, component_names: List[str]):
component_id = int(component_id)
if component_id in self.design._components:
- # type: QComponent
- component = self.design._components[component_id]
+ component: "QComponent" = self.design._components[component_id]
if 1: # highlight bounding box
bounds = component.qgeometry_bounds(
@@ -810,8 +819,8 @@ def highlight_components(self, component_names: List[str]):
**text_kw,
**dict(horizontalalignment='left' if n[0] >= 0 else 'right')
}
- # type: matplotlib.text.Text
- text = ax.text(*(m + dist * n), pin_name, **kw)
+ text: "matplotlib.text.Text" = ax.text(
+ *(m + dist * n), pin_name, **kw)
text.set_bbox(text_bbox_kw)
self._annotations['text'] += [text]
diff --git a/qiskit_metal/renderers/renderer_mpl/mpl_interaction.py b/qiskit_metal/renderers/renderer_mpl/mpl_interaction.py
index 154d9b672..5b9b12337 100644
--- a/qiskit_metal/renderers/renderer_mpl/mpl_interaction.py
+++ b/qiskit_metal/renderers/renderer_mpl/mpl_interaction.py
@@ -84,9 +84,9 @@
import matplotlib.pyplot as _plt
import numpy
-from PySide2.QtCore import Qt
-from PySide2.QtGui import QIcon
-from PySide2.QtWidgets import QAction, QLabel
+from PySide6.QtCore import Qt
+from PySide6.QtGui import QIcon, QAction
+from PySide6.QtWidgets import QLabel
from ... import Dict
diff --git a/qiskit_metal/tests/run_all_tests.py b/qiskit_metal/tests/run_all_tests.py
index ca142ac20..698d92411 100644
--- a/qiskit_metal/tests/run_all_tests.py
+++ b/qiskit_metal/tests/run_all_tests.py
@@ -12,7 +12,6 @@
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
"""Qiskit Metal main unit test functionality."""
-
import os
import fnmatch
import sys
@@ -23,20 +22,46 @@
PATTERN = "test*.py"
print("====> Running the entire test suite now...")
ERRORS_EXIST = 0
- for entry in LIST_OF_FILES:
- if fnmatch.fnmatch(entry, PATTERN):
- if entry != sys.argv[0]:
- print("Running ", entry, " tests...")
- cmd = 'python ' + entry
- ERROR_BACK = subprocess.call(cmd, shell=True)
- if ERROR_BACK != 3221225477: # access violation
- ERRORS_EXIST += ERROR_BACK
- print("")
-
- print("All tests complete")
- if ERRORS_EXIST == 0:
- print("Congratulations, all the tests PASSED!")
- print("Have a nice day...")
- else:
- print("One or more tests have FAILED!")
- print("Scroll up to review the results")
+
+ # Open log files
+ with open("test_results.log",
+ "w") as results_log, open("test_errors.log", "w") as errors_log:
+ for entry in LIST_OF_FILES:
+ if fnmatch.fnmatch(entry, PATTERN):
+ if entry != sys.argv[0]:
+ print(f"Running {entry} tests...")
+ results_log.write(f"Running {entry} tests...\n")
+
+ # Run the test and capture output
+ result = subprocess.run(f"python {entry}",
+ shell=True,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ text=True)
+
+ # Write the stdout and stderr to test_results.log
+ results_log.write(result.stdout)
+ results_log.write(result.stderr)
+ results_log.write("\n")
+
+ # If there's an error, write it to test_errors.log
+ if result.returncode != 0:
+ ERRORS_EXIST += 1
+ errors_log.write(f"Error in {entry}:\n")
+ errors_log.write(result.stderr)
+ errors_log.write("\n")
+
+ print("")
+
+ print("All tests complete")
+ results_log.write("All tests complete\n")
+ if ERRORS_EXIST == 0:
+ print("Congratulations, all the tests PASSED!")
+ print("Have a nice day...")
+ results_log.write("Congratulations, all the tests PASSED!\n")
+ results_log.write("Have a nice day...\n")
+ else:
+ print("One or more tests have FAILED!")
+ print("Scroll up to review the results")
+ results_log.write("One or more tests have FAILED!\n")
+ results_log.write("Scroll up to review the results\n")
diff --git a/qiskit_metal/tests/test_toolbox_metal.py b/qiskit_metal/tests/test_toolbox_metal.py
index e0edacbb6..8ff387a92 100644
--- a/qiskit_metal/tests/test_toolbox_metal.py
+++ b/qiskit_metal/tests/test_toolbox_metal.py
@@ -19,25 +19,28 @@
"""Qiskit Metal unit tests analyses functionality."""
import unittest
-import numpy as np
+from pathlib import Path
from typing import Union
-from qiskit_metal.toolbox_metal import about
-from qiskit_metal.toolbox_metal import parsing
-from qiskit_metal.toolbox_metal import math_and_overrides
-from qiskit_metal.toolbox_metal import bounds_for_path_and_poly_tables
-from qiskit_metal.toolbox_metal.bounds_for_path_and_poly_tables import BoundsForPathAndPolyTables
-from qiskit_metal.toolbox_metal.layer_stack_handler import LayerStackHandler
-from qiskit_metal.toolbox_metal.exceptions import QiskitMetalExceptions
-from qiskit_metal.toolbox_metal.exceptions import QiskitMetalDesignError
-from qiskit_metal.toolbox_metal.exceptions import IncorrectQtException
-from qiskit_metal.toolbox_metal.exceptions import QLibraryGUIException
-from qiskit_metal.toolbox_metal.exceptions import InputError
-from qiskit_metal.tests.assertions import AssertionsMixin
-from qiskit_metal.qlibrary.qubits.transmon_concentric import TransmonConcentric
+import numpy as np
+
from qiskit_metal.designs.design_multiplanar import MultiPlanar
+from qiskit_metal.qlibrary.qubits.transmon_concentric import TransmonConcentric
from qiskit_metal.qlibrary.qubits.transmon_pocket_6 import TransmonPocket6
+from qiskit_metal.tests.assertions import AssertionsMixin
from qiskit_metal.tests.test_data.quad_coupler import QuadCoupler
+from qiskit_metal.toolbox_metal import (about, bounds_for_path_and_poly_tables,
+ math_and_overrides, parsing)
+from qiskit_metal.toolbox_metal.bounds_for_path_and_poly_tables import \
+ BoundsForPathAndPolyTables
+from qiskit_metal.toolbox_metal.exceptions import (IncorrectQtException,
+ InputError,
+ QiskitMetalDesignError,
+ QiskitMetalExceptions,
+ QLibraryGUIException)
+from qiskit_metal.toolbox_metal.layer_stack_handler import LayerStackHandler
+
+TEST_DATA = Path(__file__).parent / "test_data"
class TestToolboxMetal(unittest.TestCase, AssertionsMixin):
@@ -363,7 +366,7 @@ def test_toolbox_metal_determine_larger_box(self):
def test_toolbox_metal_get_bounds_of_path_and_poly_tables(self):
"""Test functionality of get_bounds_of_path_and_poly_tables in toolbox_metal.py"""
- ls_file_path = ("./qiskit_metal/tests/test_data/planar_chip.txt")
+ ls_file_path = TEST_DATA / 'planar_chip.txt'
multiplanar_design = MultiPlanar(metadata={},
overwrite_enabled=True,
layer_stack_filename=ls_file_path)
@@ -395,7 +398,7 @@ def test_toolbox_metal_get_bounds_of_path_and_poly_tables(self):
def test_toolbox_metal_ensure_component_box_smaller_than_chip_box_(self):
"""Test functionality of ensure_component_box_smaller_than_chip_box in toolbox_metal.py"""
- ls_file_path = ("./qiskit_metal/tests/test_data/planar_chip.txt")
+ ls_file_path = TEST_DATA / 'planar_chip.txt'
multiplanar_design = MultiPlanar(metadata={},
overwrite_enabled=True,
layer_stack_filename=ls_file_path)
@@ -436,7 +439,7 @@ def test_toolbox_metal_ensure_component_box_smaller_than_chip_box_(self):
def test_toolbox_metal_get_box_for_xy_bounds(self):
"""Test functionality of get_box_for_xy_bounds in toolbox_metal.py."""
- ls_file_path = ("./qiskit_metal/tests/test_data/planar_chip.txt")
+ ls_file_path = TEST_DATA / 'planar_chip.txt'
multiplanar_design = MultiPlanar(metadata={},
overwrite_enabled=True,
layer_stack_filename=ls_file_path)
@@ -469,7 +472,7 @@ def test_toolbox_metal_get_box_for_xy_bounds(self):
def test_toolbox_metal_are_all_chipnames_in_design(self):
"""Test functionality of are_all_chipnames_in_design in toolbox_metal.py."""
- ls_file_path = ("./qiskit_metal/tests/test_data/planar_chip.txt")
+ ls_file_path = TEST_DATA / 'planar_chip.txt'
multiplanar_design = MultiPlanar(metadata={},
overwrite_enabled=True,
layer_stack_filename=ls_file_path)
@@ -502,7 +505,7 @@ def test_toolbox_metal_are_all_chipnames_in_design(self):
def test_toolbox_metal_get_x_y_for_chip(self):
"""Test functionality of get_x_y_for_chip in toolbox_metal.py."""
- ls_file_path = ("./qiskit_metal/tests/test_data/planar_chip.txt")
+ ls_file_path = TEST_DATA / 'planar_chip.txt'
multiplanar_design = MultiPlanar(metadata={},
overwrite_enabled=True,
layer_stack_filename=ls_file_path)
@@ -537,7 +540,7 @@ def test_toolbox_metal_get_x_y_for_chip(self):
def test_toolbox_metal_chip_names_not_in_design(self):
"""Test functionality of chip_names_not_in_design in toolbox_metal.py."""
- ls_file_path = ("./qiskit_metal/tests/test_data/planar_chip.txt")
+ ls_file_path = TEST_DATA / 'planar_chip.txt'
multiplanar_design = MultiPlanar(metadata={},
overwrite_enabled=True,
layer_stack_filename=ls_file_path)
@@ -563,7 +566,7 @@ def test_toolbox_metal_chip_names_not_in_design(self):
def test_toolbox_metal_chip_size_not_in_chipname_within_design(self):
"""Test functionality of chip_size_not_in_chipname_within_design in toolbox_metal.py."""
- ls_file_path = ("./qiskit_metal/tests/test_data/planar_chip.txt")
+ ls_file_path = TEST_DATA / 'planar_chip.txt'
multiplanar_design = MultiPlanar(metadata={},
overwrite_enabled=True,
layer_stack_filename=ls_file_path)
@@ -587,7 +590,7 @@ def test_toolbox_metal_chip_size_not_in_chipname_within_design(self):
def test_toolbox_metal_get_layer_datatype_when_fill_is_true(self):
"""Test functionality of get_layer_datatype_when_fill_is_true in toolbox_metal.py."""
- ls_file_path = ("./qiskit_metal/tests/test_data/planar_chip.txt")
+ ls_file_path = TEST_DATA / 'planar_chip.txt'
multiplanar_design = MultiPlanar(metadata={},
overwrite_enabled=True,
layer_stack_filename=ls_file_path)
@@ -629,7 +632,7 @@ def test_toolbox_metal_get_layer_datatype_when_fill_is_true(self):
def test_toolbox_metal_get_properties_for_layer_datatype(self):
"""Test functionality of get_properties_for_layer_datatype in toolbox_metal.py."""
- ls_file_path = ("./qiskit_metal/tests/test_data/planar_chip.txt")
+ ls_file_path = TEST_DATA / 'planar_chip.txt'
multiplanar_design = MultiPlanar(metadata={},
overwrite_enabled=True,
layer_stack_filename=ls_file_path)
@@ -660,7 +663,7 @@ def test_toolbox_metal_get_properties_for_layer_datatype(self):
def test_toolbox_metal_is_layer_data_unique(self):
"""Test functionality of is_layer_data_unique in toolbox_metal.py."""
- ls_file_path = ("./qiskit_metal/tests/test_data/planar_chip.txt")
+ ls_file_path = TEST_DATA / 'planar_chip.txt'
multiplanar_design = MultiPlanar(metadata={},
overwrite_enabled=True,
layer_stack_filename=ls_file_path)
@@ -685,7 +688,7 @@ def test_toolbox_metal_is_layer_data_unique(self):
def test_toolbox_metal_read_csv_df(self):
"""Test functionality of read_csv_df in toolbox_metal.py."""
- ls_file_path = ("./qiskit_metal/tests/test_data/planar_chip.txt")
+ ls_file_path = TEST_DATA / 'planar_chip.txt'
multiplanar_design = MultiPlanar(metadata={},
overwrite_enabled=True,
layer_stack_filename=ls_file_path)
@@ -710,7 +713,7 @@ def test_toolbox_metal_read_csv_df(self):
def test_toolbox_metal_get_unique_chip_names(self):
"""Test functionality of get_unique_chip_names in toolbox_metal.py."""
- ls_file_path = ("./qiskit_metal/tests/test_data/planar_chip.txt")
+ ls_file_path = TEST_DATA / 'planar_chip.txt'
multiplanar_design = MultiPlanar(metadata={},
overwrite_enabled=True,
layer_stack_filename=ls_file_path)
@@ -735,7 +738,7 @@ def test_toolbox_metal_get_unique_chip_names(self):
def test_toolbox_metal_get_unique_layer_ints(self):
"""Test functionality of get_unique_layer_ints in toolbox_metal.py."""
- ls_file_path = ("./qiskit_metal/tests/test_data/planar_chip.txt")
+ ls_file_path = TEST_DATA / 'planar_chip.txt'
multiplanar_design = MultiPlanar(metadata={},
overwrite_enabled=True,
layer_stack_filename=ls_file_path)
@@ -760,7 +763,7 @@ def test_toolbox_metal_get_unique_layer_ints(self):
def test_toolbox_metal_warning_properties(self):
"""Test functionality of _warning_properties in toolbox_metal.py."""
- ls_file_path = ("./qiskit_metal/tests/test_data/planar_chip.txt")
+ ls_file_path = TEST_DATA / 'planar_chip.txt'
multiplanar_design = MultiPlanar(metadata={},
overwrite_enabled=True,
layer_stack_filename=ls_file_path)
@@ -785,7 +788,7 @@ def test_toolbox_metal_warning_properties(self):
def test_toolbox_metal_warning_search(self):
"""Test functionality of _warning_search in toolbox_metal.py."""
- ls_file_path = ("./qiskit_metal/tests/test_data/planar_chip.txt")
+ ls_file_path = TEST_DATA / 'planar_chip.txt'
multiplanar_design = MultiPlanar(metadata={},
overwrite_enabled=True,
layer_stack_filename=ls_file_path)
@@ -810,7 +813,7 @@ def test_toolbox_metal_warning_search(self):
def test_toolbox_metal_warning_search_minus_chip(self):
"""Test functionality of _warning_search_minus_chip in toolbox_metal.py."""
- ls_file_path = ("./qiskit_metal/tests/test_data/planar_chip.txt")
+ ls_file_path = TEST_DATA / 'planar_chip.txt'
multiplanar_design = MultiPlanar(metadata={},
overwrite_enabled=True,
layer_stack_filename=ls_file_path)
@@ -835,7 +838,7 @@ def test_toolbox_metal_warning_search_minus_chip(self):
def test_toolbox_metal_layer_stack_handler_pilot_error(self):
"""Test functionality of layer_stack_handler_pilot_error in toolbox_metal.py."""
- ls_file_path = ("./qiskit_metal/tests/test_data/planar_chip.txt")
+ ls_file_path = TEST_DATA / 'planar_chip.txt'
multiplanar_design = MultiPlanar(metadata={},
overwrite_enabled=True,
layer_stack_filename=ls_file_path)
diff --git a/qiskit_metal/toolbox_metal/about.py b/qiskit_metal/toolbox_metal/about.py
index 209c9c58d..71de1c8cf 100644
--- a/qiskit_metal/toolbox_metal/about.py
+++ b/qiskit_metal/toolbox_metal/about.py
@@ -47,8 +47,8 @@ def about():
str: About message
"""
import qiskit_metal
- from PySide2.QtCore import __version__ as QT_VERSION_STR
- from PySide2 import __version__ as PYSIDE_VERSION_STR
+ from PySide6.QtCore import __version__ as QT_VERSION_STR
+ from PySide6 import __version__ as PYSIDE_VERSION_STR
try:
import matplotlib
@@ -84,7 +84,7 @@ def about():
GUI
____________________________________
- PySide2 version {PYSIDE_VERSION_STR}
+ PySide6 version {PYSIDE_VERSION_STR}
Qt version {QT_VERSION_STR}
SIP version {SIP_VERSION_STR}
diff --git a/qiskit_metal/toolbox_python/display.py b/qiskit_metal/toolbox_python/display.py
index 8f4aa7431..e8de81895 100644
--- a/qiskit_metal/toolbox_python/display.py
+++ b/qiskit_metal/toolbox_python/display.py
@@ -112,7 +112,7 @@ def get_screenshot(self: 'QMainWindow',
do_display (bool): True to display the file. Defaults to True.
disp_ops (dict): Disctionary of options. Defaults to None.
"""
- from PySide2.QtWidgets import QApplication, QMainWindow
+ from PySide6.QtWidgets import QApplication, QMainWindow
path = Path(name).resolve()
diff --git a/requirements-dev.txt b/requirements-dev.txt
index 5013de879..472a3a5c6 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -1,20 +1,20 @@
# Dev tools
-jupyter==1.0.0
-jupyterlab==3.6.1
+jupyter>=1.0.0
+jupyterlab>=3.6.1
# Build tools
-wheel==0.38.4
+wheel>=0.38.4
-# Formatters
-pylint==2.16.2
-yapf==0.32.0
+# Formatters and linters
+pylint>=2.16.2
+yapf>=0.32.0
# Doc Build
sphinx>=6.0.0
-numpydoc==1.5.0
-nbsphinx==0.8.6
+numpydoc>=1.5.0
+nbsphinx>=0.8.6
qiskit-sphinx-theme~=1.16.0
sphinx-intl~=2.1.0
# Unit tests
-pytest==7.2.1
+pytest~=7.2.1
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
index 70cfeb2d5..ca4fa4602 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,22 +1,21 @@
-addict==2.4.0
-descartes==1.1.0
-gdspy==1.6.12
-geopandas==0.12.2
-ipython==8.10.0
-matplotlib==3.7.0
-numpy==1.24.2
+addict>=2.4.0
+descartes>=1.1.0
+gdstk>=0.9
+geopandas>=0.12.2
+ipython>=8.10.0
+matplotlib>=3.7.0
+numpy>=1.24.2
pandas==1.5.3
-pint==0.20.1
+pint~=0.20.1
pyEPR-quantum==0.8.5.7
-pygments==2.14.0
-pyside2==5.15.2.1
-qdarkstyle==3.1
-qutip==4.7.1
-scipy==1.10.0
-shapely==2.0.1
-scqubits==3.1.0
-gmsh==4.11.1
-pyaedt==0.6.46
-pyyaml==6.0
-cython<3.0.0
-# jupyter (if you need a fresh install) or ipykernel (if you prefer to make of this a new kernel to use from an existing jupyter install)
+pygments>=2.14.0
+pyside6
+qdarkstyle~=3.1
+qutip>=4.7.1
+scipy~=1.10.0
+shapely~=2.0.1
+scqubits~=3.1.0
+gmsh~=4.11.1
+pyaedt>=0.6.46
+pyyaml>=6.0
+cython<3.0.0
\ No newline at end of file
diff --git a/setup.py b/setup.py
index c5410fe34..7fc686af0 100644
--- a/setup.py
+++ b/setup.py
@@ -11,6 +11,7 @@
-v, --verbose
Give more output.
"""
+
# pylint: disable=invalid-name
from pathlib import Path
@@ -27,7 +28,7 @@
setup(
name="qiskit_metal",
- version="0.1.5",
+ version="0.5.0",
description="Qiskit Metal | for quantum device design & analysis",
long_description=long_description,
long_description_content_type="text/markdown",
diff --git a/tutorials/Appendix B Quick topics/Managing variables.ipynb b/tutorials/Appendix B Quick topics/Managing variables.ipynb
index 6762e2067..422c773ee 100644
--- a/tutorials/Appendix B Quick topics/Managing variables.ipynb
+++ b/tutorials/Appendix B Quick topics/Managing variables.ipynb
@@ -114,7 +114,7 @@
"metadata": {},
"outputs": [],
"source": [
- "from PySide2.QtWidgets import QAbstractItemView\n",
+ "from PySide6.QtWidgets import QAbstractItemView\n",
"table.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel)\n",
"table.setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel)"
]
diff --git a/tutorials/resources/skeleton_renderer.py b/tutorials/resources/skeleton_renderer.py
index 16a6e09a1..25fd37e32 100644
--- a/tutorials/resources/skeleton_renderer.py
+++ b/tutorials/resources/skeleton_renderer.py
@@ -12,32 +12,17 @@
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
-from qiskit_metal import Dict
-import math
-from scipy.spatial import distance
-import os
-import gdspy
-import geopandas
-import shapely
-
-from shapely.geometry import LineString as LineString
-from copy import deepcopy
-from operator import itemgetter
-from typing import TYPE_CHECKING
-from typing import Dict as Dict_
-from typing import List, Tuple, Union, Any, Iterable
-import pandas as pd
-from pandas.api.types import is_numeric_dtype
+from typing import TYPE_CHECKING, Tuple
-import numpy as np
+import geopandas
+from qiskit_metal import Dict
from qiskit_metal.renderers.renderer_base import QRenderer
-from qiskit_metal.toolbox_metal.parsing import is_true
from qiskit_metal import config
if not config.is_building_docs():
from qiskit_metal.toolbox_python.utility_functions import can_write_to_path
- from qiskit_metal.toolbox_python.utility_functions import get_range_of_vertex_to_not_fillet
+ from qiskit_metal.toolbox_python.utility_functions import get_range_of_vertex_to_not_fillet # pylint: disable=unused-import
if TYPE_CHECKING:
# For linting typechecking, import modules that can't be loaded here under normal conditions.
@@ -84,7 +69,8 @@ class QSkeletonRenderer(QRenderer):
element_table_data = dict(
# Example of adding a column named "skeleton_a_column_name"
# with default values of "a_default_value" to the junction table.
- # Note: QSkeletonRenderer.name is prefixed to "a_column_name" when the table is appended by QComponents.
+ # Note: QSkeletonRenderer.name is prefixed
+ # to "a_column_name" when the table is appended by QComponents.
junction=dict(a_column_name='a_default_value'))
"""element extensions dictionary element_extensions = dict() from base class"""
@@ -98,7 +84,8 @@ def __init__(self,
Args:
design (QDesign): Use QGeometry within QDesign to obtain elements.
initiate (bool, optional): True to initiate the renderer. Defaults to True.
- render_template (Dict, optional): Typically used by GUI for template options for GDS. Defaults to None.
+ render_template (Dict, optional): Typically used by GUI for
+ template options for GDS. Defaults to None.
render_options (Dict, optional): Used to overide all options. Defaults to None.
"""
@@ -138,7 +125,7 @@ def _can_write_to_path(self, file: str) -> int:
Returns:
int: 1 if access is allowed. Else returns 0, if access not given.
"""
- status, directory_name = can_write_to_path(file)
+ status, directory_name = can_write_to_path(file) # pylint: disable=possibly-used-before-assignment
if status:
return 1
@@ -153,8 +140,9 @@ def check_qcomps(self,
that the name of component exists in QDesign.
Args:
- highlight_qcomponents (list, optional): List of strings which denote the name of QComponents to render.
- Defaults to []. Empty list means to render entire design.
+ highlight_qcomponents (list, optional): List of strings which
+ denote the name of QComponents to render.
+ Defaults to []. Empty list means to render entire design.
Returns:
Tuple[list, int]:
@@ -173,10 +161,12 @@ def check_qcomps(self,
return unique_qcomponents, 1
# For Subtraction bounding box.
- # If list passed to export is the whole chip, then want to use the bounding box from design planar.
- # If list is subset of chip, then caluclate a custom bounding box and scale it.
+ # If list passed to export is the whole chip,
+ # then want to use the bounding box from design planar.
+ # If list is subset of chip, then caluclate a
+ # custom bounding box and scale it.
- if len(unique_qcomponents) == len(self.design._components):
+ if len(unique_qcomponents) == len(self.design._components): # pylint: disable=protected-access
# Since user wants all of the chip to be rendered, use the design.planar bounding box.
unique_qcomponents[:] = []
@@ -191,9 +181,11 @@ def get_qgeometry_tables_for_skeleton(self,
Duplicate names in hightlight_qcomponents will be removed without warning.
Args:
- highlight_qcomponents (list): List of strings which denote the name of QComponents to render.
+ highlight_qcomponents (list): List of strings which denote the
+ name of QComponents to render.
If empty, render all comonents in design.
- If QComponent names are dupliated, duplicates will be ignored.
+ If QComponent names are dupliated,
+ duplicates will be ignored.
Returns:
Tuple[int, list]:
@@ -207,7 +199,8 @@ def get_qgeometry_tables_for_skeleton(self,
return 1, table_names_for_highlight
for chip_name in self.chip_info:
for table_name in self.design.qgeometry.get_element_types():
- # Get table for chip and table_name, and reduce to keep just the list of unique_qcomponents.
+ # Get table for chip and table_name, and reduce
+ # to keep just the list of unique_qcomponents.
table = self.get_table(table_name, unique_qcomponents,
chip_name)
@@ -263,8 +256,9 @@ def write_qgeometry_table_names_to_file(self,
Args:
file_name (str): File name which can also include directory path.
If the file exists, it will be overwritten.
- highlight_qcomponents (list): List of strings which denote the name of QComponents to render.
- If empty, render all qcomponents in qdesign.
+ highlight_qcomponents (list): List of strings which denote the
+ name of QComponents to render.
+ If empty, render all qcomponents in qdesign.
Returns:
int: 0=file_name can not be written, otherwise 1=file_name has been written
@@ -286,7 +280,7 @@ def write_qgeometry_table_names_to_file(self,
total_bones_text = 'Number of bones: ' + total_bones + '\n'
- if (status == 0):
+ if status == 0:
skeleton_out = open(file_name, 'w')
skeleton_out.writelines(total_bones_text)
skeleton_out.writelines(table_names_used)