Skip to content

Commit 6737be4

Browse files
committed
fixed jammer to work with variable input and output sizes including compatibility validation
1 parent df9ef8a commit 6737be4

File tree

4 files changed

+65
-39
lines changed

4 files changed

+65
-39
lines changed

planvec/gui/planvec_gui.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,16 @@
1313
from planvec.gui.team_dir_dialog import TeamDirDialog
1414
from planvec.gui.ui_generated.planvec_ui import Ui_planvec
1515
from planvec.gui.video_stream import FrameBuffer, VideoStreamThread
16-
from planvec.pdf_jammer import PdfJammer
16+
from planvec.pdf_jammer import PdfJammer, PdfAndPlateSizeIncompatibleException
1717
from planvec.utils.date_utils import get_date_tag
1818
from planvec.utils.camera_utils import get_physical_camera_device_indices
1919
from planvec.planvec_paths import DATA_DESKTOP_DIR_PATH
2020

2121
from dotmap import DotMap
2222
from typing import Tuple
2323

24+
from planvec.utils.qt_utils import get_text_or_placeholder_text
25+
2426

2527
class PlanvecGui:
2628
"""Adds logic and behaviour to the ui elements."""
@@ -234,7 +236,17 @@ def _execute_successful_jam_info_box(msg: str) -> None:
234236

235237
if button_return.text() == '&OK':
236238
pdf_jammer = PdfJammer(data_manager=self.data_manager,
237-
out_dir_path=DATA_DESKTOP_DIR_PATH / get_date_tag())
239+
out_dir_path=DATA_DESKTOP_DIR_PATH / get_date_tag(),
240+
plate_width=int(get_text_or_placeholder_text(self.ui.outputSizeWidth)),
241+
plate_height=int(get_text_or_placeholder_text(self.ui.outputSizeHeight)),
242+
pdf_width=int(get_text_or_placeholder_text(self.ui.inputSizeWidth)),
243+
pdf_height=int(get_text_or_placeholder_text(self.ui.inputSizeHeight)))
244+
try:
245+
pdf_jammer.validate_pdf_and_plate_sizes_compatibility()
246+
except PdfAndPlateSizeIncompatibleException as exception:
247+
error_box = ErrorMsgBox(exception.message)
248+
error_box.execute()
249+
return
238250

239251
school_name = self.ui.schoolName_2.text()
240252
team_name = self.ui.teamName_2.text()

planvec/gui/processing.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ def get_curr_out_fig(self) -> plt.Figure:
5858

5959
def toggle_stopped(self):
6060
self.stopped = not self.stopped
61-
print(f"Toggled stop video. Currently: {'STOPPED' if self.stopped else 'RUNNING'}")
6261

