From 026a1c6426071eae6658712e595d6f8c292fc98f Mon Sep 17 00:00:00 2001 From: Fabien Casenave Date: Fri, 8 Aug 2025 09:38:51 +0200 Subject: [PATCH 1/5] feat(sample.py) add option to overwrite folder in save --- src/plaid/containers/sample.py | 14 ++++++++++---- tests/containers/test_sample.py | 1 + 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/plaid/containers/sample.py b/src/plaid/containers/sample.py index f828bf83..a43572cf 100644 --- a/src/plaid/containers/sample.py +++ b/src/plaid/containers/sample.py @@ -21,6 +21,7 @@ import glob import logging import os +import shutil from typing import Optional, Union import CGNS.MAP as CGM @@ -1792,17 +1793,22 @@ def get_feature_from_identifier( return self.get_nodes(**feature_identifier_) # -------------------------------------------------------------------------# - def save(self, dir_path: str) -> None: + def save(self, dir_path: str, overwrite: Optional[bool] = None) -> None: """Save the Sample in directory `dir_path`. Args: dir_path (str): relative or absolute directory path. + overwrite (str, optional): target directory overwritten if True. """ - if os.path.isdir(dir_path): - if len(glob.glob(os.path.join(dir_path, "*"))): + if os.path.exists(dir_path) and os.path.isdir(dir_path): + if len(glob.glob(os.path.join(dir_path, "*"))) and not overwrite: raise ValueError( - f"directory {dir_path} already exists and is not empty" + f"directory {dir_path} already exists and is not empty. Set `overwrite` to True if needed." ) + else: + shutil.rmtree(dir_path) + logger.warning(f"{dir_path} directory has been overwritten.") + else: os.makedirs(dir_path) diff --git a/tests/containers/test_sample.py b/tests/containers/test_sample.py index f9b76f67..8b92969c 100644 --- a/tests/containers/test_sample.py +++ b/tests/containers/test_sample.py @@ -1007,6 +1007,7 @@ def test_save(self, sample_with_tree_and_scalar_and_time_series, tmp_path): assert save_dir.is_dir() with pytest.raises(ValueError): sample_with_tree_and_scalar_and_time_series.save(save_dir) + sample_with_tree_and_scalar_and_time_series.save(save_dir, overwrite=True) def test_load_from_saved_file( self, sample_with_tree_and_scalar_and_time_series, tmp_path From e184dffc159a7a3f18609f417fcfd33369d7634e Mon Sep 17 00:00:00 2001 From: Fabien Casenave Date: Fri, 8 Aug 2025 09:49:31 +0200 Subject: [PATCH 2/5] feat(sample.py) add option to overwrite folder in save --- src/plaid/containers/sample.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/plaid/containers/sample.py b/src/plaid/containers/sample.py index a43572cf..287701dc 100644 --- a/src/plaid/containers/sample.py +++ b/src/plaid/containers/sample.py @@ -1793,7 +1793,7 @@ def get_feature_from_identifier( return self.get_nodes(**feature_identifier_) # -------------------------------------------------------------------------# - def save(self, dir_path: str, overwrite: Optional[bool] = None) -> None: + def save(self, dir_path: str, overwrite: Optional[bool] = False) -> None: """Save the Sample in directory `dir_path`. Args: @@ -1801,16 +1801,15 @@ def save(self, dir_path: str, overwrite: Optional[bool] = None) -> None: overwrite (str, optional): target directory overwritten if True. """ if os.path.exists(dir_path) and os.path.isdir(dir_path): - if len(glob.glob(os.path.join(dir_path, "*"))) and not overwrite: + if overwrite: + shutil.rmtree(dir_path) + logger.warning(f"Existing {dir_path} directory has been reset.") + elif len(glob.glob(os.path.join(dir_path, "*"))): raise ValueError( f"directory {dir_path} already exists and is not empty. Set `overwrite` to True if needed." ) - else: - shutil.rmtree(dir_path) - logger.warning(f"{dir_path} directory has been overwritten.") - else: - os.makedirs(dir_path) + os.makedirs(dir_path, exist_ok=True) mesh_dir = os.path.join(dir_path, "meshes") From 42e8a02d03f5b6f759e53241aa7fd4af1f0a02d2 Mon Sep 17 00:00:00 2001 From: Xavier Roynard Date: Tue, 12 Aug 2025 15:14:15 +0200 Subject: [PATCH 3/5] (path) replace all uses of os by pathlib --- src/plaid/containers/dataset.py | 2 +- src/plaid/containers/sample.py | 91 +++++++++++++++++--------------- src/plaid/post/bisect.py | 19 +++---- src/plaid/post/metrics.py | 19 +++---- src/plaid/problem_definition.py | 37 ++++++------- tests/containers/test_sample.py | 26 +++------ tests/post/test_bisect.py | 64 ++++++++++------------ tests/post/test_metrics.py | 56 +++++++++----------- tests/test_problem_definition.py | 26 ++++----- 9 files changed, 164 insertions(+), 176 deletions(-) diff --git a/src/plaid/containers/dataset.py b/src/plaid/containers/dataset.py index 55037fa8..db0f14d9 100644 --- a/src/plaid/containers/dataset.py +++ b/src/plaid/containers/dataset.py @@ -952,7 +952,7 @@ def update(self, *a): """ infos_fname = savedir / "infos.yaml" - if os.path.isfile(infos_fname): + if infos_fname.is_file(): with open(infos_fname, "r") as file: self._infos = yaml.safe_load(file) diff --git a/src/plaid/containers/sample.py b/src/plaid/containers/sample.py index 287701dc..cb515763 100644 --- a/src/plaid/containers/sample.py +++ b/src/plaid/containers/sample.py @@ -18,10 +18,9 @@ Self = TypeVar("Self") import copy -import glob import logging -import os import shutil +from pathlib import Path from typing import Optional, Union import CGNS.MAP as CGM @@ -137,7 +136,7 @@ class Sample(BaseModel): def __init__( self, - directory_path: str = None, + directory_path: Union[str, Path] = None, mesh_base_name: str = "Base", mesh_zone_name: str = "Zone", meshes: dict[float, CGNSTree] = None, @@ -149,7 +148,7 @@ def __init__( """Initialize an empty :class:`Sample `. Args: - directory_path (str, optional): The path from which to load PLAID sample files. + directory_path (Union[str, Path], optional): The path from which to load PLAID sample files. mesh_base_name (str, optional): The base name for the mesh. Defaults to 'Base'. mesh_zone_name (str, optional): The zone name for the mesh. Defaults to 'Zone'. meshes (dict[float, CGNSTree], optional): A dictionary mapping time steps to CGNSTrees. Defaults to None. @@ -189,7 +188,8 @@ def __init__( self._paths: dict[float, list[PathType]] = paths if directory_path is not None: - self.load(str(directory_path)) + directory_path = Path(directory_path) + self.load(directory_path) self._defaults: dict = { "active_base": None, @@ -504,9 +504,7 @@ def get_mesh( tree = copy.deepcopy(tree) for link in links: if not in_memory: - subtree, _, _ = CGM.load( - os.path.join(link[0], link[1]), subtree=link[2] - ) + subtree, _, _ = CGM.load(str(Path(link[0]) / link[1]), subtree=link[2]) else: linked_timestep = int(link[1].split(".cgns")[0].split("_")[1]) linked_timestamp = list(self._meshes.keys())[linked_timestep] @@ -636,7 +634,7 @@ def del_tree(self, time: float) -> CGNSTree: def link_tree( self, - path_linked_sample: str, + path_linked_sample: Union[str, Path], linked_sample: Self, linked_time: float, time: float, @@ -644,7 +642,7 @@ def link_tree( """Link the geometrical features of the CGNS tree of the current sample at a given time, to the ones of another sample. Args: - path_linked_sample (str): The absolute path of the folder containing the linked CGNS + path_linked_sample (Union[str, Path]): The absolute path of the folder containing the linked CGNS linked_sample (Sample): The linked sample linked_time (float): The time step of the linked CGNS in the linked sample time (float): The time step the current sample to which the CGNS tree is linked. @@ -658,6 +656,8 @@ def link_tree( # https://pycgns.github.io/MAP/examples.html#save-with-links # When you load a file all the linked-to files are resolved to produce a full CGNS/Python tree with actual node data. + path_linked_sample = Path(path_linked_sample) + if linked_time not in linked_sample._meshes: # pragma: no cover raise KeyError( f"There is no CGNS tree for time {linked_time} in linked_sample." @@ -723,7 +723,7 @@ def link_tree( ] grid[2].append(zone_family) - def find_feature_roots(sample, time, Type_t): + def find_feature_roots(sample: Sample, time: float, Type_t: str): Types_t = CGU.getAllNodesByTypeSet(sample.get_mesh(time), Type_t) # in case the type is not present in the tree if Types_t == []: # pragma: no cover @@ -741,9 +741,9 @@ def find_feature_roots(sample, time, Type_t): self.add_tree(tree, time=time) - dname = os.path.dirname(path_linked_sample) - bname = os.path.basename(path_linked_sample) - self._links[time] = [[dname, bname, fp, fp] for fp in feature_paths] + dname = path_linked_sample.parent + bname = path_linked_sample.name + self._links[time] = [[str(dname), bname, fp, fp] for fp in feature_paths] return tree @@ -1793,31 +1793,35 @@ def get_feature_from_identifier( return self.get_nodes(**feature_identifier_) # -------------------------------------------------------------------------# - def save(self, dir_path: str, overwrite: Optional[bool] = False) -> None: + def save(self, dir_path: Union[str, Path], overwrite: bool = False) -> None: """Save the Sample in directory `dir_path`. Args: - dir_path (str): relative or absolute directory path. - overwrite (str, optional): target directory overwritten if True. + dir_path (Union[str,Path]): relative or absolute directory path. + overwrite (bool): target directory overwritten if True. """ - if os.path.exists(dir_path) and os.path.isdir(dir_path): + dir_path = Path(dir_path) + + if dir_path.is_dir(): if overwrite: shutil.rmtree(dir_path) logger.warning(f"Existing {dir_path} directory has been reset.") - elif len(glob.glob(os.path.join(dir_path, "*"))): + elif len(list(dir_path.glob("*"))): raise ValueError( f"directory {dir_path} already exists and is not empty. Set `overwrite` to True if needed." ) - os.makedirs(dir_path, exist_ok=True) + dir_path.mkdir(exist_ok=True) - mesh_dir = os.path.join(dir_path, "meshes") + mesh_dir = dir_path / "meshes" if self._meshes is not None: - os.makedirs(mesh_dir) + mesh_dir.mkdir() for i, time in enumerate(self._meshes.keys()): - outfname = os.path.join(mesh_dir, f"mesh_{i:09d}.cgns") - status = CGM.save(outfname, self._meshes[time], links=self._links[time]) + outfname = mesh_dir / f"mesh_{i:09d}.cgns" + status = CGM.save( + str(outfname), self._meshes[time], links=self._links[time] + ) logger.debug(f"save -> {status=}") scalars_names = self.get_scalar_names() @@ -1828,7 +1832,7 @@ def save(self, dir_path: str, overwrite: Optional[bool] = False) -> None: scalars = np.array(scalars).reshape((1, -1)) header = ",".join(scalars_names) np.savetxt( - os.path.join(dir_path, "scalars.csv"), + dir_path / "scalars.csv", scalars, header=header, delimiter=",", @@ -1842,7 +1846,7 @@ def save(self, dir_path: str, overwrite: Optional[bool] = False) -> None: data = np.vstack((ts[0], ts[1])).T header = ",".join(["t", ts_name]) np.savetxt( - os.path.join(dir_path, f"time_series_{ts_name}.csv"), + dir_path / f"time_series_{ts_name}.csv", data, header=header, delimiter=",", @@ -1850,13 +1854,13 @@ def save(self, dir_path: str, overwrite: Optional[bool] = False) -> None: ) @classmethod - def load_from_dir(cls, dir_path: str) -> Self: + def load_from_dir(cls, dir_path: Union[str, Path]) -> Self: """Load the Sample from directory `dir_path`. This is a class method, you don't need to instantiate a `Sample` first. Args: - dir_path (str): Relative or absolute directory path. + dir_path (Union[str,Path]): Relative or absolute directory path. Returns: Sample @@ -1872,15 +1876,16 @@ def load_from_dir(cls, dir_path: str) -> Self: Note: It calls 'load' function during execution. """ + dir_path = Path(dir_path) instance = cls() instance.load(dir_path) return instance - def load(self, dir_path: str) -> None: + def load(self, dir_path: Union[str, Path]) -> None: """Load the Sample from directory `dir_path`. Args: - dir_path (str): Relative or absolute directory path. + dir_path (Union[str,Path]): Relative or absolute directory path. Raises: FileNotFoundError: Triggered if the provided directory does not exist. @@ -1896,23 +1901,23 @@ def load(self, dir_path: str) -> None: >>> Sample(3 scalars, 1 timestamp, 3 fields) """ - if not os.path.exists(dir_path): + dir_path = Path(dir_path) + + if not dir_path.exists(): raise FileNotFoundError(f'Directory "{dir_path}" does not exist. Abort') - if not os.path.isdir(dir_path): + if not dir_path.is_dir(): raise FileExistsError(f'"{dir_path}" is not a directory. Abort') - meshes_dir = os.path.join(dir_path, "meshes") - if os.path.isdir(meshes_dir): - meshes_names = glob.glob(os.path.join(meshes_dir, "*")) + meshes_dir = dir_path / "meshes" + if meshes_dir.is_dir(): + meshes_names = list(meshes_dir.glob("*")) nb_meshes = len(meshes_names) self._meshes = {} self._links = {} self._paths = {} for i in range(nb_meshes): - tree, links, paths = CGM.load( - os.path.join(meshes_dir, f"mesh_{i:09d}.cgns") - ) + tree, links, paths = CGM.load(str(meshes_dir / f"mesh_{i:09d}.cgns")) time = CGH.get_time_values(tree) self._meshes[time], self._links[time], self._paths[time] = ( @@ -1921,12 +1926,10 @@ def load(self, dir_path: str) -> None: paths, ) for i in range(len(self._links[time])): # pragma: no cover - self._links[time][i][0] = os.path.join( - meshes_dir, self._links[time][i][0] - ) + self._links[time][i][0] = str(meshes_dir / self._links[time][i][0]) - scalars_fname = os.path.join(dir_path, "scalars.csv") - if os.path.isfile(scalars_fname): + scalars_fname = dir_path / "scalars.csv" + if scalars_fname.is_file(): names = np.loadtxt( scalars_fname, dtype=str, max_rows=1, delimiter="," ).reshape((-1,)) @@ -1936,7 +1939,7 @@ def load(self, dir_path: str) -> None: for name, value in zip(names, scalars): self.add_scalar(name, value) - time_series_files = glob.glob(os.path.join(dir_path, "time_series_*.csv")) + time_series_files = list(dir_path.glob("time_series_*.csv")) for ts_fname in time_series_files: names = np.loadtxt(ts_fname, dtype=str, max_rows=1, delimiter=",").reshape( (-1,) diff --git a/src/plaid/post/bisect.py b/src/plaid/post/bisect.py index e9c17c89..444a60a8 100644 --- a/src/plaid/post/bisect.py +++ b/src/plaid/post/bisect.py @@ -1,6 +1,7 @@ """Utiliy function to plot bisect graphs comparing predictions vs. targets dataset.""" import subprocess +from pathlib import Path from typing import Union import matplotlib as mpl @@ -78,9 +79,9 @@ def is_dvipng_available(verbose: bool) -> bool: def plot_bisect( - ref_dataset: Union[Dataset, str], - pred_dataset: Union[Dataset, str], - problem_def: Union[ProblemDefinition, str], + ref_dataset: Union[Dataset, str, Path], + pred_dataset: Union[Dataset, str, Path], + problem_def: Union[ProblemDefinition, str, Path], scalar: Union[str, int], save_file_name: str = "bissec_plots", verbose: bool = False, @@ -88,9 +89,9 @@ def plot_bisect( """Plot a bisect graph comparing predictions vs. targets dataset. Args: - ref_dataset (Dataset | str): The reference dataset or its file path. - pred_dataset (Dataset | str): The predicted dataset or its file path. - problem_def (ProblemDefinition | str): The common problem for the reference and predicted dataset + ref_dataset (Dataset | str | Path): The reference dataset or its file path. + pred_dataset (Dataset | str | Path): The predicted dataset or its file path. + problem_def (ProblemDefinition | str | Path): The common problem for the reference and predicted dataset scalar (str | int): The name of the scalar to study or its index. save_file_name (str, optional): Figure name when saving to PNG format. Defaults to "bissec_plots". verbose (bool, optional): Verbose mode. Defaults to False. @@ -99,11 +100,11 @@ def plot_bisect( KeyError: If the provided scalar name is not part of the dataset. """ ### Transform path to Dataset object ### - if isinstance(ref_dataset, str): + if isinstance(ref_dataset, (str, Path)): ref_dataset: Dataset = Dataset(ref_dataset) - if isinstance(pred_dataset, str): + if isinstance(pred_dataset, (str, Path)): pred_dataset: Dataset = Dataset(pred_dataset) - if isinstance(problem_def, str): + if isinstance(problem_def, (str, Path)): problem_def: ProblemDefinition = ProblemDefinition(problem_def) # Load the testing_set diff --git a/src/plaid/post/metrics.py b/src/plaid/post/metrics.py index 87e3b7ce..6c6f1979 100644 --- a/src/plaid/post/metrics.py +++ b/src/plaid/post/metrics.py @@ -1,5 +1,6 @@ """Utility functions for computing and printing metrics for regression problems in PLAID.""" +from pathlib import Path from typing import Union import numpy as np @@ -127,27 +128,27 @@ def pretty_metrics(metrics: dict) -> None: def compute_metrics( - ref_dataset: Union[Dataset, str], - pred_dataset: Union[Dataset, str], - problem: Union[ProblemDefinition, str], + ref_dataset: Union[Dataset, str, Path], + pred_dataset: Union[Dataset, str, Path], + problem: Union[ProblemDefinition, str, Path], save_file_name: str = "test_metrics", verbose: bool = False, ) -> None: """Compute and save evaluation metrics for a given regression problem. Args: - ref_dataset (Dataset | str): Reference dataset or path to a reference dataset. - pred_dataset (Dataset | str): Predicted dataset or path to a predicted dataset. - problem (ProblemDefinition | str): Problem definition or path to a problem definition. + ref_dataset (Dataset | str | Path): Reference dataset or path to a reference dataset. + pred_dataset (Dataset | str | Path): Predicted dataset or path to a predicted dataset. + problem (ProblemDefinition | str | Path): Problem definition or path to a problem definition. save_file_name (str, optional): Name of the file to save the metrics. Defaults to "test_metrics". verbose (bool, optional): If True, print detailed information during computation. """ ### Transform path to Dataset object ### - if isinstance(ref_dataset, str): + if isinstance(ref_dataset, (str, Path)): ref_dataset: Dataset = Dataset(ref_dataset) - if isinstance(pred_dataset, str): + if isinstance(pred_dataset, (str, Path)): pred_dataset: Dataset = Dataset(pred_dataset) - if isinstance(problem, str): + if isinstance(problem, (str, Path)): problem: ProblemDefinition = ProblemDefinition(problem) ### Get important formated values ### diff --git a/src/plaid/problem_definition.py b/src/plaid/problem_definition.py index 31ea25ac..fbca9fbd 100644 --- a/src/plaid/problem_definition.py +++ b/src/plaid/problem_definition.py @@ -20,7 +20,7 @@ import csv import logging -import os +from pathlib import Path from typing import Union import yaml @@ -44,13 +44,13 @@ class ProblemDefinition(object): """Gathers all necessary informations to define a learning problem.""" - def __init__(self, directory_path: str = None) -> None: + def __init__(self, directory_path: Union[str, Path] = None) -> None: """Initialize an empty :class:`ProblemDefinition `. Use :meth:`add_inputs ` or :meth:`add_output_scalars_names ` to feed the :class:`ProblemDefinition` Args: - directory_path (str, optional): The path from which to load PLAID problem definition files. + directory_path (Union[str, Path], optional): The path from which to load PLAID problem definition files. Example: .. code-block:: python @@ -79,7 +79,8 @@ def __init__(self, directory_path: str = None) -> None: self._split: dict[str, IndexType] = None if directory_path is not None: - self._load_from_dir_(str(directory_path)) + directory_path = Path(directory_path) + self._load_from_dir_(directory_path) # -------------------------------------------------------------------------# def get_task(self) -> str: @@ -889,11 +890,11 @@ def get_all_indices(self) -> list[int]: # return res # -------------------------------------------------------------------------# - def _save_to_dir_(self, savedir: str) -> None: + def _save_to_dir_(self, savedir: Path) -> None: """Save problem information, inputs, outputs, and split to the specified directory in YAML and CSV formats. Args: - savedir (str): The directory where the problem information will be saved. + savedir (Path): The directory where the problem information will be saved. Example: .. code-block:: python @@ -902,8 +903,8 @@ def _save_to_dir_(self, savedir: str) -> None: problem = ProblemDefinition() problem._save_to_dir_("/path/to/save_directory") """ - if not (os.path.isdir(savedir)): # pragma: no cover - os.makedirs(savedir) + if not (savedir.is_dir()): # pragma: no cover + savedir.mkdir() data = { "task": self._task, @@ -917,11 +918,11 @@ def _save_to_dir_(self, savedir: str) -> None: "output_meshes": self.out_meshes_names, # list[output mesh name] } - pbdef_fname = os.path.join(savedir, "problem_infos.yaml") + pbdef_fname = savedir / "problem_infos.yaml" with open(pbdef_fname, "w") as file: yaml.dump(data, file, default_flow_style=False, sort_keys=False) - split_fname = os.path.join(savedir, "split.csv") + split_fname = savedir / "split.csv" if self._split is not None: with open(split_fname, "w", newline="") as file: write = csv.writer(file) @@ -942,11 +943,11 @@ def load(cls, save_dir: str) -> Self: # pragma: no cover instance._load_from_dir_(save_dir) return instance - def _load_from_dir_(self, save_dir: str) -> None: + def _load_from_dir_(self, save_dir: Path) -> None: """Load problem information, inputs, outputs, and split from the specified directory in YAML and CSV formats. Args: - save_dir (str): The directory from which to load the problem information. + save_dir (Path): The directory from which to load the problem information. Raises: FileNotFoundError: Triggered if the provided directory does not exist. @@ -959,15 +960,15 @@ def _load_from_dir_(self, save_dir: str) -> None: problem = ProblemDefinition() problem._load_from_dir_("/path/to/load_directory") """ - if not os.path.exists(save_dir): # pragma: no cover + if not save_dir.exists(): # pragma: no cover raise FileNotFoundError(f'Directory "{save_dir}" does not exist. Abort') - if not os.path.isdir(save_dir): # pragma: no cover + if not save_dir.is_dir(): # pragma: no cover raise FileExistsError(f'"{save_dir}" is not a directory. Abort') - pbdef_fname = os.path.join(save_dir, "problem_infos.yaml") + pbdef_fname = save_dir / "problem_infos.yaml" data = {} # To avoid crash if pbdef_fname does not exist - if os.path.isfile(pbdef_fname): + if pbdef_fname.is_file(): with open(pbdef_fname, "r") as file: data = yaml.safe_load(file) else: # pragma: no cover @@ -985,9 +986,9 @@ def _load_from_dir_(self, save_dir: str) -> None: self.in_meshes_names = data["input_meshes"] self.out_meshes_names = data["output_meshes"] - split_fname = os.path.join(save_dir, "split.csv") + split_fname = save_dir / "split.csv" split = {} - if os.path.isfile(split_fname): + if split_fname.is_file(): with open(split_fname) as file: reader = csv.reader(file, delimiter=",") for row in reader: diff --git a/tests/containers/test_sample.py b/tests/containers/test_sample.py index 8b92969c..86576d8e 100644 --- a/tests/containers/test_sample.py +++ b/tests/containers/test_sample.py @@ -7,7 +7,7 @@ # %% Imports -import os +from pathlib import Path import CGNS.PAT.cgnskeywords as CGK import CGNS.PAT.cgnsutils as CGU @@ -128,8 +128,8 @@ def test_read_index_range(tree, physical_dim): @pytest.fixture() -def current_directory(): - return os.path.dirname(os.path.abspath(__file__)) +def current_directory() -> Path: + return Path(__file__).absolute().parent # %% Tests @@ -138,15 +138,9 @@ def current_directory(): class Test_Sample: # -------------------------------------------------------------------------# def test___init__(self, current_directory): - dataset_path_1 = os.path.join( - current_directory, "dataset", "samples", "sample_000000000" - ) - dataset_path_2 = os.path.join( - current_directory, "dataset", "samples", "sample_000000001" - ) - dataset_path_3 = os.path.join( - current_directory, "dataset", "samples", "sample_000000002" - ) + dataset_path_1 = current_directory / "dataset" / "samples" / "sample_000000000" + dataset_path_2 = current_directory / "dataset" / "samples" / "sample_000000001" + dataset_path_3 = current_directory / "dataset" / "samples" / "sample_000000002" sample_already_filled_1 = Sample(dataset_path_1) sample_already_filled_2 = Sample(dataset_path_2) sample_already_filled_3 = Sample(dataset_path_3) @@ -164,16 +158,12 @@ def test___init__(self, current_directory): ) def test__init__unknown_directory(self, current_directory): - dataset_path = os.path.join( - current_directory, "dataset", "samples", "sample_000000298" - ) + dataset_path = current_directory / "dataset" / "samples" / "sample_000000298" with pytest.raises(FileNotFoundError): Sample(dataset_path) def test__init__file_provided(self, current_directory): - dataset_path = os.path.join( - current_directory, "dataset", "samples", "sample_000067392" - ) + dataset_path = current_directory / "dataset" / "samples" / "sample_000067392" with pytest.raises(FileExistsError): Sample(dataset_path) diff --git a/tests/post/test_bisect.py b/tests/post/test_bisect.py index 8c78ddaf..a2712615 100644 --- a/tests/post/test_bisect.py +++ b/tests/post/test_bisect.py @@ -5,8 +5,8 @@ # # -import os import shutil +from pathlib import Path import pytest @@ -16,45 +16,41 @@ @pytest.fixture() -def current_directory() -> str: - return os.path.dirname(os.path.abspath(__file__)) +def current_directory() -> Path: + return Path(__file__).absolute().parent @pytest.fixture() -def working_directory() -> str: - return os.getcwd() +def working_directory() -> Path: + return Path.cwd() class Test_Bisect: def test_bisect_with_paths(self, current_directory, working_directory): - ref_path = os.path.join(current_directory, "dataset_ref") - pred_path = os.path.join(current_directory, "dataset_pred") - problem_path = os.path.join(current_directory, "problem_definition") + ref_path = current_directory / "dataset_ref" + pred_path = current_directory / "dataset_pred" + problem_path = current_directory / "problem_definition" plot_bisect(ref_path, pred_path, problem_path, "scalar_2", "differ_bisect_plot") shutil.move( - os.path.join(working_directory, "differ_bisect_plot.png"), - os.path.join(current_directory, "differ_bisect_plot.png"), + working_directory / "differ_bisect_plot.png", + current_directory / "differ_bisect_plot.png", ) def test_bisect_with_objects(self, current_directory, working_directory): - ref_path = Dataset(os.path.join(current_directory, "dataset_pred")) - pred_path = Dataset(os.path.join(current_directory, "dataset_pred")) - problem_path = ProblemDefinition( - os.path.join(current_directory, "problem_definition") - ) + ref_path = Dataset(current_directory / "dataset_pred") + pred_path = Dataset(current_directory / "dataset_pred") + problem_path = ProblemDefinition(current_directory / "problem_definition") plot_bisect(ref_path, pred_path, problem_path, "scalar_2", "equal_bisect_plot") shutil.move( - os.path.join(working_directory, "equal_bisect_plot.png"), - os.path.join(current_directory, "equal_bisect_plot.png"), + working_directory / "equal_bisect_plot.png", + current_directory / "equal_bisect_plot.png", ) def test_bisect_with_mix(self, current_directory, working_directory): scalar_index = 0 - ref_path = os.path.join(current_directory, "dataset_ref") - pred_path = os.path.join(current_directory, "dataset_near_pred") - problem_path = ProblemDefinition( - os.path.join(current_directory, "problem_definition") - ) + ref_path = current_directory / "dataset_ref" + pred_path = current_directory / "dataset_near_pred" + problem_path = ProblemDefinition(current_directory / "problem_definition") plot_bisect( ref_path, pred_path, @@ -64,16 +60,14 @@ def test_bisect_with_mix(self, current_directory, working_directory): verbose=True, ) shutil.move( - os.path.join(working_directory, "converge_bisect_plot.png"), - os.path.join(current_directory, "converge_bisect_plot.png"), + working_directory / "converge_bisect_plot.png", + current_directory / "converge_bisect_plot.png", ) def test_bisect_error(self, current_directory): - ref_path = os.path.join(current_directory, "dataset_ref") - pred_path = os.path.join(current_directory, "dataset_near_pred") - problem_path = ProblemDefinition( - os.path.join(current_directory, "problem_definition") - ) + ref_path = current_directory / "dataset_ref" + pred_path = current_directory / "dataset_near_pred" + problem_path = ProblemDefinition(current_directory / "problem_definition") with pytest.raises(KeyError): plot_bisect( ref_path, @@ -85,9 +79,9 @@ def test_bisect_error(self, current_directory): ) def test_generated_files(self, current_directory): - path_1 = os.path.join(current_directory, "differ_bisect_plot.png") - path_2 = os.path.join(current_directory, "equal_bisect_plot.png") - path_3 = os.path.join(current_directory, "converge_bisect_plot.png") - assert os.path.exists(path_1) - assert os.path.exists(path_2) - assert os.path.exists(path_3) + path_1 = current_directory / "differ_bisect_plot.png" + path_2 = current_directory / "equal_bisect_plot.png" + path_3 = current_directory / "converge_bisect_plot.png" + assert path_1.is_file() + assert path_2.is_file() + assert path_3.is_file() diff --git a/tests/post/test_metrics.py b/tests/post/test_metrics.py index bef94e97..4cb185e7 100644 --- a/tests/post/test_metrics.py +++ b/tests/post/test_metrics.py @@ -5,8 +5,8 @@ # # -import os import shutil +from pathlib import Path import pytest import yaml @@ -17,53 +17,49 @@ @pytest.fixture() -def current_directory() -> str: - return os.path.dirname(os.path.abspath(__file__)) +def current_directory() -> Path: + return Path(__file__).absolute().parent @pytest.fixture() -def working_directory() -> str: - return os.getcwd() +def working_directory() -> Path: + return Path.cwd() class Test_Metrics: def test_compute_metrics_with_paths(self, current_directory, working_directory): - ref_ds = os.path.join(current_directory, "dataset_ref") - pred_ds = os.path.join(current_directory, "dataset_near_pred") - problem = os.path.join(current_directory, "problem_definition") + ref_ds = current_directory / "dataset_ref" + pred_ds = current_directory / "dataset_near_pred" + problem = current_directory / "problem_definition" compute_metrics(ref_ds, pred_ds, problem, "first_metrics") shutil.move( - os.path.join(working_directory, "first_metrics.yaml"), - os.path.join(current_directory, "first_metrics.yaml"), + working_directory / "first_metrics.yaml", + current_directory / "first_metrics.yaml", ) def test_compute_metrics_with_objects(self, current_directory, working_directory): - ref_ds = Dataset(os.path.join(current_directory, "dataset_ref")) - pred_ds = Dataset(os.path.join(current_directory, "dataset_pred")) - problem = ProblemDefinition( - os.path.join(current_directory, "problem_definition") - ) + ref_ds = Dataset(current_directory / "dataset_ref") + pred_ds = Dataset(current_directory / "dataset_pred") + problem = ProblemDefinition(current_directory / "problem_definition") compute_metrics(ref_ds, pred_ds, problem, "second_metrics", verbose=True) shutil.move( - os.path.join(working_directory, "second_metrics.yaml"), - os.path.join(current_directory, "second_metrics.yaml"), + working_directory / "second_metrics.yaml", + current_directory / "second_metrics.yaml", ) def test_compute_metrics_mix(self, current_directory, working_directory): - ref_ds = Dataset(os.path.join(current_directory, "dataset_ref")) - pred_ds = Dataset(os.path.join(current_directory, "dataset_ref")) - problem = ProblemDefinition( - os.path.join(current_directory, "problem_definition") - ) + ref_ds = Dataset(current_directory / "dataset_ref") + pred_ds = Dataset(current_directory / "dataset_ref") + problem = ProblemDefinition(current_directory / "problem_definition") compute_metrics(ref_ds, pred_ds, problem, "third_metrics", verbose=True) shutil.move( - os.path.join(working_directory, "third_metrics.yaml"), - os.path.join(current_directory, "third_metrics.yaml"), + working_directory / "third_metrics.yaml", + current_directory / "third_metrics.yaml", ) def test_compute_RMSE_data(self, current_directory): - path = os.path.join(current_directory, "first_metrics.yaml") - with open(path, "r") as file: + path = current_directory / "first_metrics.yaml" + with path.open("r") as file: contenu_yaml = yaml.load(file, Loader=yaml.FullLoader) assert contenu_yaml["rRMSE for scalars"]["train"]["scalar_2"] < 0.2 assert contenu_yaml["rRMSE for scalars"]["test"]["scalar_2"] < 0.2 @@ -73,8 +69,8 @@ def test_compute_RMSE_data(self, current_directory): assert contenu_yaml["R2 for scalars"]["test"]["scalar_2"] > 0.8 def test_compute_rRMSE_data(self, current_directory): - path = os.path.join(current_directory, "second_metrics.yaml") - with open(path, "r") as file: + path = current_directory / "second_metrics.yaml" + with path.open("r") as file: contenu_yaml = yaml.load(file, Loader=yaml.FullLoader) assert contenu_yaml["rRMSE for scalars"]["train"]["scalar_2"] > 0.75 assert contenu_yaml["rRMSE for scalars"]["test"]["scalar_2"] > 0.75 @@ -84,8 +80,8 @@ def test_compute_rRMSE_data(self, current_directory): assert contenu_yaml["R2 for scalars"]["test"]["scalar_2"] < 0.0 def test_compute_R2_data(self, current_directory): - path = os.path.join(current_directory, "third_metrics.yaml") - with open(path, "r") as file: + path = current_directory / "third_metrics.yaml" + with path.open("r") as file: contenu_yaml = yaml.load(file, Loader=yaml.FullLoader) assert contenu_yaml["rRMSE for scalars"]["train"]["scalar_2"] == 0.0 assert contenu_yaml["rRMSE for scalars"]["test"]["scalar_2"] == 0.0 diff --git a/tests/test_problem_definition.py b/tests/test_problem_definition.py index 5c0be7a6..4c984e35 100644 --- a/tests/test_problem_definition.py +++ b/tests/test_problem_definition.py @@ -9,6 +9,7 @@ import os import subprocess +from pathlib import Path import pytest @@ -23,18 +24,21 @@ def problem_definition() -> ProblemDefinition: @pytest.fixture() -def current_directory() -> str: - return os.path.dirname(os.path.abspath(__file__)) +def current_directory() -> Path: + return Path(__file__).absolute().parent @pytest.fixture(scope="session", autouse=True) def clean_tests(): + base_dir = Path(__file__).absolute().parent if os.name == "nt": # Windows - retcode = subprocess.call(["cmd", "/c", "tests\\clean.bat"]) + script_path = base_dir / "clean.bat" + retcode = subprocess.call(["cmd", "/c", str(script_path)]) else: # Unix - retcode = subprocess.call(["sh", "./tests/clean.sh"]) + script_path = base_dir / "clean.sh" + retcode = subprocess.call(["sh", str(script_path)]) assert retcode == 0, "Test cleanup script failed" @@ -100,7 +104,7 @@ def test_add_output_scalars_names(self, problem_definition): # -------------------------------------------------------------------------# def test_filter_scalars_names(self, current_directory): - d_path = os.path.join(current_directory, "problem_definition") + d_path = current_directory / "problem_definition" problem = ProblemDefinition(d_path) filter_in = problem.filter_input_scalars_names( ["predict_scalar", "test_scalar"] @@ -165,7 +169,7 @@ def test_add_output_fields_names(self, problem_definition): # -------------------------------------------------------------------------# def test_filter_fields_names(self, current_directory): - d_path = os.path.join(current_directory, "problem_definition") + d_path = current_directory / "problem_definition" problem = ProblemDefinition(d_path) filter_in = problem.filter_input_fields_names(["predict_field", "test_field"]) filter_out = problem.filter_output_fields_names(["predict_field", "test_field"]) @@ -234,7 +238,7 @@ def test_add_output_timeseries_names(self, problem_definition): # -------------------------------------------------------------------------# def test_filter_timeseries_names(self, current_directory): - d_path = os.path.join(current_directory, "problem_definition") + d_path = current_directory / "problem_definition" problem = ProblemDefinition(d_path) filter_in = problem.filter_input_timeseries_names( ["predict_timeseries", "test_timeseries"] @@ -305,7 +309,7 @@ def test_add_output_meshes_names(self, problem_definition): # -------------------------------------------------------------------------# def test_filter_meshes_names(self, current_directory): - d_path = os.path.join(current_directory, "problem_definition") + d_path = current_directory / "problem_definition" problem = ProblemDefinition(d_path) print(f"{problem=}") print(f"{problem.get_input_meshes_names()=}") @@ -364,9 +368,7 @@ def test_save(self, problem_definition, current_directory): new_split = {"train": [0, 1, 2], "test": [3, 4]} problem_definition.set_split(new_split) - problem_definition._save_to_dir_( - os.path.join(current_directory, "problem_definition") - ) + problem_definition._save_to_dir_(current_directory / "problem_definition") def test_load_path_object(self, current_directory): from pathlib import Path @@ -375,7 +377,7 @@ def test_load_path_object(self, current_directory): ProblemDefinition(my_dir / "problem_definition") def test_load(self, current_directory): - d_path = os.path.join(current_directory, "problem_definition") + d_path = current_directory / "problem_definition" problem = ProblemDefinition(d_path) assert problem.get_task() == "regression" assert set(problem.get_input_scalars_names()) == set( From 2edbd7242c4a087d95691791e306e7b62126ff30 Mon Sep 17 00:00:00 2001 From: Xavier Roynard Date: Tue, 12 Aug 2025 15:50:40 +0200 Subject: [PATCH 4/5] (examples) replace all uses of os by pathlib --- examples/containers/dataset_example.py | 5 ++- examples/containers/sample_example.py | 10 ++--- examples/post/bisect_example.py | 56 +++++++++++++------------- examples/post/metrics_example.py | 45 +++++++++++---------- examples/problem_definition_example.py | 7 ++-- 5 files changed, 63 insertions(+), 60 deletions(-) diff --git a/examples/containers/dataset_example.py b/examples/containers/dataset_example.py index c6af860c..7cbd6702 100644 --- a/examples/containers/dataset_example.py +++ b/examples/containers/dataset_example.py @@ -15,6 +15,7 @@ # %% # Import required libraries import os +from pathlib import Path # %% # Import necessary libraries and functions @@ -388,8 +389,8 @@ def dprint(name: str, dictio: dict, end: str = "\n"): # ### Save the dataset to a TAR (Tape Archive) file # %% -tmpdir = f"/tmp/test_safe_to_delete_{np.random.randint(low=1, high=2_000_000_000)}" -tmpfile = os.path.join(tmpdir, "test_file.plaid") +tmpdir = Path(f"/tmp/test_safe_to_delete_{np.random.randint(low=1, high=2_000_000_000)}") +tmpfile = tmpdir / "test_file.plaid" print(f"Save dataset in: {tmpfile}") dataset.save(tmpfile) diff --git a/examples/containers/sample_example.py b/examples/containers/sample_example.py index d155f2d7..5f01ce90 100644 --- a/examples/containers/sample_example.py +++ b/examples/containers/sample_example.py @@ -14,7 +14,7 @@ # %% # Import required libraries -import os +from pathlib import Path # %% # Import necessary libraries and functions @@ -517,10 +517,10 @@ def show_sample(sample: Sample): # ### Save Sample to as a file tree # %% -test_pth = f"/tmp/test_safe_to_delete_{np.random.randint(low=1, high=2_000_000_000)}" -os.makedirs(test_pth) +test_pth = Path(f"/tmp/test_safe_to_delete_{np.random.randint(low=1, high=2_000_000_000)}") +test_pth.mkdir(parents=True, exist_ok=True) -sample_save_fname = os.path.join(test_pth, "test") +sample_save_fname = test_pth / "test" print(f"saving path: {sample_save_fname}") sample.save(sample_save_fname) @@ -537,7 +537,7 @@ def show_sample(sample: Sample): # ### Load a Sample from a directory via the Sample class # %% -new_sample_2 = Sample.load_from_dir(os.path.join(test_pth, "test")) +new_sample_2 = Sample.load_from_dir(test_pth / "test") show_sample(new_sample) diff --git a/examples/post/bisect_example.py b/examples/post/bisect_example.py index 87262ef8..e61cede4 100644 --- a/examples/post/bisect_example.py +++ b/examples/post/bisect_example.py @@ -7,7 +7,8 @@ # %% # Importing Required Libraries -import os +from typing import Union +from pathlib import Path from plaid.containers.dataset import Dataset from plaid.post.bisect import plot_bisect, prepare_datasets @@ -15,27 +16,26 @@ # %% -def get_project_root(path: str, index=3) -> str: +def get_project_root(path: Union[str, Path], index: int=3) -> Path: """Find the project root path Args: - path (str): Current path of the notebook + path (Union[str, Path]): Current path of the notebook index (int, optional): The number of parents to go back. Defaults to 3. Returns: - str: The project root path + Path: The project root path """ + path = Path(path) if index == 0: return path - return get_project_root(os.path.dirname(path), index - 1) + return get_project_root(path.parent, index - 1) # Setting up Directories -current_directory = os.getcwd() -# dataset_directory = os.path.join(get_project_root(current_directory), "tests", "post") -dataset_directory = os.path.join( - get_project_root(current_directory, 1), "tests", "post" -) +current_directory = Path.cwd() +# dataset_directory = get_project_root(current_directory) / "tests" / "post" +dataset_directory = get_project_root(current_directory, 1) / "tests" / "post" # %% [markdown] # ## Prepare Datasets for comparision # @@ -44,9 +44,9 @@ def get_project_root(path: str, index=3) -> str: # %% # Load PLAID datasets and problem metadata objects -ref_ds = Dataset(os.path.join(dataset_directory, "dataset_ref")) -pred_ds = Dataset(os.path.join(dataset_directory, "dataset_near_pred")) -problem = ProblemDefinition(os.path.join(dataset_directory, "problem_definition")) +ref_ds = Dataset(dataset_directory / "dataset_ref") +pred_ds = Dataset(dataset_directory / "dataset_near_pred") +problem = ProblemDefinition(dataset_directory / "problem_definition") # Get output scalars from reference and prediction dataset ref_out_scalars, pred_out_scalars, out_scalars_names = prepare_datasets( @@ -79,9 +79,9 @@ def get_project_root(path: str, index=3) -> str: print("=== Plot with file paths ===") # Load PLAID datasets and problem metadata from files -ref_path = os.path.join(dataset_directory, "dataset_ref") -pred_path = os.path.join(dataset_directory, "dataset_pred") -problem_path = os.path.join(dataset_directory, "problem_definition") +ref_path = dataset_directory / "dataset_ref" +pred_path = dataset_directory / "dataset_pred" +problem_path = dataset_directory / "problem_definition" # Using file paths to generate bisect plot on scalar_2 plot_bisect(ref_path, pred_path, problem_path, "scalar_2", "differ_bisect_plot") @@ -95,9 +95,9 @@ def get_project_root(path: str, index=3) -> str: print("=== Plot with PLAID objects ===") # Load PLAID datasets and problem metadata objects -ref_path = Dataset(os.path.join(dataset_directory, "dataset_ref")) -pred_path = Dataset(os.path.join(dataset_directory, "dataset_ref")) -problem_path = ProblemDefinition(os.path.join(dataset_directory, "problem_definition")) +ref_path = Dataset(dataset_directory / "dataset_ref") +pred_path = Dataset(dataset_directory / "dataset_ref") +problem_path = ProblemDefinition(dataset_directory / "problem_definition") # Using PLAID objects to generate bisect plot on scalar_2 plot_bisect(ref_path, pred_path, problem_path, "scalar_2", "equal_bisect_plot") @@ -111,9 +111,9 @@ def get_project_root(path: str, index=3) -> str: print("=== Mix with scalar index and verbose ===") # Mix -ref_path = os.path.join(dataset_directory, "dataset_ref") -pred_path = os.path.join(dataset_directory, "dataset_near_pred") -problem_path = ProblemDefinition(os.path.join(dataset_directory, "problem_definition")) +ref_path = dataset_directory / "dataset_ref" +pred_path = dataset_directory / "dataset_near_pred" +problem_path = ProblemDefinition(dataset_directory / "problem_definition") # Using scalar index and verbose option to generate bisect plot scalar_index = 0 @@ -131,14 +131,14 @@ def get_project_root(path: str, index=3) -> str: import shutil shutil.move( - os.path.join(current_directory, "differ_bisect_plot.png"), - os.path.join(current_directory, "post", "differ_bisect_plot.png"), + current_directory / "differ_bisect_plot.png", + current_directory / "post" / "differ_bisect_plot.png", ) shutil.move( - os.path.join(current_directory, "equal_bisect_plot.png"), - os.path.join(current_directory, "post", "equal_bisect_plot.png"), + current_directory / "equal_bisect_plot.png", + current_directory / "post" / "equal_bisect_plot.png", ) shutil.move( - os.path.join(current_directory, "converge_bisect_plot.png"), - os.path.join(current_directory, "post", "converge_bisect_plot.png"), + current_directory / "converge_bisect_plot.png", + current_directory / "post" / "converge_bisect_plot.png", ) diff --git a/examples/post/metrics_example.py b/examples/post/metrics_example.py index c36ed554..0e07f89f 100644 --- a/examples/post/metrics_example.py +++ b/examples/post/metrics_example.py @@ -8,6 +8,8 @@ # %% # Importing Required Libraries import os +from typing import Union +from pathlib import Path from plaid.containers.dataset import Dataset from plaid.post.metrics import compute_metrics, prepare_datasets, pretty_metrics @@ -15,27 +17,26 @@ # %% -def get_project_root(path: str, index=3) -> str: +def get_project_root(path: Union[str, Path], index: int=3) -> Path: """Find the project root path Args: - path (str): Current path of the notebook + path (Union[str, Path]): Current path of the notebook index (int, optional): The number of parents to go back. Defaults to 3. Returns: - str: The project root path + Path: The project root path """ + path = Path(path) if index == 0: return path - return get_project_root(os.path.dirname(path), index - 1) + return get_project_root(path.parent, index - 1) # Setting up Directories -current_directory = os.getcwd() -# dataset_directory = os.path.join(get_project_root(current_directory), "tests", "post") -dataset_directory = os.path.join( - get_project_root(current_directory, 1), "tests", "post" -) +current_directory = Path.cwd() +# dataset_directory = get_project_root(current_directory) / "tests" / "post" +dataset_directory = get_project_root(current_directory, 1) / "tests" / "post" # %% [markdown] # ## Prepare Datasets for comparision @@ -44,9 +45,9 @@ def get_project_root(path: str, index=3) -> str: # %% # Load PLAID datasets and problem metadata objects -ref_ds = Dataset(os.path.join(dataset_directory, "dataset_ref")) -pred_ds = Dataset(os.path.join(dataset_directory, "dataset_near_pred")) -problem = ProblemDefinition(os.path.join(dataset_directory, "problem_definition")) +ref_ds = Dataset(dataset_directory / "dataset_ref") +pred_ds = Dataset(dataset_directory / "dataset_near_pred") +problem = ProblemDefinition(dataset_directory / "problem_definition") # Get output scalars from reference and prediction dataset ref_out_scalars, pred_out_scalars, out_scalars_names = prepare_datasets( @@ -79,9 +80,9 @@ def get_project_root(path: str, index=3) -> str: print("=== Metrics with file paths ===") # Load PLAID datasets and problem metadata file paths -ref_ds = os.path.join(dataset_directory, "dataset_ref") -pred_ds = os.path.join(dataset_directory, "dataset_near_pred") -problem = os.path.join(dataset_directory, "problem_definition") +ref_ds = dataset_directory / "dataset_ref" +pred_ds = dataset_directory / "dataset_near_pred" +problem = dataset_directory / "problem_definition" # Using file paths to generate metrics metrics = compute_metrics(ref_ds, pred_ds, problem, "first_metrics") @@ -100,9 +101,9 @@ def get_project_root(path: str, index=3) -> str: print("=== Metrics with PLAID objects and verbose ===") # Load PLAID datasets and problem metadata objects -ref_ds = Dataset(os.path.join(dataset_directory, "dataset_ref")) -pred_ds = Dataset(os.path.join(dataset_directory, "dataset_pred")) -problem = ProblemDefinition(os.path.join(dataset_directory, "problem_definition")) +ref_ds = Dataset(dataset_directory / "dataset_ref") +pred_ds = Dataset(dataset_directory / "dataset_pred") +problem = ProblemDefinition(dataset_directory / "problem_definition") # Pretty print activated with verbose mode metrics = compute_metrics(ref_ds, pred_ds, problem, "second_metrics", verbose=True) @@ -127,10 +128,10 @@ def get_project_root(path: str, index=3) -> str: import shutil shutil.move( - os.path.join(current_directory, "first_metrics.yaml"), - os.path.join(current_directory, "post", "first_metrics.yaml"), + current_directory / "first_metrics.yaml", + current_directory / "post" / "first_metrics.yaml", ) shutil.move( - os.path.join(current_directory, "second_metrics.yaml"), - os.path.join(current_directory, "post", "second_metrics.yaml"), + current_directory / "second_metrics.yaml", + current_directory / "post" / "second_metrics.yaml", ) diff --git a/examples/problem_definition_example.py b/examples/problem_definition_example.py index f8281376..340df658 100644 --- a/examples/problem_definition_example.py +++ b/examples/problem_definition_example.py @@ -14,6 +14,7 @@ # %% # Import required libraries import os +from pathlib import Path import numpy as np @@ -192,9 +193,9 @@ # ### Save a Problem Definition to a directory # %% -test_pth = f"/tmp/test_safe_to_delete_{np.random.randint(low=1, high=2_000_000_000)}" -pb_def_save_fname = os.path.join(test_pth, "test") -os.makedirs(test_pth) +test_pth = Path(f"/tmp/test_safe_to_delete_{np.random.randint(low=1, high=2_000_000_000)}") +pb_def_save_fname = test_pth / "test" +test_pth.mkdir(parents=True, exist_ok=True) print() print(f"saving path: {pb_def_save_fname}") From f818434cc5342c1bc77bffc066eb546643b915e8 Mon Sep 17 00:00:00 2001 From: Xavier Roynard Date: Tue, 12 Aug 2025 15:53:23 +0200 Subject: [PATCH 5/5] (docs) replace all uses of os by pathlib --- docs/conf.py | 15 +++---- docs/source/notebooks/bisect.ipynb | 40 ++++++++++--------- docs/source/notebooks/metrics.ipynb | 34 ++++++++-------- .../source/notebooks/problem_definition.ipynb | 8 ++-- docs/source/notebooks/sample.ipynb | 16 ++++---- 5 files changed, 55 insertions(+), 58 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 5d049dcc..cb326089 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -14,22 +14,17 @@ # -- Path setup -------------------------------------------------------------- import datetime -import os import sys - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# +from pathlib import Path sys.path.insert(0, ".") sys.path.insert(0, "../") -basedir = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) +basedir = Path(__file__).absolute().parent.parent sys.path.insert(0, basedir) -sys.path.insert(0, os.path.join(basedir, "src/plaid")) -# sys.path.insert(0, os.path.join(basedir, "tests")) -sys.path.insert(0, os.path.join(basedir, "examples")) +sys.path.insert(0, basedir / "src" / "plaid") +# sys.path.insert(0, basedir / "tests") +sys.path.insert(0, basedir / "examples") print(sys.path) diff --git a/docs/source/notebooks/bisect.ipynb b/docs/source/notebooks/bisect.ipynb index d7b6ef96..9b3b0545 100644 --- a/docs/source/notebooks/bisect.ipynb +++ b/docs/source/notebooks/bisect.ipynb @@ -17,7 +17,8 @@ "outputs": [], "source": [ "# Importing Required Libraries\n", - "import os\n", + "from typing import Union\n", + "from pathlib import Path\n", "\n", "from plaid.containers.dataset import Dataset\n", "from plaid.post.bisect import plot_bisect, prepare_datasets\n", @@ -30,24 +31,25 @@ "metadata": {}, "outputs": [], "source": [ - "def get_project_root(path: str, index=3) -> str:\n", + "def get_project_root(path: Union[str, Path], index: int=3) -> Path:\n", " \"\"\"Find the project root path\n", "\n", " Args:\n", - " path (str): Current path of the notebook\n", + " path (Union[str, Path]): Current path of the notebook\n", " index (int, optional): The number of parents to go back. Defaults to 3.\n", "\n", " Returns:\n", - " str: The project root path\n", + " Path: The project root path\n", " \"\"\"\n", + " path = Path(path)\n", " if index == 0:\n", " return path\n", - " return get_project_root(os.path.dirname(path), index - 1)\n", + " return get_project_root(path.parent, index - 1)\n", "\n", "\n", "# Setting up Directories\n", - "current_directory = os.getcwd()\n", - "dataset_directory = os.path.join(get_project_root(current_directory), \"tests\", \"post\")" + "current_directory = Path.cwd()\n", + "dataset_directory = get_project_root(current_directory) / \"tests\" / \"post\"" ] }, { @@ -66,9 +68,9 @@ "outputs": [], "source": [ "# Load PLAID datasets and problem metadata objects\n", - "ref_ds = Dataset(os.path.join(dataset_directory, \"dataset_ref\"))\n", - "pred_ds = Dataset(os.path.join(dataset_directory, \"dataset_near_pred\"))\n", - "problem = ProblemDefinition(os.path.join(dataset_directory, \"problem_definition\"))\n", + "ref_ds = Dataset(dataset_directory / \"dataset_ref\")\n", + "pred_ds = Dataset(dataset_directory / \"dataset_near_pred\")\n", + "problem = ProblemDefinition(dataset_directory / \"problem_definition\")\n", "\n", "# Get output scalars from reference and prediction dataset\n", "ref_out_scalars, pred_out_scalars, out_scalars_names = prepare_datasets(\n", @@ -117,9 +119,9 @@ "print(\"=== Plot with file paths ===\")\n", "\n", "# Load PLAID datasets and problem metadata from files\n", - "ref_path = os.path.join(dataset_directory, \"dataset_ref\")\n", - "pred_path = os.path.join(dataset_directory, \"dataset_pred\")\n", - "problem_path = os.path.join(dataset_directory, \"problem_definition\")\n", + "ref_path = dataset_directory / \"dataset_ref\"\n", + "pred_path = dataset_directory / \"dataset_pred\"\n", + "problem_path = dataset_directory / \"problem_definition\"\n", "\n", "# Using file paths to generate bisect plot on scalar_2\n", "plot_bisect(ref_path, pred_path, problem_path, \"scalar_2\", \"differ_bisect_plot\")" @@ -143,9 +145,9 @@ "print(\"=== Plot with PLAID objects ===\")\n", "\n", "# Load PLAID datasets and problem metadata objects\n", - "ref_path = Dataset(os.path.join(dataset_directory, \"dataset_ref\"))\n", - "pred_path = Dataset(os.path.join(dataset_directory, \"dataset_ref\"))\n", - "problem_path = ProblemDefinition(os.path.join(dataset_directory, \"problem_definition\"))\n", + "ref_path = Dataset(dataset_directory / \"dataset_ref\")\n", + "pred_path = Dataset(dataset_directory / \"dataset_pred\")\n", + "problem_path = ProblemDefinition(dataset_directory / \"problem_definition\")\n", "\n", "# Using PLAID objects to generate bisect plot on scalar_2\n", "plot_bisect(ref_path, pred_path, problem_path, \"scalar_2\", \"equal_bisect_plot\")" @@ -169,9 +171,9 @@ "print(\"=== Mix with scalar index and verbose ===\")\n", "\n", "# Mix\n", - "ref_path = os.path.join(dataset_directory, \"dataset_ref\")\n", - "pred_path = os.path.join(dataset_directory, \"dataset_near_pred\")\n", - "problem_path = ProblemDefinition(os.path.join(dataset_directory, \"problem_definition\"))\n", + "ref_path = dataset_directory / \"dataset_ref\"\n", + "pred_path = dataset_directory / \"dataset_near_pred\"\n", + "problem_path = ProblemDefinition(dataset_directory / \"problem_definition\")\n", "\n", "# Using scalar index and verbose option to generate bisect plot\n", "scalar_index = 0\n", diff --git a/docs/source/notebooks/metrics.ipynb b/docs/source/notebooks/metrics.ipynb index d47e03ba..b0ea2609 100644 --- a/docs/source/notebooks/metrics.ipynb +++ b/docs/source/notebooks/metrics.ipynb @@ -17,7 +17,8 @@ "outputs": [], "source": [ "# Importing Required Libraries\n", - "import os\n", + "from typing import Union\n", + "from pathlib import Path\n", "\n", "from plaid.containers.dataset import Dataset\n", "from plaid.post.metrics import compute_metrics, prepare_datasets, pretty_metrics\n", @@ -30,24 +31,25 @@ "metadata": {}, "outputs": [], "source": [ - "def get_project_root(path: str, index=3) -> str:\n", + "def get_project_root(path: Union[str, Path], index=3) -> Path:\n", " \"\"\"Find the project root path\n", "\n", " Args:\n", - " path (str): Current path of the notebook\n", + " path (Union[str, Path]): Current path of the notebook\n", " index (int, optional): The number of parents to go back. Defaults to 3.\n", "\n", " Returns:\n", - " str: The project root path\n", + " Path: The project root path\n", " \"\"\"\n", + " path = Path(path)\n", " if index == 0:\n", " return path\n", - " return get_project_root(os.path.dirname(path), index - 1)\n", + " return get_project_root(path.parent, index - 1)\n", "\n", "\n", "# Setting up Directories\n", - "current_directory = os.getcwd()\n", - "dataset_directory = os.path.join(get_project_root(current_directory), \"tests\", \"post\")" + "current_directory = Path.cwd()\n", + "dataset_directory = current_directory / \"tests\" / \"post\"" ] }, { @@ -66,9 +68,9 @@ "outputs": [], "source": [ "# Load PLAID datasets and problem metadata objects\n", - "ref_ds = Dataset(os.path.join(dataset_directory, \"dataset_ref\"))\n", - "pred_ds = Dataset(os.path.join(dataset_directory, \"dataset_near_pred\"))\n", - "problem = ProblemDefinition(os.path.join(dataset_directory, \"problem_definition\"))\n", + "ref_ds = Dataset(dataset_directory / \"dataset_ref\")\n", + "pred_ds = Dataset(dataset_directory / \"dataset_near_pred\")\n", + "problem = ProblemDefinition(dataset_directory / \"problem_definition\")\n", "\n", "# Get output scalars from reference and prediction dataset\n", "ref_out_scalars, pred_out_scalars, out_scalars_names = prepare_datasets(\n", @@ -117,9 +119,9 @@ "print(\"=== Metrics with file paths ===\")\n", "\n", "# Load PLAID datasets and problem metadata file paths\n", - "ref_ds = os.path.join(dataset_directory, \"dataset_ref\")\n", - "pred_ds = os.path.join(dataset_directory, \"dataset_near_pred\")\n", - "problem = os.path.join(dataset_directory, \"problem_definition\")\n", + "ref_ds = dataset_directory / \"dataset_ref\"\n", + "pred_ds = dataset_directory / \"dataset_near_pred\"\n", + "problem = dataset_directory / \"problem_definition\"\n", "\n", "# Using file paths to generate metrics\n", "metrics = compute_metrics(ref_ds, pred_ds, problem, \"first_metrics\")\n", @@ -148,9 +150,9 @@ "print(\"=== Metrics with PLAID objects and verbose ===\")\n", "\n", "# Load PLAID datasets and problem metadata objects\n", - "ref_ds = Dataset(os.path.join(dataset_directory, \"dataset_ref\"))\n", - "pred_ds = Dataset(os.path.join(dataset_directory, \"dataset_pred\"))\n", - "problem = ProblemDefinition(os.path.join(dataset_directory, \"problem_definition\"))\n", + "ref_ds = Dataset(dataset_directory / \"dataset_ref\")\n", + "pred_ds = Dataset(dataset_directory / \"dataset_pred\")\n", + "problem = ProblemDefinition(dataset_directory / \"problem_definition\")\n", "\n", "# Pretty print activated with verbose mode\n", "metrics = compute_metrics(ref_ds, pred_ds, problem, \"second_metrics\", verbose=True)" diff --git a/docs/source/notebooks/problem_definition.ipynb b/docs/source/notebooks/problem_definition.ipynb index 24186b4a..42f68c06 100644 --- a/docs/source/notebooks/problem_definition.ipynb +++ b/docs/source/notebooks/problem_definition.ipynb @@ -24,7 +24,7 @@ "outputs": [], "source": [ "# Import required libraries\n", - "import os\n", + "from pathlib import Path\n", "\n", "import numpy as np" ] @@ -229,9 +229,9 @@ "metadata": {}, "outputs": [], "source": [ - "test_pth = f\"/tmp/test_safe_to_delete_{np.random.randint(1e10, 1e12)}\"\n", - "pb_def_save_fname = os.path.join(test_pth, \"test\")\n", - "os.makedirs(test_pth)\n", + "test_pth = Path(f\"/tmp/test_safe_to_delete_{np.random.randint(1e10, 1e12)}\")\n", + "pb_def_save_fname = test_pth / \"test\"\n", + "test_pth.mkdir(parents=True, exist_ok=True)\n", "print(f\"saving path: {pb_def_save_fname}\")\n", "\n", "problem._save_to_dir_(pb_def_save_fname)" diff --git a/docs/source/notebooks/sample.ipynb b/docs/source/notebooks/sample.ipynb index 0dca91bc..92724a7c 100644 --- a/docs/source/notebooks/sample.ipynb +++ b/docs/source/notebooks/sample.ipynb @@ -25,7 +25,7 @@ "outputs": [], "source": [ "# Import required libraries\n", - "import os\n", + "from pathlib import Path\n", "\n", "import numpy as np" ] @@ -255,9 +255,7 @@ "metadata": {}, "outputs": [], "source": [ - "path_linked_sample = os.path.join(\n", - " os.getcwd(), \"dataset/samples/sample_000000000/meshes/mesh_000000000.cgns\"\n", - ")\n", + "path_linked_sample = Path.cwd() / \"dataset/samples/sample_000000000/meshes/mesh_000000000.cgns\"\n", "new_sample_mult_mesh.link_tree(\n", " path_linked_sample, linked_sample=sample, linked_time=0.0, time=1.5\n", ")\n", @@ -929,10 +927,10 @@ "metadata": {}, "outputs": [], "source": [ - "test_pth = f\"/tmp/test_safe_to_delete_{np.random.randint(1e10, 1e12)}\"\n", - "os.makedirs(test_pth)\n", + "test_pth = Path(f\"/tmp/test_safe_to_delete_{np.random.randint(1e10, 1e12)}\")\n", + "test_pth.mkdir(parents=True, exist_ok=True)\n", "\n", - "sample_save_fname = os.path.join(test_pth, \"test\")\n", + "sample_save_fname = test_pth / \"test\"\n", "print(f\"saving path: {sample_save_fname}\")\n", "\n", "sample.save(sample_save_fname)" @@ -969,9 +967,9 @@ "metadata": {}, "outputs": [], "source": [ - "new_sample_2 = Sample.load_from_dir(os.path.join(test_pth, \"test\"))\n", + "new_sample_2 = Sample.load_from_dir(test_pth / \"test\")\n", "\n", - "show_sample(new_sample)" + "show_sample(new_sample_2)" ] }, {