33import math
44from pathlib import Path
55
6- from dotmap import DotMap
7-
86from planvec .gui .datamanager import DataManager
97from planvec .utils .date_utils import get_date_time_tag
10- from config import planvec_config
118from 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-
2010UNITE_FILE_TEMPL = 'unite_plate-{plate_idx}_{date_time_tag}.pdf'
2111JAMMED_FILE_TEMPL = 'jammed_plate-{plate_idx}_{date_time_tag}.pdf'
2212
2313
2414class 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'\t Grid 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
164171def 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
0 commit comments