6362
def set_input_width(self, width_cm) -> None:
6463
_, current_height_inches = self.processing_config.out_size_inches
@@ -94,7 +93,6 @@ def _calculate_display_shape_in_pixels(width_in_inches: float, height_in_inches:
9493
@QtCore.pyqtSlot()
9594
def toggle_canny_slot(self) -> None:
9695
self.do_canny = not self.do_canny
97-
print(f"Toggled canny. Currently doing canny? {'YES' if self.do_canny else 'NO'}")
9896

9997
@staticmethod
10098
def process_frame(img, processing_config: DotMap, color_ranges: dict, do_canny: bool, ax: plt.Axes) -> (plt.Axes, QImage):

planvec/pdf_jammer.py

Lines changed: 42 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,24 @@
33
import math
44
from pathlib import Path
55

6-
from dotmap import DotMap
7-
86
from planvec.gui.datamanager import DataManager
97
from planvec.utils.date_utils import get_date_time_tag
10-
from config import planvec_config
118
from typing import Dict, List
129

13-
14-
# todo: need not hardcode but use values from GUI for this
15-
PLATE_WIDTH = 50
16-
PLATE_HEIGHT = 80
17-
PDF_WIDTH = 20
18-
PDF_HEIGHT = 14
19-
2010
UNITE_FILE_TEMPL = 'unite_plate-{plate_idx}_{date_time_tag}.pdf'
2111
JAMMED_FILE_TEMPL = 'jammed_plate-{plate_idx}_{date_time_tag}.pdf'
2212

2313

2414
class PdfJammer:
25-
def __init__(self, data_manager: DataManager, out_dir_path: Path, verbose: bool = True):
15+
def __init__(self, data_manager: DataManager, out_dir_path: Path,
16+
plate_width: int, plate_height: int, pdf_width: int, pdf_height: int,
17+
verbose: bool = True):
2618
self.data_manager = data_manager
2719
self.out_dir = out_dir_path
20+
self.plate_width = plate_width
21+
self.plate_height = plate_height
22+
self.pdf_width = pdf_width
23+
self.pdf_height = pdf_height
2824
self.verbose = verbose
2925

3026
def run(self, pdf_paths: List[str]) -> None:
@@ -41,23 +37,23 @@ def run(self, pdf_paths: List[str]) -> None:
4137
def create_commands(self, pdfs) -> (List[List[str]], List[List[str]]):
4238
"""Main function to arrange all pdfs in the input list on one or more single-page pdfs."""
4339
self.print_general_info(len(pdfs))
44-
n_grippers_per_plate = calc_max_n_pdfs_per_plate(PLATE_WIDTH, PLATE_HEIGHT, PDF_WIDTH, PDF_HEIGHT)
40+
n_pdfs_per_plate = calc_max_n_pdfs_per_plate(self.plate_width, self.plate_height, self.pdf_width, self.pdf_height)
4541
unite_commands = []
4642
jam_commands = []
47-
for plate_idx, pdfs_chunk in enumerate(chunks(pdfs, n_grippers_per_plate)):
43+
for plate_idx, pdfs_chunk in enumerate(chunks(pdfs, n_pdfs_per_plate)):
4844
unite_command, unite_file_path = self._create_unite_command(pdfs_chunk, plate_idx)
4945
jam_command = self._create_jam_command(unite_file_path, len(pdfs_chunk))
5046
# Step one: 'pdfunite' -> Merge all pdfs of this chunk into one pdf as pages
5147
unite_commands.append(unite_command)
5248
# Step two: 'pdfjam' -> Arrange all pages in the united pdf on a board given the dimensions of the
5349
# board and the individual pdfs.
5450
jam_commands.append(jam_command)
55-
self.print_plate_info(len(pdfs_chunk), plate_idx, jam_command[-1])
51+
self.print_plate_info(len(pdfs_chunk), plate_idx, jam_command[-1], self.plate_width, self.pdf_width, self.pdf_height)
5652
return unite_commands, jam_commands
5753

5854
def _create_unite_command(self, pdfs, plate_idx):
5955
"""Creates the subprocess command to merge multiple pdfs to one pdf with multiple pages."""
60-
n_grippers_per_plate = calc_max_n_pdfs_per_plate(PLATE_WIDTH, PLATE_HEIGHT, PDF_HEIGHT, PDF_HEIGHT)
56+
n_grippers_per_plate = calc_max_n_pdfs_per_plate(self.plate_width, self.plate_height, self.pdf_height, self.pdf_height)
6157
if len(pdfs) > n_grippers_per_plate:
6258
raise ValueError(f'Cannot have more than {n_grippers_per_plate} on one plate! Given: {len(pdfs)}.')
6359
out_file_name = UNITE_FILE_TEMPL.format(plate_idx=plate_idx,
@@ -67,21 +63,21 @@ def _create_unite_command(self, pdfs, plate_idx):
6763
return command, out_file_path
6864

6965
def _create_jam_command(self, united_file_path, n_pdfs):
70-
"""Creates a list of strings representing the subprocess command to jam them ."""
66+
"""Creates a list of strings representing the subprocess command to jam them."""
7167
out_dir_path, united_file_name = os.path.split(united_file_path)
7268
jam_file_name = '_'.join(['jammed', united_file_name.split('_', 1)[1]])
7369
out_file_path = os.path.join(self.data_manager.out_dir_path, jam_file_name)
7470

75-
max_pdfs_per_plate = calc_max_n_pdfs_per_plate(PLATE_WIDTH, PLATE_HEIGHT, PDF_WIDTH, PDF_HEIGHT)
76-
n_max_cols = calc_max_n_horizontal(PLATE_WIDTH, PDF_WIDTH)
77-
n_max_rows = calc_max_n_vertical(PLATE_HEIGHT, PDF_HEIGHT)
71+
max_pdfs_per_plate = calc_max_n_pdfs_per_plate(self.plate_width, self.plate_height, self.pdf_width, self.pdf_height)
72+
n_max_cols = calc_max_n_horizontal(self.plate_width, self.pdf_width)
73+
n_max_rows = calc_max_n_vertical(self.plate_height, self.pdf_height)
7874
n_cols = n_pdfs if n_pdfs < n_max_cols else n_max_cols
7975
n_rows = math.ceil(n_pdfs / n_cols)
8076
assert n_rows <= n_max_rows, f'n_rows ({n_rows}) cannot be larger than n_max_rows ({n_max_rows}).'
81-
width = n_cols * PDF_WIDTH
82-
height = n_rows * PDF_HEIGHT
77+
output_width = n_cols * self.pdf_width
78+
output_height = n_rows * self.pdf_height
8379
command = ['pdfjam'] + [f'--nup {n_cols}x{n_rows}'] + [united_file_path] + [
84-
f"--papersize \'{{{width}cm, {height}cm}}\'"]
80+
f"--papersize \'{{{output_width}cm, {output_height}cm}}\'"]
8581
command += [f'--outfile {out_file_path}']
8682
return command
8783

@@ -134,32 +130,43 @@ def print_pdf_paths(teams_pdf_dict: Dict[str, List[str]]) -> None:
134130
print(f' {os.path.split(path)[1]}')
135131

136132
def print_general_info(self, n_pdfs_total):
137-
max_pdfs_per_plate = calc_max_n_pdfs_per_plate(PLATE_WIDTH, PLATE_HEIGHT, PDF_WIDTH, PDF_HEIGHT)
133+
max_pdfs_per_plate = calc_max_n_pdfs_per_plate(self.plate_width, self.plate_height, self.pdf_width, self.pdf_height)
138134
n_plates = calc_n_plates(max_pdfs_per_plate, n_pdfs_total)
139135
print(f'Collecting output from {self.data_manager.out_dir_path}...')
140136
print(f'Found {n_pdfs_total} pdf output files.')
141137
pdfs_dict = self.accumulate_pdf_paths_all_schools_and_teams()
142138
PdfJammer.print_pdf_paths(pdfs_dict)
143139
print(f'Given dimensions:')
144-
print(f' Plate width:\t {PLATE_WIDTH}')
145-
print(f' Plate height:\t {PLATE_HEIGHT}')
146-
print(f' PDF width:\t\t {PDF_WIDTH}')
147-
print(f' PDF width:\t\t {PDF_HEIGHT}')
140+
print(f' Plate width:\t {self.plate_width}')
141+
print(f' Plate height:\t {self.plate_height}')
142+
print(f' PDF width:\t\t {self.pdf_width}')
143+
print(f' PDF width:\t\t {self.pdf_height}')
148144
print(f' which means maximum {max_pdfs_per_plate} PDF\'s per plate and...')
149145
print(f' and in this case {n_plates} {"plates" if n_plates > 1 else "plate"} '
150146
f'for {n_pdfs_total} PDF\'s in total.')
151147

152148
@staticmethod
153-
def print_plate_info(n_pdfs_on_plate, plate_idx, out_file_path):
154-
n_cols, n_rows = calc_n_cols_rows(n_pdfs_on_plate)
155-
final_width, final_height = calc_final_width_height(n_cols, n_rows)
149+
def print_plate_info(n_pdfs_on_plate, plate_idx, out_file_path, plate_width, pdf_width, pdf_height):
150+
n_cols, n_rows = calc_n_cols_rows(n_pdfs_on_plate, plate_width, pdf_width)
151+
final_width, final_height = calc_final_width_height(n_cols, n_rows, pdf_width, pdf_height)
156152
print(f'Plate {plate_idx + 1}: ')
157153
print(f'\t{n_pdfs_on_plate} PDF{"s" if n_pdfs_on_plate > 1 else ""} on this plate.')
158154
print(f'\tGrid dimensions {n_cols}{"cols" if n_cols > 1 else "col"} x '
159155
f'{n_rows}{"rows" if n_rows > 1 else "row"} with a total size of '
160156
f'{final_width}x{final_height} cm')
161157
print(f'\t{out_file_path}')
162158

159+
def validate_pdf_and_plate_sizes_compatibility(self) -> None:
160+
if self.pdf_width > self.plate_width:
161+
raise PdfAndPlateSizeIncompatibleException("PDF Input kann nicht breiter als Output Platte sein!")
162+
if self.pdf_height > self.plate_height:
163+
raise PdfAndPlateSizeIncompatibleException("PDF Input kann nicht höher als Output Platte sein!")
164+
165+
166+
class PdfAndPlateSizeIncompatibleException(Exception):
167+
def __init__(self, message: str) -> None:
168+
self.message = message
169+
163170

164171
def calc_max_n_horizontal(plate_width, pdf_width):
165172
return plate_width // pdf_width
@@ -179,17 +186,17 @@ def calc_n_plates(max_pdfs_per_plate, n_pdfs):
179186
return math.ceil(n_pdfs / max_pdfs_per_plate)
180187

181188

182-
def calc_n_cols_rows(n_pdfs):
189+
def calc_n_cols_rows(n_pdfs, plate_width, pdf_width):
183190
"""Given the dimensions of the plate and single pdf and the number of pdfs, how many cols and rows are required."""
184-
n_max_cols = calc_max_n_horizontal(PLATE_WIDTH, PDF_WIDTH)
191+
n_max_cols = calc_max_n_horizontal(plate_width, pdf_width)
185192
n_cols = n_pdfs if n_pdfs < n_max_cols else n_max_cols
186193
n_rows = math.ceil(n_pdfs / n_cols)
187194
return n_cols, n_rows
188195

189196

190-
def calc_final_width_height(n_cols, n_rows):
191-
width = n_cols * PDF_WIDTH
192-
height = n_rows * PDF_HEIGHT
197+
def calc_final_width_height(n_cols, n_rows, pdf_width, pdf_height):
198+
width = n_cols * pdf_width
199+
height = n_rows * pdf_height
193200
return width, height
194201

195202

planvec/utils/qt_utils.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from PyQt5.QtWidgets import QLineEdit
2+
3+
4+
def get_text_or_placeholder_text(text_widget: QLineEdit) -> str:
5+
"""If a text is present, that is not '', grab the text, else, grab the placeholder text."""
6+
if text_widget.text() != '':
7+
return text_widget.text()
8+
else:
9+
return text_widget.placeholderText()

0 commit comments

Comments
 (0)