Repository: claritychallenge/clarity (language: python)

Issue:
Consistent use of pathlib throughout codebase
Much of the file handling throughout the codebase could be improved by the use of pathlib

- places where paths are being built via ad-hoc string operations
- places where 'os' is being used where pathlib would be tidier
- places where the glob module could be replaced with pathlib.glob

For rationale see e.g. articles [here](https://towardsdatascience.com/why-you-should-start-using-pathlib-as-an-alternative-to-the-os-module-d9eccd994745)  and [here](https://treyhunner.com/2018/12/why-you-should-be-using-pathlib/)

Merging main into the branch
Merging main into this branch to catch it up prior to completing the PR


Discussion / hints:

Fix patch:
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
index af760092a..8dfd87d89 100644
--- a/.git-blame-ignore-revs
+++ b/.git-blame-ignore-revs
@@ -1,3 +1,26 @@
+# pathlib consistency (https://github.com/claritychallenge/clarity/pull/236)
+c2a4a8b9853a4f459b369b1bfcb5071f59a88cdb # Ignoring pathlib consistency commits from blame history
+3386ea686528fc04ef75b8451371ac1b2aa571a8 # Merge pull request #242 from claritychallenge/main
+90eb7f02d153e8c34db94591d8f2fdfaac60cc02 # Fixes to recipes/e029+e032_sheffield/prepare_data
+5200a5a361f47aaf66bff4378efa5b810b4532db # Fixes for enhancer/gha/gha_interface
+953f8e44a10b04410dd0443c7f3e9a523bf562f1 # Made final fixes for clarity/data/cec1_dataset
+38664e1c50d97bce58242245596bea37a8ccc7db # Made fixes for clarity/data/cec1_dataset
+b815b23158891e7e81193b19883d3b3a8edbeebe # Made fixes for clarity/predictor/torch_msbg
+f1f6075d260850ad2044ca06c7a1692a91a9686f # Made fixes for recipes/cec1/e009_sheffield
+14daec63384e5c0fb9de599256ed9e86c2da81d7 # Made fixes for recipes/cec1/baseline
+72cb8dbfee2bd1656ae71d11e3f228e54cc643d7 # Made fixes for cpc1/e029 and cpc/e032 train
+a68d98c15006e29614f138241245483398a1310e # Made fixes for cpc1/e029 and cpc/e032 infer
+4852633d4af38a3a3c827042968872cae8e251ee # Fixed files in tests/
+f1d7850df68d82cbbc4e3eb53c0c2074eac6084c # Fixed a bug introduced using Path(__file__)
+a5a247c675c948a8769568032ec9af7c274927e8 # Fixed files in recipes/cpc1/baseline
+6e5b53655441bf59c103d88d04d39427addac648 # Mixed files in clarity/data
+c6963d7041a372f193540217eb74890dbfc0d739 # pathlib for clarity/evaluator/msbg/msbg_utils.py
+6b83a96cd4ab5f4122b708a1f254a8792b222bb5 # Converted recipes/cpc1/e029_sheffield/prepare_data.py
+0b942c784d35791d43e1e2d61b984c935754e4a8 # Made fixes for cpc1/e029 and cpc/e032 evaluate
+6055023abadfb5e806b43d92de3ff3de62a50fad # Made fixes for recipes/cec2
+049588082b5566d816388f35a23eb00635c1e858 # Merge pull request #235 from claritychallenge/222-fix-issues-raised-by-pylint
+
+
 # pylint compliance (https://github.com/claritychallenge/clarity/pull/224)
 1c4f7def50b63e449c1292ebcb1072a333752dc2 # Ignoring commit that fix pylint errors
 bd5f3068d3d149a2c169bcf2fe1ba42e00f04c22 # Dealt with F6401 false positives, and final, final missed issues.
diff --git a/clarity/data/scene_renderer_cec1.py b/clarity/data/scene_renderer_cec1.py
index c3ae323cf..c5ac66a23 100644
--- a/clarity/data/scene_renderer_cec1.py
+++ b/clarity/data/scene_renderer_cec1.py
@@ -1,7 +1,7 @@
 """Scene rendering for CEC1 challenge."""
 import logging
 import math
-import os
+from pathlib import Path
 
 import numpy as np
 import soundfile
@@ -337,7 +337,5 @@ def check_scene_exists(scene: dict, output_path: str, num_channels: int) -> bool
             ]
         )
 
-    scene_exists = True
-    for filename in files_to_check:
-        scene_exists = scene_exists and os.path.exists(filename)
-    return scene_exists
+    # Return True if all files exist, False otherwise
+    return all(Path(filename).exists() for filename in files_to_check)
diff --git a/clarity/data/utils.py b/clarity/data/utils.py
index 1c93e88ef..77e4e5069 100644
--- a/clarity/data/utils.py
+++ b/clarity/data/utils.py
@@ -1,7 +1,7 @@
 """Utilities for data generation."""
 # pylint: disable=wrong-import-position
-import os
 import sys
+from pathlib import Path
 
 if sys.version_info >= (3, 8):
     from typing import Literal
@@ -15,9 +15,7 @@
 import scipy.io
 
 SPEECH_FILTER = scipy.io.loadmat(
-    os.path.join(
-        os.path.dirname(os.path.abspath(__file__)), "params", "speech_weight.mat"
-    ),
+    Path(__file__).parent / "params/speech_weight.mat",
     squeeze_me=True,
 )
 SPEECH_FILTER = np.array(SPEECH_FILTER["filt"])
diff --git a/clarity/dataset/cec1_dataset.py b/clarity/dataset/cec1_dataset.py
index b4a8e190c..55175601f 100644
--- a/clarity/dataset/cec1_dataset.py
+++ b/clarity/dataset/cec1_dataset.py
@@ -1,5 +1,5 @@
 import json
-import os
+from pathlib import Path
 
 import librosa
 import numpy as np
@@ -93,28 +93,24 @@ def lowpass_filtering(self, x):
         return lfilter(self.lowpass_filter, 1, x)
 
     def __getitem__(self, item):
+        scenes_folder = Path(self.scenes_folder)
         if self.num_channels == 2:
             mixed = read_wavfile(
-                os.path.join(
-                    self.scenes_folder, self.scene_list[item] + self.mixed_suffix
-                )
+                scenes_folder / (self.scene_list[item] + self.mixed_suffix)
             )
         elif self.num_channels == 6:
             mixed = []
             for suffix in self.mixed_suffix:
                 mixed.append(
-                    read_wavfile(
-                        os.path.join(self.scenes_folder, self.scene_list[item] + suffix)
-                    )
+                    read_wavfile(scenes_folder / (self.scene_list[item] + suffix))
                 )
             mixed = np.concatenate(mixed, axis=0)
         else:
             raise NotImplementedError
+        target = None
         if not self.testing:
             target = read_wavfile(
-                os.path.join(
-                    self.scenes_folder, self.scene_list[item] + self.target_suffix
-                )
+                scenes_folder / (self.scene_list[item] + self.target_suffix)
             )
 
         if self.sr != 44100:
@@ -124,7 +120,7 @@ def __getitem__(self, item):
                     librosa.resample(mixed[i], target_sr=44100, orig_sr=self.sr)
                 )
             mixed = np.array(mixed_resampled)
