From 5518f7d30fc53e067e686464a8c10c738f37a91f Mon Sep 17 00:00:00 2001 From: Adam Zsarnoczay <33822153+zsarnoczay@users.noreply.github.com> Date: Wed, 5 Aug 2026 17:13:54 +0200 Subject: [PATCH 1/2] feat(DL_visuals): add dataset_paths query for pelicun 3.10 PBE needs the on-disk location of each default model dataset so it can offer them in the component database selector. pelicun 3.10 moved these datasets out of the package tree and into the separately installed DLML package, where their paths are only discoverable through the library's resolver. Add a `query dataset_paths` keyword that reads the method alias map from the pelicun resources folder, resolves each alias through `pelicun.file_io.resolve_default_dataset_path`, and writes a single JSON object mapping each alias to its absolute dataset directory and its DLML dataset ID. Leave the `query default_db` output untouched; older PBE builds parse it. --- modules/performDL/pelicun3/DL_visuals.py | 27 ++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/modules/performDL/pelicun3/DL_visuals.py b/modules/performDL/pelicun3/DL_visuals.py index 30e0d7125..517367ff8 100644 --- a/modules/performDL/pelicun3/DL_visuals.py +++ b/modules/performDL/pelicun3/DL_visuals.py @@ -1135,6 +1135,33 @@ def main(args): # noqa: D103 if args.comp_db_path == 'default_db': print(pelicun_path) # noqa: T201 + elif args.comp_db_path == 'dataset_paths': + try: + from pelicun.file_io import ( # noqa: PLC0415, RUF100 + resolve_default_dataset_path, + ) + except ImportError: + print( # noqa: T201 + 'The installed pelicun does not provide dataset path ' + 'resolution. pelicun >= 3.10 is required.', + file=sys.stderr, + ) + sys.exit(1) + + alias_map_path = pelicun_path / 'resources' / 'dlml_resource_paths.json' + with alias_map_path.open(encoding='utf-8') as f: + alias_map = json.load(f) + + dataset_paths = { + alias: { + 'path': str(resolve_default_dataset_path(alias)), + 'id': dataset_id.rstrip('/'), + } + for alias, dataset_id in alias_map.items() + } + + print(json.dumps(dataset_paths)) # noqa: T201 + # print("--- %s seconds ---" % (time.time() - start_time)) From 94fe51907d7adcd544130915181b8d9a677e3fcb Mon Sep 17 00:00:00 2001 From: Adam Zsarnoczay <33822153+zsarnoczay@users.noreply.github.com> Date: Wed, 5 Aug 2026 21:34:07 +0200 Subject: [PATCH 2/2] fix(DL_visuals): ship a patched local plotly bundle for the viewer Modern plotly emits the CDN script tag with integrity and crossorigin attributes that fail Chromium's CORS check in the PBE figure viewer, and its bundle injects :focus-visible CSS rules that the Chromium in Qt 5.15 cannot parse. This leaves the figure area blank. Write the plotly.js bundle into each figure folder and reference it relatively (include_plotlyjs='directory'), with the :focus-visible selectors downgraded to :focus. --- modules/performDL/pelicun3/DL_visuals.py | 28 ++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/modules/performDL/pelicun3/DL_visuals.py b/modules/performDL/pelicun3/DL_visuals.py index 517367ff8..bb4c09054 100644 --- a/modules/performDL/pelicun3/DL_visuals.py +++ b/modules/performDL/pelicun3/DL_visuals.py @@ -51,6 +51,7 @@ import pandas as pd from pelicun.base import convert_to_MultiIndex, pelicun_path from plotly import graph_objects as go +from plotly.offline import get_plotlyjs from plotly.subplots import make_subplots from scipy.stats import norm, weibull_min @@ -452,7 +453,7 @@ def plot_fragility(comp_db_path, output_path, create_zip='0'): # noqa: C901, D1 ) with open(f'{output_path}/{comp_id}.html', 'w') as f: # noqa: PTH123 - f.write(fig.to_html(full_html=False, include_plotlyjs='cdn')) + f.write(fig.to_html(full_html=False, include_plotlyjs='directory')) # store the source database file(s) in the output directory for future reference shutil.copy(comp_db_path, Path(output_path) / Path(comp_db_path).name) @@ -1025,7 +1026,7 @@ def plot_repair(comp_db_path, output_path, create_zip='0'): # noqa: C901, PLR09 with open(f'{output_path}/{comp_id}-{c_type}.html', 'w') as f: # noqa: PTH123 # Minimize size by not saving javascript libraries which means # internet connection is required to view the figure. - f.write(fig.to_html(full_html=False, include_plotlyjs='cdn')) + f.write(fig.to_html(full_html=False, include_plotlyjs='directory')) # store the source database file(s) in the output directory for future reference shutil.copy(comp_db_path, Path(output_path) / Path(comp_db_path).name) @@ -1102,6 +1103,27 @@ def check_diff(comp_db_path, output_path): # noqa: D103 return True +def write_plotly_bundle(output_path, create_zip='0'): # noqa: D103 + if create_zip == '1': + return + + # A local bundle is needed because the CDN script tag carries SRI/CORS + # attributes that QtWebEngine blocks, and it needs the replacement below + # because Qt 5.15's Chromium cannot parse :focus-visible CSS rules + plotly_js = get_plotlyjs().replace(':focus-visible', ':focus') + + # Refresh the bundle in cached figure folders too, so bundle updates + # reach them, but skip the write when the file is already current. + bundle_path = Path(output_path, 'plotly.min.js') + if ( + bundle_path.is_file() + and bundle_path.stat().st_size == len(plotly_js.encode('utf-8')) + ): + return + + bundle_path.write_text(plotly_js, encoding='utf-8') + + def main(args): # noqa: D103 parser = argparse.ArgumentParser() parser.add_argument('viz_type') @@ -1131,6 +1153,8 @@ def main(args): # noqa: D103 else: print('No need to generate, figures already exist in the output folder.') # noqa: T201 + write_plotly_bundle(output_path, args.zip) + elif args.viz_type == 'query': if args.comp_db_path == 'default_db': print(pelicun_path) # noqa: T201