Skip to content

Commit

Permalink
Making one shared plotting function (#6)
Browse files Browse the repository at this point in the history
* making one shared plotting function
and fixing bug to display original pieces
Signed-off-by: vsoch <vsoch@users.noreply.github.com>
  • Loading branch information
vsoch committed Jun 21, 2021
1 parent 249f554 commit c7f640b
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 97 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ and **Merged pull requests**. Critical items to know are:
The versions coincide with releases on pip. Only major versions will be released as tags on Github.

## [0.0.x](https://github.com/vsoch/puzzles/tree/master) (0.0.x)
- creating one shared plotting function (0.0.13)
- make sure to return solved figure at end (0.0.12)
- refactor to have PhotoPuzzle model (object) (0.0.11)
- addition of CHANGELOG, logger, issue templates, etc.
Expand Down
12 changes: 4 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,10 @@ puzzle.metrics()
# Height : 360
# Number pieces : 252

# Shuffle the puzzle and show it (TODO, show in place first)
# Plot the original pieces
fig = puzzle.get_puzzle_figure()

# Shuffle the puzzle and show it
puzzle.shuffle()

# Now show the puzzle broken into pieces!
Expand Down Expand Up @@ -121,10 +124,3 @@ on the board. It would be cleaner to somehow combine these two.
Currently, if we display the image before shuffle it actually isn't perfect.
But I think it should be (and this is a bug) we would want to be able to
display the image, see that it's correct, and then shuffle.


### Display Functions

Currently we have redundant logic in the functions to show the puzzle pieces
in their current array, and then the solved solution. This should be
refactored into a shared display function.
38 changes: 32 additions & 6 deletions examples/avocado-puzzle.ipynb

Large diffs are not rendered by default.

70 changes: 38 additions & 32 deletions puzzles/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,13 @@ def generate_pieces(self):
"""
Given a loaded puzzle image, generate some number of pieces.
"""
for i in range(self.vertical_num_pieces):
for j in range(self.horizontal_num_pieces):
for i in range(self.horizontal_num_pieces):
for j in range(self.vertical_num_pieces):
# Split into pieces with dimensions x, y, and color
self.pieces.append(
self.image[
i * self.piece_height : (i + 1) * self.piece_height,
j * self.piece_width : (j + 1) * self.piece_width,
j * self.piece_height : (j + 1) * self.piece_height,
i * self.piece_width : (i + 1) * self.piece_width,
:,
]
)
Expand Down Expand Up @@ -266,56 +266,62 @@ def reset_covered_indices(self):
for (x, y), index in self.covered_places.items()
}

def get_puzzle_figure(self, title=None, show=True):
def plot_puzzle(self, n_rows, n_cols, plot_piece):
"""
Show the current state of the puzzle
Shared function to plot puzzle
"""
fig, axs = plt.subplots(self.vertical_num_pieces, self.horizontal_num_pieces)
fig.set_figheight(self.vertical_num_pieces)
fig.set_figwidth(self.horizontal_num_pieces)
for x in range(self.horizontal_num_pieces):
for y in range(self.vertical_num_pieces):
fig, axs = plt.subplots(n_rows, n_cols)
fig.set_figheight(n_rows)
fig.set_figwidth(n_cols)

for y, ax_row in enumerate(axs):
for x, ax in enumerate(ax_row):
plot_piece(ax, x, y)
ax = axs[y, x]
ax.imshow(self.pieces[y + x * self.vertical_num_pieces])
ax.xaxis.set_visible(False)
ax.axes.yaxis.set_visible(False)

# Set numbered columns and rows
for col, ax in enumerate(axs[0]):
ax.set_title(col)

for row, ax in enumerate(axs[:, 0]):
ax.set_ylabel(row)
ax.axes.yaxis.set_visible(True)
ax.axes.yaxis.set_ticks([])
return fig

def get_puzzle_figure(self):
"""
Show the current state of the puzzle.
This function plots self.pieces, not the puzzle solution.
"""

def plot_piece(ax, x, y):
ax.imshow(self.pieces[y + x * self.vertical_num_pieces])

return self.plot_puzzle(
self.vertical_num_pieces, self.horizontal_num_pieces, plot_piece
)

def get_solved_figure(self):
"""
Get figure for solved puzzle
"""
n_rows = max([loc[1] for loc in self.covered_places]) + 1
n_cols = max([loc[0] for loc in self.covered_places]) + 1
fig, axs = plt.subplots(n_rows, n_cols)
fig.set_figheight(n_rows)
fig.set_figwidth(n_cols)

for y, ax_row in enumerate(axs):
for x, ax in enumerate(ax_row):
if (x, y) in self.covered_places:
piece_index = self.covered_places[(x, y)]
ax.imshow(self.pieces[piece_index])
ax = axs[y, x]
ax.xaxis.set_visible(False)
ax.axes.yaxis.set_visible(False)
# The solved figure has a different function to plot the piece
def plot_covered_piece(ax, x, y):
if (x, y) in self.covered_places:
piece_index = self.covered_places[(x, y)]
ax.imshow(self.pieces[piece_index])

for col, ax in enumerate(axs[0]):
ax.set_title(col)

