Skip to content

Commit

Permalink
Merge branch 'topic/default/better-run_from_xml' into 'branch/default'
Browse files Browse the repository at this point in the history
Fix and test run_from_xml

See merge request fluiddyn/fluidimage!73
  • Loading branch information
paugier committed Mar 5, 2024
2 parents 1dfed25 + cad2266 commit f735490
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 80 deletions.
157 changes: 92 additions & 65 deletions src/fluidimage/run_from_xml.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import argparse
import os
from abc import ABC, abstractmethod
from time import time

import numpy as np
Expand Down Expand Up @@ -80,55 +81,67 @@ def tidy_uvmat_instructions(params):
params._set_attrib("ind_start", ind_start)


class ActionBase:
def __init__(self, instructions, args):
self.instructions = instructions

# create the serie of arrays
logger.info("Create the serie of arrays")
self.serie_arrays = SerieOfArraysFromFiles(
path=instructions.path_dir_input,
slicing_tuples=instructions.slicing_tuples,
)

class ActionBase(ABC):

class ActionAverage(ActionBase):
"""Compute the average and save as a png file."""
@abstractmethod
def __init__(self, instructions, args):
"""Initialize the action class"""

@abstractmethod
def compute(self):
instructions = self.instructions
serie = self.serie_arrays
# compute the average
logger.info("Compute the average")
a = serie.get_array_from_index(0)
mean = np.zeros_like(a, dtype=np.float32)
nb_fields = 0
for a in serie.iter_arrays():
mean += a
nb_fields += 1
mean /= nb_fields

strindices_first_file = serie.compute_strindices_from_indices(
*[indices[0] for indices in instructions.slicing_tuples]
)
strindices_last_file = serie.compute_strindices_from_indices(
*[indices[1] - 1 for indices in instructions.slicing_tuples]
)

name_file = (
serie.base_name
+ serie.get_separator_base_index()
+ strindices_first_file
+ "-"
+ strindices_last_file
+ "."
+ serie.extension_file
)

path_save = os.path.join(instructions.path_dir_output, name_file)
logger.info("Save in file:\n%s", path_save)
scipy.misc.imsave(path_save, mean)
return mean
"""Perform the computation"""


# class ActionAverage(ActionBase):
# """Compute the average and save as a png file."""

# def __init__(self, instructions, args):
# self.instructions = instructions

# # create the serie of arrays
# logger.info("Create the serie of arrays")
# self.serie_arrays = SerieOfArraysFromFiles(
# path=instructions.path_dir_input,
# slicing=instructions.slicing,
# )

# def compute(self):
# instructions = self.instructions
# serie = self.serie_arrays

# slicing_tuples = serie.get_slicing_tuples()

# # create output name
# strindices_first_file = serie.compute_str_indices_from_indices(
# *[indices[0] for indices in slicing_tuples]
# )
# strindices_last_file = serie.compute_str_indices_from_indices(
# *[indices[1] - 1 for indices in slicing_tuples]
# )
# name_file = (
# serie.base_name
# + serie.get_separator_base_index()
# + strindices_first_file
# + "-"
# + strindices_last_file
# + "."
# + serie.extension_file
# )
# path_save = os.path.join(instructions.path_dir_output, name_file)

# # compute the average
# logger.info("Compute the average")
# a = serie.get_array_from_index(0)
# mean = np.zeros_like(a, dtype=np.float32)
# nb_fields = 0
# for a in serie.iter_arrays():
# mean += a
# nb_fields += 1
# mean /= nb_fields

# logger.info("Save in file:\n%s", path_save)
# scipy.misc.imsave(path_save, mean)
# return mean


def params_piv_from_uvmat_xml(instructions, args):
Expand Down Expand Up @@ -163,24 +176,25 @@ def params_piv_from_uvmat_xml(instructions, args):
return params


class ActionPIV(ActionBase):
class ActionPIVFromUvmatXML(ActionBase):
"""Compute the average and save as a png file."""

def __init__(self, instructions, args):
self.instructions = instructions
self.params = params_piv_from_uvmat_xml(instructions, args)
logger.info("Initialize fluidimage computations with parameters:")
logger.info("Initialize Fluidimage computations with parameters:")
logger.info(self.params._make_xml_text())
self.topology = TopologyPIV(self.params)

