-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Change style of DAG generated in dag_drawer() #13253
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Thank you for opening a new pull request. Before your PR can be merged it will first need to pass continuous integration tests and be reviewed. Sometimes the review process can be slow, so please be patient. While you're waiting, please feel free to review other open PRs. While only a subset of people are authorized to approve pull requests for merging, everyone is encouraged to review open pull requests. Doing reviews helps reduce the burden on the core team and helps make the project's code better for everyone. One or more of the following people are relevant to this code:
|
Pull Request Test Coverage Report for Build 15331899554Details
💛 - Coveralls |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for getting this started. I left an inline comment about the high level interface. I'm a bit concerned with how low level the current interface is and that it would require understanding how graphviz is used internally by dag_drawer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great, thank you for these additions. I wonder whether we should consider using FileSpecifier
(such as File, Path, etc) as an alternative input for load_style()
. I feel like it might benefit from not having to check whether the file exists or not. See the comments in my review.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks better so far, I do have a concern about the reuse of code for the dagstyle.py
file and some methods, so I left some tips to consider.
@raynelfss I attempted to resolve the code duplication issues in 9d6b0ec
These changes decouple the |
…r maximum customizability
Co-authored-by: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com>
* Adds functionality to load_style to support throwing errors if style is not identified * Standardizes load_style input to ingest StyleDict as a type, and DefaultStyle as an object
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me, thank you for your work. I will look for a secondary reviewer to make sure visualization is in order :)
|
||
def load_style( | ||
style: Union[dict, str, None], | ||
style_dict: type[StyleDict], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe you'd want to rename this to style_dict_type
? It makes more sense to have it in the name that this argument is type based.
Co-authored-by: Luciano Bello <766693+1ucian0@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I quickly breezed through the code once again, just found one minor detail.
# Search for file in 'styles' dir, then config_path, and finally the current directory | ||
style_name = style_name + ".json" | ||
style_paths = [] | ||
|
||
default_path = default_style.DEFAULT_STYLE_PATH / style_name | ||
style_paths.append(default_path) | ||
|
||
# check configured paths, if there are any | ||
if config: | ||
config_path = config.get(user_config_path_opt, "") | ||
if config_path: | ||
for path in config_path: | ||
style_paths.append(Path(path) / style_name) | ||
|
||
# check current directory | ||
cwd_path = Path("") / style_name | ||
style_paths.append(cwd_path) | ||
|
||
for path in style_paths: | ||
# expand ~ to the user directory and check if the file exists | ||
exp_user = path.expanduser() | ||
if os.path.isfile(exp_user): | ||
try: | ||
with open(exp_user) as infile: | ||
json_style = json.load(infile) | ||
|
||
current_style = style_dict(json_style) | ||
break | ||
except json.JSONDecodeError as err: | ||
warn( | ||
f"Could not decode JSON in file '{path}': {str(err)}. " | ||
"Will use default style.", | ||
UserWarning, | ||
2, | ||
) | ||
break | ||
except (OSError, FileNotFoundError): | ||
warn( | ||
f"Error loading JSON file '{path}'. Will use default style.", | ||
UserWarning, | ||
2, | ||
) | ||
break |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we gain any benefit from pre-computing the paths here, we might be able to fast-track it by performing each step separately and only continue if the next one hasn't been found. But I also understand this wasn't introduced by you, so it should stay as it is for now.
qiskit/visualization/style.py
Outdated
@@ -0,0 +1,223 @@ | |||
# This code is part of Qiskit. | |||
# | |||
# (C) Copyright IBM 2019. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this copyright comment change as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it's a new file that you added, it should have the current year.
Co-authored-by: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to the best of my abilities!
* Added 'custom' style that exposes graphviz customization functions for maximum customizability * Added type hints to function calls * Added docs * Adds tests for dag_drawer * Fixed invalid exceptions caught by test * ran formatter and linter on code * Formatted code and test to abide by pylint standards * Fix typo in docs for graph_attr kwarg * placed functionality into stylesheets * Added error correction to dag visualization * rewrote tests to work with new stylesheet method * Added color templates for DAGs * Added common style templates for DAGs in qiskit/visualization/dag/styles * Loaded styles from stylesheets to color DAG * Fixed bug where 'plain' DAGs did not label nodes * Re-format docs for dag_visualization * reformatted dag_visualization.py * Ran linting * Added artifacts for docs to recognize stylesheets * Fixed errors to match original invocation of dag_drawer() * Fixed small import formatting issue * Adds release notes for PR * Modified DagDependency code to match previous impl * Apply suggestions from code review Co-authored-by: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com> * merge load_style implementations * Ran linting * removed unused imports * Added docs to new load_style function * Ran linting * Refactored style classes to add types * moved load_style function to qiskit/visualization/style.py * Fixed linting issues * resolves dependency cycle * Apply suggestions from code review Co-authored-by: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com> * merge load_style implementations * fixed edge case with failing default style initialization * Fixes type init issues * Adds functionality to load_style to support throwing errors if style is not identified * Standardizes load_style input to ingest StyleDict as a type, and DefaultStyle as an object * ran black formatting * Updated documentation for load_style * Ran linting * Apply suggestions from code review Co-authored-by: Luciano Bello <766693+1ucian0@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com> * Update style.py --------- Co-authored-by: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com> Co-authored-by: Luciano Bello <766693+1ucian0@users.noreply.github.com>
Summary
Closes #13106
Adds non-breaking interface to
dag_drawer()
to allow Qiskit users to customize the colors of DAGs.Details and comments
I created stylesheets for
dag_drawer()
, that works similarly to howcircuit_drawer
does.Here is an example:
The code above generates this DAG: