diff --git a/qim3d/utils/cli.py b/qim3d/utils/cli.py index 2b6e3bd008f3896a88cbab9c1863bf7800ddb19d..db01df31c69c6779b644a69520b3c0608fcc2dce 100644 --- a/qim3d/utils/cli.py +++ b/qim3d/utils/cli.py @@ -1,11 +1,13 @@ import argparse +import qim3d +import webbrowser from qim3d.gui import data_explorer, iso3d, annotation_tool, local_thickness def main(): parser = argparse.ArgumentParser(description='Qim3d command-line interface.') subparsers = parser.add_subparsers(title='Subcommands', dest='subcommand') - # subcommands + # GUIs gui_parser = subparsers.add_parser('gui', help = 'Graphical User Interfaces.') gui_parser.add_argument('--data-explorer', action='store_true', help='Run data explorer.') @@ -15,6 +17,11 @@ def main(): gui_parser.add_argument('--host', default='0.0.0.0', help='Desired host.') gui_parser.add_argument('--platform', action='store_true', help='Use QIM platform address') + # K3D + viz_parser = subparsers.add_parser('viz', help = 'Volumetric visualization.') + viz_parser.add_argument('--source', default=False, help='Path to the image file') + viz_parser.add_argument('--destination', default='k3d.html', help='Path to save html file.') + viz_parser.add_argument('--no-browser', action='store_true', help='Do not launch browser.') args = parser.parse_args() @@ -47,5 +54,25 @@ def main(): else: interface = local_thickness.Interface() interface.launch() + + + if args.subcommand == "viz": + if not args.source: + print ("Please specify a source file using the argument --source") + return + # Load the data + print (f"Loading data from {args.source}") + volume = qim3d.io.load(str(args.source)) + print (f"Done, volume shape: {volume.shape}") + + # Make k3d plot + print ("\nGenerating k3d plot...") + qim3d.viz.vol(volume, show=False, save=str(args.destination)) + print (f"Done, plot available at <{args.destination}>") + + if not args.no_browser: + print("Opening in default browser...") + webbrowser.open_new_tab(args.destination) + if __name__ == '__main__': main() \ No newline at end of file diff --git a/qim3d/viz/__init__.py b/qim3d/viz/__init__.py index 98132cca4381071e1d1954f5f3f6315da78fa8a4..ef978e880a26f9be8a1616c8375bb2aa8114484d 100644 --- a/qim3d/viz/__init__.py +++ b/qim3d/viz/__init__.py @@ -1,2 +1,3 @@ from .visualizations import plot_metrics from .img import grid_pred, grid_overview, slices +from .k3d import vol diff --git a/qim3d/viz/k3d.py b/qim3d/viz/k3d.py new file mode 100644 index 0000000000000000000000000000000000000000..b87235027a19f6f4feb10d94bcc9885c64b95b4b --- /dev/null +++ b/qim3d/viz/k3d.py @@ -0,0 +1,47 @@ +""" +Volumetric visualization using K3D +""" + +import k3d +import numpy as np + +def vol(img, show=True, save=False): + """ + Volumetric visualization of a given volume. + + Args: + img (numpy.ndarray): The input 3D image data. It should be a 3D numpy array. + show (bool, optional): If True, displays the visualization. Defaults to True. + save (bool or str, optional): If True, saves the visualization as an HTML file. + If a string is provided, it's interpreted as the file path where the HTML + file will be saved. Defaults to False. + + Returns: + k3d.plot: If show is False, returns the K3D plot object. + + Examples: + ```python + import qim3d + vol = qim3d.examples.fly_150x256x256 + + # shows the volume inline + qim3d.viz.vol(vol) + + # saves html plot to disk + plot = qim3d.viz.vol(vol, show=False, save="plot.html") + ``` + + """ + plt_volume = k3d.volume(img.astype(np.float32)) + plot = k3d.plot() + plot += plt_volume + + if save: + # Save html to disk + with open(str(save),'w', encoding="utf-8") as fp: + fp.write(plot.get_snapshot()) + + if show: + plot.display() + else: + return plot \ No newline at end of file