Repository navigation
New path tree #1048
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
Merged
dwhswenson
merged 18 commits into
openpathsampling:master
from
dwhswenson:new_path_tree
Aug 31, 2024
Merged
New path tree #1048
Changes from 12 commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
021ec99
Start to new path trees
dwhswenson 990dc9b
fix path tree for two-way TPS connectors
dwhswenson 04bef1d
Merge branch 'master' of github.com:openpathsampling/openpathsampling…
dwhswenson 95f1aa0
First implementation of the SVG renderer
dwhswenson 571f497
maybe convert separate plotters into subclasses?
dwhswenson 95c2e30
refactor of new plotters
dwhswenson 6d6c1af
more updates to refactor new path trees
dwhswenson 16d26b8
Merge branch 'master' of github.com:openpathsampling/openpathsampling…
dwhswenson 7ad1881
minor docs update
dwhswenson f473daf
Merge remote-tracking branch 'upstream/master' into new_path_tree
dwhswenson 88b2f9a
Merge remote-tracking branch 'upstream/master' into new_path_tree
dwhswenson 64aad6d
fix up some plotting errors
dwhswenson c7029b6
Update openpathsampling/experimental/path_tree/path_tree.py
dwhswenson 16ede3b
remove commented code; use .plot method
dwhswenson 16c2a89
fix typo in make_layout_blocks; warn non-use
dwhswenson dc67ad4
remove refactored code
dwhswenson 3622d00
Update openpathsampling/experimental/path_tree/options.py
dwhswenson f4b714f
remove incorrect docstring
dwhswenson File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| from .path_tree import PathTree | ||
| from . import mpl | ||
| from . import svg |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,108 @@ | ||
| from functools import partial | ||
| from .options import canonicalize_mover | ||
| from .plotter import PathTreePlotter | ||
|
|
||
| # In addition to the standard `draw_trajectory` and `draw_connector` methods | ||
| # required of all PathTree plot styles, plot styles based on matplotlib | ||
| # should have the attribute `ax`, which returns the `Axes` object they plot | ||
| # into. | ||
|
|
||
|
|
||
|
|
||
| class MPLPlottingStyle(PathTreePlotter): | ||
| """Abstract base class for matplotlib-based path tree plotting styles. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| ax : :class:`.matplotlib.Axes` | ||
| Axes object to plot into | ||
| """ | ||
| def __init__(self, ax=None, options=None): | ||
| try: | ||
| import matplotlib.pyplot as plt | ||
| except ImportError: | ||
| raise RuntimeError("matplotlib is not installed") | ||
|
|
||
| super().__init__(options) | ||
| if ax is None: | ||
| _, ax = plt.subplots() | ||
| self.ax = ax | ||
|
|
||
| # @staticmethod | ||
| # def step_basics(step, options): | ||
| # mover = canonicalize_mover(step.mover) | ||
| # mover_options = options.movers[mover] | ||
| # color = mover_options.color | ||
| # plot_segments = mover_options.get_left_right(step) | ||
| # return mover, color, plot_segments | ||
|
|
||
| def draw_trajectory(self, row, step, options): | ||
| raise NotImplementedError() | ||
|
|
||
| def draw_connector(self, x, bottom, top, step): | ||
| mover = canonicalize_mover(step.mover) | ||
| if mover in self.CONNECTOR_FIXES: | ||
| x = self.CONNECTOR_FIXES[mover](x) | ||
|
|
||
| self.ax.plot([x,x], [-bottom, -top], color='k') | ||
|
|
||
|
|
||
| ### ThinLines plotting style ############################################### | ||
|
|
||
| class ThinLines(MPLPlottingStyle): | ||
| """ThinLines plotting style for matplotlib-based path trees. | ||
|
|
||
| This is a plotting style based on using `ax.plot` and with the style | ||
| choice that the shooting point is always represented at the middle of | ||
| its frame. This needs to us filling half of the shooting point frame so | ||
| that the trajectory line intersects the shooting point connector. This | ||
| is accomplished by the ``thin_lines_fix`` function. | ||
|
sroet marked this conversation as resolved.
Resolved
|
||
|
|
||
| """ | ||
| PLOT_TYPE = "trajectory" | ||
| def draw_trajectory(self, row, step): | ||
| mover = canonicalize_mover(step.mover) | ||
| plot_segments, color = self.get_step_plot_details(step) | ||
|
|
||
| for left, right in plot_segments: | ||
| self.ax.plot([left - 0.5, right - 0.5], [-row] * 2, lw=3, | ||
| color=color) | ||
|
|
||
|
|
||
|
|
||
| ### Blocks plotting style ################################################## | ||
|
|
||
| from matplotlib.patches import Rectangle | ||
|
|
||
| class Blocks(MPLPlottingStyle): | ||
| """Blocks plotting style for matplotlib-based path trees. | ||
|
|
||
| The Blocks plotting style uses rectangular patches for each snapshot. | ||
| """ | ||
| PLOT_TYPE = "snapshot" | ||
| def __init__(self, ax=None, options=None, *, block_size=(0.8, 0.6)): | ||
| super().__init__(ax, options) | ||
| self.block_size = block_size | ||
|
|
||
| def draw_trajectory(self, row, step): | ||
| """ | ||
| Parameters | ||
| ---------- | ||
| row : int | ||
| the row number (counting from the top) for this step | ||
| """ | ||
| mover = canonicalize_mover(step.mover) | ||
| plot_segments, color = self.get_step_plot_details(step) | ||
| # first we draw the background line | ||
| for left, right in plot_segments: | ||
| self.ax.plot([left - 0.5, right - 0.5], [-row]*2, color=color) | ||
|
|
||
| # now we draw the boxes | ||
| for left, right in plot_segments: | ||
| width, height = self.block_size | ||
| y = - row - height / 2 | ||
| for snap in range(left, right): | ||
| self.ax.add_patch( | ||
| Rectangle((snap - width / 2, y), width, height, | ||
| color=color) | ||
| ) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,104 @@ | ||
| def canonicalize_mover(mover): | ||
| if mover is not None: | ||
| return mover.__class__.__name__ | ||
|
|
||
|
|
||
| class OptionDict: | ||
| def __init__(self, dictionary, default): | ||
| self.dictionary = dictionary | ||
| self.default = default | ||
|
|
||
| def __getitem__(self, item): | ||
| try: | ||
| return self.dictionary[item] | ||
| except KeyError: | ||
| return self.default | ||
|
|
||
| def __getattr__(self, attr): | ||
| if attr in ['dictionary', 'default']: | ||
| return object.__getattribute__(self, attr) | ||
| return self[attr] | ||
|
|
||
| def __setattr__(self, key, value): | ||
| if key not in ['dictionary', 'default']: | ||
| self.dictionary[key] = value | ||
| else: | ||
| object.__setattr__(self, key, value) | ||
|
|
||
| def __repr__(self): | ||
| return (f"OptionDict({repr(self.dictionary)}, " | ||
| f"default={repr(self.default)}") | ||
|
sroet marked this conversation as resolved.
Resolved
|
||
|
|
||
|
|
||
| class PathTreeMoverOptions(object): | ||
| def __init__(self, show='full', color='#0f0'): | ||
| self.show = show | ||
| self.color = color | ||
|
|
||
| self.get_left_right_methods = { | ||
| 'full': self.get_left_right_full, | ||
| 'new': self.get_left_right_new, | ||
| } | ||
|
|
||
| @staticmethod | ||
| def get_left_right_full(step): | ||
| offset = step.offset if step.offset is not None else 0 | ||
| return [(offset, offset + len(step.trajectory))] | ||
|
|
||
| @staticmethod | ||
| def get_left_right_new(step): | ||
| offset = step.offset if step.offset is not None else 0 | ||
| return [(offset + start, offset + stop) | ||
| for start, stop in step.segments.new] | ||
|
|
||
| def get_left_right(self, step): | ||
| get_left_right = self.get_left_right_methods[self.show] | ||
| return get_left_right(step) | ||
|
|
||
| def __repr__(self): | ||
| return (f"{self.__class__.__name__}(show='{self.show}', " | ||
| f"color='{self.color})") | ||
|
|
||
|
|
||
| class PathTreeOptions(object): | ||
| def __init__(self, movers, rejected, allowed_movers, forbidden_movers): | ||
| self.movers = movers | ||
| self.rejected = rejected | ||
| self.allowed_movers = allowed_movers | ||
| self.forbidden_movers = forbidden_movers | ||
|
|
||
| def _skip_step(self, step): | ||
| mover = canonicalize_mover(step.mover) | ||
| include_rejected = self.rejected != 'hidden' | ||
| skip_rejected = not include_rejected and not step.accepted | ||
| skip_allowed = self.allowed_movers and mover not in allowed | ||
| skip_forbidden = self.forbidden_movers and mover in forbidden | ||
|
dwhswenson marked this conversation as resolved.
Resolved
|
||
| return skip_rejected or skip_allowed or skip_forbidden | ||
|
|
||
| def filter_tree_steps(self, tree_steps): | ||
| for step in tree_steps: | ||
| if not self._skip_step(step): | ||
| yield step | ||
|
|
||
|
|
||
| def create_default_options(): | ||
| two_way_options = PathTreeMoverOptions(color='#9A63EE') | ||
| movers = OptionDict( | ||
| { | ||
| 'ForwardShootMover': PathTreeMoverOptions(show='new', | ||
| color='#00f'), | ||
| 'BackwardShootMover': PathTreeMoverOptions(show='new', | ||
| color='#f00'), | ||
| 'BackwardFirstTwoWayShootingMover': two_way_options, | ||
| 'ForwardFirstTwoWayShootingMover': two_way_options, | ||
| None: PathTreeMoverOptions(color='#808080'), | ||
|
|
||
| }, | ||
| default=PathTreeMoverOptions(color="#377E22") | ||
| ) | ||
| return PathTreeOptions( | ||
| movers=movers, | ||
| rejected='hidden', | ||
| allowed_movers=None, | ||
| forbidden_movers=None, | ||
| ) | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.