holobench 1.8.0__tar.gz → 1.9.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {holobench-1.8.0 → holobench-1.9.0}/PKG-INFO +1 -1
- {holobench-1.8.0 → holobench-1.9.0}/bencher/bench_runner.py +2 -1
- {holobench-1.8.0 → holobench-1.9.0}/bencher/bencher.py +7 -2
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/example_image.py +15 -4
- {holobench-1.8.0 → holobench-1.9.0}/bencher/results/bench_result_base.py +58 -11
- {holobench-1.8.0 → holobench-1.9.0}/bencher/results/composable_container/composable_container_base.py +4 -2
- {holobench-1.8.0 → holobench-1.9.0}/bencher/results/holoview_result.py +1 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/results/panel_result.py +13 -2
- {holobench-1.8.0 → holobench-1.9.0}/bencher/utils.py +1 -1
- {holobench-1.8.0 → holobench-1.9.0}/bencher/variables/inputs.py +5 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/variables/sweep_base.py +1 -1
- {holobench-1.8.0 → holobench-1.9.0}/bencher/video_writer.py +1 -1
- {holobench-1.8.0 → holobench-1.9.0}/pyproject.toml +1 -1
- {holobench-1.8.0 → holobench-1.9.0}/README.md +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/__init__.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/bench_cfg.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/bench_plot_server.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/bench_report.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/caching.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/__init__.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/benchmark_data.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/example_all.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/example_categorical.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/example_custom_sweep.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/example_docs.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/example_float3D.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/example_float_cat.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/example_floats.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/example_floats2D.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/example_holosweep.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/example_holosweep_objects.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/example_holosweep_tap.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/example_levels.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/example_pareto.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/example_sample_cache.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/example_sample_cache_context.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/example_simple.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/example_simple_bool.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/example_simple_cat.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/example_simple_float.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/example_strings.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/example_time_event.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/example_video.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/example_workflow.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/experimental/example_bokeh_plotly.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/experimental/example_hover_ex.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/experimental/example_hvplot_explorer.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/experimental/example_interactive.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/experimental/example_streamnd.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/experimental/example_streams.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/experimental/example_template.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/experimental/example_updates.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/experimental/example_vector.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/meta/example_meta.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/meta/example_meta_cat.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/meta/example_meta_float.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/meta/example_meta_levels.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/optuna/example_optuna.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/shelved/example_float2D_scatter.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/shelved/example_float3D_cone.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/example/shelved/example_kwargs.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/job.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/optuna_conversions.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/plotting/__init__.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/plotting/plot_filter.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/plotting/plt_cnt_cfg.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/results/__init__.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/results/bench_result.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/results/composable_container/__init__.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/results/composable_container/composable_container_panel.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/results/composable_container/composable_container_video.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/results/float_formatter.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/results/optuna_result.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/results/plotly_result.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/results/video_result.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/results/video_summary.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/variables/parametrised_sweep.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/variables/results.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/variables/time.py +0 -0
- {holobench-1.8.0 → holobench-1.9.0}/bencher/worker_job.py +0 -0
@@ -103,7 +103,7 @@ class BenchRunner:
|
|
103
103
|
for r in range(1, repeats + 1):
|
104
104
|
for lvl in range(min_level, max_level + 1):
|
105
105
|
if grouped:
|
106
|
-
report_level = BenchReport(f"{
|
106
|
+
report_level = BenchReport(f"{run_cfg.run_tag}_{self.name}")
|
107
107
|
|
108
108
|
for bch_fn in self.bench_fns:
|
109
109
|
run_lvl = deepcopy(run_cfg)
|
@@ -114,6 +114,7 @@ class BenchRunner:
|
|
114
114
|
res = bch_fn(run_lvl, report_level)
|
115
115
|
else:
|
116
116
|
res = bch_fn(run_lvl, BenchReport())
|
117
|
+
res.report.bench_name = f"{run_cfg.run_tag}_{res.report.bench_name}"
|
117
118
|
self.show_publish(res.report, show, publish, save, debug)
|
118
119
|
self.results.append(res)
|
119
120
|
if grouped:
|
@@ -175,8 +175,13 @@ class Bench(BenchPlotServer):
|
|
175
175
|
self.plot_callbacks = []
|
176
176
|
self.plot = True
|
177
177
|
|
178
|
-
def add_plot_callback(self, callback: Callable[[BenchResult], pn.panel]) -> None:
|
179
|
-
|
178
|
+
def add_plot_callback(self, callback: Callable[[BenchResult], pn.panel], **kwargs) -> None:
|
179
|
+
"""Add a plotting callback that will be called on any result produced when calling a sweep funciton. You can pass additional arguments to the plotting function with kwargs. e.g. add_plot_callback(bch.BenchResult.to_video_grid,)
|
180
|
+
|
181
|
+
Args:
|
182
|
+
callback (Callable[[BenchResult], pn.panel]): _description_
|
183
|
+
"""
|
184
|
+
self.plot_callbacks.append(partial(callback, **kwargs))
|
180
185
|
|
181
186
|
def set_worker(self, worker: Callable, worker_input_cfg: ParametrizedSweep = None) -> None:
|
182
187
|
"""Set the benchmark worker function and optionally the type the worker expects
|
@@ -18,6 +18,7 @@ class BenchPolygons(bch.ParametrizedSweep):
|
|
18
18
|
linestyle = bch.StringSweep(["solid", "dashed", "dotted"])
|
19
19
|
color = bch.StringSweep(["red", "green", "blue"])
|
20
20
|
polygon = bch.ResultImage()
|
21
|
+
area = bch.ResultVar()
|
21
22
|
# hmap = bch.ResultHmap()
|
22
23
|
|
23
24
|
def __call__(self, **kwargs):
|
@@ -25,6 +26,7 @@ class BenchPolygons(bch.ParametrizedSweep):
|
|
25
26
|
points = polygon_points(self.radius, self.sides)
|
26
27
|
# self.hmap = hv.Curve(points)
|
27
28
|
self.polygon = self.points_to_polygon_png(points, bch.gen_image_path("polygon"))
|
29
|
+
self.area = self.radius * self.sides
|
28
30
|
return super().__call__()
|
29
31
|
|
30
32
|
def points_to_polygon_png(self, points: list[float], filename: str):
|
@@ -52,17 +54,26 @@ class BenchPolygons(bch.ParametrizedSweep):
|
|
52
54
|
def example_image(
|
53
55
|
run_cfg: bch.BenchRunCfg = bch.BenchRunCfg(), report: bch.BenchReport = bch.BenchReport()
|
54
56
|
) -> bch.Bench:
|
57
|
+
run_cfg.use_cache = False
|
55
58
|
bench = bch.Bench("polygons", BenchPolygons(), run_cfg=run_cfg, report=report)
|
56
59
|
|
60
|
+
bench.result_vars = ["polygon", "area"]
|
61
|
+
|
62
|
+
bench.add_plot_callback(bch.BenchResult.to_sweep_summary)
|
63
|
+
# bench.add_plot_callback(bch.BenchResult.to_auto, level=2)
|
64
|
+
bench.add_plot_callback(bch.BenchResult.to_panes, level=3)
|
65
|
+
# bench.add_plot_callback(bch.BenchResult.to_panes)
|
66
|
+
|
57
67
|
sweep_vars = ["sides", "radius", "linewidth", "color"]
|
68
|
+
|
69
|
+
# sweep_vars = ["sides", "radius" ]
|
70
|
+
|
58
71
|
for i in range(1, len(sweep_vars)):
|
59
72
|
s = sweep_vars[:i]
|
60
73
|
bench.plot_sweep(
|
61
74
|
f"Polygons Sweeping {len(s)} Parameters",
|
62
75
|
input_vars=s,
|
63
|
-
result_vars=[BenchPolygons.param.polygon],
|
64
76
|
)
|
65
|
-
|
66
77
|
return bench
|
67
78
|
|
68
79
|
|
@@ -97,6 +108,6 @@ if __name__ == "__main__":
|
|
97
108
|
# ex_run_cfg.debug = True
|
98
109
|
# ex_run_cfg.repeats = 2
|
99
110
|
ex_run_cfg.level = 4
|
100
|
-
example_image_vid(ex_run_cfg).report.show()
|
111
|
+
# example_image_vid(ex_run_cfg).report.show()
|
101
112
|
# example_image_vid_sequential(ex_run_cfg).report.show()
|
102
|
-
|
113
|
+
example_image(ex_run_cfg).report.show()
|
@@ -10,6 +10,8 @@ import panel as pn
|
|
10
10
|
from bencher.utils import int_to_col, color_tuple_to_css, callable_name
|
11
11
|
|
12
12
|
from bencher.variables.parametrised_sweep import ParametrizedSweep
|
13
|
+
from bencher.variables.inputs import with_level
|
14
|
+
|
13
15
|
from bencher.variables.results import OptDir
|
14
16
|
from copy import deepcopy
|
15
17
|
from bencher.results.optuna_result import OptunaResult
|
@@ -21,6 +23,7 @@ from bencher.variables.results import (
|
|
21
23
|
)
|
22
24
|
|
23
25
|
from bencher.results.composable_container.composable_container_panel import ComposableContainerPanel
|
26
|
+
from bencher.utils import listify
|
24
27
|
|
25
28
|
# todo add plugins
|
26
29
|
# https://gist.github.com/dorneanu/cce1cd6711969d581873a88e0257e312
|
@@ -54,7 +57,7 @@ class BenchResultBase(OptunaResult):
|
|
54
57
|
return self.ds.count()
|
55
58
|
|
56
59
|
def to_hv_dataset(
|
57
|
-
self, reduce: ReduceType = ReduceType.AUTO, result_var: ResultVar = None
|
60
|
+
self, reduce: ReduceType = ReduceType.AUTO, result_var: ResultVar = None, level: int = None
|
58
61
|
) -> hv.Dataset:
|
59
62
|
"""Generate a holoviews dataset from the xarray dataset.
|
60
63
|
|
@@ -67,11 +70,11 @@ class BenchResultBase(OptunaResult):
|
|
67
70
|
|
68
71
|
if reduce == ReduceType.NONE:
|
69
72
|
kdims = [i.name for i in self.bench_cfg.all_vars]
|
70
|
-
return hv.Dataset(self.to_dataset(reduce, result_var), kdims=kdims)
|
71
|
-
return hv.Dataset(self.to_dataset(reduce, result_var))
|
73
|
+
return hv.Dataset(self.to_dataset(reduce, result_var, level), kdims=kdims)
|
74
|
+
return hv.Dataset(self.to_dataset(reduce, result_var, level))
|
72
75
|
|
73
76
|
def to_dataset(
|
74
|
-
self, reduce: ReduceType = ReduceType.AUTO, result_var: ResultVar = None
|
77
|
+
self, reduce: ReduceType = ReduceType.AUTO, result_var: ResultVar = None, level: int = None
|
75
78
|
) -> xr.Dataset:
|
76
79
|
"""Generate a summarised xarray dataset.
|
77
80
|
|
@@ -84,20 +87,25 @@ class BenchResultBase(OptunaResult):
|
|
84
87
|
if reduce == ReduceType.AUTO:
|
85
88
|
reduce = ReduceType.REDUCE if self.bench_cfg.repeats > 1 else ReduceType.SQUEEZE
|
86
89
|
|
87
|
-
|
90
|
+
ds_out = self.ds if result_var is None else self.ds[result_var.name]
|
88
91
|
|
89
92
|
match (reduce):
|
90
93
|
case ReduceType.REDUCE:
|
91
|
-
ds_reduce_mean =
|
92
|
-
ds_reduce_std =
|
94
|
+
ds_reduce_mean = ds_out.mean(dim="repeat", keep_attrs=True)
|
95
|
+
ds_reduce_std = ds_out.std(dim="repeat", keep_attrs=True)
|
93
96
|
|
94
97
|
for v in ds_reduce_mean.data_vars:
|
95
98
|
ds_reduce_mean[f"{v}_std"] = ds_reduce_std[v]
|
96
|
-
|
99
|
+
ds_out = ds_reduce_mean
|
97
100
|
case ReduceType.SQUEEZE:
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
+
ds_out = ds_out.squeeze(drop=True)
|
102
|
+
if level is not None:
|
103
|
+
coords_no_repeat = {}
|
104
|
+
for c, v in ds_out.coords.items():
|
105
|
+
if c != "repeat":
|
106
|
+
coords_no_repeat[c] = with_level(v.to_numpy(), level)
|
107
|
+
return ds_out.sel(coords_no_repeat)
|
108
|
+
return ds_out
|
101
109
|
|
102
110
|
def get_optimal_vec(
|
103
111
|
self,
|
@@ -405,6 +413,45 @@ class BenchResultBase(OptunaResult):
|
|
405
413
|
return container(val, styles={"background": "white"}, **kwargs)
|
406
414
|
return val
|
407
415
|
|
416
|
+
@staticmethod
|
417
|
+
def select_level(
|
418
|
+
dataset: xr.Dataset,
|
419
|
+
level: int,
|
420
|
+
include_types: List[type] = None,
|
421
|
+
exclude_names: List[str] = None,
|
422
|
+
) -> xr.Dataset:
|
423
|
+
"""Given a dataset, return a reduced dataset that only contains data from a specified level. By default all types of variables are filtered at the specified level. If you only want to get a reduced level for some types of data you can pass in a list of types to get filtered, You can also pass a list of variables names to exclude from getting filtered
|
424
|
+
Args:
|
425
|
+
dataset (xr.Dataset): dataset to filter
|
426
|
+
level (int): desired data resolution level
|
427
|
+
include_types (List[type], optional): Only filter data of these types. Defaults to None.
|
428
|
+
exclude_names (List[str], optional): Only filter data with these variable names. Defaults to None.
|
429
|
+
|
430
|
+
Returns:
|
431
|
+
xr.Dataset: A reduced dataset at the specified level
|
432
|
+
|
433
|
+
Example: a dataset with float_var: [1,2,3,4,5] cat_var: [a,b,c,d,e]
|
434
|
+
|
435
|
+
select_level(ds,2) -> [1,5] [a,e]
|
436
|
+
select_level(ds,2,(float)) -> [1,5] [a,b,c,d,e]
|
437
|
+
select_level(ds,2,exclude_names=["cat_var]) -> [1,5] [a,b,c,d,e]
|
438
|
+
|
439
|
+
see test_bench_result_base.py -> test_select_level()
|
440
|
+
"""
|
441
|
+
coords_no_repeat = {}
|
442
|
+
for c, v in dataset.coords.items():
|
443
|
+
if c != "repeat":
|
444
|
+
vals = v.to_numpy()
|
445
|
+
print(vals.dtype)
|
446
|
+
include = True
|
447
|
+
if include_types is not None and vals.dtype not in listify(include_types):
|
448
|
+
include = False
|
449
|
+
if exclude_names is not None and c in listify(exclude_names):
|
450
|
+
include = False
|
451
|
+
if include:
|
452
|
+
coords_no_repeat[c] = with_level(v.to_numpy(), level)
|
453
|
+
return dataset.sel(coords_no_repeat)
|
454
|
+
|
408
455
|
# MAPPING TO LOWER LEVEL BENCHCFG functions so they are available at a top level.
|
409
456
|
def to_sweep_summary(self, **kwargs):
|
410
457
|
return self.bench_cfg.to_sweep_summary(**kwargs)
|
@@ -36,9 +36,11 @@ class ComposableContainerBase:
|
|
36
36
|
return f"{var_value}"
|
37
37
|
return None
|
38
38
|
|
39
|
-
def __init__(
|
39
|
+
def __init__(
|
40
|
+
self, horizontal: bool = True, compose_method: ComposeType = ComposeType.right
|
41
|
+
) -> None:
|
40
42
|
self.horizontal: bool = horizontal
|
41
|
-
self.compose_method =
|
43
|
+
self.compose_method = compose_method
|
42
44
|
self.container = []
|
43
45
|
|
44
46
|
def append(self, obj: Any) -> None:
|
@@ -2,6 +2,7 @@ from typing import Optional
|
|
2
2
|
from functools import partial
|
3
3
|
import panel as pn
|
4
4
|
from param import Parameter
|
5
|
+
import holoviews as hv
|
5
6
|
from bencher.results.bench_result_base import BenchResultBase, ReduceType
|
6
7
|
from bencher.results.video_result import VideoControls
|
7
8
|
from bencher.variables.results import (
|
@@ -18,13 +19,23 @@ class PanelResult(BenchResultBase):
|
|
18
19
|
)
|
19
20
|
|
20
21
|
def to_panes(
|
21
|
-
self,
|
22
|
+
self,
|
23
|
+
result_var: Parameter = None,
|
24
|
+
hv_dataset=None,
|
25
|
+
target_dimension: int = 0,
|
26
|
+
container=None,
|
27
|
+
level: int = None,
|
28
|
+
**kwargs
|
22
29
|
) -> Optional[pn.pane.panel]:
|
23
30
|
if container is None:
|
24
31
|
container = pn.pane.panel
|
32
|
+
if hv_dataset is None:
|
33
|
+
hv_dataset = self.to_hv_dataset(ReduceType.SQUEEZE, level=level)
|
34
|
+
elif not isinstance(hv_dataset, hv.Dataset):
|
35
|
+
hv_dataset = hv.Dataset(hv_dataset)
|
25
36
|
return self.map_plot_panes(
|
26
37
|
partial(self.ds_to_container, container=container),
|
27
|
-
hv_dataset=
|
38
|
+
hv_dataset=hv_dataset,
|
28
39
|
target_dimension=target_dimension,
|
29
40
|
result_var=result_var,
|
30
41
|
result_types=PANEL_TYPES,
|
@@ -150,7 +150,7 @@ def callable_name(any_callable: Callable[..., Any]) -> str:
|
|
150
150
|
|
151
151
|
|
152
152
|
def listify(obj) -> list:
|
153
|
-
"""Take an object and turn it into a list if its not already a list"""
|
153
|
+
"""Take an object and turn it into a list if its not already a list. However if the object is none, don't turn it into a list"""
|
154
154
|
if obj is None:
|
155
155
|
return None
|
156
156
|
if isinstance(obj, list):
|
@@ -191,3 +191,8 @@ def box(name, center, width):
|
|
191
191
|
var = FloatSweep(default=center, bounds=(center - width, center + width))
|
192
192
|
var.name = name
|
193
193
|
return var
|
194
|
+
|
195
|
+
|
196
|
+
def with_level(arr: list, level) -> list:
|
197
|
+
return IntSweep(sample_values=arr).with_level(level).values()
|
198
|
+
# return tmp.with_sample_values(arr).with_level(level).values()
|
@@ -138,7 +138,7 @@ class SweepBase(param.Parameter):
|
|
138
138
|
output.step = None # pylint: disable = attribute-defined-outside-init
|
139
139
|
return output
|
140
140
|
|
141
|
-
def with_sample_values(self, sample_values:
|
141
|
+
def with_sample_values(self, sample_values: list) -> SweepBase:
|
142
142
|
output = deepcopy(self)
|
143
143
|
# TODO set up class properly. Slightly complicated due to slots
|
144
144
|
try:
|
@@ -32,7 +32,7 @@ class VideoWriter:
|
|
32
32
|
return self.filename
|
33
33
|
|
34
34
|
@staticmethod
|
35
|
-
def create_label(label, width=None, height=
|
35
|
+
def create_label(label, width=None, height=14):
|
36
36
|
if width is None:
|
37
37
|
width = len(label) * 8
|
38
38
|
new_img = Image.new("RGB", (width, height), (255, 255, 255))
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|