diff --git a/plotid/create_id.py b/plotid/create_id.py index bfab1a5191a1690c0bb2c831af06580ff2f331a9..f28d94ae18e32fd835561a9cdbbc942f7b6660bc 100644 --- a/plotid/create_id.py +++ b/plotid/create_id.py @@ -7,6 +7,7 @@ Functions: """ import time import uuid +import qrcode def create_id(id_method): @@ -40,3 +41,24 @@ def create_id(id_method): '"time": Unix time converted to hexadecimal\n' '"random": Random UUID') return figure_id + + +def create_qrcode(figure_id): + """ + Create a QR Code from an identifier. + + Parameters + ---------- + figure_id : str + Identifier which will be embedded in the qrcode. + + Returns + ------- + QR Code as PilImage. + """ + qrc = qrcode.QRCode(version=1, box_size=10, border=0) + qrc.add_data(figure_id) + qrc.make(fit=True) + img = qrc.make_image(fill_color="black", back_color="white") + + return img diff --git a/plotid/example.py b/plotid/example.py index 153e2f745202665d0b9e686b011068cc49d31f69..f137a5a3541c3b0d137017196ca7eb6844154bb1 100644 --- a/plotid/example.py +++ b/plotid/example.py @@ -37,7 +37,7 @@ plt.plot(x, y, color='blue') plt.plot(x, y_2, color='red') plt.savefig(IMG2) -# %% TagPlot +# %% tagplot # If multiple figures should be tagged, figures must be provided as list. FIGS_AS_LIST = [FIG1, FIG2] @@ -51,6 +51,7 @@ IMGS_AS_LIST = [IMG1, IMG2] FIGS_AND_IDS = tagplot(IMGS_AS_LIST, 'image', prefix=PROJECT_ID, id_method='time', location='west') + # %% Publish # Arguments: Source directory or files as list, destination directory, figures, # plots or images. diff --git a/plotid/plotoptions.py b/plotid/plotoptions.py index dee0f7114f099f61248866cea20612981caffe92..41e4ba80b9363e85f85636e3d41e4d4eebfb4ad0 100644 --- a/plotid/plotoptions.py +++ b/plotid/plotoptions.py @@ -33,6 +33,8 @@ class PlotOptions: id_method for creating the ID. Create an ID by Unix time is referenced as 'time', create a random ID with id_method='random'. The default is 'time'. + qrcode : bool, optional + Experimental status. Print qrcode on exported plot. Default: False. """ def __init__(self, figs, rotation, position, **kwargs): @@ -43,6 +45,7 @@ class PlotOptions: self.position = position self.prefix = kwargs.get('prefix', '') self.id_method = kwargs.get('id_method', 'time') + self.qrcode = kwargs.get('qrcode', False) def __str__(self): """Representation if an object of this class is printed.""" diff --git a/plotid/tagplot.py b/plotid/tagplot.py index bb16c1a2075ce561d4427446a566c91ed1122f44..41d4ae6db8e0936fe2b2b7584a3b94c519ad8010 100644 --- a/plotid/tagplot.py +++ b/plotid/tagplot.py @@ -80,8 +80,7 @@ def tagplot(figs, engine, location='east', **kwargs): position = (0.75, 0.015) case 'custom': # TODO: Get rotation and position from user input & check if valid - rotation = 0 - position = (0.5, 0.5) + pass case _: warnings.warn(f'Location "{location}" is not a defined ' 'location, TagPlot uses location "east" ' diff --git a/plotid/tagplot_image.py b/plotid/tagplot_image.py index decc9e5a2379cc61868cbeabf294de70bff4e418..05b4ab13a6f166c5c31f603c5a4f713e59876536 100644 --- a/plotid/tagplot_image.py +++ b/plotid/tagplot_image.py @@ -7,7 +7,7 @@ Functions: """ import os from PIL import Image, ImageDraw, ImageFont, ImageOps -from plotid.create_id import create_id +from plotid.create_id import create_id, create_qrcode from plotid.plotoptions import PlotOptions, PlotIDTransfer @@ -55,6 +55,10 @@ def tagplot_image(plotid_object): (int(img.width*plotid_object.position[0]), int(img.height*(1-plotid_object.position[1]))), txt) + if plotid_object.qrcode: + qrcode = create_qrcode(img_id) + qrcode.thumbnail((100, 100), Image.ANTIALIAS) + img.paste(qrcode, box=(img.width-100, img.height-100)) plotid_object.figs[i] = img figs_and_ids = PlotIDTransfer(plotid_object.figs, plotid_object.figure_ids) diff --git a/plotid/tagplot_matplotlib.py b/plotid/tagplot_matplotlib.py index 1ba05720c67deb9f56ab7ec77da981f41cada5b5..eef060cde9d38883e40a129703ecaedc8b482288 100644 --- a/plotid/tagplot_matplotlib.py +++ b/plotid/tagplot_matplotlib.py @@ -8,7 +8,8 @@ Functions: import matplotlib import matplotlib.pyplot as plt -from plotid.create_id import create_id +from PIL import Image +from plotid.create_id import create_id, create_qrcode from plotid.plotoptions import PlotOptions, PlotIDTransfer @@ -51,7 +52,12 @@ def tagplot_matplotlib(plotid_object): s=fig_id, ha='left', wrap=True, rotation=plotid_object.rotation, fontsize=fontsize, color=color) - fig.tight_layout() + + if plotid_object.qrcode: + qrcode = create_qrcode(fig_id) + qrcode.thumbnail((100, 100), Image.ANTIALIAS) + fig.figimage(qrcode, fig.bbox.xmax - 100, 0, cmap='bone') + fig.tight_layout() figs_and_ids = PlotIDTransfer(plotid_object.figs, plotid_object.figure_ids) return figs_and_ids diff --git a/requirements.txt b/requirements.txt index a70ca0a9a91df50dc4885d797a31f7c128ce6f35..2852cbf877c24388285007a33e824e59bb1120a9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,4 +8,5 @@ packaging==21.3 Pillow==9.1.0 pyparsing==3.0.8 python-dateutil==2.8.2 +qrcode==7.3.1 six==1.16.0 diff --git a/tests/test_create_id.py b/tests/test_create_id.py index b47ae91a384be0845f55c758648d8f5e4feaee5e..2f8e4b2b669b49a8f295ba7f60799e89804b02b5 100644 --- a/tests/test_create_id.py +++ b/tests/test_create_id.py @@ -5,7 +5,9 @@ Unittests for create_id """ import unittest +import qrcode import plotid.create_id as cid +from plotid.create_id import create_qrcode class TestCreateID(unittest.TestCase): @@ -30,6 +32,11 @@ class TestCreateID(unittest.TestCase): self.assertEqual(len(cid.create_id('time')), 10) self.assertEqual(len(cid.create_id('random')), 8) + def test_qrcode(self): + """Test if qrcode returns a image.""" + self.assertIsInstance(create_qrcode('test_ID'), + qrcode.image.pil.PilImage) + if __name__ == '__main__': unittest.main() diff --git a/tests/test_plotoptions.py b/tests/test_plotoptions.py index ee752c2c66993dd75bd8be0a27214b00f5861b80..87b4f306f5781172f54f209397e3a463185d968b 100644 --- a/tests/test_plotoptions.py +++ b/tests/test_plotoptions.py @@ -44,7 +44,7 @@ class TestTagplot(unittest.TestCase): "<class 'plotid.plotoptions.PlotOptions'>: {'figs': " "'FIG', 'figure_ids': [], 'rotation': 270, 'position'" ": (100, 200), 'prefix': 'xyz', 'id_method': " - "'random'}") + "'random', 'qrcode': False}") def test_str_plotidtransfer(self): """ diff --git a/tests/test_tagplot_image.py b/tests/test_tagplot_image.py index ad42d82113ab850cacf739a5315877726132f5f4..2c236c57bccd97748def00665fcf509d10a343b8 100644 --- a/tests/test_tagplot_image.py +++ b/tests/test_tagplot_image.py @@ -40,7 +40,7 @@ class TestTagplotImage(unittest.TestCase): respectively. """ options = PlotOptions(IMGS_AS_LIST, ROTATION, POSITION, - prefix=PROJECT_ID, id_method=METHOD) + prefix=PROJECT_ID, id_method=METHOD, qrcode=True) options.validate_input() figs_and_ids = tagplot_image(options) self.assertIsInstance(figs_and_ids.figs[0], diff --git a/tests/test_tagplot_matplotlib.py b/tests/test_tagplot_matplotlib.py index f6b9b4ce7ee010ed6be15b3080f6f386a809e45d..87cc22bfbce4422105aabdb9f1286f5e55e608a5 100644 --- a/tests/test_tagplot_matplotlib.py +++ b/tests/test_tagplot_matplotlib.py @@ -30,7 +30,7 @@ class TestTagplotMatplotlib(unittest.TestCase): def test_mplfigures(self): """ Test of returned objects. Check if they are matplotlib figures. """ options = PlotOptions(FIGS_AS_LIST, ROTATION, POSITION, - prefix=PROJECT_ID, id_method=METHOD) + prefix=PROJECT_ID, id_method=METHOD, qrcode=True) options.validate_input() figs_and_ids = tagplot_matplotlib(options) self.assertIsInstance(figs_and_ids.figs[0], Figure)