diff --git a/CHANGES.md b/CHANGES.md index 727f1e54..0c156ce1 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,7 +1,15 @@ # Release notes See also the -[unreleased changes](https://foss.heptapod.net/fluiddyn/fluidimage/-/compare/0.4.2...branch%2Fdefault). +[unreleased changes](https://foss.heptapod.net/fluiddyn/fluidimage/-/compare/0.4.3...branch%2Fdefault). + +## [0.4.3] (2024-03-27) + +- [!85](https://foss.heptapod.net/fluiddyn/fluidimage/-/merge_requests/85): `fluidpivviewer`. +- [!84](https://foss.heptapod.net/fluiddyn/fluidimage/-/merge_requests/84): `multi_exec_async` + using {class}`fluidimage.topologies.splitters.Splitter`. +- Other bugfixes and improvements (name PIV files and + {class}`fluidimage.postproc.vector_field.VectorFieldOnGrid`). ## [0.4.2] (2024-03-20) @@ -168,3 +176,4 @@ This version contains incompatible API changes documented here. [0.4.0]: https://foss.heptapod.net/fluiddyn/fluidimage/-/compare/0.3.0...0.4.0 [0.4.1]: https://foss.heptapod.net/fluiddyn/fluidimage/-/compare/0.4.0...0.4.1 [0.4.2]: https://foss.heptapod.net/fluiddyn/fluidimage/-/compare/0.4.1...0.4.2 +[0.4.3]: https://foss.heptapod.net/fluiddyn/fluidimage/-/compare/0.4.2...0.4.3 diff --git a/doc/conf.py b/doc/conf.py index c54b180a..17542e78 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -13,18 +13,13 @@ import os -os.environ["OMP_NUM_THREADS"] = "1" - import fluidimage -# we want this module to be importable. -try: - import fluidimage.topologies.optical_flow -except Exception: - import traceback - - traceback.print_exc() +# we want these modules to be importable. +import fluidimage.topologies.preproc +import fluidimage.topologies.optical_flow +os.environ["OMP_NUM_THREADS"] = "1" # -- General configuration ---------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. diff --git a/doc/examples/piv_parallel.py b/doc/examples/piv_parallel.py index 30cbbc61..f8f2ebf2 100644 --- a/doc/examples/piv_parallel.py +++ b/doc/examples/piv_parallel.py @@ -5,11 +5,17 @@ params.series.path = get_path_image_samples() / "Karman/Images" +params.mask.strcrop = "50:350, 0:380" + params.piv0.shape_crop_im0 = 32 -params.multipass.number = 2 -params.multipass.use_tps = False +params.piv0.displacement_max = 5 +params.piv0.nb_peaks_to_search = 2 -params.mask.strcrop = ":, 50:500" +params.fix.correl_min = 0.4 +params.fix.threshold_diff_neighbour = 2.0 + +params.multipass.number = 2 +params.multipass.use_tps = "last" # params.saving.how = 'complete' params.saving.postfix = "piv_example" diff --git a/doc/examples/piv_try_params.py b/doc/examples/piv_try_params.py index 8d1f62c8..1fa40400 100644 --- a/doc/examples/piv_try_params.py +++ b/doc/examples/piv_try_params.py @@ -4,20 +4,18 @@ params = Work.create_default_params() -params.multipass.number = 2 -params.multipass.use_tps = True +params.series.path = "../../image_samples/Oseen/Images" + +params.mask.strcrop = "30:250, 100:" params.piv0.shape_crop_im0 = 32 params.piv0.displacement_max = 5 + params.fix.correl_min = 0.2 params.fix.threshold_diff_neighbour = 8 -params.mask.strcrop = "30:250, 100:" - -path = "../../image_samples/Oseen/Images" -# path = '../../image_samples/Karman/Images' -params.series.path = path -params.series.str_subset = "i+1:i+3" +params.multipass.number = 2 +params.multipass.use_tps = True work = Work(params=params) diff --git a/doc/examples/piv_try_params_Karman.py b/doc/examples/piv_try_params_Karman.py new file mode 100644 index 00000000..524b6b42 --- /dev/null +++ b/doc/examples/piv_try_params_Karman.py @@ -0,0 +1,28 @@ +"""To be run in IPython to find a good set of parameters""" + +from fluidimage.piv import Work + +params = Work.create_default_params() + +params.series.path = "../../image_samples/Karman/Images" + +params.mask.strcrop = "50:350, 0:380" + +params.fix.correl_min = 0.4 +params.fix.threshold_diff_neighbour = 2.0 + +params.piv0.shape_crop_im0 = 32 +params.piv0.displacement_max = 5 +params.piv0.nb_peaks_to_search = 2 + +params.multipass.number = 2 +params.multipass.use_tps = "last" + +work = Work(params=params) + +piv = work.process_1_serie() + +# piv.display(show_interp=True, scale=0.3, show_error=False) +piv.display(show_interp=False, scale=1, show_error=True) + +# piv.save() diff --git a/doc/tutorials/tuto_piv.md b/doc/tutorials/tuto_piv.md index cbbd1c1c..1df3e1fc 100644 --- a/doc/tutorials/tuto_piv.md +++ b/doc/tutorials/tuto_piv.md @@ -66,9 +66,17 @@ the input images: path_src = get_path_image_samples() / "Karman/Images" params.series.path = str(path_src) -params.piv0.shape_crop_im0 = 64 +params.mask.strcrop = "50:350, 0:400" + +params.piv0.shape_crop_im0 = 48 +params.piv0.displacement_max = 5 +params.piv0.nb_peaks_to_search = 2 + +params.fix.correl_min = 0.4 +params.fix.threshold_diff_neighbour = 2.0 + params.multipass.number = 2 -params.multipass.use_tps = False +params.multipass.use_tps = "last" ``` After instantiating the `Work` class, @@ -204,15 +212,23 @@ params.saving._print_doc() path_src = get_path_image_samples() / "Karman/Images" params.series.path = str(path_src) -params.piv0.shape_crop_im0 = 64 +params.mask.strcrop = "50:350, 0:400" + +params.piv0.shape_crop_im0 = 48 +params.piv0.displacement_max = 5 +params.piv0.nb_peaks_to_search = 2 + +params.fix.correl_min = 0.4 +params.fix.threshold_diff_neighbour = 2.0 + params.multipass.number = 2 -params.multipass.use_tps = False +params.multipass.use_tps = "last" params.saving.how = 'recompute' params.saving.postfix = "doc_piv_ipynb" ``` -In order to run the PIV computation, we have to instanciate an object of the class +In order to run the PIV computation, we have to instantiate an object of the class {class}`fluidimage.piv.Topology`. ```{code-cell} ipython3 @@ -243,6 +259,13 @@ path_src topology.path_dir_result ``` +```{code-cell} ipython3 +sorted(path.name for path in topology.path_dir_result.glob("*")) +``` + +Fluidimage provides the command `fluidpivviewer`, which starts a very simple GUI to +visualize the PIV results. + ## Analyzing the computation ```{code-cell} ipython3 diff --git a/image_samples/Milestone/piv_0001a-b.h5 b/image_samples/Milestone/piv_0001a-b.h5 new file mode 120000 index 00000000..5497784e --- /dev/null +++ b/image_samples/Milestone/piv_0001a-b.h5 @@ -0,0 +1 @@ +./piv_0000a-b.h5 \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 5ebe9be5..bf46b0ac 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ build-backend = 'mesonpy' [project] name = "fluidimage" -version = "0.4.2" +version = "0.4.3" description = "Fluid image processing with Python." authors = [ {name = "Pierre Augier", email = "pierre.augier@legi.cnrs.fr"}, @@ -55,6 +55,7 @@ Homepage = "https://foss.heptapod.net/fluiddyn/fluidimage" fluidimviewer-pg = "fluidimage.gui.pg_main:main" fluidimviewer = "fluidimage.gui.imviewer:main" fluidimlauncher = "fluidimage.gui.launcher.main:main" +fluidpivviewer = "fluidimage.gui.piv_viewer:main" [project.optional-dependencies] pims = ["pims"] diff --git a/src/fluidimage/__init__.py b/src/fluidimage/__init__.py index 0e9fc39e..96b9500f 100644 --- a/src/fluidimage/__init__.py +++ b/src/fluidimage/__init__.py @@ -65,6 +65,10 @@ def get_path_image_samples(): if path_image_samples.exists(): return path_image_samples.resolve() + path_image_samples = Path.home() / "dev/fluidimage/image_samples" + if path_image_samples.exists(): + return path_image_samples + # Gitlab and Github CI for name_env_var_project_dir in ("CI_PROJECT_DIR", "GITHUB_WORKSPACE"): ci_project_dir = os.getenv(name_env_var_project_dir) diff --git a/src/fluidimage/gui/__init__.py b/src/fluidimage/gui/__init__.py index 1fb4452b..24a81e5f 100644 --- a/src/fluidimage/gui/__init__.py +++ b/src/fluidimage/gui/__init__.py @@ -9,8 +9,10 @@ .. autosummary:: :toctree: + base_matplotlib imviewer launcher pg_main + piv_viewer """ diff --git a/src/fluidimage/gui/base_matplotlib.py b/src/fluidimage/gui/base_matplotlib.py new file mode 100644 index 00000000..487d13f9 --- /dev/null +++ b/src/fluidimage/gui/base_matplotlib.py @@ -0,0 +1,32 @@ +"""Base class using matplotlib widgets + +""" + +from matplotlib.widgets import Button, TextBox + + +class AppMatplotlibWidgets: + + _buttons: dict + _textboxes: dict + + def __init__(self): + self._buttons = {} + self._textboxes = {} + + def _create_button(self, fig, rect, text, func): + ax = fig.add_axes(rect) + button = Button(ax, text) + button.on_clicked(func) + self._buttons[text] = button + return button + + def _create_text_box(self, fig, rect, name, func, initial): + ax = fig.add_axes(rect) + textbox = TextBox(ax, name, initial=initial) + textbox.on_submit(func) + self._textboxes[name] = textbox + return textbox + + def get_textbox(self, key): + return self._textboxes[key] diff --git a/src/fluidimage/gui/imviewer.py b/src/fluidimage/gui/imviewer.py index 5419b6dc..dd93e679 100644 --- a/src/fluidimage/gui/imviewer.py +++ b/src/fluidimage/gui/imviewer.py @@ -14,11 +14,11 @@ from glob import glob import matplotlib.pyplot as plt -from matplotlib.widgets import Button, TextBox from fluiddyn.io.image import imread from fluiddyn.util import time_as_str from fluiddyn.util.serieofarrays import SerieOfArraysFromFiles +from fluidimage.gui.base_matplotlib import AppMatplotlibWidgets from fluidimage.util import safe_eval extensions = ["png", "tif", "tiff", "jpg", "jpeg", "bmp", "cine"] @@ -66,7 +66,7 @@ def parse_args(): return parser.parse_args() -class ImageViewer: +class ImageViewer(AppMatplotlibWidgets): """Simple Image viewer.""" def __init__(self, args): @@ -98,8 +98,7 @@ def __init__(self, args): self.nb_images = len(self.path_files) print(f"Will use {self.nb_images} images in the dir {path_dir}") - self._buttons = {} - self._textboxes = {} + super().__init__() fig = self.fig = plt.figure() fig.canvas.manager.set_window_title( @@ -133,14 +132,12 @@ def __init__(self, args): function_buttons[3] = self._increase_ifile_n y = size_button / 3.0 - for i, x in enumerate(x_buttons): - name = name_buttons[i] - func = function_buttons[i] + for x, name, func in zip(x_buttons, name_buttons, function_buttons): self._create_button(fig, [x, y, size_button, size_button], name, func) self._n = 1 - self._create_text( + self._create_text_box( fig, [0.1, y, 2 * size_button, size_button], "n = ", @@ -148,7 +145,7 @@ def __init__(self, args): "1", ) - self._create_text( + self._create_text_box( fig, [0.87, 0.92, 1.5 * size_button, size_button], "cmax = ", @@ -156,7 +153,7 @@ def __init__(self, args): "{:.2f}".format(self.clim[1]), ) - self._create_text( + self._create_text_box( fig, [0.87, 0.1, 1.5 * size_button, size_button], "cmin = ", @@ -235,20 +232,6 @@ def change_im(self): print("\rchanged to file " + name_file + " " * 20) self._image_changing = False - def _create_button(self, fig, rect, text, func): - ax = fig.add_axes(rect) - button = Button(ax, text) - button.on_clicked(func) - self._buttons[text] = button - return button - - def _create_text(self, fig, rect, name, func, initial): - ax = fig.add_axes(rect) - textbox = TextBox(ax, name, initial=initial) - textbox.on_submit(func) - self._textboxes[name] = textbox - return textbox - def _switch(self): if self._last_was_increase: self._decrease_ifile_n() diff --git a/src/fluidimage/gui/meson.build b/src/fluidimage/gui/meson.build index ec28bc3b..2b204cce 100644 --- a/src/fluidimage/gui/meson.build +++ b/src/fluidimage/gui/meson.build @@ -1,11 +1,14 @@ python_sources = [ '__init__.py', + 'base_matplotlib.py', 'imviewer.py', 'pg_main.py', 'pg_wrapper.py', + 'piv_viewer.py', 'test_imviewer.py', 'test_imviewer_pg.py', + 'test_piv_viewer.py', ] py.install_sources( diff --git a/src/fluidimage/gui/piv_viewer.py b/src/fluidimage/gui/piv_viewer.py new file mode 100644 index 00000000..bcc13dce --- /dev/null +++ b/src/fluidimage/gui/piv_viewer.py @@ -0,0 +1,211 @@ +"""PIV viewer + +Coded with matplotlib GUI! + +.. autoclass:: VectorFieldsViewer + :members: + :private-members: + +""" + +import argparse +import os +import sys +from pathlib import Path + +import h5py +import matplotlib.pyplot as plt + +from fluiddyn.util.serieofarrays import SerieOfArraysFromFiles +from fluidimage.gui.base_matplotlib import AppMatplotlibWidgets + +size_button = 0.06 +sep_button = 0.02 +x0 = 0.5 + +name_buttons = ["-1", "+1"] + +x_buttons = [ + x0 + i * (size_button + sep_button) for i in range(len(name_buttons)) +] + + +def get_piv_data_from_path(path): + + with h5py.File(path, "r") as file: + class_name = file.attrs["class_name"] + module_name = file.attrs["module_name"] + + if isinstance(class_name, bytes): + class_name = class_name.decode() + module_name = module_name.decode() + + if ( + class_name in ("MultipassPIVResults", "LightPIVResults") + and module_name == "fluidimage.data_objects.piv" + ): + if class_name == "MultipassPIVResults": + with h5py.File(path, "r") as file: + keys = sorted(key for key in file.keys() if key.startswith("piv")) + key_piv = keys[-1] + else: + key_piv = "piv" + + with h5py.File(path, "r") as file: + piv = file[key_piv] + ixvecs = piv["ixvecs_final"][...] + iyvecs = piv["iyvecs_final"][...] + deltaxs = piv["deltaxs_final"][...] + deltays = piv["deltays_final"][...] + + else: + raise NotImplementedError + + return deltaxs, deltays, ixvecs, iyvecs + + +class VectorFieldsViewer(AppMatplotlibWidgets): + """A simple vector field viewer.""" + + @classmethod + def parse_args(cls): + + parser = argparse.ArgumentParser( + description=cls.__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter, + ) + parser.add_argument( + "path", + help="Path file or directory.", + type=str, + nargs="?", + default=os.getcwd(), + ) + parser.add_argument( + "-v", "--verbose", help="verbose mode", action="count" + ) + + return parser.parse_args() + + def __init__(self, args): + super().__init__() + + path = Path(args.path).absolute() + + if path.is_file(): + path_file_init = path + else: + path_file_init = None + + if path.is_dir(): + try: + path = next(path.glob("piv*")) + except StopIteration: + print(f"No PIV files found in {args.path}") + sys.exit(1) + + serie = self.serie = SerieOfArraysFromFiles(path) + + if not serie: + print(f"Not PIV file found (from {args.path=})") + sys.exit(1) + + self.path_dir = Path(serie.path_dir) + + # initialize the figure + fig = self.fig = plt.figure() + self.ax = fig.add_axes([0.07, 0.15, 0.9, 0.78]) + + self._init_name_files() + + if path_file_init is None: + path_file_init = self.path_dir / self.name_files[0] + self.index_file = 0 + else: + self.index_file = self.name_files.index(path_file_init.name) + + self._init_figure(path_file_init) + + plt.show() + + def _init_name_files(self): + + self.name_files = sorted( + p.name + for p in self.path_dir.glob( + self.serie.base_name + "*" + self.serie.extension_file + ) + ) + self.num_files = len(self.name_files) + self.fig.canvas.manager.set_window_title( + f"{self.num_files} PIV files in {self.path_dir}" + ) + + def _init_figure(self, path_file_init): + + self.ax.set_title(path_file_init.name) + + deltaxs, deltays, ixvecs, iyvecs = get_piv_data_from_path(path_file_init) + + self.ax.invert_yaxis() + + self._quiver = self.ax.quiver( + ixvecs, iyvecs, deltaxs, deltays, angles="xy", scale_units="xy" + ) + + y = size_button / 3.0 + + self._create_text_box( + self.fig, + [0.1, y, size_button, size_button], + "index = ", + self._change_index_from_textbox, + str(self.index_file), + ) + + function_buttons = [self._decrement_index, self._increment_index] + for x, name, func in zip(x_buttons, name_buttons, function_buttons): + self._create_button( + self.fig, [x, y, size_button, size_button], name, func + ) + + def _increment_index(self, event=None): + self._set_index(self.index_file + 1) + + def _decrement_index(self, event=None): + self._set_index(self.index_file - 1) + + def _change_index_from_textbox(self, text): + try: + index = int(text) + except ValueError: + self._set_textbox_value(self.index_file) + return + if index >= self.num_files: + index = self.num_files - 1 + elif index < 0: + index = 0 + self._set_textbox_value(index) + self._set_index(index) + + def _set_textbox_value(self, value): + textbox = self.get_textbox("index = ") + textbox.set_val(str(value)) + + def _set_index(self, index): + if index == self.index_file: + return + self.index_file = index % self.num_files + self._set_textbox_value(self.index_file) + self._update_fig() + + def _update_fig(self): + path_file = self.path_dir / self.name_files[self.index_file] + deltaxs, deltays, ixvecs, iyvecs = get_piv_data_from_path(path_file) + self.ax.set_title(path_file.name) + self._quiver.set_UVC(deltaxs, deltays) + + +def main(): + args = VectorFieldsViewer.parse_args() + return VectorFieldsViewer(args) diff --git a/src/fluidimage/gui/test_piv_viewer.py b/src/fluidimage/gui/test_piv_viewer.py new file mode 100644 index 00000000..e38d92a6 --- /dev/null +++ b/src/fluidimage/gui/test_piv_viewer.py @@ -0,0 +1,40 @@ +import sys + +from fluidimage import get_path_image_samples +from fluidimage.gui.piv_viewer import main + + +def test_main(monkeypatch): + + path_image_samples = get_path_image_samples() + path = path_image_samples / "Milestone" + + command = f"fluidpivviewer {path}" + + with monkeypatch.context() as ctx: + ctx.setattr(sys, "argv", command.split()) + viewer = main() + + assert viewer.index_file == 0 + + path = path / "piv_0000a-b.h5" + command = f"fluidpivviewer {path}" + + with monkeypatch.context() as ctx: + ctx.setattr(sys, "argv", command.split()) + viewer = main() + + assert viewer.index_file == 0 + + viewer._increment_index() + assert viewer.index_file == 1 + + viewer._change_index_from_textbox("10") + assert viewer.index_file == 1 + + viewer._change_index_from_textbox("-1") + assert viewer.index_file == 0 + + viewer._decrement_index() + + viewer._change_index_from_textbox("abc") diff --git a/src/fluidimage/meson.build b/src/fluidimage/meson.build index bb05b337..284b2ba8 100644 --- a/src/fluidimage/meson.build +++ b/src/fluidimage/meson.build @@ -9,6 +9,7 @@ python_sources = [ 'image2image.py', 'optical_flow.py', 'piv.py', + 'preproc.py', 'run_from_xml.py', 'synthetic.py', 'test_image2image.py', @@ -26,7 +27,6 @@ subdir('data_objects') subdir('executors') subdir('gui') subdir('postproc') -subdir('preproc') subdir('reconstruct') subdir('topologies') subdir('util') diff --git a/src/fluidimage/preproc/__init__.py b/src/fluidimage/preproc.py similarity index 86% rename from src/fluidimage/preproc/__init__.py rename to src/fluidimage/preproc.py index 9c1cd08f..009fb087 100644 --- a/src/fluidimage/preproc/__init__.py +++ b/src/fluidimage/preproc.py @@ -5,16 +5,6 @@ undesirable effects. Preprocessing images by careful use of thresholds and filters can significantly improve the quality of PIV. -Provides: - -.. autosummary:: - :toctree: - - toolbox - _toolbox_cv - _toolbox_py - io - Provides .. autoclass:: Work diff --git a/src/fluidimage/topologies/preproc.py b/src/fluidimage/topologies/preproc.py index e123179a..d6080456 100644 --- a/src/fluidimage/topologies/preproc.py +++ b/src/fluidimage/topologies/preproc.py @@ -18,7 +18,7 @@ from fluidimage.data_objects.preproc import PreprocResults, get_name_preproc from fluidimage.topologies import TopologyBaseFromSeries, prepare_path_dir_result from fluidimage.topologies.splitters import SplitterFromSeries -from fluidimage.util import imread, logger +from fluidimage.util import imread from fluidimage.works import image2image from fluidimage.works.preproc import ( WorkPreproc, diff --git a/src/fluidimage/works/meson.build b/src/fluidimage/works/meson.build index 1c68c7b9..49666c92 100644 --- a/src/fluidimage/works/meson.build +++ b/src/fluidimage/works/meson.build @@ -4,7 +4,6 @@ python_sources = [ 'bos.py', 'image2image.py', 'optical_flow.py', - 'preproc.py', 'surface_tracking.py', 'with_mask.py', 'test_bos.py', @@ -18,3 +17,4 @@ py.install_sources( ) subdir('piv') +subdir('preproc') diff --git a/src/fluidimage/works/preproc.py b/src/fluidimage/works/preproc/__init__.py similarity index 94% rename from src/fluidimage/works/preproc.py rename to src/fluidimage/works/preproc/__init__.py index 4c2c4a7f..d474640e 100644 --- a/src/fluidimage/works/preproc.py +++ b/src/fluidimage/works/preproc/__init__.py @@ -5,6 +5,16 @@ Provides: +.. autosummary:: + :toctree: + + toolbox + _toolbox_cv + _toolbox_py + io + +Provides: + .. autoclass:: WorkPreproc :members: :private-members: @@ -24,8 +34,7 @@ get_ind_middle, ) from fluidimage.util import print_memory_usage - -from . import BaseWorkFromSerie +from fluidimage.works import BaseWorkFromSerie def _make_doc_with_filtered_params_doc(cls): @@ -40,11 +49,11 @@ def _make_doc_with_filtered_params_doc(cls): def _get_backend_class(backend): if backend == "python": - from fluidimage.preproc.toolbox import PreprocToolsPy + from fluidimage.works.preproc.toolbox import PreprocToolsPy return PreprocToolsPy elif backend == "opencv": - from fluidimage.preproc.toolbox import PreprocToolsCV + from fluidimage.works.preproc.toolbox import PreprocToolsCV return PreprocToolsCV diff --git a/src/fluidimage/preproc/_toolbox_cv.py b/src/fluidimage/works/preproc/_toolbox_cv.py similarity index 99% rename from src/fluidimage/preproc/_toolbox_cv.py rename to src/fluidimage/works/preproc/_toolbox_cv.py index 65406a56..d7fa7cd0 100644 --- a/src/fluidimage/preproc/_toolbox_cv.py +++ b/src/fluidimage/works/preproc/_toolbox_cv.py @@ -12,7 +12,8 @@ import numpy as np -from .._opencv import cv2 +from fluidimage._opencv import cv2 + from .io import iterate_multiple_imgs __all__ = [ diff --git a/src/fluidimage/preproc/_toolbox_py.py b/src/fluidimage/works/preproc/_toolbox_py.py similarity index 100% rename from src/fluidimage/preproc/_toolbox_py.py rename to src/fluidimage/works/preproc/_toolbox_py.py diff --git a/src/fluidimage/preproc/io.py b/src/fluidimage/works/preproc/io.py similarity index 100% rename from src/fluidimage/preproc/io.py rename to src/fluidimage/works/preproc/io.py diff --git a/src/fluidimage/preproc/meson.build b/src/fluidimage/works/preproc/meson.build similarity index 79% rename from src/fluidimage/preproc/meson.build rename to src/fluidimage/works/preproc/meson.build index 557923ca..d1861c78 100644 --- a/src/fluidimage/preproc/meson.build +++ b/src/fluidimage/works/preproc/meson.build @@ -9,5 +9,5 @@ python_sources = [ py.install_sources( python_sources, - subdir: 'fluidimage/preproc' + subdir: 'fluidimage/works/preproc' ) diff --git a/src/fluidimage/preproc/toolbox.py b/src/fluidimage/works/preproc/toolbox.py similarity index 99% rename from src/fluidimage/preproc/toolbox.py rename to src/fluidimage/works/preproc/toolbox.py index 946b6313..93c5e991 100644 --- a/src/fluidimage/preproc/toolbox.py +++ b/src/fluidimage/works/preproc/toolbox.py @@ -20,8 +20,7 @@ import inspect from fluidimage._opencv import error_import_cv2 - -from ..util import logger +from fluidimage.util import logger class PreprocToolsBase: