Skip to content
Snippets Groups Projects
Commit c643cb71 authored by Mayr, Hannes's avatar Mayr, Hannes Committed by Hock, Martin
Browse files

Resolve "Default name for exported plots"

parent d5b1fdff
No related branches found
No related tags found
2 merge requests!52Create v0.2.2,!48Resolve "Default name for exported plots"
......@@ -59,9 +59,9 @@ Optional parameters can be used to customize the tag process.
- *prefix* : str, optional
Will be added as prefix to the ID.
- *id_method* : str, optional
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'.
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".
- *location* : string, optional
Location for ID to be displayed on the plot. Default is 'east'.
Location for ID to be displayed on the plot. Default is "east".
- *qrcode* : boolean, optional
Experimental support for encoding the ID in a QR Code.
- *id_on_plot* : boolean, optional
......@@ -72,13 +72,13 @@ Example:
FIG1 = plt.figure()
FIG2 = plt.figure()
FIGS_AS_LIST = [FIG1, FIG2]
FIGS_AND_IDS = tagplot(FIGS_AS_LIST, 'matplotlib', prefix='XY23_', id_method='random', location='west')
FIGS_AND_IDS = tagplot(FIGS_AS_LIST, "matplotlib", prefix="XY23_", id_method="random", location="west")
```
### publish()
Save plot, data and measuring script. It is possible to export multiple figures at once.
`publish(figs_and_ids, src_datapath, dst_path, plot_name)`
`publish(figs_and_ids, src_datapath, dst_path)`
- *figs_and_ids* must be a PlotIDTransfer object. Therefore, it can be directly passed from tagplot() to publish().
- *src_datapath* specifies the path to (raw) data that should be published. It can be a string or a list of strings that specifies all files and directories which will be published.
......@@ -90,8 +90,10 @@ Optional parameters can be used to customize the publish process.
Method how the data should be stored. Available options:
- *centralized*: The raw data will copied only once. All other plots will reference this data via sym link.
- *individual*: The complete raw data will be copied to a folder for every plot, respectively.
- *plot_names* : str or list of str, optional
Name for the exported plot. If not provided, the corresponding IDs will be used.
Example:
`publish(figs_and_ids, '/home/user/Documents/research_data', '/home/user/Documents/exported_data', 'EnergyOverTime-Plot')`
`publish(figs_and_ids, "/home/user/Documents/research_data", "/home/user/Documents/exported_data", plot_names=["EnergyOverTime-Plot", "TimeOverEnergy-Plot")`
## Build
If you want to build plotID yourself, follow these steps:
......
......@@ -35,6 +35,6 @@ FIGS_AND_IDS = tagplot(
# Export your tagged images, copy the research data that generated the images,
# specify the destination folder and give a name for the exported image files.
publish(FIGS_AND_IDS, ["../README.md", "../docs", "../LICENSE"], "./data", "my_image")
publish(FIGS_AND_IDS, ["../README.md", "../docs", "../LICENSE"], "./data")
# Required arguments: publish(output of tagplot(), list of files,
# path to destination folder, name(s) for the resulting images)
# path to destination folder)
......@@ -46,6 +46,6 @@ FIGS_AND_IDS = tagplot(
# %% Publish
publish(FIGS_AND_IDS, ["../README.md", "../docs", "../LICENSE"], "data", "my_plot")
publish(FIGS_AND_IDS, ["../README.md", "../docs", "../LICENSE"], "data")
# Required arguments: publish(output of tagplot(), list of files,
# path to destination folder, name(s) for the resulting images)
# path to destination folder)
......@@ -33,17 +33,17 @@ class PublishOptions:
Export the plot and copy specified files to the destiantion folder.
"""
def __init__(self, figs_and_ids, src_datapaths, dst_path, plot_names, **kwargs):
def __init__(self, figs_and_ids, src_datapaths, dst_path, **kwargs):
if not isinstance(figs_and_ids, PlotIDTransfer):
raise RuntimeError("figs_and_ids is not an instance of " "PlotIDTransfer.")
raise RuntimeError("figs_and_ids is not an instance of PlotIDTransfer.")
self.figure = figs_and_ids.figs
self.figure_ids = figs_and_ids.figure_ids
self.src_datapaths = src_datapaths
self.dst_path = os.path.abspath(dst_path)
self.plot_names = plot_names
self.data_storage = kwargs.get("data_storage", "individual")
self.dst_path_head, self.dst_dirname = os.path.split(self.dst_path)
self.plot_names = kwargs.get("plot_names", self.figure_ids)
def __str__(self):
"""Representation if an object of this class is printed."""
......@@ -91,7 +91,7 @@ class PublishOptions:
# Check if data_storage is a string
if not isinstance(self.data_storage, str):
raise TypeError("The specified data_storage method is not a " "string.")
raise TypeError("The specified data_storage method is not a string.")
def export(self):
"""
......@@ -160,7 +160,7 @@ class PublishOptions:
if delete_dir in ("yes", "y", "Yes", "YES"):
shutil.rmtree(dst_path_invisible)
raise RuntimeError(
"Publishing was unsuccessful. " "Try re-running publish."
"Publishing was unsuccessful. Try re-running publish."
) from exc
case _:
raise ValueError(
......@@ -233,7 +233,7 @@ class PublishOptions:
)
def publish(figs_and_ids, src_datapath, dst_path, plot_name, **kwargs):
def publish(figs_and_ids, src_datapath, dst_path, **kwargs):
"""
Save plot, data and measuring script.
......@@ -245,8 +245,7 @@ def publish(figs_and_ids, src_datapath, dst_path, plot_name, **kwargs):
Path to data that should be published.
dst_path : str
Path to the destination directory.
plot_name : str or list of str
Name for the exported plot.
**kwargs : dict, optional
Extra arguments for additional publish options.
......@@ -258,14 +257,14 @@ def publish(figs_and_ids, src_datapath, dst_path, plot_name, **kwargs):
will reference this data via sym link.
individual [default]: The complete raw data will be copied to a
folder for every plot, respectively.
plot_names : str or list of str, optional
Name for the exported plot. If not provided, the corresponding IDs will be used.
Returns
-------
None.
"""
publish_container = PublishOptions(
figs_and_ids, src_datapath, dst_path, plot_name, **kwargs
)
publish_container = PublishOptions(figs_and_ids, src_datapath, dst_path, **kwargs)
publish_container.validate_input()
publish_container.export()
......@@ -58,7 +58,7 @@ class TestPublish(unittest.TestCase):
PlotIDTransfer(FIG, "testID"),
SRC_DIR,
DST_PATH + "/",
PIC_NAME,
plot_names=PIC_NAME,
data_storage="individual",
)
assert os.path.isfile(os.path.join(DST_PATH, "testID", PIC_NAME + ".png"))
......@@ -70,29 +70,47 @@ class TestPublish(unittest.TestCase):
"from a Python script. Therefore, the script cannot be "
"copied.",
)
def test_publish_multiple_figs(self):
def test_publish_multiple_figs_custom_name(self):
"""
Test publish with multiple figures and check if all exported picture
files exist.
files exist with the provided strings as their names.
"""
publish(FIGS_AND_IDS, SRC_DIR, DST_PATH, PIC_NAME_LIST)
publish(FIGS_AND_IDS, SRC_DIR, DST_PATH, plot_names=PIC_NAME_LIST)
for i, name in enumerate(PIC_NAME_LIST):
assert os.path.isfile(os.path.join(DST_PATH, IDS_AS_LIST[i], name + ".png"))
# Skip test if tests are run from command line.
@unittest.skipIf(
not os.path.isfile(sys.argv[0]),
"Publish is not called "
"from a Python script. Therefore, the script cannot be "
"copied.",
)
def test_publish_multiple_figs_standard_name(self):
"""
Test publish with multiple figures and check if all exported picture
files exist with the IDs as their names.
"""
publish(FIGS_AND_IDS, SRC_DIR, DST_PATH)
for identifier in IDS_AS_LIST:
assert os.path.isfile(
os.path.join(DST_PATH, identifier, identifier + ".png")
)
def test_figs_and_ids(self):
"""
Test if RuntimeError is raised when figs_and_ids is not an
PlotIDTransfer object.
"""
with self.assertRaises(RuntimeError):
publish("FIGS_AND_IDS", SRC_DIR, DST_PATH, PIC_NAME_LIST)
publish("FIGS_AND_IDS", SRC_DIR, DST_PATH)
def test_wrong_ids(self):
"""Test if Error is raised if IDs are of wrong type."""
with self.assertRaises(TypeError):
publish(PlotIDTransfer(FIG, 3), SRC_DIR, DST_PATH, PIC_NAME)
publish(PlotIDTransfer(FIG, 3), SRC_DIR, DST_PATH)
with self.assertRaises(TypeError):
publish(PlotIDTransfer(FIG, ["i", 4]), SRC_DIR, DST_PATH, PIC_NAME)
publish(PlotIDTransfer(FIG, ["i", 4]), SRC_DIR, DST_PATH)
def test_publish_multiple_src_files(self):
"""
......@@ -105,7 +123,7 @@ class TestPublish(unittest.TestCase):
FIGS_AND_IDS,
files_and_dir,
DST_PATH,
PIC_NAME_LIST,
plot_names=PIC_NAME_LIST,
data_storage="individual",
)
for identifier in IDS_AS_LIST:
......@@ -117,14 +135,14 @@ class TestPublish(unittest.TestCase):
def test_src_directory(self):
"""Test if Error is raised when source directory does not exist."""
with self.assertRaises(FileNotFoundError):
publish(FIGS_AND_IDS, "not_existing_folder", DST_PATH, PIC_NAME)
publish(FIGS_AND_IDS, "not_existing_folder", DST_PATH)
def test_src_directory_type(self):
"""Test if Error is raised when source directory is not a string."""
with self.assertRaises(TypeError):
publish(FIGS_AND_IDS, [SRC_DIR, 4], DST_PATH, PIC_NAME)
publish(FIGS_AND_IDS, [SRC_DIR, 4], DST_PATH)
with self.assertRaises(TypeError):
publish(FIGS_AND_IDS, 4, DST_PATH, PIC_NAME)
publish(FIGS_AND_IDS, 4, DST_PATH)
def test_dst_directory(self):
"""
......@@ -132,7 +150,7 @@ class TestPublish(unittest.TestCase):
destination dir does not exist.
"""
with self.assertRaises(FileNotFoundError):
publish(FIGS_AND_IDS, SRC_DIR, "not_existing_folder/data", PIC_NAME)
publish(FIGS_AND_IDS, SRC_DIR, "not_existing_folder/data")
def test_script_exists(self):
"""
......@@ -158,8 +176,7 @@ class TestPublish(unittest.TestCase):
"from plotid.publish import publish\n"
"from plotid.plotoptions import PlotIDTransfer\n"
"publish(PlotIDTransfer(plt.figure(), 'testID2'),"
" 'test_src_folder', 'test_parent/test_dst_folder',"
" 'test_picture')",
" 'test_src_folder', 'test_parent/test_dst_folder')",
],
capture_output=True,
check=True,
......@@ -172,8 +189,7 @@ class TestPublish(unittest.TestCase):
"from plotid.publish import publish\n"
"from plotid.plotoptions import PlotIDTransfer\n"
"publish(PlotIDTransfer(plt.figure(), 'testID2'), "
"'test_src_folder', 'test_parent/test_dst_folder', "
"'test_picture')",
"'test_src_folder', 'test_parent/test_dst_folder')",
],
capture_output=True,
)
......@@ -199,9 +215,7 @@ class TestPublish(unittest.TestCase):
os.mkdir(os.path.join(DST_PATH, IDS_AS_LIST[0]))
# Mock user input as 'yes'
with patch("builtins.input", return_value="yes"):
publish(
FIGS_AND_IDS, SRC_DIR, DST_PATH, PIC_NAME, data_storage="individual"
)
publish(FIGS_AND_IDS, SRC_DIR, DST_PATH, data_storage="individual")
# Skip test if tests are run from command line.
@unittest.skipIf(
......@@ -221,7 +235,7 @@ class TestPublish(unittest.TestCase):
# Mock user input as 'no'
with patch("builtins.input", return_value="no"):
with self.assertRaises(RuntimeError):
publish(FIGS_AND_IDS, SRC_DIR, DST_PATH, PIC_NAME)
publish(FIGS_AND_IDS, SRC_DIR, DST_PATH)
# Skip test if tests are run from command line.
@unittest.skipIf(
......@@ -241,9 +255,7 @@ class TestPublish(unittest.TestCase):
# Mock user input as empty (no should be default).
with patch("builtins.input", return_value=""):
with self.assertRaises(RuntimeError):
publish(
FIGS_AND_IDS, SRC_DIR, DST_PATH, PIC_NAME, data_storage="individual"
)
publish(FIGS_AND_IDS, SRC_DIR, DST_PATH, data_storage="individual")
# Skip test if tests are run from command line.
@unittest.skipIf(
......@@ -264,7 +276,7 @@ class TestPublish(unittest.TestCase):
# Mock user input as 'yes' for deleting the partial copied data
with patch("builtins.input", side_effect=["yes", "yes"]):
with self.assertRaises(RuntimeError):
publish(FIGS_AND_IDS, SRC_DIR, DST_PATH, PIC_NAME)
publish(FIGS_AND_IDS, SRC_DIR, DST_PATH, plot_names=PIC_NAME)
assert not os.path.isdir(invisible_path1)
os.remove("test_picture1.tmp.png")
os.remove("test_picture2.tmp.png")
......@@ -284,16 +296,12 @@ class TestPublish(unittest.TestCase):
"""
with self.assertRaises(ValueError):
publish(
FIGS_AND_IDS,
SRC_DIR,
DST_PATH,
PIC_NAME,
data_storage="none_existing_method",
FIGS_AND_IDS, SRC_DIR, DST_PATH, data_storage="none_existing_method"
)
with self.assertRaises(TypeError):
publish(FIGS_AND_IDS, SRC_DIR, DST_PATH, PIC_NAME, data_storage=3)
publish(FIGS_AND_IDS, SRC_DIR, DST_PATH, data_storage=3)
with self.assertRaises(TypeError):
publish(FIGS_AND_IDS, SRC_DIR, DST_PATH, PIC_NAME, data_storage=[])
publish(FIGS_AND_IDS, SRC_DIR, DST_PATH, data_storage=[])
def test_str(self):
"""
......@@ -301,7 +309,7 @@ class TestPublish(unittest.TestCase):
correct.
"""
self.maxDiff = None
publish_obj = PublishOptions(FIGS_AND_IDS, SRC_DIR, DST_PATH, PIC_NAME)
publish_obj = PublishOptions(FIGS_AND_IDS, SRC_DIR, DST_PATH)
self.assertIn(
"<class 'plotid.publish.PublishOptions'>: {'figure': "
"[<Figure size 640x480 with 0 Axes>, <Figure size"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment