Skip to content

Commit

Permalink
Add config option (#18)
Browse files Browse the repository at this point in the history
Margin frame updates are now in their own function.
When adding a new page layout parameters except for the margin are not reset
Updates to tox to skip display catch in imports

* Update README.md include
Fixed a few typos.
Added description on config syntax.
  • Loading branch information
ebenp authored Jan 26, 2021
1 parent b723817 commit 5522719
Show file tree
Hide file tree
Showing 18 changed files with 211 additions and 66 deletions.
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,13 @@ fp.add_page(
nrows=3, ncols=2, orientation="portrait", height_ratios=[1, 1, 2]
)
```
FigPager options read from an .ini file can be updated via the instance's config. The syntax is config[section][subsection][option] = value.
```
fp.config['Text']['Document Title']['text']
```


The FigPager instance can be be closed following the example below.
Finally, FigPager instance can be closed following the example below.
```
fp.close()
```
Expand Down
140 changes: 85 additions & 55 deletions figpager/figpager.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
Written by Eben Pendleton
MIT License
"""

# used to deep copy config
import copy
# used in metadata
Expand All @@ -20,7 +21,9 @@
matplotlib.use('Agg')

# used to draw lines on the figure
import matplotlib.lines as lines
import matplotlib.lines as lines # isort: split
# used to validate and read in ini files
import configobj
# matplotlib import used in setting figure and axes
import matplotlib.pyplot as plt
# import package resources to get ini
Expand All @@ -29,9 +32,6 @@
from matplotlib.backends.backend_pdf import PdfPages
# used to set the plot layout in the figure
from matplotlib.gridspec import GridSpec

# used to validate and read in ini files
import configobj
# import the validator
from validate import Validator

Expand Down Expand Up @@ -64,7 +64,6 @@ def float_list_value(v, minl=None, maxl=None, minv=None, maxv=None):

return [is_float(mem, min=minv, max=maxv) for mem in is_list(v, minl, maxl)]


class FigPager:

""" Class to use matplotlib's figure with multi and single page outputs """
Expand All @@ -74,7 +73,7 @@ class FigPager:
path = os.path.abspath(__file__)

# used to find ini files saved in the package
page_layout_path = pkg_resources.resource_filename('figpager', 'page_layout/')
page_layout_path = pkg_resources.resource_filename("figpager", "page_layout/")

def __init__(
self,
Expand Down Expand Up @@ -167,8 +166,6 @@ def __init__(
# hold outfile full path
self.outfile = outfile



# hold multipage indicator
self.multipage = False
if self.type in ["pdf", "pgf"]:
Expand Down Expand Up @@ -204,8 +201,7 @@ def __init__(

# read in the ini file of paper sizes
config = configobj.ConfigObj(
os.path.join(self.page_layout_path, "paper_sizes.ini"),
configspec=spec,
os.path.join(self.page_layout_path, "paper_sizes.ini"), configspec=spec,
)

# validate against the config above
Expand Down Expand Up @@ -533,6 +529,30 @@ def _parse_option(self, section, subsection, option):
except KeyError:
return None

def _parse_option(self, section, subsection, option):

"""
Parse a given config option given the file's section, subsection and option.
Return None if option is not found
Args:
section: config file section. [example]
subsection: config file subsection. [[example]]
option: config file option. example=True
Returns: option value or None
"""

try:
return self.config[section][subsection][option]
except KeyError:
try:
return self.config[section][subsection][self.paper_size.title()][
self.orientation.title()
][option]
except KeyError:
return None

def _update_from_layout(self):

"""
Expand Down Expand Up @@ -574,34 +594,7 @@ def _update_from_layout(self):

self.marginframe = self._parse_option("Layout", "Margin", "margin_frame")
if self.marginframe:
self.constrained_layout = False
self.leftmargin = (
self._parse_option("Layout", "Margin", "left_margin")
* self.figure_unit_conversion
)
self.rightmargin = (
self._parse_option("Layout", "Margin", "right_margin")
* self.figure_unit_conversion
)
self.topmargin = (
self._parse_option("Layout", "Margin", "top_margin")
* self.figure_unit_conversion
)
self.bottommargin = (
self._parse_option("Layout", "Margin", "bottom_margin")
* self.figure_unit_conversion
)
self.marginpad = (
self._parse_option("Layout", "Margin", "margin_pad")
* self.figure_unit_conversion
)

self.framewidth = (
self.pagewidth_inch - self.leftmargin - self.rightmargin
)
self.frameheight = (
self.pageheight_inch - self.topmargin - self.bottommargin
)
self._update_marginframe_from_layout()

self.source_path = self._parse_option("Layout", "Margin", "source_path")
self.source_path_position = [
Expand All @@ -618,7 +611,38 @@ def _update_from_layout(self):
# read text
self.configtext = self.config["Text"]

def _text_from_label(self, section, label, txt):
def _update_marginframe_from_layout(self):
"""
Update the mergin frame to what's in the current layout config.
Returns: None
"""
self.constrained_layout = False
self.leftmargin = (
self._parse_option("Layout", "Margin", "left_margin")
* self.figure_unit_conversion
)
self.rightmargin = (
self._parse_option("Layout", "Margin", "right_margin")
* self.figure_unit_conversion
)
self.topmargin = (
self._parse_option("Layout", "Margin", "top_margin")
* self.figure_unit_conversion
)
self.bottommargin = (
self._parse_option("Layout", "Margin", "bottom_margin")
* self.figure_unit_conversion
)
self.marginpad = (
self._parse_option("Layout", "Margin", "margin_pad")
* self.figure_unit_conversion
)

self.framewidth = self.pagewidth_inch - self.leftmargin - self.rightmargin
self.frameheight = self.pageheight_inch - self.topmargin - self.bottommargin

def _text_at_label(self, section, label, txt):

"""
Find label and write text at label position with label font characteristics
Expand Down Expand Up @@ -827,7 +851,7 @@ def _image_from_label(self, label):
ax.imshow(img)
ax.axis("off")

def text_from_label(self, label, txt):
def text_at_label(self, label, txt):
"""
Public function to find label and write text at label position with label font characteristics.
Assumes label is in text section
Expand All @@ -839,7 +863,7 @@ def text_from_label(self, label, txt):
Returns: None
"""
return self._text_from_label("Text", label, txt)
return self._text_at_label("Text", label, txt)

def draw_page(self):
"""
Expand All @@ -859,7 +883,9 @@ def draw_page(self):
fig, ax = plt.subplots(
constrained_layout=self.constrained_layout,
figsize=(self.pagewidth_inch, self.pageheight_inch),
squeeze=False, sharex=self.sharex, sharey=self.sharey,
squeeze=False,
sharex=self.sharex,
sharey=self.sharey,
)

# set the patch here
Expand Down Expand Up @@ -973,19 +999,21 @@ def draw_page(self):
bottom=(self.bottommargin + self.marginpad) / self.pageheight_inch,
top=(self.frameheight + self.bottommargin - self.marginpad)
/ self.pageheight_inch,
hspace=self.hspace, wspace=self.wspace,
hspace=self.hspace,
wspace=self.wspace,
)

# This resets the margins and other parameters to layout
# This resets the margins to the margin layout
if self.marginframe:
self._update_from_layout()
self._update_marginframe_from_layout()

# add any layout set text here
for k in self.config["Text"].keys():
if self._parse_option("Text", k, "text") is not None:
if 'draft' in self._parse_option("Text", k, "text").lower():
if not self.draft: continue
self._text_from_label("Text", k, self._parse_option("Text", k, "text"))
if "draft" in self._parse_option("Text", k, "text").lower():
if not self.draft:
continue
self._text_at_label("Text", k, self._parse_option("Text", k, "text"))

# add any layout set images here
for k in self.config["Images"].keys():
Expand All @@ -999,9 +1027,10 @@ def draw_page(self):
for k in self.config["Watermark"].keys():
if self._parse_option("Watermark", k, "text") is not None:
# check for draft watermark status and whether user has overridden it
if 'draft' in self._parse_option("Watermark", k, "text").lower():
if not self.draft: continue
self._text_from_label(
if "draft" in self._parse_option("Watermark", k, "text").lower():
if not self.draft:
continue
self._text_at_label(
"Watermark", k, self._parse_option("Watermark", k, "text")
)

Expand Down Expand Up @@ -1051,7 +1080,6 @@ def add_subplot(self, direction="left-to-right", pos=None, gs=None, **kwargs):
# self.subplotstartindex = pos
self.currentsubplotindex = pos


if self.direction == "top-to-bottom":
if self.subplotstartindex is None:
pos = [0, 0]
Expand Down Expand Up @@ -1089,7 +1117,7 @@ def add_subplot(self, direction="left-to-right", pos=None, gs=None, **kwargs):
if gs is None:
return self.fig.add_subplot(
self.gs[pos[0], pos[1]],
label="({},{}, {})".format(pos[0], pos[1], self.subplotcounter),
label="({},{}, {})".format(pos[0], pos[1], self.subplotcounter),
**kwargs
)
else:
Expand All @@ -1101,8 +1129,10 @@ def add_subplot(self, direction="left-to-right", pos=None, gs=None, **kwargs):
return self.fig.add_subplot(
gs,
label="({},{}, {})".format(
self.currentsubplotindex[0], self.currentsubplotindex[1],
self.subplotcounter),
self.currentsubplotindex[0],
self.currentsubplotindex[1],
self.subplotcounter,
),
**kwargs
)

Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.

matplotlib>=2.2.5
configobj==5.0.6
configobj>=5.0.6
pillow>=6.2.2
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def read(fname):

setup(
name="figpager",
version="0.31",
version="0.32",
author="Eben Pendleton",
author_email="[email protected]",
url="https://github.com/ebenp/figpager",
Expand Down
Binary file modified tests/out.pdf
Binary file not shown.
Binary file modified tests/out_2.pdf
Binary file not shown.
Binary file modified tests/out_3.pdf
Binary file not shown.
Binary file modified tests/out_4.pdf
Binary file not shown.
Binary file modified tests/out_6.pdf
Binary file not shown.
Binary file modified tests/out_7.pdf
Binary file not shown.
Binary file added tests/out_8.pdf
Binary file not shown.
3 changes: 1 addition & 2 deletions tests/test_0.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
# Test of Report configuration
import os

# backend for display in GitHub Actions
if os.environ.get('DISPLAY','') == '':
print('no display found. Using non-interactive Agg backend')
import matplotlib
matplotlib.use('Agg')

import matplotlib.pyplot as plt
import matplotlib.pyplot as plt # isort: split

from figpager import FigPager

Expand Down
2 changes: 1 addition & 1 deletion tests/test_1.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def test_main():
ax0.streamplot(X, Y, U, V, density=[0.5, 1])
ax0.set_title("Varying Density")

fp.text_from_label("Figure Title", "Figure 1")
fp.text_at_label("Figure Title", "Figure 1")

# Varying color along a streamline
ax1 = fp.add_subplot()
Expand Down
2 changes: 1 addition & 1 deletion tests/test_5.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def test_main():
ax0.streamplot(X, Y, U, V, density=[0.5, 1])
ax0.set_title("Varying Density")

fp.text_from_label("Figure Title", "Figure 1")
fp.text_at_label("Figure Title", "Figure 1")

# Varying color along a streamline
ax1 = fp.add_subplot()
Expand Down
2 changes: 1 addition & 1 deletion tests/test_6.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def test_main():
ax0.streamplot(X, Y, U, V, density=[0.5, 1])
ax0.set_title("Varying Density")

fp.text_from_label("Figure Title", "Figure 1")
fp.text_at_label("Figure Title", "Figure 1")

# Varying color along a streamline
ax1 = fp.add_subplot()
Expand Down
2 changes: 1 addition & 1 deletion tests/test_7.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def test_main():
ax0.streamplot(X, Y, U, V, density=[0.5, 1])
ax0.set_title("Varying Density")

fp.text_from_label("Figure Title", "Figure 1")
fp.text_at_label("Figure Title", "Figure 1")

# Varying color along a streamline
ax1 = fp.add_subplot()
Expand Down
Loading

0 comments on commit 5522719

Please sign in to comment.