-            if not self.testing:
+            if target is not None:
                 for i in range(target.shape[0]):
                     target_resampled.append(
                         librosa.resample(target[i], target_sr=44100, orig_sr=self.sr)
@@ -137,7 +133,8 @@ def __getitem__(self, item):
         if self.norm:
             mixed_max = np.max(np.abs(mixed))
             mixed = mixed / mixed_max
-            target = target / mixed_max
+            if target is not None:
+                target = target / mixed_max
 
         if not self.testing:
             return_data = (
diff --git a/clarity/enhancer/gha/gha_interface.py b/clarity/enhancer/gha/gha_interface.py
index ebf534be8..fb955263c 100644
--- a/clarity/enhancer/gha/gha_interface.py
+++ b/clarity/enhancer/gha/gha_interface.py
@@ -3,6 +3,8 @@
 import pathlib
 import subprocess
 import tempfile
+from pathlib import Path
+from typing import Union
 
 import numpy as np
 import soundfile
@@ -114,10 +116,8 @@ def process_files(self, infile_names, outfile_name, audiogram, listener=None):
         )
         formatted_sGt = format_gaintable(gaintable, noisegate_corr=True)
 
-        cfg_template = os.path.join(
-            os.path.dirname(os.path.abspath(__file__)),
-            "cfg_files",
-            f"{self.cfg_file}_template.cfg",
+        cfg_template = (
+            Path(__file__).parent / f"cfg_files/{self.cfg_file}_template.cfg",
         )
 
         # Merge CH1 and CH3 files. This is the baseline configuration.
@@ -178,7 +178,12 @@ def process_files(self, infile_names, outfile_name, audiogram, listener=None):
         logging.info("OpenMHA processing complete")
 
     def read_signal(
-        self, filename, offset=0, nsamples=-1, nchannels=0, offset_is_samples=False
+        self,
+        filename: Union[str, Path],
+        offset: int = 0,
+        nsamples: int = -1,
+        nchannels: int = 0,
+        offset_is_samples: bool = False,
     ):
         """Read a wavefile and return as numpy array of floats.
 
@@ -212,7 +217,9 @@ def read_signal(
 
         return x
 
-    def write_signal(self, filename, x, floating_point=True):
+    def write_signal(
+        self, filename: Union[str, Path], x, floating_point: bool = True
+    ) -> None:
         """Write a signal as fixed or floating point wav file."""
 
         if floating_point is False:
diff --git a/clarity/evaluator/msbg/msbg_utils.py b/clarity/evaluator/msbg/msbg_utils.py
index bede043ec..cceddded7 100644
--- a/clarity/evaluator/msbg/msbg_utils.py
+++ b/clarity/evaluator/msbg/msbg_utils.py
@@ -2,7 +2,7 @@
 import json
 import logging
 import math
-import os
+from pathlib import Path
 from typing import Dict, Optional, Tuple, Union
 
 import numpy as np
@@ -103,9 +103,8 @@ def read_gtf_file(gtf_file: str) -> Dict:
     """
 
     # Fix filename if necessary
-    dirname = os.path.dirname(os.path.abspath(__file__))
-    gtf_file = os.path.join(dirname, gtf_file)
-    with open(gtf_file, "r", encoding="utf-8") as fp:
+    gtf_file_path = Path(__file__).parent / gtf_file
+    with gtf_file_path.open("r", encoding="utf-8") as fp:
         data = json.load(fp)
     for key in data:
         if isinstance(data[key], list):
@@ -508,7 +507,7 @@ def pad(signal, length):
 
 
 def read_signal(
-    filename: str,
+    filename: Union[str, Path],
     offset: int = 0,
     nsamples: int = -1,
     nchannels: int = 0,
@@ -517,7 +516,7 @@ def read_signal(
     """Read a wavefile and return as numpy array of floats.
 
     Args:
-        filename (string): Name of file to read
+        filename (str|Path): Name of file to read
         offset (int, optional): Offset in samples or seconds (from start). Default is 0.
         nsamples (int): Number of samples.
         nchannels (int): expected number of channel (default: 0 = any number OK)
@@ -551,7 +550,7 @@ def read_signal(
 
 
 def write_signal(
-    filename: str,
+    filename: Union[str, Path],
     signal: np.ndarray,
     sample_frequency: float,
     floating_point: bool = True,
@@ -559,7 +558,7 @@ def write_signal(
     """Write a signal as fixed or floating point wav file.
 
     Args:
-        filename (str): name of file in to write to.
+        filename (str|Path): name of file in to write to.
         signal (ndarray): signal to write.
         sample_frequency (float): sampling frequency.
         floating_point (bool): write as floating point else an ints (default: True).
diff --git a/clarity/predictor/torch_msbg.py b/clarity/predictor/torch_msbg.py
index 578e02d82..aaa136c44 100644
--- a/clarity/predictor/torch_msbg.py
+++ b/clarity/predictor/torch_msbg.py
@@ -2,7 +2,7 @@
 An FIR-based torch implementation of approximated MSBG hearing loss model
 """
 import json
-import os
+from pathlib import Path
 
 import numpy as np
 import torch
@@ -26,57 +26,57 @@
 # old msbg matlab
 # set RMS so that peak of output file so that no clipping occurs, set so that
 # equiv0dBfileSPL > 100dB for LOUD input files
-ref_RMSdB = -31.2
+REF_RMS_DB = -31.2
 
 # what RMS of INPUT speech file translates to in real world (unweighted)
-calib_dBSPL = 65
+CALIB_DB_SPL = 65
 
 # what 0dB file signal would translate to in dB SPL:
 # constant for cochlear_simulate function
-equiv0dBfileSPL = calib_dBSPL - ref_RMSdB
+EQUIV_0_DB_FILE_SPL = CALIB_DB_SPL - REF_RMS_DB
 
 # clarity msbg
-equiv0dBSPL = 100
-ahr = 20
-equiv_0dB_SPL = equiv0dBSPL + ahr
+EQUIV_0_DB_SPL = 100
+AHR = 20
+EQUIV_0_DB_SPL = EQUIV_0_DB_SPL + AHR
 
 
-def generate_key_percent(signal, thr_dB, winlen):
-    if winlen != np.floor(winlen):
-        winlen = np.int(np.floor(winlen))
+def generate_key_percent(signal, thr_db, win_len):
+    if win_len != np.floor(win_len):
+        win_len = np.int(np.floor(win_len))
         print("\nGenerate_key_percent: \t Window length must be integer")
 
-    siglen = len(signal)
-    expected = thr_dB.copy()  # expected threshold
+    signal_len = len(signal)
+    expected = thr_db.copy()  # expected threshold
     non_zero = 10.0 ** ((expected - 30) / 10)  # put floor into histogram distribution
 
-    nframes = 0
-    totframes = np.int(np.floor(siglen / winlen))
-    every_dB = np.zeros(totframes)
+    n_frames = 0
+    total_frames = np.int(np.floor(signal_len / win_len))
+    every_db = np.zeros(total_frames)
 
-    for ix in range(totframes):
-        start = ix * winlen
-        this_sum = np.sum(signal[start : start + winlen] ** 2)  # sum of squares
-        every_dB[nframes] = 10 * np.log10(non_zero + this_sum / winlen)
-        nframes += 1
+    for ix in range(total_frames):
+        start = ix * win_len
+        this_sum = np.sum(signal[start : start + win_len] ** 2)  # sum of squares
+        every_db[n_frames] = 10 * np.log10(non_zero + this_sum / win_len)
+        n_frames += 1
 
-    used_thr_dB = expected.copy()
+    used_thr_db = expected.copy()
 
     # histogram should produce a two-peaked curve: thresh should be set in valley
     # between the two peaks, and set a bit above that, as it heads for main peak
-    frame_idx = np.where(every_dB >= expected)[0]
+    frame_idx = np.where(every_db >= expected)[0]
     valid_frames = len(frame_idx)
-    key = np.zeros(valid_frames * winlen, dtype=np.int)
+    key = np.zeros(valid_frames * win_len, dtype=np.int)
 
     # convert frame numbers into indices for signal
     for ix in range(valid_frames):
-        key[ix * winlen : ix * winlen + winlen] = np.arange(
-            frame_idx[ix] * winlen, frame_idx[ix] * winlen + winlen, dtype=np.int
+        key[ix * win_len : ix * win_len + win_len] = np.arange(
+            frame_idx[ix] * win_len, frame_idx[ix] * win_len + win_len, dtype=np.int
         )
-    return key, used_thr_dB
+    return key, used_thr_db
 
 
-def measure_rms(signal, sr, dB_rel_rms):
+def measure_rms(signal, sr, db_rel_rms):
     """Compute RMS level of a signal.
 
     Measures total power of all 10 msec frames that are above a user-specified threshold
@@ -84,7 +84,7 @@ def measure_rms(signal, sr, dB_rel_rms):
     Args:
         signal: input signal
         sr: sampling rate
-        dB_rel_rms: threshold relative to first-stage rms (if it is made of a 2*1 array,
+        db_rel_rms: threshold relative to first-stage rms (if it is made of a 2*1 array,
             second value over rules. only single value supported currently)
 
     Returns:
@@ -95,35 +95,35 @@ def measure_rms(signal, sr, dB_rel_rms):
     # first RMS is of all signal
     first_stage_rms = np.sqrt(np.mean(signal**2))
     # use this RMS to generate key threshold to more accurate RMS
-    key_thr_dB = np.max([20 * np.log10(first_stage_rms) + dB_rel_rms, -80])
-    key, used_thr_dB = generate_key_percent(
-        signal, key_thr_dB, np.int(np.round(win_secs * sr))
+    key_thr_db = np.max([20 * np.log10(first_stage_rms) + db_rel_rms, -80])
+    key, used_thr_db = generate_key_percent(
+        signal, key_thr_db, np.int(np.round(win_secs * sr))
     )
     # active = 100.0 * len(key) / len(signal)
     rms = np.sqrt(np.mean(signal[key] ** 2))
-    rel_dB_thresh = used_thr_dB - 20 * np.log10(rms)
-    return rms, key, rel_dB_thresh
+    rel_db_thresh = used_thr_db - 20 * np.log10(rms)
+    return rms, key, rel_db_thresh
 
 
 def makesmearmat3(rl, ru, sr):
-    fftsize = 512
-    nyquist = np.int(fftsize // 2)
-    fnor = audfilt(1, 1, nyquist, sr)
-    fwid = audfilt(rl, ru, nyquist, sr)
-    fnext = np.hstack([fnor, np.zeros([nyquist, nyquist // 2])])
+    fft_size = 512
+    nyquist = np.int(fft_size // 2)
+    f_nor = audfilt(1, 1, nyquist, sr)
+    f_wid = audfilt(rl, ru, nyquist, sr)
+    f_next = np.hstack([f_nor, np.zeros([nyquist, nyquist // 2])])
 
     for i in np.arange(nyquist // 2 + 1, nyquist + 1, dtype=np.int):
-        fnext[i - 1, nyquist : np.min([2 * i - 1, 3 * nyquist // 2])] = np.flip(
-            fnor[
+        f_next[i - 1, nyquist : np.min([2 * i - 1, 3 * nyquist // 2])] = np.flip(
+            f_nor[
                 i - 1, np.max([1, 2 * i - 3 * nyquist // 2]) - 1 : (2 * i - nyquist - 1)
             ]
         )
-    fsmear = np.linalg.lstsq(fnext, fwid)[
+    f_smear = np.linalg.lstsq(f_next, f_wid)[
         0
     ]  # https://stackoverflow.com/questions/33559946/numpy-vs-mldivide-matlab-operator
-    fsmear = fsmear[:nyquist, :]
+    f_smear = f_smear[:nyquist, :]
 
-    return fsmear
+    return f_smear
 
 
 def audfilt(rl, ru, size, sr):
@@ -144,17 +144,17 @@ def audfilt(rl, ru, size, sr):
 
     g = np.zeros(size)
     for i in np.arange(2, size + 1, 1, dtype=np.int):
-        fhz = (i - 1) * sr / (2 * size)
-        erbhz = 24.7 * ((fhz * 0.00437) + 1)
-        pl = 4 * fhz / (erbhz * rl)
-        pu = 4 * fhz / (erbhz * ru)
+        f_hz = (i - 1) * sr / (2 * size)
+        erb_hz = 24.7 * ((f_hz * 0.00437) + 1)
+        pl = 4 * f_hz / (erb_hz * rl)
+        pu = 4 * f_hz / (erb_hz * ru)
         j = np.arange(1, i, dtype=np.int)
         g[j - 1] = np.abs((i - j) / (i - 1))
         aud_filter[i - 1, j - 1] = (1 + (pl * g[j - 1])) * np.exp(-pl * g[j - 1])
         j = np.arange(i, size + 1, dtype=np.int)
         g[j - 1] = np.abs((i - j) / (i - 1))
         aud_filter[i - 1, j - 1] = (1 + (pu * g[j - 1])) * np.exp(-pu * g[j - 1])
-        aud_filter[i - 1, :] = aud_filter[i - 1, :] / (erbhz * (rl + ru) / (2 * 24.7))
+        aud_filter[i - 1, :] = aud_filter[i - 1, :] / (erb_hz * (rl + ru) / (2 * 24.7))
     return aud_filter
 
 
@@ -165,14 +165,14 @@ def __init__(
         audiometric,
         sr=44100,
         spl_cali=True,
-        src_posn="ff",
+        src_position="ff",
         kernel_size=1025,
         device=None,
     ):
         super().__init__()
         self.sr = sr
         self.spl_cali = spl_cali
-        self.src_posn = src_posn
+        self.src_position = src_position
         self.kernel_size = kernel_size
         if device is None:
             self.device = "cuda" if torch.cuda.is_available() else "cpu"
@@ -193,16 +193,16 @@ def __init__(
             np.array([0.125, 0.25, 0.5, 0.75, 1, 1.5, 2, 3, 4, 6, 8, 10, 12, 14, 16])
             * 1000
         )
-        interpf = interp1d(audiometric, audiogram)
-        audiogram = interpf(audiogram_cfs)
+        interp_f = interp1d(audiometric, audiogram)
+        audiogram = interp_f(audiogram_cfs)
 
         # settings for src_to_cochlea_filt
 
-        if src_posn == "ff":
+        if src_position == "ff":
             src_corrn = FF_ED
-        elif src_posn == "df":
+        elif src_position == "df":
             src_corrn = DF_ED
-        elif src_posn == "ITU":
+        elif src_position == "ITU":
             interf_itu = interp1d(ITU_HZ, ITU_ERP_DRP)
             src_corrn = interf_itu(HZ)
         nyquist = sr / 2
@@ -215,20 +215,24 @@ def __init__(
         corrn_forward = 10 ** (0.05 * corrn_used)
         corrn_backward = 10 ** (0.05 * -1 * corrn_used)
         n_wdw = np.int(2 * np.floor((sr / 16e3) * 368 / 2))
-        coch_filter_forward = firwin2(
+        cochlear_filter_forward = firwin2(
             n_wdw + 1, hz_used / nyquist, corrn_forward, window=("kaiser", 4)
         )
-        coch_filter_backward = firwin2(
+        cochlear_filter_backward = firwin2(
             n_wdw + 1, hz_used / nyquist, corrn_backward, window=("kaiser", 4)
         )
-        self.coch_padding = len(coch_filter_forward) // 2
-        self.coch_filter_forward = (
-            torch.tensor(coch_filter_forward, dtype=torch.float32, device=self.device)
+        self.cochlear_padding = len(cochlear_filter_forward) // 2
+        self.cochlear_filter_forward = (
+            torch.tensor(
+                cochlear_filter_forward, dtype=torch.float32, device=self.device
+            )
             .unsqueeze(0)
             .unsqueeze(1)
         )
-        self.coch_filter_backward = (
-            torch.tensor(coch_filter_backward, dtype=torch.float32, device=self.device)
+        self.cochlear_filter_backward = (
+            torch.tensor(
+                cochlear_filter_backward, dtype=torch.float32, device=self.device
+            )
             .unsqueeze(0)
             .unsqueeze(1)
         )
@@ -248,44 +252,36 @@ def __init__(
         # impairment degree affects smearing simulation, and now recruitment,
         # (assuming we do not have too much SEVERE losses present)
 
-        current_dir = os.path.dirname(os.path.abspath(__file__))
-        gtf_dir = os.path.join(current_dir, "../evaluator/msbg/msbg_hparams")
+        current_dir = Path(__file__).parent
+        gtf_dir = current_dir / "../evaluator/msbg/msbg_hparams"
         if impaired_degree > 56:
             severe_not_moderate = 1
-            GT4Bankfile = os.path.join(
-                gtf_dir, "GT4FBank_Brd3.0E_Spaced2.3E_44100Fs.json"
-            )
+            gt4_bank_file = gtf_dir / "GT4FBank_Brd3.0E_Spaced2.3E_44100Fs.json"
             bw_broaden_coef = 3
         elif impaired_degree > 35:
             severe_not_moderate = 0
-            GT4Bankfile = os.path.join(
-                gtf_dir, "GT4FBank_Brd2.0E_Spaced1.5E_44100Fs.json"
-            )
+            gt4_bank_file = gtf_dir / "GT4FBank_Brd2.0E_Spaced1.5E_44100Fs.json"
             bw_broaden_coef = 2
         elif impaired_degree > 15:
             severe_not_moderate = -1
-            GT4Bankfile = os.path.join(
-                gtf_dir, "GT4FBank_Brd1.5E_Spaced1.1E_44100Fs.json"
-            )
+            gt4_bank_file = gtf_dir / "GT4FBank_Brd1.5E_Spaced1.1E_44100Fs.json"
             bw_broaden_coef = 1
         else:
             severe_not_moderate = -2
-            GT4Bankfile = os.path.join(
-                gtf_dir, "GT4FBank_Brd1.5E_Spaced1.1E_44100Fs.json"
-            )
+            gt4_bank_file = gtf_dir / "GT4FBank_Brd1.5E_Spaced1.1E_44100Fs.json"
             bw_broaden_coef = 1
-        # GT4Bank = loadmat(GT4Bankfile)
-        with open(GT4Bankfile, "r", encoding="utf-8") as fp:
-            GT4Bank = json.load(fp)
+        # gt4_bank = loadmat(gt4_bank_file)
+        with gt4_bank_file.open("r", encoding="utf-8") as fp:
+            gt4_bank = json.load(fp)
 
         if severe_not_moderate > 0:
-            fsmear = makesmearmat3(4, 2, sr)
+            f_smear = makesmearmat3(4, 2, sr)
         elif severe_not_moderate == 0:
-            fsmear = makesmearmat3(2.4, 1.6, sr)
+            f_smear = makesmearmat3(2.4, 1.6, sr)
         elif severe_not_moderate == -1:
-            fsmear = makesmearmat3(1.6, 1.1, sr)
+            f_smear = makesmearmat3(1.6, 1.1, sr)
         elif severe_not_moderate == -2:
-            fsmear = makesmearmat3(1.001, 1.001, sr)
+            f_smear = makesmearmat3(1.001, 1.001, sr)
 
         self.smear_nfft = 512
         self.smear_win_len = 256
@@ -303,83 +299,85 @@ def __init__(
         self.smear_window = torch.tensor(
             smear_window, dtype=torch.float32, device=self.device
         )
-        self.fsmear = torch.tensor(fsmear, dtype=torch.float32, device=self.device)
+        self.f_smear = torch.tensor(f_smear, dtype=torch.float32, device=self.device)
 
         """ settings for recruitment"""
-        cf_expnsn = 0 * np.array(GT4Bank["GTn_CentFrq"])
-        eq_loud_db = 0 * np.array(GT4Bank["GTn_CentFrq"])
-        for ix_cfreq in range(len(GT4Bank["GTn_CentFrq"])):
-            if GT4Bank["GTn_CentFrq"][ix_cfreq] < audiogram_cfs[0]:
-                cf_expnsn[ix_cfreq] = catch_up / (catch_up - audiogram[0])
-            elif GT4Bank["GTn_CentFrq"][ix_cfreq] > audiogram_cfs[-1]:
-                cf_expnsn[ix_cfreq] = catch_up / (catch_up - audiogram[-1])
+        cf_expansion = 0 * np.array(gt4_bank["GTn_CentFrq"])
+        eq_loud_db = 0 * np.array(gt4_bank["GTn_CentFrq"])
+        for ix_cfreq in range(len(gt4_bank["GTn_CentFrq"])):
+            if gt4_bank["GTn_CentFrq"][ix_cfreq] < audiogram_cfs[0]:
+                cf_expansion[ix_cfreq] = catch_up / (catch_up - audiogram[0])
+            elif gt4_bank["GTn_CentFrq"][ix_cfreq] > audiogram_cfs[-1]:
+                cf_expansion[ix_cfreq] = catch_up / (catch_up - audiogram[-1])
             else:
-                interp_audiog = interp1d(audiogram_cfs, audiogram)
-                audiog_cf = interp_audiog(GT4Bank["GTn_CentFrq"][ix_cfreq])
-                cf_expnsn[ix_cfreq] = catch_up / (catch_up - audiog_cf)
+                interp_audiogram = interp1d(audiogram_cfs, audiogram)
+                audiog_cf = interp_audiogram(gt4_bank["GTn_CentFrq"][ix_cfreq])
+                cf_expansion[ix_cfreq] = catch_up / (catch_up - audiog_cf)
             eq_loud_db[ix_cfreq] = catch_up
 
-        self.nchans = GT4Bank["NChans"]
+        self.n_chans = gt4_bank["NChans"]
         self.gtn_denoms = torch.tensor(
-            GT4Bank["GTn_denoms"], dtype=torch.float32, device=self.device
+            gt4_bank["GTn_denoms"], dtype=torch.float32, device=self.device
         )
         self.gtn_nums = torch.tensor(
-            GT4Bank["GTn_nums"], dtype=torch.float32, device=self.device
+            gt4_bank["GTn_nums"], dtype=torch.float32, device=self.device
         )
         self.hp_denoms = torch.tensor(
-            GT4Bank["HP_denoms"], dtype=torch.float32, device=self.device
+            gt4_bank["HP_denoms"], dtype=torch.float32, device=self.device
         )
         self.hp_nums = torch.tensor(
-            GT4Bank["HP_nums"], dtype=torch.float32, device=self.device
+            gt4_bank["HP_nums"], dtype=torch.float32, device=self.device
         )
-        self.ngamma = int(GT4Bank["NGAMMA"])
-        self.gtn_delays = GT4Bank["GTnDelays"]
-        self.start2polehp = GT4Bank["Start2PoleHP"]
+        self.ngamma = int(gt4_bank["NGAMMA"])
+        self.gtn_delays = gt4_bank["GTnDelays"]
+        self.start_2_pole_hp = gt4_bank["Start2PoleHP"]
 
-        erbn_centfrq = GT4Bank["ERBn_CentFrq"]
-        chan_lpfB = []
-        chan_lpfA = []
+        erbn_centre_freq = gt4_bank["ERBn_CentFrq"]
+        chan_lpf_b = []
+        chan_lpf_a = []
         fir_lpf = []
-        for ixch in range(self.nchans):
-            fc_envlp = (30 / 40) * np.min([100, erbn_centfrq[ixch]])
-            chan_lpfB_ch, chan_lpfA_ch = ellip(2, 0.25, 35, fc_envlp / (self.sr / 2))
-            chan_lpfB.append(chan_lpfB_ch)
-            chan_lpfA.append(chan_lpfA_ch)
+        for ixch in range(self.n_chans):
+            fc_envelope = (30 / 40) * np.min([100, erbn_centre_freq[ixch]])
+            chan_lpf_b_ch, chan_lpf_a_ch = ellip(
+                2, 0.25, 35, fc_envelope / (self.sr / 2)
+            )
+            chan_lpf_b.append(chan_lpf_b_ch)
+            chan_lpf_a.append(chan_lpf_a_ch)
             fir_lpf_ch = firwin(
-                self.kernel_size, fc_envlp / (self.sr / 2), pass_zero="lowpass"
+                self.kernel_size, fc_envelope / (self.sr / 2), pass_zero="lowpass"
             ) / np.sqrt(
                 2
             )  # sqrt(2) is for the consistency with IIR
             fir_lpf.append(fir_lpf_ch)
-        self.chan_lpfB = torch.tensor(
-            np.array(chan_lpfB), dtype=torch.float32, device=self.device
+        self.chan_lpf_b = torch.tensor(
+            np.array(chan_lpf_b), dtype=torch.float32, device=self.device
         )
-        self.chan_lpfA = torch.tensor(
-            np.array(chan_lpfA), dtype=torch.float32, device=self.device
+        self.chan_lpf_a = torch.tensor(
+            np.array(chan_lpf_a), dtype=torch.float32, device=self.device
         )
         self.fir_lpf = torch.tensor(
             np.array(fir_lpf), dtype=torch.float32, device=self.device
         ).unsqueeze(1)
 
-        self.expnsn_m1 = torch.tensor(
-            cf_expnsn - 1, dtype=torch.float32, device=self.device
+        self.expansion_m1 = torch.tensor(
+            cf_expansion - 1, dtype=torch.float32, device=self.device
         )
         # self.envlp_max = torch.tensor(10 ** (0.05 * (eq_loud_db - equiv0dBfileSPL)),
         # dtype=torch.float32, device=self.device)
-        self.envlp_max = torch.tensor(
-            10 ** (0.05 * (eq_loud_db - equiv_0dB_SPL)),
+        self.envelope_max = torch.tensor(
+            10 ** (0.05 * (eq_loud_db - EQUIV_0_DB_SPL)),
             dtype=torch.float32,
             device=self.device,
         )
 
-        recombination_dB = GT4Bank["Recombination_dB"]
-        self.recruitmnet_out_coef = torch.tensor(
-            10 ** (-0.05 * recombination_dB), dtype=torch.float32, device=self.device
+        recombination_db = gt4_bank["Recombination_dB"]
+        self.recruitment_out_coef = torch.tensor(
+            10 ** (-0.05 * recombination_db), dtype=torch.float32, device=self.device
         )
 
         "settings for FIR Gammatone Filters"
-        gt_cfreq = np.array(GT4Bank["GTn_CentFrq"])
-        gt_bw = np.array(GT4Bank["ERBn_CentFrq"]) * 1.1019 * bw_broaden_coef
+        gt_cfreq = np.array(gt4_bank["GTn_CentFrq"])
+        gt_bw = np.array(gt4_bank["ERBn_CentFrq"]) * 1.1019 * bw_broaden_coef
 
         self.padding = (self.kernel_size - 1) // 2
         n_lin = torch.linspace(
@@ -414,20 +412,20 @@ def __init__(
         self.peaks = torch.argmax(gammatone, dim=1)  # for gammatone delay calibration
 
         gammatone_sin = kernel * carrier_sin
-        filters = (gammatone * window_).view(self.nchans, 1, self.kernel_size)
+        filters = (gammatone * window_).view(self.n_chans, 1, self.kernel_size)
         # To get the normalised amplitude
         filters = filters.squeeze(1).cpu().numpy()
-        fr_max = np.zeros(self.nchans)
-        for i in range(self.nchans):
+        fr_max = np.zeros(self.n_chans)
+        for i in range(self.n_chans):
             fr = np.abs(fft(filters[i]))
             fr_ = fr[: int(self.kernel_size / 2)]
             fr_max[i] = np.max(fr_)
         amp = torch.tensor(fr_max, dtype=torch.float32, device=self.device)
         gammatone = gammatone / amp.unsqueeze(1)
         gammatone_sin = gammatone_sin / amp.unsqueeze(1)
-        self.gt_fir = (gammatone * window_).view(self.nchans, 1, self.kernel_size)
+        self.gt_fir = (gammatone * window_).view(self.n_chans, 1, self.kernel_size)
         self.gt_fir_sin = (gammatone_sin * window_).view(
-            self.nchans, 1, self.kernel_size
+            self.n_chans, 1, self.kernel_size
         )
 
         "settings for spl calibration"
@@ -437,8 +435,8 @@ def __init__(
 
     def measure_rms(self, wav):
         bs = wav.shape[0]
-        ave_rms = torch.sqrt(torch.mean(wav**2, dim=1) + EPS)
-        thr_db = 20 * torch.log10(ave_rms + EPS) + self.db_relative_rms
+        average_rms = torch.sqrt(torch.mean(wav**2, dim=1) + EPS)
+        threshold_db = 20 * torch.log10(average_rms + EPS) + self.db_relative_rms
 
         num_frames = wav.shape[1] // self.win_len
         wav_reshaped = torch.reshape(
@@ -448,7 +446,7 @@ def measure_rms(self, wav):
 
         key_frames = (
             torch.where(
-                db_frames > thr_db.unsqueeze(1),
+                db_frames > threshold_db.unsqueeze(1),
                 torch.tensor(1, dtype=torch.float32, device=self.device),
                 torch.tensor(0, dtype=torch.float32, device=self.device),
             )
@@ -465,15 +463,17 @@ def measure_rms(self, wav):
 
     def calibrate_spl(self, x):
         if self.spl_cali:
-            levelreFS = 10 * torch.log10(torch.mean(x**2, dim=1, keepdim=True) + EPS)
-            leveldBSPL = equiv_0dB_SPL + levelreFS
+            level_re_fs = 10 * torch.log10(
+                torch.mean(x**2, dim=1, keepdim=True) + EPS
+            )
+            level_db_spl = EQUIV_0_DB_SPL + level_re_fs
             rms = self.measure_rms(x)
-            change_dB = leveldBSPL - (equiv_0dB_SPL + 20 * torch.log10(rms + EPS))
-            x = x * 10 ** (0.05 * change_dB)
+            change_db = level_db_spl - (EQUIV_0_DB_SPL + 20 * torch.log10(rms + EPS))
+            x = x * 10 ** (0.05 * change_db)
         return x
 
-    def src_to_cochlea_filt(self, x, coch_filter):
-        return F.conv1d(x, coch_filter, padding=self.coch_padding)
+    def src_to_cochlea_filt(self, x, cochlear_filter):
+        return F.conv1d(x, cochlear_filter, padding=self.cochlear_padding)
 
     def smear(self, x):
         """Padding issue needs to be worked out"""
@@ -493,7 +493,7 @@ def smear(self, x):
         phasor = spec[:, : self.smear_nfft // 2, :, :] / (mag + EPS)
 
         smeared_power = (
-            torch.matmul(power.transpose(-1, -2), self.fsmear.transpose(0, 1))
+            torch.matmul(power.transpose(-1, -2), self.f_smear.transpose(0, 1))
             .transpose(-1, -2)
             .unsqueeze(-1)
             + EPS
@@ -517,10 +517,10 @@ def smear(self, x):
         return smeared_wav.unsqueeze(1)
 
     def recruitment(self, x):
-        nsamps = x.shape[-1]
+        n_samples = x.shape[-1]
         ixhp = 0
         outputs = []
-        for ixch in range(self.nchans):
+        for ixch in range(self.n_chans):
             # Gammaton filtering
             pass_n = torchaudio.functional.lfilter(
                 x, self.gtn_denoms[ixch, :], self.gtn_nums[ixch, :]
@@ -532,71 +532,77 @@ def recruitment(self, x):
             dly = self.gtn_delays[ixch]
 
             pass_n_cali = torch.zeros_like(pass_n)
-            pass_n_cali[:, :, : nsamps - dly] = pass_n[:, :, dly:nsamps]
+            pass_n_cali[:, :, : n_samples - dly] = pass_n[:, :, dly:n_samples]
             # Tail control
-            if ixch >= self.start2polehp:
+            if ixch >= self.start_2_pole_hp:
                 ixhp += 1
                 pass_n_cali = torchaudio.functional.lfilter(
                     pass_n_cali, self.hp_denoms[ixhp - 1, :], self.hp_nums[ixhp - 1, :]
                 )
 
             # Get the envelope
-            envlp_out = torchaudio.functional.lfilter(
-                torch.abs(pass_n_cali), self.chan_lpfA[ixch, :], self.chan_lpfB[ixch, :]
+            envelope_out = torchaudio.functional.lfilter(
+                torch.abs(pass_n_cali),
+                self.chan_lpf_a[ixch, :],
+                self.chan_lpf_b[ixch, :],
             )
-            envlp_out = torch.flip(envlp_out, dims=[-1])
-            envlp_out = torchaudio.functional.lfilter(
-                envlp_out, self.chan_lpfA[ixch, :], self.chan_lpfB[ixch, :]
+            envelope_out = torch.flip(envelope_out, dims=[-1])
+            envelope_out = torchaudio.functional.lfilter(
+                envelope_out, self.chan_lpf_a[ixch, :], self.chan_lpf_b[ixch, :]
             )
-            envlp_out = torch.flip(envlp_out, dims=[-1])
+            envelope_out = torch.flip(envelope_out, dims=[-1])
 
-            envlp_out = torch.clamp(envlp_out, min=EPS, max=self.envlp_max[ixch])
-            gain = (envlp_out / self.envlp_max[ixch]) ** self.expnsn_m1[ixch]
+            envelope_out = torch.clamp(
+                envelope_out, min=EPS, max=self.envelope_max[ixch]
+            )
+            gain = (envelope_out / self.envelope_max[ixch]) ** self.expansion_m1[ixch]
             outputs.append(gain * pass_n_cali)
 
         y = torch.stack(outputs, dim=-1).sum(dim=-1)
-        y = y * self.recruitmnet_out_coef
+        y = y * self.recruitment_out_coef
         return y
 
     def recruitment_fir(self, x):
-        nsamps = x.shape[-1]
-        x = x.repeat([1, self.nchans, 1])
+        n_samples = x.shape[-1]
+        x = x.repeat([1, self.n_chans, 1])
         real = F.conv1d(
-            x, self.gt_fir, bias=None, padding=self.padding, groups=self.nchans
+            x, self.gt_fir, bias=None, padding=self.padding, groups=self.n_chans
         )
         imag = F.conv1d(
-            x, self.gt_fir_sin, bias=None, padding=self.padding, groups=self.nchans
+            x, self.gt_fir_sin, bias=None, padding=self.padding, groups=self.n_chans
         )
         real_cali = torch.zeros_like(real)
         imag_cali = torch.zeros_like(imag)
-        for i in range(self.nchans):
-            real_cali[:, i, : nsamps - self.peaks[i]] = real[
-                :, i, self.peaks[i] : nsamps
+        for i in range(self.n_chans):
+            real_cali[:, i, : n_samples - self.peaks[i]] = real[
+                :, i, self.peaks[i] : n_samples
             ]
-            imag_cali[:, i, : nsamps - self.peaks[i]] = imag[
-                :, i, self.peaks[i] : nsamps
+            imag_cali[:, i, : n_samples - self.peaks[i]] = imag[
+                :, i, self.peaks[i] : n_samples
             ]
 
         env = torch.sqrt(real_cali * real_cali + imag_cali * imag_cali + EPS)
         env = F.conv1d(
-            env, self.fir_lpf, bias=None, padding=self.padding, groups=self.nchans
+            env, self.fir_lpf, bias=None, padding=self.padding, groups=self.n_chans
         )
 
-        env_max = self.envlp_max.unsqueeze(0).unsqueeze(-1).repeat([1, 1, nsamps])
+        env_max = self.envelope_max.unsqueeze(0).unsqueeze(-1).repeat([1, 1, n_samples])
         gain = torch.clamp(env / env_max, min=EPS, max=1)
-        gain = gain ** self.expnsn_m1.unsqueeze(0).unsqueeze(-1).repeat([1, 1, nsamps])
+        gain = gain ** self.expansion_m1.unsqueeze(0).unsqueeze(-1).repeat(
+            [1, 1, n_samples]
+        )
         y = torch.sum(gain * real_cali, dim=1, keepdim=True)
-        y = y * self.recruitmnet_out_coef
+        y = y * self.recruitment_out_coef
         return y
 
     def forward(self, x):
         x = self.calibrate_spl(x)
         x = x.unsqueeze(1)
-        x = self.src_to_cochlea_filt(x, self.coch_filter_forward)
+        x = self.src_to_cochlea_filt(x, self.cochlear_filter_forward)
         x = self.smear(x)
         # x = self.recruitment(x)
         x = self.recruitment_fir(x)
-        y = self.src_to_cochlea_filt(x, self.coch_filter_backward)
+        y = self.src_to_cochlea_filt(x, self.cochlear_filter_backward)
         return y.squeeze(1)
 
 
diff --git a/recipes/cec1/baseline/enhance.py b/recipes/cec1/baseline/enhance.py
index 5ae0e339c..44525d00a 100644
--- a/recipes/cec1/baseline/enhance.py
+++ b/recipes/cec1/baseline/enhance.py
@@ -1,5 +1,5 @@
 import json
-import os
+from pathlib import Path
 
 import hydra
 import numpy as np
@@ -12,11 +12,11 @@
 
 @hydra.main(config_path=".", config_name="config")
 def enhance(cfg: DictConfig) -> None:
-    enhanced_folder = os.path.join(cfg["path"]["exp_folder"], "enhanced_signals")
-    os.makedirs(enhanced_folder, exist_ok=True)
-    with open(cfg["path"]["scenes_listeners_file"], "r", encoding="utf-8") as fp:
+    enhanced_folder = Path(cfg.path.exp_folder) / "enhanced_signals"
+    enhanced_folder.mkdir(parents=True, exist_ok=True)
+    with open(cfg.path.scenes_listeners_file, "r", encoding="utf-8") as fp:
         scenes_listeners = json.load(fp)
-    with open(cfg["path"]["listeners_file"], "r", encoding="utf-8") as fp:
+    with open(cfg.path.listeners_file, "r", encoding="utf-8") as fp:
         listener_audiograms = json.load(fp)
 
     enhancer = GHAHearingAid(**cfg["GHAHearingAid"])
@@ -35,11 +35,13 @@ def enhance(cfg: DictConfig) -> None:
                 cfs=cfs, levels_l=audiogram_left, levels_r=audiogram_right
             )
 
+            infile_names = [
+                f"{cfg.path.scenes_folder}/{scene}_mixed_CH{ch}.wav"
+                for ch in range(1, cfg["num_channels"] + 1)
+            ]
+
             enhancer.process_files(
-                infile_names=[
-                    f"{cfg['path']['scenes_folder']}/{scene}_mixed_CH{ch}.wav"
-                    for ch in range(1, cfg["num_channels"] + 1)
-                ],
+                infile_names=infile_names,
                 outfile_name=f"{enhanced_folder}/{scene}_{listener}_HA-output.wav",
                 audiogram=audiogram,
                 listener=listener,
diff --git a/recipes/cec1/baseline/evaluate.py b/recipes/cec1/baseline/evaluate.py
index 2394fe522..0971a8f6b 100644
--- a/recipes/cec1/baseline/evaluate.py
+++ b/recipes/cec1/baseline/evaluate.py
@@ -1,7 +1,7 @@
 import csv
 import json
 import logging
-import os
+from pathlib import Path
 
 import hydra
 import numpy as np
@@ -39,28 +39,24 @@ def listen(ear, signal, audiogram_l, audiogram_r):
 
 @hydra.main(config_path=".", config_name="config")
 def run_HL_processing(cfg: DictConfig) -> None:
-    output_path = os.path.join(cfg["path"]["exp_folder"], "eval_signals")
-    os.makedirs(output_path, exist_ok=True)
-    with open(cfg["path"]["scenes_listeners_file"], "r", encoding="utf-8") as fp:
+    output_path = Path(cfg.path.exp_folder) / "eval_signals"
+    output_path.mkdir(parents=True, exist_ok=True)
+    with open(cfg.path.scenes_listeners_file, "r", encoding="utf-8") as fp:
         scenes_listeners = json.load(fp)
-    with open(cfg["path"]["listeners_file"], "r", encoding="utf-8") as fp:
+    with open(cfg.path.listeners_file, "r", encoding="utf-8") as fp:
         listener_audiograms = json.load(fp)
-    enhanced_folder = cfg["path"]["enhanced_signals"]
+    enhanced_folder = Path(cfg.path.enhanced_signals)
 
     # initialize ear
     ear = Ear(**cfg["MSBGEar"])
 
     for scene in tqdm(scenes_listeners):
         for listener in scenes_listeners[scene]:
-            if os.path.exists(enhanced_folder):
-                signal_file = os.path.join(
-                    enhanced_folder, f"{scene}_{listener}_HA-output.wav"
-                )
+            if enhanced_folder.exists():
+                signal_file = enhanced_folder / f"{scene}_{listener}_HA-output.wav"
             # if no enhanced signals, use the unprocessed signal for si calculation
             else:
-                signal_file = os.path.join(
-                    cfg["path"]["scenes_folder"], f"{scene}_mixed_CH0.wav"
-                )
+                signal_file = Path(cfg.path.scenes_folder) / f"{scene}_mixed_CH0.wav"
 
             # signals to write
             outfile_stem = f"{output_path}/{scene}_{listener}"
@@ -71,12 +67,12 @@ def run_HL_processing(cfg: DictConfig) -> None:
                 f"{outfile_stem}_HL-mixoutput.wav",
             ]
             # if all signals to write exist, pass
-            if all(os.path.isfile(f) for f in signal_files_to_write):
+            if all(Path(f).exists() for f in signal_files_to_write):
                 continue
 
             signal = read_signal(signal_file)
             mixture_signal = read_signal(
-                os.path.join(cfg["path"]["scenes_folder"], f"{scene}_mixed_CH0.wav")
+                Path(cfg.path.scenes_folder) / f"{scene}_mixed_CH0.wav"
             )
 
             # retrieve audiograms
@@ -105,9 +101,9 @@ def run_HL_processing(cfg: DictConfig) -> None:
                 listen(ear, mixture_signal, left_audiogram, right_audiogram),
             ]
 
-            for signal, signal_file in zip(signals_to_write, signal_files_to_write):
+            for signal, out_signal_file in zip(signals_to_write, signal_files_to_write):
                 write_signal(
-                    signal_file,
+                    out_signal_file,
                     signal,
                     MSBG_FS,
                     floating_point=True,
@@ -116,60 +112,54 @@ def run_HL_processing(cfg: DictConfig) -> None:
 
 @hydra.main(config_path=".", config_name="config")
 def run_calculate_SI(cfg: DictConfig) -> None:
-    with open(cfg["path"]["scenes_listeners_file"], "r", encoding="utf-8") as fp:
+    with open(cfg.path.scenes_listeners_file, "r", encoding="utf-8") as fp:
         scenes_listeners = json.load(fp)
-    proc_folder = os.path.join(cfg["path"]["exp_folder"], "eval_signals")
-    sii_file = os.path.join(cfg["path"]["exp_folder"], "sii.csv")
+    proc_folder = Path(cfg.path.exp_folder) / "eval_signals"
+    sii_file = Path(cfg.path.exp_folder) / "sii.csv"
     csv_lines = [["scene", "listener", "sii"]]
 
     for scene in tqdm(scenes_listeners):
         for listener in scenes_listeners[scene]:
             logging.info(f"Running SI calculation: scene {scene}, listener {listener}")
-            proc = read_signal(
-                os.path.join(proc_folder, f"{scene}_{listener}_HL-output.wav")
-            )
+            proc = read_signal(proc_folder / f"{scene}_{listener}_HL-output.wav")
             clean = read_signal(
-                os.path.join(
-                    cfg["path"]["scenes_folder"], f"{scene}_target_anechoic.wav"
-                )
-            )
-            ddf = read_signal(
-                os.path.join(proc_folder, f"{scene}_{listener}_HLddf-output.wav")
+                Path(cfg.path.scenes_folder) / f"{scene}_target_anechoic.wav"
             )
+            ddf = read_signal(proc_folder / f"{scene}_{listener}_HLddf-output.wav")
 
             # Calculate channel-specific unit impulse delay due to HL model
             # and audiograms
             delay = find_delay_impulse(ddf, initial_value=int(MSBG_FS / 2))
             if delay[0] != delay[1]:
                 logging.info(f"Difference in delay of {delay[0] - delay[1]}.")
-            maxdelay = int(np.max(delay))
+            max_delay = int(np.max(delay))
 
             # Allow for value lower than 1000 samples in case of unimpaired hearing
-            if maxdelay > 2000:
+            if max_delay > 2000:
                 logging.error("Error in delay calculation for signal time-alignment.")
 
             # Correct for delays by padding clean signals
-            cleanpad = np.zeros((len(clean) + maxdelay, 2))
-            procpad = np.zeros((len(clean) + maxdelay, 2))
+            clean_pad = np.zeros((len(clean) + max_delay, 2))
+            proc_pad = np.zeros((len(clean) + max_delay, 2))
 
-            if len(procpad) < len(proc):
+            if len(proc_pad) < len(proc):
                 raise ValueError("Padded processed signal is too short.")
 
-            cleanpad[int(delay[0]) : int(len(clean) + int(delay[0])), 0] = clean[:, 0]
-            cleanpad[int(delay[1]) : int(len(clean) + int(delay[1])), 1] = clean[:, 1]
-            procpad[: len(proc)] = proc
+            clean_pad[int(delay[0]) : int(len(clean) + int(delay[0])), 0] = clean[:, 0]
+            clean_pad[int(delay[1]) : int(len(clean) + int(delay[1])), 1] = clean[:, 1]
+            proc_pad[: len(proc)] = proc
 
             sii = mbstoi(
-                cleanpad[:, 0],
-                cleanpad[:, 1],
-                procpad[:, 0],
-                procpad[:, 1],
-                cfg["mbstoi"]["fs"],
-                cfg["mbstoi"]["gridcoarseness"],
+                clean_pad[:, 0],
+                clean_pad[:, 1],
+                proc_pad[:, 0],
+                proc_pad[:, 1],
+                cfg.mbstoi.fs,
+                cfg.mbstoi.gridcoarseness,
             )
             csv_lines.append([scene, listener, sii])  # type: ignore
 
-    with open(sii_file, "w", encoding="utf-8") as csv_f:
+    with sii_file.open("w", encoding="utf-8") as csv_f:
         csv_writer = csv.writer(
             csv_f, delimiter=",", quotechar='"', quoting=csv.QUOTE_MINIMAL
         )
diff --git a/recipes/cec1/data_preparation/prepare_cec1_data.py b/recipes/cec1/data_preparation/prepare_cec1_data.py
index 3fe6522bf..4476d1fe6 100644
--- a/recipes/cec1/data_preparation/prepare_cec1_data.py
+++ b/recipes/cec1/data_preparation/prepare_cec1_data.py
@@ -1,6 +1,6 @@
 import json
 import logging
-import os
+from pathlib import Path
 
 import hydra
 from omegaconf import DictConfig
@@ -9,7 +9,9 @@
 from clarity.data.scene_renderer_cec1 import Renderer, check_scene_exists
 
 
-def prepare_data(root_path, metafile_path, scene_folder, num_channels):
+def prepare_data(
+    root_path: str, metafile_path: str, scene_folder: str, num_channels: int
+):
     """
     Generate scene data given dataset (train or dev)
     Args:
@@ -18,10 +20,10 @@ def prepare_data(root_path, metafile_path, scene_folder, num_channels):
         scene_folder: folder containing generated scenes
         num_channels: number of channels
     """
-    with open(metafile_path, "r", encoding="utf-8") as f:
-        scenes = json.load(f)
+    with open(metafile_path, "r", encoding="utf-8") as fp:
+        scenes = json.load(fp)
 
-    os.makedirs(scene_folder, exist_ok=True)
+    Path(scene_folder).mkdir(parents=True, exist_ok=True)
 
     renderer = Renderer(input_path=root_path, output_path=scene_folder, num_channels=3)
     for scene in tqdm(scenes):
@@ -46,10 +48,10 @@ def prepare_data(root_path, metafile_path, scene_folder, num_channels):
 def run(cfg: DictConfig) -> None:
     for dataset in cfg["datasets"]:
         prepare_data(
-            cfg["input_path"],
+            cfg.input_path,
             cfg["datasets"][dataset]["metafile_path"],
             cfg["datasets"][dataset]["scene_folder"],
-            cfg["num_channels"],
+            cfg.num_channels,
         )
 
 
diff --git a/recipes/cec1/e009_sheffield/train.py b/recipes/cec1/e009_sheffield/train.py
index 8734ff4da..3089f608a 100644
--- a/recipes/cec1/e009_sheffield/train.py
+++ b/recipes/cec1/e009_sheffield/train.py
@@ -1,6 +1,6 @@
 import json
 import logging
-import os
+from pathlib import Path
 
 import hydra
 import numpy as np
@@ -77,8 +77,8 @@ def common_step(self, batch, batch_nb, train=True):
 
 
 def train_den(cfg, ear):
-    exp_dir = os.path.join(cfg.path.exp_folder, ear + "_den")
-    if os.path.exists(os.path.join(exp_dir, "best_model.pth")):
+    exp_dir = Path(cfg.path.exp_folder) / "{ear}_den"
+    if (exp_dir / "best_model.pth").exists():
         logger.info("Enhancement module exist")
         return
 
@@ -111,9 +111,9 @@ def train_den(cfg, ear):
 
     # callbacks
     callbacks = []
-    checkpoint_dir = os.path.join(exp_dir, "checkpoints/")
+    checkpoint_dir = exp_dir / "checkpoints/"
     checkpoint = ModelCheckpoint(
-        checkpoint_dir, monitor="val_loss", mode="min", save_top_k=5, verbose=True
+        str(checkpoint_dir), monitor="val_loss", mode="min", save_top_k=5, verbose=True
     )
     callbacks.append(checkpoint)
 
@@ -123,7 +123,7 @@ def train_den(cfg, ear):
     trainer = pl.Trainer(
         max_epochs=cfg.den_trainer.epochs,
         callbacks=callbacks,
-        default_root_dir=exp_dir,
+        default_root_dir=str(exp_dir),
         gpus=gpus,
         limit_train_batches=1.0,  # Useful for fast experiment
         gradient_clip_val=cfg.den_trainer.gradient_clip_val,
@@ -131,17 +131,17 @@ def train_den(cfg, ear):
     trainer.fit(den_module)
 
     best_k = {k: v.item() for k, v in checkpoint.best_k_models.items()}
-    with open(os.path.join(exp_dir, "best_k_models.json"), "w", encoding="utf-8") as fp:
+    with (exp_dir / "best_k_models.json").open("w", encoding="utf-8") as fp:
         json.dump(best_k, fp, indent=0)
     state_dict = torch.load(checkpoint.best_model_path)
     den_module.load_state_dict(state_dict=state_dict["state_dict"])
     den_module.cpu()
-    torch.save(den_module.model.state_dict(), os.path.join(exp_dir, "best_model.pth"))
+    torch.save(den_module.model.state_dict(), str(exp_dir / "best_model.pth"))
 
 
 def train_amp(cfg, ear):
-    exp_dir = os.path.join(cfg.path.exp_folder, ear + "_amp")
-    if os.path.exists(os.path.join(exp_dir, "best_model.pth")):
+    exp_dir = Path(cfg.path.exp_folder) / "{ear}_amp"
+    if (exp_dir / "best_model.pth").exists():
         logger.info("Amplification module exist")
         return
 
@@ -152,9 +152,8 @@ def train_amp(cfg, ear):
 
     # load denoising module
     den_model = ConvTasNet(**cfg.mc_conv_tasnet)
-    den_model_path = os.path.join(
-        os.path.join(cfg.path.exp_folder, ear + "_den"), "best_model.pth"
-    )
+    den_model_path = exp_dir / "{ear}_den/best_model.pth"
+
     den_model.load_state_dict(torch.load(den_model_path))
 
     # amplification module
@@ -203,9 +202,9 @@ def train_amp(cfg, ear):
 
     # callbacks
     callbacks = []
-    checkpoint_dir = os.path.join(exp_dir, "checkpoints/")
+    checkpoint_dir = exp_dir / "checkpoints/"
     checkpoint = ModelCheckpoint(
-        checkpoint_dir, monitor="val_loss", mode="min", save_top_k=5, verbose=True
+        str(checkpoint_dir), monitor="val_loss", mode="min", save_top_k=5, verbose=True
     )
     callbacks.append(checkpoint)
 
@@ -223,12 +222,12 @@ def train_amp(cfg, ear):
     trainer.fit(amp_module)
 
     best_k = {k: v.item() for k, v in checkpoint.best_k_models.items()}
-    with open(os.path.join(exp_dir, "best_k_models.json"), "w", encoding="utf-8") as fp:
+    with (exp_dir / "best_k_models.json").open("w", encoding="utf-8") as fp:
         json.dump(best_k, fp, indent=0)
     state_dict = torch.load(checkpoint.best_model_path)
     amp_module.load_state_dict(state_dict=state_dict["state_dict"])
     amp_module.cpu()
-    torch.save(amp_module.model.state_dict(), os.path.join(exp_dir, "best_model.pth"))
+    torch.save(amp_module.model.state_dict(), str(exp_dir / "best_model.pth"))
 
 
 @hydra.main(config_path=".", config_name="config")
diff --git a/recipes/cec2/baseline/data_generation/build_additional_scenes.py b/recipes/cec2/baseline/data_generation/build_additional_scenes.py
index ba8793560..e37889bee 100644
--- a/recipes/cec2/baseline/data_generation/build_additional_scenes.py
+++ b/recipes/cec2/baseline/data_generation/build_additional_scenes.py
@@ -1,5 +1,5 @@
 import logging
-import os
+from pathlib import Path
 
 import hydra
 from omegaconf import DictConfig
@@ -10,15 +10,15 @@
 
 
 def instantiate_scenes(cfg):
-    rb = RoomBuilder()
+    room_builder = RoomBuilder()
     set_random_seed(cfg.random_seed)
-    room_file = os.path.join(cfg.path.metadata_dir, "rooms.train.json")
+    room_file = Path(cfg.path.metadata_dir) / "rooms.train.json"
     for dataset in cfg.scene_datasets:
-        if not os.path.exists(cfg.path.additional_data_file):
+        if not Path(cfg.path.additional_data_file).exists():
             logger.info(f"instantiate scenes for {dataset} set")
-            rb.load(room_file)
-            sb = SceneBuilder(
-                rb=rb,
+            room_builder.load(str(room_file))
+            scene_builder = SceneBuilder(
+                rb=room_builder,
                 scene_datasets=cfg.scene_datasets[dataset],
                 target=cfg.target,
                 interferer=cfg.interferer,
@@ -26,8 +26,8 @@ def instantiate_scenes(cfg):
                 listener=cfg.listener,
                 shuffle_rooms=cfg.shuffle_rooms,
             )
-            sb.instantiate_scenes(dataset=dataset)
-            sb.save_scenes(cfg.path.additional_data_file)
+            scene_builder.instantiate_scenes(dataset=dataset)
+            scene_builder.save_scenes(cfg.path.additional_data_file)
         else:
             logger.info(f"scenes.{dataset}.json has existed, skip")
 
diff --git a/recipes/cec2/baseline/enhance.py b/recipes/cec2/baseline/enhance.py
index 36da45bfc..14883f28b 100644
--- a/recipes/cec2/baseline/enhance.py
+++ b/recipes/cec2/baseline/enhance.py
@@ -1,6 +1,6 @@
 import json
 import logging
-import os
+from pathlib import Path
 
 import hydra
 import numpy as np
@@ -16,11 +16,11 @@
 
 @hydra.main(config_path=".", config_name="config")
 def enhance(cfg: DictConfig) -> None:
-    enhanced_folder = os.path.join(cfg.path.exp_folder, "enhanced_signals")
-    os.makedirs(enhanced_folder, exist_ok=True)
-    with open(cfg.path.scenes_listeners_file, "r", encoding="utf-8") as fp:
+    enhanced_folder = Path(cfg.path.exp_folder) / "enhanced_signals"
+    enhanced_folder.mkdir(parents=True, exist_ok=True)
+    with Path(cfg.path.scenes_listeners_file).open("r", encoding="utf-8") as fp:
         scenes_listeners = json.load(fp)
-    with open(cfg.path.listeners_file, "r", encoding="utf-8") as fp:
+    with Path(cfg.path.listeners_file).open("r", encoding="utf-8") as fp:
         listener_audiograms = json.load(fp)
 
     enhancer = NALR(**cfg.nalr)
@@ -38,7 +38,7 @@ def enhance(cfg: DictConfig) -> None:
             )
 
             fs, signal = wavfile.read(
-                os.path.join(cfg.path.scenes_folder, f"{scene}_mix_CH1.wav")
+                Path(cfg.path.scenes_folder) / f"{scene}_mix_CH1.wav"
             )
             signal = signal / 32768.0
             assert fs == cfg.nalr.fs
@@ -60,7 +60,7 @@ def enhance(cfg: DictConfig) -> None:
                 logger.warning(f"Writing {filename}: {n_clipped} samples clipped")
             np.clip(enhanced, -1.0, 1.0, out=enhanced)
             signal_16 = (32768.0 * enhanced).astype(np.int16)
-            wavfile.write(os.path.join(enhanced_folder, filename), fs, signal_16)
+            wavfile.write(enhanced_folder / filename, fs, signal_16)
 
 
 # pylint: disable=no-value-for-parameter
diff --git a/recipes/cec2/baseline/evaluate.py b/recipes/cec2/baseline/evaluate.py
index e22a9df7b..1cd50f8f4 100644
--- a/recipes/cec2/baseline/evaluate.py
+++ b/recipes/cec2/baseline/evaluate.py
@@ -2,7 +2,7 @@
 import hashlib
 import json
 import logging
-import os
+from pathlib import Path
 
 import hydra
 import numpy as np
@@ -15,10 +15,10 @@
 logger = logging.getLogger(__name__)
 
 
-def read_csv_scores(file):
+def read_csv_scores(file: Path):
     score_dict = {}
-    with open(file, "r", encoding="utf-8") as f:
-        reader = csv.reader(f)
+    with file.open("r", encoding="utf-8") as fp:
+        reader = csv.reader(fp)
         _ = next(reader)
         for row in reader:
             score_dict[row[0] + "_" + row[1]] = float(row[2])
@@ -27,18 +27,18 @@ def read_csv_scores(file):
 
 @hydra.main(config_path=".", config_name="config")
 def run_calculate_SI(cfg: DictConfig) -> None:
-    with open(cfg.path.scenes_listeners_file, "r", encoding="utf-8") as fp:
+    with Path(cfg.path.scenes_listeners_file).open("r", encoding="utf-8") as fp:
         scenes_listeners = json.load(fp)
-    with open(cfg.path.listeners_file, "r", encoding="utf-8") as fp:
+    with Path(cfg.path.listeners_file).open("r", encoding="utf-8") as fp:
         listener_audiograms = json.load(fp)
-    os.makedirs(cfg.path.exp_folder, exist_ok=True)
+    Path(cfg.path.exp_folder).mkdir(parents=True, exist_ok=True)
 
-    enhanced_folder = os.path.join(cfg.path.exp_folder, "enhanced_signals")
+    enhanced_folder = Path(cfg.path.exp_folder) / "enhanced_signals"
 
     if cfg.evaluate.cal_unprocessed_si:
-        unproc_si_file = os.path.join(cfg.path.exp_folder, "si_unproc.csv")
+        unproc_si_file = Path(cfg.path.exp_folder) / "si_unproc.csv"
         unproc_csv_lines = [["scene", "listener", "haspi"]]
-        if os.path.exists(unproc_si_file):
+        if unproc_si_file.exists():
             score_dict = read_csv_scores(unproc_si_file)
             ave_score = np.mean(list(score_dict.values()))
             logger.info(
@@ -47,9 +47,9 @@ def run_calculate_SI(cfg: DictConfig) -> None:
                 ave_score,
             )
 
-    si_file = os.path.join(cfg.path.exp_folder, "si.csv")
+    si_file = Path(cfg.path.exp_folder) / "si.csv"
     csv_lines = [["scene", "listener", "haspi"]]
-    if os.path.exists(si_file):
+    if si_file.exists():
         score_dict = read_csv_scores(si_file)
         ave_score = np.mean(list(score_dict.values()))
         logger.info("si.csv exists, and the average HASPI scores is %4f", ave_score)
@@ -75,15 +75,15 @@ def run_calculate_SI(cfg: DictConfig) -> None:
 
             # retrieve signals
             fs_proc, proc = wavfile.read(
-                os.path.join(enhanced_folder, f"{scene}_{listener}_HA-output.wav")
+                enhanced_folder / f"{scene}_{listener}_HA-output.wav"
             )
 
             fs_ref_anechoic, ref_anechoic = wavfile.read(
-                os.path.join(cfg.path.scenes_folder, f"{scene}_target_anechoic_CH1.wav")
+                Path(cfg.path.scenes_folder) / f"{scene}_target_anechoic_CH1.wav"
             )
 
             fs_ref_target, ref_target = wavfile.read(
-                os.path.join(cfg.path.scenes_folder, f"{scene}_target_CH1.wav")
+                Path(cfg.path.scenes_folder) / f"{scene}_target_CH1.wav"
             )
 
             assert fs_ref_anechoic == fs_ref_target == fs_proc
@@ -117,7 +117,7 @@ def run_calculate_SI(cfg: DictConfig) -> None:
                     np.random.seed(scene_md5)
 
                 _fs_unproc, unproc = wavfile.read(
-                    os.path.join(cfg.path.scenes_folder, f"{scene}_mix_CH1.wav")
+                    Path(cfg.path.scenes_folder) / f"{scene}_mix_CH1.wav"
                 )
                 unproc = unproc / 32768.0
                 si_unproc = haspi_v2_be(
@@ -133,7 +133,7 @@ def run_calculate_SI(cfg: DictConfig) -> None:
                 logger.info(f"The unprocessed signal HASPI score is {si_unproc}")
                 unproc_csv_lines.append([scene, listener, str(si_unproc)])
 
-    with open(si_file, "w", encoding="utf-8") as csv_f:
+    with si_file.open("w", encoding="utf-8") as csv_f:
         csv_writer = csv.writer(
             csv_f, delimiter=",", quotechar='"', quoting=csv.QUOTE_MINIMAL
         )
@@ -144,7 +144,7 @@ def run_calculate_SI(cfg: DictConfig) -> None:
     logger.info("si.csv exists, and the average HASPI scores is %.4f", ave_score)
 
     if cfg.evaluate.cal_unprocessed_si:
-        with open(unproc_si_file, "w", encoding="utf-8") as csv_f:
+        with unproc_si_file.open("w", encoding="utf-8") as csv_f:
             csv_writer = csv.writer(
                 csv_f, delimiter=",", quotechar='"', quoting=csv.QUOTE_MINIMAL
             )
diff --git a/recipes/cec2/data_preparation/build_scenes.py b/recipes/cec2/data_preparation/build_scenes.py
index 43559ed7e..09581959d 100644
--- a/recipes/cec2/data_preparation/build_scenes.py
+++ b/recipes/cec2/data_preparation/build_scenes.py
@@ -1,5 +1,5 @@
 import logging
-import os
+from pathlib import Path
 
 import hydra
 from omegaconf import DictConfig
@@ -10,27 +10,27 @@
 
 
 def build_rooms_from_rpf(cfg):
-    rb = RoomBuilder()
+    room_builder = RoomBuilder()
     for dataset in cfg.room_datasets:
-        room_file = os.path.join(cfg.path.metadata_dir, f"rooms.{dataset}.json")
-        if not os.path.exists(room_file):
-            rb.build_from_rpf(**cfg.room_datasets[dataset])
-            rb.save_rooms(room_file)
+        room_file = Path(cfg.path.metadata_dir) / f"rooms.{dataset}.json"
+        if not room_file.exists():
+            room_builder.build_from_rpf(**cfg.room_datasets[dataset])
+            room_builder.save_rooms(str(room_file))
         else:
             logger.info(f"rooms.{dataset}.json exists, skip")
 
 
 def instantiate_scenes(cfg):
-    rb = RoomBuilder()
+    room_builder = RoomBuilder()
     set_random_seed(cfg.random_seed)
     for dataset in cfg.scene_datasets:
-        scene_file = os.path.join(cfg.path.metadata_dir, f"scenes.{dataset}.json")
-        if not os.path.exists(scene_file):
+        scene_file = Path(cfg.path.metadata_dir) / f"scenes.{dataset}.json"
+        if not scene_file.exists():
             logger.info(f"instantiate scenes for {dataset} set")
-            room_file = os.path.join(cfg.path.metadata_dir, f"rooms.{dataset}.json")
-            rb.load(room_file)
-            sb = SceneBuilder(
-                rb=rb,
+            room_file = Path(cfg.path.metadata_dir) / f"rooms.{dataset}.json"
+            room_builder.load(str(room_file))
+            scene_builder = SceneBuilder(
+                rb=room_builder,
                 scene_datasets=cfg.scene_datasets[dataset],
                 target=cfg.target,
                 interferer=cfg.interferer,
@@ -38,8 +38,8 @@ def instantiate_scenes(cfg):
                 listener=cfg.listener,
                 shuffle_rooms=cfg.shuffle_rooms,
             )
-            sb.instantiate_scenes(dataset=dataset)
-            sb.save_scenes(scene_file)
+            scene_builder.instantiate_scenes(dataset=dataset)
+            scene_builder.save_scenes(str(scene_file))
         else:
             logger.info(f"scenes.{dataset}.json exists, skip")
 
diff --git a/recipes/cpc1/baseline/compute_scores.py b/recipes/cpc1/baseline/compute_scores.py
index 8bf76b630..5d8a7b61f 100644
--- a/recipes/cpc1/baseline/compute_scores.py
+++ b/recipes/cpc1/baseline/compute_scores.py
@@ -1,6 +1,6 @@
 import json
 import logging
-import os
+from pathlib import Path
 
 import hydra
 import numpy as np
@@ -69,7 +69,7 @@ def compute_scores(predictions, labels):
     }
 
 
-def read_data(pred_csv, label_json):
+def read_data(pred_csv: Path, label_json: Path):
     df_pred = pd.read_csv(pred_csv).rename(
         columns={"signal_ID": "signal", "intelligibility_score": "prediction"}
     )
@@ -85,12 +85,12 @@ def read_data(pred_csv, label_json):
 def run(cfg: DictConfig) -> None:
     logger.info("Run evaluation on the closed set.")
     data_tr = read_data(
-        pred_csv=os.path.join(cfg.train_path.exp_folder, "sii.csv"),
-        label_json=cfg.train_path.scenes_file,
+        pred_csv=Path(cfg.train_path.exp_folder) / "sii.csv",
+        label_json=Path(cfg.train_path.scenes_file),
     )
     data_eval = read_data(
-        pred_csv=os.path.join(cfg.test_path.exp_folder, "sii.csv"),
-        label_json="../test_listener_responses/CPC1.test.json",
+        pred_csv=Path(cfg.test_path.exp_folder) / "sii.csv",
+        label_json=Path("../test_listener_responses/CPC1.test.json"),
     )
     logger.info("Apply logistic fitting.")
     model = Model()
@@ -100,12 +100,12 @@ def run(cfg: DictConfig) -> None:
 
     logger.info("Run evaluation on the open set.")
     data_tr = read_data(
-        pred_csv=os.path.join(cfg.train_indep_path.exp_folder, "sii.csv"),
-        label_json=cfg.train_indep_path.scenes_file,
+        pred_csv=Path(cfg.train_indep_path.exp_folder) / "sii.csv",
+        label_json=Path(cfg.train_indep_path.scenes_file),
     )
     data_eval = read_data(
-        pred_csv=os.path.join(cfg.test_indep_path.exp_folder, "sii.csv"),
-        label_json="../test_listener_responses/CPC1.test_indep.json",
+        pred_csv=Path(cfg.test_indep_path.exp_folder) / "sii.csv",
+        label_json=Path("../test_listener_responses/CPC1.test_indep.json"),
     )
     logger.info("Apply logistic fitting.")
     model = Model()
diff --git a/recipes/cpc1/baseline/run.py b/recipes/cpc1/baseline/run.py
index 1ff44edb2..fd99c6476 100644
--- a/recipes/cpc1/baseline/run.py
+++ b/recipes/cpc1/baseline/run.py
@@ -1,7 +1,7 @@
 import csv
 import json
 import logging
-import os
+from pathlib import Path
 
 import hydra
 import numpy as np
@@ -40,13 +40,13 @@ def listen(ear, signal, audiogram_l, audiogram_r):
 
 
 def run_HL_processing(cfg, path):
-    output_path = os.path.join(path.exp_folder, "eval_signals")
-    os.makedirs(output_path, exist_ok=True)
+    output_path = Path(path.exp_folder) / "eval_signals"
+    output_path.mkdir(parents=True, exist_ok=True)
     with open(path.scenes_file, "r", encoding="utf-8") as fp:
         scenes = json.load(fp)
     with open(path.listeners_file, "r", encoding="utf-8") as fp:
         listener_audiograms = json.load(fp)
-    enhanced_folder = path.scenes_folder
+    enhanced_folder = Path(path.scenes_folder)
 
     # initialize ear
     ear = Ear(**cfg["MSBGEar"])
@@ -55,7 +55,7 @@ def run_HL_processing(cfg, path):
         scene = scene_dict["scene"]
         listener = scene_dict["listener"]
         system = scene_dict["system"]
-        signal_file = os.path.join(enhanced_folder, f"{scene}_{listener}_{system}.wav")
+        signal_file = enhanced_folder / f"{scene}_{listener}_{system}.wav"
 
         # signals to write
         outfile_stem = f"{output_path}/{scene}_{listener}_{system}"
@@ -66,13 +66,11 @@ def run_HL_processing(cfg, path):
             f"{outfile_stem}_HL-mixoutput.wav",
         ]
         # if all signals to write exist, pass
-        if all(os.path.isfile(f) for f in signal_files_to_write):
+        if all(Path(f).exists() for f in signal_files_to_write):
             continue
 
         signal = read_signal(signal_file)
-        mixture_signal = read_signal(
-            os.path.join(path.ref_folder, f"{scene}_mixed_CH0.wav")
-        )
+        mixture_signal = read_signal(Path(path.ref_folder) / f"{scene}_mixed_CH0.wav")
 
         # retrieve audiograms
         cfs = np.array(listener_audiograms[listener]["audiogram_cfs"])
@@ -107,23 +105,18 @@ def run_HL_processing(cfg, path):
 def run_calculate_SI(cfg, path) -> None:
     with open(path.scenes_file, "r", encoding="utf-8") as fp:
         scenes = json.load(fp)
-    proc_folder = os.path.join(path.exp_folder, "eval_signals")
-    sii_file = os.path.join(path.exp_folder, "sii.csv")
+    proc_folder = Path(path.exp_folder) / "eval_signals"
+    ref_folder = Path(path.ref_folder)
+    sii_file = Path(path.exp_folder) / "sii.csv"
     csv_lines = [["signal_ID", "intelligibility_score"]]
 
     for scene_dict in tqdm(scenes):
         scene = scene_dict["scene"]
         listener = scene_dict["listener"]
         system = scene_dict["system"]
-        proc = read_signal(
-            os.path.join(proc_folder, f"{scene}_{listener}_{system}_HL-output.wav")
-        )
-        clean = read_signal(
-            os.path.join(path.ref_folder, f"{scene}_target_anechoic.wav")
-        )
-        ddf = read_signal(
-            os.path.join(proc_folder, f"{scene}_{listener}_{system}_HLddf-output.wav")
-        )
+        proc = read_signal(proc_folder / f"{scene}_{listener}_{system}_HL-output.wav")
+        clean = read_signal(ref_folder / f"{scene}_target_anechoic.wav")
+        ddf = read_signal(proc_folder / f"{scene}_{listener}_{system}_HLddf-output.wav")
 
         # Calculate channel-specific unit impulse delay due to HL model and audiograms
         delay = find_delay_impulse(ddf, initial_value=int(MSBG_FS / 2))
diff --git a/recipes/cpc1/e029_sheffield/evaluate.py b/recipes/cpc1/e029_sheffield/evaluate.py
index abb3323c7..fbfb60198 100644
--- a/recipes/cpc1/e029_sheffield/evaluate.py
+++ b/recipes/cpc1/e029_sheffield/evaluate.py
@@ -1,6 +1,6 @@
 import json
 import logging
-import os
+from pathlib import Path
 
 import hydra
 import numpy as np
@@ -68,22 +68,18 @@ def compute_scores(predictions, labels):
     }
 
 
-def read_data(pred_json, label_json):
-    prediction = []
-    label = []
-
+def read_data(pred_json: Path, label_json: Path):
     # read label_json to dict
-    label_dict = {}
-    with open(label_json, "r", encoding="utf-8") as fp:
-        label_json = json.load(fp)
-    for item in label_json:
-        label_dict[item["signal"]] = item["correctness"] / 100.0
+    with label_json.open("r", encoding="utf-8") as fp:
+        labels = json.load(fp)
+
+    label_dict = {item["signal"]: item["correctness"] for item in labels}
 
-    with open(pred_json, "r", encoding="utf-8") as fp:
+    with pred_json.open("r", encoding="utf-8") as fp:
         pred_dict = json.load(fp)
-    for signal, pred in pred_dict.items():
-        prediction.append(pred * 100.0)
-        label.append(label_dict[signal])
+
+    prediction = [pred * 100.0 for pred in pred_dict.values()]
+    label = [label_dict[signal] for signal in pred_dict]
 
     return np.array(prediction), np.array(label)
 
@@ -99,12 +95,12 @@ def run(cfg: DictConfig) -> None:
 
     # encoder representation evaluation
     prediction_dev, label_dev = read_data(
-        os.path.join(cfg.path.exp_folder, "dev_conf.json"),
-        os.path.join(cfg.path.cpc1_train_data, f"metadata/CPC1.{'train'+track}.json"),
+        Path(cfg.path.exp_folder) / "dev_conf.json",
+        Path(cfg.path.cpc1_train_data) / f"metadata/CPC1.{'train'+track}.json",
     )
     prediction_test, label_test = read_data(
-        os.path.join(cfg.path.exp_folder, "test_conf.json"),
-        f"../test_listener_responses/CPC1.{'test'+track}.json",
+        Path(cfg.path.exp_folder) / "test_conf.json",
+        Path(f"../test_listener_responses/CPC1.{'test'+track}.json"),
     )
 
     logger.info("Apply logistic fitting.")
@@ -115,12 +111,12 @@ def run(cfg: DictConfig) -> None:
 
     # decoder representation evaluation
     prediction_dev, label_dev = read_data(
-        os.path.join(cfg.path.exp_folder, "dev_negent.json"),
-        os.path.join(cfg.path.cpc1_train_data, f"metadata/CPC1.{'train'+track}.json"),
+        Path(cfg.path.exp_folder) / "dev_negent.json",
+        Path(cfg.path.cpc1_train_data) / f"metadata/CPC1.{'train'+track}.json",
     )
     prediction_test, label_test = read_data(
-        os.path.join(cfg.path.exp_folder, "test_negent.json"),
-        f"../test_listener_responses/CPC1.{'test'+track}.json",
+        Path(cfg.path.exp_folder) / "test_negent.json",
+        Path(f"../test_listener_responses/CPC1.{'test'+track}.json"),
     )
 
     logger.info("Apply logistic fitting.")
@@ -129,9 +125,8 @@ def run(cfg: DictConfig) -> None:
     fit_pred = model.predict(prediction_test)
     negent_scores = compute_scores(fit_pred * 100, label_test * 100)
 
-    with open(
-        os.path.join(cfg.path.exp_folder, "results.json"), "w", encoding="utf-8"
-    ) as fp:
+    results_file = Path(cfg.path.exp_folder) / "results.json"
+    with results_file.open("w", encoding="utf-8") as fp:
         json.dump(
             {
                 "confidence_results": conf_scores,
diff --git a/recipes/cpc1/e029_sheffield/infer.py b/recipes/cpc1/e029_sheffield/infer.py
index 5832be503..5fe363e1f 100644
--- a/recipes/cpc1/e029_sheffield/infer.py
+++ b/recipes/cpc1/e029_sheffield/infer.py
@@ -1,7 +1,7 @@
 import copy
 import json
 import logging
-import os
+from pathlib import Path
 
 import hydra
 import speechbrain as sb
@@ -148,56 +148,51 @@ def run(cfg: DictConfig) -> None:
         track = ""
     else:
         logger.error("cpc1_track has to be closed or open")
+        raise ValueError("cpc1_track has to be closed or open")
 
     asr_model, tokenizer, bos_index = init_asr(cfg.asr_config)
 
     left_dev_csv = sb.dataio.dataio.load_data_csv(
-        os.path.join(cfg.path.exp_folder, "cpc1_asr_data" + track, "left_dev_msbg.csv")
+        Path(cfg.path.exp_folder) / f"cpc1_asr_data{track}/left_dev_msbg.csv"
     )  # using left ear csvfile for data loading
     left_test_csv = sb.dataio.dataio.load_data_csv(
-        os.path.join(cfg.path.exp_folder, "cpc1_asr_data" + track, "left_test_msbg.csv")
+        Path(cfg.path.exp_folder) / f"cpc1_asr_data{track}/left_test_msbg.csv"
     )  # using left ear csvfile for data loading
 
-    dev_conf = {}
-    dev_negent = {}
+    exp_path = Path(cfg.path.exp_folder)
+
     # dev set uncertainty
+    dev_conf = {}
+    dev_neg_entropy = {}
     for wav_id, wav_obj in tqdm(left_dev_csv.items()):
         left_proc_path = wav_obj["wav"]
         uncertainty = compute_uncertainty(
             left_proc_path, asr_model, bos_index, tokenizer
         )
         dev_conf[wav_id] = uncertainty[0].tolist()
-        dev_negent[wav_id] = uncertainty[1].tolist()
+        dev_neg_entropy[wav_id] = uncertainty[1].tolist()
 
-        with open(
-            os.path.join(cfg.path.exp_folder, "dev_conf.json"), "w", encoding="utf-8"
-        ) as fp:
+        with (exp_path / "dev_conf.json").open("w", encoding="utf-8") as fp:
             json.dump(dev_conf, fp)
-        with open(
-            os.path.join(cfg.path.exp_folder, "dev_negent.json"), "w", encoding="utf-8"
-        ) as fp:
-            json.dump(dev_negent, fp)
+        with (exp_path / "dev_negent.json").open("w", encoding="utf-8") as fp:
+            json.dump(dev_neg_entropy, fp)
 
     # test set similarity
     test_conf = {}
-    test_negent = {}
+    test_neg_entropy = {}
     for wav_id, wav_obj in tqdm(left_test_csv.items()):
         left_proc_path = wav_obj["wav"]
         uncertainty = compute_uncertainty(
             left_proc_path, asr_model, bos_index, tokenizer
         )
         test_conf[wav_id] = uncertainty[0].tolist()
-        test_negent[wav_id] = uncertainty[1].tolist()
+        test_neg_entropy[wav_id] = uncertainty[1].tolist()
 
-        with open(
-            os.path.join(cfg.path.exp_folder, "test_conf.json"), "w", encoding="utf-8"
-        ) as fp:
+        with (exp_path / "test_conf.json").open("w", encoding="utf-8") as fp:
             json.dump(test_conf, fp)
 
-        with open(
-            os.path.join(cfg.path.exp_folder, "test_negent.json"), "w", encoding="utf-8"
-        ) as fp:
-            json.dump(test_negent, fp)
+        with (exp_path / "test_negent.json").open("w", encoding="utf-8") as fp:
+            json.dump(test_neg_entropy, fp)
 
 
 # pylint: disable=no-value-for-parameter
diff --git a/recipes/cpc1/e029_sheffield/prepare_data.py b/recipes/cpc1/e029_sheffield/prepare_data.py
index 34e5db155..aeb39065c 100644
--- a/recipes/cpc1/e029_sheffield/prepare_data.py
+++ b/recipes/cpc1/e029_sheffield/prepare_data.py
@@ -2,8 +2,8 @@
 import csv
 import json
 import logging
-import os
 import random
+from pathlib import Path
 
 import hydra
 import numpy as np
@@ -22,23 +22,21 @@
 
 
 def run_data_split(cfg, track):
-    os.makedirs(os.path.join(cfg.path.exp_folder, "data_split"), exist_ok=True)
-    scene_train_json = os.path.join(
-        cfg.path.exp_folder, "data_split", f"scene_train_list{track}.json"
-    )
-    scene_dev_json = os.path.join(
-        cfg.path.exp_folder, "data_split", f"scene_dev_list{track}.json"
-    )
-    if os.path.isfile(scene_train_json) and os.path.isfile(scene_dev_json):
+    data_split_dir = Path(cfg.path.exp_folder) / "data_split"
+    data_split_dir.mkdir(parents=True, exist_ok=True)
+    scene_train_json = data_split_dir / f"scene_train_list{track}.json"
+    scene_dev_json = data_split_dir / f"scene_dev_list{track}.json"
+
+    if scene_train_json.exists() and scene_dev_json.exists():
         logger.info("Train set and dev set lists exist...")
         return
 
-    file_path = os.path.join(
-        cfg.path.root,
-        "clarity_CPC1_data_train/metadata",
-        f"CPC1.{'train'+track}.json",
+    file_path = (
+        Path(cfg.path.root)
+        / f"clarity_CPC1_data_train/metadata/CPC1.{'train'+track}.json"
     )
-    with open(file_path, "r", encoding="utf-8") as fp:
+
+    with file_path.open("r", encoding="utf-8") as fp:
         scenes_dict = json.load(fp)
     scene_list = []
     for item in scenes_dict:
@@ -49,9 +47,9 @@ def run_data_split(cfg, track):
     )
     scene_train_list = list(set(scene_list) - set(scene_dev_list))
 
-    with open(scene_train_json, "w", encoding="utf-8") as fp:
+    with scene_train_json.open("w", encoding="utf-8") as fp:
         json.dump(scene_train_list, fp)
-    with open(scene_dev_json, "w", encoding="utf-8") as fp:
+    with scene_dev_json.open("w", encoding="utf-8") as fp:
         json.dump(scene_dev_list, fp)
 
 
@@ -79,22 +77,18 @@ def listen(ear, signal, audiogram_l, audiogram_r):
 def run_msbg_simulation(cfg, track):
     for split in ["train", "test"]:
         dataset = split + track
-        dataset_folder = os.path.join(cfg.path.root, "clarity_CPC1_data_" + split)
-        output_path = os.path.join(dataset_folder, "clarity_data/HA_outputs", dataset)
-        file_path = os.path.join(dataset_folder, "metadata", f"CPC1.{dataset}.json")
-        with open(file_path, "r", encoding="utf-8") as fp:
+        dataset_folder = Path(cfg.path.root) / f"clarity_CPC1_data_{split}"
+        output_path = dataset_folder / "clarity_data/HA_outputs" / dataset
+        file_path = dataset_folder / f"metadata/CPC1.{dataset}.json"
+        with file_path.open("r", encoding="utf-8") as fp:
             scenes = json.load(fp)
         if split == "train":
-            file_path = os.path.join(
-                dataset_folder, "metadata", "listeners.CPC1_train.json"
-            )
-            with open(file_path, "r", encoding="utf-8") as fp:
+            file_path = dataset_folder / "metadata/listeners.CPC1_train.json"
+            with file_path.open("r", encoding="utf-8") as fp:
                 listener_audiograms = json.load(fp)
         else:
-            file_path = os.path.join(
-                dataset_folder, "metadata", "listeners.CPC1_all.json"
-            )
-            with open(file_path, "r", encoding="utf-8") as fp:
+            file_path = Path(dataset_folder) / "metadata/listeners.CPC1_all.json"
+            with file_path.open("r", encoding="utf-8") as fp:
                 listener_audiograms = json.load(fp)
 
         # initialize ear
@@ -104,15 +98,15 @@ def run_msbg_simulation(cfg, track):
             scene = scene_dict["scene"]
             listener = scene_dict["listener"]
             system = scene_dict["system"]
-            signal_file = os.path.join(output_path, f"{scene}_{listener}_{system}.wav")
+            signal_file = output_path / f"{scene}_{listener}_{system}.wav"
 
             # signals to write
-            outfile_stem = f"{output_path}/{scene}_{listener}_{system}"
+            outfile_stem = output_path / f"{scene}_{listener}_{system}"
             signal_files_to_write = [
-                f"{outfile_stem}_HL-output.wav",
+                Path(f"{outfile_stem}_HL-output.wav"),
             ]
             # if all signals to write exist, pass
-            if all(os.path.isfile(f) for f in signal_files_to_write):
+            if all(f.exists() for f in signal_files_to_write):
                 continue
             signal = read_signal(signal_file)
 
@@ -141,68 +135,56 @@ def run_msbg_simulation(cfg, track):
 
 
 def generate_data_split(
-    orig_data_json,
-    orig_signal_folder,
-    target_data_folder,
+    orig_data_json: Path,
+    orig_signal_folder: Path,
+    target_data_folder: Path,
     data_split,
     split_data_list,
     if_msbg=False,
     if_ref=False,
 ):
-    with open(orig_data_json, "r", encoding="utf-8") as fp:
+    with orig_data_json.open("r", encoding="utf-8") as fp:
         all_data_list = json.load(fp)
 
-    left_tgt_signal_folder = os.path.join(
-        target_data_folder, orig_signal_folder.split("/")[-2] + "_left"
+    ext = ""
+    if if_msbg:
+        ext = "_msbg"
+    elif if_ref:
+        ext = "_ref"
+
+    left_tgt_signal_folder = target_data_folder / (
+        str(orig_signal_folder).split("/")[-2] + "_left" + ext
     )
-    right_tgt_signal_folder = os.path.join(
-        target_data_folder, orig_signal_folder.split("/")[-2] + "_right"
+
+    right_tgt_signal_folder = target_data_folder / (
+        str(orig_signal_folder).split("/")[-2] + "_right" + ext
     )
-    if if_msbg:
-        left_tgt_signal_folder = left_tgt_signal_folder + "_msbg"
-        right_tgt_signal_folder = right_tgt_signal_folder + "_msbg"
-    if if_ref:
-        left_tgt_signal_folder = left_tgt_signal_folder + "_ref"
-        right_tgt_signal_folder = right_tgt_signal_folder + "_ref"
-    os.makedirs(left_tgt_signal_folder, exist_ok=True)
-    os.makedirs(right_tgt_signal_folder, exist_ok=True)
+
+    left_tgt_signal_folder.mkdir(parents=True, exist_ok=True)
+    right_tgt_signal_folder.mkdir(parents=True, exist_ok=True)
 
     csv_lines_left = [["ID", "duration", "wav", "spk_id", "wrd"]]
     csv_lines_right = [["ID", "duration", "wav", "spk_id", "wrd"]]
     csv_lines_binaural = [["ID", "duration", "wav", "spk_id", "wrd"]]
 
-    left_csvfile = "left_" + data_split
-    right_csvfile = "right_" + data_split
-    binaural_csvfile = "binaural_" + data_split
-    if if_msbg:
-        left_csvfile += "_msbg"
-        right_csvfile += "_msbg"
-        binaural_csvfile += "_msbg"
-    if if_ref:
-        left_csvfile += "_ref"
-        right_csvfile += "_ref"
-        binaural_csvfile += "_ref"
-    left_csvfile = os.path.join(target_data_folder, left_csvfile + ".csv")
-    right_csvfile = os.path.join(target_data_folder, right_csvfile + ".csv")
-    binaural_csvfile = os.path.join(target_data_folder, binaural_csvfile + ".csv")
+    left_csvfile = target_data_folder / f"left_{data_split}{ext}.csv"
+    right_csvfile = target_data_folder / f"right_{data_split}{ext}.csv"
+    binaural_csvfile = target_data_folder / f"binaural_{data_split}{ext}.csv"
 
     for item in tqdm(all_data_list):
         snt_id = item["signal"]
         if snt_id.split("_")[0] in split_data_list or data_split == "test":
             if if_msbg:
-                wav_file = os.path.join(orig_signal_folder, snt_id + "_HL-output.wav")
+                wav_file = orig_signal_folder / f"{snt_id}_HL-output.wav"
             elif if_ref:
-                wav_file = os.path.join(
-                    orig_signal_folder,
-                    "../..",
-                    "scenes",
-                    snt_id.split("_")[0] + "_target_anechoic.wav",
+                wav_file = orig_signal_folder / (
+                    f"../../scenes/{snt_id.split('_')[0]}_target_anechoic.wav"
                 )
             else:
-                wav_file = os.path.join(orig_signal_folder, snt_id + ".wav")
-            wav_file_left = os.path.join(left_tgt_signal_folder, snt_id + ".wav")
-            wav_file_right = os.path.join(right_tgt_signal_folder, snt_id + ".wav")
-            if os.path.isfile(wav_file_left) and os.path.isfile(wav_file_right):
+                wav_file = orig_signal_folder / f"{snt_id}.wav"
+            wav_file_left = left_tgt_signal_folder / f"{snt_id}.wav"
+            wav_file_right = right_tgt_signal_folder / f"{snt_id}.wav"
+            if wav_file_left.exists() and wav_file_right.exists():
                 continue
 
             spk_id = item["listener"]  # should be listener_id
@@ -218,32 +200,34 @@ def generate_data_split(
             sf.write(wav_file_left, utt_16k[2 * targ_fs :, 0], targ_fs)
             sf.write(wav_file_right, utt_16k[2 * targ_fs :, 1], targ_fs)
 
-            csv_lines_left.append([snt_id, str(duration), wav_file_left, spk_id, wrds])
+            csv_lines_left.append(
+                [snt_id, str(duration), str(wav_file_left), spk_id, wrds]
+            )
             csv_lines_right.append(
-                [snt_id, str(duration), wav_file_right, spk_id, wrds]
+                [snt_id, str(duration), str(wav_file_right), spk_id, wrds]
             )
             csv_lines_binaural.append(
-                ["left_" + snt_id, str(duration), wav_file_left, spk_id, wrds]
+                ["left_" + snt_id, str(duration), str(wav_file_left), spk_id, wrds]
             )
             csv_lines_binaural.append(
-                ["right_" + snt_id, str(duration), wav_file_right, spk_id, wrds]
+                ["right_" + snt_id, str(duration), str(wav_file_right), spk_id, wrds]
             )
 
-    with open(left_csvfile, mode="w", encoding="utf-8") as csv_f:
+    with left_csvfile.open(mode="w", encoding="utf-8") as csv_f:
         csv_writer = csv.writer(
             csv_f, delimiter=",", quotechar='"', quoting=csv.QUOTE_MINIMAL
         )
         for line in csv_lines_left:
             csv_writer.writerow(line)
 
-    with open(right_csvfile, mode="w", encoding="utf-8") as csv_f:
+    with right_csvfile.open(mode="w", encoding="utf-8") as csv_f:
         csv_writer = csv.writer(
             csv_f, delimiter=",", quotechar='"', quoting=csv.QUOTE_MINIMAL
         )
         for line in csv_lines_right:
             csv_writer.writerow(line)
 
-    with open(binaural_csvfile, mode="w", encoding="utf-8") as csv_f:
+    with binaural_csvfile.open(mode="w", encoding="utf-8") as csv_f:
         csv_writer = csv.writer(
             csv_f, delimiter=",", quotechar='"', quoting=csv.QUOTE_MINIMAL
         )
@@ -252,23 +236,23 @@ def generate_data_split(
 
 
 def run_signal_generation_train(cfg, track):
-    train_json_path = os.path.join(
-        cfg.path.cpc1_train_data, f"metadata/CPC1.{'train'+track}.json"
+    train_json_path = (
+        Path(cfg.path.cpc1_train_data) / f"metadata/CPC1.{'train'+track}.json"
     )
-    train_signal_folder = os.path.join(
-        cfg.path.cpc1_train_data, f"clarity_data/HA_outputs/{'train'+track}/"
+
+    train_signal_folder = (
+        Path(cfg.path.cpc1_train_data) / f"clarity_data/HA_outputs/{'train'+track}/"
     )
-    target_folder = os.path.join(cfg.path.exp_folder, "cpc1_asr_data" + track)
+
+    target_folder = Path(cfg.path.exp_folder) / f"cpc1_asr_data{track}"
     lists_to_generate = [
-        os.path.join(
-            cfg.path.exp_folder, "data_split", f"scene_train_list{track}.json"
-        ),
-        os.path.join(cfg.path.exp_folder, "data_split", f"scene_dev_list{track}.json"),
+        Path(cfg.path.exp_folder) / f"data_split/scene_train_list{track}.json",
+        Path(cfg.path.exp_folder) / f"data_split/scene_dev_list{track}.json",
     ]
 
     datasets_to_generate = []
     for list_to_generate in lists_to_generate:
-        with open(list_to_generate, "r", encoding="utf-8") as fp:
+        with list_to_generate.open("r", encoding="utf-8") as fp:
             datasets_to_generate.append(json.load(fp))
 
     for list_to_generate, dataset in zip(lists_to_generate, datasets_to_generate):
@@ -276,7 +260,7 @@ def run_signal_generation_train(cfg, track):
         #     train_json_path,
         #     train_signal_folder,
         #     target_folder,
-        #     os.path.basename(list_to_generate).split("_")[1],
+        #     list_to_generate.name.split("_")[1],
         #     datasets_to_generate[i],
         # )
 
@@ -284,7 +268,7 @@ def run_signal_generation_train(cfg, track):
             train_json_path,
             train_signal_folder,
             target_folder,
-            os.path.basename(list_to_generate).split("_")[1],
+            list_to_generate.name.split("_")[1],
             dataset,
             if_msbg=True,
         )
@@ -293,20 +277,21 @@ def run_signal_generation_train(cfg, track):
             train_json_path,
             train_signal_folder,
             target_folder,
-            os.path.basename(list_to_generate).split("_")[1],
+            list_to_generate.name.split("_")[1],
             dataset,
             if_ref=True,
         )
 
 
 def run_signal_generation_test(cfg, track):
-    test_json_path = os.path.join(
-        cfg.path.cpc1_test_data, f"metadata/CPC1.{'test'+track}.json"
+    test_json_path = (
+        Path(cfg.path.cpc1_test_data) / f"metadata/CPC1.{'test'+track}.json"
     )
-    test_signal_folder = os.path.join(
-        cfg.path.cpc1_test_data, f"clarity_data/HA_outputs/{'test'+track}/"
+    test_signal_folder = (
+        Path(cfg.path.cpc1_test_data) / f"clarity_data/HA_outputs/{'test'+track}/"
     )
-    target_folder = os.path.join(cfg.path.exp_folder, "cpc1_asr_data" + track)
+
+    target_folder = Path(cfg.path.exp_folder) / f"cpc1_asr_data{track}"
 
     # generate_data_split(
     #     test_json_path, test_signal_folder, target_folder, "test", [],
@@ -329,6 +314,7 @@ def run(cfg: DictConfig) -> None:
         track = ""
     else:
         logger.error("cpc1_track has to be closed or open")
+        raise ValueError("cpc1_track has to be closed or open")
 
     logger.info("Split all training data into train set and dev set.")
     run_data_split(cfg, track)
diff --git a/recipes/cpc1/e029_sheffield/train_asr.py b/recipes/cpc1/e029_sheffield/train_asr.py
index 0f99a2e8d..5ab762393 100644
--- a/recipes/cpc1/e029_sheffield/train_asr.py
+++ b/recipes/cpc1/e029_sheffield/train_asr.py
@@ -8,7 +8,6 @@
 # pylint: disable=W0201  # code requires attributes defined outside __init__
 
 import logging
-import os
 import sys
 from pathlib import Path
 
@@ -360,8 +359,8 @@ def main():
 
     # Testing
     for dataset_key, test_dataset in test_datasets.items():
-        asr_brain.hparams.wer_file = os.path.join(
-            hparams["output_folder"], f"wer_{dataset_key}.txt"
+        asr_brain.hparams.wer_file = (
+            Path(hparams["output_folder"]) / f"wer_{dataset_key}.txt"
         )
         asr_brain.evaluate(
             test_dataset,
diff --git a/recipes/cpc1/e032_sheffield/evaluate.py b/recipes/cpc1/e032_sheffield/evaluate.py
index ff66b150e..af917f5a9 100644
--- a/recipes/cpc1/e032_sheffield/evaluate.py
+++ b/recipes/cpc1/e032_sheffield/evaluate.py
@@ -1,6 +1,6 @@
 import json
 import logging
-import os
+from pathlib import Path
 
 import hydra
 import numpy as np
@@ -69,22 +69,18 @@ def compute_scores(predictions, labels):
     }
 
 
-def read_data(pred_json, label_json):
-    prediction = []
-    label = []
-
+def read_data(pred_json: Path, label_json: Path):
     # read label_json to dict
-    label_dict = {}
-    with open(label_json, "r", encoding="utf-8") as fp:
-        label_json = json.load(fp)
-    for item in label_json:
-        label_dict[item["signal"]] = item["correctness"]
+    with label_json.open("r", encoding="utf-8") as fp:
+        labels = json.load(fp)
+
+    label_dict = {item["signal"]: item["correctness"] for item in labels}
 
-    with open(pred_json, "r", encoding="utf-8") as fp:
+    with pred_json.open("r", encoding="utf-8") as fp:
         pred_dict = json.load(fp)
-    for signal, pred in pred_dict.items():
-        prediction.append(pred * 100.0)
-        label.append(label_dict[signal])
+
+    prediction = [pred * 100.0 for pred in pred_dict.values()]
+    label = [label_dict[signal] for signal in pred_dict]
 
     return np.array(prediction), np.array(label)
 
@@ -100,12 +96,12 @@ def run(cfg: DictConfig) -> None:
 
     # encoder representation evaluation
     prediction_dev, label_dev = read_data(
-        os.path.join(cfg.path.exp_folder, "dev_enc_similarity.json"),
-        os.path.join(cfg.path.cpc1_train_data, f"metadata/CPC1.{'train'+track}.json"),
+        Path(cfg.path.exp_folder) / "dev_enc_similarity.json",
+        Path(cfg.path.cpc1_train_data) / f"metadata/CPC1.{'train'+track}.json",
     )
     prediction_test, label_test = read_data(
-        os.path.join(cfg.path.exp_folder, "test_enc_similarity.json"),
-        f"../test_listener_responses/CPC1.{'test'+track}.json",
+        Path(cfg.path.exp_folder) / "test_enc_similarity.json",
+        Path(f"../test_listener_responses/CPC1.{'test'+track}.json"),
     )
 
     logger.info("Apply logistic fitting.")
@@ -116,12 +112,12 @@ def run(cfg: DictConfig) -> None:
 
     # decoder representation evaluation
     prediction_dev, label_dev = read_data(
-        os.path.join(cfg.path.exp_folder, "dev_dec_similarity.json"),
-        os.path.join(cfg.path.cpc1_train_data, f"metadata/CPC1.{'train'+track}.json"),
+        Path(cfg.path.exp_folder) / "dev_dec_similarity.json",
+        Path(cfg.path.cpc1_train_data) / f"metadata/CPC1.{'train'+track}.json",
     )
     prediction_test, label_test = read_data(
-        os.path.join(cfg.path.exp_folder, "test_dec_similarity.json"),
-        f"../test_listener_responses/CPC1.{'test'+track}.json",
+        Path(cfg.path.exp_folder) / "test_dec_similarity.json",
+        Path(f"../test_listener_responses/CPC1.{'test'+track}.json"),
     )
 
     logger.info("Apply logistic fitting.")
@@ -130,10 +126,9 @@ def run(cfg: DictConfig) -> None:
     fit_pred = model.predict(prediction_test)
     dec_scores = compute_scores(fit_pred, label_test)
 
-    with open(
-        os.path.join(cfg.path.exp_folder, "results.json"), "w", encoding="utf-8"
-    ) as f:
-        json.dump({"enc_results": enc_scores, "dec_results": dec_scores}, f)
+    results_file = Path(cfg.path.exp_folder) / "results.json"
+    with results_file.open("w", encoding="utf-8") as fp:
+        json.dump({"enc_results": enc_scores, "dec_results": dec_scores}, fp)
 
 
 # pylint: disable=no-value-for-parameter
diff --git a/recipes/cpc1/e032_sheffield/infer.py b/recipes/cpc1/e032_sheffield/infer.py
index 56d0edca8..9af00a6da 100644
--- a/recipes/cpc1/e032_sheffield/infer.py
+++ b/recipes/cpc1/e032_sheffield/infer.py
@@ -1,6 +1,6 @@
 import json
 import logging
-import os
+from pathlib import Path
 
 import hydra
 import speechbrain as sb
@@ -227,14 +227,16 @@ def run(cfg: DictConfig) -> None:
         track = ""
     else:
         logger.error("cpc1_track has to be closed or open")
+        raise ValueError("cpc1_track has to be closed or open")
 
     asr_model, tokenizer, bos_index = init_asr(cfg.asr_config)
 
+    exp_path = Path(cfg.path.exp_folder)
     left_dev_csv = sb.dataio.dataio.load_data_csv(
-        os.path.join(cfg.path.exp_folder, "cpc1_asr_data" + track, "left_dev_msbg.csv")
+        exp_path / f"cpc1_asr_data{track}/left_dev_msbg.csv"
     )  # using left ear csvfile for data loading
     left_test_csv = sb.dataio.dataio.load_data_csv(
-        os.path.join(cfg.path.exp_folder, "cpc1_asr_data" + track, "left_test_msbg.csv")
+        exp_path / f"cpc1_asr_data{track}/left_test_msbg.csv"
     )  # using left ear csvfile for data loading
 
     # dev set similarity
@@ -249,17 +251,9 @@ def run(cfg: DictConfig) -> None:
         dev_enc_similarity[wav_id] = similarity[0].tolist()
         dev_dec_similarity[wav_id] = similarity[1].tolist()
 
-        with open(
-            os.path.join(cfg.path.exp_folder, "dev_enc_similarity.json"),
-            "w",
-            encoding="utf-8",
-        ) as fp:
+        with (exp_path / "dev_enc_similarity.json").open("w", encoding="utf-8") as fp:
             json.dump(dev_enc_similarity, fp)
-        with open(
-            os.path.join(cfg.path.exp_folder, "dev_dec_similarity.json"),
-            "w",
-            encoding="utf-8",
-        ) as fp:
+        with (exp_path / "dev_dec_similarity.json").open("w", encoding="utf-8") as fp:
             json.dump(dev_dec_similarity, fp)
 
     # test set similarity
@@ -274,18 +268,10 @@ def run(cfg: DictConfig) -> None:
         test_enc_similarity[wav_id] = similarity[0].tolist()
         test_dec_similarity[wav_id] = similarity[1].tolist()
 
-        with open(
-            os.path.join(cfg.path.exp_folder, "test_enc_similarity.json"),
-            "w",
-            encoding="utf-8",
-        ) as fp:
+        with (exp_path / "test_enc_similarity.json").open("w", encoding="utf-8") as fp:
             json.dump(test_enc_similarity, fp)
 
-        with open(
-            os.path.join(cfg.path.exp_folder, "test_dec_similarity.json"),
-            "w",
-            encoding="utf-8",
-        ) as fp:
+        with (exp_path / "test_dec_similarity.json").open("w", encoding="utf-8") as fp:
             json.dump(test_dec_similarity, fp)
 
 
diff --git a/recipes/cpc1/e032_sheffield/prepare_data.py b/recipes/cpc1/e032_sheffield/prepare_data.py
index 6bf2fabb7..2b9ee7d0e 100644
--- a/recipes/cpc1/e032_sheffield/prepare_data.py
+++ b/recipes/cpc1/e032_sheffield/prepare_data.py
@@ -2,8 +2,8 @@
 import csv
 import json
 import logging
-import os
 import random
+from pathlib import Path
 
 import hydra
 import numpy as np
@@ -22,23 +22,21 @@
 
 
 def run_data_split(cfg, track):
-    os.makedirs(os.path.join(cfg.path.exp_folder, "data_split"), exist_ok=True)
-    scene_train_json = os.path.join(
-        cfg.path.exp_folder, "data_split", f"scene_train_list{track}.json"
-    )
-    scene_dev_json = os.path.join(
-        cfg.path.exp_folder, "data_split", f"scene_dev_list{track}.json"
-    )
-    if os.path.isfile(scene_train_json) and os.path.isfile(scene_dev_json):
+    data_split_dir = Path(cfg.path.exp_folder) / "data_split"
+    data_split_dir.mkdir(parents=True, exist_ok=True)
+    scene_train_json = data_split_dir / f"scene_train_list{track}.json"
+    scene_dev_json = data_split_dir / f"scene_dev_list{track}.json"
+
+    if scene_train_json.exists() and scene_dev_json.exists():
         logger.info("Train set and dev set lists exist...")
         return
 
-    filepath = os.path.join(
-        cfg.path.root,
-        "clarity_CPC1_data_train/metadata",
-        f"CPC1.{'train'+track}.json",
+    file_path = (
+        Path(cfg.path.root)
+        / f"clarity_CPC1_data_train/metadata/CPC1.{'train'+track}.json"
     )
-    with open(filepath, "r", encoding="utf-8") as fp:
+
+    with file_path.open("r", encoding="utf-8") as fp:
         scenes_dict = json.load(fp)
     scene_list = []
     for item in scenes_dict:
@@ -49,9 +47,9 @@ def run_data_split(cfg, track):
     )
     scene_train_list = list(set(scene_list) - set(scene_dev_list))
 
-    with open(scene_train_json, "w", encoding="utf-8") as fp:
+    with scene_train_json.open("w", encoding="utf-8") as fp:
         json.dump(scene_train_list, fp)
-    with open(scene_dev_json, "w", encoding="utf-8") as fp:
+    with scene_dev_json.open("w", encoding="utf-8") as fp:
         json.dump(scene_dev_list, fp)
 
 
@@ -79,22 +77,18 @@ def listen(ear, signal, audiogram_l, audiogram_r):
 def run_msbg_simulation(cfg, track):
     for split in ["train", "test"]:
         dataset = split + track
-        dataset_folder = os.path.join(cfg.path.root, "clarity_CPC1_data_" + split)
-        output_path = os.path.join(dataset_folder, "clarity_data/HA_outputs", dataset)
-        file_path = os.path.join(dataset_folder, "metadata", f"CPC1.{dataset}.json")
-        with open(file_path, "r", encoding="utf-8") as fp:
+        dataset_folder = Path(cfg.path.root) / f"clarity_CPC1_data_{split}"
+        output_path = dataset_folder / "clarity_data/HA_outputs" / dataset
+        file_path = dataset_folder / f"metadata/CPC1.{dataset}.json"
+        with file_path.open("r", encoding="utf-8") as fp:
             scenes = json.load(fp)
         if split == "train":
-            file_path = os.path.join(
-                dataset_folder, "metadata", "listeners.CPC1_train.json"
-            )
-            with open(file_path, "r", encoding="utf-8") as fp:
+            file_path = dataset_folder / "metadata/listeners.CPC1_train.json"
+            with file_path.open("r", encoding="utf-8") as fp:
                 listener_audiograms = json.load(fp)
         else:
-            file_path = os.path.join(
-                dataset_folder, "metadata", "listeners.CPC1_all.json"
-            )
-            with open(file_path, "r", encoding="utf-8") as fp:
+            file_path = Path(dataset_folder) / "metadata/listeners.CPC1_all.json"
+            with file_path.open("r", encoding="utf-8") as fp:
                 listener_audiograms = json.load(fp)
 
         # initialize ear
@@ -104,15 +98,15 @@ def run_msbg_simulation(cfg, track):
             scene = scene_dict["scene"]
             listener = scene_dict["listener"]
             system = scene_dict["system"]
-            signal_file = os.path.join(output_path, f"{scene}_{listener}_{system}.wav")
+            signal_file = output_path / f"{scene}_{listener}_{system}.wav"
 
             # signals to write
-            outfile_stem = f"{output_path}/{scene}_{listener}_{system}"
+            outfile_stem = output_path / f"{scene}_{listener}_{system}"
             signal_files_to_write = [
-                f"{outfile_stem}_HL-output.wav",
+                Path(f"{outfile_stem}_HL-output.wav"),
             ]
             # if all signals to write exist, pass
-            if all(os.path.isfile(f) for f in signal_files_to_write):
+            if all(f.exists() for f in signal_files_to_write):
                 continue
             signal = read_signal(signal_file)
 
@@ -141,68 +135,56 @@ def run_msbg_simulation(cfg, track):
 
 
 def generate_data_split(
-    orig_data_json,
-    orig_signal_folder,
-    target_data_folder,
+    orig_data_json: Path,
+    orig_signal_folder: Path,
+    target_data_folder: Path,
     data_split,
     split_data_list,
     if_msbg=False,
     if_ref=False,
 ):
-    with open(orig_data_json, "r", encoding="utf-8") as fp:
+    with orig_data_json.open("r", encoding="utf-8") as fp:
         all_data_list = json.load(fp)
 
-    left_tgt_signal_folder = os.path.join(
-        target_data_folder, orig_signal_folder.split("/")[-2] + "_left"
+    ext = ""
+    if if_msbg:
+        ext = "_msbg"
+    elif if_ref:
+        ext = "_ref"
+
+    left_tgt_signal_folder = target_data_folder / (
+        str(orig_signal_folder).split("/")[-2] + "_left" + ext
     )
-    right_tgt_signal_folder = os.path.join(
-        target_data_folder, orig_signal_folder.split("/")[-2] + "_right"
+
+    right_tgt_signal_folder = target_data_folder / (
+        str(orig_signal_folder).split("/")[-2] + "_right" + ext
     )
-    if if_msbg:
-        left_tgt_signal_folder = left_tgt_signal_folder + "_msbg"
-        right_tgt_signal_folder = right_tgt_signal_folder + "_msbg"
-    if if_ref:
-        left_tgt_signal_folder = left_tgt_signal_folder + "_ref"
-        right_tgt_signal_folder = right_tgt_signal_folder + "_ref"
-    os.makedirs(left_tgt_signal_folder, exist_ok=True)
-    os.makedirs(right_tgt_signal_folder, exist_ok=True)
+
+    left_tgt_signal_folder.mkdir(parents=True, exist_ok=True)
+    right_tgt_signal_folder.mkdir(parents=True, exist_ok=True)
 
     csv_lines_left = [["ID", "duration", "wav", "spk_id", "wrd"]]
     csv_lines_right = [["ID", "duration", "wav", "spk_id", "wrd"]]
     csv_lines_binaural = [["ID", "duration", "wav", "spk_id", "wrd"]]
 
-    left_csvfile = "left_" + data_split
-    right_csvfile = "right_" + data_split
-    binaural_csvfile = "binaural_" + data_split
-    if if_msbg:
-        left_csvfile += "_msbg"
-        right_csvfile += "_msbg"
-        binaural_csvfile += "_msbg"
-    if if_ref:
-        left_csvfile += "_ref"
-        right_csvfile += "_ref"
-        binaural_csvfile += "_ref"
-    left_csvfile = os.path.join(target_data_folder, left_csvfile + ".csv")
-    right_csvfile = os.path.join(target_data_folder, right_csvfile + ".csv")
-    binaural_csvfile = os.path.join(target_data_folder, binaural_csvfile + ".csv")
+    left_csvfile = target_data_folder / f"left_{data_split}{ext}.csv"
+    right_csvfile = target_data_folder / f"right_{data_split}{ext}.csv"
+    binaural_csvfile = target_data_folder / f"binaural_{data_split}{ext}.csv"
 
     for item in tqdm(all_data_list):
         snt_id = item["signal"]
         if snt_id.split("_")[0] in split_data_list or data_split == "test":
             if if_msbg:
-                wav_file = os.path.join(orig_signal_folder, snt_id + "_HL-output.wav")
+                wav_file = orig_signal_folder / f"{snt_id}_HL-output.wav"
             elif if_ref:
-                wav_file = os.path.join(
-                    orig_signal_folder,
-                    "../..",
-                    "scenes",
-                    snt_id.split("_")[0] + "_target_anechoic.wav",
+                wav_file = orig_signal_folder / (
+                    f"../../scenes/{snt_id.split('_')[0]}_target_anechoic.wav"
                 )
             else:
-                wav_file = os.path.join(orig_signal_folder, snt_id + ".wav")
-            wav_file_left = os.path.join(left_tgt_signal_folder, snt_id + ".wav")
-            wav_file_right = os.path.join(right_tgt_signal_folder, snt_id + ".wav")
-            if os.path.isfile(wav_file_left) and os.path.isfile(wav_file_right):
+                wav_file = orig_signal_folder / f"{snt_id}.wav"
+            wav_file_left = left_tgt_signal_folder / f"{snt_id}.wav"
+            wav_file_right = right_tgt_signal_folder / f"{snt_id}.wav"
+            if wav_file_left.exists() and wav_file_right.exists():
                 continue
 
             spk_id = item["listener"]  # should be listener_id
@@ -218,32 +200,34 @@ def generate_data_split(
             sf.write(wav_file_left, utt_16k[2 * targ_fs :, 0], targ_fs)
             sf.write(wav_file_right, utt_16k[2 * targ_fs :, 1], targ_fs)
 
-            csv_lines_left.append([snt_id, str(duration), wav_file_left, spk_id, wrds])
+            csv_lines_left.append(
+                [snt_id, str(duration), str(wav_file_left), spk_id, wrds]
+            )
             csv_lines_right.append(
-                [snt_id, str(duration), wav_file_right, spk_id, wrds]
+                [snt_id, str(duration), str(wav_file_right), spk_id, wrds]
             )
             csv_lines_binaural.append(
-                ["left_" + snt_id, str(duration), wav_file_left, spk_id, wrds]
+                ["left_" + snt_id, str(duration), str(wav_file_left), spk_id, wrds]
             )
             csv_lines_binaural.append(
-                ["right_" + snt_id, str(duration), wav_file_right, spk_id, wrds]
+                ["right_" + snt_id, str(duration), str(wav_file_right), spk_id, wrds]
             )
 
-    with open(left_csvfile, mode="w", encoding="utf-8") as csv_f:
+    with left_csvfile.open(mode="w", encoding="utf-8") as csv_f:
         csv_writer = csv.writer(
             csv_f, delimiter=",", quotechar='"', quoting=csv.QUOTE_MINIMAL
         )
         for line in csv_lines_left:
             csv_writer.writerow(line)
 
-    with open(right_csvfile, mode="w", encoding="utf-8") as csv_f:
+    with right_csvfile.open(mode="w", encoding="utf-8") as csv_f:
         csv_writer = csv.writer(
             csv_f, delimiter=",", quotechar='"', quoting=csv.QUOTE_MINIMAL
         )
         for line in csv_lines_right:
             csv_writer.writerow(line)
 
-    with open(binaural_csvfile, mode="w", encoding="utf-8") as csv_f:
+    with binaural_csvfile.open(mode="w", encoding="utf-8") as csv_f:
         csv_writer = csv.writer(
             csv_f, delimiter=",", quotechar='"', quoting=csv.QUOTE_MINIMAL
         )
@@ -252,23 +236,23 @@ def generate_data_split(
 
 
 def run_signal_generation_train(cfg, track):
-    train_json_path = os.path.join(
-        cfg.path.cpc1_train_data, f"metadata/CPC1.{'train'+track}.json"
+    train_json_path = (
+        Path(cfg.path.cpc1_train_data) / f"metadata/CPC1.{'train'+track}.json"
     )
-    train_signal_folder = os.path.join(
-        cfg.path.cpc1_train_data, f"clarity_data/HA_outputs/{'train'+track}/"
+
+    train_signal_folder = (
+        Path(cfg.path.cpc1_train_data) / f"clarity_data/HA_outputs/{'train'+track}/"
     )
-    target_folder = os.path.join(cfg.path.exp_folder, "cpc1_asr_data" + track)
+
+    target_folder = Path(cfg.path.exp_folder) / f"cpc1_asr_data{track}"
     lists_to_generate = [
-        os.path.join(
-            cfg.path.exp_folder, "data_split", f"scene_train_list{track}.json"
-        ),
-        os.path.join(cfg.path.exp_folder, "data_split", f"scene_dev_list{track}.json"),
+        Path(cfg.path.exp_folder) / f"data_split/scene_train_list{track}.json",
+        Path(cfg.path.exp_folder) / f"data_split/scene_dev_list{track}.json",
     ]
 
     datasets_to_generate = []
     for list_to_generate in lists_to_generate:
-        with open(list_to_generate, "r", encoding="utf-8") as fp:
+        with list_to_generate.open("r", encoding="utf-8") as fp:
             datasets_to_generate.append(json.load(fp))
 
     for list_to_generate, dataset in zip(lists_to_generate, datasets_to_generate):
@@ -276,7 +260,7 @@ def run_signal_generation_train(cfg, track):
         #     train_json_path,
         #     train_signal_folder,
         #     target_folder,
-        #     os.path.basename(list_to_generate).split("_")[1],
+        #     list_to_generate.name.split("_")[1],
         #     datasets_to_generate[i],
         # )
 
@@ -284,7 +268,7 @@ def run_signal_generation_train(cfg, track):
             train_json_path,
             train_signal_folder,
             target_folder,
-            os.path.basename(list_to_generate).split("_")[1],
+            list_to_generate.name.split("_")[1],
             dataset,
             if_msbg=True,
         )
@@ -293,20 +277,21 @@ def run_signal_generation_train(cfg, track):
             train_json_path,
             train_signal_folder,
             target_folder,
-            os.path.basename(list_to_generate).split("_")[1],
+            list_to_generate.name.split("_")[1],
             dataset,
             if_ref=True,
         )
 
 
 def run_signal_generation_test(cfg, track):
-    test_json_path = os.path.join(
-        cfg.path.cpc1_test_data, f"metadata/CPC1.{'test'+track}.json"
+    test_json_path = (
+        Path(cfg.path.cpc1_test_data) / f"metadata/CPC1.{'test'+track}.json"
     )
-    test_signal_folder = os.path.join(
-        cfg.path.cpc1_test_data, f"clarity_data/HA_outputs/{'test'+track}/"
+    test_signal_folder = (
+        Path(cfg.path.cpc1_test_data) / f"clarity_data/HA_outputs/{'test'+track}/"
     )
-    target_folder = os.path.join(cfg.path.exp_folder, "cpc1_asr_data" + track)
+
+    target_folder = Path(cfg.path.exp_folder) / f"cpc1_asr_data{track}"
 
     # generate_data_split(
     #     test_json_path, test_signal_folder, target_folder, "test", [],
@@ -329,6 +314,7 @@ def run(cfg: DictConfig) -> None:
         track = ""
     else:
         logger.error("cpc1_track has to be closed or open")
+        raise ValueError("cpc1_track has to be closed or open")
 
     logger.info("Split all training data into train set and dev set.")
     run_data_split(cfg, track)
diff --git a/recipes/cpc1/e032_sheffield/train_asr.py b/recipes/cpc1/e032_sheffield/train_asr.py
index eac380b43..622f5917a 100644
--- a/recipes/cpc1/e032_sheffield/train_asr.py
+++ b/recipes/cpc1/e032_sheffield/train_asr.py
@@ -6,7 +6,6 @@
 """
 
 import logging
-import os
 import sys
 from pathlib import Path
 
@@ -376,8 +375,8 @@ def main():
     # Testing
     for dataset_key, test_dataset in test_datasets.items():
         # dataset_keys are test_clean, test_other etc
-        asr_brain.hparams.wer_file = os.path.join(
-            hparams["output_folder"], f"wer_{dataset_key}.txt"
+        asr_brain.hparams.wer_file = (
+            Path(hparams["output_folder"]) / f"wer_{dataset_key}.txt"
         )
         asr_brain.evaluate(
             test_dataset,


Test patch:
diff --git a/recipes/cec1/e009_sheffield/test.py b/recipes/cec1/e009_sheffield/test.py
index ce5f799b1..ee99ee185 100644
--- a/recipes/cec1/e009_sheffield/test.py
+++ b/recipes/cec1/e009_sheffield/test.py
@@ -1,4 +1,4 @@
-import os
+from pathlib import Path
 
 import hydra
 import numpy as np
@@ -16,12 +16,14 @@
 
 @hydra.main(config_path=".", config_name="config")
 def run(cfg: DictConfig) -> None:
-    output_folder = os.path.join(cfg.path.exp_folder, "enhanced_" + cfg.listener.id)
-    os.makedirs(output_folder, exist_ok=True)
+    exp_folder = Path(cfg.path.exp_folder)
+    output_folder = exp_folder / f"enhanced_{cfg.listener.id}"
+    output_folder.mkdir(parents=True, exist_ok=True)
 
     test_set = CEC1Dataset(**cfg.test_dataset)
     test_loader = DataLoader(dataset=test_set, **cfg.test_loader)
 
+    down_sample = up_sample = None
     if cfg.downsample_factor != 1:
         down_sample = torchaudio.transforms.Resample(
             orig_freq=cfg.sr,
@@ -44,9 +46,8 @@ def run(cfg: DictConfig) -> None:
                 torch.cuda.empty_cache()
                 # load denoising module
                 den_model = ConvTasNet(**cfg.mc_conv_tasnet)
-                den_model_path = os.path.join(
-                    os.path.join(cfg.path.exp_folder, ear + "_den"), "best_model.pth"
-                )
+                den_model_path = exp_folder / f"{ear}_den/best_model.pth"
+
                 den_model.load_state_dict(
                     torch.load(den_model_path, map_location=device)
                 )
@@ -55,9 +56,8 @@ def run(cfg: DictConfig) -> None:
 
                 # load amplification module
                 amp_model = AudiometricFIR(**cfg.fir)
-                amp_model_path = os.path.join(
-                    os.path.join(cfg.path.exp_folder, ear + "_amp"), "best_model.pth"
-                )
+                amp_model_path = exp_folder / f"{ear}_amp/best_model.pth"
+
                 amp_model.load_state_dict(
                     torch.load(amp_model_path, map_location=device)
                 )
@@ -65,20 +65,18 @@ def run(cfg: DictConfig) -> None:
                 _amp_model.eval()
 
                 noisy = noisy.to(device)
-                if cfg.downsample_factor != 1:
+                proc = noisy
+                if down_sample is not None:
                     proc = down_sample(noisy)
                 enhanced = amp_model(den_model(proc)).squeeze(1)
-                if cfg.downsample_factor != 1:
+                if up_sample is not None:
                     enhanced = up_sample(enhanced)
                 enhanced = torch.clamp(enhanced, -1, 1)
                 out.append(enhanced.detach().cpu().numpy()[0])
 
             out = np.stack(out, axis=0).transpose()
             write(
-                os.path.join(
-                    output_folder,
-                    scene[0] + "_" + cfg.listener.id + "_" + "HA-output.wav",
-                ),
+                output_folder / f"{scene[0]}_{cfg.listener.id}_HA-output.wav",
                 out,
                 cfg.sr,
             )
diff --git a/tests/regression/test_CEC2_scene_builder.py b/tests/regression/test_CEC2_scene_builder.py
index fc85f956c..d515ed787 100644
--- a/tests/regression/test_CEC2_scene_builder.py
+++ b/tests/regression/test_CEC2_scene_builder.py
@@ -2,7 +2,7 @@
 # Use scene builder to build random scene
 
 import json
-import os
+from pathlib import Path
 
 from omegaconf import OmegaConf
 
@@ -10,16 +10,17 @@
 
 
 def test_CEC2_scene_builder(regtest):
+    """Regression test for CEC2 scene builder"""
     cfg = OmegaConf.load("tests/test_data/configs/test_CEC2_scene_builder.yaml")
     cfg.path.root = "tests"
     set_random_seed(cfg.random_seed)
     dataset = "train"
-    rb = RoomBuilder()
+    room_builder = RoomBuilder()
 
-    room_file = os.path.join(cfg.path.metadata_dir, f"rooms.{dataset}.json")
-    rb.load(room_file)
-    sb = SceneBuilder(
-        rb=rb,
+    room_file = Path(cfg.path.metadata_dir) / f"rooms.{dataset}.json"
+    room_builder.load(room_file)
+    scene_builder = SceneBuilder(
+        rb=room_builder,
         scene_datasets=cfg.scene_datasets[dataset],
         target=cfg.target,
         interferer=cfg.interferer,
@@ -27,9 +28,9 @@ def test_CEC2_scene_builder(regtest):
         listener=cfg.listener,
         shuffle_rooms=cfg.shuffle_rooms,
     )
-    sb.instantiate_scenes(dataset=dataset)
+    scene_builder.instantiate_scenes(dataset=dataset)
 
-    print(len(sb.scenes))
+    print(len(scene_builder.scenes))
 
     with regtest:
-        print(json.dumps(sb.scenes, indent=4))
+        print(json.dumps(scene_builder.scenes, indent=4))