Example #1
0
    def test_minimal_piv(self):

        params = WorkPIV.create_default_params()

        # for a very short computation
        params.piv0.shape_crop_im0 = 32
        params.piv0.grid.overlap = -3

        # still buggy
        # params.piv0.nb_peaks_to_search = 2

        params.multipass.number = 2

        params.fix.displacement_max = 2
        params.fix.threshold_diff_neighbour = 2

        piv = WorkPIV(params=params)

        with stdout_redirected():
            result = piv.calcul(self.serie)

        result.piv0.save(self.path_tmp)
        result.save(self.path_tmp)

        path_file = next(self.path_tmp.iterdir())
        MultipassPIVResults(path_file)

        result.save(self.path_tmp, "uvmat")

        light = result.make_light_result()

        light.save(self.path_tmp)
        path_file = next(self.path_tmp.glob("*light*"))

        LightPIVResults(str_path=str(path_file))
Example #2
0
    def test_piv_list(self):

        params = WorkPIV.create_default_params()

        # for a very short computation
        params.piv0.shape_crop_im0 = [33, 44]
        params.piv0.grid.overlap = -3
        # params.piv0.nb_peaks_to_search = 2

        params.multipass.use_tps = False

        piv = WorkPIV(params=params)

        with stdout_redirected():
            result = piv.calcul(self.serie)

        piv0 = result.piv0
        im0, im1 = piv0.get_images()
        with stdout_redirected():
            DisplayPIV(im0, im1, piv0)
            d = DisplayPIV(im0, im1, piv0, show_interp=True, hist=True)

        d.switch()
        d.select_arrow([0], artist=d.q)
        d.select_arrow([0], artist=None)

        event = MyObj()

        event.key = "alt+h"
        event.inaxes = None
        d.onclick(event)

        event.inaxes = d.ax1

        event.key = "alt+s"
        d.onclick(event)
        event.key = "alt+left"
        d.onclick(event)
        event.key = "alt+right"
        d.onclick(event)

        event.artist = None
        d.onpick(event)

        event.artist = d.q
        event.ind = [0]
        d.onpick(event)
Example #3
0
 def calcul(self, tuple_image_path):
     """Compute a BOS field"""
     image, name = tuple_image_path
     array_couple = ArrayCoupleBOS(
         names=(self.name_reference, name),
         arrays=(self.image_reference, image),
         params_mask=self.params.mask,
         serie=self.serie,
         paths=[self.path_reference, self.path_dir_src / name],
     )
     return WorkPIV(self.params).calcul(array_couple)
Example #4
0
from fluidimage import SeriesOfArrays
from fluidimage.works.piv import WorkPIV

params = WorkPIV.create_default_params()

params.multipass.number = 2
params.multipass.use_tps = True

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:'

work = WorkPIV(params=params)

path = '../../image_samples/Oseen/Images'
# path = '../../image_samples/Karman/Images'
series = SeriesOfArrays(path, 'i+1:i+3')
serie = series.get_serie_from_index(0)

piv = work.calcul(serie)

# piv.display(show_interp=True, scale=0.3, show_error=True)
piv.display(show_interp=False, scale=1, show_error=True)

# result.save()
Example #5
0
import pstats
import cProfile

from fluidimage import SeriesOfArrays
from fluidimage.works.piv import WorkPIV

params = WorkPIV.create_default_params()

# for a very short computation
params.piv0.shape_crop_im0 = 32
params.piv0.grid.overlap = 0.5

# params.piv0.method_subpix = 'centroid'
# params.piv0.method_correl = 'theano'

params.multipass.number = 2
params.multipass.use_tps = 'last'
params.multipass.coeff_zoom = [2]

piv = WorkPIV(params=params)

series = SeriesOfArrays('../../image_samples/Oseen/Images', 'i+1:i+3')
serie = series.get_serie_from_index(0)

cProfile.runctx('result = piv.calcul(serie)', globals(), locals(),
                'profile.pstats')

s = pstats.Stats('profile.pstats')
s.strip_dirs().sort_stats('time').print_stats(10)

