Source code for mesh2hrtf.Output2HRTF.process_multiple_outputs2hrtf

import os
import shutil
import glob
import mesh2hrtf as m2h


[docs] def process_multiple_outputs2hrtf( paths, merge=False, inspect=False, pattern=None, plot=None, plane="horizontal", atol=.1, savedir=None): """ Process NumCalc outputs from multiple projects and write data to disk. This is a convenience function that process multiple Mesh2HRTF projects and offers to merge and plot the results in one call: 1. Run :py:func:`~mesh2hrtf.output2hrtf` in folders specified by `paths`. This also calls :py:func:`~mesh2hrtf.write_output_report`, :py:func:`~mesh2hrtf.reference_hrtfs`, and :py:func:`~mesh2hrtf.compute_hrirs`. 2. Run :py:func:`~mesh2hrtf.merge_sofa_files` (optional). 3. Run :py:func:`~mesh2hrtf.inspect_sofa_files` (optional). If merge is ``True``, only the merged data is inspected. 4. Move data to `savedir` (optional). If merge is ``True`` only the merged data will be moved and the remaining data is deleted. The file names of the moved data stat with the name of the folder from which they were moved to `savedir`. Parameters ---------- paths : str, tuple of strings Paths to search for Mesh2HRTF projects. If `paths` is a tuple, the projects found in the paths will be merged if `merge` is ``True``. E.g., if ``paths[0]`` is ``"some/path/left/*"`` and ``paths[1]`` is ``"some/path/right/*"`` all SOFA files in the matching folders will be merged. If `merge` is ``False`` all projects will be processed independently. merge : bool, optional ``True`` to merge data from different projets using :py:func:`~mesh2hrtf.merge_sofa_files` (see `paths` above). The default ``False`` does not merge data. inspect : bool, optional ``True`` to plot data the results from different projets using :py:func:`~mesh2hrtf.inspect_sofa_files`. If `merge` is ``True`` this is only done for the merged data. The default ``False`` does not plot the data. pattern : str, optional Merge, inspect and move only SOFA files that have `pattern` in their file names. E.g., if `pattern` is ``"HRIR"`` only the SOFA files containing HRIR in their name will be merged, inspected, and coped to `savedir` (see below). plot : str, optional This parameter is passed to :py:func:`~mesh2hrtf.inspect_sofa_files`. plane : str, optional This parameter is passed to :py:func:`~mesh2hrtf.inspect_sofa_files`. atol : float, optional This parameter is passed to :py:func:`~mesh2hrtf.inspect_sofa_files`. savedir : str, optional Path under which the results are saved. The default ``None`` will leave the data in their project folders, any other value will move the data to `savedir` and delete all data in `project_folder/Output2HRTF` except for the project reports. Raises ------ ValueError If issues were detected in any Mesh2HRTF project. The value error is raised after all data was processed. """ # check input ------------------------------------------------------------- if isinstance(paths, str): paths = (paths, ) if not isinstance(paths, (tuple, list)) or len(paths) > 2: raise ValueError( "paths must be a string or a tuple with a maximum length of two") if merge and len(paths) != 2: raise ValueError("path must be a tuple of length two if merge is True") # create save directories if it does not exist # (already done here to throw early errors if savedir is invalid) if savedir is not None and not os.path.isdir(savedir): os.mkdir(savedir) # loop paths for running output_2_hrtf in folders ------------------------- print("Generating SOFA files") print("---------------------") # for tracking of issues issues = [] for pp, path in enumerate(paths): # loop folders in path folders = glob.glob(path) for ff, folder in enumerate(folders): # check name = os.path.basename(folder) if not os.path.isfile(os.path.join(folder, "parameters.json")): print(f"Skipping: {name}") continue print((f"{name} (path {pp+1}/{len(paths)}, " f"folder {ff+1}/{len(folders)})")) # run output2hrtf m2h.output2hrtf(folder) # track issues if os.path.isfile(os.path.join( folder, "Output2HRTF", "report_issues.txt")): issues.append(folder) # merge SOFA files -------------------------------------------------------- if merge: print("\nMerging SOFA files") print("------------------") m2h.merge_sofa_files(paths, pattern) # if SOFA files were merged, only the merged files are used in the # following (merged files saved under paths[0]) paths_inspect = (paths[0], ) pattern = "*merged*" if pattern is None else pattern + "*merged*" else: paths_inspect = paths # inspect SOFA files ------------------------------------------------------ if inspect: print("\nInspecting SOFA files") print("---------------------") for pp, path in enumerate(paths_inspect): print(f"{path} ({pp+1}/{len(paths_inspect)})") m2h.inspect_sofa_files(path, pattern, plot, plane, atol) # return if data should be left in place ---------------------------------- if savedir is None: if issues: msg = ("Detected issues in NumCalc output. Check report files in " "the following Output2HRTF folders:\n") msg += "\n".join(issues) raise ValueError(msg) print("\nfinished") return # move data to savedir ---------------------------------------------------- print("\nMoving results to savedir") print("-------------------------") for pp, path in enumerate(paths): # loop folders in path folders = glob.glob(path) if pattern is None: pattern = "*" for ff, folder in enumerate(folders): name = os.path.basename(folder) # copy data if pp == 0 or not merge: # sofa files and plots for file in glob.glob(os.path.join( folder, "Output2HRTF", pattern)): if file.endswith((".sofa", ".pdf", ".jpeg")): copy_name = name + "_" + os.path.basename( file).replace("_merged", "") shutil.copyfile(file, os.path.join(savedir, copy_name)) # remove data for file in glob.glob(os.path.join(folder, "Output2HRTF", "*")): if "report" not in file: os.remove(file) if issues: msg = ("Detected issues in NumCalc output. Check report files in " f"{savedir} and the following Output2HRTF folders:\n") msg += "\n".join(issues) with open(os.path.join(savedir, "report_issues.txt"), "w") as issues: issues.write(msg) raise ValueError(msg) print("\nfinished") return