wolfhece 2.2.44__py3-none-any.whl → 2.2.46__py3-none-any.whl
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.
- wolfhece/PyCrosssections.py +215 -24
- wolfhece/PyDraw.py +18 -11
- wolfhece/PyGui.py +1 -1
- wolfhece/PyVertexvectors.py +45 -22
- wolfhece/apps/version.py +1 -1
- wolfhece/dike.py +20 -8
- wolfhece/lazviewer/laz_viewer.py +29 -6
- wolfhece/math_parser/calculator.py +1 -1
- wolfhece/matplotlib_fig.py +4 -4
- wolfhece/mesh2d/wolf2dprev.py +5 -13
- wolfhece/pydike.py +3 -274
- wolfhece/report/common.py +141 -24
- wolfhece/report/compare_arrays.py +43 -34
- wolfhece/report/compare_cs_dem.py +1453 -0
- wolfhece/report/pdf.py +1 -1
- wolfhece/synthetic_dike.py +276 -0
- wolfhece/wolf_array.py +11 -6
- wolfhece/wolfresults_2D.py +99 -0
- {wolfhece-2.2.44.dist-info → wolfhece-2.2.46.dist-info}/METADATA +1 -1
- {wolfhece-2.2.44.dist-info → wolfhece-2.2.46.dist-info}/RECORD +23 -21
- {wolfhece-2.2.44.dist-info → wolfhece-2.2.46.dist-info}/WHEEL +0 -0
- {wolfhece-2.2.44.dist-info → wolfhece-2.2.46.dist-info}/entry_points.txt +0 -0
- {wolfhece-2.2.44.dist-info → wolfhece-2.2.46.dist-info}/top_level.txt +0 -0
wolfhece/report/common.py
CHANGED
@@ -3,9 +3,12 @@ import wx
|
|
3
3
|
import os
|
4
4
|
import platform
|
5
5
|
|
6
|
+
import pandas as pd
|
6
7
|
import pymupdf as pdf
|
7
8
|
from tempfile import NamedTemporaryFile
|
8
9
|
from tempfile import TemporaryDirectory
|
10
|
+
from functools import cached_property
|
11
|
+
from PIL import Image
|
9
12
|
|
10
13
|
import matplotlib.pyplot as plt
|
11
14
|
import numpy as np
|
@@ -159,6 +162,81 @@ li {{
|
|
159
162
|
|
160
163
|
return html, css
|
161
164
|
|
165
|
+
|
166
|
+
def dict_to_html(data_dict:dict, font_size="10pt", font_family="Helvetica"):
|
167
|
+
""" Convert a dictionary to an HTML table with dataframe_image """
|
168
|
+
|
169
|
+
df = pd.DataFrame.from_dict(data_dict)
|
170
|
+
|
171
|
+
# Convert the DataFrame to an HTML table
|
172
|
+
html = df.to_html(index=False, border=0, justify='left')
|
173
|
+
|
174
|
+
# Generate the CSS
|
175
|
+
css = f"""
|
176
|
+
table {{
|
177
|
+
font-size: {font_size};
|
178
|
+
font-family: {font_family};
|
179
|
+
color: #2C3E50;
|
180
|
+
border-collapse: collapse;
|
181
|
+
}}
|
182
|
+
th, td {{
|
183
|
+
padding: 8px 12px;
|
184
|
+
border: 1px solid #BDC3C7;
|
185
|
+
}}
|
186
|
+
"""
|
187
|
+
|
188
|
+
return html, css
|
189
|
+
|
190
|
+
def dataframe_to_html(data:pd.DataFrame, font_size="10pt", font_family="Helvetica"):
|
191
|
+
""" Convert a DataFrame to an HTML table with dataframe_image """
|
192
|
+
|
193
|
+
# Convert the DataFrame to an HTML table
|
194
|
+
html = data.to_html(index=False, border=0, justify='left')
|
195
|
+
|
196
|
+
# Generate the CSS
|
197
|
+
css = f"""
|
198
|
+
table {{
|
199
|
+
font-size: {font_size};
|
200
|
+
font-family: {font_family};
|
201
|
+
color: #2C3E50;
|
202
|
+
border-collapse: collapse;
|
203
|
+
}}
|
204
|
+
th, td {{
|
205
|
+
padding: 8px 12px;
|
206
|
+
border: 1px solid #BDC3C7;
|
207
|
+
}}
|
208
|
+
"""
|
209
|
+
|
210
|
+
return html, css
|
211
|
+
|
212
|
+
def convert_report_to_images(pdf_path: str | Path, dpi=150) -> list[Image.Image]:
|
213
|
+
""" Convert the PDF report to a list of images (one per page).
|
214
|
+
|
215
|
+
:param dpi: Dots per inch for the output images.
|
216
|
+
:return: List of Images, one per page.
|
217
|
+
"""
|
218
|
+
|
219
|
+
if pdf_path is None:
|
220
|
+
raise ValueError("PDF report has not been saved yet. Please save the report before converting to images.")
|
221
|
+
|
222
|
+
pdf_path = Path(pdf_path)
|
223
|
+
if not pdf_path.exists():
|
224
|
+
raise FileNotFoundError(f"PDF report not found at {pdf_path}. Please check the path.")
|
225
|
+
|
226
|
+
doc = pdf.open(pdf_path)
|
227
|
+
images = []
|
228
|
+
|
229
|
+
zoom = dpi / 72 # 72 dpi is the default resolution
|
230
|
+
mat = pdf.Matrix(zoom, zoom)
|
231
|
+
|
232
|
+
for page_num in range(len(doc)):
|
233
|
+
page = doc.load_page(page_num)
|
234
|
+
pix = page.get_pixmap(matrix=mat, alpha=False)
|
235
|
+
img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
|
236
|
+
images.append(img)
|
237
|
+
|
238
|
+
return images
|
239
|
+
|
162
240
|
# A4 format
|
163
241
|
PAGE_WIDTH = 21 # cm
|
164
242
|
PAGE_HEIGHT = 29.7 # cm
|
@@ -169,7 +247,10 @@ SLIDE_WIDTH = inches2cm(13.3333) # cm
|
|
169
247
|
|
170
248
|
class DefaultLayoutA4(Zones):
|
171
249
|
"""
|
172
|
-
|
250
|
+
Global layout for A4 report.
|
251
|
+
|
252
|
+
This class inherits from Zones and defines a standard layout for A4 reports.
|
253
|
+
It includes predefined areas for the title, versions, logo, and footer.
|
173
254
|
"""
|
174
255
|
|
175
256
|
def __init__(self, title:str, filename = '', ox = 0, oy = 0, tx = 0, ty = 0, parent=None, is2D=True, idx = '', plotted = True, mapviewer=None, need_for_wx = False, bbox = None, find_minmax = True, shared = False, colors = None):
|
@@ -260,14 +341,21 @@ class DefaultLayoutA4(Zones):
|
|
260
341
|
vec_footer.find_minmax()
|
261
342
|
elts.add_vector(vec_footer, forceparent=True)
|
262
343
|
|
263
|
-
self._layout = {}
|
264
344
|
self._doc = None # Placeholder for the PDF document
|
265
345
|
self._pdf_path = None # Placeholder for the PDF file path
|
266
346
|
|
267
347
|
def add_element(self, name:str, width:float, height:float, x:float = 0, y:float = 0) -> vector:
|
268
348
|
"""
|
269
|
-
Add
|
349
|
+
Add a single element to the page.
|
350
|
+
|
351
|
+
:param name: Name of the element.
|
352
|
+
:param width: Width of the element in cm.
|
353
|
+
:param height: Height of the element in cm.
|
354
|
+
:param x: X coordinate of the bottom-left corner in cm.
|
355
|
+
:param y: Y coordinate of the bottom-left corner in cm.
|
356
|
+
:return: The created vector representing the element.
|
270
357
|
"""
|
358
|
+
|
271
359
|
vec = vector(name=name)
|
272
360
|
vec.add_vertex(wv(x, y))
|
273
361
|
vec.add_vertex(wv(x + width, y))
|
@@ -287,6 +375,19 @@ class DefaultLayoutA4(Zones):
|
|
287
375
|
first_x:float = 0, first_y:float = 0,
|
288
376
|
count_x:int = 1, count_y:int = 1,
|
289
377
|
padding:float = None) -> zone:
|
378
|
+
"""
|
379
|
+
Add multiple elements to the page in a grid.
|
380
|
+
|
381
|
+
:param name: Base name for the elements.
|
382
|
+
:param width: Width of each element in cm.
|
383
|
+
:param height: Height of each element in cm.
|
384
|
+
:param first_x: X coordinate of the first element in cm.
|
385
|
+
:param first_y: Y coordinate of the first element in cm.
|
386
|
+
:param count_x: Number of elements in the X direction (positive for right, negative for left).
|
387
|
+
:param count_y: Number of elements in the Y direction (positive for up, negative for down).
|
388
|
+
:param padding: Padding between elements in cm. If None, use self.padding.
|
389
|
+
:return: A zone containing the added elements.
|
390
|
+
"""
|
290
391
|
|
291
392
|
if padding is None:
|
292
393
|
padding = self.padding
|
@@ -315,7 +416,10 @@ class DefaultLayoutA4(Zones):
|
|
315
416
|
|
316
417
|
def check_if_overlap(self, vec:vector) -> bool:
|
317
418
|
"""
|
318
|
-
Check if the vector overlaps with any existing vector in the layout.
|
419
|
+
Check if the vector overlaps with any existing vector in the page layout.
|
420
|
+
|
421
|
+
:param vec: The vector to check.
|
422
|
+
:return: True if there is an overlap, False otherwise.
|
319
423
|
"""
|
320
424
|
for existing_vec in self['Elements'].myvectors:
|
321
425
|
if vec.linestring.overlaps(existing_vec.linestring):
|
@@ -327,6 +431,7 @@ class DefaultLayoutA4(Zones):
|
|
327
431
|
"""
|
328
432
|
Get the useful part of the page, excluding margins.
|
329
433
|
"""
|
434
|
+
|
330
435
|
vec = self[('Page', _('Page'))]
|
331
436
|
vec.find_minmax()
|
332
437
|
|
@@ -355,6 +460,7 @@ class DefaultLayoutA4(Zones):
|
|
355
460
|
"""
|
356
461
|
Get the dimensions of the page in centimeters.
|
357
462
|
"""
|
463
|
+
|
358
464
|
vec = self[('Page', _('Page'))]
|
359
465
|
vec.find_minmax()
|
360
466
|
width = vec.xmax - vec.xmin
|
@@ -364,25 +470,47 @@ class DefaultLayoutA4(Zones):
|
|
364
470
|
@property
|
365
471
|
def keys(self) -> list[str]:
|
366
472
|
"""
|
367
|
-
Get the keys of the layout.
|
473
|
+
Get the keys of the page layout.
|
368
474
|
"""
|
475
|
+
|
369
476
|
return [vec.myname for vec in self['Elements'].myvectors]
|
370
477
|
|
371
|
-
|
478
|
+
@cached_property
|
479
|
+
def layout(self) -> dict:
|
480
|
+
"""
|
481
|
+
Get the layout as a dictionary.
|
482
|
+
"""
|
483
|
+
|
484
|
+
return self._to_dict()
|
485
|
+
|
486
|
+
def get_item_in_layout(self, name:str):
|
487
|
+
""" Override the indexing to access layout elements by name. """
|
488
|
+
if isinstance(name, str):
|
489
|
+
if name not in self.layout:
|
490
|
+
raise KeyError(f"Element '{name}' not found in layout.")
|
491
|
+
|
492
|
+
return self.layout[name]
|
493
|
+
|
494
|
+
def _to_dict(self):
|
372
495
|
"""
|
373
496
|
Convert the layout Zones to a dictionary.
|
374
497
|
"""
|
498
|
+
|
375
499
|
layout = {}
|
376
500
|
|
377
501
|
for vec in self['Elements'].myvectors:
|
378
502
|
vec.find_minmax()
|
379
503
|
layout[vec.myname] = rect_cm(vec.xmin, PAGE_HEIGHT - vec.ymax, vec.xmax - vec.xmin, vec.ymax - vec.ymin)
|
380
504
|
|
505
|
+
return layout
|
506
|
+
|
381
507
|
def plot(self, scale=1.):
|
382
508
|
"""
|
383
|
-
Plot the layout using matplotlib.
|
509
|
+
Plot the page layout using matplotlib.
|
510
|
+
|
384
511
|
:param scale: Scale factor for the plot.
|
385
512
|
"""
|
513
|
+
|
386
514
|
fig, ax = plt.subplots(figsize=(cm2inches(PAGE_WIDTH) * scale, cm2inches(PAGE_HEIGHT)*scale))
|
387
515
|
|
388
516
|
self['Elements'].plot_matplotlib(ax = ax)
|
@@ -401,17 +529,6 @@ class DefaultLayoutA4(Zones):
|
|
401
529
|
|
402
530
|
return fig, ax
|
403
531
|
|
404
|
-
def _create_layout_pdf(self) -> dict:
|
405
|
-
"""
|
406
|
-
Create the layout dictionary for the report.
|
407
|
-
:return: A dictionary with layout information.
|
408
|
-
"""
|
409
|
-
for vec in self['Elements'].myvectors:
|
410
|
-
vec.find_minmax()
|
411
|
-
self._layout[vec.myname] = rect_cm(vec.xmin, PAGE_HEIGHT - vec.ymax, vec.xmax - vec.xmin, vec.ymax - vec.ymin)
|
412
|
-
|
413
|
-
return self._layout
|
414
|
-
|
415
532
|
def _summary_versions(self):
|
416
533
|
""" Find the versions of the simulation, wolfhece and the wolfgpu package """
|
417
534
|
import json
|
@@ -426,24 +543,23 @@ class DefaultLayoutA4(Zones):
|
|
426
543
|
return group_title, text
|
427
544
|
|
428
545
|
def _insert_to_page(self, page: pdf.Page):
|
546
|
+
""" Insert the layout into the PDF page. """
|
429
547
|
|
430
|
-
layout
|
431
|
-
|
432
|
-
page.insert_htmlbox(layout['Title'], f"<h1>{self.title}</h1>",
|
548
|
+
page.insert_htmlbox(self.layout['Title'], f"<h1>{self.title}</h1>",
|
433
549
|
css='h1 {font-size:16pt; font-family:Helvetica; color:#333}')
|
434
550
|
|
435
551
|
# versions box
|
436
552
|
try:
|
437
553
|
text = self._summary_versions()
|
438
554
|
html, css = list_to_html_aligned(text[1], font_size="10pt", font_family="Helvetica")
|
439
|
-
spare_height, scale = page.insert_htmlbox(layout['Versions'], html, css=css, scale_low
|
555
|
+
spare_height, scale = page.insert_htmlbox(self.layout['Versions'], html, css=css, scale_low=0.1)
|
440
556
|
|
441
557
|
if spare_height < 0.:
|
442
558
|
logging.warning("Text overflow in versions box. Adjusting scale.")
|
443
559
|
except:
|
444
560
|
logging.error("Failed to insert versions text. Using fallback method.")
|
445
561
|
|
446
|
-
rect = layout['Logo']
|
562
|
+
rect = self.layout['Logo']
|
447
563
|
# Add the logo to the top-right corner
|
448
564
|
logo_path = Path(__file__).parent / 'wolf_report.png'
|
449
565
|
if logo_path.exists():
|
@@ -454,7 +570,7 @@ class DefaultLayoutA4(Zones):
|
|
454
570
|
# Footer
|
455
571
|
# ------
|
456
572
|
# Insert the date and time of the report generation, the user and the PC name
|
457
|
-
footer_rect = layout['Footer']
|
573
|
+
footer_rect = self.layout['Footer']
|
458
574
|
footer_text = f"<p>Report generated on {dt.now()} by {os.getlogin()} on {platform.uname().node} - {platform.uname().machine} - {platform.uname().release} - {platform.uname().version}</br> \
|
459
575
|
This report does not guarantee the quality of the model and in no way commits the software developers.</p>"
|
460
576
|
page.insert_htmlbox(footer_rect, footer_text,
|
@@ -490,6 +606,7 @@ class DefaultLayoutA4(Zones):
|
|
490
606
|
self._pdf_path = None
|
491
607
|
return
|
492
608
|
|
609
|
+
|
493
610
|
@property
|
494
611
|
def pdf_path(self):
|
495
612
|
""" Return the PDF document """
|
@@ -9,8 +9,9 @@ import pymupdf as pdf
|
|
9
9
|
import wx
|
10
10
|
from tqdm import tqdm
|
11
11
|
from matplotlib import use, get_backend
|
12
|
+
from PIL.Image import Image
|
12
13
|
|
13
|
-
from .common import A4_rect, rect_cm, list_to_html, list_to_html_aligned, get_rect_from_text
|
14
|
+
from .common import A4_rect, rect_cm, list_to_html, list_to_html_aligned, get_rect_from_text, convert_report_to_images
|
14
15
|
from .common import inches2cm, pts2cm, cm2pts, cm2inches, DefaultLayoutA4, NamedTemporaryFile, pt2inches, TemporaryDirectory
|
15
16
|
from ..wolf_array import WolfArray, header_wolf, vector, zone, Zones, wolfvertex as wv, wolfpalette
|
16
17
|
from ..PyTranslate import _
|
@@ -39,11 +40,11 @@ class ArrayDifferenceLayout(DefaultLayoutA4):
|
|
39
40
|
width = useful.xmax - useful.xmin
|
40
41
|
height = useful.ymax - useful.ymin
|
41
42
|
|
42
|
-
self._hitograms = self.add_element_repeated(
|
43
|
+
self._hitograms = self.add_element_repeated("Histogram", width=width, height=2.5,
|
43
44
|
first_x=useful.xmin, first_y=useful.ymax,
|
44
45
|
count_x=1, count_y=-2, padding=0.5)
|
45
46
|
|
46
|
-
self._arrays = self.add_element_repeated(
|
47
|
+
self._arrays = self.add_element_repeated("Arrays", width= (width-self.padding) / 2, height=5.5,
|
47
48
|
first_x=useful.xmin, first_y=self._hitograms.ymin - self.padding,
|
48
49
|
count_x=2, count_y=-3, padding=0.5)
|
49
50
|
|
@@ -73,10 +74,10 @@ class CompareArraysLayout2(DefaultLayoutA4):
|
|
73
74
|
width = useful.xmax - useful.xmin
|
74
75
|
height = useful.ymax - useful.ymin
|
75
76
|
|
76
|
-
self._summary = self.add_element_repeated(
|
77
|
+
self._summary = self.add_element_repeated("Histogram", width=(width-self.padding) / 2, height=6., first_x=useful.xmin, first_y=useful.ymax-6, count_x=2, count_y=1)
|
77
78
|
|
78
|
-
self._arrays = self.add_element_repeated(
|
79
|
-
self._diff_rect = self.add_element(
|
79
|
+
self._arrays = self.add_element_repeated("Arrays", width= (width-self.padding) / 2, height=6., count_x=2, count_y=1, first_x=useful.xmin, first_y=14)
|
80
|
+
self._diff_rect = self.add_element("Position", width= width, height=11.5, x=useful.xmin, y=useful.ymin)
|
80
81
|
|
81
82
|
|
82
83
|
class ArrayDifference():
|
@@ -402,12 +403,12 @@ class ArrayDifference():
|
|
402
403
|
|
403
404
|
return fig, ax
|
404
405
|
|
405
|
-
def _complete_report(self,
|
406
|
+
def _complete_report(self, page:ArrayDifferenceLayout):
|
406
407
|
|
407
408
|
"""
|
408
409
|
Complete the report with the arrays and histograms.
|
409
410
|
"""
|
410
|
-
useful =
|
411
|
+
useful = page.useful_part
|
411
412
|
|
412
413
|
# Plot reference array
|
413
414
|
key_fig = [('Histogram_0-0', self.plot_histograms),
|
@@ -418,11 +419,11 @@ class ArrayDifference():
|
|
418
419
|
('Arrays_1-1', self.plot_to_compare),
|
419
420
|
('Arrays_0-2', self.plot_difference),]
|
420
421
|
|
421
|
-
keys =
|
422
|
+
keys = page.keys
|
422
423
|
for key, fig_routine in key_fig:
|
423
424
|
if key in keys:
|
424
425
|
|
425
|
-
rect =
|
426
|
+
rect = page.get_item_in_layout(key)
|
426
427
|
|
427
428
|
fig, ax = fig_routine()
|
428
429
|
|
@@ -435,7 +436,7 @@ class ArrayDifference():
|
|
435
436
|
# convert canvas to PNG and insert it into the PDF
|
436
437
|
temp_file = NamedTemporaryFile(delete=False, suffix='.png')
|
437
438
|
fig.savefig(temp_file, format='png', bbox_inches='tight', dpi=self._dpi)
|
438
|
-
|
439
|
+
page._page.insert_image(page.get_item_in_layout(key), filename=temp_file.name)
|
439
440
|
# delete the temporary file
|
440
441
|
temp_file.delete = True
|
441
442
|
temp_file.close()
|
@@ -448,7 +449,7 @@ class ArrayDifference():
|
|
448
449
|
key = 'Arrays_1-2'
|
449
450
|
if key in keys:
|
450
451
|
text, css = list_to_html(self._summary_text, font_size='8pt')
|
451
|
-
|
452
|
+
page._page.insert_htmlbox(page.get_item_in_layout(key), text,
|
452
453
|
css=css)
|
453
454
|
|
454
455
|
def create_report(self, output_file: str | Path = None) -> Path:
|
@@ -461,10 +462,10 @@ class ArrayDifference():
|
|
461
462
|
if output_file.exists():
|
462
463
|
logging.warning(f"Output file {output_file} already exists. It will be overwritten.")
|
463
464
|
|
464
|
-
|
465
|
-
|
466
|
-
self._complete_report(
|
467
|
-
|
465
|
+
page = ArrayDifferenceLayout(f"Differences - Index n°{self.index}")
|
466
|
+
page.create_report()
|
467
|
+
self._complete_report(page)
|
468
|
+
page.save_report(output_file)
|
468
469
|
sleep(0.2) # Ensure the file is saved before returning
|
469
470
|
|
470
471
|
return output_file
|
@@ -788,18 +789,18 @@ class CompareArrays:
|
|
788
789
|
]
|
789
790
|
return text_left, text_right
|
790
791
|
|
791
|
-
def _complete_report(self,
|
792
|
+
def _complete_report(self, page:CompareArraysLayout):
|
792
793
|
""" Complete the report with the global summary and individual differences. """
|
793
794
|
|
794
795
|
key_fig = [('Arrays_0-0', self.plot_reference),
|
795
796
|
('Arrays_1-0', self.plot_to_compare),
|
796
797
|
('Difference', self.plot_difference),]
|
797
798
|
|
798
|
-
keys =
|
799
|
+
keys = page.keys
|
799
800
|
for key, fig_routine in key_fig:
|
800
801
|
if key in keys:
|
801
802
|
|
802
|
-
rect =
|
803
|
+
rect = page.get_item_in_layout(key)
|
803
804
|
|
804
805
|
fig, ax = fig_routine()
|
805
806
|
|
@@ -809,7 +810,7 @@ class CompareArrays:
|
|
809
810
|
# convert canvas to PNG and insert it into the PDF
|
810
811
|
temp_file = NamedTemporaryFile(delete=False, suffix='.png')
|
811
812
|
fig.savefig(temp_file, format='png', bbox_inches='tight', dpi=self._dpi)
|
812
|
-
|
813
|
+
page._page.insert_image(page.get_item_in_layout(key), filename=temp_file.name)
|
813
814
|
# delete the temporary file
|
814
815
|
temp_file.delete = True
|
815
816
|
temp_file.close()
|
@@ -821,12 +822,12 @@ class CompareArrays:
|
|
821
822
|
|
822
823
|
tleft, tright = self.summary_text
|
823
824
|
|
824
|
-
rect =
|
825
|
+
rect = page.get_item_in_layout('Summary_0-0')
|
825
826
|
text_left, css_left = list_to_html(tleft, font_size='8pt')
|
826
|
-
|
827
|
-
rect =
|
827
|
+
page._page.insert_htmlbox(rect, text_left, css=css_left)
|
828
|
+
rect = page.get_item_in_layout('Summary_1-0')
|
828
829
|
text_right, css_right = list_to_html(tright, font_size='8pt')
|
829
|
-
|
830
|
+
page._page.insert_htmlbox(rect, text_right, css=css_right)
|
830
831
|
|
831
832
|
def plot_histogram_features(self, figax:tuple[plt.Figure, plt.Axes]=None, density = True, alpha = 0.5, **kwargs) -> tuple[plt.Figure, plt.Axes]:
|
832
833
|
"""
|
@@ -901,7 +902,7 @@ class CompareArrays:
|
|
901
902
|
|
902
903
|
return fig, ax
|
903
904
|
|
904
|
-
def _complete_report2(self,
|
905
|
+
def _complete_report2(self, page:CompareArraysLayout):
|
905
906
|
""" Complete the report with the individual differences. """
|
906
907
|
|
907
908
|
key_fig = [('Histogram_0-0', self.plot_histogram_features),
|
@@ -911,11 +912,11 @@ class CompareArrays:
|
|
911
912
|
('Position', self.plot_topo_grey),
|
912
913
|
]
|
913
914
|
|
914
|
-
keys =
|
915
|
+
keys = page.keys
|
915
916
|
for key, fig_routine in key_fig:
|
916
917
|
if key in keys:
|
917
918
|
|
918
|
-
rect =
|
919
|
+
rect = page.get_item_in_layout(key)
|
919
920
|
|
920
921
|
fig, ax = fig_routine()
|
921
922
|
|
@@ -926,7 +927,7 @@ class CompareArrays:
|
|
926
927
|
# convert canvas to PNG and insert it into the PDF
|
927
928
|
temp_file = NamedTemporaryFile(delete=False, suffix='.png')
|
928
929
|
fig.savefig(temp_file, format='png', bbox_inches='tight', dpi=self._dpi)
|
929
|
-
|
930
|
+
page._page.insert_image(page.get_item_in_layout(key), filename=temp_file.name)
|
930
931
|
# delete the temporary file
|
931
932
|
temp_file.delete = True
|
932
933
|
temp_file.close()
|
@@ -949,9 +950,9 @@ class CompareArrays:
|
|
949
950
|
if output_file.exists():
|
950
951
|
logging.warning(f"Output file {output_file} already exists. It will be overwritten.")
|
951
952
|
|
952
|
-
|
953
|
-
|
954
|
-
self._complete_report(
|
953
|
+
page = CompareArraysLayout("Comparison Report")
|
954
|
+
page.create_report()
|
955
|
+
self._complete_report(page)
|
955
956
|
|
956
957
|
if nb_max_differences < 0:
|
957
958
|
nb_max_differences = len(self.difference_parts)
|
@@ -975,12 +976,12 @@ class CompareArrays:
|
|
975
976
|
all_pdfs.extend([self.difference_parts[idx].create_report(Path(temp_dir) / f"array_difference_{idx}.pdf") for idx in tqdm(features_to_treat, desc="Creating individual difference reports")])
|
976
977
|
|
977
978
|
for pdf_file in tqdm(all_pdfs, desc="Compiling PDFs"):
|
978
|
-
|
979
|
+
page._doc.insert_file(pdf_file)
|
979
980
|
|
980
981
|
# create a TOC
|
981
|
-
|
982
|
+
page._doc.set_toc(page._doc.get_toc())
|
982
983
|
|
983
|
-
|
984
|
+
page.save_report(output_file)
|
984
985
|
self._pdf_path = output_file
|
985
986
|
|
986
987
|
@property
|
@@ -991,6 +992,14 @@ class CompareArrays:
|
|
991
992
|
else:
|
992
993
|
raise AttributeError("PDF path not set. Please create the report first.")
|
993
994
|
|
995
|
+
def convert_report_to_images(self, dpi:int = 150) -> list[Image]:
|
996
|
+
""" Convert the PDF report to a list of images (one per page). """
|
997
|
+
if self.pdf_path is None or not self.pdf_path.exists():
|
998
|
+
raise FileNotFoundError("PDF report not found. Please create the report first.")
|
999
|
+
|
1000
|
+
images = convert_report_to_images(self.pdf_path, dpi=dpi)
|
1001
|
+
return images
|
1002
|
+
|
994
1003
|
class CompareArrays_wx(PDFViewer):
|
995
1004
|
|
996
1005
|
def __init__(self, reference: WolfArray | str | Path,
|