for row, ax in enumerate(axs[:, 0]):
ax.set_ylabel(row)
ax.axes.yaxis.set_visible(True)
ax.axes.yaxis.set_ticks([])
return fig
return self.plot_puzzle(
n_rows=max([loc[1] for loc in self.covered_places]) + 1,
n_cols=max([loc[0] for loc in self.covered_places]) + 1,
plot_piece=plot_covered_piece,
)

@property
def vertical_num_pieces(self):
Expand Down
2 changes: 1 addition & 1 deletion puzzles/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
__copyright__ = "Copyright 2018-2021, Vanessa Sochat"
__license__ = "MPL 2.0"

__version__ = "0.0.12"
__version__ = "0.0.13"
AUTHOR = "Vanessa Sochat"
AUTHOR_EMAIL = "vsoch@users.noreply.github.com"
NAME = "puzzles"
Expand Down
95 changes: 45 additions & 50 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,17 @@
# HELPER FUNCTIONS #############################################################
################################################################################


def get_lookup():
'''get version by way of sregistry.version, returns a
lookup dictionary with several global variables without
needing to import singularity
'''
lookup = dict()
version_file = os.path.join('puzzles', 'version.py')
version_file = os.path.join("puzzles", "version.py")
with open(version_file) as filey:
exec(filey.read(), lookup)
return lookup


# Read in requirements
def get_reqs(lookup=None, key='INSTALL_REQUIRES'):
'''get requirements, mean reading in requirements and versions from
the lookup obtained with get_lookup'''

def get_reqs(lookup=None, key="INSTALL_REQUIRES"):
if lookup == None:
lookup = get_lookup()

Expand All @@ -31,32 +25,31 @@ def get_reqs(lookup=None, key='INSTALL_REQUIRES'):
module_name = module[0]
module_meta = module[1]
if "exact_version" in module_meta:
dependency = "%s==%s" %(module_name,module_meta['exact_version'])
dependency = "%s==%s" % (module_name, module_meta["exact_version"])
elif "min_version" in module_meta:
if module_meta['min_version'] == None:
if module_meta["min_version"] == None:
dependency = module_name
else:
dependency = "%s>=%s" %(module_name,module_meta['min_version'])
dependency = "%s>=%s" % (module_name, module_meta["min_version"])
install_requires.append(dependency)
return install_requires



# Make sure everything is relative to setup.py
install_path = os.path.dirname(os.path.abspath(__file__))
install_path = os.path.dirname(os.path.abspath(__file__))
os.chdir(install_path)

# Get version information from the lookup
lookup = get_lookup()
VERSION = lookup['__version__']
NAME = lookup['NAME']
AUTHOR = lookup['AUTHOR']
AUTHOR_EMAIL = lookup['AUTHOR_EMAIL']
PACKAGE_URL = lookup['PACKAGE_URL']
KEYWORDS = lookup['KEYWORDS']
DESCRIPTION = lookup['DESCRIPTION']
LICENSE = lookup['LICENSE']
with open('README.md') as filey:
VERSION = lookup["__version__"]
NAME = lookup["NAME"]
AUTHOR = lookup["AUTHOR"]
AUTHOR_EMAIL = lookup["AUTHOR_EMAIL"]
PACKAGE_URL = lookup["PACKAGE_URL"]
KEYWORDS = lookup["KEYWORDS"]
DESCRIPTION = lookup["DESCRIPTION"]
LICENSE = lookup["LICENSE"]
with open("README.md") as filey:
LONG_DESCRIPTION = filey.read()

################################################################################
Expand All @@ -68,30 +61,32 @@ def get_reqs(lookup=None, key='INSTALL_REQUIRES'):

INSTALL_REQUIRES = get_reqs(lookup)

setup(name=NAME,
version=VERSION,
author=AUTHOR,
author_email=AUTHOR_EMAIL,
maintainer=AUTHOR,
maintainer_email=AUTHOR_EMAIL,
packages=find_packages(),
include_package_data=True,
zip_safe=False,
url=PACKAGE_URL,
license=LICENSE,
description=DESCRIPTION,
long_description=LONG_DESCRIPTION,
long_description_content_type="text/markdown",
keywords=KEYWORDS,
install_requires = INSTALL_REQUIRES,
classifiers=[
'Intended Audience :: Science/Research',
'Intended Audience :: Developers',
'License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)',
'Programming Language :: C',
'Programming Language :: Python',
'Topic :: Software Development',
'Topic :: Scientific/Engineering',
'Operating System :: Unix',
'Programming Language :: Python :: 3',
])
setup(
name=NAME,
version=VERSION,
author=AUTHOR,
author_email=AUTHOR_EMAIL,
maintainer=AUTHOR,
maintainer_email=AUTHOR_EMAIL,
packages=find_packages(),
include_package_data=True,
zip_safe=False,
url=PACKAGE_URL,
license=LICENSE,
description=DESCRIPTION,
long_description=LONG_DESCRIPTION,
long_description_content_type="text/markdown",
keywords=KEYWORDS,
install_requires=INSTALL_REQUIRES,
classifiers=[
"Intended Audience :: Science/Research",
"Intended Audience :: Developers",
"License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)",
"Programming Language :: C",
"Programming Language :: Python",
"Topic :: Software Development",
"Topic :: Scientific/Engineering",
"Operating System :: Unix",
"Programming Language :: Python :: 3",
],
)

0 comments on commit c7f640b

Please sign in to comment.