code: def beer_lambert_law(raw, ppf=6.0):
      r"""Convert NIRS optical density data to haemoglobin concentration.
  
      Parameters
      ----------
      raw : instance of Raw
          The optical density data.
      ppf : float
          The partial pathlength factor.
  
      Returns
      -------
      raw : instance of Raw
          The modified raw instance.
      """
      raw = raw.copy().load_data()
      _validate_type(raw, BaseRaw, "raw")
      _validate_type(ppf, "numeric", "ppf")
      ppf = float(ppf)
      picks = _validate_nirs_info(
          raw.info, fnirs="od", which="Beer-lambert"
      )
      # This is the one place we *really* need the actual/accurate frequencies
      freqs = np.array(
          [raw.info["chs"][pick]["loc"][9] for pick in picks], float
      )
      abs_coef = _load_absorption(freqs)
      distances = source_detector_distances(raw.info, picks="all")
      bad = ~np.isfinite(distances[picks])
      bad |= distances[picks] <= 0
      if bad.any():
          warn(
              "Source-detector distances are zero on NaN, some resulting "
              "concentrations will be zero. Consider setting a montage "
              "with raw.set_montage."
          )
      distances[picks[bad]] = 0.0
      if (distances[picks] > 0.1).any():
          warn(
              "Source-detector distances are greater than 10 cm. "
              "Large distances will result in invalid data, and are "
              "likely due to optode locations being stored in a "
              " unit other than meters."
          )
      rename = dict()
      for ii, jj in zip(picks[::2], picks[1::2]):
          EL = abs_coef * distances[ii] * ppf
          iEL = linalg.pinv(EL)
  
          raw._data[[ii, jj]] = iEL @ raw._data[[ii, jj]] * 1e-3
  
          # Update channel information
          coil_dict = dict(
              hbo=FIFF.FIFFV_COIL_FNIRS_HBO,
              hbr=FIFF.FIFFV_COIL_FNIRS_HBR,
          )
          for ki, kind in zip((ii, jj), ("hbo", "hbr")):
              ch = raw.info["chs"][ki]
              ch.update(
                  coil_type=coil_dict[kind], unit=FIFF.FIFF_UNIT_MOL
              )
              new_name = f'{ch["ch_name"].split(" ")[0]} {kind}'
              rename[ch["ch_name"]] = new_name
      raw.rename_channels(rename)
  
      # Validate the format of data after transformation is valid
      _validate_nirs_info(raw.info, fnirs="hb")
      return raw
  
file_path: mne-python/mne/preprocessing/nirs/_beer_lambert_law.py
imports: import os.path
  import numpy
  from scipy import linalg
  from scipy.interpolate import interp1d
  from scipy.io import loadmat
  from ..._fiff.constants import FIFF
  from ...io import BaseRaw
  from ...utils import _validate_type, warn
  from ..nirs import _validate_nirs_info, source_detector_distances
label_desc: Use image node_id 1 for calling a global function with example usage: beer_lambert_law(raw, ppf) and returns: raw