Skip to content
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

feat: render ProblemSet as DOT #86

Merged
merged 7 commits into from
Jul 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@
"heli",
"heurisch",
"imag",
"ipykernel",
"isfunction",
"isinstance",
"jpsi",
Expand Down
45 changes: 37 additions & 8 deletions docs/usage/reaction.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,42 @@
"metadata": {},
"outputs": [],
"source": [
"problem_sets = stm.create_problem_sets()"
"problem_sets = stm.create_problem_sets()\n",
"sorted(problem_sets, reverse=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To get an idea of what these {class}`.ProblemSet`s represent, you can use {func}`.asdot` and {doc}`graphviz:index` to visualize one of them (see {doc}`usage/visualize`):"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import graphviz\n",
"\n",
"from qrules import io\n",
"\n",
"some_problem_set = problem_sets[60.0][0]\n",
"dot = io.asdot(some_problem_set, render_node=True)\n",
"graphviz.Source(dot)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Each {class}`.ProblemSet` provides a mapping of {attr}`~.ProblemSet.initial_facts` that represent the initial and final states with spin projections. The nodes and edges in between these {attr}`~.ProblemSet.initial_facts` are still to be generated. This will be done from the provided {attr}`~.ProblemSet.solving_settings` ({class}`~.GraphSettings`). There are two mechanisms there:\n",
"\n",
"1. One the one hand, the {attr}`.EdgeSettings.qn_domains` and {attr}`.NodeSettings.qn_domains` contained in the {class}`~.GraphSettings` define the **domain** over which quantum number sets can be generated.\n",
"2. On the other, the {attr}`.EdgeSettings.rule_priorities` and {attr}`.NodeSettings.rule_priorities` in {class}`~.GraphSettings` define which **{mod}`.conservation_rules`** are used to determine which of the sets of generated quantum numbers are valid.\n",
"\n",
"Together, these two constraints allow the {class}`.StateTransitionManager` to generate a number of {class}`.StateTransitionGraph`s that comply with the selected {mod}`.conservation_rules`."
]
},
{
Expand Down Expand Up @@ -362,10 +397,6 @@
},
"outputs": [],
"source": [
"import graphviz\n",
"\n",
"from qrules import io\n",
"\n",
"dot = io.asdot(reaction, collapse_graphs=True, render_node=False)\n",
"graphviz.Source(dot)"
]
Expand Down Expand Up @@ -401,8 +432,6 @@
"metadata": {},
"outputs": [],
"source": [
"from qrules import io\n",
"\n",
"io.asdict(reaction.transition_groups[0].topology)"
]
},
Expand Down Expand Up @@ -448,7 +477,7 @@
"metadata": {
"celltoolbar": "Raw Cell Format",
"kernelspec": {
"display_name": "Python 3",
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
Expand Down
80 changes: 73 additions & 7 deletions docs/usage/visualize.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"The {mod}`~qrules.io` module allows you to convert {class}`.StateTransitionGraph` and {class}`.Topology` instances to [DOT language](https://graphviz.org/doc/info/lang.html) with {func}`.asdot`. You can visualize its output with third-party libraries, such as [Graphviz](https://graphviz.org). This is particularly useful after running {meth}`~.StateTransitionManager.find_solutions`, which produces a {class}`.ReactionInfo` object with a {class}`.list` of {class}`.StateTransitionGraph` instances (see {doc}`/usage/reaction`)."
"The {mod}`~qrules.io` module allows you to convert {class}`.StateTransitionGraph`, {class}`.Topology` instances, and {class}`.ProblemSet`s to [DOT language](https://graphviz.org/doc/info/lang.html) with {func}`.asdot`. You can visualize its output with third-party libraries, such as [Graphviz](https://graphviz.org). This is particularly useful after running {meth}`~.StateTransitionManager.find_solutions`, which produces a {class}`.ReactionInfo` object with a {class}`.list` of {class}`.StateTransitionGraph` instances (see {doc}`/usage/reaction`)."
]
},
{
Expand Down Expand Up @@ -80,7 +80,7 @@
"source": [
"import graphviz\n",
"\n",
"from qrules import io\n",
"import qrules\n",
"from qrules.topology import create_isobar_topologies, create_n_body_topology"
]
},
Expand All @@ -91,7 +91,7 @@
"outputs": [],
"source": [
"topology = create_n_body_topology(2, 4)\n",
"graphviz.Source(io.asdot(topology, render_initial_state_id=True))"
"graphviz.Source(qrules.io.asdot(topology, render_initial_state_id=True))"
]
},
{
Expand All @@ -108,7 +108,7 @@
"outputs": [],
"source": [
"topologies = create_isobar_topologies(4)\n",
"graphviz.Source(io.asdot(topologies))"
"graphviz.Source(qrules.io.asdot(topologies))"
]
},
{
Expand All @@ -125,7 +125,7 @@
"outputs": [],
"source": [
"topologies = create_isobar_topologies(3)\n",
"graphviz.Source(io.asdot(topologies, render_node=False))"
"graphviz.Source(qrules.io.asdot(topologies, render_node=False))"
]
},
{
Expand All @@ -142,7 +142,7 @@
"outputs": [],
"source": [
"topologies = create_isobar_topologies(5)\n",
"dot = io.asdot(\n",
"dot = qrules.io.asdot(\n",
" topologies[0],\n",
" render_final_state_id=False,\n",
" render_resonance_id=True,\n",
Expand All @@ -154,6 +154,72 @@
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## {class}`.ProblemSet`s"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"As noted in {doc}`usage/reaction`, the {class}`.StateTransitionManager` provides more control than the façade function {func}`.generate_transitions`. One advantages, is that the {class}`.StateTransitionManager` first generates a set of {class}`.ProblemSet`s with {meth}`.create_problem_sets` that you can further configure if you wish."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"stm = qrules.StateTransitionManager(\n",
" initial_state=[\"J/psi(1S)\"],\n",
" final_state=[\"K0\", \"Sigma+\", \"p~\"],\n",
" formalism=\"canonical-helicity\",\n",
")\n",
"problem_sets = stm.create_problem_sets()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that the output of {meth}`.create_problem_sets` is a {obj}`dict` with {obj}`float` values as keys (representing the interaction strength) and {obj}`list`s of {obj}`.ProblemSet`s as values."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"sorted(problem_sets, reverse=True)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"len(problem_sets[60.0])"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"problem_set = problem_sets[60.0][0]\n",
"dot = qrules.io.asdot(problem_set, render_node=True)\n",
"graphviz.Source(dot)"
]
},
{
"cell_type": "markdown",
"metadata": {
"tags": []
},
"source": [
"## {class}`.StateTransition`s"
]
Expand Down Expand Up @@ -297,7 +363,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
Expand Down
13 changes: 10 additions & 3 deletions src/qrules/_implementers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""A collection of implementation tools that can be used accross all modules."""

from typing import Any, Callable
from typing import Any, Callable, Type, TypeVar

import attr

Expand All @@ -10,10 +10,17 @@
PrettyPrinter = Any


def implement_pretty_repr() -> Callable[[type], type]:
_DecoratedClass = TypeVar("_DecoratedClass")


def implement_pretty_repr() -> Callable[
[Type[_DecoratedClass]], Type[_DecoratedClass]
]:
"""Implement a pretty :code:`repr` in a `attr` decorated class."""

def decorator(decorated_class: type) -> type:
def decorator(
decorated_class: Type[_DecoratedClass],
) -> Type[_DecoratedClass]:
if not attr.has(decorated_class):
raise TypeError(
"Can only implement a pretty repr for a class created with attrs"
Expand Down
3 changes: 2 additions & 1 deletion src/qrules/io/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from qrules.particle import Particle, ParticleCollection
from qrules.topology import StateTransitionGraph, Topology
from qrules.transition import (
ProblemSet,
ReactionInfo,
State,
StateTransition,
Expand Down Expand Up @@ -126,7 +127,7 @@ def asdot(
"""
if isinstance(instance, StateTransition):
instance = instance.to_graph()
if isinstance(instance, (StateTransitionGraph, Topology)):
if isinstance(instance, (ProblemSet, StateTransitionGraph, Topology)):
return _dot.graph_to_dot(
instance,
render_node=render_node,
Expand Down
Loading