diff --git a/scripts/parse_commands.py b/scripts/parse_commands.py index 38b0d92cdf24b7fcdafbeaa5bb3a7de6736d6712..b86751fb6cf52fbb3e265ab45f98f45301e07cac 100644 --- a/scripts/parse_commands.py +++ b/scripts/parse_commands.py @@ -40,6 +40,7 @@ if __name__ == '__main__': cmds_dec.extend(re.findall(r"REF decoder command:\\n\\t(.*?)\\n", line)) cmds_rend.extend(re.findall(r"Running command\\n(.*?)\\n", line)) cmds_isar_post_rend.extend(re.findall(r"Running ISAR post renderer command\\n(.*?)\\n", line)) + cmds_isar_post_rend.extend(re.findall(r"Running ISAR EXT REND command\\n(.*?)\\n", line)) # If pytest-html < v4 is used, the parsing will fail and render empty lists. This is a work-around in case that happens. if all(not x for x in [cmds_enc, cmds_dec, cmds_rend, cmds_isar_post_rend]): @@ -72,6 +73,8 @@ if __name__ == '__main__': rend_cmd = True elif "Running ISAR post renderer command" in line: isar_post_rend_cmd = True + elif "Running ISAR EXT REND command" in line: + isar_post_rend_cmd = True # Sort lists to keep deterministic order between runs cmds_enc.sort() @@ -135,7 +138,7 @@ if __name__ == '__main__': if '.txt' in arg: arg = re.sub('tests', REF_PATH, arg) # Identify special cases of output files: dectrace, spltmd.bit - if 'spltmd.bit' in arg or 'dectrace' in arg: + if 'spltmd' in arg or 'dectrace' in arg: arg = re.sub('tests', CUT_PATH, arg) if 'tests' in arg: if not input_set: @@ -189,7 +192,7 @@ if __name__ == '__main__': arg = path.relpath(arg).replace('\\','/') arg = re.sub('IVAS_rend_ref(.exe)?', '$CUT_REND_BIN', arg) arg = re.sub('scripts', TESTV_PATH, arg) - arg = re.sub('tests/renderer_short/data', TESTV_PATH + r'renderer_short/data/', arg) + arg = re.sub('tests/renderer_short/data', TESTV_PATH + r'/renderer_short/data/', arg) arg = re.sub('tests', CUT_PATH, arg) args.append(arg) cmd = ' '.join(args) @@ -214,6 +217,7 @@ if __name__ == '__main__': arg = path.relpath(arg).replace('\\','/') arg = re.sub('ISAR_post_rend_ref(.exe)?', '$CUT_ISAR_POST_REND_BIN', arg) arg = re.sub('scripts', TESTV_PATH, arg) + arg = re.sub('tests/split_rendering/error_patterns', TESTV_PATH + r'/testv/split_rendering/error_patterns', arg) if re.search("^tests.*bit$",arg): arg = re.sub('tests', REF_PATH, arg) arg = re.sub('tests', CUT_PATH, arg) diff --git a/scripts/testv/stv1ISM48s_cut.wav b/scripts/testv/stv1ISM48s_cut.wav new file mode 100644 index 0000000000000000000000000000000000000000..d28db1c6bf241827e516e0db490c8a3f54eb55de --- /dev/null +++ b/scripts/testv/stv1ISM48s_cut.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:41b6161c00a1c97a61563b34ec14bcd728ed990f614c32c98de0525fe2bb3cb5 +size 480044 diff --git a/scripts/testv/stv1MASA1TC48c_cut.wav b/scripts/testv/stv1MASA1TC48c_cut.wav new file mode 100644 index 0000000000000000000000000000000000000000..263f109000e4a141bdbabe41a7c5686421e05e0d --- /dev/null +++ b/scripts/testv/stv1MASA1TC48c_cut.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2409df48bf501463db0e468aeeee11e5aa866f0adf91ef714a7c6fc506235aa1 +size 288044 diff --git a/scripts/testv/stv2MASA2TC48c_cut.wav b/scripts/testv/stv2MASA2TC48c_cut.wav new file mode 100644 index 0000000000000000000000000000000000000000..e159c4f9ae1d39c5ad6ed62c7241ac722f4a7ecd --- /dev/null +++ b/scripts/testv/stv2MASA2TC48c_cut.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:60a713ed1b97cf94b16849806951ef83d8f41c8ee455b267ec0a292c695cbbc1 +size 576044 diff --git a/scripts/testv/stv4ISM48s_cut.wav b/scripts/testv/stv4ISM48s_cut.wav new file mode 100644 index 0000000000000000000000000000000000000000..905a5b39ef0056547a122d23ec27fac2270a6304 --- /dev/null +++ b/scripts/testv/stv4ISM48s_cut.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6ff9fac351439f5d32392d6b143ba088e657ceb66afbdf355a1877d696454d52 +size 1920044 diff --git a/scripts/testv/stv51MC48c_cut.wav b/scripts/testv/stv51MC48c_cut.wav new file mode 100644 index 0000000000000000000000000000000000000000..45a6d15dcacb926a86ace60fe019d685f6f48b6c --- /dev/null +++ b/scripts/testv/stv51MC48c_cut.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e1c51a0e0d7a09f31e219ea3da3800d942c421345f69802e91d9986a72f58dd3 +size 2880044 diff --git a/scripts/testv/stv714MC48c_cut.wav b/scripts/testv/stv714MC48c_cut.wav new file mode 100644 index 0000000000000000000000000000000000000000..cabcb790b06b55e5fb8a98c3ab190547cec7bbd6 --- /dev/null +++ b/scripts/testv/stv714MC48c_cut.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:da62e19b166089efae2f22e68d76b82d3295d15785a4967465a04bc1c75b0462 +size 3456044 diff --git a/scripts/testv/stvOMASA_1ISM_1MASA1TC48c_cut.wav b/scripts/testv/stvOMASA_1ISM_1MASA1TC48c_cut.wav new file mode 100644 index 0000000000000000000000000000000000000000..10ad690c7086a86ee080ee2a9fea57fd90d6c9e2 --- /dev/null +++ b/scripts/testv/stvOMASA_1ISM_1MASA1TC48c_cut.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e99552fd0ced5c2e429643a52b9da587ac565ad4e9443ab2dadc70dcd97c4edb +size 576044 diff --git a/scripts/testv/stvOMASA_4ISM_2MASA2TC48c_cut.wav b/scripts/testv/stvOMASA_4ISM_2MASA2TC48c_cut.wav new file mode 100644 index 0000000000000000000000000000000000000000..70b494f20148403b6c626299987b20bc43b0de92 --- /dev/null +++ b/scripts/testv/stvOMASA_4ISM_2MASA2TC48c_cut.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a5dd8a743f64ef52285c3ca6e6d938a5eb4522aa1ce7ddd308241e6c06de1e96 +size 1728044 diff --git a/scripts/testv/stvOSBA_1ISM_FOA48c_cut.wav b/scripts/testv/stvOSBA_1ISM_FOA48c_cut.wav new file mode 100644 index 0000000000000000000000000000000000000000..3e78974e30cc87a433b726aeb0251bd87b9e6273 --- /dev/null +++ b/scripts/testv/stvOSBA_1ISM_FOA48c_cut.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ba6a0cbd579bcd8d359b948eecf3ae25c80ae20be583b92906d9ead97d0c8a7c +size 2400044 diff --git a/scripts/testv/stvOSBA_3ISM_3OA48c_cut.wav b/scripts/testv/stvOSBA_3ISM_3OA48c_cut.wav new file mode 100644 index 0000000000000000000000000000000000000000..532f2251d5ef7bc7980eac31730dc4c4b3401d2e --- /dev/null +++ b/scripts/testv/stvOSBA_3ISM_3OA48c_cut.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ebe917d67e56059ec79bbbafb3fbbaa8227161935021b3fcab977242a8a57f0b +size 9120044 diff --git a/scripts/testv/stvOSBA_4ISM_3OA48c_cut.wav b/scripts/testv/stvOSBA_4ISM_3OA48c_cut.wav new file mode 100644 index 0000000000000000000000000000000000000000..0804be6fa716fe2c28ac052191516a29a2efe7be --- /dev/null +++ b/scripts/testv/stvOSBA_4ISM_3OA48c_cut.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7c273f51c67e952bddf073dd404cdfb83201b5f24324742c45404b10e561e8c0 +size 9600044 diff --git a/tests/conformance-test/test_26252.py b/tests/conformance-test/test_26252.py index 0179f58bfcfb30d01fc37046896b960d82e97bad..395e258e126c0013fcdaa05c14f32af1c7a4189d 100644 --- a/tests/conformance-test/test_26252.py +++ b/tests/conformance-test/test_26252.py @@ -59,7 +59,7 @@ def replace_paths(instr, testv_path, ref_path, cut_path): test_dict = {} TEST_DIR = "." -scripts=["Readme_IVAS_enc.txt", "Readme_IVAS_dec.txt", "Readme_IVAS_rend.txt", "Readme_IVAS_JBM_dec.txt", "Readme_IVAS_ISAR_dec.txt", "Readme_IVAS_ISAR_post_rend.txt"] +scripts=["Readme_IVAS_enc.txt", "Readme_IVAS_dec.txt", "Readme_IVAS_rend.txt", "Readme_IVAS_JBM_dec.txt", "Readme_IVAS_ISAR_dec.txt", "Readme_IVAS_ISAR_post_rend.txt"] for s in scripts: with open(os.path.join(TEST_DIR, s), "r", encoding="UTF-8") as fp: diff --git a/tests/renderer/utils.py b/tests/renderer/utils.py index 9acb1b7f18101c802f3c9edb5b65af498ce85806..1aa7370f08dd8d919e2cf028bf3e4cfb223447b8 100644 --- a/tests/renderer/utils.py +++ b/tests/renderer/utils.py @@ -67,8 +67,7 @@ from pyaudio3dtools.audiofile import readfile from ..cmp_pcm import cmp_pcm from ..conftest import get_split_idx, parse_properties - -def _run_cmd(cmd, env, test_info=None): +def _run_cmd(cmd, test_info=None, env=None ): """ Helper function for running some command. Raises a SystemError if either the return code is non-zero or a USAN printout is detected @@ -93,32 +92,30 @@ def _run_cmd(cmd, env, test_info=None): raise SystemError(error) -def run_cmd(cmd, test_info, env=None): +def run_cmd(cmd, test_info=None, env=None): logging.info(f"\nRunning command\n{' '.join(cmd)}\n") - _run_cmd(cmd, env, test_info) + _run_cmd(cmd, test_info=test_info, env=env) -def run_isar_ext_rend_cmd(cmd, env=None): +def run_isar_ext_rend_cmd(cmd, test_info=None, env=None): logging.info(f"\nRunning ISAR EXT REND command\n{' '.join(cmd)}\n") - _run_cmd(cmd, env) + _run_cmd(cmd, test_info=test_info, env=env) -def run_ivas_isar_enc_cmd(cmd, env=None): +def run_ivas_isar_enc_cmd(cmd, test_info=None, env=None): logging.info(f"\nRunning IVAS ISAR encoder command\n{' '.join(cmd)}\n") - _run_cmd(cmd, env) - + _run_cmd(cmd, test_info=test_info, env=env) -def run_ivas_isar_dec_cmd(cmd, env=None): +def run_ivas_isar_dec_cmd(cmd, test_info=None, env=None): if BIN_SUFFIX_MERGETARGET in cmd[0]: logging.info(f"\nREF decoder command:\n\t{' '.join(cmd)}\n") else: logging.info(f"\nDUT decoder command:\n\t{' '.join(cmd)}\n") - _run_cmd(cmd, env) - + _run_cmd(cmd, test_info=test_info, env=env) -def run_isar_post_rend_cmd(cmd, env=None): +def run_isar_post_rend_cmd(cmd, test_info=None, env=None): logging.info(f"\nRunning ISAR post renderer command\n{' '.join(cmd)}\n") - _run_cmd(cmd, env) + _run_cmd(cmd, test_info=test_info, env=env) def check_BE( diff --git a/tests/split_rendering/test_split_rendering.py b/tests/split_rendering/test_split_rendering.py index 0ff32fa290ccdb0693d1d2f296630a652ab20881..32efd73109fe0d210c61aab117e23eec1c75a343 100644 --- a/tests/split_rendering/test_split_rendering.py +++ b/tests/split_rendering/test_split_rendering.py @@ -36,7 +36,6 @@ from tests.split_rendering.utils import * """ Ambisonics """ - @pytest.mark.parametrize("delay_profile", DELAY_PROFILES) @pytest.mark.parametrize("trajectory", SPLIT_REND_HR_TRAJECTORIES_TO_TEST) @pytest.mark.parametrize("render_config", RENDERER_CONFIGS_TO_TEST_AMBI) @@ -104,6 +103,7 @@ def test_ambisonics_external_split( test_info, in_fmt=in_fmt, render_config=RENDER_CFG_DIR.joinpath(f"{render_config}.txt"), + binary_suffix=EXE_SUFFIX, pre_trajectory=pre_trajectory, post_trajectory=post_trajectory, get_mld=get_mld, @@ -184,6 +184,7 @@ def test_multichannel_external_split( test_info, in_fmt=in_fmt, render_config=RENDER_CFG_DIR.joinpath(f"{render_config}.txt"), + binary_suffix=EXE_SUFFIX, pre_trajectory=pre_trajectory, post_trajectory=post_trajectory, get_mld=get_mld, @@ -264,6 +265,7 @@ def test_ism_external_split( test_info, in_fmt=in_fmt, render_config=RENDER_CFG_DIR.joinpath(f"{render_config}.txt"), + binary_suffix=EXE_SUFFIX, pre_trajectory=pre_trajectory, post_trajectory=post_trajectory, get_mld=get_mld, @@ -344,6 +346,7 @@ def test_masa_external_split( test_info, in_fmt=in_fmt, render_config=RENDER_CFG_DIR.joinpath(f"{render_config}.txt"), + binary_suffix=EXE_SUFFIX, pre_trajectory=pre_trajectory, post_trajectory=post_trajectory, get_mld=get_mld, @@ -424,6 +427,7 @@ def test_omasa_external_split( test_info, in_fmt=in_fmt, render_config=RENDER_CFG_DIR.joinpath(f"{render_config}.txt"), + binary_suffix=EXE_SUFFIX, pre_trajectory=pre_trajectory, post_trajectory=post_trajectory, get_mld=get_mld, @@ -504,6 +508,7 @@ def test_osba_external_split( test_info, in_fmt=in_fmt, render_config=RENDER_CFG_DIR.joinpath(f"{render_config}.txt"), + binary_suffix=EXE_SUFFIX, pre_trajectory=pre_trajectory, post_trajectory=post_trajectory, get_mld=get_mld, @@ -544,6 +549,7 @@ def test_post_rend_plc( test_info, in_fmt=in_fmt, render_config=RENDER_CFG_DIR.joinpath(f"{render_config}.txt"), + binary_suffix=EXE_SUFFIX, pre_trajectory=pre_trajectory, post_trajectory=post_trajectory, plc_error_pattern=ERROR_PATTERNS_DIR.joinpath(f"{error_pattern}.ep"), @@ -557,7 +563,6 @@ def test_post_rend_plc( """ BINAURAL_SPLIT_PCM """ - full_chain_split_pcm_params = [ ("HOA3", "96000", "split_renderer_config_1dof_512k_default"), ("7_1_4", "512000", "split_renderer_config_3dofhq_512k_lc3plus"), @@ -639,6 +644,7 @@ def test_external_split_pcm( render_config=RENDER_CFG_DIR.joinpath(f"{render_config}.txt"), pre_trajectory=pre_trajectory, post_trajectory=post_trajectory, + binary_suffix=EXE_SUFFIX, renderer_fmt="BINAURAL_SPLIT_PCM", get_mld=get_mld, mld_lim=get_mld_lim, @@ -679,6 +685,7 @@ def test_framing_combinations_external_split( render_config=RENDER_FRAMING_CFG_DIR.joinpath(f"{render_config}.txt"), pre_trajectory=pre_trajectory, post_trajectory=post_trajectory, + binary_suffix=EXE_SUFFIX, post_rend_fr=post_rend_fr, pre_rend_fr=pre_rend_fr, get_mld=get_mld, diff --git a/tests/split_rendering/utils.py b/tests/split_rendering/utils.py index ca7a5143c581d181f895fed3914c6a3a760484f1..39fe5cf1a703e429f2008923067f25686d1fa8e8 100644 --- a/tests/split_rendering/utils.py +++ b/tests/split_rendering/utils.py @@ -35,6 +35,7 @@ import sys from pathlib import Path from tempfile import TemporaryDirectory from typing import Tuple, Optional +from os import path import numpy as np import pytest @@ -61,7 +62,6 @@ from ..conftest import parse_properties sys.path.append(SCRIPTS_DIR) from pyaudio3dtools.audiofile import readfile, writefile - def lc3plus_used(test_info, in_fmt, render_config): return ( # LC3plus used explicitly @@ -147,27 +147,6 @@ def check_xfail( "unsupported framing: LCLD codec doesn't support aggregation. Pre-renderer (ISAR) frame size must match LCLD frame size." ) - -def truncate_signal( - in_file: Path, - out_file: Path, -) -> None: - """ - Truncate the signal in in_file to maximum INPUT_DURATION_SEC seconds, - and write the truncated signal to out_file - """ - data, fs = readfile(in_file) - - if data.ndim == 1: - data_out = data[: INPUT_DURATION_SEC * fs] - elif data.ndim == 2: - data_out = data[: INPUT_DURATION_SEC * fs, :] - else: - raise ValueError(f"Cannot truncate data with dimension of {data.ndim}") - - writefile(out_file, data_out, fs) - - def run_full_chain_split_rendering( record_property, props_to_record, @@ -199,7 +178,6 @@ def run_full_chain_split_rendering( with TemporaryDirectory() as tmp_dir: tmp_dir = Path(tmp_dir) - cut_in_file = tmp_dir.joinpath("cut_input.wav") renderer_fmt_for_filename = renderer_fmt.replace("BINAURAL_", "") filename_base = f"{in_fmt}_{bitrate}_{renderer_fmt_for_filename}_full_cfg_{render_config.stem}_fr_pre_{pre_rend_fr}_post_{post_rend_fr}" @@ -223,6 +201,7 @@ def run_full_chain_split_rendering( ivas_bitstream = output_path_base.joinpath(ivas_bitstream_stem) split_bitstream = output_path_base.joinpath(split_bitstream_stem) out_file = output_path_base.joinpath(out_file_stem) + if renderer_fmt == "BINAURAL_SPLIT_PCM": split_md_file = output_path_base.joinpath(split_md_file_stem) @@ -245,8 +224,7 @@ def run_full_chain_split_rendering( # if in REF or CUT creation mode use the comparetestv if test_info.config.option.create_ref or test_info.config.option.create_cut: in_file = FORMAT_TO_FILE_COMPARETEST[in_fmt] - truncate_signal(in_file, cut_in_file) - + cut_in_file = in_file.with_stem(in_file.stem + "_cut") enc_cmd[3] = str(cut_in_file) else: enc_cmd[3] = str(FORMAT_TO_FILE_SMOKETEST[in_fmt]) @@ -257,7 +235,7 @@ def run_full_chain_split_rendering( enc_cmd[1:1] = FORMAT_TO_IVAS_COD_FORMAT[in_fmt] - run_ivas_isar_enc_cmd(enc_cmd) + run_ivas_isar_enc_cmd(enc_cmd, test_info=test_info) if delay_profile: rtp_bitstream = ivas_bitstream.with_suffix(".netsimout") @@ -292,8 +270,8 @@ def run_full_chain_split_rendering( if delay_profile: dec_cmd[5:5] = ["-voip"] - run_ivas_isar_dec_cmd(dec_cmd) - + run_ivas_isar_dec_cmd(dec_cmd, test_info=test_info) + # run split renderer post_rend_cmd = SPLIT_POST_REND_CMD[:] @@ -309,7 +287,7 @@ def run_full_chain_split_rendering( if renderer_fmt == "BINAURAL_SPLIT_PCM": post_rend_cmd[7:7] = ["-im", str(split_md_file)] - run_isar_post_rend_cmd(post_rend_cmd) + run_isar_post_rend_cmd(post_rend_cmd, test_info=test_info) if test_info.config.option.create_cut: # CUT creation mode will run a comparison with REF @@ -374,25 +352,28 @@ def run_external_split_rendering( with TemporaryDirectory() as tmp_dir: tmp_dir = Path(tmp_dir) - cut_in_file = tmp_dir.joinpath("cut_input.wav") - split_bitstream = tmp_dir.joinpath("split.bit") + + renderer_fmt_for_filename = renderer_fmt.replace("BINAURAL_", "") + filename_base = f"{in_fmt}_{renderer_fmt_for_filename}_ext_cfg_{render_config.stem}_fr_pre_{pre_rend_fr}_post_{post_rend_fr}" + + if plc_error_pattern: + filename_base += f"_plc_{plc_error_pattern.stem}" + + split_bitstream_stem = f"{filename_base}.splt.bit" if renderer_fmt == "BINAURAL_SPLIT_PCM": - split_md_file = tmp_dir.joinpath("split_md.bin") + split_md_file_stem = f"{filename_base}.spltmd.bit" - renderer_fmt_for_filename = renderer_fmt.replace("BINAURAL_", "") - out_file_stem = f"{in_fmt}_{renderer_fmt_for_filename}_ext_cfg_{render_config.stem}_fr_pre_{pre_rend_fr}_post_{post_rend_fr}.wav" + out_file_stem = f"{filename_base}.wav" if test_info.config.option.create_ref: output_path_base = OUTPUT_PATH_REF else: output_path_base = OUTPUT_PATH_CUT + split_bitstream = output_path_base.joinpath(split_bitstream_stem) out_file = output_path_base.joinpath(out_file_stem) - - if plc_error_pattern: - out_file = out_file.with_stem( - f"{out_file.stem}_plc_{plc_error_pattern.stem}" - ) + if renderer_fmt == "BINAURAL_SPLIT_PCM": + split_md_file = output_path_base.joinpath(split_md_file_stem) # check for metadata files if in_fmt.upper().startswith("ISM") and "SBA" in in_fmt.upper(): @@ -403,7 +384,7 @@ def run_external_split_rendering( else: in_meta_files = None - # generate split-rendering bitstream + # run ISAR pre-renderer split_pre_cmd = SPLIT_PRE_REND_CMD[:] if test_info.config.option.create_ref: @@ -413,8 +394,7 @@ def run_external_split_rendering( # if in REF or CUT creation mode use the comparetestv if test_info.config.option.create_ref or test_info.config.option.create_cut: in_file = FORMAT_TO_FILE_COMPARETEST[in_fmt] - truncate_signal(in_file, cut_in_file) - + cut_in_file = in_file.with_stem(in_file.stem + "_cut") split_pre_cmd[6] = str(cut_in_file) else: split_pre_cmd[6] = str(FORMAT_TO_FILE_SMOKETEST[in_fmt]) @@ -430,9 +410,9 @@ def run_external_split_rendering( if in_meta_files: split_pre_cmd[9:9] = ["-im", *in_meta_files] - run_isar_ext_rend_cmd(split_pre_cmd) + run_isar_ext_rend_cmd(split_pre_cmd, test_info=test_info) - # run split renderer + # run ISAR post-renderer split_post_cmd = SPLIT_POST_REND_CMD[:] if test_info.config.option.create_ref: @@ -450,15 +430,11 @@ def run_external_split_rendering( if plc_error_pattern: split_post_cmd[1:1] = ["-prbfi", str(plc_error_pattern)] - run_isar_ext_rend_cmd(split_post_cmd) + run_isar_ext_rend_cmd(split_post_cmd, test_info=test_info) if test_info.config.option.create_cut: # CUT creation mode will run a comparison with REF out_file_ref = OUTPUT_PATH_REF.joinpath(out_file_stem) - if plc_error_pattern: - out_file_ref = out_file_ref.with_stem( - f"{out_file_ref.stem}_plc_{plc_error_pattern.stem}" - ) output_differs, reason = cmp_pcm( out_file,