print('with gprof2dot and graphviz (command dot):\n'
Example #6
0
    def create_default_params(cls):
        """Class method returning the default parameters.

        Typical usage::

          params = TopologyPIV.create_default_params()
          # modify parameters here
          ...

          topo = TopologyPIV(params)

        """
        params = ParamContainer(tag="params")

        params._set_child(
            "series",
            attribs={
                "path": "",
                "strcouple": "i:i+2",
                "ind_start": 0,
                "ind_stop": None,
                "ind_step": 1,
            },
        )

        params.series._set_doc("""
Parameters indicating the input series of images.

path : str, {''}

    String indicating the input images (can be a full path towards an image
    file or a string given to `glob`).

strcouple : 'i:i+2'

    String indicating as a Python slicing how couples of images are formed.
    There is one couple per value of `i`. The values of `i` are set with the
    other parameters `ind_start`, `ind_step` and `ind_stop` approximately with
    the function range (`range(ind_start, ind_stop, ind_step)`).

    Python slicing is a very powerful notation to define subset from a
    (possibly multidimensional) set of images. For a user, an alternative is to
    understand how Python slicing works. See for example this page:
    http://stackoverflow.com/questions/509211/explain-pythons-slice-notation.

    Another possibility is to follow simple examples:

    For single-frame images (im0, im1, im2, im3, ...), we keep the default
    value 'i:i+2' to form the couples (im0, im1), (im1, im2), ...

    To see what it gives, one can use IPython and range:

    >>> i = 0
    >>> list(range(10))[i:i+2]
    [0, 1]

    >>> list(range(10))[i:i+4:2]
    [0, 2]

    We see that we can also use the value 'i:i+4:2' to form the couples (im0,
    im2), (im1, im3), ...

    For double-frame images (im1a, im1b, im2a, im2b, ...) you can write

    >>> params.series.strcouple = 'i, 0:2'

    In this case, the first couple will be (im1a, im1b).

    To get the first couple (im1a, im1a), we would have to write

    >>> params.series.strcouple = 'i:i+2, 0'

ind_start : int, {0}

ind_step : int, {1}

int_stop : None

""")

        params._set_child("saving",
                          attribs={
                              "path": None,
                              "how": "ask",
                              "postfix": "piv"
                          })

        params.saving._set_doc("""Saving of the results.

path : None or str

    Path of the directory where the data will be saved. If None, the path is
    obtained from the input path and the parameter `postfix`.

how : str {'ask'}

    'ask', 'new_dir', 'complete' or 'recompute'.

postfix : str

    Postfix from which the output file is computed.
""")

        WorkPIV._complete_params_with_default(params)

        params._set_internal_attr(
            "_value_text",
            json.dumps({
                "program": "fluidimage",
                "module": "fluidimage.topologies.piv",
                "class": "TopologyPIV",
            }),
        )

        params._set_child("preproc")
        image2image.complete_im2im_params_with_default(params.preproc)

        return params
Example #7
0
    def __init__(self, params, logging_level="info", nb_max_workers=None):

        self.params = params

        self.series = SeriesOfArrays(
            params.series.path,
            params.series.strcouple,
            ind_start=params.series.ind_start,
            ind_stop=params.series.ind_stop,
            ind_step=params.series.ind_step,
        )

        path_dir = self.series.serie.path_dir
        path_dir_result, self.how_saving = prepare_path_dir_result(
            path_dir, params.saving.path, params.saving.postfix,
            params.saving.how)

        super().__init__(
            path_dir_result=path_dir_result,
            logging_level=logging_level,
            nb_max_workers=nb_max_workers,
        )

        queue_couples_of_names = self.add_queue("couples of names")
        queue_paths = self.add_queue("paths")
        queue_arrays = queue_arrays1 = self.add_queue("arrays")
        queue_couples_of_arrays = self.add_queue("couples of arrays")
        queue_piv = self.add_queue("piv")

        if params.preproc.im2im is not None:
            queue_arrays1 = self.add_queue("arrays1")

        self.add_work(
            "fill (couples of names, paths)",
            func_or_cls=self.fill_couples_of_names_and_paths,
            output_queue=(queue_couples_of_names, queue_paths),
            kind=("global", "one shot"),
        )
        self.add_work(
            "read array",
            func_or_cls=imread,
            input_queue=queue_paths,
            output_queue=queue_arrays,
            kind="io",
        )

        if params.preproc.im2im is not None:
            im2im_func = image2image.TopologyImage2Image.init_im2im(
                self, params.preproc)

            self.add_work(
                "image2image",
                func_or_cls=im2im_func,
                input_queue=queue_arrays,
                output_queue=queue_arrays1,
            )

        self.add_work(
            "make couples of arrays",
            func_or_cls=self.make_couples,
            params_cls=None,
            input_queue=(queue_couples_of_names, queue_arrays),
            output_queue=queue_couples_of_arrays,
            kind="global",
        )

        self.work_piv = WorkPIV(self.params)

        self.add_work(
            "compute piv",
            func_or_cls=self.work_piv.calcul,
            params_cls=params,
            input_queue=queue_couples_of_arrays,
            output_queue=queue_piv,
        )

        self.add_work(
            "save piv",
            func_or_cls=self.save_piv_object,
            input_queue=queue_piv,
            kind="io",
        )
        self.results = []
Example #8
0
from fluidimage.works.piv import WorkPIV

import params_piv

try:
    reload
except NameError:
    from importlib import reload

reload(params_piv)

iexp = 0

params = params_piv.make_params_piv(iexp)

work = WorkPIV(params=params)

pathin = params.series.path

series = SeriesOfArrays(pathin,
                        params.series.strcouple,
                        ind_start=params.series.ind_start)

# c060a.png and c060b.png
serie = series.get_serie_from_index(params.series.ind_start)

piv = work.calcul(serie)

# piv.piv0.display(show_interp=True, scale=0.05, show_error=True)

piv.display(show_interp=False, scale=0.05, show_error=True)
Example #9
0
class TopologyPIV(TopologyBase):
    """Topology for PIV.

    Parameters
    ----------

    params : None

      A ParamContainer containing the parameters for the computation.

    logging_level : str, {'warning', 'info', 'debug', ...}

      Logging level.

    nb_max_workers : None, int

      Maximum numbers of "workers". If None, a number is computed from the
      number of cores detected. If there are memory errors, you can try to
      decrease the number of workers.

    """
    @classmethod
    def create_default_params(cls):
        """Class method returning the default parameters.

        For developers: cf. fluidsim.base.params

        """
        params = ParamContainer(tag="params")

        params._set_child(
            "series",
            attribs={
                "path": "",
                "strcouple": "i:i+2",
                "ind_start": 0,
                "ind_stop": None,
                "ind_step": 1,
            },
        )

        params.series._set_doc("""
Parameters indicating the input series of images.

path : str, {''}

    String indicating the input images (can be a full path towards an image
    file or a string given to `glob`).

strcouple : 'i:i+2'

    String indicating as a Python slicing how couples of images are formed.
    There is one couple per value of `i`. The values of `i` are set with the
    other parameters `ind_start`, `ind_step` and `ind_stop` approximately with
    the function range (`range(ind_start, ind_stop, ind_step)`).

    Python slicing is a very powerful notation to define subset from a
    (possibly multidimensional) set of images. For a user, an alternative is to
    understand how Python slicing works. See for example this page:
    http://stackoverflow.com/questions/509211/explain-pythons-slice-notation.

    Another possibility is to follow simple examples:

    For single-frame images (im0, im1, im2, im3, ...), we keep the default
    value 'i:i+2' to form the couples (im0, im1), (im1, im2), ...

    To see what it gives, one can use ipython and range:

    >>> i = 0
    >>> list(range(10))[i:i+2]
    [0, 1]

    >>> list(range(10))[i:i+4:2]
    [0, 2]

    We see that we can also use the value 'i:i+4:2' to form the couples (im0,
    im2), (im1, im3), ...

    For double-frame images (im1a, im1b, im2a, im2b, ...) you can write

    >>> params.series.strcouple = 'i, 0:2'

    In this case, the first couple will be (im1a, im1b).

    To get the first couple (im1a, im1a), we would have to write

    >>> params.series.strcouple = 'i:i+2, 0'

ind_start : int, {0}

ind_step : int, {1}

int_stop : None

""")

        params._set_child("saving",
                          attribs={
                              "path": None,
                              "how": "ask",
                              "postfix": "piv"
                          })

        params.saving._set_doc("""Saving of the results.

path : None or str

    Path of the directory where the data will be saved. If None, the path is
    obtained from the input path and the parameter `postfix`.

how : str {'ask'}

    'ask', 'new_dir', 'complete' or 'recompute'.

postfix : str

    Postfix from which the output file is computed.
""")

        WorkPIV._complete_params_with_default(params)

        params._set_internal_attr(
            "_value_text",
            json.dumps({
                "program": "fluidimage",
                "module": "fluidimage.topologies.piv",
                "class": "TopologyPIV",
            }),
        )

        params._set_child("preproc")
        image2image.complete_im2im_params_with_default(params.preproc)

        return params

    def __init__(self, params=None, logging_level="info", nb_max_workers=None):

        if params is None:
            params = self.__class__.create_default_params()

        self.params = params
        self.piv_work = WorkPIV(params)

        serie_arrays = SerieOfArraysFromFiles(params.series.path)

        self.series = SeriesOfArrays(
            serie_arrays,
            params.series.strcouple,
            ind_start=params.series.ind_start,
            ind_stop=params.series.ind_stop,
            ind_step=params.series.ind_step,
        )

        path_dir = self.series.serie.path_dir
        path_dir_result, self.how_saving = prepare_path_dir_result(
            path_dir, params.saving.path, params.saving.postfix,
            params.saving.how)

        self.path_dir_result = path_dir_result

        self.results = {}

        def save_piv_object(o):
            ret = o.save(path_dir_result)
            return ret

        self.wq_piv = WaitingQueueThreading("delta",
                                            save_piv_object,
                                            self.results,
                                            topology=self)
        self.wq_couples = WaitingQueueMultiprocessing("couple",
                                                      self.piv_work.calcul,
                                                      self.wq_piv,
                                                      topology=self)

        self.wq_images = WaitingQueueMakeCouple("array image",
                                                self.wq_couples,
                                                topology=self)

        if params.preproc.im2im is not None:
            self.im2im_func = image2image.TopologyImage2Image.init_im2im(
                self, params.preproc)

            self.wq_images0 = WaitingQueueMultiprocessing("image ",
                                                          self.im2im_func,
                                                          self.wq_images,
                                                          topology=self)
            wq_after_load = self.wq_images0
        else:
            wq_after_load = self.wq_images

        self.wq0 = WaitingQueueLoadImage(destination=wq_after_load,
                                         path_dir=path_dir,
                                         topology=self)

        if params.preproc.im2im is not None:
            waiting_queues = [
                self.wq0,
                self.wq_images0,
                self.wq_images,
                self.wq_couples,
                self.wq_piv,
            ]
        else:
            waiting_queues = [
                self.wq0,
                self.wq_images,
                self.wq_couples,
                self.wq_piv,
            ]

        super().__init__(
            waiting_queues,
            path_output=path_dir_result,
            logging_level=logging_level,
            nb_max_workers=nb_max_workers,
        )

        self.add_series(self.series)

    def add_series(self, series):

        if len(series) == 0:
            logger.warning("add 0 couple. No PIV to compute.")
            return

        if self.how_saving == "complete":
            names = []
            index_series = []
            for i, serie in enumerate(series):
                name_piv = get_name_piv(serie, prefix="piv")
                if os.path.exists(os.path.join(self.path_dir_result,
                                               name_piv)):
                    continue

                for name in serie.get_name_arrays():
                    if name not in names:
                        names.append(name)

                index_series.append(i * series.ind_step + series.ind_start)

            if len(index_series) == 0:
                logger.warning(
                    'topology in mode "complete" and work already done.')
                return

            series.set_index_series(index_series)

            logger.debug(repr(names))
            logger.debug(repr([serie.get_name_arrays() for serie in series]))
        else:
            names = series.get_name_all_arrays()

        nb_series = len(series)
        print("Add {} PIV fields to compute.".format(nb_series))

        for i, serie in enumerate(series):
            if i > 1:
                break

            print("Files of serie {}: {}".format(i, serie.get_name_arrays()))

        self.wq0.add_name_files(names)
        self.wq_images.add_series(series)

        k, o = self.wq0.popitem()
        im = self.wq0.work(o)
        self.wq0.fill_destination(k, im)

        # a little bit strange, to apply mask...
        try:
            params_mask = self.params.mask
        except AttributeError:
            params_mask = None

        couple = ArrayCouple(names=("", ""),
                             arrays=(im, im),
                             params_mask=params_mask)
        im, _ = couple.get_arrays()

        self.piv_work._prepare_with_image(im)

    def print_at_exit(self, time_since_start):

        txt = "Stop compute after t = {:.2f} s".format(time_since_start)
        try:
            nb_results = len(self.results)
        except AttributeError:
            nb_results = None
        if nb_results is not None and nb_results > 0:
            txt += " ({} piv fields, {:.2f} s/field).".format(
                nb_results, time_since_start / nb_results)
        else:
            txt += "."

        txt += "\npath results:\n" + str(self.path_dir_result)

        print(txt)
Example #10
0
    def __init__(self, params=None, logging_level="info", nb_max_workers=None):

        if params is None:
            params = self.__class__.create_default_params()

        self.params = params
        self.piv_work = WorkPIV(params)

        serie_arrays = SerieOfArraysFromFiles(params.series.path)

        self.series = SeriesOfArrays(
            serie_arrays,
            params.series.strcouple,
            ind_start=params.series.ind_start,
            ind_stop=params.series.ind_stop,
            ind_step=params.series.ind_step,
        )

        path_dir = self.series.serie.path_dir
        path_dir_result, self.how_saving = prepare_path_dir_result(
            path_dir, params.saving.path, params.saving.postfix,
            params.saving.how)

        self.path_dir_result = path_dir_result

        self.results = {}

        def save_piv_object(o):
            ret = o.save(path_dir_result)
            return ret

        self.wq_piv = WaitingQueueThreading("delta",
                                            save_piv_object,
                                            self.results,
                                            topology=self)
        self.wq_couples = WaitingQueueMultiprocessing("couple",
                                                      self.piv_work.calcul,
                                                      self.wq_piv,
                                                      topology=self)

        self.wq_images = WaitingQueueMakeCouple("array image",
                                                self.wq_couples,
                                                topology=self)

        if params.preproc.im2im is not None:
            self.im2im_func = image2image.TopologyImage2Image.init_im2im(
                self, params.preproc)

            self.wq_images0 = WaitingQueueMultiprocessing("image ",
                                                          self.im2im_func,
                                                          self.wq_images,
                                                          topology=self)
            wq_after_load = self.wq_images0
        else:
            wq_after_load = self.wq_images

        self.wq0 = WaitingQueueLoadImage(destination=wq_after_load,
                                         path_dir=path_dir,
                                         topology=self)

        if params.preproc.im2im is not None:
            waiting_queues = [
                self.wq0,
                self.wq_images0,
                self.wq_images,
                self.wq_couples,
                self.wq_piv,
            ]
        else:
            waiting_queues = [
                self.wq0,
                self.wq_images,
                self.wq_couples,
                self.wq_piv,
            ]

        super().__init__(
            waiting_queues,
            path_output=path_dir_result,
            logging_level=logging_level,
            nb_max_workers=nb_max_workers,
        )

        self.add_series(self.series)
Example #11
0
# import h5py

from fluidimage import SeriesOfArrays
from fluidimage.works.piv import WorkPIV
from fluidimage.data_objects.piv import LightPIVResults


params = WorkPIV.create_default_params()

# # for a very short computation
# params.piv0.shape_crop_im0 = 128
# params.piv0.grid.overlap = 0.

# params.piv0.method_subpix = 'centroid'
# params.piv0.method_correl = 'pythran'

params.multipass.number = 1
params.multipass.use_tps = False
# params.multipass.coeff_zoom = [2, 2]

# bug params.piv0.shape_crop_im0 = 128  # !!
params.piv0.shape_crop_im0 = 64  # (80, 90)
# params.piv0.shape_crop_im1 = (38, 36)
params.fix.correl_min = 0.2
params.fix.threshold_diff_neighbour = 4
# params.piv0.grid.overlap = 10

piv = WorkPIV(params=params)

series = SeriesOfArrays("../../../image_samples/Oseen/Images", "i+1:i+3")
serie = series.get_serie_from_index(0)
Example #12
0
    def create_default_params(cls):
        """Class method returning the default parameters.

        Typical usage::

          params = TopologyPIV.create_default_params()
          # modify parameters here
          ...

          topo = TopologyPIV(params)

        """
        params = ParamContainer(tag="params")

        params._set_child("images", attribs={"path": "", "str_slice": None})

        params.images._set_doc(
            """
Parameters indicating the input image set.

path : str, {''}

    String indicating the input images (can be a full path towards an image
    file or a string given to `glob`).

str_slice : None

    String indicating as a Python slicing how to select images from the serie of
    images on the disk. If None, no selection so all images are going to be
    processed.

"""
        )

        params._set_attrib("reference", 0)

        params._set_doc(
            """
reference : str or int, {0}

    Reference file (from which the displacements will be computed). Can be an
    absolute file path, a file name or the index in the list of files found
    from the parameters in ``params.images``.

"""
        )

        params._set_child(
            "saving", attribs={"path": None, "how": "ask", "postfix": "bos"}
        )

        params.saving._set_doc(
            """Saving of the results.

path : None or str

    Path of the directory where the data will be saved. If None, the path is
    obtained from the input path and the parameter `postfix`.

how : str {'ask'}

    'ask', 'new_dir', 'complete' or 'recompute'.

postfix : str

    Postfix from which the output file is computed.
"""
        )

        WorkPIV._complete_params_with_default(params)

        params._set_internal_attr(
            "_value_text",
            json.dumps(
                {
                    "program": "fluidimage",
                    "module": "fluidimage.topologies.bos",
                    "class": "TopologyBOS",
                }
            ),
        )

        params._set_child("preproc")
        image2image.complete_im2im_params_with_default(params.preproc)

        return params