def compute(self):
t = time()
self.topology.compute(sequential=False)
self.topology.compute()
t = time() - t
print(f"ellapsed time: {t}s")
print(f"elapsed time: {t} s")


actions_classes = {"aver_stat": ActionAverage, "civ_series": ActionPIV}
# actions_classes = {"aver_stat": ActionAverage, "civ_series": ActionPIVFromUvmatXML}
actions_classes = {"civ_series": ActionPIVFromUvmatXML}

programs = ["uvmat", "fluidimage"]

Expand Down Expand Up @@ -215,33 +229,29 @@ def main():
args = parse_args()

path_instructions_xml = args.path
logger.info(
"\nFrom Python, start with instructions in xml file:\n%s",
path_instructions_xml,
)

params = ParamContainer(path_file=path_instructions_xml)

program = None

try:
params.Action.ActionName
except AttributeError:
pass
try:
program = params._value_text["program"]
except (AttributeError, KeyError):
pass
else:
program = "uvmat"

try:
program = params._value_text["program"]
except (AttributeError, KeyError):
pass

if program not in programs:
raise ValueError("Can not detect the program to launch.")

print(args)
logger.info(
"\nUsing instructions in xml file:\n%s",
path_instructions_xml,
)

print(f"using input file from {program}")
kwargs_compute = {}

if program == "uvmat":
tidy_uvmat_instructions(params)
Expand All @@ -264,7 +274,24 @@ def main():
modif_fluidimage_params(params, args)
action = cls(params)

return action.compute()
try:
compute_args = params.compute_args
except AttributeError:
pass
else:
for key in (
"executor",
"nb_max_workers",
"sleep_time",
"sequential",
"stop_if_error",
):
try:
kwargs_compute[key] = compute_args[key]
except (KeyError, AttributeError):
pass

return action.compute(**kwargs_compute)


if __name__ == "__main__":
Expand Down
57 changes: 42 additions & 15 deletions src/fluidimage/test_run_from_xml.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,56 @@
import os
import shutil
import sys
import unittest

from fluidimage import get_path_image_samples
from fluidimage.piv import TopologyPIV
from fluidimage.run_from_xml import main

path_image_samples = get_path_image_samples()

on_linux = sys.platform == "linux"

@unittest.skipIf(sys.platform != "linux", "Only supported on Linux")
def test_main(monkeypatch):

class TestRunFromXML(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.current_dir = os.getcwd()
os.chdir(path_image_samples)
monkeypatch.chdir(path_image_samples)

@classmethod
def tearDownClass(cls):
os.chdir(cls.current_dir)
path = path_image_samples / "Karman/Images.civ/0_XML/Karman_1-4.xml"
command = f"run {path} --mode recompute"

@unittest.skipIf(not on_linux, "Only supported on Linux")
def test_main(self):
path = path_image_samples / "Karman/Images.civ/0_XML/Karman_1-4.xml"
command = f"run {str(path)} --mode recompute"
sys.argv = command.split()
with monkeypatch.context() as ctx:
ctx.setattr(sys, "argv", command.split())
main()


def test_piv_sequential(tmp_path, monkeypatch):

path_dir_images = tmp_path / "Images"
path_dir_images.mkdir()

for path_im in (path_image_samples / "Jet/Images").glob("*"):
shutil.copy(path_im, path_dir_images)

params = TopologyPIV.create_default_params()

params.series.path = str(path_dir_images)

params.piv0.shape_crop_im0 = 128
params.multipass.number = 2
params.multipass.use_tps = False

params.saving.how = "recompute"
params.saving.postfix = "test_piv_run_from_xml"

params._set_child(
"compute_args",
attribs={"executor": "exec_async_sequential", "nb_max_workers": 1},
)

path_params = path_dir_images.parent / "params.xml"

params._save_as_xml(path_file=path_params)
assert path_params.exists()

with monkeypatch.context() as ctx:
ctx.setattr(sys, "argv", ["run", str(path_params)])
main()

0 comments on commit f735490

Please sign in to comment.